diff --git a/.gdbinit b/.gdbinit deleted file mode 100644 index 855ad96..0000000 --- a/.gdbinit +++ /dev/null @@ -1,4 +0,0 @@ -set history save on -file target/x86_64-ableos/debug/ableos -target remote localhost:9000 -tui enable diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml deleted file mode 100644 index e7afbac..0000000 --- a/.github/workflows/rust.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Build - -on: - - push - - pull_request - -env: - CARGO_TERM_COLOR: always - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - components: rust-src - - uses: actions-rs/cargo@v1 - with: - command: repbuild - args: run diff --git a/.gitignore b/.gitignore index 8740171..2f7896d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1 @@ -userland/root_fs/mnt/ target/ -limine/ -.disk.img -.gdb_history -!*/.gitkeep -__pycache__/ -debug.log diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..a32d038 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,5 @@ +[submodule "limine"] + path = limine + url = https://github.com/limine-bootloader/limine.git + branch = v4.x-branch-binary + shallow = true diff --git a/.vscode/settings.json b/.vscode/settings.json index 0814706..4e57780 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,3 @@ { - "files.associations": { - "stddef.h": "c" - }, - "rust-analyzer.checkOnSave.allTargets": false, + "rust-analyzer.checkOnSave.allTargets": false } \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 3a0df9f..bc18679 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,100 +3,28 @@ version = 3 [[package]] -name = "ab_glyph" -version = "0.2.15" +name = "aho-corasick" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24606928a235e73cdef55a0c909719cadd72fce573e5713d58cb2952d8f5794c" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ - "ab_glyph_rasterizer", - "libm", - "owned_ttf_parser", + "memchr", ] [[package]] -name = "ab_glyph_rasterizer" +name = "android_system_properties" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a13739d7177fbd22bb0ed28badfff9f372f8bef46c863db4e1c6248f6b223b6e" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ - "libm", + "libc", ] [[package]] -name = "ableos" -version = "0.1.1" -dependencies = [ - "ab_glyph", - "acpi", - "axel", - "bitflags", - "bootloader", - "clparse", - "cpuio", - "ext2", - "externc-libm", - "facepalm", - "genfs", - "hashbrown", - "kernel", - "lazy_static", - "libwasm", - "linked_list_allocator", - "lliw", - "log", - "logos", - "pc-beeper", - "pc-keyboard", - "pic8259", - "picorand", - "pretty-hex", - "qrcode", - "rdrand", - "riscv", - "rkyv", - "seq-macro", - "serde", - "spin 0.9.4", - "toml", - "uart_16550", - "unicode-width", - "versioning", - "vga", - "volatile 0.2.7", - "wasmi", - "watson", - "x86_64", - "y-compositor-protocol", -] - -[[package]] -name = "acpi" -version = "4.1.1" +name = "anyhow" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "654f48ab3178632ea535be1765073b990895cb62f70a7e5671975d7150c26d15" -dependencies = [ - "bit_field", - "log", - "rsdp", -] - -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "asl" -version = "0.1.0" -dependencies = [ - "logos", -] +checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" [[package]] name = "atty" @@ -104,7 +32,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -116,27 +44,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] -name = "axel" -version = "0.1.0" -source = "git+https://git.ablecorp.us/able/aos_userland#a9a2514de31c10c1f02956f3513a636e2c5190ff" -dependencies = [ - "hashbrown", - "log", - "logos", - "versioning", -] - -[[package]] -name = "bare-metal" -version = "1.0.0" +name = "bit" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" - -[[package]] -name = "beef" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" +checksum = "2b645c5c09a7d4035949cfce1a915785aaad6f17800c35fda8a8c311c491f284" [[package]] name = "bit_field" @@ -151,10 +62,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "bootloader" -version = "0.9.22" +name = "bumpalo" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de78decc37247c7cfac5dbf3495c7298c6ac97cb355161caa7e15969c6648e6c" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + +[[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.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "cfg-if" @@ -163,45 +86,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "clparse" -version = "0.1.0" -source = "git+https://git.ablecorp.us/able/core_utils#46a97f827bd11f3cea8dcab797b9697d9485c4b3" -dependencies = [ - "hashbrown", - "log", - "toml", -] - -[[package]] -name = "colored" -version = "2.0.0" +name = "chrono" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" dependencies = [ - "atty", - "lazy_static", + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits", + "time", + "wasm-bindgen", "winapi", ] [[package]] -name = "conquer-once" -version = "0.3.2" +name = "codespan-reporting" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c6d3a9775a69f6d1fe2cc888999b67ed30257d3da4d2af91984e722f2ec918a" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" dependencies = [ - "conquer-util", + "termcolor", + "unicode-width", ] [[package]] -name = "conquer-util" -version = "0.3.0" +name = "core-foundation-sys" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e763eef8846b13b380f37dfecda401770b0ca4e56e95170237bd7c25c7db3582" - -[[package]] -name = "cpuio" -version = "0.3.2" -source = "git+https://git.ablecorp.us/ondra05/cpuio.git#093cc103101b4ba4abd02d77c884113a376cdc64" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "crossbeam-queue" @@ -223,82 +136,124 @@ dependencies = [ ] [[package]] -name = "downcast-rs" -version = "1.2.0" +name = "cxx" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +checksum = "9a140f260e6f3f79013b8bfc65e7ce630c9ab4388c6a89c71e07226f49487b72" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] [[package]] -name = "embedded-hal" -version = "0.2.7" +name = "cxx-build" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +checksum = "da6383f459341ea689374bf0a42979739dc421874f112ff26f829b8040b8e613" dependencies = [ - "nb 0.1.3", - "void", + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", ] [[package]] -name = "ext2" -version = "0.1.1" +name = "cxxbridge-flags" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90201c1a650e95ccff1c8c0bb5a343213bdd317c6e600a93075bca2eff54ec97" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b75aed41bb2e6367cae39e6326ef817a851db13c13e4f3263714ca3cfb8de56" dependencies = [ - "bitflags", - "genfs", - "rlibc", - "spin 0.9.4", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "externc-libm" -version = "0.1.0" -source = "git+https://git.ablecorp.us/able/externc-libm.git#0781df85c094bcd7e5ef7505e9c5cc6317eeda75" +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ - "libm", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "facepalm" -version = "0.1.0" +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" dependencies = [ + "humantime", + "is-terminal", "log", + "regex", + "termcolor", ] [[package]] -name = "fnv" -version = "1.0.7" +name = "errno" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] [[package]] -name = "font8x8" +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "error-stack" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d224e04b2d93d974c08e375dac9b8d1a513846e44c6666450a57b1ed963f9" +dependencies = [ + "anyhow", + "owo-colors", + "rustc_version", +] + +[[package]] +name = "error-stack" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875488b8711a968268c7cf5d139578713097ca4635a76044e8fe8eedf831d07e" - -[[package]] -name = "genfs" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65b9e52a0ffd4c2f11f9f84e8885a40cb99f490971eee78bbd7ddffd6ac023d6" - -[[package]] -name = "getrandom" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "5f00447f331c7f726db5b8532ebc9163519eed03c6d7c8b73c90b3ff5646ac85" dependencies = [ - "cfg-if", - "libc", - "wasi", + "rustc_version", ] [[package]] -name = "hashbrown" -version = "0.12.3" +name = "fatfs" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "05669f8e7e2d7badc545c513710f0eba09c2fbef683eb859fd79c46c355048e0" dependencies = [ - "ahash", + "bitflags", + "byteorder", + "chrono", + "log", ] [[package]] @@ -311,57 +266,122 @@ dependencies = [ ] [[package]] -name = "kernel" -version = "0.1.2" +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "iana-time-zone" +version = "0.1.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "716f12fbcfac6ffab0a5e9ec51d0a0ff70503742bb2dc7b99396394c9dc323f0" dependencies = [ - "crossbeam-queue", - "linked_list_allocator", - "log", - "slab", - "spin 0.9.4", - "versioning", + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows", ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "iana-time-zone-haiku" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" dependencies = [ - "spin 0.5.2", + "cxx", + "cxx-build", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb" +dependencies = [ + "hermit-abi 0.3.1", + "libc", + "windows-sys", +] + +[[package]] +name = "is-terminal" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "256017f749ab3117e93acb91063009e1f1bb56d03965b14c2c8df4eb02c524d8" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys", +] + +[[package]] +name = "is_ci" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" + +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "kernel" +version = "0.2.0" +dependencies = [ + "crossbeam-queue", + "derive_more", + "error-stack 0.3.1", + "limine", + "log", + "sbi", + "slab", + "spin", + "uart_16550", + "versioning", + "x2apic", + "x86_64", ] [[package]] name = "libc" -version = "0.2.126" +version = "0.2.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" [[package]] -name = "libm" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da83a57f3f5ba3680950aa3cbc806fc297bc0b289d42e8942ed528ace71b8145" +name = "limine" +version = "0.1.10" +source = "git+https://github.com/limine-bootloader/limine-rs#2f0ae642064749372a61cf3290f22ce71d21df27" [[package]] -name = "libwasm" -version = "0.1.0" -source = "git+https://git.ablecorp.us/able/libwasm.git#4ffcd290f8bc918ca4adf5e23ce2097968e4a8b2" - -[[package]] -name = "linked_list_allocator" -version = "0.9.1" +name = "link-cplusplus" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "549ce1740e46b291953c4340adcd74c59bcf4308f4cac050fd33ba91b7168f4a" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" dependencies = [ - "spinning_top", + "cc", ] [[package]] -name = "lliw" -version = "0.2.0" +name = "linux-raw-sys" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d502c8bcc35a4f7ca9a7ffb7ac27b15ba30b1b92c2d69a1e4437e2635d73af7" +checksum = "cd550e73688e6d578f0ac2119e32b797a327631a42f9433e59d02e139c8df60d" [[package]] name = "lock_api" @@ -383,48 +403,10 @@ dependencies = [ ] [[package]] -name = "logos" -version = "0.12.1" +name = "memchr" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf8b031682c67a8e3d5446840f9573eb7fe26efe7ec8d195c9ac4c0647c502f1" -dependencies = [ - "logos-derive", -] - -[[package]] -name = "logos-derive" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d849148dbaf9661a6151d1ca82b13bb4c4c128146a88d05253b38d4e2f496c" -dependencies = [ - "beef", - "fnv", - "proc-macro2", - "quote", - "regex-syntax", - "syn", -] - -[[package]] -name = "memory_units" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" - -[[package]] -name = "nb" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" -dependencies = [ - "nb 1.0.0", -] - -[[package]] -name = "nb" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "num-integer" @@ -436,17 +418,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-rational" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.15" @@ -463,54 +434,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" [[package]] -name = "owned_ttf_parser" -version = "0.15.1" +name = "owo-colors" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ef1a404ae479dd6906f4fa2c88b3c94028f1284beb42a47c183a7c27ee9a3e" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" dependencies = [ - "ttf-parser", + "supports-color", ] [[package]] -name = "parity-wasm" -version = "0.42.2" +name = "paste" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be5e13c266502aadf83426d87d81a0f5d1ef45b8027f5a471c360abfe4bfae92" - -[[package]] -name = "pc-beeper" -version = "0.1.0" -source = "git+https://github.com/AbleOS/pc-beeper#9b61a9d60552a9da4285f5ceb39ab2cccbb60b4b" -dependencies = [ - "x86_64", -] - -[[package]] -name = "pc-keyboard" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6f2d937e3b8d63449b01401e2bae4041bc9dd1129c2e3e0d239407cf6635ac" - -[[package]] -name = "pic8259" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24ec21f514e2e16e94649f1d041ca4a7069b512c037ac156360652a775e6229d" -dependencies = [ - "x86_64", -] - -[[package]] -name = "picorand" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fc30519d2508c7e20e01da371cd27b1d4533fdb98e279955cb636b50210688" - -[[package]] -name = "pretty-hex" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5c99d529f0d30937f6f4b8a86d988047327bb88d04d2c4afc356de74722131" +checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" [[package]] name = "proc-macro2" @@ -521,30 +457,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "ptr_meta" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" -dependencies = [ - "ptr_meta_derive", -] - -[[package]] -name = "ptr_meta_derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "qrcode" -version = "0.12.0" - [[package]] name = "quote" version = "1.0.21" @@ -555,88 +467,76 @@ dependencies = [ ] [[package]] -name = "rand_core" -version = "0.6.3" +name = "raw-cpuid" +version = "10.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" +dependencies = [ + "bitflags", +] [[package]] -name = "rdrand" -version = "0.8.2" +name = "regex" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e233b642160555c1aa1ff7a78443c6139342f411b6fa6602af2ebbfee9e166bb" +checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" dependencies = [ - "rand_core", + "aho-corasick", + "memchr", + "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.27" +version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "repbuild" -version = "0.1.0" -dependencies = [ - "colored", -] - -[[package]] -name = "riscv" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e2856a701069e2d262b264750d382407d272d5527f7a51d3777d1805b4e2d3c" -dependencies = [ - "bare-metal", - "bit_field", - "embedded-hal", -] - -[[package]] -name = "rkyv" -version = "0.7.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15" -dependencies = [ - "hashbrown", - "ptr_meta", - "rkyv_derive", - "seahash", -] - -[[package]] -name = "rkyv_derive" -version = "0.7.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "rlibc" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc874b127765f014d792f16763a81245ab80500e2ad921ed4ee9e82481ee08fe" - -[[package]] -name = "rsdp" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d3add2fc55ef37511bcf81a08ee7a09eff07b23aae38b06a29024a38c604b1" +version = "0.2.0" dependencies = [ + "env_logger", + "error-stack 0.2.4", + "fatfs", "log", ] +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.37.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e78cc525325c06b4a7ff02db283472f3c042b7ff0c391f96c6d5ac6f4f91b75" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "rustversion" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" +[[package]] +name = "sbi" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29cb0870400aca7e4487e8ec1e93f9d4288da763cb1da2cedc5102e62b6522ad" + [[package]] name = "scopeguard" version = "1.1.0" @@ -644,16 +544,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] -name = "seahash" -version = "4.1.0" +name = "scratch" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" [[package]] -name = "seq-macro" -version = "0.3.1" +name = "semver" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0772c5c30e1a0d91f6834f8e545c69281c099dfa9a3ac58d96a9fd629c8d4898" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" [[package]] name = "serde" @@ -684,12 +584,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.4" @@ -700,12 +594,13 @@ dependencies = [ ] [[package]] -name = "spinning_top" -version = "0.2.4" +name = "supports-color" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75adad84ee84b521fb2cca2d4fd0f1dab1d8d026bda3c5bea4ca63b5f9f9293c" +checksum = "8ba6faf2ca7ee42fdd458f4347ae0a9bd6bcc445ad7cb57ad82b383f18870d6f" dependencies = [ - "lock_api", + "atty", + "is_ci", ] [[package]] @@ -720,19 +615,24 @@ dependencies = [ ] [[package]] -name = "toml" -version = "0.5.9" -source = "git+https://git.ablecorp.us/theoddgarlic/toml-rs#34db433429f3ad38921d13ac9aba74c8a706f376" +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ - "hashbrown", - "serde", + "winapi-util", ] [[package]] -name = "ttf-parser" -version = "0.15.2" +name = "time" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi", + "winapi", +] [[package]] name = "uart_16550" @@ -757,12 +657,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - [[package]] name = "versioning" version = "0.1.2" @@ -771,34 +665,6 @@ dependencies = [ "serde", ] -[[package]] -name = "vga" -version = "0.2.7" -source = "git+https://git.ablecorp.us/able/vga.git#fd41943bb05ca90414e84cff3def1ffe72a62efe" -dependencies = [ - "ab_glyph", - "bitflags", - "conquer-once", - "font8x8", - "log", - "num-traits", - "spin 0.9.4", - "spinning_top", - "x86_64", -] - -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - -[[package]] -name = "volatile" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b06ad3ed06fef1713569d547cdbdb439eafed76341820fb0e0344f29a41945" - [[package]] name = "volatile" version = "0.4.5" @@ -807,49 +673,63 @@ checksum = "e3ca98349dda8a60ae74e04fd90c7fb4d6a4fbe01e6d3be095478aa0b76f6c0c" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] -name = "wasmi" -version = "0.9.1" +name = "wasm-bindgen" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca00c5147c319a8ec91ec1a0edbec31e566ce2c9cc93b3f9bb86a9efd0eb795d" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ - "downcast-rs", - "libm", - "memory_units", - "num-rational", - "num-traits", - "parity-wasm", - "wasmi-validation", + "cfg-if", + "wasm-bindgen-macro", ] [[package]] -name = "wasmi-validation" -version = "0.4.1" +name = "wasm-bindgen-backend" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "165343ecd6c018fc09ebcae280752702c9a2ef3e6f8d02f1cfcbdb53ef6d7937" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ - "parity-wasm", + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", ] [[package]] -name = "watson" -version = "0.4.1" +name = "wasm-bindgen-macro" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cea7ead78c402dbf14e7f11911b0b48955ea13d46e012e2d98775e23c65d4ef" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ - "serde", - "webassembly", + "quote", + "wasm-bindgen-macro-support", ] [[package]] -name = "webassembly" -version = "0.5.0" +name = "wasm-bindgen-macro-support" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1a10e1dedffff9cfcbdd33c289c65b87da634259a460a3f23d513649fa7a8c" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "winapi" @@ -867,12 +747,166 @@ 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 = "windows" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2649ff315bee4c98757f15dac226efe3d81927adbb6e882084bb1ee3e0c330a7" +dependencies = [ + "windows-targets 0.47.0", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f8996d3f43b4b2d44327cd71b7b0efd1284ab60e6e9d0e8b630e18555d87d3e" +dependencies = [ + "windows_aarch64_gnullvm 0.47.0", + "windows_aarch64_msvc 0.47.0", + "windows_i686_gnu 0.47.0", + "windows_i686_msvc 0.47.0", + "windows_x86_64_gnu 0.47.0", + "windows_x86_64_gnullvm 0.47.0", + "windows_x86_64_msvc 0.47.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831d567d53d4f3cb1db332b68e6e2b6260228eb4d99a777d8b2e8ed794027c90" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a42d54a417c60ce4f0e31661eed628f0fa5aca73448c093ec4d45fab4c51cdf" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1925beafdbb22201a53a483db861a5644123157c1c3cee83323a2ed565d71e3" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8ef8f2f1711b223947d9b69b596cf5a4e452c930fb58b6fc3fdae7d0ec6b31" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7acaa0c2cf0d2ef99b61c308a0c3dbae430a51b7345dedec470bd8f53f5a3642" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a0628f71be1d11e17ca4a0e9e15b3a5180f6fbf1c2d55e3ba3f850378052c1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6e62c256dc6d40b8c8707df17df8d774e60e39db723675241e7c15e910bce7" + +[[package]] +name = "x2apic" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "547152b57dd1ae0ce7a4ef1c6470f6039aa7ed22e2179d5bc4f3eda1304e0db3" +dependencies = [ + "bit", + "bitflags", + "paste", + "raw-cpuid", + "x86_64", +] + [[package]] name = "x86_64" version = "0.14.10" @@ -882,14 +916,5 @@ dependencies = [ "bit_field", "bitflags", "rustversion", - "volatile 0.4.5", -] - -[[package]] -name = "y-compositor-protocol" -version = "0.1.1" -source = "git+https://git.ablecorp.us/able/y-compositor-protocol.git#d3bcd0d41c712bfc4b4f0f9e7b5dd470e00c04a2" -dependencies = [ - "rkyv", - "serde", + "volatile", ] diff --git a/Cargo.toml b/Cargo.toml index 2384b5d..8b24ff1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,2 @@ [workspace] -members = [ - "ableos", - "asl", - "ext2-rs", - "kernel", - "facepalm", - "repbuild" -] +members = ["kernel", "repbuild"] diff --git a/TODO.md b/TODO.md deleted file mode 100644 index fb0e776..0000000 --- a/TODO.md +++ /dev/null @@ -1,46 +0,0 @@ -# AbleOS -## General -- [ ] Improve EXT2 -- [ ] Remove x86 specific code and refine the boot process - -## Capabilities -A new process should not have any capabilities at all until it is given them or requests them and is approved. -- [ ] Filesystem cap - - [ ] Create a new filesystem - - [ ] Unmount/Mount a filesystem - - [ ] read a file - - [ ] write a file - - [ ] delete a file - -- [ ] Network cap - - [ ] open/close socket - - [ ] bind/unbind socket - -- [ ] Manage Process cap - - [ ] spawn Process cap - - [ ] kill Process cap - -## Riscv - -## ARM -- [ ] Get arm-version booting on real hardware - -## Drivers -- [ ] Slim down driver specific program code - - [ ] Remove entry/exit functions for drivers - -## Filesystem -- [ ] Create a vfs that ties into the capability system -- [ ] Remote home directory - - [ ] local file caching - - [ ] remote file changes - - [ ] Update file if the remote file changes - - - - - -# Tooling -## Repbuild -- [ ] make generation of the ext2 image possible - diff --git a/ableos/.cargo/config.toml b/ableos/.cargo/config.toml deleted file mode 100644 index b747c1c..0000000 --- a/ableos/.cargo/config.toml +++ /dev/null @@ -1,15 +0,0 @@ -[build] -# target = "riscv64gc-unknown-none-elf" -target = "json_targets/x86_64-ableos.json" - -[unstable] -build-std = ["core", "compiler_builtins", "alloc"] -build-std-features = ["compiler-builtins-mem"] - -[target.'cfg(target_arch = "x86_64")'] -rustflags = ["-C", "target-feature=+rdrand"] -runner = "bootimage runner" - -[target.riscv64gc-unknown-none-elf] -rustflags = "-C link-arg=-Tableos/src/arch/riscv/virt.lds" -# ableos/src/arch/riscv/virt.lds diff --git a/ableos/Cargo.toml b/ableos/Cargo.toml deleted file mode 100644 index ca47df0..0000000 --- a/ableos/Cargo.toml +++ /dev/null @@ -1,159 +0,0 @@ -[package] -edition = "2021" -name = "ableos" -version = "0.1.1" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[profile.release] -panic = "abort" - -[package.metadata.bootimage] -run-command = [ - "qemu-system-x86_64", - - "-device", - "piix4-ide,id=ide", - - "-drive", - "file={},format=raw,if=none,id=disk", - - "-device", - "ide-hd,drive=disk,bus=ide.0" -] -run-args = [ - # "--nodefaults", - "-cpu", "Broadwell-v3", - "-m", "4G", - "-serial", "stdio", - "-smp", "cores=2", - - - "-audiodev", "id=pa,driver=pa", - "-machine", "pcspk-audiodev=pa", - - - # "-device", - # "VGA", - # "-device", - # "virtio-gpu-pci", - - "-device", "vmware-svga", - "-device", "sb16", - - - # "-machine", "pcspk-audiodev=0", - - # "-qmp", - # "unix:../qmp-sock,server,nowait", -] - -test-args = [ - "-device", - "isa-debug-exit,iobase=0xf4,iosize=0x04", - "-serial", - "stdio", -] - -[dependencies] -lazy_static = { version = "1.4.0", features = ["spin_no_std"] } -qrcode = { path = "../qrcode-rust" } -bitflags = "1.3" -lliw = "0.2.0" -spin = "0.9" -pretty-hex = "0.2.1" -unicode-width = "0.1.7" -picorand = "0.1.0" -watson = "0.4" -genfs = "0.1.0" -axel = { git = "https://git.ablecorp.us/able/aos_userland" } -versioning = { git = "https://git.ablecorp.us/able/aos_userland" } -# embedded-graphics = "*" -pc-keyboard = "0.5" -# mini-backtrace = "0.1" -clparse = { git = "https://git.ablecorp.us/able/core_utils", default-features = false } -seq-macro = "0.3" - -[dependencies.linked_list_allocator] -version = "0.9.0" -features = ["use_spin_nightly"] -[dependencies.log] -version = "0.4.17" -default-features = false - -[dependencies.logos] -version = "0.12" -default-features = false -features = ["export_derive"] - -[dependencies.rdrand] -version = "0.8" -default-features = false - -[dependencies.kernel] -path = "../kernel" - -[dependencies.serde] -version = "1.0" -default-features = false -features = ["derive", "alloc"] - -[dependencies.hashbrown] -version = "0.12" -default-features = false -features = ["inline-more"] - -[dependencies.rkyv] -version = "0.7" -default-features = false -features = ["size_64", "alloc"] - -# [dependencies.smoltcp] -# version = "0.8.0" -# default-features = false -# features = ["log", "proto-ipv4"] - -[dependencies.y-compositor-protocol] -git = "https://git.ablecorp.us:443/able/y-compositor-protocol.git" - -[dependencies.ext2] -path = "../ext2-rs" - -[dependencies.toml] -git = "https://git.ablecorp.us:443/theoddgarlic/toml-rs" -# version = "0.5.8" -default-features = false - -[dependencies.facepalm] -path = "../facepalm" - -[dependencies.ab_glyph] -version = "*" -default-features = false -features = ["libm"] - -[dependencies.wasmi] -default-features = false -features = ["core"] -version = "*" - -[dependencies.libwasm] -git = "https://git.ablecorp.us:443/able/libwasm.git" -default-features = false - -[dependencies.externc-libm] -git = "https://git.ablecorp.us:443/able/externc-libm.git" - -[target.'cfg(target_arch = "riscv")'.dependencies] -riscv = "*" - -[target.'cfg(target_arch = "x86_64")'.dependencies] -bootloader = { version = "0.9.8", features = ["map_physical_memory"] } -cpuio = { git = "https://git.ablecorp.us/ondra05/cpuio.git" } -pic8259 = "0.10.1" -uart_16550 = "0.2.0" -volatile = "0.2.6" -x86_64 = "0.14.8" -pc-beeper = { git = "https://github.com/AbleOS/pc-beeper" } -acpi = "4.1.0" -vga = { git = "https://git.ablecorp.us:443/able/vga.git" } -# vga = { path = "../../vga" } diff --git a/ableos/assets/balloon.txt b/ableos/assets/balloon.txt deleted file mode 100644 index 42192dc..0000000 --- a/ableos/assets/balloon.txt +++ /dev/null @@ -1,11 +0,0 @@ - ,-""""-. OS: \0BLUE\0 AbleOS \0RESET\0 - ,'\ _ _`. Host: ??? - / \)_)-)_)-\ Kernel: AKern-{}-v{} -: : Uptime: {} -\ / Packages: None - \ / Shell: BuiltinShell - `. ,' Resolution: 640x480 - `. ,' Terminal: VGABuffer - `.,' CPU: {} - /\`. ,-._ GPU: VGA Compatible - `-' Memory: {}/{} \ No newline at end of file diff --git a/ableos/assets/fonts/OpenSansEmoji.ttf b/ableos/assets/fonts/OpenSansEmoji.ttf deleted file mode 100644 index 57d86a6..0000000 Binary files a/ableos/assets/fonts/OpenSansEmoji.ttf and /dev/null differ diff --git a/ableos/assets/fonts/unifont-14.0.01.ttf b/ableos/assets/fonts/unifont-14.0.01.ttf deleted file mode 100644 index f955a83..0000000 Binary files a/ableos/assets/fonts/unifont-14.0.01.ttf and /dev/null differ diff --git a/ableos/assets/fonts/unifont_upper-14.0.01.ttf b/ableos/assets/fonts/unifont_upper-14.0.01.ttf deleted file mode 100644 index 7f6409b..0000000 Binary files a/ableos/assets/fonts/unifont_upper-14.0.01.ttf and /dev/null differ diff --git a/ableos/assets/img_array/balloon_array.txt b/ableos/assets/img_array/balloon_array.txt deleted file mode 100644 index 8c1b9e7..0000000 --- a/ableos/assets/img_array/balloon_array.txt +++ /dev/null @@ -1,4582 +0,0 @@ - - &[255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 254, 254, 255, 255, 254, 254, 254, 255, 254, 254, 254, 254, 255, 255, 255, 254, 254, 254, - 255, 255, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 254, 254, 254, 254, 254, 254, 253, 254, 254, 253, 254, 254, 254, 254, 254, - 254, 254, 254, 254, 254, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 253, 253, 253, 253, 253, 253, 254, 254, 253, 253, 254, 253, 253, - 254, 255, 254, 254, 254, 254, 253, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 254, 253, 253, 254, 254, 252, 251, 251, 251, 251, 252, 250, - 251, 252, 252, 252, 252, 251, 253, 254, 254, 254, 253, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 252, 247, 241, 226, 209, 201, 201, 197, 190, 200, - 211, 198, 187, 187, 179, 162, 157, 164, 191, 220, 234, 242, 250, 253, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, - 254, 254, 254, 254, 254, 254, 253, 247, 241, 233, 209, 174, 149, 130, 105, 112, 123, 100, - 70, 69, 80, 80, 74, 60, 43, 30, 29, 34, 54, 79, 96, 131, 180, 211, 234, 250, 254, 254, 254, - 254, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 254, 253, - 254, 254, 254, 249, 234, 199, 140, 106, 106, 97, 53, 36, 37, 27, 25, 40, 41, 16, 7, 5, 8, - 12, 10, 4, 1, 1, 2, 5, 7, 7, 12, 37, 82, 103, 141, 203, 241, 253, 254, 253, 253, 253, 253, - 253, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 251, 244, 230, 201, 117, - 66, 56, 36, 21, 28, 30, 25, 9, 3, 3, 4, 4, 1, 1, 1, 2, 2, 5, 6, 5, 7, 10, 3, 1, 3, 6, 5, 9, - 12, 11, 30, 92, 172, 224, 247, 253, 253, 253, 253, 253, 252, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 254, 253, 249, 244, 235, 211, 174, 118, 51, 56, 109, 61, 10, 6, 29, 71, 40, 8, 1, 0, 0, 0, - 1, 3, 4, 2, 3, 5, 9, 14, 16, 7, 2, 4, 9, 6, 1, 2, 5, 33, 61, 55, 69, 133, 204, 244, 253, - 253, 254, 252, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, - 254, 254, 254, 254, 254, 254, 255, 254, 253, 252, 239, 190, 163, 175, 178, 138, 71, 43, 49, - 85, 53, 9, 2, 12, 48, 51, 12, 1, 1, 0, 0, 0, 2, 7, 6, 3, 3, 6, 9, 6, 5, 5, 2, 3, 10, 5, 8, - 30, 78, 86, 37, 12, 25, 71, 149, 229, 252, 253, 253, 253, 255, 255, 255, 254, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 253, 254, 254, 254, 254, 254, 254, 253, 254, 253, 254, 254, 250, 223, 175, - 126, 66, 37, 38, 46, 55, 74, 75, 25, 10, 11, 15, 25, 22, 11, 9, 2, 5, 16, 19, 12, 12, 9, - 12, 27, 46, 43, 20, 12, 9, 11, 14, 8, 6, 15, 29, 44, 56, 42, 25, 24, 41, 55, 40, 32, 100, - 193, 239, 253, 254, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, - 249, 247, 251, 254, 253, 250, 227, 166, 83, 35, 15, 15, 12, 6, 1, 4, 25, 46, 16, 0, 2, 24, - 73, 54, 21, 4, 6, 39, 74, 75, 115, 115, 51, 35, 76, 152, 168, 99, 72, 90, 96, 69, 38, 17, - 18, 33, 25, 15, 25, 38, 58, 93, 61, 25, 28, 45, 70, 119, 196, 244, 252, 253, 253, 253, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 254, 254, 253, 253, 253, 247, 221, 216, 227, 240, 242, 190, 107, 50, 36, 17, - 4, 9, 30, 39, 19, 1, 2, 3, 12, 8, 9, 23, 36, 18, 12, 15, 41, 88, 120, 150, 212, 210, 153, - 145, 177, 213, 221, 201, 200, 216, 198, 172, 142, 100, 50, 23, 19, 41, 88, 100, 98, 93, 49, - 36, 77, 58, 30, 40, 87, 159, 218, 246, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 253, - 246, 216, 184, 181, 184, 179, 150, 81, 30, 27, 64, 61, 25, 25, 63, 119, 80, 8, 2, 10, 35, - 25, 27, 38, 30, 37, 75, 119, 163, 196, 216, 234, 247, 250, 247, 247, 250, 251, 252, 252, - 252, 253, 250, 247, 244, 235, 207, 139, 78, 54, 44, 35, 34, 42, 41, 61, 136, 122, 90, 79, - 55, 46, 85, 169, 237, 252, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 245, 198, 149, 136, 143, 121, - 61, 36, 33, 20, 11, 33, 80, 103, 68, 50, 95, 110, 39, 30, 80, 105, 63, 79, 109, 116, 158, - 212, 241, 251, 253, 253, 254, 252, 253, 254, 253, 253, 254, 254, 254, 253, 253, 254, 253, - 253, 254, 254, 249, 224, 161, 81, 40, 30, 35, 38, 40, 41, 36, 42, 51, 41, 27, 30, 56, 129, - 206, 242, 253, 255, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 253, 253, 252, 215, 130, 90, 95, 75, 32, 11, 9, 18, 20, 9, 9, 27, - 54, 30, 10, 22, 53, 61, 77, 118, 158, 155, 184, 221, 236, 249, 253, 254, 254, 254, 254, - 254, 254, 254, 254, 254, 254, 254, 255, 254, 254, 254, 255, 254, 254, 254, 255, 254, 252, - 247, 216, 156, 80, 25, 16, 12, 4, 1, 5, 17, 30, 28, 25, 34, 53, 87, 139, 207, 242, 252, - 254, 253, 253, 253, 252, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 254, 253, 247, 196, 118, 83, 66, 25, 7, 3, 3, 15, 29, 38, 37, 23, 12, 5, 1, 6, 28, 69, 103, - 153, 212, 238, 247, 253, 253, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 253, 241, 186, 79, 25, 6, - 1, 2, 9, 20, 32, 37, 65, 76, 29, 19, 34, 78, 146, 211, 247, 253, 253, 253, 253, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 225, 160, 113, 65, 22, 10, - 4, 3, 3, 11, 39, 110, 142, 63, 16, 28, 30, 32, 70, 146, 200, 238, 252, 254, 254, 254, 253, - 254, 254, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 253, 253, 254, 254, 253, 251, 224, 149, 54, 12, 30, 60, 75, 80, 90, - 174, 116, 12, 1, 3, 7, 18, 66, 148, 215, 247, 253, 253, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 254, 252, 207, 100, 39, 12, 3, 2, 3, 5, 7, 7, 19, 88, 130, - 58, 30, 105, 152, 167, 212, 246, 253, 254, 254, 254, 253, 253, 254, 254, 254, 254, 253, - 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 254, 253, 254, 254, 254, 254, 254, 250, 214, 146, 118, 125, 125, 117, 88, 80, 29, 5, 4, 4, - 3, 0, 4, 22, 60, 139, 207, 245, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 254, - 254, 253, 249, 167, 38, 7, 4, 2, 0, 2, 5, 7, 6, 8, 33, 53, 45, 78, 156, 221, 246, 253, 254, - 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 255, 254, - 254, 253, 246, 212, 156, 84, 29, 8, 4, 6, 36, 30, 8, 5, 16, 38, 49, 46, 32, 56, 145, 233, - 251, 254, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 252, 254, 250, 198, 66, 14, 14, 7, 2, 1, - 2, 4, 3, 4, 5, 9, 25, 86, 181, 238, 252, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 241, 191, 85, - 17, 4, 2, 29, 40, 12, 12, 73, 112, 102, 100, 46, 30, 67, 136, 193, 241, 253, 253, 253, 254, - 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 254, 252, 253, 253, 253, 207, 72, 12, 27, 21, 6, 0, 1, 2, 3, 4, 2, 3, 12, 81, 197, - 249, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 253, 252, 254, 252, 235, 179, 110, 37, 12, 30, 51, - 56, 51, 34, 23, 30, 35, 69, 110, 77, 66, 146, 223, 245, 252, 254, 253, 253, 254, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 251, - 234, 144, 35, 11, 12, 5, 1, 2, 6, 2, 0, 2, 3, 9, 44, 137, 227, 253, 254, 253, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 254, 253, 254, 253, 253, 252, 242, 192, 107, 56, 56, 56, 29, 21, 20, 17, 15, - 19, 28, 24, 18, 42, 87, 135, 204, 245, 252, 252, 253, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 252, 250, 210, 113, 61, 22, 10, 3, 0, 0, - 1, 3, 1, 1, 0, 11, 38, 80, 151, 231, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, - 254, 254, 254, 253, 251, 233, 179, 105, 41, 23, 24, 23, 14, 9, 5, 5, 7, 7, 14, 21, 37, 102, - 189, 236, 251, 253, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, - 253, 253, 254, 252, 212, 80, 8, 10, 11, 11, 6, 2, 2, 0, 0, 0, 1, 1, 15, 70, 151, 191, 235, - 252, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 254, 254, 252, - 226, 147, 64, 25, 11, 6, 5, 6, 7, 8, 6, 11, 14, 11, 34, 85, 141, 210, 247, 253, 254, 253, - 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 252, 253, 252, 253, 253, 226, 108, 18, 6, 14, - 36, 46, 25, 11, 5, 0, 1, 0, 3, 6, 24, 103, 215, 232, 244, 253, 253, 254, 254, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 249, 217, 141, 65, 22, 8, - 2, 1, 3, 6, 9, 11, 8, 8, 12, 46, 132, 212, 247, 253, 254, 253, 254, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 253, 253, 253, 252, 227, 125, 81, 54, 25, 37, 89, 110, 55, 18, 7, 5, 7, 12, - 19, 49, 67, 86, 133, 171, 221, 250, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 253, 253, 252, 242, 201, 115, 43, 12, 2, 3, 6, 5, 5, 6, 5, 5, - 23, 89, 160, 196, 242, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, - 234, 125, 37, 39, 42, 33, 27, 29, 42, 59, 33, 9, 8, 23, 28, 22, 59, 61, 33, 35, 70, 150, - 233, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 253, 253, 252, 253, 252, 229, 167, 90, 38, 12, 7, 5, 2, 2, 2, 5, 12, 33, 59, 102, 190, 245, - 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 253, 242, 154, 83, 63, 28, 18, 15, 6, 2, - 10, 42, 36, 20, 27, 49, 55, 20, 19, 27, 15, 8, 24, 86, 201, 253, 254, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 253, 254, 253, 253, 242, - 196, 106, 38, 14, 6, 4, 2, 6, 15, 21, 22, 41, 89, 140, 203, 246, 254, 254, 254, 254, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, - 253, 253, 253, 254, 246, 170, 85, 93, 61, 22, 9, 6, 4, 3, 4, 9, 22, 60, 71, 99, 98, 34, 45, - 83, 53, 21, 30, 72, 172, 247, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 244, 186, 90, 43, 20, 9, 5, 11, 27, - 23, 12, 27, 74, 113, 136, 199, 249, 253, 254, 253, 254, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 253, 253, 251, 186, 54, 40, 56, - 32, 12, 7, 11, 18, 7, 2, 2, 46, 125, 110, 84, 48, 30, 83, 123, 70, 33, 42, 77, 145, 236, - 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 254, 253, 252, 241, 171, 82, 41, 25, 32, 32, 22, 14, 19, 30, 30, 55, 95, - 147, 225, 253, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 254, 253, 253, 252, 218, 80, 12, 9, 18, 12, 7, 7, 23, 42, 16, 5, - 38, 164, 205, 147, 80, 34, 12, 28, 34, 30, 56, 119, 147, 151, 221, 253, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 252, - 253, 253, 232, 137, 61, 50, 85, 72, 28, 21, 42, 40, 11, 17, 73, 132, 193, 247, 253, 253, - 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 254, 253, 254, 233, 107, 17, 12, 6, 3, 5, 5, 7, 16, 29, 18, 45, 179, 247, 223, 129, 54, 22, - 11, 12, 9, 14, 59, 156, 181, 154, 205, 252, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 253, 253, 251, 215, 125, - 69, 72, 58, 30, 30, 37, 25, 25, 36, 73, 155, 203, 227, 252, 253, 254, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 254, 235, 136, 27, 3, - 7, 10, 5, 3, 4, 3, 3, 6, 30, 160, 249, 253, 236, 142, 51, 23, 24, 25, 16, 12, 30, 81, 113, - 131, 194, 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 250, 210, 110, 56, 27, 9, 7, 17, 32, 80, - 102, 96, 128, 172, 196, 241, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 254, 253, 246, 140, 27, 1, 0, 3, 9, 8, 4, 4, 5, 8, 30, 126, - 237, 253, 253, 250, 200, 113, 68, 58, 34, 30, 25, 14, 30, 70, 126, 205, 250, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 254, 253, 246, 176, 83, 36, 12, 6, 10, 12, 21, 33, 36, 46, 75, 133, 210, - 251, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 254, 252, 181, 30, 1, 0, 2, 7, 12, 30, 28, 17, 19, 60, 161, 235, 252, 253, 253, 253, 244, - 198, 144, 103, 54, 61, 56, 25, 32, 76, 118, 186, 244, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 253, 252, 212, 110, 69, 61, 32, 7, 2, 1, 2, 10, 27, 51, 90, 165, 238, 253, 254, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 209, 61, 4, 2, 10, - 25, 25, 27, 76, 112, 96, 88, 162, 247, 253, 253, 254, 253, 253, 245, 196, 160, 127, 93, 84, - 85, 90, 82, 76, 66, 122, 225, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 240, 154, 109, - 115, 56, 7, 3, 0, 0, 7, 25, 48, 73, 128, 213, 253, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 254, 254, 254, 224, 92, 14, 10, 10, 30, 65, 55, 33, 30, 54, 87, - 133, 221, 253, 253, 253, 254, 253, 254, 249, 201, 155, 129, 108, 90, 103, 121, 65, 25, 38, - 119, 221, 252, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 254, 251, 209, 142, 98, 38, 5, 3, 1, 0, - 2, 12, 25, 53, 105, 193, 247, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 253, 253, 253, 247, 154, 33, 23, 27, 19, 24, 46, 41, 17, 3, 10, 70, 187, 249, 254, 254, - 254, 254, 254, 254, 253, 233, 178, 136, 110, 107, 103, 56, 17, 25, 89, 159, 221, 250, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 254, 254, 253, 234, 151, 70, 24, 8, 6, 6, 2, 5, 10, 11, 30, 88, - 157, 229, 253, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 217, - 90, 37, 30, 30, 17, 7, 10, 12, 6, 8, 28, 134, 240, 253, 254, 255, 255, 255, 254, 254, 254, - 251, 235, 187, 137, 87, 38, 10, 30, 109, 162, 184, 224, 251, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 254, 254, 254, 245, 168, 71, 41, 30, 18, 16, 25, 33, 23, 12, 33, 77, 90, 179, 249, 253, - 253, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 244, 168, 72, 25, 12, 21, 29, - 25, 20, 24, 37, 82, 113, 215, 252, 253, 254, 255, 255, 255, 254, 254, 254, 253, 252, 239, - 203, 98, 25, 17, 73, 153, 159, 169, 219, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, - 253, 216, 119, 67, 50, 22, 8, 46, 38, 12, 32, 61, 51, 59, 162, 245, 253, 253, 254, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 254, 253, 249, 191, 90, 76, 71, 51, 64, 84, 71, 42, 49, 93, - 174, 215, 250, 252, 253, 254, 255, 255, 255, 254, 254, 254, 254, 254, 247, 196, 100, 64, - 77, 95, 112, 122, 151, 217, 251, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 242, - 178, 85, 46, 27, 11, 18, 9, 2, 14, 30, 24, 59, 164, 236, 251, 254, 253, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, - 255, 254, 254, 254, 253, 224, 109, 38, 41, 61, 73, 58, 45, 30, 15, 12, 40, 178, 251, 253, - 254, 254, 254, 255, 255, 255, 255, 254, 253, 254, 254, 242, 171, 120, 137, 165, 136, 115, - 116, 155, 224, 247, 245, 246, 246, 242, 242, 244, 245, 247, 253, 254, 254, 255, 254, 254, - 254, 254, 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 252, 224, 132, 76, - 64, 39, 10, 1, 0, 1, 7, 24, 71, 100, 165, 237, 253, 253, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, - 254, 236, 134, 36, 14, 8, 11, 19, 14, 11, 14, 30, 51, 105, 227, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 246, 203, 184, 180, 177, 189, 170, 153, 167, 184, - 178, 163, 175, 212, 204, 181, 165, 160, 161, 167, 175, 186, 201, 229, 247, 253, 253, 252, - 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 246, 181, 107, 72, 46, 17, 6, - 3, 1, 2, 10, 28, 37, 85, 189, 250, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 254, 254, 249, 176, 56, - 20, 19, 15, 11, 12, 12, 15, 17, 40, 99, 199, 251, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 253, 242, 230, 214, 197, 180, 140, 121, 93, 102, 137, 128, 93, - 110, 108, 87, 79, 76, 61, 37, 32, 42, 64, 99, 138, 181, 232, 251, 254, 254, 254, 253, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 253, 253, 220, 144, 84, 58, 44, 30, 15, 3, 0, 3, 8, 19, 48, - 141, 241, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 254, 253, 254, 254, 223, 96, 32, 38, 64, 83, 72, 30, 15, 10, - 8, 20, 116, 233, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 252, 251, 246, 221, 140, 73, 56, 37, 79, 165, 137, 44, 23, 18, 19, 19, 15, 9, 4, 4, 12, 46, - 61, 41, 49, 123, 229, 244, 250, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 254, 242, - 171, 106, 80, 60, 37, 17, 6, 4, 12, 18, 23, 54, 141, 236, 253, 254, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, - 254, 247, 160, 53, 40, 51, 88, 125, 107, 36, 7, 4, 6, 44, 184, 250, 253, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 252, 224, 153, 109, 51, 25, 9, - 36, 87, 70, 23, 5, 3, 4, 2, 0, 0, 3, 33, 74, 141, 115, 39, 16, 46, 133, 155, 191, 235, 250, - 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 253, 251, 214, 168, 141, 78, 27, 12, 9, 10, 34, 54, - 68, 122, 167, 209, 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 253, 227, 129, 100, 73, 40, 45, 37, 27, - 23, 25, 37, 61, 151, 242, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, - 254, 254, 254, 253, 221, 113, 38, 17, 8, 10, 4, 2, 2, 3, 14, 22, 9, 1, 0, 0, 2, 17, 70, 87, - 100, 66, 21, 5, 7, 18, 38, 88, 159, 206, 229, 249, 253, 254, 254, 253, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, - 250, 231, 200, 121, 49, 20, 15, 16, 25, 51, 132, 186, 133, 115, 216, 252, 254, 254, 253, - 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, - 253, 246, 183, 151, 168, 93, 49, 53, 28, 15, 30, 66, 112, 161, 227, 252, 254, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 254, 254, 244, 152, 59, 21, 2, 2, - 14, 8, 0, 0, 3, 19, 33, 12, 2, 2, 3, 8, 16, 12, 6, 5, 5, 2, 1, 1, 0, 8, 29, 65, 149, 195, - 218, 250, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 254, 254, 253, 252, 216, 135, 93, 63, 33, 29, 39, 17, 14, 56, - 97, 88, 90, 177, 245, 253, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 254, 252, 209, 99, 95, 100, 51, 38, 34, 12, 4, 11, 20, 68, - 181, 247, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 253, - 250, 210, 145, 122, 78, 18, 6, 12, 7, 0, 1, 3, 4, 12, 12, 15, 27, 29, 17, 8, 1, 0, 0, 1, 3, - 3, 1, 0, 1, 5, 24, 93, 144, 168, 226, 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 253, 217, 100, - 53, 42, 28, 30, 34, 7, 0, 10, 36, 76, 115, 164, 231, 253, 253, 254, 254, 254, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 242, 157, 49, 39, 46, - 36, 19, 6, 5, 10, 8, 12, 85, 220, 253, 252, 254, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 254, 254, 254, 253, 249, 205, 118, 82, 63, 38, 20, 14, 14, 10, 5, 6, 5, 8, 23, 50, 90, - 118, 105, 76, 59, 46, 30, 14, 6, 16, 42, 56, 30, 3, 1, 9, 30, 68, 117, 181, 242, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 253, 254, 245, 174, 106, 100, 103, 93, 58, 30, 25, 23, 33, 61, 112, 165, - 221, 251, 253, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 254, 254, 254, 252, 216, 127, 33, 10, 17, 25, 18, 6, 7, 24, 53, 80, 164, 246, 253, 254, - 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 218, 96, 25, 17, 14, - 19, 37, 40, 25, 18, 14, 30, 54, 88, 142, 186, 215, 221, 220, 218, 212, 204, 187, 113, 30, - 11, 17, 35, 27, 9, 2, 1, 4, 24, 85, 164, 235, 253, 254, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 253, 234, - 164, 119, 133, 132, 56, 74, 110, 65, 37, 43, 73, 131, 197, 244, 253, 253, 253, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 242, 147, 66, 17, 5, - 9, 18, 20, 12, 12, 30, 71, 141, 223, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 254, 254, 249, 169, 43, 9, 10, 20, 38, 66, 76, 58, 34, 15, 43, 144, 224, - 245, 251, 253, 253, 254, 254, 253, 252, 247, 179, 60, 17, 5, 1, 2, 6, 4, 1, 2, 12, 50, 136, - 230, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 254, 254, 254, 254, 250, 197, 117, 93, 79, 37, 61, 96, 53, 38, 49, - 68, 105, 168, 231, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 254, 254, 253, 254, 253, 204, 67, 17, 12, 14, 11, 15, 17, 15, 18, 15, 33, 160, 246, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 244, 161, 64, - 30, 33, 42, 46, 50, 65, 64, 39, 18, 55, 184, 252, 253, 253, 255, 255, 255, 255, 254, 253, - 252, 200, 78, 30, 17, 8, 4, 3, 6, 11, 8, 12, 35, 115, 221, 253, 254, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 254, 253, 234, 168, 105, 56, 28, 24, 25, 21, 33, 51, 68, 100, 160, 224, 251, 253, 253, - 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 247, 162, 46, - 14, 16, 19, 14, 14, 18, 16, 19, 11, 56, 209, 252, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 254, 254, 249, 221, 166, 106, 76, 51, 25, 20, 29, 23, 18, 40, - 106, 213, 253, 253, 253, 255, 255, 255, 255, 254, 254, 253, 217, 119, 82, 61, 37, 21, 15, - 15, 33, 23, 25, 68, 154, 225, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 251, 220, 151, - 82, 33, 7, 3, 6, 12, 15, 24, 56, 134, 214, 247, 253, 253, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 253, 254, 254, 246, 176, 70, 15, 6, 14, 23, 34, 37, 24, 29, - 55, 157, 247, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 254, 255, 246, 233, 197, 123, 68, 35, 18, 19, 25, 22, 19, 79, 179, 241, 253, 253, 254, 255, - 255, 255, 255, 254, 253, 253, 231, 175, 159, 103, 34, 28, 38, 30, 25, 40, 61, 98, 183, 240, - 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 253, 252, 218, 139, 82, 46, 16, 2, 1, 1, 1, 4, 24, - 84, 164, 221, 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, - 254, 250, 219, 165, 99, 28, 7, 15, 44, 71, 58, 30, 44, 107, 221, 253, 254, 254, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 241, 207, 137, 59, 21, 11, - 12, 25, 42, 61, 72, 116, 179, 238, 253, 253, 254, 254, 254, 254, 249, 246, 253, 253, 234, - 158, 128, 85, 25, 12, 34, 37, 23, 42, 64, 83, 170, 244, 253, 254, 254, 254, 254, 254, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 254, 253, 254, 230, 140, 68, 54, 48, 14, 0, 0, 1, 15, 48, 83, 117, 172, 241, 254, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 219, 109, 35, 25, 20, 6, 8, 36, - 64, 49, 24, 37, 134, 245, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 254, 254, 221, 129, 53, 19, 9, 7, 10, 18, 39, 100, 144, 123, 152, 231, 254, - 253, 253, 253, 252, 240, 195, 184, 225, 244, 219, 83, 22, 22, 29, 11, 14, 16, 15, 15, 29, - 77, 177, 245, 253, 253, 254, 253, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 254, 246, 183, 85, 55, 58, 22, - 3, 1, 4, 19, 51, 77, 100, 156, 227, 252, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 254, 253, 245, 156, 50, 22, 17, 11, 8, 6, 11, 14, 11, 14, 78, 200, 252, 253, 253, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 223, 126, 49, - 25, 15, 8, 7, 21, 36, 77, 121, 123, 155, 230, 254, 253, 253, 253, 244, 184, 110, 103, 137, - 163, 156, 55, 8, 4, 9, 5, 3, 2, 2, 3, 14, 58, 163, 238, 253, 252, 253, 252, 253, 254, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 254, 254, 253, 251, 232, 148, 78, 53, 33, 20, 12, 5, 4, 16, 37, 67, 126, 196, 244, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 252, 218, 97, 49, 64, 41, 22, 36, - 25, 11, 7, 10, 51, 159, 241, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 254, 254, 238, 166, 80, 30, 12, 7, 12, 32, 41, 54, 95, 135, 171, - 229, 253, 253, 251, 242, 177, 95, 58, 63, 82, 93, 88, 71, 59, 25, 5, 2, 3, 3, 0, 1, 3, 8, - 38, 115, 191, 238, 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 253, 250, 196, 84, 35, 33, 23, - 8, 2, 1, 4, 14, 33, 69, 134, 217, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 254, 251, 176, 61, 35, 45, 44, 63, 90, 42, 15, 15, 32, 110, 212, 252, 253, 254, 254, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 242, 184, 99, - 30, 9, 10, 23, 30, 27, 41, 86, 100, 120, 178, 217, 227, 207, 138, 49, 24, 33, 60, 89, 109, - 95, 90, 93, 42, 11, 5, 3, 4, 2, 0, 4, 12, 11, 12, 37, 106, 207, 246, 253, 253, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 254, 253, 253, 253, 217, 95, 38, 30, 20, 7, 1, 1, 4, 10, 17, 32, 71, 170, 247, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 254, 254, 255, 254, 254, 254, 247, 158, 65, 27, 9, 28, 90, 96, 39, 25, 33, - 59, 139, 231, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 254, 252, 242, 176, 98, 45, 22, 15, 17, 12, 5, 18, 38, 17, 14, 33, 76, 128, - 96, 21, 1, 7, 38, 87, 105, 129, 131, 67, 22, 10, 9, 6, 3, 3, 1, 1, 16, 61, 55, 20, 7, 23, - 99, 154, 193, 240, 253, 254, 254, 253, 254, 254, 254, 254, 254, 253, 254, 254, 254, 254, - 253, 254, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 236, 166, 115, 58, 28, 12, 4, 3, 10, 18, - 17, 20, 44, 136, 238, 254, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 254, 254, 253, 240, 160, 112, - 83, 36, 28, 49, 68, 80, 73, 56, 71, 175, 247, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 245, 181, 82, 46, 30, 15, 4, 2, 1, - 5, 6, 1, 1, 2, 12, 21, 9, 1, 6, 17, 45, 61, 28, 16, 23, 30, 20, 10, 3, 2, 1, 2, 6, 9, 23, - 72, 73, 29, 12, 19, 28, 34, 60, 138, 219, 249, 253, 253, 253, 253, 252, 252, 252, 253, 254, - 254, 254, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 254, 253, 254, 254, 254, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 249, 216, 166, 75, 24, 12, - 7, 8, 16, 25, 24, 22, 54, 134, 227, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 254, 249, - 196, 100, 82, 105, 82, 35, 17, 30, 83, 72, 37, 75, 210, 252, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 250, 190, 76, 34, 33, - 24, 8, 3, 3, 1, 0, 0, 4, 16, 5, 1, 1, 5, 30, 34, 24, 18, 3, 0, 0, 4, 23, 37, 14, 3, 3, 6, - 9, 16, 16, 14, 15, 12, 17, 34, 27, 21, 29, 61, 129, 209, 249, 253, 253, 253, 253, 253, 253, - 251, 242, 227, 214, 206, 203, 205, 215, 231, 239, 242, 250, 252, 252, 253, 254, 254, 254, - 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 251, 200, 116, - 55, 28, 19, 7, 1, 4, 23, 42, 65, 90, 136, 212, 252, 253, 254, 253, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, - 253, 229, 141, 69, 44, 51, 58, 25, 4, 4, 19, 23, 27, 105, 236, 254, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 253, 235, - 152, 71, 38, 17, 6, 2, 1, 0, 0, 0, 3, 11, 0, 0, 1, 5, 11, 11, 9, 6, 1, 0, 1, 1, 6, 19, 28, - 21, 8, 5, 18, 48, 30, 15, 5, 5, 16, 23, 18, 17, 24, 49, 99, 165, 238, 253, 253, 253, 253, - 249, 226, 194, 168, 123, 95, 81, 71, 63, 71, 92, 108, 150, 199, 209, 227, 244, 253, 254, - 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 221, - 142, 93, 61, 38, 19, 8, 9, 24, 49, 93, 106, 121, 183, 247, 253, 254, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, - 254, 254, 251, 205, 110, 58, 25, 15, 18, 24, 29, 25, 22, 50, 115, 203, 251, 254, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, - 253, 253, 240, 187, 112, 46, 12, 4, 0, 0, 6, 25, 24, 4, 0, 2, 10, 4, 1, 3, 9, 7, 10, 24, - 21, 7, 3, 8, 40, 65, 36, 35, 134, 207, 162, 93, 39, 18, 14, 17, 21, 41, 79, 115, 155, 209, - 247, 253, 253, 253, 239, 179, 110, 87, 129, 128, 88, 56, 45, 50, 39, 15, 16, 53, 100, 90, - 90, 110, 157, 214, 242, 252, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 242, 183, 106, 58, 48, 45, 25, 9, 11, 22, 48, 53, 61, 127, 232, 253, 254, - 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 254, 253, 254, 242, 165, 65, 34, 24, 12, 6, 7, 18, 22, 25, 64, 159, 242, - 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 254, 254, 254, 254, 254, 254, 249, 226, 171, 102, 48, 19, 11, 29, 59, 39, 10, 12, 25, - 22, 12, 18, 20, 23, 35, 68, 123, 113, 39, 12, 12, 23, 38, 45, 123, 234, 252, 250, 233, 180, - 116, 56, 36, 65, 120, 172, 194, 213, 242, 252, 253, 253, 241, 162, 97, 77, 51, 58, 65, 51, - 48, 93, 131, 80, 16, 5, 7, 16, 22, 18, 15, 30, 60, 108, 180, 235, 251, 253, 254, 253, 254, - 255, 255, 255, 255, 255, 255, 255, 254, 254, 251, 207, 108, 51, 35, 22, 8, 2, 2, 7, 17, 27, - 46, 103, 212, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 254, 226, 110, 20, 11, 23, 25, 9, 1, 0, - 1, 10, 44, 144, 244, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 250, 233, 186, 122, 72, - 51, 44, 25, 20, 44, 61, 28, 37, 67, 49, 46, 99, 113, 118, 99, 38, 19, 25, 44, 48, 103, 215, - 252, 253, 254, 253, 251, 236, 195, 139, 122, 134, 168, 213, 239, 252, 253, 253, 242, 179, - 123, 92, 53, 28, 20, 20, 20, 34, 79, 77, 35, 18, 15, 3, 3, 12, 11, 6, 14, 18, 18, 41, 116, - 200, 242, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 227, 151, 93, - 36, 7, 2, 1, 1, 1, 7, 30, 60, 105, 201, 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 251, 194, 78, 7, - 0, 9, 22, 14, 4, 2, 2, 12, 58, 173, 251, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 254, 254, - 254, 253, 242, 219, 169, 123, 103, 100, 97, 67, 35, 44, 42, 29, 46, 88, 50, 20, 9, 4, 8, - 38, 109, 161, 221, 250, 252, 252, 254, 253, 253, 253, 254, 249, 229, 201, 201, 233, 250, - 253, 253, 247, 183, 74, 69, 53, 20, 10, 8, 6, 8, 8, 9, 4, 2, 18, 33, 12, 7, 22, 19, 10, 20, - 42, 34, 16, 37, 93, 184, 249, 254, 254, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, - 241, 177, 106, 46, 17, 5, 3, 0, 0, 6, 41, 72, 110, 195, 247, 254, 254, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, - 238, 148, 61, 9, 2, 2, 2, 4, 9, 12, 16, 39, 112, 219, 254, 253, 254, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 254, 254, 254, 254, 254, 253, 253, 252, 247, 242, 239, 194, 116, 96, 64, 23, 17, 28, - 30, 15, 7, 5, 5, 12, 42, 129, 223, 252, 253, 253, 253, 254, 254, 254, 253, 254, 254, 253, - 254, 254, 253, 253, 254, 252, 207, 105, 29, 21, 21, 12, 11, 12, 4, 6, 20, 18, 11, 9, 17, - 18, 9, 9, 14, 19, 27, 46, 68, 49, 24, 41, 84, 161, 237, 250, 254, 255, 255, 255, 255, 255, - 255, 255, 254, 254, 254, 242, 157, 53, 38, 34, 12, 5, 3, 0, 3, 32, 78, 115, 174, 241, 253, - 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 253, 254, 219, 103, 30, 6, 6, 5, 3, 3, 10, 25, 45, 74, 161, 242, 253, 253, - 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 246, - 221, 210, 152, 75, 54, 56, 54, 58, 56, 37, 41, 73, 132, 217, 251, 254, 254, 254, 254, 254, - 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 236, 138, 54, 15, 22, 49, 35, 23, - 38, 16, 8, 23, 61, 74, 51, 34, 23, 21, 19, 9, 12, 27, 35, 25, 20, 19, 39, 73, 107, 144, - 204, 247, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 247, 198, 82, 25, 18, 17, 12, - 12, 9, 2, 12, 50, 100, 163, 236, 253, 254, 254, 254, 254, 254, 254, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 252, 199, 83, 23, 22, 39, 25, - 14, 20, 42, 75, 84, 103, 198, 250, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 241, 203, 181, 173, 137, 103, 93, - 90, 109, 167, 227, 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 253, 219, 100, 37, 17, 23, 61, 61, 49, 65, 48, 20, 12, 63, 107, 98, 75, 80, - 105, 107, 63, 38, 25, 9, 1, 1, 4, 15, 41, 53, 56, 135, 231, 254, 254, 254, 253, 254, 254, - 254, 253, 254, 254, 252, 220, 116, 46, 27, 20, 12, 23, 35, 11, 6, 23, 73, 150, 225, 252, - 254, 254, 254, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 254, 241, 140, 42, 23, 80, 127, 60, 23, 53, 132, 133, 89, 135, 231, 253, - 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 254, 253, 253, 250, 240, 205, 159, 150, 183, 221, 245, 252, 254, 254, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 251, 211, 125, 92, - 66, 20, 16, 45, 63, 41, 55, 41, 50, 141, 199, 214, 213, 217, 227, 229, 206, 138, 43, 3, 0, - 0, 0, 3, 18, 35, 55, 128, 218, 252, 254, 254, 254, 253, 253, 253, 253, 254, 252, 251, 210, - 118, 84, 41, 10, 5, 15, 27, 18, 7, 16, 54, 119, 189, 239, 251, 253, 254, 254, 253, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 219, 90, - 30, 21, 46, 66, 42, 35, 55, 80, 55, 58, 166, 247, 254, 253, 254, 254, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 253, - 253, 251, 246, 245, 249, 252, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 253, 239, 191, 180, 181, 144, 38, 7, 12, 18, 11, 21, 51, 119, - 221, 251, 252, 253, 253, 253, 238, 181, 93, 25, 7, 7, 5, 6, 6, 6, 17, 60, 137, 212, 250, - 253, 253, 253, 253, 253, 251, 249, 242, 224, 187, 127, 61, 38, 20, 9, 5, 2, 3, 5, 11, 30, - 69, 85, 110, 150, 186, 221, 245, 252, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 254, 252, 217, 106, 48, 22, 10, 9, 19, 34, 34, 20, 18, 65, - 198, 252, 254, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 254, 254, 253, 253, 254, 254, 253, 253, 253, 254, 254, 254, - 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 233, - 197, 210, 196, 134, 25, 2, 1, 3, 5, 20, 61, 143, 237, 253, 254, 253, 253, 254, 242, 152, - 58, 23, 38, 54, 22, 16, 12, 11, 20, 53, 119, 203, 249, 253, 253, 252, 247, 229, 198, 186, - 179, 131, 75, 38, 17, 8, 9, 18, 10, 1, 1, 1, 7, 23, 41, 43, 53, 56, 59, 105, 170, 216, 246, - 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 219, - 155, 96, 51, 23, 27, 22, 12, 9, 9, 33, 110, 226, 253, 254, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, - 254, 254, 255, 255, 254, 254, 255, 255, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 253, 231, 165, 120, 79, 49, 15, 6, 10, 15, 16, 28, 48, - 121, 235, 253, 254, 253, 254, 254, 247, 158, 61, 34, 56, 82, 42, 30, 34, 34, 37, 60, 103, - 177, 242, 242, 224, 197, 160, 102, 55, 63, 77, 50, 25, 12, 6, 3, 5, 11, 4, 0, 0, 0, 1, 4, - 3, 5, 9, 16, 37, 78, 112, 152, 218, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 237, 171, 118, 99, 95, 123, 160, 61, 5, 0, 11, 63, 152, 239, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 214, 107, 46, - 34, 30, 27, 24, 19, 15, 16, 25, 40, 112, 231, 253, 254, 254, 254, 254, 250, 177, 97, 71, - 58, 41, 24, 23, 34, 53, 65, 75, 90, 131, 173, 120, 73, 61, 58, 30, 8, 4, 3, 5, 8, 8, 2, 2, - 1, 0, 0, 0, 0, 0, 0, 3, 2, 7, 18, 38, 87, 150, 176, 207, 242, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 227, 138, 51, 22, 46, 140, 150, 46, 7, 6, - 21, 69, 171, 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 252, 210, 95, 30, 18, 25, 36, 25, 9, 3, 12, 42, 65, 125, 227, 253, 254, 254, 254, 254, - 251, 198, 123, 81, 51, 22, 10, 7, 9, 30, 58, 61, 59, 71, 84, 34, 10, 7, 10, 7, 1, 0, 0, 1, - 3, 7, 11, 10, 2, 0, 0, 0, 0, 0, 0, 1, 1, 9, 43, 85, 140, 193, 210, 242, 253, 254, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 218, 112, 21, 3, 18, 69, - 38, 8, 11, 28, 49, 99, 203, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 253, 227, 139, 56, 20, 22, 34, 28, 19, 16, 24, 48, 66, 125, 223, 253, - 254, 255, 254, 254, 253, 216, 123, 48, 23, 20, 17, 9, 3, 8, 17, 17, 22, 36, 44, 15, 4, 3, - 0, 0, 1, 2, 6, 3, 0, 2, 7, 9, 4, 0, 0, 0, 0, 0, 0, 0, 0, 5, 34, 77, 119, 184, 231, 252, - 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 247, 187, - 83, 14, 3, 4, 6, 2, 5, 14, 25, 51, 123, 223, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 247, 210, 122, 61, 25, 25, 60, 109, 132, 75, 29, - 42, 123, 224, 253, 253, 254, 254, 254, 252, 223, 133, 46, 20, 30, 39, 27, 19, 12, 6, 3, 1, - 4, 4, 3, 6, 7, 5, 12, 28, 11, 3, 2, 1, 0, 3, 6, 6, 2, 0, 0, 2, 1, 1, 4, 11, 24, 65, 146, - 210, 240, 252, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, - 254, 254, 223, 122, 51, 28, 14, 9, 4, 6, 32, 54, 27, 34, 123, 230, 254, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 251, 219, 137, 73, 25, 15, 38, - 83, 115, 80, 35, 56, 138, 211, 246, 253, 253, 254, 254, 247, 193, 166, 170, 79, 18, 15, 20, - 22, 12, 11, 10, 1, 0, 0, 2, 8, 12, 19, 45, 54, 18, 2, 3, 12, 19, 20, 12, 8, 5, 1, 1, 8, 21, - 10, 9, 24, 61, 128, 217, 253, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 254, 253, 254, 253, 193, 82, 46, 51, 37, 32, 23, 24, 54, 69, 46, 72, 160, - 241, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 253, 226, 122, 60, 46, 30, 10, 7, 8, 12, 24, 43, 74, 134, 213, 250, 253, 254, 253, 221, 98, - 84, 134, 49, 5, 3, 5, 5, 3, 8, 11, 3, 0, 0, 1, 5, 10, 21, 32, 27, 24, 32, 27, 49, 84, 85, - 59, 39, 17, 4, 2, 12, 27, 14, 11, 32, 93, 163, 229, 253, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 249, 168, 67, 34, 30, 27, 30, 36, - 46, 58, 46, 61, 156, 221, 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 253, 240, 163, 138, 149, 75, 12, 1, 0, 0, 2, 7, 30, 75, 150, 232, - 253, 252, 234, 135, 51, 36, 24, 9, 0, 0, 0, 0, 0, 3, 3, 1, 0, 0, 1, 5, 12, 12, 12, 18, 28, - 51, 86, 139, 184, 195, 162, 109, 46, 15, 6, 6, 6, 9, 21, 44, 89, 160, 229, 254, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 246, 157, - 61, 12, 2, 5, 8, 24, 58, 59, 40, 59, 160, 237, 254, 253, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 249, 207, 181, 171, 110, 33, 8, 3, 1, 4, - 15, 36, 48, 90, 183, 240, 200, 115, 35, 44, 35, 7, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 15, 25, - 45, 51, 35, 42, 76, 97, 131, 207, 245, 252, 242, 194, 135, 68, 28, 14, 8, 3, 5, 18, 25, 41, - 120, 217, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 254, 254, 254, 242, 163, 74, 25, 12, 10, 15, 40, 59, 37, 32, 69, 144, 231, 253, 254, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 238, - 176, 123, 132, 66, 14, 3, 5, 22, 30, 19, 28, 81, 143, 158, 80, 34, 15, 22, 25, 10, 0, 2, 1, - 0, 0, 0, 3, 10, 30, 76, 112, 138, 153, 153, 153, 181, 220, 239, 247, 253, 254, 254, 237, - 150, 82, 46, 23, 18, 27, 23, 9, 10, 16, 38, 115, 213, 253, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 240, 152, 93, 93, 88, 51, 39, - 34, 33, 32, 51, 103, 179, 242, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 254, 254, 250, 212, 125, 98, 78, 45, 22, 14, 17, 12, 5, 15, - 58, 96, 72, 38, 27, 17, 14, 20, 12, 2, 6, 5, 4, 3, 8, 35, 76, 131, 192, 224, 237, 240, 241, - 246, 251, 253, 254, 254, 254, 254, 254, 239, 148, 73, 44, 25, 11, 11, 29, 30, 34, 43, 48, - 109, 209, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 254, 254, 253, 225, 138, 115, 156, 179, 110, 49, 18, 12, 25, 60, 123, 204, 247, 255, 254, - 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, - 253, 247, 195, 90, 86, 123, 122, 66, 12, 4, 8, 10, 12, 18, 23, 41, 48, 50, 38, 23, 14, 18, - 35, 42, 30, 30, 66, 120, 187, 225, 244, 252, 253, 253, 254, 253, 254, 254, 254, 253, 254, - 254, 253, 245, 197, 132, 66, 25, 20, 23, 29, 21, 25, 43, 53, 103, 209, 253, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 216, 156, 126, - 90, 78, 65, 24, 7, 6, 12, 38, 110, 211, 249, 254, 254, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 254, 250, 191, 128, 142, 153, - 98, 27, 11, 16, 9, 2, 0, 1, 11, 33, 68, 83, 61, 53, 93, 109, 79, 88, 162, 216, 236, 252, - 254, 254, 254, 254, 254, 253, 254, 254, 254, 254, 253, 254, 254, 253, 239, 184, 148, 67, - 14, 49, 100, 63, 15, 12, 29, 60, 125, 216, 253, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 254, 251, 206, 134, 78, 29, 11, 14, 11, 8, 9, 16, - 40, 120, 220, 251, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 254, 254, 254, 254, 254, 253, 247, 218, 163, 84, 36, 23, 23, 25, 15, 6, 3, - 3, 2, 6, 19, 41, 51, 88, 173, 167, 113, 163, 242, 253, 254, 253, 254, 254, 254, 253, 254, - 254, 254, 255, 254, 253, 254, 254, 254, 253, 233, 159, 112, 46, 18, 60, 139, 116, 41, 20, - 27, 66, 134, 213, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 253, 250, 184, 77, 30, 14, 3, 2, 10, 14, 24, 51, 85, 146, 227, 253, 254, - 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, - 254, 254, 254, 254, 254, 250, 220, 126, 43, 23, 19, 20, 30, 28, 22, 25, 18, 16, 32, 46, 54, - 86, 134, 155, 191, 240, 254, 254, 255, 255, 254, 254, 254, 254, 254, 254, 255, 255, 254, - 253, 253, 255, 254, 254, 233, 161, 92, 33, 20, 27, 56, 90, 90, 74, 63, 88, 146, 212, 253, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 247, - 157, 42, 24, 27, 11, 6, 15, 24, 46, 113, 148, 155, 223, 252, 254, 254, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, - 253, 252, 241, 187, 112, 53, 23, 37, 51, 58, 75, 71, 87, 106, 99, 107, 123, 148, 201, 244, - 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, 254, - 254, 234, 157, 75, 19, 9, 2, 3, 29, 137, 206, 157, 136, 180, 229, 254, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 241, 141, 43, 29, 28, 16, - 18, 41, 35, 37, 87, 117, 136, 219, 252, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 253, 252, 253, - 244, 210, 148, 84, 53, 48, 61, 67, 93, 100, 97, 123, 161, 203, 242, 252, 254, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, 254, 254, 234, 131, - 46, 12, 6, 1, 1, 12, 84, 143, 127, 122, 179, 239, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 237, 140, 60, 34, 18, 8, 21, 59, 51, 21, - 24, 49, 117, 223, 252, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 254, 253, 252, 253, 253, 247, - 220, 165, 112, 81, 88, 122, 134, 129, 147, 190, 234, 252, 253, 253, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, 254, 254, 236, 127, 42, 27, 22, - 8, 6, 8, 15, 28, 44, 86, 169, 238, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 253, 239, 170, 97, 45, 19, 10, 10, 22, 30, 12, 9, 30, 119, - 229, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 254, 253, 254, 254, 254, 252, 240, - 217, 206, 221, 232, 232, 236, 245, 252, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 241, 176, 119, 92, 84, 71, 53, 32, - 30, 24, 21, 53, 147, 232, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 253, 253, 235, 181, 119, 61, 35, 30, 20, 11, 20, 17, 20, 48, 125, 229, 253, - 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 253, 254, 254, 245, 217, 200, 163, 106, 89, 70, 56, 69, 65, - 51, 77, 161, 236, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 253, 227, 157, 135, 126, 93, 48, 25, 22, 42, 23, 17, 37, 110, 227, 254, 254, - 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 253, 253, 254, 242, 187, 139, 81, 28, 25, 34, 30, 35, 51, 82, 132, - 196, 242, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 254, 253, 231, 171, 163, 145, 82, 24, 11, 15, 28, 11, 6, 23, 110, 235, 254, 253, 253, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 254, 254, 254, 253, 254, 231, 152, 71, 19, 4, 7, 18, 19, 23, 30, 60, 109, 173, 238, - 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 252, - 234, 174, 110, 49, 12, 3, 5, 5, 3, 2, 8, 35, 139, 244, 254, 254, 253, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, - 254, 254, 253, 210, 117, 51, 12, 7, 11, 11, 24, 37, 33, 29, 49, 126, 230, 253, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 252, 211, 99, 28, 8, - 4, 9, 28, 32, 16, 18, 40, 69, 151, 245, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 252, - 187, 81, 38, 14, 8, 11, 9, 9, 17, 24, 29, 51, 138, 235, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 250, 201, 100, 39, 18, 17, 24, 40, 61, - 68, 72, 79, 90, 155, 244, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 252, 189, 86, 34, 9, - 9, 14, 8, 5, 9, 17, 32, 77, 167, 241, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 253, 250, 199, 120, 70, 48, 53, 49, 28, 44, 88, 99, 85, 95, - 170, 247, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, 252, 201, 106, 38, 7, 5, 8, 8, 7, 7, - 9, 30, 102, 189, 245, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 249, 198, 102, 54, 49, 56, 41, 19, 23, 46, 61, 65, 97, 189, 251, 254, 254, - 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 254, 254, 254, 254, 251, 194, 110, 68, 35, 15, 12, 14, 11, 5, 5, 29, 121, - 205, 250, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 254, 247, 204, 109, 49, 23, 12, 9, 15, 19, 20, 30, 51, 93, 189, 251, 254, 254, 254, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 254, 254, 254, 254, 251, 187, 117, 99, 63, 20, 15, 23, 20, 16, 24, 46, 107, 200, 250, - 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 247, - 211, 148, 65, 17, 3, 7, 16, 16, 12, 22, 46, 90, 189, 250, 254, 254, 254, 254, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 254, 254, 254, 251, 189, 120, 85, 44, 18, 23, 38, 33, 37, 74, 89, 93, 193, 250, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 247, 206, 158, - 73, 27, 18, 20, 18, 11, 12, 19, 44, 102, 203, 251, 254, 254, 254, 254, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, - 254, 247, 167, 86, 44, 18, 25, 44, 55, 44, 30, 58, 85, 112, 204, 251, 253, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 244, 190, 108, 61, 45, 25, - 18, 19, 14, 11, 16, 41, 115, 219, 253, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 239, - 141, 51, 16, 8, 25, 46, 48, 51, 28, 17, 46, 134, 223, 252, 253, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 244, 184, 81, 38, 25, 9, 9, 24, 28, - 17, 16, 43, 113, 215, 252, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 235, 164, 79, 21, 6, - 12, 28, 30, 38, 46, 56, 66, 120, 227, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 245, 178, 69, 30, 21, 7, 5, 12, 17, 12, 18, 53, - 123, 216, 253, 254, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 234, 174, 115, 45, 11, 12, 20, - 18, 12, 30, 92, 144, 172, 240, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 253, 237, 150, 68, 43, 23, 6, 2, 6, 7, 4, 12, 44, 99, 203, 254, - 254, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 254, 254, 252, 212, 116, 95, 78, 32, 15, 14, 12, 8, 15, 48, - 133, 227, 252, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 234, 136, 59, 33, 12, 3, 2, 10, 20, 17, 21, 36, 80, 201, 254, 254, 254, 254, - 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 254, 254, 249, 178, 56, 42, 82, 72, 16, 8, 7, 27, 48, 67, 135, 233, 253, - 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 236, 148, 59, 21, 7, 3, 4, 16, 48, 83, 92, 75, 105, 216, 253, 253, 253, 253, 254, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 253, 254, 244, 161, 39, 16, 40, 41, 8, 4, 5, 21, 37, 65, 137, 227, 253, 254, 254, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 234, 158, 73, 25, 12, - 17, 23, 21, 37, 74, 112, 115, 142, 224, 254, 253, 253, 253, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 236, - 154, 67, 28, 18, 14, 7, 8, 12, 8, 11, 44, 130, 233, 253, 254, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 230, 144, 69, 25, 19, 42, 55, 22, - 12, 9, 32, 97, 157, 219, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 220, 136, 113, 59, - 21, 22, 28, 27, 33, 24, 34, 76, 164, 246, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 232, 133, 45, 15, 12, 21, 25, 21, 27, 27, 45, - 108, 174, 230, 253, 254, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 250, 193, 90, 46, 19, 7, 12, 42, 68, - 64, 55, 61, 100, 198, 252, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 241, 160, 64, 25, 19, 18, 23, 37, 71, 76, 74, 100, 151, 227, - 253, 254, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 254, 254, 237, 148, 48, 11, 10, 11, 11, 25, 56, 59, 39, 46, - 112, 223, 254, 254, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 254, 244, 186, 112, 68, 48, 43, 56, 70, 63, 39, 33, 46, 88, 206, 254, 254, - 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 253, 204, 98, 45, 30, 30, 25, 12, 8, 18, 27, 35, 95, 186, 246, - 253, 254, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 254, 242, 198, 159, 113, 55, 23, 37, 80, 64, 23, 15, 28, 76, 201, 254, 254, 253, 253, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, - 254, 254, 254, 247, 157, 61, 46, 58, 67, 50, 25, 23, 23, 22, 55, 122, 209, 252, 253, 254, - 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 244, 191, 127, 71, 25, 6, 11, 35, 33, 18, 16, 41, 107, 217, 253, 253, 253, 254, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 254, 254, - 253, 237, 128, 51, 45, 74, 72, 37, 17, 19, 17, 12, 40, 126, 225, 254, 254, 254, 254, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 242, 171, - 84, 30, 11, 5, 7, 8, 7, 6, 15, 51, 125, 223, 253, 253, 254, 254, 254, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 254, 253, 220, 118, - 55, 46, 64, 45, 16, 8, 4, 3, 4, 43, 168, 245, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 236, 159, 92, 45, 17, 5, 7, 18, - 22, 9, 33, 74, 126, 217, 254, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 254, 252, 253, 249, 191, 90, 38, 25, 19, 14, 14, - 15, 8, 6, 15, 93, 224, 252, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 240, 173, 116, 72, 29, 6, 6, 35, 71, 42, 79, - 132, 165, 227, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 253, 253, 252, 237, 128, 30, 8, 5, 3, 5, 8, 15, 19, 25, 45, - 138, 244, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 240, 170, 86, 51, 32, 14, 4, 9, 25, 30, 59, 102, 153, 224, - 254, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 253, 253, 250, 196, 53, 5, 2, 2, 3, 5, 11, 12, 9, 23, 77, 199, 253, 253, - 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 242, 176, 95, 59, 45, 24, 5, 1, 1, 12, 25, 54, 122, 218, 253, 253, 254, 254, - 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 254, - 252, 225, 129, 25, 2, 3, 10, 9, 12, 36, 50, 21, 44, 134, 242, 254, 253, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 244, - 189, 133, 103, 64, 22, 3, 1, 3, 19, 39, 61, 122, 220, 254, 254, 254, 254, 254, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 247, 153, 55, - 40, 25, 39, 72, 51, 28, 39, 56, 71, 149, 218, 253, 254, 253, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 245, 184, 109, - 64, 28, 5, 2, 6, 18, 46, 78, 83, 108, 201, 253, 254, 253, 254, 254, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 252, 233, 110, 41, 80, 93, 65, - 65, 48, 30, 39, 67, 116, 210, 249, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 242, 172, 75, 25, 10, 4, - 4, 19, 35, 48, 61, 63, 78, 174, 250, 254, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 254, 254, 254, 254, 247, 174, 77, 49, 79, 89, 34, 16, 14, 18, 39, - 92, 150, 226, 253, 254, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 241, 157, 61, 33, 30, 23, 16, 20, 22, 15, - 20, 43, 82, 175, 247, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 254, 253, 254, 253, 253, 252, 203, 63, 23, 25, 28, 23, 17, 22, 17, 11, 22, 82, 197, 247, - 254, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 254, 239, 144, 59, 41, 38, 30, 23, 20, 14, 7, 20, 67, 128, - 199, 249, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, - 254, 253, 253, 239, 146, 38, 8, 4, 4, 9, 30, 61, 46, 22, 17, 97, 236, 253, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 254, 242, 178, 84, 24, 8, 8, 19, 25, 22, 16, 41, 84, 130, 200, 250, 253, - 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 254, 253, 246, - 181, 83, 34, 14, 6, 3, 5, 18, 32, 36, 39, 50, 170, 252, 253, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 253, 247, 211, 115, 25, 4, 3, 10, 12, 15, 46, 55, 59, 100, 199, 251, 254, 254, 254, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 252, 253, 252, 205, 73, 14, 8, 9, - 12, 16, 11, 16, 18, 30, 71, 148, 238, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 249, - 200, 100, 41, 24, 12, 2, 1, 9, 61, 51, 42, 103, 215, 252, 254, 254, 254, 254, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 254, 254, 254, 254, 253, 253, 231, 134, 48, 16, 12, 24, 35, 30, - 12, 9, 9, 19, 100, 223, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 250, 201, 102, - 60, 45, 27, 9, 6, 8, 24, 36, 49, 89, 184, 247, 253, 253, 253, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 254, 254, 253, 254, 253, 253, 244, 135, 50, 42, 23, 25, 45, 39, 14, 7, 12, 15, 41, - 180, 250, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 252, 221, 139, 72, 30, 16, 25, - 19, 7, 5, 30, 46, 51, 123, 234, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, - 253, 254, 253, 253, 221, 76, 12, 12, 12, 30, 60, 37, 5, 6, 16, 29, 123, 240, 253, 253, 253, - 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 253, 238, 175, 79, 17, 5, 22, 17, 4, 3, 16, 22, 32, - 100, 221, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 253, 253, 235, - 189, 86, 11, 5, 9, 23, 35, 18, 5, 8, 18, 87, 223, 251, 253, 254, 253, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 254, 253, 232, 161, 75, 37, 21, 5, 3, 3, 8, 6, 17, 53, 130, 221, 253, 253, - 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 239, 146, 61, 32, 17, 16, 18, - 8, 2, 3, 12, 27, 74, 201, 252, 253, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 253, 225, 131, 74, 85, 80, 24, 12, 20, 15, 10, 33, 77, 131, 216, 252, 254, 254, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 253, 253, 245, 176, 71, 15, 9, 15, 14, 12, 8, 7, 15, 40, 78, - 175, 247, 254, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 232, 129, - 56, 50, 73, 92, 72, 51, 20, 27, 48, 65, 112, 207, 250, 254, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 253, 252, 251, 174, 49, 21, 20, 19, 12, 11, 15, 29, 56, 65, 61, 144, 237, 253, - 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 244, 159, 56, 15, 12, - 37, 40, 29, 32, 60, 71, 80, 117, 198, 246, 254, 254, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 253, 251, 204, 50, 4, 12, 30, 43, 32, 16, 14, 25, 45, 37, 84, 227, 252, 253, 253, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 247, 183, 87, 34, 7, 2, 2, 4, 16, - 41, 66, 84, 110, 171, 239, 254, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 201, 73, 9, 36, - 51, 32, 23, 25, 21, 10, 9, 12, 48, 192, 253, 253, 252, 254, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 253, 251, 200, 136, 107, 46, 5, 3, 4, 6, 14, 27, 43, 73, 141, - 230, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 231, 108, 25, 50, 107, 83, 25, 8, 19, 40, - 29, 12, 36, 152, 247, 253, 253, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 254, 253, 253, 217, 142, 123, 74, 16, 11, 15, 15, 12, 11, 18, 46, 121, 216, 253, 254, - 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 254, 253, 253, 244, 174, 92, 77, 95, 80, 43, 25, 20, 22, 38, 34, 34, 136, - 238, 253, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 254, 253, 224, 103, 44, 25, 17, 17, 28, 40, 30, 18, 25, 60, 125, 205, 250, 254, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 253, 253, 252, 231, 142, 100, 117, 105, 37, 16, 30, 49, 40, 19, 7, 21, 121, 235, 253, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 254, - 230, 112, 38, 17, 16, 36, 73, 55, 21, 14, 27, 78, 143, 207, 249, 253, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 252, - 225, 123, 37, 16, 22, 30, 12, 15, 43, 50, 19, 7, 15, 102, 231, 253, 253, 254, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 241, 151, - 77, 49, 35, 45, 88, 39, 7, 8, 25, 65, 121, 184, 244, 254, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 234, 118, 34, - 17, 5, 1, 2, 5, 11, 25, 25, 11, 9, 73, 210, 252, 254, 253, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 249, 191, 140, 126, 78, - 41, 53, 38, 32, 30, 29, 44, 93, 152, 231, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, 254, 230, 127, 46, 24, 9, 2, 4, 5, 14, - 12, 8, 7, 6, 55, 192, 252, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 229, 179, 123, 82, 64, 46, 70, 95, 61, - 36, 59, 112, 148, 221, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 253, 254, 255, 255, 253, 253, 252, 216, 102, 37, 33, 14, 4, 3, 15, 33, 38, 22, 8, 2, 42, - 187, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 253, 254, 253, 240, 174, 98, 65, 45, 27, 50, 71, 43, 35, 73, 127, - 168, 224, 252, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 254, - 254, 253, 251, 213, 100, 25, 25, 35, 23, 12, 12, 25, 33, 25, 20, 22, 56, 173, 247, 253, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 253, 254, 253, 240, 164, 95, 54, 14, 6, 14, 25, 21, 23, 44, 82, 150, 224, - 252, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 253, 251, - 211, 92, 27, 17, 22, 35, 30, 21, 17, 14, 9, 7, 15, 80, 193, 249, 253, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, - 254, 253, 253, 247, 177, 90, 49, 12, 3, 7, 14, 12, 10, 16, 38, 97, 183, 242, 254, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 254, 249, 205, 86, 32, 44, 36, 17, - 12, 11, 9, 5, 2, 2, 10, 63, 187, 249, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 251, - 199, 100, 58, 38, 17, 16, 14, 7, 4, 15, 41, 68, 115, 212, 252, 254, 254, 254, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 254, 254, 254, 253, 254, 254, 254, 253, 239, 183, 100, 42, 48, 71, 46, 12, 6, 10, 18, 29, - 25, 30, 84, 197, 249, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 225, 139, 77, - 51, 30, 18, 7, 2, 5, 14, 23, 41, 80, 174, 244, 253, 253, 254, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 252, 254, 253, - 252, 253, 251, 226, 133, 53, 27, 19, 14, 14, 10, 11, 23, 42, 71, 116, 125, 139, 207, 250, - 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 244, 184, 93, 35, 29, 19, 4, 0, - 6, 12, 8, 19, 48, 123, 221, 252, 252, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 254, 252, 253, 249, 206, - 93, 15, 5, 6, 6, 10, 19, 28, 35, 48, 75, 89, 87, 148, 223, 252, 253, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 251, 214, 110, 60, 49, 25, 7, 2, 2, 5, 12, 29, 68, - 122, 196, 247, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 241, 177, 85, 17, 1, 4, 9, 12, 25, - 56, 66, 43, 40, 58, 74, 118, 212, 251, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 254, 253, 239, 170, 126, 82, 43, 25, 16, 6, 10, 44, 69, 87, 122, 178, 238, - 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, - 254, 254, 254, 254, 254, 253, 247, 218, 133, 56, 36, 18, 4, 6, 9, 9, 16, 38, 46, 24, 23, - 51, 130, 218, 251, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 254, 254, 251, 221, 166, 92, 46, 46, 56, 42, 40, 97, 85, 60, 82, 141, 211, 250, 254, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 253, - 254, 254, 240, 183, 95, 33, 17, 21, 27, 10, 4, 7, 14, 17, 17, 19, 25, 51, 117, 215, 253, - 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, - 238, 171, 100, 49, 37, 61, 71, 59, 69, 39, 28, 53, 99, 166, 240, 253, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 253, 251, 227, 137, - 51, 24, 27, 21, 12, 32, 18, 10, 25, 43, 24, 12, 34, 110, 177, 227, 252, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 246, 187, 137, - 98, 51, 27, 25, 18, 6, 5, 19, 54, 85, 129, 212, 253, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 254, 254, 253, 253, 253, 250, 227, 191, 142, 51, 11, 18, 50, 45, - 27, 30, 20, 23, 45, 32, 6, 21, 103, 219, 247, 253, 253, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 251, 213, 159, 142, 116, 61, - 30, 17, 7, 4, 9, 29, 61, 113, 198, 250, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 254, 254, 254, 253, 252, 241, 187, 110, 67, 46, 24, 12, 16, 42, 78, 51, 11, 5, 12, 16, - 14, 34, 92, 192, 247, 253, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 254, 252, 254, 237, 171, 112, 93, 66, 45, 45, 37, 12, 3, 8, - 32, 105, 205, 242, 253, 254, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 255, 254, 254, 254, - 249, 226, 174, 83, 25, 10, 10, 19, 32, 23, 15, 30, 25, 3, 1, 1, 3, 25, 116, 205, 247, 255, - 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 254, 254, 254, 253, 251, 216, 121, 58, 46, 54, 56, 29, 10, 3, 5, 27, 77, 132, 187, - 241, 252, 254, 253, 253, 254, 253, 253, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 251, 242, 227, 186, 110, 58, 42, 43, - 35, 32, 29, 34, 34, 21, 6, 3, 5, 9, 17, 54, 147, 232, 251, 253, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 254, - 253, 253, 246, 201, 146, 93, 43, 18, 8, 5, 6, 14, 30, 34, 46, 112, 187, 239, 253, 253, 253, - 254, 253, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 253, - 254, 254, 253, 253, 249, 230, 184, 125, 82, 56, 34, 32, 51, 61, 41, 33, 22, 12, 12, 11, 4, - 6, 27, 61, 117, 194, 244, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 254, 253, 253, 246, 215, - 123, 37, 9, 12, 19, 23, 16, 10, 6, 12, 37, 67, 136, 213, 242, 250, 252, 253, 253, 254, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 253, 252, 240, 216, 178, - 122, 60, 23, 12, 15, 32, 37, 21, 12, 7, 9, 10, 8, 6, 12, 22, 33, 78, 162, 227, 250, 253, - 254, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 251, 210, 108, 49, 42, 40, 61, 77, - 29, 3, 1, 2, 5, 3, 10, 51, 106, 151, 193, 235, 251, 254, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 254, 253, 247, 231, 215, 201, 141, 84, 51, 24, 7, 7, 12, 17, 24, 12, 1, 0, - 0, 2, 4, 7, 16, 56, 100, 126, 187, 242, 253, 254, 253, 253, 254, 253, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, - 254, 255, 255, 254, 253, 239, 167, 118, 110, 54, 61, 154, 139, 67, 29, 6, 1, 0, 1, 2, 5, - 11, 30, 82, 139, 200, 240, 252, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, - 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 254, 254, 254, 254, 254, 254, - 254, 254, 253, 253, 254, 254, 254, 254, 253, 252, 250, 244, 230, 211, 199, 201, 175, 100, - 72, 77, 48, 16, 4, 3, 12, 20, 12, 4, 0, 1, 3, 8, 16, 12, 7, 10, 37, 122, 203, 234, 252, - 254, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 240, - 205, 134, 51, 40, 123, 184, 164, 119, 39, 3, 1, 2, 4, 5, 3, 4, 12, 24, 55, 135, 210, 246, - 253, 253, 253, 253, 253, 254, 253, 253, 254, 254, 253, 253, 254, 253, 253, 253, 254, 254, - 253, 253, 253, 253, 253, 253, 254, 253, 253, 252, 253, 252, 250, 249, 246, 242, 233, 223, - 212, 196, 177, 161, 132, 95, 69, 75, 113, 109, 39, 17, 21, 37, 21, 2, 5, 18, 8, 1, 0, 3, - 18, 36, 56, 85, 63, 41, 56, 119, 210, 247, 253, 253, 254, 253, 254, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 250, 216, 151, 95, 63, 65, 82, 83, - 40, 9, 7, 10, 12, 17, 14, 12, 17, 23, 36, 75, 153, 229, 252, 253, 253, 253, 254, 254, 253, - 253, 253, 254, 253, 254, 254, 253, 253, 253, 253, 252, 251, 252, 251, 247, 245, 242, 238, - 226, 210, 210, 212, 203, 191, 184, 167, 134, 105, 82, 66, 55, 41, 29, 19, 14, 14, 19, 37, - 46, 22, 11, 16, 58, 45, 5, 3, 4, 1, 1, 1, 16, 48, 56, 54, 70, 93, 136, 192, 235, 252, 253, - 253, 254, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, - 253, 252, 254, 253, 247, 221, 143, 61, 30, 27, 18, 11, 14, 16, 17, 29, 30, 39, 72, 85, 88, - 127, 204, 247, 253, 253, 252, 254, 253, 251, 249, 247, 245, 235, 227, 224, 217, 212, 214, - 215, 197, 172, 172, 203, 194, 143, 116, 148, 170, 129, 77, 75, 85, 70, 50, 46, 34, 18, 12, - 9, 7, 14, 25, 11, 2, 5, 7, 3, 1, 1, 1, 1, 1, 9, 9, 3, 2, 7, 6, 4, 16, 45, 75, 85, 100, 137, - 194, 240, 253, 254, 253, 253, 253, 254, 254, 253, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 254, 254, 254, 253, 253, 253, 253, 249, 196, 88, 49, 46, 36, 30, - 39, 34, 45, 66, 88, 121, 154, 169, 217, 247, 245, 230, 217, 211, 216, 225, 196, 168, 165, - 161, 120, 88, 75, 83, 116, 161, 138, 65, 50, 65, 95, 84, 43, 23, 51, 110, 113, 73, 43, 33, - 29, 19, 7, 2, 2, 30, 61, 51, 33, 25, 20, 7, 2, 1, 1, 0, 0, 0, 0, 0, 0, 8, 36, 56, 71, 58, - 38, 61, 100, 132, 177, 221, 242, 253, 254, 254, 254, 253, 254, 254, 254, 254, 253, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, 254, 254, 253, 253, - 251, 218, 121, 74, 77, 93, 90, 72, 76, 85, 105, 134, 147, 148, 183, 198, 195, 211, 207, - 160, 100, 77, 93, 123, 108, 97, 93, 74, 41, 17, 14, 59, 105, 115, 79, 33, 43, 67, 46, 23, - 12, 9, 14, 40, 63, 74, 43, 18, 24, 34, 4, 3, 17, 75, 107, 70, 23, 4, 5, 7, 1, 0, 0, 0, 1, - 3, 4, 7, 18, 49, 103, 110, 80, 59, 56, 102, 160, 205, 241, 253, 253, 254, 254, 254, 254, - 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 253, 253, 237, 138, 45, 42, 44, 39, 39, 39, 56, 98, 143, 181, 162, - 113, 146, 143, 75, 79, 117, 113, 56, 20, 17, 22, 24, 36, 42, 34, 22, 7, 9, 44, 51, 25, 23, - 48, 45, 39, 16, 4, 5, 11, 15, 10, 11, 23, 19, 9, 24, 56, 16, 17, 64, 51, 19, 8, 1, 0, 1, 5, - 4, 2, 2, 5, 19, 28, 33, 58, 79, 81, 90, 93, 74, 80, 129, 198, 237, 251, 254, 254, 254, 253, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 253, 242, 157, 48, 14, 15, 15, 10, 5, 2, 5, 17, 51, - 88, 73, 33, 40, 46, 15, 9, 14, 20, 18, 7, 3, 1, 0, 1, 8, 30, 32, 12, 3, 2, 2, 0, 3, 12, 3, - 0, 0, 0, 7, 34, 36, 8, 4, 8, 12, 12, 17, 41, 37, 25, 51, 19, 3, 2, 2, 0, 2, 10, 45, 80, 66, - 46, 61, 63, 63, 89, 102, 93, 107, 162, 199, 223, 247, 253, 251, 252, 253, 254, 254, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 252, 184, 68, 18, 10, 8, 8, 7, 8, 2, 3, 2, 2, 3, 3, - 1, 2, 9, 8, 11, 7, 1, 2, 2, 3, 6, 12, 6, 2, 4, 7, 8, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 5, 17, - 12, 3, 3, 12, 37, 36, 18, 15, 30, 22, 19, 12, 8, 8, 8, 7, 16, 50, 150, 201, 148, 108, 130, - 131, 133, 159, 191, 213, 233, 249, 252, 253, 254, 253, 253, 253, 253, 254, 254, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 254, 254, 254, 254, 217, 79, 19, 11, 10, 7, 4, 3, 2, 1, 2, 1, 0, 0, 0, 0, 0, - 0, 1, 7, 12, 11, 4, 7, 16, 22, 45, 20, 1, 0, 1, 4, 4, 1, 0, 0, 1, 1, 3, 4, 3, 7, 9, 8, 4, - 5, 7, 14, 44, 51, 34, 27, 43, 50, 45, 35, 27, 25, 39, 61, 87, 137, 203, 215, 190, 187, 217, - 231, 239, 246, 251, 253, 254, 254, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 254, 253, 254, 244, 110, 8, 1, 3, 5, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 15, 34, 25, 16, 20, 12, 15, 12, 15, 20, 14, 7, 6, 14, 28, 19, 8, 21, 35, 19, 24, 41, - 37, 28, 36, 46, 43, 38, 46, 66, 80, 96, 117, 131, 133, 143, 156, 164, 181, 205, 223, 239, - 247, 249, 250, 251, 253, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 251, 187, 34, 3, 2, 2, 3, 2, 0, 0, 0, 1, - 4, 4, 4, 4, 4, 4, 6, 5, 3, 6, 19, 46, 46, 27, 22, 15, 20, 38, 80, 115, 80, 41, 44, 93, 146, - 138, 117, 127, 128, 115, 123, 141, 149, 155, 167, 183, 190, 187, 192, 205, 218, 227, 236, - 242, 247, 249, 252, 254, 254, 254, 253, 253, 253, 253, 253, 253, 254, 254, 254, 254, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 254, - 252, 227, 110, 22, 8, 9, 9, 9, 5, 1, 1, 3, 5, 7, 18, 28, 32, 35, 39, 32, 21, 19, 24, 42, - 61, 63, 61, 73, 70, 79, 103, 145, 176, 160, 151, 168, 207, 233, 235, 233, 236, 236, 239, - 240, 244, 246, 247, 249, 251, 252, 252, 252, 252, 254, 254, 254, 254, 254, 253, 254, 254, - 254, 254, 254, 253, 253, 253, 253, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 246, 160, 63, 46, 27, 25, - 34, 42, 28, 10, 2, 7, 22, 30, 56, 93, 109, 113, 122, 122, 108, 110, 120, 131, 141, 153, - 173, 200, 209, 215, 221, 233, 241, 242, 246, 251, 252, 252, 254, 253, 252, 253, 253, 254, - 254, 253, 253, 254, 254, 254, 254, 253, 253, 254, 254, 254, 254, 254, 253, 253, 254, 255, - 254, 254, 254, 253, 253, 253, 254, 254, 254, 255, 254, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 254, 254, 253, 254, 254, 253, 205, 89, 81, 123, 85, 54, 48, - 50, 45, 30, 18, 54, 146, 179, 196, 215, 224, 226, 232, 239, 239, 242, 246, 247, 249, 252, - 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, 254, 254, 254, 255, - 254, 254, 254, 254, 254, 254, 254, 255, 255, 254, 254, 255, 254, 254, 254, 254, 254, 255, - 254, 254, 255, 255, 255, 254, 254, 255, 255, 255, 254, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 253, 253, 253, 253, 253, 241, 150, 113, 113, 67, 32, 35, 36, - 30, 42, 53, 60, 153, 242, 253, 253, 254, 253, 254, 254, 254, 254, 254, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 252, 254, 253, 253, 252, 209, 118, 119, 88, 25, 19, 56, 54, - 29, 37, 51, 102, 223, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 254, 253, 253, 253, 227, 120, 53, 41, 36, 48, 69, 105, 78, - 32, 27, 56, 175, 251, 254, 254, 254, 254, 254, 253, 254, 254, 254, 254, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 254, 254, - 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 254, 254, 255, 254, 254, 254, 254, 254, - 254, 255, 254, 254, 254, 254, 254, 253, 253, 242, 145, 30, 8, 4, 14, 53, 60, 34, 30, 20, - 24, 110, 238, 253, 254, 254, 254, 254, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 254, 254, 253, 253, 254, 253, - 253, 253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 253, 254, 253, 253, 253, 253, 254, - 254, 254, 253, 253, 254, 254, 253, 254, 252, 207, 112, 46, 14, 6, 5, 6, 8, 4, 10, 18, 50, - 181, 252, 253, 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 252, 253, 253, 254, 253, 254, 253, 252, 253, - 252, 253, 254, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, - 253, 253, 252, 253, 254, 252, 253, 235, 128, 98, 44, 9, 10, 18, 18, 14, 22, 51, 90, 152, - 239, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 254, 253, 254, 254, 251, 244, 225, 200, - 190, 198, 211, 215, 213, 216, 213, 207, 204, 204, 200, 197, 201, 223, 238, 211, 195, 204, - 207, 197, 189, 193, 196, 190, 174, 99, 21, 21, 16, 23, 42, 74, 93, 72, 77, 96, 153, 232, - 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 253, 242, 214, 179, 148, 108, 83, - 72, 76, 88, 97, 95, 102, 103, 93, 79, 64, 56, 69, 89, 98, 135, 127, 73, 43, 51, 69, 74, 69, - 51, 30, 16, 4, 1, 1, 4, 29, 46, 65, 88, 61, 51, 71, 187, 251, 254, 254, 254, 254, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, - 254, 254, 254, 252, 249, 225, 166, 100, 79, 86, 72, 59, 44, 39, 49, 59, 42, 39, 43, 48, 40, - 30, 25, 41, 53, 21, 23, 56, 48, 22, 16, 28, 35, 30, 17, 5, 2, 8, 10, 2, 1, 6, 11, 12, 15, - 12, 27, 120, 237, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 254, 252, 231, 183, 139, 95, - 64, 78, 109, 90, 46, 21, 23, 32, 30, 18, 23, 25, 25, 24, 30, 29, 14, 11, 2, 0, 3, 16, 33, - 19, 4, 2, 2, 3, 2, 6, 21, 23, 12, 3, 0, 0, 0, 0, 3, 56, 206, 253, 254, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 253, 254, 253, 249, 201, 110, 63, 71, 75, 76, 97, 100, 71, 37, 20, 19, 14, 2, 12, 53, 36, - 12, 11, 27, 38, 16, 14, 9, 2, 0, 2, 8, 5, 0, 1, 2, 2, 4, 9, 9, 6, 11, 8, 11, 19, 17, 11, - 39, 160, 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 244, 199, 117, 49, 35, 61, 67, 44, - 25, 12, 7, 22, 30, 21, 8, 1, 7, 33, 10, 0, 1, 6, 18, 32, 49, 41, 11, 2, 1, 2, 2, 6, 15, 28, - 29, 18, 10, 5, 6, 9, 20, 37, 64, 83, 95, 164, 239, 253, 253, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 254, 254, 255, 255, 254, 254, 255, 255, 255, 254, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 253, - 246, 183, 80, 46, 48, 59, 35, 16, 7, 3, 2, 6, 14, 23, 25, 12, 1, 1, 3, 3, 2, 4, 5, 11, 25, - 46, 48, 19, 6, 6, 14, 16, 18, 37, 90, 96, 44, 16, 11, 18, 34, 55, 61, 74, 110, 173, 238, - 252, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, - 254, 254, 254, 254, 254, 254, 254, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 254, 253, 254, 254, 253, 242, 176, 69, 18, 44, 50, 25, 5, 2, 1, 1, 2, 9, 10, - 27, 54, 39, 12, 11, 14, 25, 51, 76, 83, 85, 110, 136, 84, 39, 39, 56, 71, 61, 44, 58, 110, - 107, 69, 61, 65, 48, 53, 76, 103, 130, 177, 239, 254, 254, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 252, 253, 253, 254, - 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 254, 254, 254, - 247, 162, 54, 17, 30, 67, 38, 11, 5, 7, 7, 3, 4, 16, 35, 81, 145, 167, 154, 145, 144, 162, - 186, 184, 179, 184, 194, 198, 166, 152, 170, 184, 190, 190, 170, 155, 169, 172, 160, 155, - 154, 152, 156, 171, 194, 227, 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 252, 253, 253, 253, 253, 253, - 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 253, 252, 213, 80, - 21, 22, 37, 25, 19, 19, 24, 33, 25, 15, 30, 64, 113, 177, 223, 242, 247, 247, 247, 249, - 250, 247, 245, 246, 247, 247, 245, 246, 247, 249, 249, 250, 249, 244, 246, 247, 246, 244, - 242, 246, 247, 247, 251, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 252, 247, 233, 240, 247, 252, 254, 253, - 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 252, 253, 231, 120, 37, - 20, 25, 25, 10, 25, 39, 53, 53, 51, 88, 135, 174, 220, 246, 253, 253, 254, 254, 253, 253, - 253, 254, 254, 253, 254, 253, 254, 254, 253, 253, 253, 253, 253, 254, 254, 253, 254, 254, - 254, 253, 254, 253, 253, 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 242, 206, 165, 184, 205, 221, 238, 247, - 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 252, 242, 149, 33, 12, 12, - 17, 21, 27, 28, 36, 44, 36, 69, 196, 242, 249, 254, 254, 254, 254, 254, 254, 254, 254, 253, - 254, 254, 253, 254, 253, 253, 254, 254, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, - 254, 254, 253, 254, 254, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 254, 254, 247, 213, 153, 107, 123, 151, 171, 200, 227, 249, - 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 218, 106, 50, 33, 18, 17, - 34, 30, 14, 11, 21, 42, 132, 238, 252, 253, 254, 254, 254, 254, 254, 254, 255, 255, 254, - 254, 254, 254, 255, 254, 254, 254, 254, 254, 255, 255, 254, 254, 255, 255, 255, 254, 254, - 254, 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 254, 253, 235, 192, 142, 93, 90, 115, 142, 171, 203, 236, - 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 251, 203, 106, 60, 48, 32, 19, - 23, 27, 23, 14, 38, 97, 198, 252, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 254, 253, 230, 178, 137, 100, 79, 82, 107, 132, 160, 203, - 246, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 246, 175, 80, 22, 21, 27, 18, - 11, 24, 40, 46, 58, 113, 216, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 254, 253, 234, 170, 116, 93, 65, 45, 56, 92, 143, 191, 234, - 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 239, 160, 85, 32, 12, 12, 18, 22, - 35, 51, 56, 65, 140, 234, 253, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 253, 253, 245, 199, 135, 80, 44, 28, 36, 65, 103, 146, 195, 244, - 254, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 230, 157, 100, 71, 34, 19, 25, 29, 30, - 50, 48, 72, 164, 242, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 254, 253, 254, 251, 220, 143, 56, 27, 25, 34, 44, 56, 85, 143, 225, 252, - 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 253, 232, 164, 102, 84, 72, 54, 37, 29, 28, 33, 37, - 84, 181, 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 253, 254, 247, 197, 113, 51, 35, 36, 28, 25, 41, 70, 118, 203, 247, 254, - 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 254, 254, 244, 200, 128, 82, 103, 100, 56, 46, 55, 18, 22, - 89, 194, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 253, 254, 245, 176, 103, 74, 61, 44, 18, 14, 42, 81, 117, 181, 239, 253, - 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 247, 221, 162, 103, 107, 113, 75, 53, 54, 20, 28, - 79, 190, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 253, 254, 249, 192, 113, 63, 37, 24, 16, 15, 32, 56, 79, 138, 215, 250, 253, - 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 253, 223, 164, 129, 113, 107, 90, 51, 20, 25, 51, 58, 79, - 187, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 253, 254, 253, 234, 172, 78, 33, 35, 35, 23, 28, 30, 36, 82, 179, 241, 253, 253, - 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 250, 193, 105, 76, 84, 73, 41, 17, 17, 63, 86, 59, 93, 201, 252, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 254, 254, 253, 246, 200, 112, 59, 49, 56, 84, 85, 50, 30, 50, 112, 196, 250, 254, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 244, 159, 70, 25, 14, 18, 17, 12, 16, 45, 45, 58, 121, 218, 253, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, - 253, 241, 184, 130, 87, 46, 38, 73, 74, 45, 41, 65, 88, 157, 242, 254, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 254, 236, 137, 60, 14, 2, 5, 10, 10, 21, 32, 25, 73, 169, 238, 254, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 247, - 193, 122, 93, 69, 34, 28, 30, 30, 46, 76, 103, 166, 239, 254, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 231, - 135, 68, 25, 10, 14, 15, 17, 41, 68, 54, 105, 198, 247, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 252, 224, 150, - 103, 88, 46, 29, 32, 48, 70, 92, 126, 196, 245, 253, 254, 254, 254, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 227, 134, - 89, 73, 42, 24, 23, 29, 46, 73, 79, 127, 201, 247, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 247, 214, 134, - 69, 54, 44, 46, 72, 129, 162, 148, 180, 221, 250, 254, 254, 253, 253, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 254, 253, 216, 107, 83, - 103, 64, 22, 15, 18, 16, 20, 49, 122, 207, 251, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 247, 201, 128, - 84, 60, 29, 22, 44, 108, 146, 120, 125, 181, 241, 253, 254, 253, 253, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 254, 252, 207, 90, 40, 29, - 23, 19, 12, 7, 5, 20, 64, 143, 231, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 249, 181, 109, 100, 60, - 15, 7, 20, 55, 81, 84, 86, 144, 225, 252, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 253, 254, 254, 251, 212, 103, 30, 14, 12, 12, 11, - 11, 19, 70, 143, 183, 242, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 251, 191, 92, 59, 32, 12, 9, 10, 20, - 56, 85, 71, 102, 184, 242, 254, 254, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 253, 254, 254, 242, 159, 72, 32, 22, 16, 15, 23, 30, 33, 82, 161, - 191, 242, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 254, 253, 215, 113, 53, 24, 22, 22, 12, 6, 25, 56, 46, - 65, 138, 226, 253, 254, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 253, 253, 253, 230, 117, 39, 29, 23, 14, 24, 33, 25, 14, 25, 82, 163, 242, - 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 254, 232, 156, 95, 41, 22, 18, 9, 5, 7, 18, 24, 43, 105, 203, - 251, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 253, 253, 252, 225, 110, 33, 22, 16, 12, 28, 39, 30, 25, 25, 64, 166, 247, 253, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 254, 244, 190, 138, 71, 32, 18, 15, 12, 6, 5, 18, 50, 92, 179, 247, 254, - 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 254, - 251, 216, 108, 32, 12, 12, 28, 39, 40, 50, 56, 53, 81, 200, 252, 253, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 254, 254, 250, 198, 135, 103, 84, 63, 50, 40, 20, 12, 37, 86, 108, 158, 231, 254, 253, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 247, 192, - 98, 41, 12, 17, 72, 66, 29, 25, 39, 64, 120, 233, 253, 254, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, - 252, 214, 149, 128, 116, 88, 66, 49, 32, 39, 71, 98, 93, 119, 205, 253, 254, 254, 254, 254, - 254, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 253, 253, 249, 209, 134, 103, 86, - 40, 33, 59, 43, 20, 17, 32, 100, 196, 250, 253, 253, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, - 235, 189, 133, 73, 46, 44, 35, 22, 28, 46, 61, 65, 93, 180, 249, 253, 253, 254, 254, 254, - 254, 254, 254, 254, 254, 253, 254, 253, 253, 254, 253, 246, 187, 83, 43, 73, 116, 98, 67, - 34, 25, 49, 79, 79, 163, 240, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 240, 178, - 113, 51, 30, 32, 39, 24, 8, 7, 27, 74, 120, 178, 242, 252, 252, 252, 252, 251, 250, 249, - 247, 247, 247, 247, 247, 247, 247, 244, 223, 169, 76, 20, 12, 12, 30, 86, 131, 97, 78, 60, - 55, 122, 226, 253, 254, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 247, 190, 110, 64, - 44, 34, 37, 50, 36, 14, 25, 86, 160, 174, 167, 172, 178, 187, 209, 207, 180, 156, 137, 128, - 142, 168, 183, 183, 174, 159, 120, 61, 25, 20, 12, 3, 7, 35, 61, 72, 122, 82, 50, 177, 250, - 253, 254, 254, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 251, 219, 144, 109, 99, 65, 39, 77, - 97, 41, 30, 53, 109, 138, 121, 109, 89, 81, 99, 96, 73, 53, 41, 34, 48, 90, 99, 72, 51, 46, - 33, 19, 15, 12, 8, 6, 12, 20, 12, 14, 56, 90, 148, 239, 253, 253, 253, 254, 253, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 254, 254, 253, 253, 237, 170, 150, 161, 110, 49, 48, 50, 16, 8, 12, 23, 42, 69, - 63, 33, 14, 10, 12, 16, 15, 11, 10, 12, 30, 25, 8, 2, 2, 3, 7, 10, 5, 4, 12, 25, 20, 15, - 16, 35, 121, 227, 252, 253, 254, 254, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, - 244, 183, 145, 135, 85, 33, 12, 3, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 2, 3, 2, 1, 2, 2, 3, 1, - 0, 0, 0, 4, 5, 5, 14, 24, 20, 19, 54, 79, 117, 209, 251, 254, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 254, 253, 254, 251, 219, 146, 80, 34, 12, 6, 2, 3, 5, 5, 4, 2, 1, 2, 2, - 3, 4, 3, 1, 0, 2, 2, 1, 0, 0, 0, 1, 2, 2, 2, 6, 12, 20, 21, 15, 32, 90, 164, 227, 251, 253, - 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, 254, 250, 220, 146, - 76, 32, 12, 4, 2, 4, 6, 7, 4, 3, 9, 21, 25, 23, 9, 3, 4, 8, 10, 6, 5, 4, 5, 17, 30, 22, 15, - 14, 17, 21, 29, 61, 113, 175, 234, 252, 253, 253, 253, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 254, 254, 253, 242, 220, 175, 103, 51, 20, 8, 6, 4, 3, 3, 12, - 41, 67, 49, 25, 17, 16, 12, 15, 25, 24, 19, 25, 59, 97, 73, 51, 56, 69, 68, 79, 144, 211, - 245, 253, 253, 253, 254, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 254, 254, 254, 254, 253, 254, 254, 247, 218, 169, 103, 64, 51, 48, 43, 41, 49, 56, 46, 40, - 49, 58, 40, 43, 61, 51, 43, 54, 86, 100, 79, 82, 112, 134, 152, 190, 235, 252, 254, 254, - 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 254, 253, 250, 242, 219, 200, 189, 176, 164, 157, 157, 158, 164, - 175, 186, 181, 177, 179, 175, 175, 184, 194, 195, 189, 199, 219, 233, 244, 251, 253, 253, - 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 253, 253, 253, 252, 250, 247, 247, 247, - 247, 249, 251, 251, 252, 251, 250, 250, 251, 251, 253, 252, 251, 253, 253, 253, 253, 253, - 253, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 253, 254, 254, 254, 253, - 253, 253, 254, 253, 253, 253, 253, 253, 252, 253, 253, 254, 254, 254, 253, 254, 253, 253, - 254, 252, 254, 254, 254, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 254, - 254, 255, 255, 254, 254, 254, 253, 254, 254, 254, 253, 254, 254, 254, 253, 253, 254, 254, - 254, 254, 254, 254, 253, 254, 254, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, 254, - 254, 254, 254, 255, 255, 254, 254, 254, 254, 255, 255, 254, 254, 254, 254, 254, 254, 254, - 254, 254, 255, 255, 254, 254, 254, 254, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255,] \ No newline at end of file diff --git a/ableos/assets/img_array/output.in b/ableos/assets/img_array/output.in deleted file mode 100644 index eed7185..0000000 --- a/ableos/assets/img_array/output.in +++ /dev/null @@ -1 +0,0 @@ -[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 81, 83, 88, 89, 89, 91, 92, 94, 98, 103, 104, 106, 107, 108, 111, 112, 115, 116, 116, 117, 116, 116, 115, 116, 114, 113, 114, 115, 112, 108, 111, 118, 121, 124, 126, 127, 127, 128, 128, 127, 126, 125, 126, 132, 135, 137, 137, 136, 134, 130, 128, 128, 128, 128, 129, 129, 128, 130, 150, 158, 158, 159, 160, 160, 162, 164, 167, 170, 173, 180, 186, 184, 174, 154, 140, 138, 136, 135, 135, 135, 135, 135, 135, 135, 135, 133, 130, 129, 130, 133, 137, 142, 143, 144, 143, 143, 142, 139, 136, 132, 131, 132, 133, 135, 139, 146, 154, 166, 179, 186, 188, 189, 189, 188, 188, 189, 190, 192, 192, 192, 194, 197, 198, 198, 198, 198, 198, 198, 200, 201, 203, 205, 206, 207, 206, 204, 201, 200, 202, 205, 209, 212, 214, 213, 211, 209, 207, 205, 204, 201, 200, 203, 207, 209, 211, 214, 216, 218, 220, 222, 224, 225, 225, 226, 225, 224, 222, 220, 217, 215, 213, 213, 213, 212, 211, 211, 211, 212, 212, 211, 213, 217, 218, 218, 219, 221, 223, 225, 226, 227, 227, 228, 228, 228, 229, 231, 234, 237, 239, 239, 238, 236, 233, 230, 227, 226, 224, 225, 227, 229, 229, 232, 236, 238, 239, 239, 238, 238, 238, 238, 237, 237, 237, 237, 238, 238, 238, 238, 238, 238, 238, 239, 240, 241, 242, 241, 239, 238, 239, 240, 240, 239, 239, 239, 241, 243, 245, 246, 247, 247, 248, 248, 248, 247, 244, 243, 244, 246, 246, 246, 246, 245, 244, 242, 241, 239, 238, 235, 235, 238, 239, 239, 240, 241, 243, 245, 247, 247, 248, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 83, 85, 86, 87, 88, 89, 92, 94, 99, 102, 103, 104, 106, 106, 107, 109, 110, 111, 112, 113, 114, 114, 115, 114, 113, 111, 112, 107, 105, 110, 116, 119, 122, 124, 124, 125, 124, 124, 125, 125, 124, 123, 127, 133, 134, 134, 135, 133, 130, 126, 125, 125, 126, 126, 127, 126, 114, 126, 156, 157, 157, 158, 159, 159, 161, 163, 165, 167, 170, 177, 185, 196, 212, 235, 223, 169, 138, 135, 134, 135, 135, 134, 134, 133, 131, 128, 128, 128, 130, 134, 138, 141, 142, 142, 141, 141, 139, 137, 135, 133, 133, 134, 133, 131, 133, 136, 141, 151, 163, 176, 180, 181, 181, 181, 182, 182, 184, 186, 188, 190, 191, 191, 191, 191, 191, 191, 192, 193, 194, 195, 197, 198, 199, 200, 199, 197, 195, 193, 194, 198, 202, 206, 208, 207, 205, 204, 202, 200, 199, 198, 198, 200, 202, 203, 206, 209, 211, 213, 215, 216, 217, 219, 220, 221, 220, 218, 217, 214, 211, 209, 207, 207, 206, 205, 206, 205, 206, 207, 209, 210, 212, 213, 214, 215, 216, 218, 220, 222, 223, 224, 225, 225, 226, 227, 228, 230, 231, 232, 233, 233, 232, 231, 229, 227, 224, 222, 223, 225, 226, 228, 229, 232, 235, 237, 238, 238, 238, 238, 238, 237, 236, 235, 234, 234, 234, 235, 235, 236, 236, 237, 237, 237, 238, 240, 240, 241, 241, 241, 239, 238, 238, 238, 237, 237, 238, 238, 240, 243, 245, 246, 246, 246, 247, 247, 247, 247, 247, 246, 246, 246, 245, 244, 241, 240, 238, 237, 237, 237, 237, 237, 237, 238, 238, 239, 240, 242, 244, 247, 247, 247, 247, 246, 246, 246, 246, 246, 246, 246, 246, 246, 84, 85, 85, 86, 89, 93, 97, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 111, 112, 112, 113, 111, 109, 104, 103, 109, 114, 117, 120, 121, 122, 122, 122, 120, 121, 122, 123, 122, 122, 128, 131, 132, 132, 132, 129, 125, 122, 122, 122, 122, 123, 122, 115, 113, 137, 157, 156, 156, 157, 157, 158, 161, 162, 163, 164, 167, 174, 183, 196, 219, 239, 245, 246, 231, 187, 142, 135, 134, 133, 133, 130, 127, 126, 127, 130, 132, 134, 137, 140, 142, 142, 142, 141, 138, 137, 134, 133, 133, 134, 135, 135, 134, 135, 138, 144, 155, 167, 175, 177, 179, 181, 182, 183, 184, 187, 188, 190, 190, 189, 189, 189, 190, 191, 192, 193, 195, 195, 196, 197, 198, 198, 196, 195, 193, 193, 195, 198, 201, 204, 205, 204, 203, 203, 201, 200, 199, 198, 199, 200, 202, 204, 206, 209, 211, 212, 213, 214, 215, 216, 218, 218, 217, 216, 214, 211, 209, 207, 206, 205, 205, 204, 205, 205, 206, 206, 209, 211, 212, 213, 214, 215, 217, 219, 221, 224, 225, 226, 226, 227, 227, 229, 230, 231, 231, 230, 230, 230, 228, 227, 225, 224, 222, 221, 223, 225, 225, 227, 228, 230, 233, 236, 238, 239, 240, 240, 239, 238, 238, 236, 235, 234, 233, 234, 235, 235, 236, 236, 236, 237, 238, 240, 240, 241, 242, 242, 240, 238, 237, 237, 237, 237, 237, 237, 238, 239, 242, 244, 246, 246, 246, 246, 247, 247, 247, 247, 247, 246, 245, 242, 240, 238, 237, 236, 236, 236, 237, 237, 237, 237, 238, 238, 239, 241, 243, 244, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 84, 85, 86, 90, 94, 97, 100, 100, 101, 102, 103, 104, 105, 106, 106, 106, 108, 109, 110, 110, 111, 111, 108, 100, 101, 109, 112, 116, 118, 119, 120, 120, 119, 116, 117, 120, 120, 120, 119, 124, 129, 130, 130, 130, 128, 124, 120, 119, 119, 120, 120, 117, 107, 115, 119, 147, 157, 156, 156, 156, 156, 157, 159, 160, 161, 162, 165, 171, 180, 193, 228, 242, 247, 246, 247, 246, 241, 206, 154, 135, 131, 125, 123, 125, 129, 131, 132, 133, 137, 140, 142, 142, 142, 141, 139, 136, 134, 132, 132, 134, 135, 135, 133, 135, 138, 144, 152, 162, 170, 173, 175, 179, 182, 184, 186, 188, 189, 189, 188, 188, 188, 188, 190, 191, 192, 194, 195, 196, 196, 196, 196, 195, 194, 193, 192, 193, 195, 198, 200, 202, 202, 201, 201, 201, 201, 200, 200, 199, 199, 200, 202, 205, 207, 209, 211, 212, 213, 213, 213, 213, 214, 214, 213, 212, 210, 208, 207, 206, 205, 204, 203, 203, 204, 205, 206, 207, 208, 210, 211, 213, 215, 217, 219, 221, 222, 224, 226, 226, 227, 227, 228, 229, 229, 229, 229, 228, 227, 226, 224, 222, 222, 221, 221, 221, 223, 224, 226, 226, 228, 229, 231, 235, 238, 239, 240, 240, 241, 241, 240, 239, 238, 236, 234, 233, 233, 234, 234, 235, 236, 237, 238, 240, 241, 242, 242, 242, 241, 239, 238, 237, 237, 237, 237, 237, 237, 237, 239, 242, 244, 246, 246, 246, 246, 246, 247, 247, 247, 245, 243, 242, 240, 238, 237, 236, 236, 237, 237, 237, 237, 237, 237, 238, 239, 240, 242, 243, 245, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 245, 84, 88, 92, 94, 95, 97, 99, 100, 101, 101, 103, 103, 104, 105, 106, 106, 106, 107, 108, 108, 105, 98, 98, 106, 110, 114, 116, 117, 118, 117, 115, 113, 113, 117, 118, 118, 117, 118, 125, 127, 128, 128, 128, 124, 118, 116, 116, 116, 117, 113, 108, 109, 99, 118, 152, 156, 155, 155, 155, 155, 156, 156, 158, 161, 161, 163, 167, 176, 187, 224, 245, 246, 247, 247, 247, 247, 247, 245, 220, 163, 127, 126, 128, 130, 130, 130, 132, 136, 140, 141, 142, 142, 141, 140, 137, 134, 131, 131, 133, 135, 134, 132, 132, 135, 141, 149, 159, 170, 173, 174, 177, 181, 184, 187, 188, 187, 187, 187, 187, 187, 188, 190, 191, 193, 194, 194, 195, 195, 195, 194, 193, 192, 191, 191, 192, 195, 197, 200, 200, 200, 200, 200, 200, 200, 201, 200, 200, 199, 200, 202, 205, 207, 209, 211, 212, 212, 211, 211, 211, 211, 211, 210, 209, 208, 206, 205, 204, 203, 201, 200, 202, 202, 204, 205, 207, 208, 210, 212, 213, 215, 217, 220, 222, 224, 226, 226, 226, 227, 228, 228, 227, 228, 227, 226, 226, 225, 223, 222, 221, 221, 220, 220, 221, 222, 224, 225, 226, 228, 229, 231, 234, 237, 238, 240, 240, 241, 241, 241, 241, 240, 238, 236, 234, 233, 233, 233, 233, 234, 236, 237, 239, 241, 242, 243, 242, 242, 240, 239, 237, 237, 237, 237, 237, 237, 237, 238, 240, 243, 244, 246, 246, 246, 246, 246, 246, 245, 244, 242, 240, 238, 237, 236, 236, 236, 237, 237, 237, 237, 237, 237, 238, 239, 240, 241, 243, 244, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 245, 243, 87, 91, 93, 94, 96, 97, 98, 99, 100, 101, 102, 103, 103, 103, 104, 104, 104, 105, 100, 95, 96, 103, 107, 111, 113, 114, 115, 114, 112, 110, 110, 114, 116, 117, 116, 114, 119, 124, 126, 127, 126, 124, 119, 115, 114, 114, 114, 108, 105, 110, 115, 115, 129, 155, 155, 154, 154, 153, 154, 154, 155, 155, 158, 160, 162, 164, 171, 182, 203, 239, 246, 246, 247, 247, 247, 247, 247, 247, 246, 228, 175, 136, 128, 127, 127, 129, 134, 139, 141, 141, 141, 141, 140, 138, 135, 131, 130, 132, 135, 133, 131, 130, 132, 137, 144, 154, 166, 175, 178, 179, 182, 185, 186, 186, 185, 185, 185, 186, 187, 188, 190, 192, 193, 194, 193, 193, 193, 193, 192, 191, 190, 189, 190, 192, 194, 196, 198, 199, 199, 199, 199, 199, 200, 201, 200, 200, 200, 201, 203, 206, 207, 209, 211, 211, 211, 211, 210, 209, 208, 208, 207, 207, 205, 204, 203, 202, 200, 199, 199, 198, 199, 202, 205, 207, 208, 210, 212, 214, 216, 218, 221, 223, 225, 226, 227, 228, 228, 227, 227, 227, 226, 224, 223, 222, 221, 221, 220, 220, 220, 220, 221, 221, 222, 223, 224, 226, 228, 229, 231, 233, 236, 239, 239, 240, 241, 241, 241, 241, 241, 240, 238, 237, 235, 234, 233, 233, 234, 235, 238, 239, 240, 242, 242, 242, 242, 241, 239, 237, 237, 236, 237, 237, 237, 237, 237, 239, 241, 243, 245, 246, 246, 246, 246, 245, 244, 243, 241, 239, 237, 236, 236, 236, 237, 237, 237, 237, 237, 237, 237, 238, 239, 240, 241, 242, 244, 244, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 245, 243, 243, 243, 89, 92, 93, 94, 95, 96, 97, 98, 99, 100, 100, 102, 102, 102, 101, 101, 94, 90, 94, 100, 104, 109, 110, 111, 112, 111, 109, 107, 107, 111, 113, 115, 115, 113, 114, 120, 123, 124, 125, 125, 120, 114, 112, 112, 112, 105, 103, 109, 114, 120, 124, 144, 155, 154, 153, 152, 152, 152, 153, 154, 154, 155, 158, 160, 162, 166, 177, 190, 218, 242, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 235, 178, 129, 125, 125, 130, 135, 138, 139, 140, 140, 140, 138, 136, 131, 128, 130, 133, 132, 128, 126, 129, 133, 139, 148, 161, 172, 178, 181, 183, 184, 184, 183, 183, 183, 184, 185, 187, 189, 191, 192, 192, 192, 192, 191, 191, 190, 190, 189, 188, 188, 189, 191, 193, 195, 196, 197, 197, 198, 198, 199, 200, 200, 200, 200, 200, 201, 204, 206, 207, 209, 210, 210, 210, 209, 208, 207, 206, 205, 205, 204, 203, 202, 201, 199, 199, 198, 198, 198, 199, 200, 203, 205, 207, 210, 212, 215, 217, 219, 222, 224, 225, 226, 227, 229, 228, 227, 225, 224, 223, 221, 220, 219, 218, 219, 219, 220, 220, 220, 221, 221, 222, 222, 224, 226, 227, 228, 230, 233, 235, 238, 239, 240, 240, 241, 241, 241, 241, 240, 238, 237, 235, 234, 233, 234, 235, 236, 238, 238, 241, 241, 242, 242, 242, 241, 239, 238, 237, 236, 236, 236, 237, 237, 238, 239, 241, 243, 244, 245, 246, 246, 245, 244, 243, 241, 239, 238, 237, 236, 236, 236, 237, 237, 237, 237, 237, 237, 238, 238, 239, 240, 241, 242, 242, 243, 244, 244, 246, 246, 246, 244, 242, 240, 238, 236, 237, 239, 241, 242, 242, 88, 91, 93, 94, 95, 96, 97, 98, 99, 100, 100, 100, 98, 96, 89, 87, 93, 97, 100, 105, 106, 108, 109, 108, 106, 104, 104, 107, 111, 113, 113, 113, 112, 116, 120, 122, 122, 123, 121, 114, 111, 111, 110, 103, 101, 108, 116, 122, 127, 126, 147, 154, 153, 151, 151, 151, 151, 151, 152, 153, 153, 155, 158, 160, 163, 169, 182, 201, 229, 245, 246, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 238, 183, 126, 129, 132, 134, 136, 138, 137, 138, 137, 135, 130, 127, 129, 131, 128, 124, 123, 125, 129, 134, 143, 156, 169, 178, 181, 182, 181, 181, 181, 182, 183, 184, 185, 187, 188, 190, 191, 191, 190, 189, 189, 188, 187, 186, 186, 185, 186, 187, 190, 191, 193, 194, 194, 195, 196, 198, 199, 200, 200, 200, 200, 200, 202, 204, 206, 207, 208, 209, 209, 209, 209, 207, 206, 204, 203, 202, 201, 200, 200, 198, 198, 198, 198, 199, 199, 201, 203, 204, 205, 206, 209, 212, 215, 218, 220, 222, 224, 226, 227, 228, 228, 227, 225, 223, 221, 220, 219, 217, 216, 216, 217, 218, 220, 220, 221, 221, 222, 222, 222, 224, 226, 228, 228, 230, 232, 235, 238, 239, 240, 240, 241, 241, 241, 241, 240, 238, 237, 235, 233, 233, 234, 236, 237, 238, 239, 240, 241, 241, 242, 242, 241, 239, 237, 237, 236, 236, 236, 236, 237, 238, 240, 241, 243, 244, 245, 246, 245, 244, 244, 243, 240, 238, 237, 236, 236, 236, 237, 237, 237, 237, 237, 237, 237, 238, 238, 239, 240, 240, 241, 241, 241, 242, 242, 243, 241, 236, 226, 216, 209, 204, 201, 199, 202, 208, 218, 229, 239, 89, 91, 93, 95, 98, 99, 101, 100, 99, 99, 95, 90, 84, 85, 92, 95, 98, 101, 103, 104, 104, 103, 102, 101, 102, 103, 107, 111, 111, 111, 111, 112, 117, 120, 121, 121, 120, 116, 110, 109, 108, 101, 100, 111, 119, 124, 126, 126, 121, 146, 152, 152, 151, 150, 150, 149, 149, 150, 151, 152, 153, 154, 157, 160, 164, 172, 188, 213, 239, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 240, 188, 132, 133, 133, 133, 134, 135, 135, 132, 127, 124, 127, 130, 127, 122, 120, 122, 124, 131, 138, 151, 166, 177, 179, 178, 178, 178, 179, 180, 182, 184, 185, 187, 188, 188, 189, 189, 187, 186, 186, 185, 185, 183, 183, 183, 184, 186, 188, 189, 191, 192, 192, 193, 195, 197, 199, 200, 200, 200, 200, 200, 201, 203, 206, 207, 207, 208, 207, 208, 208, 206, 205, 203, 202, 200, 200, 199, 198, 197, 197, 197, 197, 198, 201, 204, 207, 207, 208, 208, 209, 211, 214, 218, 219, 221, 224, 225, 226, 227, 226, 224, 223, 220, 218, 217, 216, 215, 215, 216, 216, 217, 219, 221, 221, 221, 221, 221, 222, 223, 226, 228, 229, 230, 232, 234, 236, 238, 239, 240, 241, 241, 241, 241, 240, 238, 237, 235, 233, 233, 234, 235, 237, 238, 239, 240, 241, 241, 242, 242, 241, 239, 238, 237, 236, 236, 236, 236, 237, 238, 240, 242, 243, 244, 245, 245, 244, 244, 243, 241, 240, 237, 236, 236, 236, 237, 237, 237, 237, 237, 237, 237, 237, 238, 238, 239, 240, 240, 240, 240, 239, 239, 239, 236, 227, 213, 198, 184, 170, 161, 155, 151, 150, 154, 163, 176, 193, 211, 93, 97, 101, 102, 101, 101, 100, 98, 95, 88, 80, 82, 88, 90, 96, 99, 101, 102, 102, 100, 98, 96, 98, 100, 102, 107, 109, 110, 110, 110, 112, 117, 118, 119, 119, 116, 110, 107, 106, 99, 100, 114, 120, 124, 124, 124, 125, 120, 145, 150, 151, 150, 150, 148, 148, 148, 149, 149, 150, 151, 153, 153, 156, 161, 165, 175, 195, 223, 243, 246, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 242, 192, 132, 133, 131, 131, 131, 130, 124, 121, 123, 128, 127, 121, 119, 117, 121, 127, 136, 147, 161, 172, 175, 175, 175, 176, 177, 179, 181, 183, 185, 186, 187, 187, 186, 185, 184, 183, 183, 183, 182, 181, 180, 181, 182, 184, 186, 188, 189, 190, 191, 193, 196, 197, 199, 199, 199, 199, 200, 200, 201, 203, 205, 206, 206, 206, 206, 206, 206, 205, 204, 202, 201, 200, 199, 197, 196, 196, 196, 196, 197, 198, 201, 204, 206, 209, 211, 212, 212, 212, 214, 216, 218, 219, 220, 222, 223, 224, 223, 222, 219, 218, 216, 215, 214, 214, 214, 215, 216, 218, 220, 222, 221, 221, 220, 221, 221, 223, 226, 228, 229, 230, 232, 233, 236, 238, 239, 240, 241, 241, 241, 241, 239, 238, 236, 234, 233, 233, 234, 235, 236, 237, 238, 239, 240, 241, 241, 241, 241, 239, 238, 236, 235, 235, 236, 236, 237, 239, 241, 242, 244, 244, 244, 245, 245, 243, 242, 241, 238, 237, 236, 236, 236, 237, 238, 237, 237, 237, 237, 237, 238, 238, 239, 239, 240, 240, 239, 239, 238, 237, 237, 228, 209, 188, 169, 150, 135, 123, 115, 111, 109, 108, 111, 119, 132, 149, 170, 105, 103, 102, 101, 101, 99, 97, 88, 81, 82, 77, 83, 94, 97, 99, 99, 98, 98, 96, 94, 95, 96, 97, 101, 106, 107, 107, 108, 109, 112, 114, 116, 116, 116, 111, 107, 104, 97, 103, 117, 122, 123, 123, 123, 123, 123, 117, 143, 150, 150, 150, 149, 148, 148, 148, 148, 148, 148, 149, 149, 150, 151, 154, 159, 165, 178, 198, 229, 245, 246, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 243, 193, 132, 130, 128, 125, 120, 117, 119, 125, 127, 122, 116, 114, 118, 125, 135, 143, 153, 164, 170, 171, 172, 174, 176, 179, 180, 182, 183, 184, 184, 184, 183, 182, 180, 179, 179, 179, 178, 177, 177, 178, 179, 181, 184, 185, 187, 188, 191, 194, 197, 199, 199, 199, 199, 199, 199, 200, 201, 202, 203, 204, 205, 205, 205, 205, 205, 204, 203, 202, 201, 199, 198, 196, 195, 194, 195, 195, 197, 200, 203, 205, 207, 210, 212, 212, 213, 214, 215, 217, 217, 218, 219, 219, 219, 219, 218, 217, 216, 215, 214, 212, 212, 213, 214, 215, 217, 218, 221, 222, 222, 221, 220, 220, 220, 222, 225, 228, 230, 231, 231, 233, 235, 238, 239, 239, 240, 240, 241, 240, 239, 237, 235, 233, 233, 233, 234, 234, 235, 236, 236, 237, 238, 240, 241, 242, 241, 240, 238, 237, 235, 235, 235, 237, 238, 239, 241, 243, 244, 244, 244, 244, 245, 243, 241, 239, 237, 236, 236, 236, 237, 237, 238, 237, 237, 237, 237, 238, 238, 239, 239, 240, 240, 240, 239, 239, 238, 237, 235, 221, 197, 170, 145, 124, 109, 100, 97, 97, 98, 99, 99, 100, 100, 103, 112, 128, 105, 103, 102, 101, 99, 89, 81, 83, 87, 88, 92, 90, 84, 96, 97, 95, 91, 89, 91, 93, 93, 97, 102, 104, 105, 105, 108, 109, 112, 114, 114, 114, 112, 106, 100, 97, 106, 118, 121, 122, 122, 121, 121, 121, 121, 117, 141, 148, 148, 149, 148, 147, 147, 147, 147, 147, 148, 148, 148, 148, 148, 148, 149, 152, 166, 179, 201, 232, 246, 246, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 243, 193, 127, 123, 116, 113, 115, 123, 126, 121, 112, 112, 118, 124, 131, 137, 145, 155, 165, 169, 172, 174, 176, 178, 179, 180, 181, 181, 182, 181, 180, 178, 176, 175, 176, 176, 175, 174, 174, 175, 176, 177, 179, 182, 185, 188, 192, 195, 197, 199, 200, 199, 198, 198, 198, 199, 200, 201, 202, 202, 203, 204, 204, 204, 205, 203, 202, 201, 200, 198, 196, 194, 194, 193, 194, 195, 198, 200, 204, 205, 207, 210, 211, 212, 212, 213, 215, 216, 218, 219, 219, 219, 218, 219, 217, 215, 214, 212, 210, 210, 211, 212, 214, 215, 217, 220, 222, 222, 223, 222, 221, 220, 220, 222, 224, 227, 229, 230, 231, 233, 235, 237, 239, 239, 240, 240, 240, 239, 238, 236, 234, 232, 232, 233, 233, 234, 235, 234, 234, 234, 237, 238, 240, 241, 241, 240, 238, 236, 235, 235, 236, 237, 238, 240, 242, 243, 244, 244, 244, 244, 243, 241, 240, 238, 237, 236, 236, 236, 237, 238, 238, 238, 237, 238, 238, 239, 239, 240, 240, 241, 240, 240, 239, 238, 238, 237, 233, 215, 188, 158, 130, 107, 96, 95, 96, 97, 98, 98, 99, 99, 100, 100, 101, 101, 103, 105, 103, 102, 91, 82, 84, 86, 86, 90, 94, 96, 96, 96, 83, 81, 88, 89, 90, 90, 92, 97, 101, 102, 103, 105, 107, 109, 112, 112, 112, 112, 107, 98, 98, 108, 119, 120, 120, 121, 120, 120, 121, 120, 120, 116, 139, 147, 148, 148, 148, 148, 147, 147, 147, 146, 147, 147, 148, 148, 147, 148, 146, 147, 141, 164, 177, 203, 233, 245, 246, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 243, 181, 114, 113, 114, 119, 119, 114, 112, 114, 118, 121, 126, 131, 138, 148, 160, 168, 172, 174, 175, 175, 177, 178, 178, 178, 178, 177, 175, 173, 172, 172, 172, 172, 172, 172, 172, 172, 173, 175, 177, 179, 182, 186, 191, 195, 198, 198, 198, 198, 197, 197, 197, 198, 199, 200, 200, 201, 201, 202, 202, 203, 204, 203, 202, 201, 199, 197, 195, 193, 193, 193, 193, 196, 198, 201, 204, 206, 208, 210, 212, 212, 212, 212, 213, 215, 217, 218, 218, 219, 219, 220, 220, 218, 217, 215, 211, 209, 210, 211, 214, 215, 218, 220, 222, 224, 225, 223, 221, 220, 219, 221, 223, 227, 229, 231, 231, 232, 235, 237, 239, 239, 239, 239, 239, 239, 238, 235, 233, 232, 232, 232, 233, 234, 234, 233, 233, 233, 235, 237, 239, 241, 241, 240, 238, 237, 235, 235, 237, 238, 239, 241, 242, 243, 244, 244, 244, 243, 242, 239, 237, 236, 235, 236, 236, 237, 237, 238, 238, 238, 238, 238, 239, 239, 240, 240, 241, 241, 240, 240, 239, 238, 238, 236, 232, 212, 183, 151, 121, 99, 93, 94, 95, 96, 97, 97, 98, 98, 99, 100, 100, 100, 101, 101, 103, 91, 82, 84, 85, 85, 88, 93, 95, 96, 95, 93, 90, 88, 86, 76, 84, 89, 93, 98, 100, 101, 102, 104, 106, 109, 110, 109, 109, 106, 97, 97, 109, 118, 118, 118, 118, 118, 118, 118, 118, 117, 115, 112, 135, 147, 147, 147, 147, 147, 147, 147, 146, 147, 147, 147, 146, 141, 137, 140, 145, 146, 146, 139, 155, 175, 204, 232, 242, 245, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 243, 177, 114, 118, 110, 108, 113, 116, 115, 117, 119, 124, 132, 144, 157, 166, 169, 172, 173, 173, 174, 175, 175, 174, 172, 171, 169, 168, 167, 168, 168, 168, 168, 169, 168, 168, 171, 174, 178, 181, 183, 187, 190, 192, 193, 194, 195, 195, 195, 195, 196, 196, 197, 198, 199, 200, 200, 201, 202, 202, 203, 203, 202, 200, 197, 195, 194, 193, 192, 192, 194, 197, 200, 202, 204, 207, 209, 211, 212, 212, 211, 211, 211, 213, 216, 217, 218, 218, 219, 220, 221, 222, 222, 219, 215, 212, 211, 211, 214, 216, 218, 221, 224, 226, 227, 226, 223, 221, 220, 221, 223, 227, 229, 230, 231, 232, 234, 236, 239, 238, 239, 239, 239, 238, 236, 233, 232, 231, 232, 232, 233, 234, 233, 233, 233, 233, 234, 237, 238, 240, 241, 240, 238, 237, 236, 236, 237, 238, 240, 242, 243, 244, 244, 244, 244, 242, 240, 238, 236, 235, 233, 233, 234, 236, 237, 237, 238, 238, 238, 239, 239, 240, 241, 241, 241, 240, 240, 240, 239, 239, 238, 237, 230, 209, 179, 146, 116, 95, 91, 93, 94, 95, 96, 96, 97, 98, 98, 99, 99, 100, 100, 101, 101, 83, 84, 84, 84, 86, 91, 94, 94, 95, 93, 89, 87, 87, 88, 89, 89, 82, 81, 98, 100, 100, 102, 103, 106, 109, 108, 107, 105, 95, 96, 108, 114, 115, 116, 116, 116, 116, 117, 116, 115, 113, 111, 106, 126, 147, 147, 147, 147, 147, 146, 136, 121, 105, 89, 73, 57, 46, 41, 41, 38, 49, 70, 88, 105, 114, 166, 203, 224, 232, 238, 244, 246, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 243, 175, 108, 113, 112, 112, 112, 111, 113, 119, 129, 140, 153, 163, 167, 168, 171, 171, 172, 171, 170, 168, 167, 165, 163, 163, 163, 164, 165, 164, 164, 163, 164, 165, 168, 173, 179, 184, 188, 191, 192, 191, 190, 189, 189, 189, 190, 193, 194, 195, 196, 197, 198, 199, 199, 200, 201, 202, 202, 202, 201, 198, 195, 193, 192, 191, 192, 193, 196, 198, 200, 202, 204, 207, 209, 210, 210, 211, 210, 210, 210, 212, 214, 216, 218, 218, 219, 220, 221, 222, 221, 220, 218, 216, 214, 213, 215, 217, 219, 222, 226, 228, 229, 228, 226, 222, 221, 221, 223, 227, 229, 230, 231, 232, 233, 236, 238, 238, 239, 239, 239, 238, 235, 233, 231, 231, 231, 232, 233, 233, 233, 233, 233, 233, 234, 236, 238, 240, 241, 240, 239, 238, 236, 236, 238, 239, 241, 243, 243, 244, 244, 244, 243, 241, 238, 236, 234, 233, 232, 232, 234, 235, 235, 236, 236, 237, 238, 239, 240, 240, 241, 242, 242, 240, 240, 240, 240, 239, 239, 238, 227, 204, 174, 141, 112, 93, 90, 91, 93, 94, 94, 96, 96, 97, 97, 98, 99, 99, 100, 100, 100, 101, 83, 83, 84, 89, 92, 93, 93, 92, 89, 86, 86, 87, 87, 87, 88, 92, 97, 98, 86, 90, 101, 101, 106, 108, 108, 105, 95, 97, 109, 112, 113, 114, 114, 115, 115, 115, 114, 113, 111, 108, 107, 104, 117, 147, 146, 146, 145, 126, 96, 71, 48, 43, 44, 45, 38, 38, 40, 46, 49, 41, 43, 45, 47, 50, 51, 61, 107, 163, 200, 223, 227, 229, 234, 237, 237, 241, 243, 244, 244, 246, 247, 247, 247, 247, 247, 247, 247, 247, 247, 241, 165, 112, 108, 106, 106, 111, 118, 126, 136, 148, 159, 165, 166, 168, 168, 168, 165, 163, 162, 161, 159, 158, 158, 159, 160, 161, 161, 160, 158, 159, 162, 168, 175, 181, 186, 190, 192, 193, 192, 190, 188, 186, 187, 186, 187, 189, 191, 193, 196, 196, 198, 199, 200, 201, 201, 201, 199, 197, 193, 191, 191, 191, 190, 191, 193, 196, 198, 200, 201, 203, 206, 208, 210, 211, 210, 209, 209, 209, 211, 213, 215, 217, 218, 219, 221, 222, 221, 220, 219, 217, 215, 215, 214, 216, 219, 222, 225, 228, 230, 230, 229, 226, 223, 221, 220, 223, 227, 229, 231, 231, 232, 233, 235, 238, 239, 239, 239, 239, 237, 234, 233, 232, 231, 232, 233, 233, 233, 233, 233, 233, 233, 235, 236, 238, 240, 241, 241, 239, 238, 237, 237, 238, 239, 241, 242, 243, 244, 244, 243, 242, 240, 237, 235, 233, 232, 232, 234, 234, 235, 235, 235, 236, 236, 237, 238, 239, 241, 242, 242, 241, 240, 240, 240, 240, 240, 240, 238, 224, 198, 166, 135, 107, 91, 90, 91, 92, 93, 93, 94, 95, 96, 96, 97, 98, 98, 99, 99, 100, 100, 100, 83, 86, 90, 92, 93, 92, 89, 86, 85, 86, 86, 86, 87, 89, 94, 97, 99, 99, 98, 92, 84, 100, 106, 105, 94, 98, 109, 112, 112, 112, 113, 113, 114, 113, 111, 109, 107, 107, 107, 108, 109, 109, 145, 147, 139, 106, 57, 43, 44, 51, 69, 71, 65, 43, 40, 39, 39, 44, 83, 58, 41, 45, 53, 51, 54, 66, 79, 85, 128, 169, 189, 194, 198, 199, 209, 206, 201, 205, 206, 212, 239, 246, 247, 247, 247, 247, 247, 247, 247, 246, 237, 151, 110, 107, 111, 118, 124, 132, 142, 153, 162, 165, 165, 163, 161, 159, 157, 156, 156, 155, 154, 154, 155, 156, 157, 157, 154, 153, 155, 161, 169, 178, 184, 188, 190, 191, 190, 189, 187, 187, 187, 187, 186, 185, 186, 187, 188, 190, 193, 195, 197, 198, 199, 200, 199, 197, 193, 189, 187, 186, 188, 189, 190, 193, 194, 196, 198, 199, 202, 205, 208, 209, 210, 209, 209, 207, 208, 210, 212, 214, 215, 217, 219, 220, 221, 220, 219, 217, 215, 214, 214, 215, 217, 220, 224, 227, 230, 231, 231, 229, 226, 223, 220, 219, 222, 226, 229, 231, 231, 231, 232, 235, 238, 239, 239, 239, 238, 237, 234, 233, 231, 231, 232, 233, 233, 233, 233, 233, 233, 233, 234, 236, 238, 240, 241, 241, 240, 238, 237, 238, 238, 239, 240, 241, 242, 242, 242, 242, 241, 238, 236, 234, 233, 232, 233, 234, 235, 236, 236, 236, 236, 236, 237, 238, 239, 239, 240, 240, 240, 240, 240, 240, 240, 240, 241, 237, 220, 191, 160, 128, 101, 89, 89, 90, 90, 91, 92, 93, 94, 95, 95, 96, 97, 97, 98, 99, 99, 99, 100, 100, 88, 91, 92, 91, 89, 85, 84, 85, 86, 86, 86, 87, 91, 96, 98, 99, 98, 95, 92, 98, 102, 86, 85, 92, 107, 110, 110, 111, 112, 112, 112, 110, 108, 106, 105, 105, 108, 111, 111, 109, 105, 141, 142, 105, 48, 44, 44, 44, 43, 65, 76, 56, 27, 27, 28, 29, 30, 34, 56, 84, 46, 49, 59, 65, 73, 60, 92, 142, 128, 126, 131, 153, 164, 177, 187, 206, 215, 210, 207, 206, 199, 240, 245, 247, 247, 247, 247, 247, 247, 247, 246, 228, 102, 109, 118, 123, 130, 137, 147, 157, 160, 158, 156, 154, 153, 153, 153, 152, 152, 151, 152, 152, 153, 153, 151, 149, 149, 153, 161, 171, 180, 185, 188, 188, 188, 187, 185, 184, 183, 184, 186, 187, 188, 188, 187, 187, 188, 189, 190, 191, 193, 195, 195, 195, 192, 189, 186, 183, 182, 184, 186, 189, 191, 193, 194, 196, 198, 200, 204, 207, 209, 209, 208, 207, 206, 206, 208, 211, 212, 214, 216, 217, 219, 219, 219, 217, 215, 214, 213, 214, 216, 219, 222, 226, 229, 231, 232, 232, 229, 226, 222, 219, 217, 220, 224, 228, 231, 231, 231, 231, 234, 238, 239, 239, 239, 238, 237, 235, 233, 231, 231, 233, 234, 233, 233, 233, 233, 233, 233, 234, 236, 238, 240, 241, 242, 240, 239, 237, 238, 238, 239, 239, 240, 240, 240, 240, 239, 238, 237, 235, 234, 232, 232, 233, 235, 235, 236, 236, 237, 238, 238, 239, 240, 239, 239, 239, 239, 238, 238, 238, 239, 240, 241, 242, 236, 214, 184, 151, 119, 95, 87, 87, 89, 89, 90, 91, 92, 93, 93, 94, 95, 96, 96, 97, 98, 98, 99, 99, 99, 100, 90, 91, 89, 84, 83, 84, 85, 86, 89, 87, 89, 94, 97, 98, 98, 96, 92, 89, 92, 96, 91, 91, 98, 104, 109, 110, 110, 111, 110, 107, 103, 103, 104, 106, 111, 113, 114, 113, 109, 97, 134, 120, 68, 44, 44, 44, 44, 45, 76, 66, 49, 76, 43, 43, 43, 43, 43, 42, 42, 70, 72, 84, 77, 68, 64, 77, 105, 104, 152, 162, 165, 165, 155, 139, 148, 171, 196, 181, 148, 124, 126, 228, 239, 243, 246, 246, 247, 247, 247, 246, 247, 245, 157, 85, 124, 129, 135, 141, 148, 152, 151, 150, 149, 149, 150, 150, 150, 150, 149, 149, 150, 151, 149, 145, 144, 147, 153, 164, 174, 181, 184, 186, 186, 185, 184, 182, 181, 181, 183, 184, 186, 187, 187, 188, 189, 190, 189, 188, 188, 188, 188, 187, 187, 187, 185, 183, 181, 180, 182, 185, 187, 189, 191, 192, 194, 196, 198, 202, 206, 208, 208, 207, 205, 204, 205, 207, 209, 210, 212, 213, 214, 215, 216, 216, 214, 213, 212, 212, 214, 217, 221, 224, 227, 230, 231, 232, 231, 228, 225, 221, 218, 217, 218, 222, 226, 229, 231, 230, 231, 233, 236, 239, 239, 239, 238, 238, 236, 234, 232, 232, 233, 233, 233, 234, 234, 234, 234, 233, 234, 236, 238, 239, 241, 242, 240, 239, 238, 237, 237, 238, 238, 238, 238, 238, 238, 237, 236, 235, 234, 233, 233, 233, 235, 235, 235, 236, 237, 238, 238, 239, 240, 241, 242, 241, 240, 239, 237, 236, 237, 237, 238, 239, 241, 232, 208, 177, 143, 112, 90, 85, 86, 87, 88, 89, 89, 91, 91, 92, 93, 94, 95, 95, 96, 97, 97, 98, 98, 99, 99, 99, 89, 85, 82, 83, 84, 86, 92, 96, 93, 94, 96, 97, 97, 96, 94, 88, 89, 88, 83, 88, 97, 96, 96, 105, 109, 109, 107, 102, 99, 101, 103, 107, 111, 114, 114, 114, 113, 110, 91, 85, 63, 44, 44, 44, 44, 44, 49, 82, 66, 43, 42, 78, 51, 43, 43, 43, 43, 45, 70, 80, 77, 64, 78, 87, 122, 160, 79, 90, 100, 117, 149, 167, 170, 170, 184, 207, 197, 200, 227, 212, 154, 185, 237, 238, 240, 246, 246, 247, 247, 247, 247, 246, 201, 97, 107, 138, 139, 142, 145, 146, 146, 147, 147, 147, 148, 148, 148, 148, 148, 149, 149, 144, 140, 141, 147, 156, 167, 176, 181, 182, 183, 184, 182, 179, 178, 178, 180, 182, 184, 185, 186, 187, 187, 188, 189, 189, 189, 188, 186, 183, 181, 178, 179, 179, 179, 179, 180, 181, 183, 185, 186, 188, 190, 191, 194, 197, 200, 204, 207, 207, 205, 203, 202, 203, 205, 207, 208, 209, 210, 211, 210, 211, 211, 211, 211, 211, 213, 216, 219, 222, 225, 227, 230, 231, 230, 228, 227, 223, 220, 218, 217, 217, 219, 224, 228, 229, 229, 231, 233, 236, 238, 238, 238, 238, 237, 236, 235, 234, 233, 233, 233, 234, 234, 234, 234, 234, 234, 234, 236, 237, 239, 240, 241, 240, 239, 238, 237, 237, 237, 237, 237, 237, 237, 236, 235, 234, 234, 234, 233, 234, 234, 235, 235, 236, 237, 237, 238, 239, 240, 241, 242, 242, 241, 240, 239, 238, 237, 237, 237, 238, 239, 239, 227, 201, 169, 135, 105, 86, 84, 85, 86, 87, 87, 88, 89, 90, 91, 92, 93, 93, 94, 95, 96, 96, 97, 98, 98, 99, 99, 99, 82, 82, 83, 85, 93, 99, 100, 100, 99, 98, 97, 97, 95, 91, 87, 85, 81, 83, 89, 94, 99, 102, 103, 103, 101, 96, 94, 99, 102, 105, 108, 112, 112, 113, 114, 112, 102, 79, 49, 43, 44, 44, 44, 44, 42, 40, 39, 47, 41, 41, 40, 43, 44, 40, 42, 43, 64, 85, 74, 48, 77, 88, 87, 67, 139, 105, 75, 85, 97, 121, 117, 115, 147, 190, 197, 191, 221, 229, 210, 207, 230, 204, 223, 237, 237, 239, 245, 247, 247, 247, 247, 246, 227, 109, 101, 128, 140, 141, 143, 143, 144, 144, 145, 145, 147, 147, 148, 148, 148, 146, 140, 138, 141, 148, 157, 168, 177, 180, 180, 181, 180, 178, 176, 175, 176, 179, 181, 183, 184, 185, 186, 186, 186, 186, 186, 185, 184, 183, 181, 177, 174, 172, 173, 175, 177, 179, 180, 181, 183, 184, 185, 187, 190, 193, 196, 199, 203, 205, 206, 203, 201, 200, 200, 201, 205, 207, 208, 208, 207, 206, 207, 208, 208, 210, 213, 215, 217, 220, 223, 225, 227, 228, 228, 227, 226, 225, 222, 219, 217, 216, 216, 218, 223, 226, 228, 228, 228, 231, 234, 238, 238, 237, 236, 235, 235, 234, 234, 234, 233, 234, 234, 234, 234, 234, 233, 233, 234, 236, 237, 239, 240, 241, 240, 239, 237, 237, 236, 237, 237, 236, 236, 236, 235, 234, 234, 234, 234, 234, 234, 235, 236, 236, 236, 237, 238, 239, 239, 240, 241, 242, 241, 240, 240, 239, 238, 238, 238, 239, 240, 240, 239, 223, 195, 161, 127, 99, 84, 83, 83, 84, 85, 86, 87, 88, 89, 90, 91, 91, 92, 93, 94, 94, 95, 96, 96, 97, 98, 98, 99, 99, 82, 84, 92, 101, 103, 103, 103, 103, 101, 99, 97, 94, 88, 82, 80, 83, 88, 94, 99, 102, 102, 100, 95, 91, 91, 96, 100, 103, 106, 107, 109, 111, 112, 112, 106, 89, 56, 42, 44, 44, 44, 44, 44, 44, 44, 42, 40, 41, 43, 44, 44, 43, 43, 39, 34, 30, 50, 53, 41, 42, 62, 79, 69, 72, 120, 95, 65, 69, 86, 110, 123, 139, 130, 119, 184, 222, 220, 196, 198, 208, 194, 214, 223, 212, 236, 237, 238, 243, 246, 247, 247, 247, 239, 117, 112, 183, 136, 144, 142, 143, 143, 144, 145, 146, 147, 148, 148, 145, 139, 138, 142, 145, 148, 157, 170, 177, 178, 179, 179, 178, 175, 174, 174, 177, 179, 180, 181, 183, 183, 184, 184, 184, 183, 182, 180, 178, 176, 174, 172, 171, 170, 171, 173, 176, 178, 179, 180, 181, 182, 183, 186, 188, 192, 196, 199, 203, 205, 203, 201, 198, 197, 197, 199, 201, 204, 205, 205, 204, 203, 204, 205, 207, 209, 214, 218, 220, 222, 223, 224, 225, 226, 225, 225, 225, 223, 220, 218, 216, 215, 215, 217, 221, 226, 228, 229, 228, 229, 232, 235, 237, 237, 236, 234, 232, 232, 233, 233, 233, 234, 234, 234, 234, 234, 233, 233, 233, 235, 236, 238, 240, 241, 241, 239, 238, 237, 235, 235, 235, 236, 236, 236, 235, 234, 234, 235, 236, 236, 236, 236, 236, 236, 237, 237, 238, 239, 240, 241, 241, 241, 240, 239, 238, 238, 237, 238, 239, 239, 241, 242, 239, 221, 190, 155, 121, 94, 82, 82, 82, 83, 84, 85, 86, 87, 87, 88, 89, 90, 91, 92, 92, 93, 94, 95, 95, 96, 97, 97, 98, 98, 99, 90, 100, 103, 104, 104, 103, 103, 103, 102, 99, 95, 83, 78, 83, 90, 96, 100, 101, 100, 97, 91, 88, 89, 93, 98, 102, 105, 105, 106, 107, 108, 110, 108, 104, 74, 38, 44, 44, 44, 44, 44, 44, 43, 38, 33, 24, 21, 26, 29, 39, 44, 43, 43, 43, 43, 43, 40, 32, 24, 32, 44, 85, 52, 158, 209, 164, 67, 71, 72, 101, 111, 118, 137, 172, 140, 146, 209, 218, 172, 164, 155, 164, 187, 225, 206, 222, 237, 237, 240, 246, 246, 246, 241, 122, 128, 237, 179, 140, 143, 143, 145, 146, 147, 147, 147, 146, 138, 135, 141, 146, 147, 149, 158, 171, 175, 176, 177, 177, 175, 172, 172, 173, 176, 178, 179, 180, 181, 182, 182, 181, 180, 178, 177, 174, 173, 170, 167, 166, 167, 168, 169, 172, 174, 176, 177, 178, 180, 182, 184, 186, 189, 192, 195, 199, 202, 204, 202, 199, 196, 194, 195, 196, 198, 200, 200, 200, 200, 199, 201, 203, 208, 211, 216, 219, 221, 222, 222, 222, 222, 222, 223, 222, 222, 221, 219, 217, 215, 214, 214, 215, 218, 225, 229, 231, 230, 229, 230, 232, 235, 237, 235, 234, 232, 231, 231, 231, 231, 232, 234, 234, 234, 233, 233, 233, 233, 234, 236, 238, 240, 241, 241, 239, 238, 237, 235, 235, 235, 235, 235, 234, 233, 233, 234, 235, 236, 237, 237, 237, 236, 237, 237, 238, 239, 240, 240, 241, 240, 240, 239, 238, 238, 237, 237, 237, 239, 239, 240, 242, 238, 219, 187, 151, 116, 90, 81, 81, 81, 82, 83, 84, 85, 86, 86, 87, 88, 89, 90, 90, 91, 92, 92, 93, 94, 95, 96, 96, 97, 97, 98, 98, 103, 103, 103, 103, 104, 104, 103, 103, 100, 87, 80, 86, 92, 97, 100, 100, 98, 93, 89, 87, 87, 90, 96, 101, 103, 105, 105, 105, 107, 107, 106, 104, 102, 59, 35, 43, 44, 44, 44, 44, 44, 44, 44, 43, 37, 23, 22, 38, 43, 43, 44, 43, 43, 43, 43, 42, 42, 42, 40, 32, 23, 58, 58, 162, 214, 184, 82, 72, 72, 75, 104, 110, 112, 129, 187, 172, 118, 162, 172, 156, 157, 131, 137, 168, 215, 189, 158, 169, 193, 210, 223, 226, 212, 126, 203, 245, 236, 164, 145, 146, 146, 147, 148, 146, 137, 132, 139, 145, 145, 146, 147, 159, 172, 174, 174, 175, 175, 172, 169, 170, 172, 174, 176, 178, 179, 179, 179, 179, 178, 176, 173, 170, 168, 167, 164, 163, 163, 164, 166, 169, 170, 172, 174, 175, 178, 179, 182, 184, 187, 189, 192, 195, 198, 201, 202, 201, 197, 193, 191, 191, 193, 194, 195, 195, 195, 196, 197, 200, 203, 209, 213, 217, 220, 222, 222, 220, 219, 219, 220, 220, 220, 220, 219, 218, 216, 215, 213, 212, 213, 216, 221, 227, 231, 233, 232, 230, 231, 233, 235, 234, 234, 233, 232, 231, 231, 231, 232, 231, 231, 232, 232, 233, 233, 233, 234, 236, 237, 239, 241, 241, 239, 238, 237, 235, 235, 235, 235, 235, 233, 232, 232, 234, 235, 236, 237, 237, 237, 237, 237, 238, 239, 240, 240, 241, 241, 240, 239, 238, 237, 237, 237, 237, 238, 238, 239, 240, 241, 236, 215, 182, 147, 112, 87, 80, 80, 81, 81, 82, 83, 84, 84, 85, 86, 87, 87, 88, 89, 90, 91, 91, 92, 93, 94, 94, 95, 96, 96, 97, 97, 98, 102, 102, 103, 103, 103, 104, 100, 86, 82, 89, 93, 97, 98, 98, 94, 89, 86, 86, 86, 88, 93, 99, 103, 104, 104, 105, 107, 108, 107, 106, 105, 94, 38, 27, 34, 43, 44, 44, 44, 44, 44, 44, 44, 37, 19, 19, 25, 38, 43, 43, 43, 43, 42, 42, 40, 37, 38, 41, 42, 43, 44, 35, 37, 104, 188, 200, 82, 88, 71, 72, 76, 102, 109, 110, 120, 159, 165, 129, 119, 145, 141, 144, 129, 117, 148, 191, 192, 116, 96, 106, 128, 130, 164, 216, 246, 246, 245, 230, 154, 147, 147, 145, 138, 130, 136, 142, 142, 143, 143, 145, 155, 168, 170, 171, 172, 170, 167, 166, 168, 170, 172, 174, 175, 176, 176, 175, 175, 173, 170, 167, 164, 163, 161, 160, 160, 161, 163, 165, 167, 169, 171, 173, 175, 177, 180, 182, 185, 188, 190, 192, 195, 197, 198, 200, 200, 196, 191, 188, 188, 189, 190, 191, 190, 191, 193, 195, 200, 205, 210, 215, 218, 220, 221, 220, 218, 217, 218, 217, 217, 218, 218, 217, 216, 215, 214, 213, 211, 211, 214, 218, 224, 230, 234, 233, 232, 232, 233, 234, 233, 233, 233, 233, 233, 233, 232, 231, 231, 230, 229, 230, 230, 231, 233, 235, 236, 237, 239, 240, 240, 239, 238, 236, 235, 235, 235, 235, 234, 233, 232, 232, 233, 235, 236, 237, 237, 237, 237, 237, 239, 239, 240, 241, 241, 240, 239, 238, 237, 237, 237, 237, 237, 238, 239, 239, 239, 239, 234, 211, 178, 142, 108, 85, 79, 79, 79, 80, 81, 81, 82, 83, 84, 85, 85, 86, 87, 88, 89, 90, 90, 91, 92, 92, 93, 94, 95, 95, 96, 97, 97, 97, 102, 102, 102, 102, 97, 86, 84, 92, 94, 95, 96, 95, 90, 86, 85, 85, 86, 86, 90, 97, 102, 103, 104, 104, 106, 108, 108, 107, 104, 105, 85, 24, 23, 35, 44, 44, 44, 44, 44, 44, 44, 44, 37, 25, 22, 30, 42, 43, 43, 43, 43, 43, 42, 42, 42, 42, 37, 28, 29, 38, 55, 88, 49, 75, 129, 188, 123, 79, 99, 79, 69, 74, 100, 109, 109, 114, 147, 163, 142, 107, 127, 129, 127, 123, 103, 132, 168, 193, 202, 218, 223, 233, 243, 246, 247, 247, 247, 242, 223, 139, 135, 138, 141, 140, 138, 138, 139, 142, 145, 149, 156, 161, 162, 162, 158, 157, 161, 162, 163, 165, 166, 168, 168, 167, 167, 166, 165, 162, 159, 159, 158, 156, 156, 157, 160, 163, 165, 167, 168, 171, 173, 176, 179, 181, 182, 184, 187, 190, 192, 194, 195, 196, 197, 197, 194, 189, 185, 184, 186, 187, 187, 186, 188, 192, 196, 201, 206, 212, 215, 218, 219, 218, 216, 215, 215, 216, 217, 216, 216, 216, 215, 214, 214, 213, 212, 210, 211, 212, 215, 221, 228, 232, 233, 232, 233, 233, 233, 232, 233, 232, 233, 233, 233, 233, 233, 233, 231, 230, 229, 230, 231, 232, 233, 235, 237, 238, 240, 240, 239, 237, 236, 235, 235, 235, 235, 233, 232, 231, 232, 233, 236, 237, 237, 237, 237, 237, 238, 239, 240, 240, 241, 240, 239, 238, 238, 237, 236, 236, 237, 237, 238, 239, 239, 239, 238, 232, 208, 174, 138, 104, 82, 79, 79, 79, 79, 79, 80, 81, 82, 83, 84, 84, 85, 86, 87, 88, 88, 89, 90, 91, 91, 92, 93, 94, 94, 95, 96, 96, 97, 97, 102, 100, 95, 85, 85, 92, 92, 91, 91, 89, 86, 85, 85, 85, 85, 85, 87, 94, 100, 103, 103, 103, 105, 107, 108, 108, 107, 104, 106, 78, 22, 25, 39, 44, 44, 44, 44, 44, 44, 44, 43, 37, 23, 20, 22, 37, 44, 43, 43, 43, 43, 43, 42, 42, 42, 42, 42, 42, 38, 28, 35, 77, 63, 48, 115, 126, 128, 79, 95, 110, 129, 72, 70, 96, 108, 109, 112, 139, 150, 138, 107, 107, 119, 113, 116, 97, 120, 154, 191, 189, 222, 236, 237, 241, 246, 247, 246, 244, 239, 212, 126, 154, 152, 139, 138, 140, 149, 154, 150, 145, 149, 151, 149, 145, 142, 159, 190, 186, 159, 153, 157, 165, 166, 158, 154, 160, 164, 162, 155, 151, 151, 151, 152, 159, 166, 170, 169, 168, 170, 173, 178, 185, 187, 185, 183, 185, 188, 191, 193, 193, 194, 194, 195, 192, 187, 183, 181, 182, 183, 183, 184, 187, 191, 197, 203, 208, 212, 215, 217, 217, 215, 213, 212, 212, 214, 215, 215, 215, 214, 212, 212, 212, 212, 211, 209, 209, 210, 214, 219, 225, 229, 232, 233, 232, 232, 232, 232, 232, 231, 232, 233, 233, 233, 233, 232, 231, 232, 232, 231, 231, 232, 234, 235, 237, 237, 238, 238, 238, 237, 236, 235, 234, 234, 233, 232, 231, 231, 232, 234, 236, 237, 237, 237, 237, 237, 238, 239, 240, 240, 240, 239, 238, 237, 237, 236, 236, 237, 237, 238, 239, 239, 239, 238, 238, 231, 206, 172, 135, 101, 81, 77, 78, 78, 79, 79, 79, 80, 81, 82, 82, 83, 84, 85, 86, 86, 87, 88, 89, 89, 90, 91, 92, 92, 93, 94, 95, 95, 96, 96, 97, 93, 83, 85, 93, 91, 86, 84, 83, 82, 83, 84, 84, 85, 85, 85, 89, 98, 102, 103, 103, 104, 106, 107, 107, 108, 107, 105, 107, 75, 22, 28, 42, 44, 44, 44, 44, 44, 44, 44, 45, 43, 42, 42, 42, 43, 44, 44, 43, 42, 43, 43, 43, 42, 42, 42, 42, 42, 43, 43, 56, 81, 53, 36, 31, 107, 113, 118, 82, 67, 101, 126, 164, 89, 67, 89, 108, 109, 112, 138, 140, 123, 103, 93, 109, 107, 110, 95, 108, 145, 182, 195, 213, 230, 237, 240, 245, 245, 244, 242, 236, 176, 148, 165, 165, 149, 166, 195, 200, 193, 149, 145, 149, 163, 160, 148, 180, 207, 210, 187, 154, 170, 185, 189, 181, 170, 179, 190, 190, 175, 162, 163, 161, 158, 166, 178, 183, 181, 177, 175, 177, 186, 196, 197, 190, 184, 186, 190, 193, 195, 192, 191, 191, 191, 189, 185, 180, 179, 179, 180, 182, 186, 192, 198, 206, 212, 213, 214, 216, 216, 214, 212, 210, 211, 212, 214, 215, 215, 212, 210, 210, 211, 211, 209, 208, 207, 208, 211, 217, 222, 227, 230, 231, 231, 231, 231, 231, 231, 231, 232, 233, 233, 232, 232, 231, 231, 231, 231, 232, 232, 234, 235, 237, 237, 237, 237, 237, 236, 235, 235, 234, 234, 233, 232, 231, 231, 231, 232, 234, 236, 237, 238, 237, 237, 238, 238, 239, 240, 239, 239, 238, 237, 237, 236, 236, 236, 237, 237, 238, 239, 239, 239, 237, 237, 231, 205, 170, 133, 99, 80, 77, 77, 77, 77, 77, 78, 79, 80, 80, 81, 82, 83, 84, 84, 85, 86, 87, 87, 88, 89, 90, 90, 91, 92, 93, 93, 94, 95, 95, 96, 96, 86, 93, 91, 86, 82, 82, 82, 82, 82, 82, 82, 83, 84, 85, 93, 100, 101, 102, 102, 104, 106, 105, 105, 104, 104, 104, 104, 76, 22, 23, 37, 43, 43, 43, 44, 44, 42, 37, 36, 36, 38, 40, 45, 45, 44, 44, 44, 43, 42, 43, 43, 42, 42, 42, 42, 42, 42, 43, 44, 77, 100, 103, 67, 29, 95, 117, 116, 97, 78, 58, 103, 141, 196, 111, 70, 80, 106, 109, 113, 135, 132, 112, 96, 81, 99, 104, 104, 95, 97, 134, 168, 202, 219, 214, 232, 239, 244, 243, 241, 235, 214, 167, 183, 197, 191, 190, 206, 207, 208, 192, 175, 194, 209, 206, 201, 210, 213, 213, 202, 180, 197, 205, 206, 209, 206, 207, 211, 212, 208, 198, 195, 189, 177, 181, 196, 202, 200, 193, 187, 187, 195, 207, 205, 193, 185, 189, 196, 202, 203, 199, 194, 194, 197, 198, 195, 187, 181, 180, 184, 189, 195, 201, 208, 215, 220, 221, 219, 217, 216, 215, 212, 211, 212, 214, 216, 216, 214, 212, 210, 210, 209, 208, 206, 206, 206, 208, 213, 218, 223, 228, 229, 229, 229, 229, 229, 230, 230, 231, 232, 232, 232, 231, 230, 231, 230, 231, 231, 231, 233, 236, 237, 239, 239, 238, 237, 236, 234, 233, 232, 232, 231, 231, 231, 231, 231, 232, 234, 237, 237, 237, 237, 237, 238, 239, 239, 239, 239, 238, 237, 237, 236, 235, 236, 237, 237, 238, 239, 239, 239, 238, 237, 237, 230, 206, 170, 132, 99, 79, 77, 77, 77, 77, 77, 77, 78, 78, 79, 80, 81, 82, 83, 83, 84, 85, 86, 86, 87, 88, 89, 89, 90, 91, 92, 92, 93, 94, 94, 95, 95, 96, 92, 88, 82, 81, 81, 82, 82, 82, 82, 82, 82, 82, 86, 94, 97, 99, 98, 98, 99, 99, 97, 96, 96, 101, 108, 113, 88, 23, 21, 36, 42, 42, 42, 43, 44, 39, 35, 35, 33, 31, 33, 30, 22, 28, 36, 44, 43, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 42, 55, 92, 102, 106, 87, 55, 74, 123, 123, 117, 81, 50, 67, 107, 142, 192, 131, 73, 75, 100, 110, 113, 130, 121, 105, 92, 76, 90, 102, 99, 94, 89, 126, 154, 200, 233, 217, 215, 216, 225, 222, 212, 235, 225, 166, 199, 205, 206, 209, 208, 209, 210, 212, 212, 213, 211, 209, 211, 213, 213, 213, 212, 216, 218, 217, 217, 216, 216, 216, 218, 220, 215, 209, 207, 196, 194, 208, 215, 215, 209, 203, 202, 204, 208, 206, 197, 191, 196, 204, 213, 216, 214, 209, 208, 212, 216, 214, 205, 197, 194, 198, 205, 211, 214, 218, 224, 229, 230, 228, 225, 223, 221, 219, 218, 219, 221, 222, 220, 219, 217, 215, 211, 208, 206, 205, 205, 205, 206, 211, 218, 223, 226, 227, 227, 228, 228, 229, 230, 231, 231, 231, 231, 230, 229, 230, 230, 231, 231, 231, 232, 234, 237, 239, 240, 240, 239, 237, 235, 233, 231, 230, 229, 229, 229, 230, 231, 232, 235, 237, 237, 237, 237, 237, 238, 239, 239, 239, 239, 237, 237, 236, 235, 236, 237, 237, 238, 239, 239, 239, 239, 238, 237, 235, 230, 206, 171, 133, 99, 79, 76, 77, 76, 77, 77, 77, 77, 77, 78, 79, 80, 81, 81, 82, 83, 83, 84, 85, 86, 87, 87, 88, 89, 90, 90, 91, 92, 92, 93, 94, 95, 95, 96, 86, 82, 80, 80, 79, 78, 78, 77, 77, 77, 77, 86, 93, 97, 105, 94, 93, 92, 92, 96, 89, 81, 84, 101, 110, 103, 30, 21, 35, 40, 39, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 44, 41, 33, 30, 39, 42, 42, 42, 42, 42, 42, 42, 42, 43, 42, 44, 74, 99, 104, 106, 95, 62, 40, 123, 127, 128, 96, 74, 25, 77, 112, 122, 171, 141, 72, 69, 91, 108, 109, 123, 113, 98, 89, 75, 82, 99, 95, 93, 84, 122, 144, 205, 233, 235, 236, 232, 236, 238, 237, 234, 217, 177, 207, 208, 209, 209, 209, 210, 212, 213, 213, 212, 210, 211, 212, 213, 214, 215, 218, 218, 218, 218, 217, 216, 217, 219, 222, 218, 213, 213, 203, 199, 216, 220, 222, 219, 214, 212, 210, 209, 209, 205, 204, 207, 212, 217, 225, 228, 225, 224, 228, 233, 232, 224, 217, 216, 221, 225, 226, 226, 228, 233, 238, 239, 237, 234, 232, 231, 229, 229, 230, 230, 230, 229, 228, 225, 221, 218, 214, 211, 209, 206, 204, 206, 212, 218, 222, 225, 226, 226, 227, 228, 229, 230, 231, 230, 230, 229, 229, 229, 229, 229, 231, 231, 231, 233, 236, 238, 239, 240, 240, 238, 236, 235, 233, 231, 229, 229, 229, 230, 231, 233, 236, 237, 237, 237, 237, 237, 238, 238, 239, 238, 238, 236, 236, 235, 236, 237, 237, 238, 239, 239, 239, 239, 238, 237, 237, 234, 229, 207, 172, 133, 99, 78, 76, 76, 75, 75, 75, 76, 77, 76, 77, 78, 79, 80, 80, 81, 82, 82, 83, 84, 85, 85, 86, 87, 88, 88, 89, 90, 91, 91, 92, 93, 93, 94, 95, 95, 77, 76, 75, 82, 81, 72, 73, 75, 83, 93, 90, 103, 107, 102, 113, 106, 104, 108, 106, 110, 101, 77, 87, 101, 103, 46, 23, 25, 30, 29, 43, 44, 44, 44, 44, 44, 42, 33, 30, 34, 40, 44, 44, 42, 42, 42, 39, 39, 41, 42, 42, 42, 42, 42, 42, 43, 42, 52, 90, 102, 105, 106, 103, 66, 45, 107, 130, 130, 121, 83, 45, 27, 90, 125, 127, 158, 133, 55, 65, 81, 106, 107, 116, 106, 94, 88, 76, 76, 95, 93, 91, 81, 116, 143, 211, 233, 236, 237, 237, 238, 238, 236, 233, 204, 190, 205, 207, 209, 208, 209, 210, 212, 213, 211, 210, 210, 211, 205, 208, 214, 218, 218, 218, 217, 216, 216, 216, 218, 221, 218, 214, 214, 210, 206, 218, 223, 224, 222, 220, 218, 216, 215, 217, 218, 219, 218, 217, 219, 226, 232, 232, 232, 234, 236, 237, 235, 232, 233, 236, 238, 238, 237, 237, 239, 242, 243, 243, 241, 240, 239, 238, 238, 237, 238, 239, 238, 236, 234, 231, 228, 225, 224, 221, 216, 213, 214, 218, 222, 224, 225, 226, 227, 229, 229, 230, 230, 230, 229, 228, 229, 229, 229, 229, 229, 230, 231, 232, 235, 237, 239, 240, 239, 238, 237, 235, 233, 231, 230, 230, 229, 230, 232, 235, 237, 238, 238, 237, 237, 237, 237, 238, 238, 238, 236, 236, 235, 236, 236, 237, 238, 239, 240, 240, 239, 239, 238, 237, 236, 234, 228, 207, 172, 134, 100, 78, 75, 75, 75, 75, 75, 75, 75, 75, 76, 77, 77, 78, 79, 80, 81, 82, 82, 83, 83, 84, 85, 86, 87, 87, 88, 89, 89, 90, 91, 92, 92, 93, 94, 94, 95, 68, 71, 77, 97, 102, 83, 82, 98, 106, 112, 112, 112, 111, 107, 113, 112, 112, 115, 114, 111, 107, 96, 101, 101, 72, 22, 22, 20, 25, 42, 44, 44, 44, 44, 44, 42, 32, 20, 21, 33, 43, 44, 44, 42, 42, 42, 42, 43, 39, 37, 42, 42, 42, 45, 44, 43, 43, 68, 97, 103, 106, 106, 106, 76, 54, 76, 133, 132, 132, 93, 72, 30, 29, 100, 135, 138, 144, 113, 33, 53, 71, 101, 103, 111, 102, 92, 88, 77, 73, 92, 91, 88, 80, 108, 147, 218, 233, 236, 237, 237, 237, 237, 236, 232, 195, 193, 204, 207, 208, 208, 209, 210, 209, 207, 205, 207, 207, 199, 204, 211, 217, 217, 217, 216, 216, 215, 216, 218, 219, 218, 213, 214, 216, 218, 222, 224, 224, 223, 221, 221, 221, 221, 222, 224, 225, 225, 223, 222, 226, 231, 232, 232, 233, 236, 237, 237, 237, 238, 240, 241, 241, 241, 240, 240, 241, 243, 244, 244, 244, 243, 242, 242, 242, 242, 243, 243, 241, 239, 239, 238, 237, 237, 236, 231, 228, 227, 230, 232, 231, 231, 232, 233, 234, 233, 231, 230, 229, 229, 230, 230, 229, 230, 231, 231, 231, 232, 235, 237, 239, 239, 239, 238, 237, 235, 232, 230, 230, 230, 230, 232, 234, 236, 237, 238, 238, 238, 237, 237, 237, 238, 237, 237, 236, 235, 236, 236, 237, 238, 239, 239, 240, 240, 239, 238, 237, 236, 235, 232, 229, 211, 176, 137, 100, 78, 73, 74, 74, 75, 75, 75, 75, 75, 75, 75, 76, 77, 78, 79, 79, 80, 81, 82, 82, 83, 84, 85, 85, 86, 87, 88, 88, 89, 89, 90, 91, 92, 93, 93, 94, 95, 82, 95, 92, 109, 111, 105, 106, 112, 113, 114, 114, 115, 115, 114, 113, 111, 111, 114, 112, 106, 100, 100, 102, 95, 29, 22, 19, 25, 42, 44, 44, 44, 44, 44, 44, 35, 23, 23, 32, 42, 44, 44, 44, 42, 42, 42, 42, 42, 43, 37, 30, 41, 43, 48, 44, 46, 47, 83, 100, 104, 106, 106, 106, 89, 61, 46, 124, 133, 133, 120, 79, 43, 52, 42, 104, 140, 140, 141, 100, 26, 38, 60, 95, 100, 107, 99, 90, 86, 77, 70, 82, 83, 86, 78, 102, 150, 217, 233, 236, 237, 237, 237, 237, 234, 231, 186, 203, 205, 207, 207, 207, 206, 205, 201, 196, 196, 198, 192, 192, 202, 213, 215, 215, 215, 215, 215, 216, 216, 217, 214, 210, 213, 219, 223, 224, 224, 224, 224, 221, 221, 223, 224, 224, 226, 228, 229, 228, 227, 228, 230, 231, 229, 230, 233, 236, 237, 237, 237, 238, 239, 240, 240, 239, 239, 239, 240, 242, 242, 244, 243, 242, 241, 242, 243, 244, 243, 243, 242, 243, 243, 245, 247, 247, 244, 241, 241, 243, 242, 241, 240, 241, 241, 241, 239, 237, 234, 234, 234, 235, 235, 235, 235, 236, 236, 237, 237, 237, 239, 240, 240, 239, 237, 235, 231, 230, 229, 229, 230, 233, 235, 236, 238, 238, 238, 238, 237, 237, 237, 237, 237, 237, 236, 236, 236, 237, 238, 239, 239, 240, 240, 239, 238, 237, 236, 235, 233, 231, 229, 217, 184, 143, 104, 78, 73, 73, 74, 73, 73, 73, 74, 75, 75, 75, 75, 76, 77, 77, 78, 79, 80, 81, 81, 82, 83, 84, 84, 85, 86, 86, 87, 88, 88, 89, 89, 90, 91, 92, 93, 94, 94, 108, 110, 104, 110, 113, 111, 109, 113, 114, 114, 114, 114, 115, 115, 113, 109, 106, 109, 102, 60, 43, 95, 102, 64, 22, 22, 19, 39, 44, 44, 44, 44, 44, 44, 42, 33, 32, 39, 44, 44, 44, 44, 42, 42, 42, 42, 42, 42, 42, 42, 38, 28, 41, 43, 44, 37, 50, 71, 75, 83, 92, 103, 106, 101, 64, 50, 99, 134, 134, 134, 92, 69, 52, 64, 57, 101, 140, 141, 140, 92, 25, 28, 48, 85, 95, 104, 95, 90, 82, 76, 66, 72, 72, 83, 79, 98, 144, 220, 233, 236, 236, 237, 237, 236, 233, 227, 183, 204, 205, 205, 205, 203, 200, 194, 192, 191, 191, 190, 191, 193, 204, 211, 212, 213, 214, 214, 214, 214, 212, 206, 206, 210, 220, 225, 226, 226, 226, 224, 221, 221, 225, 227, 228, 229, 230, 231, 232, 230, 230, 230, 230, 227, 227, 230, 234, 235, 236, 234, 233, 235, 237, 238, 238, 238, 239, 238, 239, 239, 239, 241, 241, 241, 241, 242, 243, 243, 243, 243, 244, 245, 246, 249, 250, 249, 249, 249, 250, 249, 248, 248, 248, 249, 248, 246, 243, 242, 242, 243, 243, 244, 243, 243, 244, 244, 243, 242, 242, 242, 242, 241, 239, 236, 232, 230, 229, 230, 231, 233, 236, 237, 238, 238, 238, 238, 237, 237, 237, 237, 237, 237, 236, 236, 236, 238, 239, 239, 240, 240, 239, 238, 237, 236, 235, 234, 232, 230, 229, 223, 195, 154, 113, 81, 72, 73, 73, 73, 73, 73, 73, 73, 74, 75, 75, 75, 75, 76, 77, 78, 79, 79, 80, 81, 82, 82, 83, 84, 85, 85, 86, 87, 87, 88, 87, 87, 88, 90, 92, 93, 93, 94, 113, 113, 109, 110, 114, 113, 110, 114, 115, 115, 112, 107, 111, 112, 109, 106, 103, 98, 56, 71, 57, 79, 89, 23, 23, 22, 21, 41, 44, 44, 44, 44, 43, 38, 37, 42, 44, 43, 44, 44, 44, 44, 42, 42, 42, 42, 42, 42, 42, 42, 42, 40, 27, 39, 43, 45, 46, 53, 67, 68, 67, 69, 83, 97, 74, 55, 60, 135, 135, 136, 123, 80, 63, 62, 64, 64, 91, 139, 142, 141, 82, 24, 26, 39, 70, 90, 101, 93, 89, 79, 75, 64, 64, 65, 81, 79, 93, 155, 228, 233, 235, 237, 237, 237, 235, 232, 218, 171, 198, 203, 203, 201, 199, 197, 193, 193, 194, 195, 194, 195, 200, 207, 211, 212, 212, 212, 213, 211, 207, 200, 199, 203, 218, 225, 226, 226, 226, 225, 223, 223, 227, 229, 228, 229, 230, 231, 232, 232, 230, 228, 229, 228, 227, 228, 231, 232, 231, 230, 228, 230, 231, 232, 232, 232, 233, 233, 231, 231, 231, 234, 237, 238, 239, 240, 241, 241, 241, 242, 244, 245, 246, 249, 250, 250, 250, 250, 252, 251, 252, 252, 252, 252, 252, 251, 250, 250, 250, 251, 251, 251, 250, 250, 251, 251, 249, 247, 246, 245, 245, 244, 242, 238, 235, 233, 233, 234, 236, 237, 238, 239, 239, 239, 238, 238, 237, 238, 238, 237, 237, 236, 236, 237, 238, 238, 239, 239, 238, 237, 236, 235, 234, 233, 232, 230, 229, 228, 226, 206, 168, 126, 89, 72, 71, 72, 73, 73, 73, 73, 73, 73, 73, 73, 75, 75, 75, 76, 76, 77, 78, 79, 80, 81, 81, 82, 82, 83, 84, 85, 86, 86, 87, 87, 86, 86, 87, 90, 91, 92, 93, 93, 114, 114, 113, 113, 114, 113, 111, 114, 115, 115, 112, 103, 105, 106, 103, 102, 102, 74, 97, 102, 96, 68, 46, 22, 23, 24, 27, 40, 42, 39, 43, 44, 43, 40, 37, 38, 44, 44, 44, 44, 44, 43, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 40, 26, 38, 51, 61, 48, 49, 65, 64, 61, 63, 65, 65, 56, 49, 114, 138, 138, 136, 99, 51, 61, 61, 64, 64, 82, 135, 144, 138, 67, 24, 25, 32, 60, 85, 98, 91, 89, 77, 74, 62, 60, 62, 79, 77, 90, 145, 220, 232, 235, 237, 236, 236, 233, 232, 204, 192, 194, 188, 200, 202, 201, 196, 195, 196, 197, 197, 198, 201, 204, 209, 211, 209, 211, 213, 211, 207, 204, 201, 199, 213, 224, 226, 226, 226, 226, 226, 225, 228, 229, 229, 228, 227, 228, 227, 227, 225, 223, 220, 219, 218, 216, 214, 212, 209, 207, 208, 211, 215, 217, 219, 219, 220, 221, 221, 219, 221, 223, 227, 229, 229, 230, 231, 231, 232, 233, 235, 237, 240, 245, 248, 249, 249, 249, 250, 252, 251, 252, 252, 252, 252, 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 252, 251, 251, 250, 250, 249, 247, 244, 242, 240, 241, 241, 242, 243, 243, 243, 242, 240, 239, 240, 240, 240, 239, 238, 236, 236, 237, 237, 238, 238, 237, 236, 236, 234, 233, 231, 231, 230, 229, 229, 228, 228, 216, 182, 140, 99, 74, 72, 71, 72, 73, 73, 73, 73, 73, 73, 74, 74, 75, 75, 75, 75, 76, 77, 78, 79, 79, 80, 81, 82, 82, 83, 84, 84, 85, 86, 86, 87, 85, 85, 87, 89, 91, 92, 92, 93, 114, 114, 114, 114, 114, 112, 111, 113, 114, 114, 113, 106, 107, 107, 107, 104, 98, 94, 102, 102, 103, 41, 22, 22, 23, 24, 23, 39, 44, 42, 34, 36, 43, 44, 44, 44, 44, 43, 42, 41, 42, 42, 42, 42, 42, 42, 42, 41, 41, 41, 42, 43, 44, 36, 24, 47, 61, 62, 44, 49, 64, 64, 59, 60, 59, 55, 49, 65, 107, 86, 56, 50, 54, 76, 45, 58, 65, 64, 71, 125, 145, 137, 56, 24, 24, 28, 49, 78, 94, 90, 87, 75, 73, 60, 59, 60, 77, 77, 87, 115, 197, 232, 234, 236, 237, 235, 232, 231, 189, 198, 212, 203, 197, 191, 195, 198, 198, 198, 200, 203, 201, 204, 208, 205, 200, 204, 214, 213, 211, 211, 208, 204, 212, 222, 222, 220, 220, 219, 217, 217, 216, 215, 209, 201, 197, 193, 191, 190, 190, 186, 184, 190, 192, 182, 178, 177, 171, 173, 175, 177, 182, 187, 193, 198, 202, 204, 206, 207, 210, 214, 217, 219, 221, 222, 222, 222, 222, 222, 223, 223, 226, 231, 238, 242, 245, 247, 249, 251, 252, 252, 251, 252, 252, 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, 252, 251, 250, 249, 248, 248, 248, 248, 248, 249, 248, 246, 244, 244, 244, 245, 245, 242, 239, 237, 236, 237, 236, 236, 235, 234, 233, 231, 230, 230, 229, 228, 227, 228, 228, 228, 223, 194, 153, 111, 79, 71, 72, 72, 73, 73, 74, 74, 74, 74, 74, 74, 75, 75, 75, 75, 76, 76, 77, 78, 78, 79, 80, 80, 81, 82, 82, 83, 84, 85, 85, 86, 86, 84, 84, 85, 89, 90, 91, 92, 93, 113, 114, 114, 113, 112, 111, 109, 112, 113, 114, 113, 108, 107, 108, 108, 107, 92, 102, 105, 103, 105, 42, 23, 23, 23, 22, 35, 40, 44, 44, 42, 33, 27, 39, 44, 44, 44, 44, 44, 44, 41, 38, 37, 41, 41, 41, 41, 41, 41, 42, 42, 44, 44, 44, 37, 26, 60, 69, 61, 42, 54, 63, 62, 56, 56, 55, 50, 49, 49, 49, 50, 55, 64, 96, 95, 51, 58, 66, 64, 64, 107, 143, 130, 43, 23, 23, 25, 33, 70, 91, 90, 86, 73, 72, 60, 59, 60, 75, 77, 83, 112, 159, 223, 233, 235, 236, 233, 232, 227, 176, 188, 188, 193, 198, 194, 195, 196, 199, 195, 191, 191, 194, 195, 193, 190, 191, 204, 202, 199, 197, 194, 185, 180, 179, 179, 184, 199, 205, 208, 211, 212, 213, 210, 205, 202, 199, 198, 195, 192, 187, 184, 191, 193, 177, 173, 175, 172, 171, 165, 153, 150, 154, 162, 171, 180, 190, 198, 202, 204, 206, 209, 213, 217, 218, 218, 217, 215, 214, 213, 214, 214, 217, 222, 228, 232, 238, 245, 249, 250, 252, 252, 252, 251, 251, 251, 251, 249, 250, 252, 253, 253, 254, 254, 253, 253, 253, 253, 253, 253, 253, 252, 252, 252, 252, 252, 252, 252, 252, 252, 251, 251, 250, 249, 249, 250, 249, 246, 242, 239, 237, 237, 237, 236, 233, 231, 229, 228, 228, 228, 227, 226, 226, 227, 228, 228, 206, 166, 123, 86, 72, 72, 72, 73, 73, 74, 74, 74, 74, 75, 75, 75, 75, 75, 75, 76, 76, 76, 77, 78, 78, 79, 79, 80, 81, 81, 82, 82, 84, 84, 85, 86, 85, 82, 82, 84, 88, 90, 91, 91, 92, 109, 112, 113, 113, 113, 110, 105, 112, 113, 114, 113, 111, 108, 109, 109, 105, 97, 104, 111, 114, 102, 22, 23, 23, 24, 24, 43, 43, 43, 42, 37, 33, 34, 22, 35, 43, 43, 44, 43, 42, 42, 41, 41, 37, 36, 40, 41, 41, 42, 42, 43, 44, 44, 41, 46, 49, 29, 81, 78, 61, 44, 65, 63, 62, 54, 55, 53, 50, 50, 50, 50, 51, 61, 98, 106, 102, 65, 55, 68, 64, 64, 83, 130, 123, 34, 22, 22, 22, 28, 65, 88, 91, 86, 73, 72, 60, 59, 60, 75, 78, 89, 119, 132, 204, 233, 234, 234, 233, 231, 218, 170, 198, 201, 201, 194, 178, 186, 189, 190, 189, 188, 186, 183, 173, 172, 174, 181, 176, 179, 188, 196, 201, 206, 213, 221, 223, 225, 225, 226, 226, 226, 227, 229, 229, 229, 229, 227, 224, 223, 222, 219, 217, 216, 210, 208, 209, 206, 204, 192, 170, 153, 145, 144, 147, 156, 167, 179, 191, 201, 205, 207, 211, 215, 221, 224, 225, 223, 222, 219, 216, 212, 211, 213, 217, 222, 228, 234, 242, 248, 251, 252, 251, 251, 251, 251, 248, 247, 248, 251, 253, 253, 254, 254, 254, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, 252, 252, 252, 252, 252, 250, 247, 245, 243, 242, 241, 237, 234, 231, 229, 228, 227, 227, 226, 226, 226, 227, 228, 214, 178, 135, 95, 73, 72, 73, 73, 74, 74, 74, 75, 75, 75, 75, 75, 75, 75, 76, 76, 76, 76, 77, 77, 78, 78, 79, 79, 80, 80, 81, 81, 82, 83, 84, 84, 85, 83, 79, 79, 82, 87, 89, 90, 91, 92, 102, 106, 110, 111, 112, 111, 109, 110, 113, 113, 113, 113, 111, 109, 109, 97, 106, 109, 115, 115, 79, 22, 24, 24, 24, 25, 43, 43, 43, 31, 33, 37, 43, 38, 20, 30, 38, 41, 42, 42, 41, 41, 41, 41, 41, 37, 36, 41, 42, 42, 43, 43, 37, 42, 56, 60, 49, 82, 122, 85, 60, 50, 79, 63, 61, 51, 57, 54, 52, 51, 51, 51, 51, 74, 103, 106, 105, 79, 52, 73, 64, 64, 66, 117, 113, 29, 22, 22, 20, 28, 63, 88, 93, 86, 72, 73, 61, 59, 61, 75, 79, 153, 133, 155, 196, 210, 233, 232, 232, 230, 195, 145, 171, 194, 201, 200, 201, 202, 204, 205, 203, 201, 203, 193, 193, 194, 205, 208, 212, 216, 218, 216, 217, 221, 225, 224, 225, 226, 226, 227, 227, 228, 229, 229, 230, 227, 225, 225, 225, 226, 225, 224, 225, 228, 226, 223, 222, 219, 216, 209, 192, 179, 164, 152, 148, 151, 159, 172, 187, 198, 206, 211, 213, 217, 224, 232, 233, 233, 233, 232, 228, 223, 220, 220, 221, 223, 227, 232, 239, 247, 251, 252, 252, 252, 250, 247, 246, 246, 250, 252, 253, 253, 253, 254, 254, 254, 254, 254, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, 251, 249, 248, 247, 245, 242, 240, 237, 234, 231, 228, 228, 228, 228, 228, 230, 221, 188, 146, 105, 77, 72, 73, 74, 74, 74, 74, 75, 75, 75, 75, 76, 76, 76, 76, 76, 76, 76, 77, 77, 77, 78, 78, 79, 79, 79, 80, 80, 81, 81, 82, 83, 84, 85, 82, 78, 78, 81, 87, 88, 89, 90, 91, 101, 103, 107, 110, 111, 112, 112, 111, 112, 112, 112, 113, 112, 110, 109, 98, 108, 112, 115, 121, 46, 22, 24, 24, 26, 24, 43, 40, 32, 19, 20, 34, 37, 43, 40, 67, 129, 122, 104, 64, 39, 41, 41, 41, 41, 41, 40, 36, 40, 43, 41, 35, 44, 49, 57, 61, 62, 46, 125, 135, 89, 57, 70, 86, 65, 61, 52, 61, 58, 53, 51, 51, 51, 50, 65, 100, 106, 106, 91, 53, 81, 66, 64, 64, 100, 78, 28, 22, 22, 21, 26, 60, 89, 96, 85, 73, 77, 65, 59, 62, 79, 93, 208, 171, 170, 206, 195, 201, 216, 231, 229, 163, 157, 152, 162, 184, 199, 202, 202, 203, 202, 202, 205, 207, 209, 209, 212, 212, 215, 215, 215, 210, 217, 223, 226, 226, 225, 226, 226, 227, 227, 229, 229, 230, 230, 225, 222, 224, 225, 226, 225, 224, 224, 227, 227, 224, 223, 220, 221, 225, 223, 213, 202, 189, 179, 167, 155, 153, 166, 182, 197, 206, 212, 215, 221, 230, 239, 241, 241, 241, 239, 237, 235, 235, 232, 228, 227, 230, 235, 239, 244, 247, 250, 250, 249, 246, 245, 246, 249, 253, 253, 253, 253, 253, 254, 254, 254, 254, 254, 253, 253, 253, 253, 253, 254, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, 251, 251, 249, 248, 245, 244, 241, 238, 235, 234, 234, 234, 232, 227, 199, 158, 116, 83, 73, 73, 74, 75, 75, 75, 75, 76, 76, 76, 76, 77, 76, 77, 77, 77, 77, 77, 77, 77, 77, 78, 79, 79, 79, 79, 79, 79, 80, 80, 81, 82, 83, 84, 82, 78, 77, 80, 85, 86, 86, 88, 90, 105, 108, 109, 111, 111, 112, 112, 111, 111, 111, 111, 112, 110, 107, 106, 100, 113, 114, 114, 118, 19, 21, 24, 25, 26, 23, 41, 33, 19, 19, 18, 29, 42, 38, 41, 42, 114, 143, 143, 143, 123, 81, 40, 40, 41, 41, 42, 42, 38, 35, 35, 42, 46, 56, 59, 66, 70, 64, 51, 170, 141, 91, 85, 103, 90, 70, 58, 59, 67, 61, 54, 52, 51, 51, 50, 59, 97, 106, 106, 92, 51, 88, 72, 64, 64, 57, 52, 30, 22, 21, 22, 25, 61, 93, 100, 82, 76, 82, 74, 61, 68, 85, 131, 227, 212, 193, 210, 215, 204, 189, 211, 224, 174, 198, 193, 184, 179, 186, 188, 190, 194, 200, 205, 208, 206, 210, 214, 215, 214, 214, 213, 215, 219, 222, 225, 227, 226, 225, 226, 226, 227, 227, 228, 229, 230, 227, 221, 224, 225, 225, 225, 223, 222, 226, 227, 225, 224, 222, 222, 226, 228, 225, 221, 217, 211, 201, 182, 161, 152, 162, 178, 193, 202, 208, 215, 223, 233, 242, 242, 243, 244, 244, 245, 245, 244, 241, 235, 233, 235, 238, 240, 242, 244, 246, 249, 246, 245, 246, 249, 252, 253, 253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, 252, 251, 250, 250, 251, 249, 245, 243, 242, 242, 240, 235, 213, 173, 128, 91, 74, 74, 74, 75, 75, 76, 76, 76, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 78, 78, 79, 78, 78, 78, 78, 79, 79, 80, 80, 82, 83, 81, 77, 76, 79, 83, 83, 84, 87, 89, 111, 111, 111, 112, 112, 112, 111, 110, 107, 108, 109, 111, 110, 103, 99, 101, 114, 114, 115, 94, 20, 21, 25, 25, 27, 23, 38, 36, 18, 19, 22, 33, 43, 43, 39, 38, 43, 117, 143, 143, 143, 143, 129, 85, 42, 42, 42, 42, 40, 35, 36, 45, 44, 61, 73, 72, 77, 85, 71, 120, 183, 142, 91, 137, 111, 95, 75, 56, 73, 75, 65, 56, 53, 52, 51, 50, 55, 93, 106, 106, 97, 55, 83, 80, 65, 64, 63, 59, 32, 22, 20, 24, 25, 63, 97, 102, 76, 82, 88, 83, 64, 77, 86, 175, 231, 231, 212, 198, 209, 215, 188, 230, 209, 181, 197, 197, 198, 198, 199, 200, 196, 191, 192, 198, 195, 194, 206, 212, 214, 214, 216, 216, 219, 220, 225, 226, 226, 225, 225, 226, 227, 227, 227, 228, 228, 225, 223, 225, 226, 225, 224, 222, 221, 223, 225, 225, 225, 224, 224, 226, 228, 227, 225, 223, 219, 216, 205, 182, 158, 152, 160, 173, 186, 197, 203, 214, 224, 234, 242, 242, 243, 243, 246, 246, 247, 246, 245, 243, 241, 239, 240, 240, 240, 240, 243, 246, 247, 249, 250, 252, 252, 252, 253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, 252, 253, 253, 252, 251, 250, 250, 249, 244, 227, 188, 143, 101, 76, 74, 75, 76, 76, 76, 77, 77, 77, 77, 77, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 77, 77, 77, 77, 77, 77, 77, 77, 77, 79, 80, 79, 76, 74, 77, 81, 82, 83, 86, 89, 113, 113, 112, 112, 113, 112, 110, 108, 105, 104, 110, 112, 111, 102, 93, 105, 115, 115, 116, 69, 20, 21, 25, 26, 27, 24, 34, 35, 20, 20, 25, 31, 43, 43, 42, 40, 36, 45, 125, 143, 143, 143, 142, 143, 126, 78, 43, 41, 36, 43, 41, 60, 74, 57, 72, 94, 95, 93, 99, 84, 175, 183, 130, 127, 168, 121, 98, 79, 101, 86, 83, 68, 56, 55, 53, 52, 50, 53, 89, 106, 106, 101, 55, 68, 84, 67, 64, 91, 62, 36, 23, 19, 24, 25, 66, 101, 100, 70, 89, 94, 87, 63, 84, 92, 210, 231, 231, 232, 211, 195, 183, 217, 229, 188, 191, 197, 197, 194, 194, 194, 195, 196, 200, 204, 204, 201, 203, 197, 203, 204, 212, 217, 218, 217, 223, 224, 224, 224, 224, 225, 226, 226, 226, 227, 227, 226, 226, 227, 227, 226, 225, 223, 222, 223, 224, 224, 224, 224, 226, 227, 229, 230, 228, 225, 222, 220, 216, 198, 166, 147, 151, 157, 163, 174, 187, 197, 212, 225, 237, 241, 242, 242, 244, 246, 247, 247, 246, 246, 246, 246, 244, 241, 239, 238, 239, 243, 249, 250, 251, 251, 252, 252, 252, 252, 252, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, 252, 252, 252, 241, 206, 158, 114, 81, 75, 76, 76, 77, 77, 77, 77, 78, 78, 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 78, 78, 77, 76, 76, 76, 76, 75, 74, 73, 73, 73, 74, 74, 71, 71, 73, 77, 80, 82, 86, 88, 113, 113, 113, 113, 113, 113, 110, 105, 103, 103, 114, 117, 115, 103, 94, 111, 120, 117, 111, 36, 21, 22, 25, 26, 26, 26, 30, 33, 25, 20, 26, 31, 42, 43, 43, 42, 41, 35, 53, 133, 143, 143, 144, 143, 143, 142, 116, 44, 45, 46, 45, 43, 88, 115, 65, 85, 112, 115, 108, 108, 112, 111, 156, 152, 181, 167, 132, 98, 91, 134, 99, 90, 71, 55, 58, 55, 52, 51, 53, 85, 105, 106, 100, 70, 62, 75, 72, 119, 104, 63, 38, 22, 19, 23, 26, 70, 103, 93, 69, 97, 98, 77, 64, 93, 126, 227, 231, 232, 232, 230, 210, 195, 229, 227, 175, 196, 195, 195, 194, 193, 195, 201, 203, 206, 207, 207, 206, 209, 212, 211, 193, 200, 205, 215, 217, 220, 219, 219, 224, 224, 225, 226, 226, 226, 227, 227, 227, 229, 229, 228, 227, 227, 227, 225, 225, 225, 226, 226, 227, 228, 229, 230, 230, 229, 226, 224, 221, 213, 186, 157, 145, 147, 150, 150, 160, 176, 192, 214, 230, 239, 240, 240, 242, 244, 246, 246, 246, 247, 248, 248, 248, 246, 241, 238, 238, 241, 247, 250, 251, 251, 251, 251, 252, 251, 252, 252, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 253, 253, 254, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, 252, 249, 223, 177, 128, 89, 76, 76, 77, 77, 77, 78, 78, 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 78, 77, 76, 76, 74, 74, 73, 71, 69, 67, 66, 65, 65, 62, 63, 66, 72, 78, 81, 85, 86, 111, 112, 113, 113, 113, 113, 108, 101, 101, 107, 115, 117, 115, 105, 99, 118, 127, 115, 116, 17, 20, 21, 25, 26, 26, 26, 24, 34, 27, 20, 26, 35, 41, 43, 43, 42, 41, 41, 35, 70, 140, 144, 144, 148, 146, 144, 120, 138, 94, 48, 56, 63, 65, 107, 141, 78, 109, 120, 98, 36, 49, 158, 203, 218, 197, 190, 176, 129, 100, 115, 150, 105, 96, 76, 55, 61, 56, 53, 52, 55, 84, 104, 106, 99, 86, 78, 56, 70, 172, 74, 64, 39, 22, 21, 23, 28, 74, 105, 82, 73, 102, 95, 67, 69, 99, 173, 230, 231, 232, 232, 230, 229, 229, 228, 215, 176, 198, 198, 197, 198, 200, 204, 205, 206, 207, 208, 210, 212, 215, 215, 204, 201, 212, 202, 200, 210, 208, 211, 222, 223, 224, 224, 224, 225, 226, 226, 226, 227, 228, 228, 228, 229, 229, 227, 225, 225, 225, 226, 228, 228, 229, 230, 231, 231, 230, 227, 224, 221, 210, 182, 149, 137, 140, 139, 139, 152, 169, 196, 221, 237, 239, 239, 240, 241, 243, 245, 246, 247, 247, 246, 246, 246, 245, 240, 239, 241, 246, 250, 251, 252, 251, 252, 251, 251, 251, 252, 253, 254, 254, 254, 254, 254, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, 237, 196, 146, 100, 77, 77, 77, 77, 78, 78, 78, 79, 79, 79, 79, 79, 79, 80, 80, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 78, 77, 76, 75, 73, 72, 70, 68, 65, 62, 57, 54, 54, 51, 52, 55, 62, 69, 74, 78, 81, 111, 112, 112, 112, 113, 113, 109, 101, 101, 107, 112, 122, 124, 125, 106, 124, 119, 130, 95, 20, 18, 21, 24, 25, 26, 26, 19, 36, 26, 21, 23, 39, 43, 43, 43, 43, 41, 41, 41, 34, 94, 143, 143, 146, 150, 137, 138, 144, 142, 115, 59, 87, 105, 99, 136, 152, 97, 76, 39, 42, 71, 104, 198, 245, 208, 215, 196, 174, 129, 101, 144, 150, 110, 103, 82, 58, 63, 57, 55, 53, 57, 81, 101, 105, 96, 89, 97, 63, 130, 172, 65, 64, 37, 20, 23, 24, 30, 80, 103, 69, 81, 105, 79, 65, 73, 102, 210, 230, 231, 232, 230, 229, 229, 228, 228, 194, 189, 197, 198, 201, 202, 206, 207, 208, 208, 210, 213, 214, 215, 214, 213, 215, 215, 215, 210, 195, 188, 204, 219, 221, 222, 221, 223, 224, 225, 225, 225, 226, 227, 228, 229, 229, 229, 228, 225, 225, 225, 225, 227, 228, 228, 229, 230, 231, 231, 229, 227, 223, 219, 201, 160, 133, 133, 134, 134, 136, 149, 177, 212, 235, 240, 240, 240, 241, 241, 243, 244, 245, 245, 244, 243, 243, 243, 243, 240, 241, 246, 249, 251, 251, 251, 251, 252, 250, 250, 252, 253, 254, 254, 254, 254, 253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 253, 246, 213, 163, 115, 82, 77, 77, 78, 78, 78, 79, 79, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, 80, 80, 80, 80, 80, 80, 79, 79, 78, 76, 75, 74, 72, 70, 69, 65, 60, 55, 49, 45, 42, 41, 41, 44, 50, 55, 59, 63, 67, 111, 111, 112, 112, 112, 112, 112, 105, 106, 113, 136, 136, 134, 105, 109, 124, 125, 137, 73, 20, 19, 21, 23, 24, 24, 26, 21, 31, 31, 24, 21, 37, 43, 43, 43, 42, 41, 41, 41, 41, 34, 119, 143, 144, 147, 125, 150, 151, 149, 144, 135, 94, 118, 125, 122, 159, 79, 42, 43, 73, 80, 87, 88, 212, 217, 231, 208, 207, 167, 126, 97, 171, 151, 117, 108, 85, 61, 65, 58, 56, 54, 56, 72, 90, 98, 94, 92, 106, 95, 192, 132, 36, 33, 23, 21, 24, 24, 32, 85, 99, 62, 85, 98, 64, 65, 81, 134, 224, 230, 231, 231, 229, 229, 229, 228, 227, 175, 197, 200, 201, 202, 204, 208, 209, 210, 211, 212, 213, 214, 215, 214, 216, 216, 212, 212, 211, 192, 164, 200, 219, 219, 219, 217, 222, 224, 224, 224, 225, 226, 226, 227, 228, 228, 227, 225, 224, 224, 224, 225, 227, 228, 228, 228, 229, 230, 229, 227, 225, 221, 213, 175, 137, 131, 131, 132, 133, 140, 162, 203, 234, 241, 241, 241, 241, 241, 241, 242, 243, 242, 242, 241, 241, 242, 243, 243, 243, 247, 249, 250, 250, 251, 251, 250, 250, 249, 250, 252, 254, 254, 254, 254, 254, 254, 254, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 251, 226, 181, 132, 91, 77, 78, 78, 79, 80, 80, 81, 81, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 80, 80, 80, 80, 80, 80, 80, 80, 79, 77, 76, 74, 73, 71, 69, 63, 58, 52, 46, 41, 38, 36, 35, 35, 36, 38, 41, 44, 46, 50, 111, 112, 112, 112, 112, 112, 112, 112, 108, 130, 135, 125, 108, 105, 106, 113, 137, 137, 39, 19, 21, 22, 22, 24, 24, 25, 20, 21, 38, 24, 22, 30, 43, 43, 42, 42, 41, 41, 40, 41, 40, 49, 137, 143, 123, 143, 150, 152, 153, 156, 166, 181, 116, 126, 124, 95, 40, 61, 172, 83, 107, 122, 131, 155, 229, 233, 209, 230, 203, 154, 127, 123, 182, 150, 123, 112, 85, 66, 66, 58, 55, 53, 55, 67, 80, 89, 89, 96, 108, 143, 201, 79, 24, 22, 21, 27, 28, 23, 35, 92, 89, 60, 87, 76, 64, 67, 90, 151, 226, 229, 231, 230, 229, 229, 228, 228, 218, 175, 201, 201, 201, 201, 205, 209, 211, 212, 212, 213, 214, 214, 215, 216, 217, 216, 215, 215, 205, 203, 171, 170, 213, 217, 216, 218, 222, 223, 223, 224, 225, 226, 226, 226, 226, 225, 224, 223, 223, 224, 224, 225, 226, 227, 228, 228, 227, 227, 227, 225, 222, 221, 193, 145, 131, 131, 131, 133, 135, 154, 199, 233, 239, 241, 241, 241, 241, 240, 239, 240, 240, 240, 240, 240, 241, 243, 244, 245, 247, 249, 250, 250, 250, 250, 250, 249, 248, 249, 251, 253, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 252, 238, 199, 149, 103, 79, 78, 79, 80, 80, 81, 81, 81, 81, 82, 82, 82, 82, 82, 82, 82, 82, 82, 81, 82, 81, 81, 81, 81, 81, 80, 80, 79, 77, 75, 73, 70, 65, 59, 53, 48, 43, 38, 35, 32, 32, 31, 31, 31, 32, 32, 33, 34, 36, 112, 112, 112, 112, 112, 113, 113, 113, 107, 126, 125, 131, 132, 114, 114, 124, 137, 127, 24, 23, 21, 21, 21, 23, 23, 23, 18, 18, 33, 29, 24, 25, 41, 43, 42, 41, 41, 41, 41, 39, 40, 39, 96, 142, 115, 148, 151, 152, 153, 161, 188, 209, 198, 126, 119, 32, 37, 78, 124, 95, 126, 161, 167, 155, 231, 232, 219, 227, 231, 197, 141, 122, 158, 183, 149, 126, 115, 82, 73, 66, 58, 54, 54, 54, 63, 72, 78, 81, 100, 104, 181, 165, 74, 36, 24, 21, 38, 33, 24, 37, 94, 78, 60, 79, 63, 63, 76, 102, 177, 227, 230, 230, 230, 229, 229, 228, 226, 197, 188, 200, 200, 202, 202, 208, 210, 211, 212, 212, 213, 213, 214, 216, 217, 217, 217, 216, 216, 215, 202, 181, 140, 201, 218, 218, 221, 222, 223, 223, 224, 225, 226, 226, 226, 224, 222, 221, 223, 223, 223, 223, 224, 225, 225, 225, 224, 224, 224, 222, 220, 222, 203, 150, 132, 132, 131, 131, 131, 151, 193, 225, 231, 235, 238, 241, 240, 239, 239, 238, 239, 239, 240, 239, 240, 242, 244, 246, 248, 250, 250, 250, 250, 250, 250, 248, 247, 249, 251, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 253, 253, 253, 253, 252, 252, 246, 214, 166, 118, 84, 79, 80, 81, 81, 82, 82, 82, 82, 82, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 82, 82, 82, 81, 81, 81, 80, 79, 76, 71, 65, 59, 52, 47, 42, 38, 35, 32, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 117, 113, 112, 112, 113, 113, 109, 122, 134, 136, 136, 129, 119, 108, 114, 120, 133, 114, 27, 27, 21, 20, 21, 23, 23, 22, 18, 19, 22, 38, 23, 28, 38, 43, 43, 41, 41, 41, 41, 41, 38, 39, 42, 120, 123, 145, 152, 153, 153, 168, 199, 218, 212, 207, 94, 26, 71, 81, 107, 122, 135, 185, 201, 212, 232, 232, 227, 227, 233, 230, 184, 133, 119, 182, 183, 148, 128, 116, 83, 92, 65, 60, 54, 53, 54, 59, 63, 65, 65, 103, 125, 168, 111, 86, 67, 35, 23, 48, 44, 27, 36, 87, 69, 60, 64, 62, 66, 85, 136, 190, 226, 230, 229, 228, 228, 227, 225, 222, 173, 198, 201, 201, 201, 203, 208, 210, 211, 212, 212, 213, 213, 214, 216, 216, 217, 218, 218, 216, 211, 199, 182, 137, 186, 219, 219, 221, 222, 222, 223, 224, 225, 225, 224, 222, 221, 221, 221, 221, 221, 220, 220, 221, 220, 218, 217, 217, 218, 218, 216, 211, 193, 164, 159, 157, 153, 154, 156, 167, 190, 204, 208, 213, 217, 225, 232, 236, 238, 237, 238, 238, 239, 239, 239, 241, 244, 246, 248, 249, 249, 250, 250, 250, 249, 249, 248, 249, 251, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 254, 254, 254, 254, 254, 253, 253, 252, 250, 249, 249, 247, 225, 183, 134, 93, 80, 81, 82, 82, 82, 82, 83, 83, 83, 84, 84, 84, 84, 84, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 82, 82, 81, 79, 74, 67, 59, 52, 46, 41, 37, 34, 32, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 117, 116, 113, 112, 112, 111, 123, 136, 136, 136, 132, 122, 110, 123, 114, 119, 124, 100, 33, 27, 20, 20, 21, 22, 22, 21, 18, 20, 20, 33, 29, 29, 35, 43, 43, 41, 41, 41, 41, 41, 40, 37, 39, 56, 126, 142, 150, 154, 150, 175, 208, 219, 207, 177, 55, 53, 76, 115, 109, 133, 155, 201, 204, 232, 232, 231, 231, 232, 235, 236, 228, 166, 136, 154, 188, 188, 149, 128, 115, 117, 99, 63, 62, 55, 53, 55, 57, 58, 58, 63, 91, 139, 140, 78, 74, 76, 39, 24, 50, 54, 37, 26, 61, 61, 59, 61, 62, 76, 90, 174, 194, 222, 228, 227, 226, 225, 222, 219, 207, 169, 200, 200, 200, 201, 206, 209, 211, 211, 212, 212, 212, 213, 214, 216, 216, 217, 217, 216, 210, 210, 196, 189, 161, 179, 218, 218, 219, 220, 223, 223, 223, 223, 224, 220, 219, 218, 218, 217, 218, 218, 217, 216, 214, 209, 210, 212, 213, 209, 205, 205, 207, 211, 213, 208, 202, 200, 196, 192, 191, 188, 186, 185, 188, 196, 209, 220, 226, 228, 231, 233, 236, 238, 239, 240, 243, 246, 247, 249, 249, 249, 250, 250, 250, 249, 249, 250, 251, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 254, 254, 253, 253, 253, 252, 249, 246, 244, 244, 232, 196, 150, 106, 82, 81, 82, 83, 83, 83, 83, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 83, 83, 83, 83, 80, 75, 69, 61, 53, 46, 40, 35, 32, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 116, 115, 114, 113, 112, 107, 135, 130, 127, 121, 108, 117, 108, 123, 115, 121, 119, 89, 37, 23, 20, 21, 21, 21, 22, 20, 19, 20, 28, 23, 39, 22, 33, 41, 42, 41, 40, 40, 41, 41, 40, 40, 36, 45, 79, 140, 145, 147, 161, 185, 213, 216, 209, 187, 77, 151, 102, 87, 122, 165, 202, 198, 232, 233, 232, 231, 232, 233, 236, 237, 238, 220, 146, 126, 213, 197, 197, 151, 127, 113, 149, 96, 63, 63, 58, 53, 56, 57, 56, 56, 56, 100, 143, 113, 91, 75, 54, 29, 28, 49, 56, 53, 38, 37, 54, 60, 61, 64, 85, 99, 200, 200, 212, 225, 224, 222, 218, 213, 206, 182, 182, 199, 199, 201, 204, 208, 209, 210, 210, 210, 211, 212, 213, 214, 216, 216, 216, 215, 208, 205, 210, 195, 189, 143, 183, 216, 214, 216, 221, 222, 222, 223, 223, 219, 215, 216, 216, 215, 215, 216, 214, 210, 208, 205, 207, 206, 209, 210, 216, 223, 226, 225, 221, 213, 206, 202, 200, 201, 201, 201, 199, 194, 188, 188, 198, 211, 218, 220, 222, 223, 225, 228, 233, 237, 242, 245, 248, 248, 249, 249, 249, 250, 251, 250, 250, 251, 251, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 253, 253, 253, 252, 250, 246, 243, 241, 235, 211, 168, 121, 87, 82, 82, 83, 84, 84, 84, 85, 85, 85, 86, 86, 86, 86, 86, 85, 85, 85, 84, 84, 84, 84, 84, 84, 84, 82, 77, 70, 63, 54, 46, 39, 35, 32, 31, 31, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 115, 114, 114, 114, 114, 109, 122, 133, 135, 135, 129, 113, 113, 126, 119, 124, 119, 63, 33, 21, 20, 21, 21, 22, 22, 20, 19, 19, 35, 24, 34, 30, 29, 39, 42, 42, 41, 40, 40, 40, 40, 40, 40, 37, 58, 102, 143, 152, 159, 196, 217, 209, 220, 157, 130, 195, 208, 105, 140, 209, 194, 215, 234, 233, 232, 229, 232, 234, 236, 237, 239, 238, 194, 138, 183, 232, 205, 202, 146, 125, 115, 172, 87, 63, 63, 61, 55, 56, 58, 56, 55, 48, 135, 140, 87, 82, 70, 53, 29, 24, 44, 53, 59, 55, 46, 49, 60, 61, 73, 90, 111, 211, 208, 194, 217, 214, 210, 206, 200, 193, 161, 194, 199, 200, 204, 206, 207, 208, 208, 205, 208, 212, 212, 214, 215, 216, 215, 214, 207, 205, 210, 214, 198, 185, 157, 203, 210, 209, 217, 220, 220, 221, 219, 217, 212, 216, 216, 214, 210, 211, 207, 201, 201, 198, 197, 210, 212, 206, 208, 212, 209, 204, 199, 197, 201, 209, 215, 221, 225, 227, 228, 223, 218, 213, 214, 218, 221, 221, 220, 220, 220, 220, 223, 229, 237, 243, 246, 248, 249, 249, 249, 250, 250, 248, 248, 249, 251, 251, 252, 252, 253, 253, 253, 252, 252, 253, 253, 253, 252, 252, 252, 253, 253, 254, 254, 253, 253, 253, 252, 251, 249, 244, 241, 237, 225, 192, 145, 101, 82, 83, 83, 85, 85, 86, 86, 86, 86, 86, 87, 87, 87, 87, 87, 86, 86, 86, 86, 86, 85, 85, 85, 83, 80, 73, 64, 56, 47, 40, 34, 31, 31, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 115, 114, 113, 114, 110, 122, 135, 135, 127, 114, 128, 109, 121, 133, 126, 129, 109, 40, 24, 22, 21, 22, 22, 24, 21, 20, 19, 18, 35, 36, 24, 39, 23, 38, 42, 41, 41, 40, 40, 40, 40, 40, 41, 42, 47, 69, 124, 150, 174, 208, 222, 212, 227, 183, 162, 233, 241, 236, 187, 209, 170, 235, 233, 231, 231, 229, 231, 234, 236, 238, 240, 241, 230, 161, 139, 239, 234, 209, 204, 139, 123, 126, 183, 81, 63, 64, 63, 58, 54, 56, 56, 54, 105, 142, 118, 79, 65, 54, 44, 28, 22, 38, 52, 58, 64, 62, 58, 55, 59, 81, 93, 117, 211, 222, 184, 197, 201, 197, 191, 187, 185, 165, 196, 198, 203, 205, 206, 206, 207, 204, 201, 208, 212, 214, 216, 215, 213, 211, 206, 206, 207, 214, 215, 204, 184, 179, 208, 207, 210, 217, 218, 218, 215, 210, 210, 214, 215, 213, 205, 203, 198, 193, 179, 182, 200, 193, 188, 193, 197, 199, 203, 207, 211, 214, 217, 220, 222, 224, 228, 229, 231, 229, 217, 211, 212, 214, 216, 222, 225, 226, 223, 219, 219, 225, 232, 239, 241, 244, 247, 247, 247, 247, 248, 247, 246, 247, 248, 250, 251, 251, 251, 251, 251, 251, 251, 251, 252, 250, 250, 249, 250, 251, 251, 252, 252, 252, 252, 252, 252, 250, 247, 243, 239, 232, 217, 176, 129, 92, 83, 84, 85, 86, 86, 87, 87, 87, 88, 88, 88, 88, 88, 87, 87, 88, 87, 87, 87, 87, 86, 86, 82, 76, 67, 59, 49, 41, 35, 32, 31, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 114, 114, 113, 109, 129, 135, 133, 122, 114, 129, 107, 119, 125, 136, 126, 131, 92, 38, 21, 22, 23, 23, 24, 25, 21, 20, 19, 17, 32, 42, 30, 33, 33, 29, 37, 36, 39, 41, 40, 39, 40, 41, 42, 44, 54, 68, 85, 143, 183, 222, 228, 228, 234, 222, 183, 245, 246, 247, 245, 243, 236, 234, 232, 228, 224, 228, 233, 235, 236, 238, 240, 241, 241, 206, 144, 199, 245, 235, 211, 203, 133, 119, 151, 180, 75, 64, 69, 66, 62, 56, 53, 55, 65, 117, 122, 74, 62, 51, 43, 37, 27, 22, 31, 49, 54, 64, 61, 59, 52, 51, 66, 79, 103, 188, 222, 196, 171, 185, 186, 186, 186, 180, 169, 193, 200, 203, 205, 206, 206, 204, 198, 201, 221, 229, 236, 235, 240, 239, 232, 226, 223, 217, 207, 205, 197, 193, 205, 206, 205, 210, 213, 212, 210, 204, 209, 212, 213, 211, 195, 174, 150, 161, 186, 178, 170, 176, 183, 190, 198, 205, 209, 210, 211, 213, 216, 215, 218, 220, 224, 226, 228, 219, 197, 186, 193, 206, 215, 223, 229, 231, 229, 228, 226, 229, 233, 235, 234, 234, 237, 242, 244, 245, 245, 245, 244, 245, 245, 248, 249, 250, 250, 250, 250, 250, 250, 250, 249, 248, 247, 247, 247, 248, 248, 249, 248, 249, 249, 250, 251, 249, 245, 241, 234, 229, 208, 165, 121, 89, 85, 86, 87, 88, 88, 88, 88, 89, 88, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 87, 85, 79, 71, 62, 52, 43, 36, 32, 31, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 114, 113, 112, 125, 134, 130, 116, 125, 130, 128, 106, 107, 128, 136, 125, 132, 75, 34, 64, 23, 25, 22, 25, 25, 24, 19, 19, 18, 27, 41, 40, 28, 39, 23, 29, 29, 32, 38, 40, 39, 40, 41, 41, 44, 45, 86, 76, 114, 184, 234, 236, 236, 238, 238, 209, 246, 246, 245, 243, 240, 236, 232, 229, 224, 221, 228, 233, 235, 237, 239, 241, 242, 244, 238, 168, 154, 245, 245, 234, 211, 197, 126, 111, 176, 164, 73, 66, 74, 74, 66, 60, 54, 52, 53, 48, 37, 38, 41, 38, 35, 33, 27, 23, 27, 48, 53, 59, 61, 61, 61, 67, 77, 71, 62, 57, 62, 67, 82, 149, 184, 186, 186, 178, 173, 187, 199, 204, 197, 199, 219, 238, 251, 254, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 242, 218, 187, 200, 206, 204, 203, 204, 203, 203, 200, 197, 187, 169, 145, 111, 122, 162, 170, 163, 162, 164, 169, 176, 182, 185, 182, 179, 183, 185, 203, 217, 216, 220, 225, 227, 229, 230, 232, 221, 200, 189, 200, 215, 233, 239, 239, 235, 230, 231, 235, 237, 236, 230, 227, 227, 231, 237, 241, 243, 244, 244, 245, 245, 247, 249, 250, 250, 250, 250, 250, 249, 248, 247, 246, 246, 245, 244, 245, 246, 246, 245, 246, 247, 248, 249, 247, 244, 238, 232, 228, 202, 158, 115, 87, 87, 87, 89, 89, 89, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 89, 89, 87, 82, 75, 66, 56, 46, 38, 33, 31, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 30, 30, 30, 30, 114, 113, 110, 126, 127, 114, 130, 134, 134, 115, 121, 115, 130, 136, 124, 129, 49, 46, 75, 25, 26, 21, 25, 24, 26, 19, 19, 18, 21, 40, 41, 39, 34, 35, 19, 24, 25, 31, 40, 39, 40, 41, 41, 43, 47, 57, 101, 88, 170, 237, 244, 244, 244, 246, 240, 247, 247, 245, 243, 240, 234, 228, 226, 220, 225, 227, 234, 236, 237, 239, 241, 243, 244, 244, 219, 141, 219, 246, 246, 230, 210, 192, 118, 112, 181, 160, 70, 63, 77, 82, 75, 64, 59, 51, 50, 50, 37, 31, 30, 28, 26, 25, 25, 23, 22, 39, 50, 52, 60, 61, 61, 79, 90, 94, 96, 93, 87, 78, 75, 96, 133, 132, 131, 132, 122, 167, 209, 236, 252, 249, 238, 243, 253, 254, 251, 242, 242, 246, 249, 251, 253, 253, 253, 253, 253, 252, 228, 191, 173, 164, 154, 141, 127, 112, 106, 106, 105, 116, 146, 159, 161, 161, 161, 161, 159, 155, 149, 140, 136, 149, 167, 191, 196, 216, 226, 227, 230, 229, 228, 232, 235, 238, 240, 232, 209, 198, 208, 225, 242, 242, 239, 237, 238, 240, 240, 239, 236, 231, 227, 227, 227, 235, 242, 244, 246, 247, 248, 248, 251, 251, 251, 251, 251, 250, 248, 245, 244, 245, 245, 245, 244, 244, 244, 244, 244, 244, 245, 246, 246, 245, 241, 235, 233, 229, 197, 154, 107, 88, 89, 89, 90, 90, 91, 91, 91, 92, 92, 92, 92, 91, 91, 91, 91, 91, 90, 86, 78, 70, 59, 49, 40, 34, 31, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 114, 113, 110, 123, 116, 131, 134, 133, 123, 115, 121, 117, 130, 136, 127, 113, 40, 83, 69, 26, 27, 20, 25, 24, 25, 22, 19, 18, 18, 37, 41, 41, 39, 40, 26, 18, 22, 26, 34, 41, 40, 41, 41, 42, 50, 54, 100, 98, 135, 227, 246, 247, 247, 247, 247, 247, 247, 245, 242, 239, 231, 224, 221, 220, 225, 231, 235, 236, 238, 240, 241, 244, 245, 245, 246, 180, 180, 246, 247, 245, 225, 210, 181, 108, 130, 182, 159, 69, 60, 75, 87, 86, 74, 64, 58, 50, 49, 41, 29, 28, 26, 25, 24, 24, 22, 21, 22, 35, 40, 49, 57, 63, 81, 90, 93, 95, 96, 95, 95, 95, 95, 98, 108, 154, 217, 249, 250, 245, 232, 225, 228, 241, 252, 241, 227, 228, 232, 236, 241, 244, 249, 252, 253, 254, 254, 253, 253, 249, 221, 142, 115, 110, 108, 106, 107, 125, 144, 156, 160, 160, 161, 159, 151, 138, 125, 118, 113, 122, 167, 193, 200, 203, 214, 223, 226, 228, 231, 231, 231, 234, 236, 238, 241, 241, 224, 212, 215, 218, 235, 244, 242, 241, 241, 243, 243, 242, 241, 242, 238, 229, 223, 224, 238, 246, 247, 248, 250, 251, 251, 252, 252, 252, 251, 250, 247, 244, 244, 245, 244, 244, 244, 244, 245, 245, 244, 244, 245, 244, 244, 242, 237, 233, 234, 229, 197, 149, 103, 89, 90, 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 90, 83, 73, 63, 53, 43, 35, 32, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 117, 114, 114, 108, 126, 134, 129, 117, 107, 121, 121, 118, 129, 135, 134, 88, 38, 102, 63, 26, 25, 20, 24, 24, 24, 25, 19, 18, 17, 31, 41, 41, 41, 41, 39, 19, 18, 21, 25, 39, 41, 41, 41, 41, 51, 57, 65, 127, 115, 194, 245, 247, 247, 247, 247, 247, 247, 245, 242, 237, 228, 224, 219, 221, 227, 233, 236, 237, 239, 241, 242, 244, 245, 246, 246, 232, 144, 233, 247, 246, 243, 219, 210, 154, 94, 163, 183, 159, 70, 59, 78, 85, 90, 87, 77, 66, 58, 50, 44, 32, 28, 27, 25, 25, 25, 23, 22, 22, 20, 30, 33, 37, 48, 71, 77, 82, 85, 87, 91, 94, 96, 141, 218, 238, 226, 215, 209, 209, 215, 221, 232, 246, 231, 223, 222, 224, 227, 231, 235, 239, 243, 247, 251, 253, 254, 254, 254, 253, 249, 244, 184, 120, 127, 141, 154, 158, 159, 157, 152, 145, 139, 128, 118, 130, 143, 169, 176, 193, 195, 206, 214, 212, 224, 225, 226, 229, 231, 232, 233, 234, 235, 238, 239, 241, 226, 216, 224, 217, 227, 243, 244, 242, 241, 244, 245, 245, 246, 247, 248, 240, 225, 220, 228, 245, 249, 250, 251, 251, 251, 251, 251, 251, 251, 247, 244, 242, 242, 243, 243, 242, 243, 246, 247, 247, 247, 246, 245, 244, 242, 239, 233, 233, 236, 231, 195, 144, 101, 91, 91, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 92, 87, 77, 67, 56, 46, 37, 32, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 121, 115, 115, 115, 124, 132, 123, 120, 105, 107, 110, 110, 124, 135, 133, 86, 37, 117, 62, 25, 23, 21, 21, 24, 23, 25, 20, 19, 17, 23, 41, 41, 40, 40, 41, 33, 16, 18, 22, 27, 41, 41, 41, 41, 50, 62, 68, 119, 136, 148, 238, 247, 247, 247, 247, 247, 247, 245, 243, 239, 228, 225, 220, 223, 229, 235, 237, 239, 240, 241, 243, 241, 243, 246, 247, 246, 196, 188, 247, 247, 245, 235, 214, 207, 122, 107, 181, 183, 160, 72, 83, 122, 87, 89, 92, 91, 82, 72, 61, 52, 37, 32, 31, 27, 25, 24, 22, 21, 21, 21, 22, 20, 20, 19, 16, 19, 23, 27, 33, 82, 178, 233, 213, 204, 203, 204, 205, 211, 217, 227, 242, 227, 223, 221, 221, 223, 224, 226, 229, 234, 239, 243, 248, 252, 254, 254, 254, 254, 252, 250, 249, 211, 149, 141, 134, 125, 117, 114, 116, 116, 113, 128, 155, 181, 188, 190, 197, 200, 198, 212, 217, 221, 225, 225, 226, 228, 231, 231, 230, 230, 233, 236, 238, 239, 220, 220, 227, 219, 223, 240, 241, 240, 241, 241, 243, 244, 246, 247, 247, 245, 235, 223, 226, 237, 248, 248, 248, 248, 248, 246, 247, 246, 246, 243, 241, 241, 244, 244, 241, 240, 241, 245, 247, 248, 247, 247, 246, 243, 241, 234, 232, 234, 238, 233, 193, 141, 100, 92, 92, 93, 93, 94, 94, 94, 95, 94, 94, 94, 94, 94, 92, 84, 72, 60, 48, 38, 31, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 114, 113, 115, 116, 116, 132, 123, 121, 110, 121, 121, 115, 121, 130, 130, 78, 62, 120, 64, 24, 22, 20, 19, 23, 23, 24, 23, 18, 18, 19, 35, 41, 41, 40, 39, 41, 25, 15, 19, 21, 32, 41, 41, 40, 47, 66, 70, 94, 174, 131, 207, 246, 247, 247, 247, 247, 247, 245, 243, 240, 230, 227, 223, 228, 232, 236, 239, 240, 241, 242, 244, 236, 228, 242, 247, 247, 244, 157, 231, 247, 246, 241, 227, 211, 193, 91, 149, 183, 183, 162, 75, 72, 150, 141, 86, 89, 95, 95, 93, 85, 75, 61, 53, 50, 51, 49, 45, 44, 44, 44, 43, 39, 34, 29, 27, 26, 28, 42, 114, 218, 218, 202, 202, 202, 203, 203, 207, 209, 221, 241, 228, 223, 221, 221, 221, 221, 221, 222, 225, 229, 235, 239, 244, 249, 253, 254, 254, 254, 254, 252, 250, 249, 199, 115, 113, 108, 105, 105, 105, 146, 176, 188, 188, 192, 194, 195, 201, 207, 210, 217, 222, 225, 221, 222, 225, 228, 231, 231, 231, 231, 231, 233, 238, 231, 215, 227, 228, 217, 220, 236, 236, 237, 238, 240, 239, 240, 242, 244, 243, 241, 241, 233, 225, 228, 242, 246, 245, 244, 244, 241, 241, 242, 241, 238, 240, 242, 246, 246, 242, 238, 239, 243, 246, 246, 246, 245, 244, 242, 237, 233, 233, 237, 242, 234, 192, 140, 100, 93, 94, 94, 94, 95, 95, 95, 95, 95, 95, 95, 95, 91, 80, 66, 53, 42, 32, 27, 28, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 113, 114, 115, 113, 110, 130, 122, 120, 115, 121, 121, 121, 117, 123, 119, 60, 84, 119, 67, 23, 21, 20, 19, 20, 23, 24, 25, 19, 18, 19, 27, 41, 41, 40, 39, 40, 39, 19, 15, 20, 21, 37, 40, 40, 42, 68, 75, 74, 177, 152, 174, 245, 246, 246, 247, 247, 247, 246, 245, 241, 234, 229, 229, 231, 236, 238, 240, 241, 242, 243, 244, 245, 217, 234, 239, 247, 247, 229, 168, 246, 246, 243, 234, 220, 204, 162, 87, 176, 183, 183, 166, 79, 67, 147, 168, 86, 70, 82, 96, 100, 100, 96, 89, 82, 72, 65, 61, 56, 58, 63, 64, 63, 61, 73, 97, 82, 133, 158, 211, 198, 168, 184, 201, 202, 202, 204, 208, 210, 235, 233, 224, 221, 221, 221, 220, 220, 220, 221, 222, 225, 231, 236, 241, 246, 251, 253, 254, 254, 254, 254, 252, 251, 249, 173, 89, 82, 88, 101, 117, 125, 127, 136, 147, 158, 178, 194, 198, 206, 211, 217, 218, 225, 224, 222, 225, 227, 230, 231, 231, 231, 231, 230, 234, 214, 222, 229, 227, 212, 221, 234, 234, 237, 237, 239, 237, 236, 237, 241, 241, 237, 238, 242, 227, 220, 233, 244, 242, 242, 242, 240, 239, 241, 241, 239, 241, 244, 248, 248, 243, 238, 237, 241, 242, 242, 242, 243, 241, 240, 234, 232, 234, 239, 245, 233, 192, 141, 101, 94, 95, 95, 95, 95, 95, 95, 95, 95, 96, 95, 89, 75, 61, 47, 35, 27, 26, 27, 28, 29, 29, 29, 29, 29, 29, 29, 29, 30, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 113, 115, 115, 112, 112, 116, 124, 120, 120, 117, 119, 117, 120, 118, 113, 52, 98, 120, 72, 23, 21, 20, 19, 17, 22, 24, 25, 21, 17, 19, 22, 37, 41, 40, 39, 37, 39, 35, 17, 56, 21, 24, 40, 40, 40, 65, 79, 76, 155, 179, 143, 238, 246, 246, 247, 247, 247, 247, 245, 244, 240, 233, 235, 237, 239, 240, 241, 241, 243, 244, 245, 246, 230, 202, 239, 247, 247, 247, 203, 203, 246, 244, 237, 227, 208, 183, 151, 109, 183, 183, 183, 171, 87, 67, 130, 174, 110, 87, 100, 94, 92, 90, 89, 90, 91, 89, 84, 78, 84, 82, 95, 94, 158, 150, 144, 153, 176, 189, 156, 135, 146, 148, 199, 202, 203, 207, 197, 220, 232, 224, 222, 221, 221, 220, 220, 219, 219, 220, 220, 222, 228, 233, 239, 244, 249, 253, 254, 254, 254, 254, 254, 252, 251, 243, 137, 111, 114, 121, 129, 138, 145, 150, 156, 161, 159, 155, 168, 184, 203, 209, 213, 223, 221, 220, 224, 227, 229, 231, 231, 231, 231, 232, 213, 206, 213, 225, 218, 210, 229, 237, 236, 238, 240, 241, 238, 235, 235, 240, 242, 238, 240, 244, 232, 212, 224, 243, 243, 243, 243, 242, 241, 242, 243, 243, 244, 247, 248, 246, 243, 239, 237, 238, 239, 239, 239, 240, 240, 236, 230, 232, 237, 244, 246, 234, 194, 143, 103, 94, 95, 96, 96, 96, 96, 96, 97, 96, 95, 88, 73, 57, 43, 30, 24, 24, 26, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 111, 113, 115, 111, 111, 108, 118, 115, 114, 112, 112, 111, 107, 104, 118, 42, 108, 118, 73, 23, 20, 19, 19, 18, 20, 23, 24, 24, 18, 17, 20, 28, 40, 40, 39, 38, 32, 39, 26, 52, 89, 20, 30, 40, 40, 57, 80, 82, 132, 187, 145, 226, 246, 246, 247, 247, 247, 247, 246, 246, 244, 240, 239, 241, 241, 242, 242, 243, 244, 245, 246, 246, 246, 245, 247, 247, 247, 247, 243, 175, 224, 244, 239, 230, 215, 183, 182, 133, 151, 183, 183, 183, 175, 103, 72, 120, 179, 139, 114, 116, 116, 116, 112, 110, 125, 146, 176, 202, 206, 181, 166, 148, 145, 159, 152, 160, 153, 141, 145, 146, 145, 145, 169, 203, 205, 200, 205, 225, 224, 222, 221, 221, 221, 220, 219, 219, 219, 219, 220, 220, 225, 231, 236, 241, 247, 251, 253, 254, 254, 254, 254, 254, 252, 251, 222, 119, 115, 120, 128, 136, 141, 149, 158, 175, 193, 206, 215, 219, 202, 188, 202, 219, 219, 219, 223, 226, 228, 230, 231, 232, 232, 209, 189, 186, 201, 218, 210, 227, 235, 240, 239, 241, 242, 242, 237, 234, 236, 242, 244, 243, 244, 246, 234, 204, 215, 243, 244, 244, 246, 244, 244, 244, 245, 246, 247, 248, 246, 244, 241, 238, 237, 237, 237, 237, 237, 237, 237, 231, 229, 233, 239, 246, 246, 235, 198, 149, 107, 96, 96, 97, 96, 96, 97, 97, 97, 94, 86, 72, 56, 40, 27, 23, 24, 26, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 110, 112, 114, 111, 111, 111, 110, 112, 113, 114, 113, 112, 108, 120, 117, 43, 114, 107, 78, 23, 20, 19, 19, 19, 17, 22, 23, 25, 20, 16, 19, 23, 35, 39, 39, 39, 34, 32, 35, 26, 101, 91, 20, 35, 40, 49, 79, 83, 121, 186, 176, 213, 242, 246, 247, 247, 247, 247, 247, 246, 245, 244, 243, 244, 244, 244, 244, 244, 245, 246, 247, 247, 247, 247, 247, 247, 247, 247, 246, 227, 180, 226, 241, 233, 218, 184, 182, 181, 115, 176, 183, 183, 183, 181, 124, 78, 111, 174, 161, 116, 117, 111, 110, 123, 200, 227, 239, 233, 208, 178, 118, 130, 132, 134, 144, 145, 145, 146, 145, 145, 145, 145, 136, 201, 205, 189, 222, 224, 223, 221, 222, 221, 221, 220, 219, 219, 219, 219, 220, 220, 223, 228, 233, 238, 244, 249, 252, 254, 254, 254, 254, 254, 254, 253, 252, 175, 105, 104, 109, 117, 128, 139, 149, 156, 165, 184, 204, 220, 225, 225, 207, 190, 209, 218, 221, 225, 227, 228, 230, 228, 196, 174, 175, 182, 205, 210, 232, 237, 239, 240, 241, 241, 241, 238, 233, 234, 239, 244, 246, 246, 246, 246, 235, 199, 211, 242, 246, 245, 245, 244, 244, 245, 246, 246, 247, 247, 244, 240, 237, 236, 236, 235, 235, 235, 235, 235, 232, 227, 229, 235, 243, 247, 246, 237, 203, 156, 115, 97, 97, 97, 97, 97, 97, 97, 92, 84, 70, 54, 38, 26, 23, 24, 26, 27, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 26, 25, 26, 27, 29, 29, 29, 29, 29, 28, 110, 111, 112, 111, 110, 109, 110, 110, 112, 114, 112, 111, 127, 122, 114, 55, 107, 111, 88, 23, 20, 19, 19, 19, 18, 20, 23, 24, 24, 18, 16, 21, 28, 38, 39, 39, 39, 25, 37, 39, 48, 126, 96, 24, 37, 40, 73, 85, 134, 177, 199, 216, 232, 239, 245, 246, 247, 247, 247, 247, 247, 246, 246, 245, 245, 245, 245, 245, 246, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 244, 213, 196, 212, 234, 220, 185, 182, 183, 178, 118, 176, 183, 183, 183, 184, 149, 87, 93, 153, 176, 163, 165, 174, 165, 170, 230, 240, 210, 180, 92, 81, 116, 145, 145, 140, 120, 115, 138, 146, 145, 145, 145, 139, 178, 193, 206, 222, 223, 221, 223, 225, 222, 221, 219, 219, 219, 219, 219, 219, 220, 222, 226, 231, 235, 240, 246, 250, 252, 254, 254, 254, 254, 254, 254, 254, 240, 98, 79, 76, 76, 77, 79, 84, 97, 115, 132, 150, 168, 190, 212, 225, 224, 196, 207, 220, 224, 226, 228, 213, 177, 171, 174, 176, 182, 207, 233, 237, 237, 238, 237, 240, 241, 241, 234, 229, 232, 238, 242, 244, 245, 245, 245, 230, 200, 216, 243, 247, 246, 244, 244, 245, 244, 244, 243, 244, 244, 241, 236, 235, 234, 234, 235, 235, 234, 234, 233, 227, 226, 231, 239, 246, 246, 245, 239, 211, 167, 125, 100, 97, 97, 97, 98, 97, 90, 80, 67, 52, 37, 26, 22, 23, 25, 27, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 26, 24, 22, 24, 27, 29, 29, 29, 29, 28, 27, 109, 110, 111, 111, 109, 110, 110, 111, 111, 115, 113, 123, 130, 124, 113, 68, 110, 110, 93, 23, 21, 19, 19, 18, 19, 17, 22, 23, 25, 24, 17, 19, 24, 31, 39, 39, 39, 31, 26, 39, 45, 93, 128, 106, 36, 37, 65, 83, 135, 169, 198, 221, 225, 230, 240, 245, 246, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 237, 209, 214, 197, 213, 187, 182, 182, 142, 79, 110, 170, 183, 183, 183, 183, 170, 110, 92, 121, 170, 180, 172, 181, 164, 197, 196, 189, 89, 85, 101, 143, 133, 114, 94, 86, 95, 131, 146, 145, 145, 146, 146, 159, 192, 221, 223, 222, 222, 227, 226, 221, 221, 220, 220, 220, 220, 219, 219, 220, 220, 224, 228, 233, 237, 243, 248, 252, 253, 254, 254, 254, 255, 255, 255, 254, 183, 93, 121, 143, 116, 121, 136, 92, 82, 79, 81, 96, 124, 147, 174, 210, 224, 203, 209, 221, 211, 180, 166, 173, 174, 173, 183, 214, 224, 222, 223, 220, 219, 216, 219, 222, 225, 223, 222, 224, 226, 230, 232, 234, 236, 237, 220, 203, 225, 244, 246, 246, 245, 245, 244, 242, 239, 238, 239, 239, 237, 234, 234, 234, 234, 236, 235, 234, 233, 230, 225, 227, 234, 243, 245, 245, 245, 238, 218, 179, 138, 110, 98, 98, 98, 96, 88, 77, 63, 49, 34, 26, 23, 23, 25, 27, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 27, 23, 20, 20, 24, 27, 29, 29, 28, 27, 26, 25, 110, 110, 111, 112, 111, 110, 110, 111, 112, 114, 113, 121, 115, 120, 102, 77, 110, 110, 101, 22, 21, 19, 19, 19, 18, 18, 20, 23, 24, 29, 21, 16, 23, 27, 34, 39, 39, 33, 31, 29, 43, 57, 119, 128, 120, 65, 48, 75, 126, 161, 171, 211, 224, 225, 231, 243, 246, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 231, 205, 223, 194, 156, 134, 119, 138, 175, 170, 82, 146, 183, 183, 183, 183, 182, 147, 100, 97, 133, 169, 183, 156, 141, 188, 93, 85, 84, 128, 110, 86, 84, 85, 95, 108, 137, 146, 145, 145, 145, 146, 143, 211, 221, 222, 221, 227, 231, 224, 221, 221, 221, 221, 220, 221, 220, 220, 219, 220, 221, 226, 230, 235, 239, 245, 250, 253, 254, 254, 254, 255, 255, 255, 255, 241, 178, 179, 178, 174, 173, 175, 177, 175, 170, 162, 153, 137, 117, 115, 135, 182, 218, 185, 172, 164, 169, 171, 174, 172, 190, 212, 219, 224, 227, 230, 232, 233, 234, 234, 235, 235, 234, 233, 232, 229, 227, 225, 222, 221, 219, 210, 207, 222, 236, 240, 243, 245, 245, 243, 237, 234, 234, 234, 234, 233, 232, 232, 232, 234, 234, 234, 232, 230, 225, 224, 229, 238, 245, 245, 245, 244, 238, 222, 191, 153, 123, 102, 98, 94, 87, 74, 60, 46, 32, 25, 23, 22, 24, 27, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 25, 20, 19, 20, 25, 28, 29, 28, 25, 22, 22, 22, 110, 110, 111, 112, 113, 111, 110, 111, 112, 114, 114, 111, 112, 108, 104, 83, 109, 109, 108, 25, 21, 19, 19, 19, 18, 18, 17, 22, 23, 27, 33, 18, 17, 23, 27, 34, 38, 33, 38, 25, 33, 53, 79, 127, 128, 122, 61, 79, 76, 64, 63, 158, 224, 224, 225, 237, 246, 246, 246, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 245, 230, 201, 198, 185, 182, 183, 184, 184, 184, 159, 72, 101, 153, 178, 183, 184, 183, 178, 146, 117, 90, 103, 106, 157, 92, 84, 83, 81, 93, 111, 117, 107, 95, 97, 120, 145, 146, 145, 145, 145, 146, 134, 214, 220, 221, 225, 232, 228, 221, 221, 221, 221, 221, 221, 222, 222, 220, 219, 220, 220, 224, 228, 233, 238, 243, 248, 252, 253, 254, 254, 255, 255, 255, 254, 253, 200, 183, 178, 182, 182, 182, 182, 182, 183, 183, 185, 190, 191, 179, 155, 157, 191, 193, 205, 208, 213, 222, 226, 231, 233, 233, 232, 232, 231, 232, 232, 234, 235, 234, 233, 231, 229, 227, 226, 224, 223, 222, 221, 220, 218, 216, 215, 216, 220, 223, 228, 233, 237, 238, 234, 231, 231, 231, 230, 230, 230, 230, 230, 232, 232, 230, 229, 224, 218, 223, 232, 243, 244, 245, 244, 244, 237, 223, 201, 168, 139, 114, 96, 86, 72, 58, 43, 31, 25, 23, 23, 24, 27, 28, 29, 29, 29, 30, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 24, 20, 19, 22, 27, 29, 27, 23, 19, 18, 18, 21, 111, 111, 111, 111, 112, 112, 111, 111, 111, 112, 113, 111, 110, 109, 105, 87, 109, 109, 110, 48, 21, 19, 19, 19, 18, 18, 18, 19, 22, 24, 34, 28, 18, 16, 20, 27, 35, 32, 38, 37, 30, 42, 60, 102, 128, 127, 106, 35, 41, 75, 82, 89, 133, 214, 224, 229, 245, 245, 245, 246, 246, 246, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 243, 232, 207, 185, 181, 182, 184, 184, 184, 184, 150, 77, 82, 100, 130, 145, 166, 181, 181, 181, 179, 174, 157, 109, 69, 74, 69, 68, 105, 136, 141, 141, 137, 138, 142, 144, 145, 145, 145, 146, 146, 134, 209, 220, 222, 232, 231, 222, 221, 221, 221, 221, 222, 223, 223, 222, 221, 220, 219, 220, 221, 227, 231, 236, 240, 245, 251, 253, 254, 254, 255, 255, 255, 254, 254, 231, 154, 157, 157, 160, 160, 167, 163, 159, 151, 154, 151, 147, 148, 159, 172, 177, 183, 192, 202, 212, 216, 220, 223, 226, 223, 214, 207, 203, 203, 202, 199, 187, 174, 165, 160, 156, 156, 157, 159, 164, 171, 178, 182, 179, 174, 180, 191, 193, 196, 202, 207, 208, 213, 218, 223, 227, 229, 229, 229, 230, 230, 230, 230, 229, 224, 212, 198, 205, 222, 237, 243, 243, 244, 244, 242, 235, 221, 204, 182, 157, 126, 96, 73, 56, 41, 29, 24, 23, 23, 24, 26, 28, 29, 29, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 28, 27, 28, 29, 29, 29, 27, 23, 21, 21, 25, 28, 26, 22, 17, 15, 16, 18, 22, 112, 111, 111, 111, 111, 111, 111, 111, 111, 111, 112, 113, 113, 109, 106, 93, 108, 108, 108, 68, 22, 19, 18, 18, 18, 17, 18, 17, 21, 23, 28, 39, 23, 17, 15, 19, 28, 30, 39, 39, 34, 42, 56, 66, 118, 125, 98, 27, 118, 115, 99, 132, 154, 134, 220, 220, 244, 245, 245, 244, 244, 245, 245, 246, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 244, 234, 217, 185, 181, 182, 182, 183, 184, 183, 183, 152, 85, 90, 96, 100, 100, 100, 117, 134, 142, 101, 81, 80, 60, 55, 53, 81, 97, 134, 141, 141, 141, 142, 142, 143, 143, 143, 143, 141, 137, 121, 208, 220, 228, 231, 223, 221, 221, 221, 222, 226, 226, 226, 225, 224, 221, 220, 219, 220, 220, 225, 229, 234, 238, 243, 248, 252, 254, 254, 255, 255, 254, 254, 254, 253, 174, 163, 162, 153, 150, 153, 148, 144, 143, 145, 146, 148, 149, 149, 153, 159, 164, 166, 169, 173, 182, 194, 207, 211, 185, 162, 147, 137, 131, 125, 121, 121, 120, 120, 121, 121, 122, 124, 127, 142, 156, 165, 175, 183, 166, 160, 172, 151, 154, 176, 182, 158, 153, 165, 181, 198, 215, 225, 227, 227, 227, 227, 227, 218, 194, 164, 162, 191, 224, 241, 242, 242, 242, 241, 239, 232, 218, 203, 190, 164, 125, 87, 58, 40, 29, 24, 23, 23, 24, 25, 28, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 27, 26, 26, 27, 28, 29, 28, 25, 23, 22, 24, 27, 27, 22, 17, 14, 14, 18, 22, 26, 111, 111, 112, 112, 111, 110, 111, 111, 111, 111, 112, 113, 115, 111, 106, 95, 108, 108, 108, 84, 22, 19, 19, 18, 19, 17, 17, 19, 17, 22, 24, 34, 36, 18, 16, 14, 18, 24, 37, 39, 39, 33, 62, 67, 80, 116, 45, 25, 58, 81, 114, 147, 170, 182, 203, 215, 239, 245, 246, 244, 243, 244, 245, 245, 246, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 245, 244, 233, 215, 178, 181, 181, 182, 182, 183, 183, 183, 183, 164, 105, 94, 99, 101, 100, 98, 78, 110, 57, 76, 70, 48, 48, 61, 69, 74, 86, 104, 118, 124, 128, 131, 128, 125, 122, 117, 105, 119, 147, 217, 221, 229, 222, 221, 221, 221, 224, 230, 231, 229, 228, 227, 225, 223, 221, 220, 220, 220, 223, 227, 232, 236, 241, 247, 251, 253, 254, 255, 255, 255, 254, 254, 254, 207, 160, 157, 157, 158, 158, 158, 159, 160, 160, 158, 157, 157, 156, 156, 156, 156, 156, 157, 158, 160, 162, 166, 170, 173, 172, 170, 170, 173, 177, 179, 180, 178, 169, 153, 159, 169, 181, 189, 206, 212, 215, 217, 227, 226, 223, 226, 209, 206, 211, 203, 157, 124, 111, 116, 134, 163, 192, 214, 224, 225, 225, 215, 181, 136, 104, 135, 192, 232, 239, 240, 240, 239, 238, 234, 227, 214, 201, 179, 148, 107, 68, 41, 28, 23, 22, 23, 24, 25, 27, 28, 29, 30, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 29, 29, 29, 28, 26, 25, 24, 26, 27, 29, 28, 24, 23, 24, 27, 27, 23, 17, 13, 14, 17, 22, 27, 28, 112, 111, 110, 111, 110, 109, 110, 110, 110, 110, 111, 112, 117, 114, 107, 96, 107, 107, 107, 99, 20, 19, 20, 19, 19, 18, 17, 18, 18, 18, 23, 27, 39, 30, 17, 16, 14, 16, 30, 38, 39, 40, 42, 81, 72, 95, 18, 30, 60, 109, 108, 135, 188, 196, 217, 223, 226, 232, 240, 241, 242, 244, 244, 245, 245, 246, 247, 246, 242, 246, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 245, 243, 230, 206, 179, 182, 181, 182, 182, 182, 182, 182, 182, 182, 182, 163, 155, 153, 138, 84, 78, 79, 67, 58, 52, 50, 62, 74, 81, 81, 76, 69, 70, 77, 81, 82, 83, 80, 73, 99, 173, 219, 219, 212, 227, 223, 221, 221, 223, 228, 232, 233, 232, 231, 230, 228, 227, 225, 222, 220, 220, 221, 223, 226, 230, 235, 239, 245, 251, 252, 254, 255, 255, 255, 255, 255, 255, 238, 153, 157, 156, 156, 156, 156, 156, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 156, 156, 157, 157, 156, 156, 155, 156, 156, 157, 159, 173, 214, 229, 229, 223, 215, 208, 210, 219, 230, 232, 233, 235, 236, 237, 238, 238, 237, 234, 225, 204, 179, 137, 110, 100, 105, 130, 164, 198, 218, 217, 186, 130, 74, 79, 148, 213, 235, 237, 238, 237, 236, 234, 229, 221, 208, 186, 152, 115, 76, 44, 28, 23, 22, 23, 23, 25, 26, 28, 29, 29, 30, 29, 29, 30, 29, 29, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 29, 29, 28, 26, 24, 23, 25, 27, 28, 26, 24, 24, 25, 28, 25, 19, 14, 13, 17, 23, 27, 29, 29, 111, 111, 110, 109, 109, 109, 109, 109, 109, 110, 111, 111, 117, 117, 110, 94, 107, 107, 107, 107, 39, 19, 20, 19, 19, 19, 17, 17, 18, 17, 20, 24, 32, 38, 24, 16, 15, 14, 15, 31, 39, 39, 52, 51, 96, 76, 13, 57, 65, 80, 119, 164, 204, 198, 217, 222, 225, 226, 231, 238, 240, 241, 243, 244, 244, 245, 246, 219, 239, 246, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 245, 245, 241, 226, 190, 182, 182, 182, 181, 181, 182, 182, 182, 182, 183, 182, 159, 149, 113, 79, 82, 81, 80, 80, 80, 81, 82, 84, 85, 84, 83, 84, 81, 65, 69, 68, 65, 70, 72, 73, 74, 75, 126, 193, 229, 229, 222, 223, 227, 231, 233, 234, 234, 233, 232, 231, 230, 228, 226, 223, 220, 220, 221, 222, 225, 229, 233, 237, 243, 250, 252, 253, 255, 255, 255, 255, 255, 255, 253, 147, 128, 132, 138, 142, 148, 152, 154, 155, 156, 156, 156, 156, 156, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 156, 159, 187, 229, 232, 234, 236, 234, 229, 222, 215, 221, 232, 236, 235, 232, 231, 235, 232, 231, 227, 224, 220, 204, 183, 157, 127, 101, 104, 141, 185, 198, 150, 83, 50, 104, 183, 227, 233, 233, 233, 232, 231, 228, 223, 213, 192, 157, 116, 76, 44, 29, 23, 22, 23, 23, 24, 26, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 29, 27, 25, 23, 22, 24, 26, 25, 22, 21, 24, 27, 27, 22, 17, 16, 17, 23, 27, 29, 29, 29, 110, 109, 109, 109, 109, 109, 109, 109, 109, 109, 110, 111, 115, 118, 115, 91, 107, 107, 107, 107, 68, 20, 25, 19, 19, 19, 17, 17, 18, 17, 16, 21, 26, 36, 36, 19, 16, 15, 14, 16, 28, 38, 42, 65, 58, 111, 38, 80, 130, 96, 93, 183, 158, 187, 217, 220, 223, 227, 230, 235, 239, 240, 242, 243, 244, 245, 246, 240, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 246, 245, 245, 238, 222, 178, 182, 182, 182, 182, 182, 181, 182, 182, 183, 176, 166, 98, 75, 82, 81, 80, 80, 85, 109, 128, 135, 140, 134, 111, 96, 92, 88, 84, 67, 73, 73, 75, 71, 69, 76, 77, 78, 81, 89, 170, 222, 222, 226, 229, 231, 233, 233, 233, 233, 233, 232, 230, 228, 227, 224, 220, 220, 220, 221, 224, 227, 231, 235, 240, 250, 252, 252, 255, 255, 255, 255, 255, 255, 255, 182, 104, 104, 106, 108, 108, 109, 111, 115, 119, 122, 124, 126, 128, 131, 135, 138, 141, 146, 152, 155, 155, 155, 155, 155, 155, 155, 155, 156, 157, 160, 191, 229, 235, 230, 228, 229, 230, 226, 223, 215, 208, 221, 233, 231, 224, 228, 227, 231, 224, 222, 216, 223, 225, 215, 198, 163, 122, 97, 133, 152, 114, 58, 65, 143, 209, 226, 228, 228, 228, 227, 224, 221, 214, 194, 160, 120, 78, 47, 31, 23, 22, 22, 23, 24, 25, 27, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 29, 29, 29, 29, 29, 29, 28, 25, 23, 22, 24, 24, 21, 18, 18, 22, 26, 25, 21, 19, 19, 22, 27, 29, 29, 29, 30, 109, 109, 108, 108, 108, 109, 109, 109, 109, 109, 109, 109, 112, 118, 117, 90, 107, 106, 106, 106, 90, 21, 48, 20, 18, 19, 18, 17, 17, 17, 17, 16, 23, 30, 38, 33, 16, 17, 40, 51, 14, 23, 36, 52, 74, 56, 65, 53, 142, 186, 203, 229, 210, 203, 214, 215, 219, 225, 230, 233, 237, 240, 240, 242, 243, 244, 245, 245, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 246, 245, 245, 243, 233, 216, 159, 181, 181, 182, 182, 182, 182, 182, 182, 161, 215, 136, 70, 84, 82, 81, 92, 120, 141, 146, 146, 146, 142, 138, 137, 132, 106, 93, 90, 78, 121, 106, 77, 74, 80, 76, 71, 78, 79, 82, 92, 115, 169, 201, 213, 220, 219, 220, 225, 231, 234, 231, 230, 228, 227, 222, 219, 219, 219, 221, 222, 226, 229, 232, 237, 250, 251, 251, 254, 255, 255, 255, 255, 255, 255, 211, 111, 107, 107, 108, 110, 113, 117, 120, 122, 125, 126, 128, 133, 138, 144, 149, 152, 154, 155, 155, 155, 155, 155, 155, 155, 155, 156, 157, 173, 189, 219, 233, 225, 215, 215, 216, 214, 213, 221, 222, 217, 207, 209, 225, 226, 228, 228, 229, 225, 219, 207, 227, 231, 229, 227, 222, 190, 133, 95, 107, 88, 51, 96, 177, 217, 220, 222, 222, 222, 220, 218, 213, 195, 161, 121, 80, 49, 32, 23, 22, 22, 23, 24, 25, 27, 28, 29, 30, 31, 31, 30, 30, 30, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 29, 29, 29, 29, 28, 27, 25, 22, 22, 23, 21, 18, 15, 16, 20, 23, 24, 23, 23, 25, 27, 29, 29, 29, 30, 30, 109, 108, 108, 108, 108, 108, 108, 108, 109, 109, 109, 109, 110, 116, 118, 95, 107, 106, 106, 106, 105, 33, 68, 27, 18, 19, 19, 17, 16, 17, 17, 17, 15, 24, 34, 38, 29, 16, 16, 92, 65, 25, 19, 30, 59, 74, 75, 34, 130, 180, 214, 228, 226, 212, 211, 210, 214, 221, 228, 232, 235, 237, 240, 241, 243, 244, 244, 245, 246, 246, 247, 247, 247, 247, 247, 247, 246, 245, 245, 245, 244, 238, 226, 205, 153, 181, 180, 181, 182, 182, 181, 179, 204, 211, 203, 136, 92, 90, 91, 126, 144, 140, 147, 157, 164, 170, 175, 178, 178, 156, 133, 123, 99, 93, 156, 192, 188, 171, 146, 104, 82, 77, 81, 90, 93, 104, 114, 117, 126, 134, 143, 146, 144, 145, 153, 162, 171, 176, 180, 183, 188, 217, 219, 220, 222, 224, 226, 230, 233, 252, 254, 254, 255, 255, 255, 255, 255, 255, 255, 237, 95, 92, 92, 98, 103, 106, 108, 110, 112, 115, 117, 121, 124, 127, 130, 133, 136, 138, 141, 144, 148, 150, 152, 153, 153, 154, 161, 177, 207, 216, 217, 212, 189, 167, 162, 168, 181, 195, 199, 204, 220, 222, 212, 196, 216, 229, 228, 226, 224, 208, 206, 230, 229, 226, 227, 225, 219, 184, 120, 98, 80, 59, 132, 198, 211, 213, 214, 215, 214, 213, 209, 195, 161, 120, 80, 51, 34, 24, 22, 22, 23, 23, 25, 27, 28, 29, 29, 30, 31, 31, 31, 31, 31, 30, 30, 29, 29, 29, 29, 29, 30, 30, 30, 30, 29, 29, 29, 29, 28, 27, 25, 22, 21, 21, 19, 16, 13, 15, 19, 22, 24, 25, 27, 29, 29, 29, 29, 30, 30, 30, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 109, 114, 118, 99, 110, 107, 107, 107, 107, 73, 50, 77, 20, 18, 20, 18, 16, 16, 17, 17, 17, 16, 25, 34, 31, 23, 15, 37, 100, 71, 58, 70, 31, 58, 92, 100, 97, 157, 190, 209, 212, 211, 208, 209, 210, 217, 224, 229, 232, 234, 237, 240, 240, 243, 244, 244, 245, 245, 245, 245, 245, 245, 245, 246, 245, 245, 244, 243, 240, 232, 219, 183, 165, 180, 181, 182, 183, 170, 205, 249, 206, 240, 168, 167, 165, 120, 120, 148, 166, 197, 220, 227, 226, 222, 218, 211, 191, 192, 189, 164, 135, 110, 144, 219, 219, 214, 203, 206, 188, 154, 69, 66, 83, 88, 90, 91, 92, 94, 99, 115, 130, 142, 147, 147, 147, 147, 147, 148, 146, 219, 219, 220, 221, 223, 224, 227, 232, 252, 252, 251, 250, 251, 251, 253, 255, 255, 255, 251, 136, 86, 79, 77, 80, 89, 95, 100, 103, 106, 107, 107, 108, 108, 108, 108, 108, 108, 108, 108, 109, 109, 111, 114, 119, 128, 142, 160, 175, 180, 183, 180, 166, 158, 157, 157, 157, 158, 164, 178, 186, 204, 221, 208, 187, 205, 226, 225, 220, 200, 217, 228, 225, 220, 219, 219, 216, 197, 138, 107, 74, 86, 166, 200, 204, 206, 207, 207, 206, 204, 192, 158, 119, 80, 53, 36, 25, 22, 22, 22, 23, 24, 26, 28, 29, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 30, 29, 29, 29, 29, 29, 30, 30, 30, 29, 29, 29, 29, 29, 28, 25, 23, 21, 20, 19, 16, 15, 15, 19, 23, 25, 28, 29, 29, 29, 29, 30, 30, 30, 30, 108, 107, 108, 108, 107, 108, 108, 108, 108, 108, 108, 108, 109, 111, 117, 103, 116, 109, 108, 107, 107, 98, 23, 99, 44, 18, 19, 20, 18, 16, 17, 17, 17, 17, 16, 21, 26, 23, 19, 15, 12, 18, 18, 64, 91, 97, 120, 126, 79, 115, 166, 197, 208, 210, 206, 207, 209, 214, 221, 225, 229, 231, 234, 236, 239, 240, 242, 244, 244, 244, 245, 245, 245, 245, 245, 245, 244, 244, 242, 239, 233, 223, 214, 151, 137, 175, 178, 169, 199, 243, 252, 239, 220, 195, 165, 180, 187, 189, 188, 197, 220, 241, 247, 249, 251, 247, 234, 234, 249, 252, 248, 241, 207, 144, 128, 219, 221, 214, 211, 204, 201, 198, 154, 70, 64, 85, 89, 91, 91, 92, 93, 93, 93, 94, 110, 128, 142, 146, 146, 146, 138, 208, 219, 219, 221, 222, 224, 226, 227, 230, 229, 229, 231, 234, 237, 240, 245, 252, 255, 255, 231, 130, 77, 73, 72, 73, 73, 74, 75, 77, 84, 90, 95, 101, 106, 108, 108, 108, 108, 108, 109, 110, 111, 112, 123, 133, 144, 153, 158, 158, 157, 157, 156, 156, 155, 155, 155, 156, 156, 156, 158, 165, 178, 210, 211, 182, 193, 221, 210, 206, 218, 223, 221, 215, 213, 213, 212, 186, 125, 108, 76, 124, 187, 196, 197, 198, 199, 199, 198, 189, 157, 116, 80, 55, 37, 25, 22, 22, 23, 23, 24, 25, 28, 29, 29, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30, 29, 29, 29, 29, 29, 30, 30, 30, 29, 29, 29, 29, 28, 25, 23, 21, 20, 19, 17, 15, 17, 20, 24, 28, 29, 29, 29, 30, 30, 30, 30, 30, 30, 108, 107, 107, 107, 107, 107, 107, 108, 108, 108, 108, 108, 109, 109, 117, 104, 119, 115, 109, 109, 108, 108, 57, 80, 94, 21, 18, 20, 20, 16, 16, 17, 17, 17, 18, 17, 16, 20, 19, 17, 14, 12, 16, 17, 16, 24, 33, 65, 83, 125, 144, 187, 205, 210, 205, 205, 208, 212, 217, 221, 224, 228, 231, 233, 235, 238, 240, 241, 242, 244, 243, 244, 244, 244, 244, 243, 243, 241, 237, 232, 224, 215, 207, 91, 46, 128, 178, 205, 223, 244, 249, 204, 228, 143, 178, 189, 191, 191, 197, 219, 236, 244, 248, 250, 241, 240, 253, 254, 254, 253, 253, 250, 242, 224, 162, 206, 222, 227, 213, 205, 200, 198, 197, 135, 72, 103, 154, 97, 92, 92, 93, 93, 93, 93, 93, 93, 96, 113, 132, 145, 146, 188, 219, 219, 221, 222, 223, 224, 221, 224, 234, 240, 247, 254, 255, 255, 255, 255, 255, 255, 245, 222, 86, 75, 72, 71, 71, 71, 71, 72, 73, 74, 74, 75, 75, 81, 89, 96, 105, 107, 107, 107, 108, 104, 98, 104, 121, 141, 154, 156, 156, 155, 155, 155, 155, 155, 155, 154, 150, 146, 144, 148, 157, 160, 189, 207, 175, 181, 210, 216, 214, 213, 213, 210, 209, 210, 208, 160, 113, 106, 100, 162, 191, 193, 193, 193, 194, 193, 186, 154, 113, 80, 57, 39, 26, 22, 22, 23, 24, 24, 25, 27, 29, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30, 29, 29, 29, 29, 30, 30, 30, 29, 29, 29, 29, 28, 26, 23, 21, 20, 18, 17, 15, 18, 21, 26, 29, 29, 30, 30, 30, 30, 30, 30, 30, 31, 107, 107, 107, 107, 107, 107, 107, 107, 107, 108, 108, 108, 109, 108, 114, 105, 118, 120, 116, 110, 108, 107, 94, 68, 108, 73, 18, 18, 21, 19, 15, 17, 17, 17, 17, 17, 17, 15, 14, 17, 17, 13, 12, 16, 17, 22, 33, 26, 23, 36, 91, 151, 202, 210, 207, 206, 207, 210, 213, 217, 220, 223, 226, 229, 231, 234, 236, 238, 240, 240, 241, 242, 242, 242, 241, 240, 238, 235, 230, 223, 215, 209, 160, 115, 177, 188, 186, 195, 209, 221, 220, 191, 159, 168, 191, 196, 196, 197, 204, 221, 235, 243, 244, 239, 251, 253, 254, 254, 254, 254, 254, 253, 249, 246, 237, 233, 239, 232, 219, 215, 208, 197, 196, 190, 85, 69, 154, 174, 129, 90, 93, 93, 93, 93, 93, 93, 93, 93, 94, 111, 138, 164, 218, 220, 221, 219, 222, 229, 244, 252, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 254, 250, 181, 82, 75, 72, 73, 75, 71, 72, 71, 73, 73, 73, 73, 74, 74, 74, 73, 79, 88, 97, 105, 106, 105, 101, 91, 85, 98, 119, 129, 138, 151, 154, 152, 146, 152, 149, 143, 137, 132, 129, 131, 148, 154, 169, 197, 168, 187, 215, 211, 207, 206, 206, 207, 208, 195, 129, 112, 111, 140, 182, 189, 190, 190, 190, 190, 185, 154, 111, 80, 60, 41, 27, 23, 22, 23, 24, 24, 25, 27, 28, 29, 30, 31, 31, 31, 31, 31, 32, 31, 31, 31, 31, 31, 31, 31, 30, 29, 29, 29, 29, 30, 30, 30, 28, 29, 29, 29, 28, 26, 23, 21, 20, 18, 17, 16, 19, 23, 28, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 108, 107, 110, 115, 108, 120, 122, 121, 110, 107, 107, 83, 95, 107, 51, 17, 19, 20, 19, 14, 17, 17, 17, 16, 18, 18, 16, 13, 14, 16, 12, 12, 17, 17, 22, 25, 19, 18, 23, 49, 144, 206, 209, 207, 207, 209, 210, 213, 216, 219, 220, 223, 225, 228, 230, 232, 234, 235, 236, 237, 236, 235, 234, 231, 227, 223, 218, 212, 182, 125, 153, 185, 185, 185, 185, 187, 194, 194, 162, 187, 158, 187, 201, 203, 201, 198, 203, 216, 229, 237, 237, 249, 253, 254, 254, 254, 254, 254, 254, 254, 252, 249, 247, 250, 246, 235, 239, 234, 214, 202, 196, 195, 137, 74, 69, 172, 193, 177, 121, 116, 91, 92, 93, 93, 93, 93, 93, 93, 99, 115, 192, 217, 219, 228, 246, 253, 253, 253, 253, 254, 254, 254, 254, 255, 255, 255, 255, 255, 254, 254, 250, 144, 87, 124, 150, 163, 93, 91, 98, 74, 73, 72, 72, 73, 73, 74, 74, 75, 77, 79, 111, 95, 93, 103, 105, 102, 93, 83, 82, 90, 98, 120, 145, 141, 117, 123, 133, 130, 124, 120, 117, 117, 138, 153, 156, 184, 163, 198, 208, 205, 205, 204, 203, 203, 166, 113, 113, 115, 163, 185, 188, 189, 188, 188, 185, 156, 110, 79, 63, 43, 29, 23, 22, 23, 24, 23, 24, 26, 28, 29, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30, 29, 29, 29, 29, 30, 30, 28, 29, 29, 29, 29, 26, 24, 21, 20, 18, 16, 18, 21, 25, 29, 29, 30, 30, 30, 30, 30, 30, 31, 31, 32, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 108, 118, 106, 120, 118, 117, 112, 108, 108, 100, 62, 109, 102, 33, 18, 19, 19, 17, 15, 17, 17, 17, 15, 18, 20, 18, 15, 13, 14, 13, 15, 17, 16, 18, 19, 17, 18, 21, 28, 111, 196, 208, 208, 208, 209, 210, 213, 215, 216, 219, 220, 221, 224, 224, 227, 228, 228, 228, 226, 224, 221, 217, 214, 210, 185, 120, 118, 179, 186, 185, 185, 181, 179, 175, 154, 168, 182, 158, 181, 205, 208, 207, 202, 198, 201, 210, 222, 237, 248, 253, 253, 254, 254, 254, 254, 254, 254, 254, 253, 252, 253, 250, 245, 249, 253, 239, 215, 205, 200, 195, 169, 74, 73, 115, 193, 221, 197, 168, 187, 170, 148, 116, 90, 93, 94, 94, 94, 95, 106, 146, 222, 252, 253, 253, 254, 254, 253, 254, 254, 254, 254, 254, 255, 255, 254, 254, 254, 254, 255, 242, 173, 203, 196, 202, 187, 181, 181, 173, 149, 78, 68, 69, 67, 66, 97, 148, 142, 149, 194, 181, 99, 96, 125, 131, 111, 103, 99, 98, 79, 84, 91, 121, 138, 112, 93, 108, 116, 113, 109, 107, 109, 131, 153, 149, 176, 161, 203, 203, 203, 203, 199, 187, 127, 112, 112, 118, 172, 185, 188, 188, 187, 186, 158, 110, 80, 66, 46, 30, 24, 22, 23, 24, 23, 23, 25, 27, 29, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30, 29, 29, 29, 29, 30, 30, 29, 29, 29, 29, 29, 27, 24, 21, 19, 18, 16, 19, 23, 28, 29, 29, 30, 30, 30, 30, 30, 30, 31, 32, 32, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 114, 107, 112, 114, 113, 112, 109, 108, 108, 71, 97, 109, 96, 25, 18, 19, 18, 16, 16, 17, 17, 17, 15, 18, 23, 22, 17, 14, 14, 15, 15, 16, 16, 18, 18, 18, 23, 25, 25, 62, 169, 207, 207, 209, 209, 210, 212, 213, 214, 215, 217, 218, 220, 219, 220, 219, 217, 215, 213, 211, 208, 177, 110, 57, 113, 160, 161, 162, 176, 159, 161, 160, 166, 172, 155, 159, 187, 206, 212, 210, 204, 197, 197, 201, 211, 232, 245, 252, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 250, 247, 253, 254, 253, 230, 217, 220, 209, 200, 188, 74, 79, 76, 161, 225, 242, 208, 176, 190, 190, 190, 183, 164, 139, 99, 95, 95, 96, 104, 154, 252, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, 249, 216, 207, 201, 202, 201, 185, 209, 210, 206, 186, 155, 108, 77, 77, 104, 177, 207, 207, 208, 203, 199, 196, 197, 171, 154, 168, 192, 152, 117, 76, 77, 86, 109, 105, 85, 88, 102, 103, 101, 102, 106, 129, 154, 143, 162, 179, 202, 202, 202, 194, 153, 113, 112, 112, 123, 179, 184, 187, 187, 186, 161, 109, 81, 69, 47, 31, 24, 22, 23, 24, 24, 23, 25, 27, 29, 30, 30, 31, 31, 32, 32, 32, 32, 31, 32, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30, 29, 29, 29, 30, 30, 29, 29, 29, 29, 29, 27, 24, 21, 19, 17, 17, 21, 25, 29, 29, 30, 30, 30, 30, 30, 30, 31, 31, 32, 32, 108, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 108, 107, 106, 108, 110, 107, 111, 111, 111, 107, 107, 107, 104, 67, 109, 111, 92, 20, 18, 18, 17, 15, 15, 18, 17, 17, 15, 15, 24, 30, 22, 17, 15, 15, 16, 16, 16, 19, 19, 24, 25, 25, 26, 29, 132, 199, 207, 208, 209, 209, 210, 210, 211, 212, 212, 212, 212, 211, 210, 208, 207, 195, 161, 96, 33, 61, 114, 157, 176, 172, 174, 162, 170, 152, 160, 156, 162, 181, 192, 208, 213, 212, 202, 196, 195, 196, 201, 217, 242, 248, 252, 253, 254, 254, 254, 254, 254, 254, 254, 253, 253, 249, 247, 252, 254, 254, 249, 228, 230, 239, 225, 209, 196, 91, 80, 80, 103, 194, 210, 207, 179, 180, 189, 174, 188, 207, 217, 209, 173, 131, 101, 102, 109, 247, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 251, 244, 241, 237, 235, 231, 227, 223, 221, 216, 189, 209, 210, 211, 212, 212, 192, 154, 87, 79, 127, 197, 214, 214, 210, 210, 210, 211, 211, 206, 204, 198, 195, 135, 96, 74, 73, 73, 82, 83, 80, 93, 97, 97, 98, 104, 134, 152, 138, 159, 200, 202, 200, 179, 114, 113, 112, 111, 134, 182, 184, 185, 186, 161, 107, 81, 72, 49, 31, 24, 22, 22, 23, 24, 23, 25, 27, 28, 30, 30, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 31, 31, 31, 31, 31, 31, 31, 31, 31, 29, 29, 29, 30, 29, 29, 29, 29, 29, 29, 26, 24, 21, 18, 16, 18, 22, 27, 29, 29, 30, 30, 30, 30, 30, 30, 31, 32, 32, 32, 108, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 108, 107, 107, 106, 106, 109, 107, 109, 109, 110, 106, 106, 107, 107, 91, 88, 112, 112, 90, 25, 41, 21, 17, 16, 15, 17, 17, 17, 16, 14, 19, 27, 25, 18, 15, 14, 16, 16, 16, 20, 25, 25, 25, 25, 27, 26, 63, 147, 197, 208, 208, 208, 208, 207, 208, 208, 207, 207, 204, 186, 153, 105, 46, 29, 44, 105, 115, 124, 135, 123, 146, 145, 148, 152, 168, 175, 178, 186, 187, 206, 214, 211, 199, 196, 195, 195, 197, 203, 224, 244, 249, 251, 253, 254, 254, 254, 254, 254, 254, 253, 250, 247, 249, 252, 253, 254, 253, 246, 233, 246, 250, 240, 217, 201, 114, 80, 79, 80, 155, 179, 182, 184, 175, 189, 200, 219, 216, 203, 206, 235, 244, 204, 131, 109, 236, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 245, 227, 232, 246, 251, 253, 254, 254, 252, 245, 220, 223, 201, 200, 209, 210, 210, 211, 212, 210, 201, 176, 114, 98, 173, 214, 214, 214, 214, 215, 214, 210, 212, 210, 206, 201, 191, 150, 127, 70, 69, 80, 84, 78, 87, 92, 92, 98, 106, 144, 140, 126, 198, 201, 202, 140, 109, 112, 111, 102, 150, 183, 183, 183, 155, 102, 81, 75, 52, 31, 23, 22, 22, 23, 24, 24, 25, 27, 28, 30, 30, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 31, 31, 31, 31, 31, 31, 31, 31, 30, 29, 29, 30, 29, 29, 29, 29, 29, 29, 26, 23, 20, 16, 15, 18, 23, 28, 29, 30, 30, 30, 30, 30, 31, 31, 32, 31, 31, 31, 108, 108, 108, 107, 107, 107, 107, 107, 107, 107, 108, 108, 107, 108, 107, 107, 108, 109, 109, 109, 108, 107, 107, 108, 107, 110, 96, 106, 113, 115, 99, 89, 69, 17, 17, 24, 52, 17, 18, 24, 20, 17, 16, 16, 16, 16, 16, 15, 16, 17, 18, 30, 28, 25, 25, 25, 27, 27, 26, 49, 119, 163, 190, 197, 195, 187, 175, 155, 125, 74, 31, 28, 28, 28, 53, 139, 166, 183, 181, 174, 166, 162, 175, 178, 180, 179, 186, 187, 179, 200, 213, 212, 199, 196, 195, 195, 195, 197, 205, 227, 246, 250, 252, 254, 254, 254, 254, 254, 253, 253, 247, 242, 247, 253, 254, 254, 254, 253, 246, 243, 251, 253, 249, 224, 205, 134, 80, 79, 77, 142, 175, 183, 203, 219, 208, 195, 195, 190, 191, 200, 218, 253, 254, 244, 168, 227, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 246, 225, 221, 245, 253, 254, 254, 254, 254, 254, 254, 253, 228, 226, 223, 184, 200, 209, 209, 209, 210, 211, 209, 206, 198, 172, 159, 160, 212, 214, 214, 214, 214, 214, 215, 215, 213, 207, 205, 201, 181, 109, 75, 69, 82, 82, 76, 81, 78, 84, 99, 114, 154, 118, 198, 200, 185, 108, 112, 111, 100, 92, 167, 183, 182, 154, 93, 80, 78, 56, 32, 23, 21, 22, 23, 24, 25, 25, 26, 28, 30, 30, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 31, 31, 31, 31, 31, 31, 30, 29, 30, 30, 29, 29, 29, 29, 29, 28, 26, 23, 19, 15, 15, 19, 25, 29, 29, 30, 30, 30, 30, 31, 30, 32, 32, 32, 31, 32, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 107, 106, 106, 108, 108, 108, 109, 109, 108, 107, 107, 113, 110, 93, 108, 113, 118, 106, 96, 56, 28, 16, 52, 79, 28, 61, 50, 21, 19, 16, 15, 17, 16, 17, 16, 19, 23, 25, 30, 30, 27, 26, 25, 26, 27, 27, 26, 26, 27, 37, 34, 29, 27, 27, 26, 26, 27, 29, 97, 158, 189, 192, 191, 190, 189, 188, 182, 165, 165, 174, 174, 177, 187, 183, 186, 210, 211, 198, 195, 195, 195, 195, 195, 197, 207, 228, 246, 250, 252, 254, 254, 254, 254, 254, 253, 247, 242, 244, 252, 253, 254, 254, 254, 253, 248, 250, 252, 253, 252, 231, 209, 150, 80, 79, 102, 176, 200, 218, 209, 209, 179, 207, 221, 222, 245, 241, 213, 228, 254, 254, 252, 237, 254, 254, 254, 254, 254, 254, 248, 238, 235, 231, 220, 214, 235, 251, 254, 254, 254, 254, 254, 254, 254, 254, 253, 244, 219, 225, 210, 102, 128, 162, 189, 205, 210, 210, 209, 209, 209, 201, 158, 135, 208, 213, 213, 214, 214, 209, 195, 178, 186, 206, 205, 202, 197, 169, 94, 69, 78, 78, 76, 69, 67, 88, 101, 133, 141, 203, 204, 136, 111, 109, 97, 89, 107, 180, 182, 155, 91, 81, 79, 63, 34, 24, 21, 22, 22, 23, 25, 25, 26, 28, 29, 31, 31, 31, 32, 32, 33, 33, 33, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 31, 31, 31, 31, 31, 30, 29, 30, 30, 29, 29, 29, 29, 29, 28, 26, 22, 17, 15, 16, 20, 26, 29, 29, 30, 30, 30, 30, 30, 31, 31, 32, 32, 32, 33, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 107, 107, 108, 108, 108, 105, 105, 105, 107, 107, 107, 107, 106, 106, 107, 111, 114, 112, 105, 109, 120, 109, 106, 93, 71, 50, 19, 53, 98, 91, 88, 34, 25, 47, 39, 18, 17, 20, 23, 19, 28, 28, 24, 30, 30, 28, 27, 27, 27, 27, 27, 27, 26, 26, 25, 25, 26, 29, 33, 39, 92, 164, 192, 193, 193, 193, 193, 193, 192, 192, 191, 191, 167, 171, 161, 178, 187, 174, 205, 211, 199, 196, 195, 195, 195, 195, 195, 197, 208, 228, 247, 250, 252, 254, 254, 254, 254, 253, 250, 242, 242, 251, 253, 254, 254, 254, 254, 254, 250, 252, 253, 253, 252, 236, 213, 162, 81, 79, 86, 197, 219, 220, 208, 172, 207, 211, 211, 223, 244, 252, 253, 226, 242, 254, 254, 251, 248, 247, 249, 251, 239, 224, 219, 223, 223, 221, 217, 245, 253, 254, 254, 254, 254, 254, 254, 253, 253, 253, 251, 251, 221, 227, 224, 192, 185, 168, 153, 137, 130, 140, 154, 162, 171, 174, 156, 77, 115, 162, 157, 149, 123, 139, 169, 200, 212, 211, 208, 205, 204, 184, 103, 69, 70, 75, 76, 74, 67, 68, 93, 110, 140, 209, 192, 110, 104, 89, 86, 88, 131, 182, 158, 90, 81, 80, 69, 37, 26, 22, 22, 22, 24, 24, 26, 26, 28, 29, 31, 31, 31, 32, 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 32, 32, 32, 32, 32, 32, 31, 31, 31, 31, 30, 29, 30, 30, 29, 29, 29, 29, 29, 28, 25, 20, 15, 14, 18, 23, 28, 29, 30, 30, 30, 30, 31, 31, 32, 32, 31, 32, 33, 33, 107, 108, 108, 108, 108, 108, 108, 108, 109, 109, 109, 109, 110, 111, 112, 107, 106, 105, 106, 108, 108, 108, 107, 107, 108, 110, 116, 121, 115, 106, 101, 101, 98, 106, 97, 69, 41, 27, 64, 101, 106, 92, 80, 93, 74, 25, 20, 22, 21, 24, 27, 29, 29, 23, 30, 32, 30, 28, 28, 29, 28, 28, 28, 29, 32, 35, 38, 42, 54, 142, 189, 192, 193, 194, 195, 195, 196, 196, 197, 197, 196, 196, 196, 164, 160, 179, 176, 188, 209, 201, 196, 195, 195, 195, 195, 195, 195, 198, 208, 227, 246, 250, 253, 254, 254, 254, 253, 251, 242, 241, 247, 253, 254, 254, 254, 254, 254, 254, 253, 253, 254, 253, 252, 241, 217, 175, 79, 80, 79, 195, 219, 212, 177, 200, 219, 221, 222, 245, 252, 252, 252, 254, 221, 242, 237, 233, 231, 225, 221, 220, 222, 222, 221, 221, 216, 231, 252, 254, 254, 254, 254, 254, 254, 253, 250, 248, 248, 248, 249, 250, 230, 230, 225, 217, 191, 189, 180, 168, 174, 156, 123, 146, 173, 168, 167, 167, 129, 119, 186, 200, 207, 208, 209, 210, 210, 211, 211, 210, 206, 202, 168, 120, 71, 72, 75, 75, 70, 66, 69, 88, 108, 184, 142, 96, 85, 85, 86, 86, 155, 161, 91, 81, 80, 74, 42, 27, 23, 22, 23, 24, 24, 25, 26, 27, 29, 30, 31, 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 32, 32, 32, 32, 31, 31, 31, 31, 31, 29, 30, 30, 30, 30, 29, 29, 29, 28, 24, 19, 14, 15, 20, 25, 29, 29, 30, 30, 30, 31, 31, 32, 32, 32, 33, 33, 33, 34, 108, 108, 108, 108, 108, 108, 108, 109, 109, 111, 111, 111, 112, 113, 114, 110, 106, 105, 106, 107, 107, 99, 111, 113, 111, 112, 117, 117, 115, 116, 127, 129, 125, 113, 101, 99, 90, 77, 96, 103, 106, 105, 106, 103, 94, 76, 28, 22, 22, 25, 33, 30, 25, 30, 21, 28, 35, 37, 34, 32, 33, 32, 31, 34, 38, 43, 50, 76, 168, 190, 192, 193, 194, 195, 196, 196, 197, 197, 197, 197, 197, 197, 197, 183, 154, 176, 161, 204, 205, 196, 195, 195, 195, 195, 195, 195, 195, 198, 208, 226, 246, 250, 252, 254, 254, 254, 253, 247, 242, 242, 251, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 244, 222, 187, 77, 80, 82, 167, 217, 187, 193, 218, 220, 221, 227, 243, 247, 250, 242, 248, 233, 212, 216, 216, 214, 219, 221, 221, 221, 221, 221, 221, 231, 253, 254, 254, 254, 254, 254, 254, 242, 222, 217, 214, 214, 222, 228, 228, 220, 223, 220, 217, 188, 142, 90, 84, 87, 87, 87, 87, 110, 159, 187, 194, 200, 185, 153, 204, 206, 207, 208, 210, 210, 211, 211, 211, 209, 208, 199, 174, 107, 65, 68, 71, 77, 84, 92, 102, 95, 63, 82, 79, 78, 79, 82, 95, 160, 91, 80, 80, 77, 50, 29, 23, 22, 23, 24, 24, 24, 26, 28, 29, 30, 31, 31, 32, 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 32, 32, 32, 32, 31, 31, 31, 31, 30, 29, 30, 30, 30, 29, 29, 29, 27, 22, 16, 14, 17, 23, 27, 29, 29, 30, 30, 30, 31, 32, 32, 31, 32, 33, 33, 33, 33, 108, 108, 109, 105, 97, 90, 101, 108, 107, 107, 110, 111, 111, 113, 116, 115, 107, 106, 106, 104, 103, 133, 141, 119, 119, 105, 111, 120, 128, 128, 128, 130, 132, 136, 138, 126, 110, 99, 101, 106, 106, 106, 106, 106, 103, 97, 30, 27, 22, 28, 32, 38, 38, 25, 25, 17, 23, 36, 44, 45, 40, 40, 43, 47, 51, 55, 62, 166, 190, 192, 193, 195, 196, 196, 196, 196, 197, 197, 197, 197, 197, 197, 197, 198, 153, 162, 168, 205, 198, 196, 195, 195, 195, 195, 195, 195, 195, 197, 207, 224, 245, 250, 253, 254, 254, 254, 252, 247, 245, 246, 252, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 247, 224, 195, 83, 79, 81, 143, 198, 188, 216, 220, 221, 221, 230, 237, 241, 243, 235, 217, 214, 200, 201, 202, 203, 201, 213, 220, 220, 221, 222, 237, 251, 253, 253, 254, 254, 254, 254, 244, 225, 217, 218, 220, 218, 208, 182, 198, 221, 205, 165, 117, 102, 97, 91, 86, 85, 86, 86, 87, 90, 92, 96, 126, 158, 198, 172, 178, 204, 205, 205, 193, 189, 182, 172, 162, 150, 138, 130, 107, 102, 106, 110, 113, 112, 112, 112, 110, 79, 58, 71, 70, 71, 73, 76, 111, 93, 80, 80, 79, 58, 31, 25, 22, 23, 24, 25, 24, 25, 27, 29, 30, 31, 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 32, 32, 32, 31, 31, 31, 31, 31, 29, 30, 30, 30, 29, 29, 29, 26, 20, 14, 15, 19, 25, 29, 29, 29, 30, 30, 31, 31, 31, 32, 32, 33, 33, 33, 33, 33, 103, 85, 65, 73, 85, 66, 79, 107, 107, 98, 87, 100, 109, 111, 114, 117, 115, 108, 102, 114, 140, 140, 136, 131, 114, 115, 128, 128, 128, 128, 123, 126, 135, 140, 146, 148, 145, 141, 127, 114, 104, 97, 97, 105, 107, 97, 52, 49, 22, 30, 32, 33, 44, 49, 29, 25, 20, 21, 33, 46, 56, 54, 53, 58, 64, 68, 125, 189, 191, 193, 194, 195, 196, 196, 196, 197, 197, 197, 197, 197, 197, 197, 197, 197, 176, 128, 183, 201, 196, 196, 195, 195, 195, 195, 195, 195, 195, 197, 206, 222, 242, 250, 252, 253, 254, 254, 252, 250, 247, 250, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 247, 224, 199, 100, 79, 80, 117, 193, 212, 220, 220, 221, 222, 230, 233, 233, 229, 223, 209, 209, 212, 218, 220, 220, 219, 207, 199, 209, 221, 230, 249, 253, 253, 252, 252, 252, 253, 253, 214, 221, 221, 221, 220, 220, 220, 212, 158, 140, 112, 109, 106, 101, 97, 91, 85, 85, 86, 86, 88, 90, 95, 100, 104, 103, 111, 108, 101, 108, 121, 104, 98, 98, 99, 99, 97, 97, 97, 96, 96, 97, 106, 112, 112, 112, 112, 112, 96, 62, 56, 63, 64, 66, 68, 70, 81, 80, 80, 79, 66, 34, 27, 23, 23, 24, 25, 25, 25, 27, 28, 30, 31, 32, 32, 32, 33, 34, 34, 34, 34, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 32, 32, 31, 31, 31, 31, 31, 30, 29, 30, 30, 30, 29, 28, 23, 17, 14, 17, 23, 28, 29, 29, 30, 30, 30, 31, 32, 32, 32, 33, 34, 34, 34, 34, 34, 96, 92, 87, 111, 107, 100, 90, 108, 107, 106, 92, 91, 78, 102, 111, 116, 119, 114, 100, 139, 140, 138, 132, 105, 98, 101, 118, 125, 121, 109, 104, 121, 135, 143, 148, 150, 150, 151, 150, 149, 145, 141, 139, 126, 109, 104, 76, 54, 39, 62, 36, 32, 34, 46, 56, 43, 26, 21, 22, 24, 24, 29, 33, 37, 43, 59, 176, 189, 191, 193, 194, 195, 196, 196, 196, 197, 197, 197, 197, 197, 197, 197, 197, 196, 193, 107, 196, 199, 196, 195, 195, 195, 195, 195, 195, 195, 195, 197, 204, 218, 240, 249, 251, 253, 254, 254, 254, 253, 252, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 246, 222, 197, 121, 79, 80, 122, 204, 220, 220, 221, 221, 223, 227, 229, 226, 220, 213, 220, 216, 218, 215, 218, 220, 220, 220, 220, 205, 204, 243, 252, 253, 249, 247, 248, 251, 253, 245, 196, 221, 220, 220, 220, 220, 211, 156, 112, 111, 110, 109, 106, 102, 97, 91, 85, 86, 85, 82, 83, 90, 95, 101, 106, 111, 109, 100, 101, 108, 105, 100, 97, 97, 96, 95, 94, 94, 93, 93, 93, 94, 96, 110, 112, 112, 112, 108, 71, 55, 58, 59, 60, 61, 63, 72, 79, 79, 79, 73, 39, 28, 24, 23, 24, 25, 26, 26, 26, 29, 29, 31, 32, 32, 33, 33, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 33, 33, 33, 33, 33, 33, 33, 33, 32, 32, 32, 31, 31, 31, 31, 30, 30, 30, 30, 30, 30, 27, 20, 14, 14, 19, 26, 29, 29, 29, 30, 30, 31, 32, 32, 32, 33, 33, 34, 34, 34, 34, 34, 105, 104, 106, 111, 109, 108, 109, 108, 108, 108, 108, 106, 100, 102, 108, 112, 113, 117, 105, 128, 131, 111, 111, 127, 127, 118, 113, 119, 121, 122, 123, 114, 116, 137, 146, 148, 150, 151, 151, 154, 155, 156, 157, 157, 151, 110, 95, 88, 88, 125, 81, 31, 32, 35, 48, 57, 53, 43, 27, 21, 26, 32, 38, 44, 51, 120, 187, 187, 189, 191, 193, 194, 195, 195, 196, 197, 197, 197, 197, 197, 197, 196, 195, 194, 193, 136, 192, 198, 197, 196, 195, 195, 195, 195, 195, 195, 195, 195, 202, 215, 236, 247, 250, 252, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 244, 219, 196, 146, 80, 81, 148, 216, 220, 220, 221, 221, 223, 225, 224, 219, 217, 220, 220, 220, 220, 217, 211, 208, 209, 210, 219, 223, 220, 223, 253, 249, 241, 242, 246, 252, 253, 220, 204, 220, 220, 220, 220, 189, 120, 113, 111, 110, 110, 110, 108, 105, 97, 91, 81, 75, 89, 105, 108, 107, 106, 105, 105, 103, 102, 99, 99, 101, 98, 94, 86, 80, 85, 85, 84, 82, 79, 75, 67, 60, 63, 83, 110, 112, 112, 89, 65, 51, 56, 56, 57, 59, 72, 80, 79, 79, 77, 47, 30, 25, 23, 24, 25, 26, 26, 27, 28, 29, 30, 32, 32, 33, 33, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 33, 33, 33, 33, 33, 33, 32, 32, 32, 31, 31, 31, 31, 31, 31, 30, 29, 30, 29, 24, 18, 13, 16, 23, 28, 29, 29, 30, 30, 31, 31, 31, 32, 32, 33, 34, 35, 35, 35, 34, 34, 105, 113, 116, 108, 109, 108, 108, 108, 108, 108, 108, 108, 108, 108, 107, 109, 112, 112, 115, 113, 128, 124, 117, 117, 121, 125, 124, 113, 118, 124, 118, 128, 125, 116, 143, 147, 149, 150, 150, 152, 155, 161, 170, 177, 175, 160, 111, 110, 136, 143, 105, 75, 54, 34, 37, 49, 55, 48, 50, 50, 42, 36, 33, 40, 46, 159, 186, 187, 187, 189, 191, 193, 195, 195, 196, 197, 197, 197, 197, 197, 196, 195, 193, 192, 191, 155, 189, 195, 196, 196, 195, 195, 195, 195, 195, 195, 195, 195, 200, 211, 230, 243, 249, 251, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 241, 213, 198, 184, 83, 81, 187, 220, 220, 221, 221, 221, 223, 223, 222, 221, 221, 221, 221, 221, 220, 220, 220, 220, 220, 220, 204, 224, 241, 243, 224, 238, 237, 240, 249, 253, 253, 196, 204, 220, 220, 216, 159, 111, 112, 111, 110, 110, 110, 110, 110, 108, 97, 98, 105, 107, 104, 106, 110, 108, 108, 108, 110, 110, 111, 111, 111, 111, 111, 110, 109, 101, 68, 61, 63, 59, 58, 58, 59, 59, 55, 47, 95, 112, 106, 67, 59, 51, 55, 54, 55, 64, 77, 79, 79, 78, 56, 31, 26, 23, 24, 25, 26, 27, 27, 27, 29, 30, 31, 32, 33, 33, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 33, 33, 33, 33, 33, 32, 32, 32, 31, 31, 31, 31, 31, 31, 30, 29, 28, 22, 16, 14, 18, 25, 29, 29, 29, 30, 30, 31, 32, 32, 32, 33, 33, 35, 35, 35, 35, 35, 35, 111, 120, 109, 108, 109, 108, 108, 108, 107, 107, 107, 107, 109, 110, 107, 108, 110, 111, 113, 110, 114, 130, 135, 135, 138, 139, 138, 135, 132, 112, 116, 128, 128, 112, 131, 146, 147, 150, 150, 152, 158, 166, 182, 195, 200, 196, 178, 140, 149, 149, 144, 120, 48, 36, 37, 41, 51, 57, 52, 44, 44, 52, 57, 61, 70, 180, 185, 185, 186, 188, 190, 192, 194, 194, 196, 196, 197, 197, 197, 197, 196, 194, 192, 190, 190, 161, 188, 194, 196, 196, 195, 195, 195, 195, 195, 195, 195, 195, 197, 207, 226, 238, 246, 250, 252, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 237, 207, 203, 209, 119, 100, 216, 220, 220, 221, 221, 222, 223, 222, 222, 222, 221, 221, 221, 221, 221, 221, 221, 220, 220, 221, 221, 208, 250, 247, 227, 204, 217, 224, 236, 249, 249, 172, 203, 217, 195, 130, 113, 111, 110, 110, 110, 110, 110, 110, 104, 96, 107, 112, 112, 112, 112, 112, 112, 112, 111, 111, 112, 112, 111, 111, 110, 104, 93, 86, 95, 110, 105, 79, 58, 59, 58, 58, 58, 58, 56, 48, 62, 111, 102, 65, 52, 56, 54, 53, 59, 77, 79, 79, 78, 64, 35, 26, 24, 24, 25, 27, 27, 28, 28, 29, 30, 31, 32, 33, 33, 33, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 33, 33, 33, 33, 33, 32, 32, 32, 31, 31, 31, 31, 31, 30, 29, 26, 21, 15, 16, 21, 28, 29, 29, 30, 30, 31, 32, 32, 32, 33, 33, 34, 35, 35, 35, 35, 35, 35, 115, 115, 109, 108, 109, 106, 105, 105, 106, 106, 106, 107, 108, 111, 109, 108, 109, 111, 111, 112, 119, 136, 135, 138, 139, 139, 139, 137, 136, 136, 114, 102, 126, 125, 106, 131, 143, 148, 149, 153, 161, 170, 197, 211, 217, 220, 218, 207, 160, 149, 149, 107, 78, 107, 96, 72, 73, 67, 57, 57, 58, 57, 56, 57, 99, 184, 184, 185, 186, 188, 189, 191, 193, 193, 195, 196, 196, 197, 197, 197, 196, 194, 191, 189, 189, 166, 188, 193, 195, 196, 196, 195, 195, 195, 195, 195, 195, 195, 196, 203, 219, 232, 242, 248, 251, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 251, 232, 203, 206, 212, 161, 150, 220, 220, 221, 221, 221, 222, 222, 222, 222, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 228, 219, 225, 198, 222, 237, 252, 250, 227, 221, 145, 197, 161, 109, 112, 111, 110, 110, 110, 110, 110, 103, 91, 94, 105, 107, 112, 112, 112, 112, 112, 112, 110, 104, 104, 110, 112, 112, 111, 110, 110, 109, 97, 69, 91, 110, 110, 100, 63, 54, 55, 54, 49, 48, 49, 45, 94, 111, 72, 49, 58, 55, 61, 80, 75, 79, 77, 70, 41, 27, 24, 24, 25, 27, 28, 28, 28, 28, 30, 31, 32, 33, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 33, 33, 33, 33, 32, 32, 31, 31, 31, 31, 31, 31, 29, 25, 20, 15, 19, 25, 29, 29, 29, 30, 30, 31, 32, 32, 32, 33, 34, 35, 35, 35, 35, 35, 35, 35, 115, 110, 109, 109, 107, 106, 105, 105, 105, 106, 106, 106, 107, 110, 110, 109, 109, 110, 109, 107, 127, 136, 136, 136, 131, 134, 125, 130, 137, 136, 137, 132, 115, 123, 127, 111, 123, 134, 140, 147, 158, 175, 212, 221, 224, 224, 223, 217, 207, 161, 150, 116, 97, 148, 148, 125, 106, 84, 57, 57, 58, 60, 62, 65, 118, 183, 183, 184, 186, 188, 189, 190, 191, 193, 193, 194, 191, 191, 195, 197, 196, 194, 190, 189, 189, 165, 188, 192, 195, 196, 196, 195, 195, 195, 195, 195, 195, 195, 195, 199, 212, 227, 238, 245, 249, 251, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 246, 224, 203, 208, 206, 194, 191, 220, 220, 221, 221, 221, 222, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 225, 224, 208, 220, 235, 248, 254, 254, 251, 151, 141, 140, 107, 111, 110, 110, 110, 110, 110, 105, 81, 84, 97, 97, 101, 109, 112, 112, 112, 112, 112, 112, 103, 94, 95, 103, 112, 112, 111, 111, 110, 110, 106, 84, 67, 100, 110, 110, 99, 60, 48, 47, 46, 45, 45, 45, 61, 111, 90, 54, 68, 129, 79, 80, 74, 77, 73, 49, 29, 24, 24, 26, 27, 28, 28, 29, 29, 30, 31, 32, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 33, 33, 33, 33, 32, 32, 32, 31, 31, 31, 31, 28, 24, 19, 18, 22, 28, 29, 29, 30, 30, 31, 31, 32, 32, 33, 34, 35, 35, 35, 35, 35, 35, 35, 35, 110, 109, 110, 107, 106, 106, 106, 106, 106, 106, 106, 106, 106, 107, 109, 109, 108, 108, 108, 105, 113, 118, 119, 121, 131, 134, 134, 129, 125, 124, 107, 113, 126, 124, 128, 128, 131, 130, 131, 142, 154, 185, 220, 224, 224, 223, 223, 221, 215, 205, 154, 134, 101, 142, 150, 149, 140, 103, 65, 32, 35, 38, 40, 41, 122, 182, 183, 184, 186, 187, 189, 190, 190, 191, 190, 190, 181, 177, 179, 185, 182, 188, 192, 189, 188, 165, 187, 191, 193, 196, 195, 195, 195, 195, 195, 195, 195, 195, 195, 197, 204, 220, 232, 241, 247, 250, 251, 252, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 251, 239, 214, 206, 212, 201, 208, 219, 220, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 222, 225, 227, 230, 236, 240, 242, 245, 242, 252, 156, 102, 110, 110, 110, 110, 110, 110, 110, 98, 74, 90, 95, 100, 106, 112, 112, 112, 112, 112, 112, 112, 112, 96, 89, 89, 97, 112, 112, 111, 111, 110, 110, 110, 87, 80, 74, 107, 110, 109, 80, 67, 68, 46, 46, 44, 44, 47, 90, 94, 131, 198, 166, 82, 77, 74, 74, 57, 32, 25, 25, 26, 27, 28, 29, 30, 30, 30, 32, 33, 34, 35, 35, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 33, 33, 33, 32, 32, 32, 32, 31, 31, 30, 27, 22, 18, 20, 25, 29, 29, 30, 30, 30, 31, 31, 32, 33, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 109, 109, 111, 106, 106, 105, 105, 105, 105, 105, 105, 106, 106, 106, 107, 108, 107, 108, 108, 107, 114, 136, 138, 138, 137, 137, 135, 136, 136, 129, 121, 116, 125, 126, 130, 132, 137, 143, 146, 152, 163, 204, 214, 218, 223, 223, 221, 220, 219, 210, 200, 146, 79, 135, 150, 150, 150, 143, 103, 31, 25, 25, 28, 33, 119, 182, 182, 183, 187, 188, 190, 191, 191, 192, 192, 191, 192, 192, 192, 191, 189, 173, 162, 184, 189, 166, 186, 190, 192, 194, 195, 195, 195, 195, 195, 195, 195, 195, 195, 196, 199, 210, 226, 237, 243, 247, 249, 251, 251, 252, 253, 253, 254, 254, 254, 254, 254, 254, 253, 252, 252, 247, 229, 205, 215, 217, 201, 219, 220, 220, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 222, 226, 234, 243, 250, 255, 254, 254, 254, 246, 242, 149, 114, 111, 110, 110, 110, 110, 106, 87, 81, 96, 102, 108, 111, 112, 112, 112, 112, 112, 112, 112, 112, 111, 92, 88, 88, 93, 112, 112, 111, 111, 110, 110, 110, 94, 84, 58, 92, 109, 109, 97, 65, 83, 88, 64, 44, 46, 49, 82, 188, 228, 227, 133, 81, 73, 75, 65, 37, 26, 25, 26, 28, 29, 30, 31, 31, 31, 33, 33, 34, 35, 36, 36, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 34, 34, 34, 34, 33, 33, 33, 33, 32, 32, 32, 31, 31, 29, 26, 20, 18, 22, 28, 30, 29, 30, 30, 31, 31, 32, 33, 33, 35, 36, 36, 36, 35, 35, 35, 35, 35, 35, 109, 111, 110, 106, 105, 105, 105, 105, 105, 105, 105, 104, 104, 105, 105, 107, 107, 107, 107, 101, 130, 117, 131, 138, 137, 135, 135, 136, 137, 131, 124, 119, 120, 129, 130, 132, 137, 146, 153, 164, 187, 209, 212, 212, 215, 220, 221, 220, 219, 214, 207, 195, 92, 108, 150, 150, 150, 149, 138, 74, 25, 27, 29, 34, 106, 181, 181, 183, 187, 188, 190, 191, 193, 194, 193, 192, 193, 194, 194, 194, 194, 193, 187, 163, 171, 165, 185, 189, 191, 193, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 197, 202, 218, 229, 238, 243, 246, 248, 249, 250, 250, 252, 252, 253, 253, 253, 253, 252, 251, 250, 248, 239, 209, 215, 220, 214, 212, 220, 220, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 223, 225, 228, 241, 248, 254, 255, 254, 252, 250, 249, 242, 158, 117, 113, 110, 110, 110, 110, 94, 70, 91, 106, 110, 111, 111, 112, 112, 112, 112, 112, 112, 112, 112, 111, 109, 90, 88, 88, 91, 111, 112, 112, 111, 111, 110, 110, 102, 85, 63, 69, 101, 106, 99, 68, 72, 93, 94, 78, 55, 111, 211, 229, 229, 227, 107, 79, 70, 69, 43, 27, 25, 27, 29, 29, 31, 32, 33, 33, 34, 35, 36, 37, 37, 37, 37, 37, 36, 36, 36, 36, 35, 35, 36, 36, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 34, 33, 33, 33, 33, 32, 32, 32, 30, 28, 23, 18, 20, 25, 30, 30, 30, 30, 31, 31, 32, 33, 33, 35, 36, 36, 36, 36, 36, 36, 36, 35, 35, 36, 107, 108, 107, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 106, 107, 107, 106, 95, 114, 131, 116, 124, 134, 124, 121, 120, 120, 121, 122, 121, 128, 129, 131, 137, 147, 156, 167, 187, 210, 215, 211, 211, 212, 214, 219, 219, 218, 217, 210, 206, 188, 90, 149, 150, 150, 150, 149, 104, 29, 31, 33, 43, 83, 181, 181, 182, 187, 188, 191, 192, 193, 195, 194, 193, 194, 194, 195, 195, 195, 195, 192, 186, 170, 154, 185, 189, 191, 192, 194, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 199, 211, 220, 231, 238, 241, 244, 245, 247, 248, 248, 249, 250, 250, 250, 250, 250, 249, 247, 242, 228, 198, 219, 220, 214, 219, 220, 220, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 222, 224, 229, 234, 240, 244, 248, 249, 246, 240, 236, 237, 235, 153, 117, 113, 111, 110, 110, 110, 104, 66, 78, 97, 105, 111, 111, 112, 112, 112, 112, 112, 112, 112, 112, 106, 98, 90, 88, 88, 88, 90, 111, 111, 112, 112, 111, 110, 110, 107, 85, 74, 45, 87, 97, 89, 64, 67, 87, 97, 98, 139, 221, 229, 231, 231, 225, 88, 77, 68, 50, 30, 25, 27, 30, 31, 32, 33, 34, 35, 35, 36, 36, 37, 38, 38, 38, 38, 38, 38, 37, 37, 37, 37, 36, 36, 36, 35, 35, 35, 36, 36, 36, 36, 35, 35, 35, 35, 35, 34, 34, 34, 34, 34, 33, 33, 33, 33, 32, 32, 30, 26, 21, 18, 22, 28, 30, 30, 30, 30, 31, 32, 32, 33, 34, 36, 36, 36, 36, 36, 36, 37, 36, 36, 35, 35, 106, 106, 106, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 106, 108, 107, 95, 132, 141, 135, 103, 109, 112, 120, 127, 116, 127, 128, 129, 123, 129, 137, 147, 154, 160, 170, 188, 211, 222, 222, 218, 212, 212, 214, 217, 218, 217, 215, 214, 209, 206, 179, 139, 150, 149, 149, 149, 133, 33, 36, 38, 45, 63, 173, 180, 181, 185, 188, 191, 192, 194, 195, 195, 195, 194, 195, 196, 196, 197, 195, 193, 190, 184, 163, 184, 188, 190, 191, 192, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 196, 206, 214, 221, 230, 235, 238, 240, 241, 242, 243, 243, 244, 245, 245, 245, 245, 244, 241, 232, 203, 207, 218, 219, 219, 220, 220, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 223, 226, 230, 233, 236, 237, 235, 233, 232, 231, 230, 231, 228, 151, 116, 112, 110, 110, 110, 110, 105, 90, 106, 108, 106, 101, 102, 100, 96, 103, 107, 111, 112, 108, 100, 92, 88, 87, 86, 88, 88, 88, 92, 111, 112, 112, 112, 112, 110, 110, 109, 86, 81, 39, 73, 86, 77, 61, 67, 81, 99, 145, 224, 229, 233, 235, 231, 215, 82, 74, 53, 36, 26, 27, 30, 32, 34, 34, 35, 36, 36, 36, 37, 38, 39, 39, 39, 39, 39, 39, 39, 39, 38, 38, 38, 37, 36, 36, 37, 37, 36, 36, 36, 36, 36, 36, 36, 36, 35, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33, 33, 31, 29, 24, 20, 18, 25, 30, 30, 31, 31, 31, 32, 32, 33, 34, 36, 37, 37, 37, 37, 37, 37, 36, 37, 36, 35, 35, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 106, 107, 117, 142, 142, 132, 112, 127, 127, 127, 127, 127, 128, 128, 126, 127, 138, 151, 156, 160, 168, 183, 206, 222, 224, 223, 221, 219, 215, 215, 217, 216, 213, 200, 203, 211, 210, 205, 189, 147, 149, 149, 149, 150, 79, 42, 43, 47, 60, 153, 180, 181, 183, 187, 190, 192, 194, 195, 196, 196, 196, 196, 197, 198, 198, 196, 194, 191, 187, 181, 176, 187, 189, 191, 192, 193, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 200, 209, 215, 221, 227, 231, 234, 235, 236, 236, 236, 236, 237, 237, 238, 237, 235, 228, 216, 190, 210, 216, 215, 219, 220, 220, 220, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 223, 225, 226, 228, 229, 230, 229, 226, 227, 227, 229, 229, 228, 226, 153, 115, 112, 111, 110, 110, 110, 105, 90, 109, 111, 111, 111, 111, 111, 112, 111, 100, 90, 85, 89, 89, 88, 88, 87, 87, 87, 88, 88, 88, 95, 111, 112, 112, 112, 112, 110, 110, 107, 86, 80, 43, 52, 85, 73, 61, 69, 83, 132, 222, 230, 232, 235, 238, 232, 205, 80, 61, 41, 27, 28, 30, 32, 34, 36, 36, 36, 37, 37, 38, 38, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 39, 38, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 36, 36, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33, 30, 27, 22, 18, 21, 29, 31, 31, 31, 32, 32, 32, 32, 34, 35, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 36, 35, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 119, 142, 140, 114, 87, 112, 112, 114, 107, 127, 128, 127, 125, 131, 151, 157, 159, 167, 178, 199, 220, 224, 223, 222, 221, 220, 219, 217, 216, 211, 190, 196, 204, 209, 210, 209, 205, 193, 143, 150, 149, 149, 117, 47, 48, 53, 60, 126, 179, 180, 181, 187, 189, 192, 193, 195, 196, 197, 197, 197, 198, 199, 199, 198, 196, 192, 190, 186, 173, 187, 188, 191, 191, 193, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 197, 204, 211, 216, 220, 225, 227, 229, 230, 231, 231, 230, 229, 229, 229, 227, 221, 214, 207, 188, 210, 206, 214, 217, 219, 220, 220, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 222, 223, 224, 225, 225, 226, 227, 226, 224, 224, 224, 226, 227, 226, 225, 160, 114, 112, 110, 110, 110, 110, 103, 81, 101, 111, 111, 111, 111, 111, 111, 112, 112, 112, 112, 112, 106, 96, 89, 84, 86, 87, 87, 88, 88, 88, 101, 112, 112, 112, 112, 111, 110, 109, 101, 85, 78, 45, 33, 76, 68, 61, 77, 125, 220, 231, 233, 238, 244, 242, 232, 195, 68, 52, 29, 28, 30, 33, 36, 37, 37, 38, 38, 38, 38, 39, 39, 40, 41, 40, 41, 41, 41, 41, 41, 41, 40, 40, 40, 39, 39, 38, 37, 38, 37, 38, 38, 38, 38, 37, 37, 37, 37, 36, 36, 35, 35, 35, 34, 34, 34, 34, 33, 32, 28, 25, 21, 18, 24, 31, 31, 31, 31, 32, 32, 32, 33, 35, 36, 38, 38, 38, 38, 38, 38, 38, 37, 37, 37, 36, 36, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 104, 111, 139, 138, 127, 126, 127, 126, 127, 117, 126, 126, 127, 127, 130, 148, 154, 160, 173, 190, 214, 224, 224, 223, 222, 220, 220, 219, 216, 215, 211, 199, 195, 185, 199, 210, 210, 209, 206, 193, 142, 150, 148, 138, 49, 49, 65, 60, 77, 173, 179, 181, 184, 188, 191, 193, 195, 197, 197, 198, 198, 199, 199, 199, 198, 197, 194, 192, 188, 168, 193, 187, 189, 191, 192, 194, 195, 195, 195, 195, 195, 195, 195, 195, 195, 196, 201, 206, 210, 214, 217, 221, 224, 225, 225, 225, 224, 224, 223, 220, 215, 213, 209, 191, 199, 202, 203, 213, 215, 217, 218, 220, 221, 221, 221, 221, 221, 221, 221, 221, 221, 222, 223, 223, 224, 224, 224, 223, 222, 222, 222, 222, 223, 224, 224, 214, 157, 113, 112, 110, 110, 110, 110, 103, 81, 87, 106, 111, 111, 111, 111, 111, 112, 112, 112, 112, 112, 112, 112, 111, 111, 111, 104, 98, 86, 88, 89, 94, 110, 112, 112, 112, 111, 109, 109, 106, 90, 85, 77, 45, 34, 54, 64, 65, 120, 218, 232, 234, 241, 245, 245, 239, 229, 185, 62, 39, 26, 30, 34, 36, 37, 38, 38, 39, 39, 39, 40, 40, 41, 42, 42, 41, 42, 42, 42, 42, 42, 42, 41, 41, 40, 40, 40, 39, 39, 39, 39, 39, 39, 39, 39, 38, 38, 37, 37, 36, 36, 36, 35, 35, 35, 34, 34, 34, 33, 30, 26, 24, 20, 20, 28, 31, 32, 32, 32, 33, 33, 33, 34, 36, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 37, 36, 36, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 104, 103, 99, 139, 133, 121, 127, 126, 126, 126, 118, 126, 127, 127, 127, 128, 132, 142, 153, 173, 197, 214, 216, 217, 218, 219, 219, 217, 216, 215, 214, 213, 211, 209, 205, 196, 204, 210, 210, 208, 206, 195, 140, 149, 148, 64, 50, 74, 62, 60, 131, 180, 180, 182, 187, 190, 192, 194, 196, 198, 198, 198, 199, 200, 201, 200, 198, 196, 193, 190, 182, 184, 187, 188, 189, 190, 192, 194, 195, 195, 195, 195, 195, 195, 195, 195, 195, 197, 202, 206, 209, 212, 213, 215, 217, 218, 218, 218, 217, 215, 214, 212, 208, 204, 185, 199, 186, 209, 210, 212, 214, 217, 220, 221, 221, 221, 221, 221, 221, 221, 221, 222, 222, 222, 222, 222, 221, 221, 221, 221, 221, 221, 220, 221, 218, 164, 105, 109, 111, 110, 110, 110, 110, 104, 83, 86, 91, 110, 111, 112, 112, 112, 112, 112, 111, 111, 111, 112, 112, 112, 112, 112, 112, 112, 112, 110, 100, 98, 100, 103, 102, 103, 108, 109, 107, 104, 92, 85, 85, 76, 45, 36, 41, 63, 112, 219, 232, 235, 244, 245, 244, 243, 237, 222, 176, 50, 31, 29, 34, 37, 38, 39, 39, 40, 40, 41, 41, 41, 42, 42, 43, 43, 43, 44, 44, 44, 43, 43, 43, 42, 42, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 35, 34, 34, 32, 28, 25, 23, 19, 24, 31, 31, 32, 33, 33, 33, 34, 34, 35, 37, 39, 39, 39, 39, 39, 39, 38, 38, 38, 38, 37, 37, 37, 104, 104, 104, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 104, 103, 104, 103, 102, 114, 124, 119, 118, 124, 126, 126, 126, 127, 127, 127, 127, 128, 133, 144, 166, 189, 199, 201, 203, 205, 209, 210, 210, 213, 214, 212, 211, 210, 210, 209, 209, 209, 210, 210, 210, 209, 208, 198, 140, 150, 80, 59, 77, 66, 64, 91, 173, 180, 181, 184, 189, 192, 193, 196, 198, 199, 199, 200, 201, 202, 202, 199, 197, 194, 193, 189, 175, 193, 188, 189, 190, 190, 191, 194, 195, 194, 195, 195, 195, 195, 195, 195, 195, 199, 202, 204, 207, 209, 211, 211, 212, 213, 213, 213, 211, 209, 207, 203, 198, 181, 186, 194, 206, 208, 210, 212, 216, 220, 221, 221, 221, 221, 221, 221, 221, 222, 222, 222, 221, 221, 221, 221, 221, 221, 221, 220, 220, 220, 204, 166, 143, 107, 111, 110, 110, 110, 110, 107, 85, 83, 88, 100, 111, 111, 111, 112, 112, 112, 111, 111, 111, 111, 111, 111, 111, 111, 112, 112, 112, 112, 112, 112, 111, 112, 112, 112, 106, 93, 88, 85, 72, 75, 83, 85, 73, 46, 38, 41, 111, 218, 232, 236, 245, 245, 244, 243, 242, 234, 213, 166, 38, 31, 32, 37, 39, 40, 40, 40, 41, 42, 42, 42, 42, 43, 44, 44, 44, 45, 45, 45, 45, 44, 44, 44, 43, 43, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 31, 26, 24, 22, 19, 29, 32, 32, 32, 33, 33, 34, 35, 35, 37, 39, 40, 40, 40, 40, 40, 40, 40, 39, 38, 38, 38, 37, 36, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 103, 103, 104, 104, 104, 105, 102, 103, 105, 110, 110, 109, 122, 123, 115, 127, 127, 129, 134, 143, 166, 186, 190, 190, 192, 194, 199, 201, 205, 211, 211, 210, 210, 209, 209, 209, 210, 210, 210, 210, 210, 210, 210, 209, 200, 141, 85, 75, 77, 69, 67, 97, 153, 180, 180, 182, 187, 190, 192, 195, 197, 198, 199, 200, 202, 203, 203, 202, 199, 196, 194, 192, 177, 196, 188, 188, 190, 190, 190, 191, 193, 194, 194, 196, 195, 195, 195, 195, 195, 195, 198, 201, 203, 205, 206, 208, 209, 210, 209, 208, 206, 204, 201, 199, 183, 191, 176, 198, 203, 203, 206, 209, 215, 220, 220, 221, 221, 221, 221, 221, 222, 222, 222, 221, 221, 221, 221, 221, 221, 221, 220, 220, 216, 192, 187, 193, 116, 111, 110, 110, 110, 110, 109, 89, 80, 91, 84, 105, 111, 111, 111, 111, 110, 110, 109, 109, 109, 109, 109, 109, 109, 109, 111, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 110, 104, 90, 60, 64, 76, 67, 45, 41, 103, 219, 233, 238, 245, 245, 244, 243, 241, 239, 228, 206, 160, 34, 34, 35, 39, 40, 40, 41, 41, 43, 43, 44, 43, 43, 45, 45, 46, 46, 46, 46, 46, 46, 46, 45, 45, 44, 44, 43, 43, 43, 43, 43, 42, 42, 42, 41, 41, 41, 41, 40, 40, 39, 38, 38, 37, 36, 36, 35, 35, 35, 32, 28, 25, 24, 20, 22, 31, 32, 33, 33, 34, 34, 35, 35, 36, 38, 39, 39, 40, 40, 40, 40, 40, 40, 40, 39, 38, 38, 38, 37, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 105, 104, 103, 104, 105, 105, 105, 105, 104, 104, 104, 104, 105, 106, 106, 104, 103, 115, 121, 128, 136, 144, 154, 171, 173, 169, 178, 190, 193, 194, 197, 206, 210, 210, 209, 208, 207, 208, 209, 210, 210, 210, 211, 211, 211, 210, 210, 202, 97, 88, 78, 72, 70, 104, 139, 161, 180, 181, 184, 188, 192, 194, 197, 198, 200, 200, 201, 203, 203, 202, 200, 198, 195, 193, 191, 182, 199, 187, 189, 190, 190, 190, 191, 192, 193, 194, 196, 195, 195, 195, 195, 195, 195, 197, 200, 201, 202, 203, 204, 204, 204, 203, 202, 200, 197, 192, 174, 183, 185, 196, 199, 199, 202, 207, 214, 220, 220, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 220, 220, 220, 201, 199, 214, 217, 140, 114, 111, 110, 110, 110, 109, 94, 77, 88, 85, 84, 110, 111, 109, 107, 104, 99, 91, 89, 89, 88, 88, 87, 85, 85, 94, 111, 112, 112, 112, 112, 112, 112, 112, 111, 111, 110, 108, 111, 112, 111, 97, 62, 62, 56, 43, 105, 218, 233, 239, 245, 244, 244, 243, 241, 239, 235, 217, 200, 158, 35, 36, 37, 40, 41, 41, 41, 43, 44, 43, 44, 45, 46, 46, 47, 47, 48, 48, 47, 47, 47, 46, 46, 46, 46, 45, 45, 45, 45, 44, 44, 44, 43, 43, 42, 42, 41, 41, 41, 40, 40, 39, 38, 38, 37, 37, 36, 35, 35, 31, 26, 24, 23, 19, 28, 33, 33, 33, 33, 34, 35, 35, 36, 37, 39, 40, 40, 40, 39, 39, 40, 40, 40, 40, 40, 39, 38, 38, 37, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 105, 106, 105, 106, 108, 107, 107, 106, 103, 103, 103, 104, 105, 106, 106, 113, 111, 106, 96, 97, 107, 112, 143, 148, 154, 155, 155, 163, 174, 189, 191, 196, 205, 207, 206, 206, 206, 206, 208, 210, 210, 210, 211, 212, 212, 212, 211, 210, 202, 123, 78, 74, 73, 121, 130, 113, 178, 180, 181, 186, 191, 193, 195, 198, 199, 200, 200, 202, 203, 203, 202, 199, 197, 193, 192, 184, 201, 192, 187, 188, 189, 190, 190, 190, 192, 193, 194, 195, 195, 195, 195, 195, 195, 195, 196, 197, 198, 199, 200, 200, 200, 199, 197, 195, 193, 184, 174, 179, 192, 195, 196, 196, 200, 205, 214, 220, 220, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 220, 220, 211, 198, 220, 220, 165, 110, 111, 111, 110, 110, 110, 99, 75, 79, 79, 98, 109, 110, 109, 106, 105, 103, 96, 90, 89, 89, 88, 88, 86, 85, 85, 104, 112, 112, 112, 112, 112, 112, 112, 112, 111, 102, 75, 73, 82, 105, 112, 112, 94, 67, 60, 108, 219, 233, 239, 245, 244, 244, 243, 241, 239, 235, 228, 206, 195, 157, 38, 39, 39, 41, 41, 42, 44, 45, 45, 45, 45, 45, 47, 48, 48, 49, 49, 49, 48, 48, 48, 47, 47, 47, 47, 47, 47, 47, 47, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40, 40, 39, 38, 37, 37, 36, 36, 34, 28, 25, 24, 22, 20, 31, 33, 33, 34, 34, 34, 35, 36, 37, 38, 39, 40, 40, 40, 40, 40, 40, 39, 40, 40, 40, 40, 39, 38, 38, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 105, 106, 106, 107, 109, 111, 111, 108, 109, 110, 109, 104, 103, 104, 104, 104, 107, 113, 127, 125, 116, 110, 113, 120, 133, 149, 154, 154, 154, 154, 154, 151, 165, 187, 190, 199, 204, 204, 205, 205, 205, 206, 209, 210, 210, 212, 213, 213, 213, 213, 212, 210, 204, 125, 76, 73, 140, 109, 141, 144, 180, 181, 182, 188, 192, 194, 196, 198, 200, 200, 201, 202, 203, 202, 199, 198, 194, 193, 190, 185, 207, 189, 187, 188, 189, 190, 190, 190, 192, 193, 193, 194, 195, 195, 195, 195, 195, 195, 195, 195, 196, 196, 196, 195, 194, 192, 191, 189, 165, 187, 177, 192, 193, 195, 195, 198, 203, 214, 220, 220, 221, 221, 220, 220, 220, 220, 221, 221, 221, 220, 220, 220, 220, 220, 220, 212, 220, 220, 193, 103, 103, 104, 108, 110, 110, 107, 76, 75, 93, 108, 110, 110, 110, 107, 105, 104, 102, 94, 89, 89, 88, 88, 87, 86, 86, 88, 110, 111, 112, 112, 112, 112, 112, 112, 111, 110, 83, 63, 63, 66, 77, 99, 95, 78, 59, 121, 218, 233, 239, 245, 244, 244, 243, 240, 238, 235, 230, 212, 200, 190, 158, 39, 40, 41, 42, 42, 44, 46, 46, 46, 46, 46, 47, 48, 49, 50, 50, 49, 49, 49, 49, 49, 49, 48, 49, 48, 49, 49, 48, 48, 47, 47, 46, 46, 45, 45, 44, 43, 43, 42, 42, 41, 40, 40, 39, 39, 37, 37, 36, 32, 26, 24, 24, 21, 25, 33, 33, 33, 34, 34, 35, 36, 37, 38, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 40, 40, 40, 38, 38, 105, 104, 104, 104, 104, 104, 105, 105, 104, 106, 107, 107, 109, 112, 119, 118, 112, 110, 111, 113, 112, 108, 105, 105, 105, 107, 116, 129, 134, 127, 113, 111, 118, 129, 145, 153, 154, 154, 154, 155, 155, 155, 153, 150, 167, 184, 201, 204, 204, 204, 204, 205, 207, 209, 210, 211, 213, 213, 214, 214, 214, 212, 210, 206, 133, 98, 144, 107, 152, 129, 170, 180, 181, 185, 190, 193, 195, 197, 199, 199, 200, 202, 202, 201, 200, 198, 195, 193, 190, 185, 194, 205, 187, 187, 188, 189, 190, 190, 190, 191, 192, 192, 193, 193, 194, 195, 195, 194, 194, 195, 194, 193, 193, 191, 192, 191, 191, 180, 168, 183, 183, 192, 193, 196, 194, 197, 202, 214, 220, 220, 220, 220, 220, 219, 219, 220, 220, 221, 220, 220, 219, 220, 220, 220, 220, 220, 220, 213, 115, 98, 98, 99, 103, 108, 108, 86, 85, 104, 110, 110, 110, 110, 109, 106, 105, 104, 100, 93, 89, 88, 88, 88, 87, 87, 85, 97, 111, 112, 112, 112, 112, 112, 112, 112, 111, 105, 64, 61, 60, 78, 93, 81, 48, 36, 106, 216, 233, 240, 245, 244, 243, 243, 241, 239, 234, 229, 215, 202, 195, 185, 160, 40, 41, 41, 43, 44, 46, 46, 47, 47, 47, 48, 49, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 50, 50, 50, 50, 50, 50, 49, 49, 48, 47, 46, 46, 45, 45, 44, 44, 43, 42, 42, 41, 41, 40, 39, 38, 37, 36, 30, 25, 24, 23, 20, 29, 33, 34, 34, 34, 34, 35, 36, 37, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 40, 40, 39, 38, 106, 105, 105, 105, 105, 105, 105, 105, 106, 115, 116, 117, 121, 124, 123, 119, 113, 112, 112, 115, 116, 116, 113, 112, 114, 121, 126, 126, 124, 121, 113, 117, 127, 146, 157, 159, 156, 156, 157, 157, 157, 158, 156, 155, 157, 157, 184, 199, 202, 202, 202, 204, 205, 208, 210, 211, 213, 214, 214, 214, 215, 214, 211, 210, 206, 153, 110, 142, 151, 130, 109, 179, 180, 181, 186, 192, 194, 196, 198, 198, 200, 201, 201, 201, 200, 198, 196, 193, 191, 189, 183, 197, 204, 187, 187, 188, 188, 189, 189, 190, 190, 190, 191, 191, 191, 191, 192, 192, 193, 193, 193, 191, 191, 191, 191, 191, 186, 168, 179, 177, 188, 192, 193, 195, 194, 196, 201, 214, 220, 220, 220, 220, 216, 208, 214, 220, 220, 220, 220, 219, 203, 219, 220, 220, 220, 220, 219, 152, 95, 93, 94, 96, 99, 101, 87, 93, 109, 110, 110, 110, 110, 110, 107, 104, 105, 104, 99, 93, 89, 88, 88, 88, 88, 87, 85, 106, 111, 112, 112, 112, 112, 112, 112, 112, 110, 88, 57, 81, 100, 88, 52, 33, 36, 92, 214, 233, 241, 245, 245, 244, 243, 241, 238, 233, 228, 213, 201, 196, 189, 181, 161, 42, 42, 41, 44, 46, 47, 47, 47, 47, 48, 49, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 52, 51, 50, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45, 44, 43, 43, 42, 41, 41, 40, 39, 38, 35, 27, 24, 24, 23, 21, 33, 33, 34, 34, 35, 35, 36, 37, 38, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 40, 39, 38, 107, 106, 105, 105, 105, 105, 105, 105, 107, 116, 117, 121, 123, 122, 121, 120, 117, 114, 113, 117, 120, 120, 121, 122, 125, 123, 119, 116, 116, 115, 117, 125, 144, 159, 165, 166, 169, 162, 164, 163, 164, 167, 168, 161, 155, 156, 155, 187, 193, 200, 201, 201, 204, 206, 209, 211, 212, 214, 214, 214, 214, 214, 213, 211, 210, 207, 162, 146, 150, 132, 40, 152, 179, 180, 182, 187, 192, 194, 196, 198, 199, 200, 200, 200, 199, 198, 196, 193, 192, 189, 187, 181, 195, 206, 189, 186, 187, 187, 188, 188, 189, 189, 188, 188, 188, 189, 188, 188, 189, 189, 190, 190, 191, 191, 191, 190, 176, 168, 182, 178, 192, 193, 193, 195, 194, 196, 201, 214, 220, 220, 220, 217, 195, 193, 207, 220, 220, 220, 220, 210, 213, 220, 220, 220, 220, 220, 188, 90, 89, 90, 92, 94, 96, 85, 74, 93, 104, 110, 110, 110, 110, 109, 105, 105, 105, 104, 99, 92, 89, 88, 88, 88, 88, 86, 90, 111, 111, 112, 112, 112, 112, 112, 112, 112, 107, 70, 94, 94, 59, 31, 33, 35, 60, 206, 233, 241, 246, 245, 244, 243, 241, 237, 233, 226, 210, 199, 195, 190, 184, 176, 164, 47, 42, 42, 45, 47, 48, 47, 48, 48, 50, 51, 52, 53, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 54, 53, 53, 52, 51, 51, 50, 49, 50, 49, 48, 48, 48, 47, 46, 45, 44, 43, 43, 42, 41, 40, 40, 39, 34, 26, 24, 24, 23, 25, 34, 34, 34, 34, 35, 35, 36, 37, 39, 40, 40, 40, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 38, 116, 107, 106, 105, 105, 105, 105, 106, 109, 112, 114, 118, 119, 120, 118, 118, 118, 116, 114, 117, 123, 123, 122, 124, 127, 115, 111, 110, 111, 116, 123, 139, 159, 170, 173, 175, 179, 177, 176, 179, 178, 173, 173, 172, 164, 155, 155, 157, 178, 193, 196, 199, 201, 203, 207, 210, 211, 212, 214, 215, 214, 214, 213, 211, 211, 210, 207, 174, 147, 131, 40, 86, 175, 179, 180, 183, 189, 193, 195, 196, 198, 199, 199, 199, 199, 198, 196, 193, 192, 190, 188, 187, 181, 198, 209, 194, 185, 185, 186, 186, 186, 186, 187, 188, 188, 188, 188, 187, 188, 188, 189, 190, 190, 190, 189, 185, 168, 175, 176, 187, 193, 193, 192, 194, 192, 193, 200, 215, 220, 220, 220, 202, 187, 188, 212, 220, 220, 220, 220, 204, 220, 220, 220, 220, 220, 211, 104, 84, 84, 86, 89, 92, 92, 87, 105, 106, 97, 92, 97, 109, 110, 108, 105, 106, 106, 103, 98, 91, 89, 89, 88, 88, 90, 99, 109, 112, 112, 112, 112, 112, 112, 112, 112, 111, 90, 96, 75, 35, 31, 32, 35, 48, 190, 233, 241, 246, 245, 244, 243, 240, 237, 232, 220, 205, 197, 193, 189, 184, 179, 172, 165, 60, 43, 45, 45, 48, 48, 48, 49, 50, 52, 53, 53, 53, 53, 54, 53, 53, 54, 54, 54, 55, 55, 55, 54, 54, 54, 53, 52, 52, 51, 51, 50, 49, 49, 49, 48, 48, 47, 46, 46, 45, 44, 43, 42, 41, 40, 40, 32, 25, 24, 25, 22, 29, 34, 34, 34, 35, 35, 36, 37, 38, 41, 41, 41, 42, 42, 42, 42, 42, 42, 41, 40, 41, 40, 40, 40, 40, 40, 38, 125, 118, 110, 106, 106, 107, 108, 108, 108, 109, 110, 112, 114, 114, 116, 117, 116, 114, 114, 117, 123, 121, 121, 120, 122, 109, 107, 108, 112, 119, 133, 156, 170, 176, 178, 180, 182, 183, 181, 181, 181, 180, 177, 175, 172, 163, 155, 155, 158, 176, 185, 193, 198, 201, 203, 207, 210, 211, 212, 214, 213, 213, 213, 212, 211, 210, 209, 206, 179, 115, 44, 64, 137, 178, 179, 181, 185, 189, 192, 194, 196, 198, 198, 198, 198, 197, 196, 195, 193, 190, 188, 188, 186, 158, 186, 211, 201, 188, 184, 184, 184, 185, 185, 186, 186, 187, 187, 187, 186, 187, 188, 188, 189, 189, 188, 172, 169, 179, 182, 193, 193, 193, 193, 193, 188, 188, 199, 215, 220, 220, 216, 190, 186, 195, 218, 220, 220, 220, 220, 210, 220, 220, 220, 215, 208, 145, 78, 77, 78, 81, 85, 90, 82, 95, 100, 101, 103, 105, 103, 90, 95, 104, 104, 105, 103, 98, 94, 88, 87, 89, 98, 106, 111, 111, 111, 112, 112, 112, 112, 112, 112, 112, 111, 108, 82, 87, 32, 31, 32, 35, 58, 174, 233, 242, 246, 246, 244, 243, 240, 236, 225, 212, 201, 195, 191, 188, 184, 180, 175, 170, 166, 83, 44, 47, 45, 48, 48, 49, 51, 52, 53, 54, 54, 54, 55, 54, 54, 55, 55, 55, 56, 56, 56, 56, 56, 55, 55, 54, 53, 53, 52, 52, 51, 50, 50, 49, 49, 48, 47, 47, 46, 46, 45, 44, 43, 42, 40, 39, 29, 25, 25, 25, 21, 33, 34, 34, 35, 35, 36, 36, 38, 39, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 40, 40, 40, 40, 40, 38, 122, 120, 116, 112, 112, 113, 112, 109, 109, 110, 110, 108, 108, 112, 114, 115, 113, 112, 112, 113, 114, 114, 115, 115, 118, 106, 107, 110, 114, 124, 148, 169, 177, 179, 180, 181, 182, 183, 183, 181, 182, 181, 178, 174, 171, 165, 158, 155, 154, 155, 166, 188, 194, 199, 201, 203, 207, 210, 211, 211, 213, 213, 213, 213, 212, 211, 210, 209, 205, 179, 79, 63, 80, 170, 178, 180, 182, 186, 190, 192, 195, 197, 198, 197, 197, 196, 195, 194, 192, 191, 189, 188, 186, 178, 80, 151, 206, 207, 196, 185, 183, 183, 184, 185, 185, 185, 185, 185, 186, 186, 187, 187, 188, 186, 174, 165, 177, 181, 192, 193, 193, 193, 193, 193, 187, 182, 197, 215, 220, 220, 208, 189, 188, 208, 216, 217, 218, 219, 219, 215, 220, 220, 214, 199, 177, 74, 70, 70, 72, 76, 81, 86, 81, 94, 94, 94, 96, 100, 107, 110, 106, 90, 97, 100, 97, 94, 92, 91, 99, 108, 111, 111, 111, 111, 112, 112, 112, 112, 112, 112, 112, 112, 110, 91, 89, 49, 31, 32, 61, 151, 177, 231, 242, 246, 246, 245, 243, 239, 228, 215, 205, 199, 194, 190, 187, 184, 181, 178, 174, 169, 166, 105, 46, 47, 45, 49, 49, 51, 52, 53, 54, 55, 55, 55, 55, 55, 56, 56, 56, 56, 57, 57, 57, 57, 56, 56, 55, 54, 54, 54, 53, 53, 52, 52, 51, 51, 50, 49, 48, 48, 47, 46, 46, 44, 44, 43, 41, 38, 27, 25, 25, 26, 24, 34, 34, 35, 35, 36, 36, 37, 38, 40, 42, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 40, 40, 40, 40, 38, 120, 121, 121, 117, 113, 114, 113, 108, 110, 111, 110, 107, 108, 109, 112, 112, 111, 109, 109, 108, 110, 112, 113, 113, 114, 106, 108, 113, 117, 132, 162, 176, 180, 180, 181, 182, 183, 183, 183, 183, 182, 181, 178, 172, 167, 163, 157, 156, 155, 154, 146, 164, 188, 196, 199, 200, 202, 207, 210, 211, 211, 211, 213, 213, 213, 212, 211, 210, 209, 204, 186, 105, 74, 127, 177, 179, 181, 182, 186, 190, 193, 194, 196, 196, 195, 195, 194, 194, 193, 191, 189, 188, 187, 186, 144, 69, 101, 175, 207, 205, 194, 187, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 184, 177, 165, 173, 180, 190, 193, 193, 193, 193, 193, 193, 187, 176, 194, 211, 219, 219, 205, 189, 190, 207, 213, 214, 214, 216, 214, 214, 220, 218, 196, 187, 102, 64, 64, 65, 68, 72, 78, 76, 89, 88, 87, 86, 88, 94, 103, 110, 110, 109, 92, 90, 97, 97, 104, 111, 111, 111, 111, 111, 111, 111, 112, 112, 112, 112, 112, 112, 112, 111, 109, 76, 66, 34, 104, 145, 156, 167, 222, 242, 245, 245, 243, 235, 222, 211, 205, 201, 196, 192, 189, 186, 184, 182, 179, 175, 172, 169, 166, 126, 49, 48, 46, 49, 51, 52, 53, 54, 55, 56, 56, 56, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58, 57, 57, 56, 56, 55, 55, 54, 54, 53, 53, 52, 51, 51, 50, 50, 49, 48, 48, 46, 46, 45, 43, 42, 36, 27, 25, 26, 26, 28, 35, 35, 35, 36, 36, 37, 38, 39, 41, 42, 42, 42, 41, 41, 41, 41, 41, 42, 42, 42, 42, 42, 40, 40, 40, 39, 38, 124, 126, 122, 121, 116, 114, 114, 110, 111, 114, 110, 110, 110, 110, 110, 107, 106, 107, 107, 108, 111, 113, 113, 114, 113, 107, 112, 115, 125, 142, 172, 179, 180, 181, 182, 182, 183, 183, 183, 183, 183, 183, 179, 172, 162, 158, 156, 156, 156, 155, 156, 149, 179, 190, 197, 199, 200, 202, 206, 209, 210, 211, 212, 213, 214, 214, 214, 213, 212, 210, 204, 191, 113, 81, 168, 177, 179, 180, 183, 186, 189, 192, 194, 194, 194, 194, 193, 192, 192, 191, 189, 189, 188, 186, 183, 96, 72, 76, 110, 169, 203, 206, 205, 204, 203, 202, 199, 198, 195, 192, 187, 182, 180, 168, 172, 179, 182, 193, 193, 193, 193, 193, 193, 193, 189, 172, 189, 198, 209, 215, 201, 188, 187, 198, 208, 209, 209, 211, 204, 214, 219, 204, 186, 147, 60, 57, 58, 60, 64, 68, 74, 80, 82, 79, 80, 78, 79, 86, 99, 110, 110, 110, 109, 96, 73, 95, 109, 111, 111, 111, 111, 111, 111, 112, 112, 112, 112, 112, 112, 111, 111, 111, 93, 65, 50, 139, 179, 173, 167, 208, 240, 243, 236, 224, 211, 204, 201, 198, 195, 193, 191, 188, 186, 184, 182, 180, 177, 174, 172, 169, 167, 146, 49, 49, 48, 49, 52, 54, 54, 55, 56, 56, 57, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 58, 58, 58, 57, 57, 57, 56, 55, 54, 54, 53, 53, 52, 52, 51, 50, 49, 49, 48, 47, 47, 46, 44, 43, 33, 28, 26, 27, 25, 32, 35, 35, 35, 36, 36, 37, 39, 40, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 42, 42, 42, 41, 40, 40, 39, 37, 122, 121, 122, 122, 118, 117, 116, 113, 114, 111, 108, 108, 108, 108, 109, 107, 106, 107, 107, 108, 111, 111, 112, 112, 113, 117, 126, 133, 156, 168, 178, 181, 181, 182, 182, 183, 183, 183, 183, 183, 183, 184, 183, 175, 159, 159, 158, 156, 155, 155, 155, 135, 107, 179, 193, 198, 198, 199, 202, 206, 209, 210, 212, 213, 214, 215, 215, 215, 214, 212, 210, 204, 191, 133, 146, 171, 177, 179, 181, 183, 186, 189, 192, 194, 193, 193, 191, 191, 190, 189, 189, 188, 187, 186, 186, 163, 64, 74, 79, 80, 89, 137, 173, 199, 208, 208, 209, 208, 206, 202, 193, 184, 179, 177, 179, 182, 188, 192, 193, 193, 193, 193, 193, 193, 190, 177, 182, 190, 196, 201, 195, 185, 185, 191, 204, 204, 205, 207, 194, 212, 215, 188, 179, 79, 52, 51, 53, 55, 60, 65, 70, 83, 77, 77, 75, 73, 74, 79, 97, 110, 110, 110, 110, 109, 95, 61, 70, 97, 109, 111, 111, 111, 112, 112, 112, 112, 112, 112, 111, 111, 111, 110, 67, 60, 121, 179, 165, 172, 195, 225, 224, 211, 203, 201, 198, 196, 195, 192, 191, 189, 187, 186, 184, 182, 181, 179, 176, 174, 172, 170, 168, 162, 59, 50, 50, 49, 53, 54, 55, 56, 57, 58, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 59, 59, 59, 58, 58, 58, 57, 57, 56, 56, 55, 54, 54, 53, 53, 52, 51, 51, 50, 49, 47, 47, 46, 45, 43, 31, 28, 27, 27, 24, 34, 35, 35, 36, 36, 37, 38, 40, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 42, 42, 42, 40, 40, 39, 37, 119, 117, 120, 122, 121, 120, 120, 117, 112, 108, 107, 108, 107, 107, 107, 107, 106, 106, 106, 107, 109, 109, 107, 108, 120, 132, 141, 156, 171, 181, 183, 186, 186, 184, 183, 184, 183, 183, 183, 183, 183, 183, 182, 174, 166, 167, 165, 159, 154, 154, 154, 120, 84, 129, 163, 195, 198, 198, 199, 202, 206, 210, 211, 213, 215, 215, 216, 216, 215, 215, 214, 211, 205, 199, 174, 155, 168, 176, 180, 181, 184, 186, 189, 192, 192, 192, 192, 192, 192, 190, 189, 188, 187, 186, 186, 186, 125, 62, 76, 79, 80, 74, 66, 64, 100, 137, 161, 178, 192, 197, 197, 190, 179, 178, 186, 192, 193, 193, 193, 191, 188, 187, 191, 193, 191, 180, 172, 186, 188, 191, 187, 184, 184, 186, 198, 199, 200, 202, 189, 209, 198, 183, 142, 50, 48, 48, 49, 52, 57, 65, 71, 75, 71, 72, 72, 70, 71, 76, 99, 108, 104, 102, 96, 93, 96, 103, 65, 42, 67, 94, 108, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 96, 58, 77, 176, 150, 169, 190, 196, 201, 197, 196, 195, 194, 193, 192, 191, 189, 188, 186, 185, 184, 183, 182, 180, 177, 176, 174, 172, 171, 169, 168, 95, 51, 52, 51, 55, 55, 57, 57, 58, 59, 60, 60, 60, 60, 60, 60, 61, 61, 60, 60, 60, 60, 59, 59, 59, 59, 58, 58, 57, 57, 56, 56, 56, 55, 54, 53, 52, 51, 51, 50, 48, 47, 46, 46, 41, 30, 28, 27, 27, 26, 35, 35, 35, 36, 37, 38, 39, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 42, 41, 40, 39, 36, 116, 114, 115, 122, 123, 123, 120, 116, 112, 109, 107, 108, 107, 106, 106, 106, 106, 106, 106, 107, 108, 107, 106, 117, 132, 141, 155, 171, 179, 183, 186, 188, 189, 189, 184, 185, 183, 183, 181, 180, 181, 182, 179, 174, 172, 172, 172, 165, 154, 154, 154, 102, 85, 154, 154, 175, 196, 197, 197, 198, 202, 207, 210, 212, 214, 215, 216, 216, 216, 216, 216, 216, 214, 210, 204, 193, 160, 158, 174, 181, 183, 183, 184, 189, 192, 194, 203, 210, 214, 215, 207, 199, 192, 189, 188, 187, 180, 82, 63, 77, 79, 78, 66, 62, 60, 59, 59, 51, 69, 75, 121, 181, 186, 180, 188, 192, 193, 192, 190, 186, 182, 181, 185, 193, 192, 181, 168, 186, 185, 186, 185, 184, 184, 184, 193, 195, 196, 198, 185, 202, 185, 179, 76, 46, 45, 45, 47, 50, 56, 64, 73, 60, 71, 68, 68, 68, 69, 75, 101, 90, 76, 74, 70, 70, 74, 104, 110, 81, 33, 41, 63, 91, 108, 111, 111, 110, 111, 111, 111, 111, 111, 71, 61, 127, 141, 169, 187, 188, 190, 191, 190, 190, 190, 190, 189, 189, 188, 187, 186, 185, 184, 183, 182, 181, 178, 177, 175, 174, 173, 171, 170, 169, 129, 52, 53, 52, 56, 57, 58, 58, 59, 60, 60, 60, 61, 61, 61, 61, 61, 61, 61, 61, 61, 60, 60, 60, 59, 59, 59, 59, 58, 58, 57, 57, 56, 56, 55, 54, 53, 52, 51, 50, 50, 48, 47, 46, 39, 29, 27, 27, 27, 28, 35, 35, 36, 37, 37, 38, 40, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 41, 40, 38, 36, 114, 113, 112, 118, 123, 119, 116, 115, 112, 110, 109, 107, 106, 106, 106, 105, 105, 106, 106, 106, 107, 106, 107, 126, 142, 154, 169, 183, 184, 185, 189, 189, 187, 193, 188, 184, 184, 183, 182, 180, 180, 182, 181, 178, 177, 175, 174, 169, 154, 154, 150, 87, 98, 162, 154, 122, 189, 197, 197, 196, 199, 204, 209, 211, 214, 215, 216, 216, 217, 219, 220, 220, 219, 217, 214, 209, 204, 188, 160, 159, 181, 182, 183, 184, 195, 217, 227, 230, 231, 231, 232, 229, 223, 212, 198, 190, 187, 158, 60, 64, 77, 79, 72, 63, 60, 59, 60, 54, 63, 73, 72, 127, 212, 189, 182, 184, 181, 180, 181, 181, 180, 179, 180, 189, 193, 183, 164, 186, 183, 184, 183, 184, 184, 184, 189, 192, 193, 194, 179, 190, 182, 148, 45, 43, 43, 43, 45, 49, 60, 46, 49, 71, 68, 67, 67, 67, 68, 74, 99, 86, 74, 71, 70, 70, 96, 110, 111, 112, 91, 36, 33, 40, 62, 89, 106, 110, 110, 110, 111, 111, 101, 57, 60, 118, 166, 184, 185, 187, 188, 188, 188, 188, 188, 188, 187, 187, 186, 186, 185, 184, 184, 183, 182, 179, 178, 176, 175, 174, 173, 172, 172, 170, 156, 55, 55, 55, 54, 58, 59, 59, 60, 60, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 60, 60, 60, 59, 59, 59, 58, 58, 57, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 36, 29, 28, 27, 24, 31, 35, 35, 36, 37, 38, 39, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 41, 40, 38, 35, 109, 110, 110, 112, 118, 115, 114, 114, 113, 111, 107, 106, 106, 106, 106, 105, 105, 106, 106, 106, 107, 106, 112, 136, 156, 174, 180, 189, 192, 198, 200, 189, 184, 191, 194, 186, 187, 188, 183, 180, 182, 182, 182, 181, 180, 177, 175, 169, 154, 154, 137, 84, 120, 162, 140, 83, 134, 194, 196, 196, 197, 200, 205, 209, 212, 215, 216, 216, 219, 221, 221, 222, 222, 222, 221, 219, 216, 212, 206, 193, 175, 173, 182, 183, 183, 206, 227, 232, 232, 232, 233, 232, 232, 231, 227, 212, 196, 188, 119, 58, 65, 77, 77, 66, 62, 62, 62, 60, 51, 71, 70, 70, 137, 192, 186, 181, 180, 179, 180, 180, 180, 179, 179, 183, 193, 185, 163, 185, 183, 184, 183, 183, 184, 184, 186, 190, 191, 192, 169, 184, 182, 97, 43, 41, 42, 42, 44, 50, 57, 42, 70, 69, 67, 66, 66, 66, 67, 73, 94, 86, 71, 70, 73, 90, 110, 110, 112, 112, 112, 95, 37, 33, 33, 40, 60, 87, 106, 110, 110, 110, 78, 61, 59, 157, 182, 183, 184, 185, 186, 186, 186, 186, 186, 186, 185, 185, 185, 184, 184, 183, 183, 181, 180, 179, 177, 176, 176, 175, 174, 173, 172, 172, 170, 92, 57, 57, 55, 59, 59, 60, 61, 61, 61, 61, 61, 61, 62, 62, 62, 61, 61, 62, 61, 61, 61, 61, 61, 61, 60, 60, 60, 59, 59, 58, 58, 57, 57, 56, 55, 54, 54, 52, 51, 50, 49, 46, 34, 29, 28, 27, 25, 33, 35, 36, 36, 37, 38, 39, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 41, 39, 37, 35, 106, 107, 107, 108, 109, 112, 113, 113, 112, 107, 106, 106, 106, 106, 106, 105, 105, 105, 105, 106, 106, 113, 123, 145, 177, 182, 186, 192, 197, 201, 201, 192, 185, 193, 198, 197, 197, 195, 185, 181, 182, 183, 182, 181, 181, 176, 173, 165, 154, 154, 120, 84, 140, 165, 103, 84, 81, 152, 194, 196, 196, 197, 201, 206, 211, 214, 216, 217, 220, 221, 222, 223, 223, 224, 224, 224, 223, 222, 220, 217, 211, 203, 183, 178, 184, 186, 207, 228, 232, 232, 233, 233, 233, 233, 232, 231, 220, 199, 181, 81, 56, 68, 76, 72, 66, 64, 64, 65, 51, 66, 68, 67, 67, 63, 63, 72, 94, 136, 195, 205, 204, 198, 190, 182, 189, 186, 172, 176, 183, 183, 183, 183, 184, 185, 185, 188, 189, 190, 163, 184, 167, 43, 41, 41, 41, 41, 44, 55, 50, 69, 69, 68, 66, 66, 66, 66, 66, 72, 88, 82, 70, 72, 91, 110, 110, 111, 112, 112, 112, 112, 98, 41, 34, 33, 33, 39, 57, 88, 106, 90, 56, 63, 117, 180, 181, 182, 183, 184, 184, 185, 185, 185, 185, 185, 185, 184, 184, 184, 183, 183, 182, 180, 179, 178, 177, 177, 176, 175, 175, 174, 173, 172, 171, 138, 58, 58, 55, 59, 60, 61, 61, 61, 61, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 61, 61, 61, 60, 60, 59, 59, 58, 57, 56, 56, 55, 54, 53, 52, 50, 49, 45, 33, 28, 27, 27, 26, 34, 35, 35, 36, 37, 38, 39, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 41, 40, 37, 34, 106, 107, 107, 105, 106, 111, 113, 113, 107, 105, 105, 106, 106, 106, 106, 105, 105, 105, 105, 106, 108, 125, 138, 170, 186, 183, 187, 190, 200, 201, 201, 197, 191, 194, 198, 200, 198, 190, 182, 181, 181, 183, 182, 180, 179, 173, 171, 165, 155, 154, 101, 92, 158, 142, 83, 83, 85, 107, 152, 188, 196, 196, 198, 202, 208, 212, 215, 217, 220, 222, 223, 223, 225, 226, 227, 226, 227, 227, 226, 225, 224, 221, 215, 207, 193, 185, 180, 195, 218, 231, 232, 233, 233, 233, 233, 232, 232, 221, 196, 160, 57, 54, 69, 74, 69, 67, 66, 67, 59, 57, 67, 64, 64, 62, 62, 63, 60, 51, 78, 170, 213, 216, 212, 199, 189, 188, 180, 167, 183, 183, 183, 183, 184, 183, 184, 187, 187, 186, 166, 183, 133, 41, 40, 39, 40, 42, 46, 58, 71, 71, 69, 68, 66, 67, 67, 67, 66, 69, 81, 84, 71, 94, 110, 110, 111, 112, 112, 112, 112, 112, 112, 104, 53, 32, 33, 33, 33, 38, 56, 55, 60, 70, 163, 179, 181, 182, 182, 183, 183, 184, 184, 184, 184, 184, 184, 184, 183, 183, 183, 182, 181, 180, 179, 179, 178, 178, 176, 176, 175, 174, 174, 173, 172, 162, 82, 59, 59, 57, 61, 61, 61, 62, 62, 62, 62, 62, 62, 62, 63, 62, 63, 63, 63, 63, 63, 63, 63, 62, 62, 70, 63, 61, 60, 60, 59, 59, 58, 57, 57, 56, 55, 54, 53, 52, 50, 43, 31, 28, 27, 27, 27, 35, 35, 35, 36, 37, 38, 39, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 40, 39, 36, 34, 108, 107, 107, 105, 105, 111, 112, 107, 105, 105, 105, 106, 106, 106, 106, 105, 104, 104, 104, 106, 115, 135, 159, 184, 193, 186, 184, 184, 190, 193, 201, 201, 198, 193, 199, 197, 196, 187, 180, 183, 180, 181, 181, 175, 172, 171, 169, 167, 161, 151, 87, 125, 163, 92, 83, 83, 97, 143, 155, 157, 178, 195, 195, 199, 204, 209, 213, 216, 220, 221, 222, 224, 226, 227, 228, 228, 229, 229, 229, 228, 228, 228, 227, 226, 222, 217, 209, 190, 185, 199, 221, 232, 232, 232, 233, 233, 232, 232, 218, 192, 127, 53, 53, 69, 70, 68, 67, 67, 64, 49, 64, 62, 61, 59, 58, 60, 63, 50, 45, 45, 94, 192, 218, 216, 195, 187, 179, 166, 183, 183, 183, 183, 183, 183, 183, 182, 187, 179, 171, 183, 82, 39, 38, 39, 40, 42, 51, 64, 72, 70, 69, 68, 66, 67, 67, 67, 66, 66, 73, 85, 80, 110, 110, 111, 111, 112, 112, 112, 112, 112, 112, 111, 108, 89, 53, 34, 34, 36, 34, 57, 64, 123, 178, 179, 181, 182, 183, 183, 183, 183, 184, 184, 184, 184, 184, 183, 183, 183, 182, 182, 181, 181, 180, 180, 179, 178, 177, 176, 176, 175, 174, 174, 173, 168, 130, 60, 60, 59, 61, 61, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 64, 64, 64, 64, 64, 64, 63, 64, 68, 76, 62, 62, 61, 61, 60, 59, 59, 58, 57, 56, 56, 55, 53, 52, 50, 41, 31, 28, 27, 26, 30, 35, 35, 35, 36, 37, 38, 40, 42, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 41, 40, 39, 36, 33, 110, 108, 107, 106, 106, 110, 108, 105, 105, 105, 105, 105, 105, 106, 105, 104, 104, 104, 104, 109, 122, 148, 178, 194, 199, 194, 188, 184, 184, 186, 196, 201, 199, 199, 196, 188, 192, 186, 180, 183, 181, 180, 179, 167, 166, 173, 170, 168, 167, 144, 85, 156, 121, 83, 85, 89, 127, 153, 155, 152, 169, 195, 195, 196, 199, 204, 210, 215, 218, 221, 223, 224, 226, 227, 228, 229, 230, 231, 231, 231, 231, 231, 231, 231, 230, 229, 227, 225, 217, 203, 192, 199, 220, 229, 232, 232, 233, 232, 231, 216, 188, 90, 50, 54, 66, 66, 66, 66, 64, 47, 59, 59, 58, 57, 55, 54, 61, 55, 43, 41, 41, 48, 157, 211, 214, 189, 181, 164, 183, 183, 183, 182, 182, 182, 182, 180, 186, 175, 176, 169, 38, 38, 38, 38, 40, 42, 54, 58, 71, 70, 69, 68, 67, 67, 67, 66, 66, 66, 66, 79, 93, 111, 111, 111, 111, 112, 112, 112, 112, 112, 112, 103, 101, 104, 102, 69, 41, 36, 44, 61, 79, 168, 179, 180, 181, 182, 183, 183, 183, 183, 184, 184, 184, 184, 183, 183, 183, 183, 182, 182, 181, 181, 181, 180, 180, 178, 177, 177, 176, 176, 175, 174, 173, 171, 159, 89, 60, 61, 61, 62, 62, 62, 62, 63, 63, 63, 63, 63, 64, 65, 64, 65, 65, 64, 65, 64, 64, 64, 64, 63, 63, 62, 62, 62, 61, 60, 60, 58, 58, 57, 56, 55, 55, 53, 50, 38, 30, 28, 27, 25, 32, 36, 35, 35, 36, 37, 38, 40, 42, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 40, 39, 36, 33, 107, 107, 106, 106, 106, 108, 105, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 104, 107, 117, 134, 169, 186, 198, 199, 199, 195, 194, 191, 187, 193, 200, 198, 196, 190, 184, 185, 184, 181, 180, 183, 179, 178, 169, 166, 175, 174, 171, 169, 133, 110, 149, 81, 83, 104, 131, 152, 154, 155, 155, 155, 187, 195, 195, 195, 199, 205, 211, 215, 220, 222, 224, 226, 228, 228, 229, 231, 231, 231, 231, 232, 232, 232, 232, 232, 232, 232, 231, 230, 229, 227, 216, 195, 191, 217, 229, 232, 232, 232, 229, 214, 175, 56, 46, 54, 62, 62, 62, 61, 50, 52, 56, 55, 54, 52, 51, 53, 59, 43, 39, 38, 38, 38, 81, 190, 211, 183, 167, 180, 183, 182, 181, 180, 181, 181, 176, 184, 167, 179, 141, 38, 37, 37, 37, 39, 46, 67, 42, 60, 71, 70, 69, 67, 67, 67, 66, 66, 66, 63, 70, 96, 111, 112, 112, 112, 112, 112, 112, 113, 102, 82, 66, 65, 64, 63, 62, 62, 42, 57, 74, 135, 178, 180, 181, 182, 183, 183, 183, 183, 184, 184, 184, 184, 184, 183, 183, 183, 183, 182, 182, 182, 182, 182, 181, 180, 179, 178, 177, 177, 176, 176, 175, 174, 173, 167, 138, 61, 61, 62, 62, 62, 63, 63, 63, 63, 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 64, 64, 64, 63, 63, 62, 62, 61, 60, 60, 58, 57, 56, 56, 55, 54, 49, 36, 29, 28, 27, 25, 33, 35, 35, 35, 36, 37, 38, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 40, 38, 36, 33, 107, 108, 106, 106, 107, 106, 106, 104, 105, 105, 105, 105, 105, 105, 106, 105, 105, 106, 114, 128, 155, 180, 187, 200, 201, 194, 190, 198, 200, 197, 198, 197, 190, 189, 184, 183, 183, 183, 180, 180, 180, 179, 177, 172, 168, 173, 174, 171, 169, 116, 130, 89, 83, 83, 106, 152, 154, 153, 155, 155, 156, 143, 190, 194, 194, 195, 199, 205, 211, 216, 221, 222, 225, 227, 228, 230, 231, 231, 231, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 231, 229, 224, 207, 196, 221, 232, 232, 230, 226, 210, 148, 47, 43, 54, 56, 57, 56, 53, 45, 52, 51, 50, 49, 48, 46, 57, 47, 39, 37, 37, 36, 32, 53, 153, 195, 179, 170, 183, 182, 180, 179, 180, 180, 174, 183, 165, 181, 107, 37, 37, 37, 38, 40, 48, 80, 33, 38, 68, 70, 70, 68, 67, 67, 66, 66, 65, 63, 63, 95, 112, 112, 112, 112, 112, 112, 101, 79, 65, 63, 63, 64, 63, 61, 60, 60, 58, 68, 104, 169, 180, 181, 182, 183, 183, 183, 183, 184, 184, 184, 184, 184, 184, 184, 183, 183, 183, 183, 183, 183, 182, 183, 182, 180, 180, 179, 178, 177, 177, 176, 176, 175, 174, 172, 159, 100, 61, 62, 62, 63, 63, 63, 64, 64, 64, 65, 65, 66, 66, 66, 66, 66, 66, 65, 65, 65, 65, 65, 65, 64, 64, 63, 63, 62, 62, 61, 60, 59, 58, 57, 56, 55, 54, 47, 34, 29, 28, 27, 27, 33, 35, 35, 35, 36, 37, 38, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 40, 38, 35, 33, 108, 107, 106, 107, 106, 106, 106, 105, 105, 105, 105, 105, 105, 106, 106, 106, 106, 110, 123, 150, 180, 184, 192, 201, 201, 198, 194, 200, 201, 201, 194, 191, 187, 187, 183, 183, 182, 181, 181, 180, 180, 178, 176, 173, 169, 172, 173, 169, 166, 89, 87, 82, 82, 91, 120, 153, 153, 154, 155, 155, 154, 155, 146, 190, 194, 193, 194, 198, 205, 211, 216, 221, 223, 227, 228, 229, 231, 231, 231, 232, 232, 232, 232, 233, 233, 233, 233, 233, 233, 233, 232, 233, 232, 231, 227, 214, 185, 215, 230, 231, 229, 221, 205, 112, 42, 41, 49, 51, 52, 50, 41, 48, 47, 47, 45, 44, 42, 46, 53, 40, 37, 36, 35, 32, 36, 66, 83, 142, 169, 183, 181, 179, 180, 180, 179, 169, 183, 168, 182, 58, 37, 37, 37, 37, 41, 65, 77, 33, 39, 52, 69, 70, 68, 66, 66, 66, 66, 66, 64, 60, 93, 111, 112, 112, 110, 97, 76, 63, 62, 60, 61, 62, 63, 61, 60, 59, 59, 65, 102, 143, 175, 181, 183, 183, 183, 183, 183, 184, 184, 184, 184, 184, 184, 184, 184, 184, 183, 183, 183, 183, 183, 183, 183, 182, 181, 180, 180, 179, 178, 178, 177, 176, 175, 174, 173, 167, 146, 67, 62, 62, 62, 64, 64, 64, 64, 65, 66, 66, 66, 66, 66, 67, 67, 66, 66, 66, 66, 66, 65, 65, 65, 65, 64, 64, 63, 63, 62, 61, 60, 59, 58, 56, 56, 54, 44, 33, 28, 28, 28, 28, 33, 34, 34, 35, 36, 37, 39, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 41, 40, 38, 36, 33, 109, 108, 108, 107, 106, 106, 105, 106, 105, 105, 105, 105, 105, 106, 106, 106, 110, 118, 134, 162, 168, 189, 199, 198, 199, 201, 201, 201, 201, 201, 195, 194, 189, 185, 183, 183, 180, 181, 181, 180, 179, 178, 175, 173, 168, 169, 170, 171, 151, 71, 82, 82, 83, 134, 153, 153, 154, 154, 154, 155, 157, 158, 156, 152, 193, 193, 193, 194, 197, 205, 211, 216, 221, 223, 226, 228, 230, 231, 232, 232, 232, 232, 232, 233, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 231, 228, 214, 185, 212, 230, 230, 227, 215, 192, 73, 39, 38, 44, 46, 46, 37, 44, 43, 42, 42, 40, 39, 37, 49, 41, 37, 36, 36, 35, 27, 55, 71, 72, 141, 183, 181, 179, 179, 179, 179, 172, 180, 165, 168, 36, 36, 36, 37, 38, 42, 80, 73, 33, 50, 39, 62, 70, 68, 66, 67, 66, 66, 65, 64, 59, 79, 101, 99, 88, 70, 63, 61, 61, 60, 60, 60, 62, 61, 61, 60, 58, 64, 102, 109, 168, 179, 182, 183, 183, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 183, 183, 183, 183, 182, 182, 181, 181, 180, 179, 178, 177, 177, 176, 175, 174, 172, 161, 120, 64, 63, 61, 63, 64, 65, 66, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67, 65, 65, 66, 66, 65, 65, 65, 65, 64, 64, 63, 62, 62, 60, 60, 58, 57, 56, 55, 40, 32, 28, 27, 27, 28, 33, 34, 34, 34, 36, 37, 39, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 41, 39, 39, 35, 33, 110, 109, 109, 107, 106, 106, 106, 106, 105, 105, 106, 106, 106, 106, 106, 108, 116, 129, 148, 170, 171, 191, 200, 193, 198, 200, 199, 190, 196, 201, 200, 200, 190, 184, 182, 182, 181, 180, 180, 180, 179, 177, 177, 173, 168, 170, 170, 169, 108, 81, 81, 82, 104, 151, 155, 154, 154, 154, 155, 156, 157, 157, 157, 156, 172, 193, 193, 192, 193, 196, 204, 210, 215, 219, 222, 224, 227, 230, 231, 232, 232, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 231, 228, 203, 186, 220, 231, 229, 223, 210, 157, 38, 35, 34, 37, 40, 37, 37, 42, 40, 39, 38, 37, 35, 37, 42, 37, 36, 36, 36, 30, 37, 67, 72, 100, 182, 181, 179, 179, 179, 179, 176, 173, 165, 149, 36, 35, 35, 36, 38, 47, 90, 71, 33, 40, 61, 39, 67, 68, 66, 66, 66, 65, 65, 64, 59, 58, 63, 63, 62, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 59, 65, 102, 111, 146, 171, 182, 183, 183, 184, 184, 184, 184, 184, 184, 185, 185, 185, 185, 185, 185, 185, 185, 185, 184, 184, 184, 183, 183, 183, 183, 182, 181, 181, 180, 179, 178, 177, 176, 176, 175, 174, 169, 155, 88, 63, 64, 61, 65, 66, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 66, 67, 66, 66, 66, 66, 66, 65, 64, 64, 63, 63, 62, 61, 60, 59, 58, 56, 54, 37, 31, 27, 27, 25, 29, 33, 33, 33, 34, 36, 37, 39, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 40, 38, 35, 33, 112, 110, 109, 108, 107, 107, 107, 107, 108, 107, 106, 106, 106, 106, 107, 115, 132, 169, 167, 187, 192, 193, 197, 199, 198, 199, 191, 184, 194, 201, 201, 202, 194, 188, 188, 183, 183, 183, 181, 180, 178, 177, 178, 177, 172, 170, 168, 118, 79, 80, 84, 119, 152, 153, 156, 154, 154, 154, 155, 153, 130, 106, 96, 74, 79, 157, 193, 192, 192, 193, 196, 203, 209, 214, 217, 220, 222, 225, 228, 231, 232, 232, 232, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 232, 225, 190, 199, 229, 230, 227, 216, 196, 91, 33, 31, 30, 31, 34, 32, 39, 39, 37, 36, 35, 33, 32, 37, 39, 36, 36, 36, 35, 27, 55, 70, 73, 152, 182, 179, 179, 179, 179, 179, 170, 168, 127, 35, 35, 35, 37, 39, 49, 97, 75, 32, 33, 63, 51, 44, 69, 67, 66, 66, 66, 64, 63, 60, 56, 57, 58, 59, 59, 59, 59, 59, 59, 59, 60, 61, 61, 60, 66, 100, 112, 122, 168, 174, 183, 184, 184, 184, 184, 184, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 184, 184, 183, 183, 183, 182, 182, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 165, 142, 67, 64, 64, 61, 66, 66, 67, 67, 67, 67, 67, 68, 68, 68, 67, 67, 67, 67, 67, 66, 66, 66, 66, 65, 65, 64, 64, 63, 62, 62, 61, 60, 58, 56, 51, 35, 30, 27, 27, 24, 30, 33, 33, 33, 35, 36, 37, 40, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 41, 40, 38, 35, 33, 112, 110, 109, 107, 107, 107, 107, 107, 107, 108, 106, 106, 107, 108, 113, 125, 154, 192, 187, 199, 197, 190, 193, 201, 198, 198, 194, 194, 201, 202, 202, 202, 198, 190, 191, 185, 186, 189, 184, 180, 178, 178, 178, 176, 172, 165, 117, 78, 79, 76, 127, 152, 153, 155, 157, 154, 154, 154, 133, 78, 109, 142, 130, 109, 68, 35, 146, 192, 192, 192, 192, 195, 202, 208, 213, 216, 219, 222, 224, 227, 229, 231, 232, 232, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 232, 208, 196, 227, 230, 228, 222, 204, 148, 33, 30, 28, 29, 30, 27, 33, 35, 33, 32, 32, 32, 31, 32, 39, 36, 34, 36, 37, 28, 36, 68, 73, 101, 182, 179, 179, 179, 179, 179, 168, 172, 97, 35, 35, 35, 37, 37, 50, 102, 105, 72, 32, 52, 67, 40, 50, 68, 66, 66, 65, 64, 63, 61, 59, 58, 59, 59, 59, 59, 59, 59, 60, 60, 61, 61, 60, 66, 96, 112, 110, 159, 163, 176, 183, 184, 184, 184, 185, 185, 185, 185, 185, 185, 185, 185, 186, 185, 185, 185, 185, 185, 185, 185, 185, 184, 184, 184, 183, 183, 182, 183, 181, 181, 180, 179, 178, 177, 176, 175, 174, 171, 160, 122, 65, 65, 64, 62, 67, 67, 67, 67, 69, 76, 91, 85, 68, 68, 67, 67, 67, 67, 67, 66, 65, 66, 65, 65, 65, 64, 64, 63, 62, 61, 60, 59, 56, 48, 33, 29, 27, 27, 23, 31, 32, 32, 33, 35, 36, 38, 40, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 40, 38, 35, 33, 111, 111, 109, 107, 107, 107, 107, 107, 106, 105, 107, 108, 109, 113, 122, 138, 169, 197, 200, 200, 199, 196, 200, 201, 200, 200, 200, 198, 200, 201, 202, 201, 197, 187, 188, 187, 190, 192, 188, 180, 181, 179, 175, 173, 169, 112, 76, 77, 68, 121, 161, 156, 155, 156, 157, 155, 152, 110, 86, 138, 110, 44, 39, 31, 26, 19, 26, 154, 192, 191, 191, 192, 194, 201, 207, 212, 216, 219, 222, 224, 227, 228, 230, 232, 232, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 232, 223, 209, 226, 231, 228, 224, 211, 179, 38, 29, 27, 28, 30, 27, 31, 38, 34, 32, 33, 32, 31, 31, 35, 37, 32, 37, 37, 31, 27, 58, 71, 73, 151, 180, 179, 179, 179, 179, 169, 177, 60, 34, 34, 34, 36, 35, 52, 102, 107, 106, 75, 34, 62, 62, 34, 51, 68, 66, 65, 63, 62, 61, 59, 59, 59, 58, 59, 59, 59, 60, 60, 61, 62, 56, 64, 94, 112, 112, 123, 174, 165, 179, 184, 184, 185, 185, 185, 185, 185, 185, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 185, 185, 185, 185, 184, 184, 184, 183, 183, 182, 182, 181, 181, 180, 179, 178, 177, 176, 175, 173, 169, 156, 100, 65, 66, 64, 64, 67, 68, 69, 84, 110, 112, 84, 68, 68, 68, 68, 68, 67, 67, 67, 66, 66, 66, 65, 65, 64, 64, 63, 62, 61, 60, 59, 56, 43, 33, 28, 26, 26, 23, 31, 32, 32, 33, 34, 37, 39, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 41, 40, 38, 35, 33, 84, 110, 107, 108, 108, 108, 107, 105, 106, 108, 109, 112, 119, 129, 145, 169, 185, 197, 199, 197, 200, 200, 201, 201, 201, 201, 199, 191, 196, 199, 201, 194, 192, 186, 189, 193, 192, 192, 190, 183, 188, 175, 171, 165, 109, 75, 70, 67, 94, 155, 161, 161, 157, 157, 158, 154, 104, 103, 133, 75, 50, 49, 50, 32, 25, 29, 29, 67, 167, 192, 191, 191, 191, 193, 198, 205, 211, 215, 220, 222, 224, 227, 229, 231, 231, 232, 232, 233, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 231, 225, 230, 231, 228, 225, 216, 191, 85, 28, 27, 27, 30, 28, 30, 40, 41, 35, 33, 33, 32, 31, 33, 37, 36, 33, 37, 35, 24, 41, 69, 74, 88, 174, 179, 179, 179, 179, 170, 178, 65, 34, 34, 34, 34, 30, 50, 96, 108, 107, 104, 78, 41, 65, 56, 33, 48, 68, 65, 63, 61, 60, 59, 59, 59, 59, 59, 59, 59, 60, 61, 67, 57, 63, 91, 112, 112, 109, 161, 164, 171, 182, 185, 185, 185, 185, 185, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 185, 185, 185, 184, 184, 184, 183, 183, 183, 182, 181, 181, 180, 179, 177, 177, 175, 174, 173, 166, 151, 85, 66, 67, 64, 64, 67, 75, 109, 117, 97, 74, 68, 68, 68, 68, 68, 68, 68, 67, 67, 66, 65, 66, 65, 65, 64, 63, 62, 61, 61, 58, 56, 38, 32, 28, 27, 26, 24, 31, 31, 31, 33, 35, 37, 39, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 40, 40, 38, 35, 33, 51, 75, 104, 108, 108, 106, 105, 107, 108, 109, 110, 118, 138, 159, 180, 193, 188, 195, 198, 192, 199, 200, 201, 199, 199, 197, 191, 190, 200, 200, 198, 188, 189, 188, 187, 193, 192, 192, 188, 187, 190, 171, 163, 102, 71, 92, 87, 93, 145, 157, 161, 163, 163, 160, 159, 112, 99, 111, 63, 54, 50, 58, 47, 32, 30, 28, 42, 79, 90, 168, 191, 191, 191, 190, 192, 196, 204, 210, 216, 220, 222, 224, 227, 229, 231, 231, 232, 232, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 232, 232, 232, 231, 229, 225, 217, 193, 121, 28, 27, 27, 30, 29, 28, 37, 44, 40, 37, 36, 32, 32, 32, 37, 37, 34, 37, 38, 25, 29, 62, 72, 75, 105, 167, 179, 179, 179, 178, 169, 55, 34, 34, 34, 31, 32, 43, 55, 91, 108, 108, 97, 82, 47, 63, 51, 33, 42, 64, 67, 62, 60, 60, 60, 60, 59, 59, 59, 60, 62, 68, 65, 57, 85, 108, 108, 108, 122, 180, 159, 172, 184, 185, 185, 185, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 185, 185, 185, 184, 184, 184, 183, 183, 182, 182, 181, 180, 179, 178, 177, 176, 175, 173, 172, 163, 144, 76, 67, 67, 64, 66, 77, 99, 94, 78, 69, 69, 68, 68, 68, 69, 68, 68, 68, 67, 67, 67, 66, 65, 65, 64, 63, 62, 61, 60, 58, 53, 34, 30, 27, 26, 25, 25, 31, 31, 31, 33, 35, 37, 40, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 41, 40, 37, 35, 33, 55, 53, 58, 91, 104, 106, 108, 108, 109, 108, 112, 130, 154, 178, 198, 200, 196, 199, 197, 189, 198, 198, 199, 191, 196, 193, 187, 196, 199, 195, 190, 186, 187, 187, 186, 191, 192, 190, 182, 187, 187, 156, 92, 83, 135, 147, 75, 104, 155, 157, 162, 166, 167, 171, 137, 68, 82, 65, 56, 54, 58, 45, 37, 34, 29, 30, 71, 83, 85, 91, 179, 191, 190, 190, 190, 191, 194, 201, 208, 215, 219, 222, 224, 226, 229, 231, 231, 232, 232, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 232, 232, 232, 229, 225, 219, 196, 142, 28, 26, 27, 31, 29, 27, 34, 45, 42, 40, 43, 35, 33, 32, 37, 39, 39, 34, 41, 28, 27, 49, 70, 74, 75, 72, 115, 145, 156, 168, 161, 53, 34, 34, 34, 30, 34, 41, 47, 50, 76, 104, 105, 96, 85, 46, 58, 44, 33, 35, 54, 68, 62, 60, 60, 59, 60, 59, 60, 63, 68, 69, 55, 76, 104, 105, 105, 104, 157, 180, 161, 173, 185, 185, 186, 186, 186, 186, 186, 186, 186, 187, 187, 187, 187, 186, 187, 187, 187, 187, 186, 186, 186, 186, 186, 185, 185, 185, 184, 184, 184, 183, 183, 183, 182, 181, 180, 179, 178, 177, 176, 174, 172, 170, 161, 138, 72, 67, 68, 66, 68, 75, 75, 69, 69, 69, 69, 69, 69, 69, 69, 68, 68, 68, 67, 67, 66, 66, 65, 64, 64, 63, 61, 60, 57, 48, 32, 30, 27, 26, 26, 25, 30, 30, 31, 32, 35, 38, 40, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 41, 39, 38, 35, 33, 64, 59, 66, 52, 64, 94, 109, 111, 109, 108, 122, 144, 171, 193, 202, 202, 202, 200, 198, 191, 198, 195, 191, 189, 198, 195, 194, 194, 189, 186, 185, 185, 185, 185, 185, 187, 186, 181, 177, 158, 118, 83, 134, 164, 165, 102, 87, 152, 158, 158, 165, 172, 174, 158, 64, 53, 63, 54, 55, 57, 39, 37, 42, 33, 29, 57, 81, 84, 85, 86, 122, 190, 190, 190, 190, 190, 190, 193, 199, 206, 214, 219, 222, 224, 226, 228, 230, 231, 231, 232, 232, 233, 233, 233, 233, 233, 233, 232, 232, 232, 232, 232, 230, 226, 220, 198, 156, 28, 26, 27, 41, 30, 26, 32, 52, 45, 44, 49, 44, 35, 33, 36, 41, 43, 34, 43, 33, 24, 33, 67, 73, 75, 73, 107, 140, 138, 137, 135, 40, 34, 34, 34, 30, 36, 40, 43, 47, 50, 62, 93, 103, 95, 84, 49, 50, 38, 33, 33, 43, 66, 63, 62, 60, 60, 61, 65, 68, 69, 65, 60, 98, 102, 102, 102, 101, 178, 180, 160, 175, 185, 186, 186, 186, 186, 186, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 186, 185, 185, 185, 184, 184, 184, 183, 182, 182, 181, 181, 179, 178, 177, 176, 175, 173, 172, 169, 160, 134, 70, 68, 68, 66, 64, 68, 68, 68, 69, 69, 69, 69, 69, 68, 68, 68, 68, 68, 67, 66, 66, 65, 64, 63, 62, 61, 59, 57, 41, 31, 29, 26, 26, 26, 25, 29, 30, 31, 32, 35, 38, 40, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 41, 40, 38, 35, 33, 95, 70, 93, 78, 56, 50, 64, 92, 106, 111, 132, 157, 186, 201, 203, 203, 202, 199, 197, 192, 195, 190, 185, 194, 200, 198, 199, 187, 183, 183, 184, 184, 185, 185, 185, 181, 180, 166, 114, 96, 137, 164, 166, 165, 144, 71, 140, 162, 157, 157, 161, 180, 182, 79, 52, 59, 56, 57, 56, 36, 37, 45, 55, 33, 43, 79, 83, 84, 85, 85, 79, 156, 190, 190, 190, 190, 190, 190, 191, 196, 204, 211, 217, 221, 223, 225, 227, 229, 231, 231, 231, 232, 232, 233, 232, 232, 232, 232, 232, 232, 232, 232, 230, 227, 221, 198, 168, 29, 27, 28, 55, 31, 26, 32, 65, 64, 52, 59, 56, 39, 36, 36, 43, 43, 35, 44, 35, 25, 28, 58, 72, 75, 78, 124, 139, 139, 139, 139, 77, 34, 34, 34, 31, 37, 41, 44, 45, 47, 49, 56, 76, 99, 91, 86, 57, 38, 33, 33, 33, 38, 64, 67, 64, 65, 68, 69, 68, 69, 56, 84, 100, 100, 99, 99, 118, 180, 180, 157, 175, 186, 186, 186, 186, 186, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 185, 185, 185, 184, 184, 183, 183, 182, 182, 181, 180, 179, 178, 176, 175, 174, 172, 170, 168, 160, 133, 71, 67, 68, 67, 64, 68, 68, 68, 69, 69, 69, 69, 68, 68, 69, 68, 68, 67, 67, 66, 65, 64, 63, 61, 60, 59, 53, 37, 30, 29, 26, 29, 31, 27, 31, 29, 31, 32, 35, 38, 40, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 41, 40, 38, 35, 33, 114, 86, 105, 109, 79, 71, 59, 52, 53, 77, 120, 163, 194, 202, 202, 202, 200, 197, 193, 190, 188, 189, 187, 194, 200, 196, 198, 185, 182, 180, 180, 179, 182, 185, 178, 149, 122, 133, 162, 169, 164, 165, 166, 164, 102, 122, 157, 158, 156, 156, 157, 164, 99, 59, 56, 56, 68, 68, 35, 37, 46, 57, 57, 36, 73, 83, 85, 86, 85, 76, 78, 84, 184, 190, 190, 190, 190, 190, 190, 190, 194, 201, 208, 215, 220, 222, 224, 227, 228, 229, 230, 231, 231, 232, 232, 232, 232, 232, 232, 232, 232, 231, 230, 227, 221, 198, 173, 29, 27, 30, 66, 34, 26, 31, 63, 71, 60, 72, 76, 46, 38, 37, 45, 43, 58, 43, 37, 25, 28, 44, 70, 74, 87, 129, 139, 139, 139, 139, 95, 45, 34, 33, 32, 39, 43, 45, 46, 47, 48, 50, 56, 63, 83, 90, 87, 63, 34, 33, 33, 33, 36, 65, 69, 69, 69, 67, 67, 65, 69, 98, 98, 97, 96, 96, 131, 181, 164, 166, 175, 186, 186, 186, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 184, 184, 183, 183, 183, 181, 181, 179, 178, 177, 176, 174, 173, 171, 169, 167, 159, 136, 75, 67, 68, 68, 64, 67, 69, 69, 69, 69, 69, 69, 69, 68, 68, 68, 68, 67, 66, 65, 64, 63, 61, 60, 58, 48, 33, 30, 28, 29, 36, 36, 30, 34, 29, 30, 33, 35, 38, 40, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 41, 40, 38, 35, 33, 116, 113, 121, 124, 120, 116, 84, 56, 58, 62, 65, 78, 114, 145, 169, 183, 195, 193, 187, 180, 178, 187, 189, 189, 192, 188, 187, 181, 182, 181, 172, 152, 133, 147, 140, 157, 177, 177, 177, 172, 168, 172, 168, 144, 92, 155, 166, 157, 155, 154, 151, 91, 56, 53, 55, 77, 83, 36, 38, 48, 57, 57, 57, 65, 81, 85, 100, 127, 124, 85, 85, 123, 146, 172, 174, 190, 190, 190, 189, 190, 190, 192, 197, 205, 211, 217, 221, 223, 225, 227, 228, 228, 228, 231, 231, 232, 231, 231, 232, 232, 232, 231, 229, 227, 221, 197, 176, 29, 27, 40, 73, 42, 29, 30, 61, 78, 60, 72, 90, 61, 42, 39, 44, 44, 69, 69, 39, 28, 27, 31, 67, 74, 77, 126, 139, 139, 139, 134, 66, 66, 37, 32, 35, 41, 45, 47, 47, 47, 47, 48, 51, 57, 63, 74, 85, 83, 64, 38, 33, 33, 33, 51, 69, 69, 68, 64, 66, 60, 91, 96, 95, 94, 93, 94, 131, 181, 159, 169, 174, 186, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 184, 184, 183, 183, 182, 182, 181, 180, 179, 177, 176, 175, 173, 172, 170, 169, 167, 161, 142, 83, 68, 68, 68, 66, 67, 69, 69, 69, 69, 69, 68, 68, 68, 68, 68, 67, 66, 65, 64, 62, 61, 59, 56, 41, 31, 29, 30, 37, 42, 42, 34, 36, 29, 31, 33, 35, 39, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 41, 39, 38, 35, 33, 114, 113, 122, 125, 126, 126, 106, 62, 59, 67, 78, 84, 84, 82, 78, 74, 82, 98, 114, 139, 131, 139, 149, 153, 153, 154, 147, 139, 130, 134, 143, 161, 178, 182, 181, 181, 180, 180, 180, 179, 178, 180, 177, 118, 148, 174, 175, 160, 154, 151, 99, 51, 50, 56, 81, 81, 38, 38, 49, 57, 57, 57, 69, 80, 93, 110, 143, 158, 122, 82, 134, 155, 161, 138, 165, 178, 190, 190, 189, 189, 189, 189, 191, 194, 200, 207, 214, 219, 222, 223, 224, 225, 226, 227, 230, 230, 230, 230, 231, 231, 231, 229, 228, 226, 219, 195, 177, 31, 26, 54, 77, 52, 30, 28, 59, 85, 62, 69, 94, 74, 47, 40, 43, 45, 64, 95, 40, 30, 25, 28, 57, 73, 93, 137, 139, 139, 139, 114, 68, 68, 58, 32, 38, 43, 47, 47, 47, 47, 47, 48, 49, 53, 60, 62, 66, 76, 77, 67, 35, 33, 33, 38, 71, 69, 65, 62, 61, 74, 94, 93, 92, 91, 90, 90, 104, 182, 171, 160, 172, 186, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 185, 185, 185, 184, 184, 184, 182, 182, 181, 180, 179, 178, 177, 176, 174, 173, 171, 169, 168, 167, 163, 149, 100, 68, 68, 68, 68, 68, 67, 68, 69, 68, 68, 68, 67, 68, 68, 67, 66, 64, 63, 61, 60, 58, 50, 37, 30, 28, 36, 45, 48, 45, 37, 36, 29, 31, 33, 35, 39, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 41, 40, 38, 36, 33, 113, 112, 118, 124, 126, 132, 135, 127, 119, 113, 126, 154, 160, 150, 145, 139, 147, 154, 120, 169, 148, 113, 114, 129, 150, 170, 185, 191, 185, 194, 190, 181, 189, 195, 185, 188, 187, 180, 179, 180, 181, 181, 160, 100, 169, 187, 189, 184, 149, 93, 49, 48, 57, 81, 80, 39, 38, 51, 57, 57, 57, 64, 80, 106, 132, 153, 160, 154, 81, 115, 151, 155, 158, 167, 159, 169, 190, 190, 190, 189, 189, 189, 189, 189, 191, 195, 202, 209, 215, 219, 221, 222, 222, 224, 227, 228, 228, 228, 229, 229, 229, 228, 226, 223, 215, 193, 175, 31, 25, 66, 80, 59, 30, 28, 56, 94, 65, 66, 98, 87, 55, 42, 39, 46, 64, 104, 40, 30, 25, 29, 43, 71, 99, 136, 140, 139, 139, 93, 68, 68, 68, 61, 38, 46, 48, 47, 47, 47, 48, 48, 48, 49, 53, 59, 60, 61, 66, 71, 62, 35, 33, 32, 64, 66, 62, 60, 55, 88, 91, 89, 87, 86, 86, 87, 91, 168, 179, 152, 172, 186, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 184, 184, 184, 183, 182, 181, 181, 179, 178, 177, 176, 175, 174, 172, 171, 169, 168, 167, 165, 157, 124, 74, 68, 68, 68, 68, 66, 65, 65, 68, 68, 67, 68, 67, 67, 66, 65, 63, 61, 59, 57, 43, 33, 29, 33, 43, 51, 51, 87, 69, 34, 30, 31, 33, 36, 39, 40, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 40, 40, 38, 36, 33, 112, 112, 113, 121, 123, 127, 136, 145, 155, 170, 187, 194, 196, 195, 191, 191, 193, 192, 186, 191, 192, 186, 179, 179, 189, 193, 189, 195, 195, 196, 188, 185, 197, 199, 189, 197, 194, 181, 181, 181, 181, 182, 113, 124, 184, 187, 196, 190, 116, 49, 48, 58, 80, 79, 38, 38, 52, 57, 57, 57, 62, 97, 101, 138, 161, 162, 162, 120, 83, 147, 153, 163, 168, 170, 156, 170, 170, 188, 190, 189, 189, 189, 189, 189, 189, 190, 192, 196, 203, 210, 215, 217, 220, 221, 224, 225, 226, 226, 227, 227, 227, 225, 223, 220, 210, 191, 171, 30, 26, 69, 83, 66, 30, 29, 51, 99, 68, 63, 99, 92, 60, 45, 36, 46, 69, 91, 39, 31, 25, 29, 32, 67, 92, 136, 142, 139, 131, 64, 68, 68, 68, 68, 41, 47, 49, 48, 48, 48, 48, 48, 48, 49, 48, 55, 60, 60, 60, 62, 67, 62, 35, 33, 50, 62, 60, 48, 65, 89, 86, 83, 81, 80, 80, 80, 87, 146, 182, 152, 171, 185, 187, 187, 187, 187, 187, 187, 187, 187, 187, 188, 188, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 185, 185, 184, 184, 183, 183, 182, 182, 181, 180, 179, 178, 177, 176, 174, 173, 172, 170, 169, 167, 167, 166, 161, 147, 108, 69, 67, 67, 67, 68, 67, 64, 63, 63, 65, 67, 66, 65, 64, 63, 60, 59, 49, 39, 30, 29, 40, 50, 53, 65, 135, 80, 30, 29, 31, 33, 36, 40, 40, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 40, 40, 38, 36, 33, 112, 111, 113, 119, 122, 127, 139, 157, 174, 181, 192, 197, 198, 197, 196, 199, 198, 196, 193, 190, 187, 183, 181, 181, 185, 190, 186, 197, 198, 195, 194, 196, 197, 195, 191, 198, 195, 182, 182, 182, 182, 171, 82, 175, 192, 185, 177, 166, 55, 49, 58, 77, 80, 37, 38, 52, 57, 57, 57, 60, 79, 142, 150, 153, 156, 159, 157, 80, 101, 157, 157, 168, 172, 173, 167, 158, 151, 179, 190, 190, 189, 189, 189, 189, 189, 188, 189, 190, 192, 196, 202, 209, 213, 216, 221, 223, 223, 222, 223, 223, 223, 222, 219, 214, 203, 189, 163, 31, 29, 53, 87, 72, 31, 28, 45, 101, 71, 62, 90, 87, 61, 47, 33, 44, 80, 74, 36, 32, 26, 29, 29, 56, 79, 133, 146, 146, 118, 68, 68, 68, 68, 68, 48, 47, 49, 48, 48, 48, 48, 48, 48, 50, 48, 50, 60, 60, 60, 60, 60, 63, 56, 33, 39, 61, 55, 42, 74, 83, 80, 77, 76, 74, 73, 74, 77, 117, 181, 162, 171, 183, 187, 187, 187, 187, 187, 187, 187, 188, 189, 189, 189, 188, 188, 188, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 185, 185, 184, 184, 183, 183, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 171, 170, 169, 168, 166, 166, 164, 159, 143, 108, 71, 68, 67, 67, 67, 68, 68, 65, 63, 62, 61, 59, 60, 59, 56, 42, 35, 29, 37, 45, 50, 55, 125, 140, 78, 29, 30, 31, 33, 36, 39, 40, 42, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 41, 40, 40, 38, 36, 33, 111, 112, 114, 118, 124, 134, 152, 174, 188, 188, 193, 197, 199, 199, 201, 201, 201, 200, 192, 194, 185, 181, 182, 181, 180, 185, 189, 198, 198, 196, 198, 196, 194, 195, 194, 198, 191, 175, 179, 183, 184, 133, 72, 184, 183, 166, 178, 64, 53, 59, 74, 81, 38, 39, 53, 57, 57, 57, 59, 72, 110, 152, 154, 161, 157, 157, 130, 61, 149, 162, 163, 166, 167, 172, 172, 166, 157, 164, 161, 189, 190, 189, 188, 188, 188, 188, 187, 187, 188, 189, 190, 194, 200, 206, 213, 217, 218, 218, 219, 219, 218, 216, 213, 207, 195, 189, 152, 31, 31, 34, 87, 79, 30, 28, 39, 100, 73, 60, 81, 79, 61, 50, 32, 41, 90, 57, 33, 33, 29, 28, 29, 45, 75, 126, 149, 155, 114, 69, 68, 68, 68, 68, 54, 48, 49, 48, 48, 48, 48, 48, 48, 50, 49, 47, 58, 60, 60, 60, 60, 60, 60, 38, 31, 52, 47, 44, 71, 78, 75, 73, 71, 70, 70, 70, 70, 89, 179, 162, 171, 182, 187, 187, 187, 187, 187, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 185, 185, 184, 184, 183, 183, 183, 182, 182, 181, 180, 179, 178, 177, 176, 175, 173, 172, 171, 170, 168, 168, 167, 166, 165, 164, 159, 149, 126, 100, 73, 68, 67, 66, 66, 66, 65, 64, 62, 60, 57, 46, 39, 32, 34, 43, 51, 54, 120, 139, 140, 72, 29, 29, 31, 33, 36, 39, 41, 42, 42, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 42, 41, 40, 40, 38, 36, 34, 111, 113, 117, 124, 134, 149, 167, 188, 194, 193, 194, 196, 195, 193, 198, 201, 201, 199, 188, 189, 182, 180, 181, 180, 180, 182, 187, 194, 196, 196, 197, 198, 198, 199, 196, 189, 174, 170, 173, 177, 174, 75, 59, 168, 169, 173, 73, 57, 60, 69, 84, 38, 38, 52, 57, 57, 57, 58, 67, 112, 163, 161, 168, 157, 156, 157, 91, 107, 158, 158, 152, 147, 137, 144, 122, 99, 101, 74, 68, 131, 162, 175, 184, 188, 187, 187, 186, 186, 187, 187, 188, 189, 189, 193, 201, 208, 211, 212, 212, 212, 211, 209, 205, 198, 192, 188, 151, 32, 32, 30, 76, 84, 31, 29, 35, 99, 73, 59, 70, 69, 60, 50, 31, 39, 97, 44, 31, 33, 35, 26, 29, 35, 96, 148, 155, 158, 86, 68, 68, 68, 68, 68, 60, 47, 49, 48, 48, 48, 48, 48, 48, 50, 50, 45, 55, 60, 60, 60, 60, 60, 60, 48, 33, 39, 44, 47, 69, 74, 72, 69, 68, 67, 66, 66, 65, 80, 155, 169, 171, 180, 187, 187, 187, 187, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 185, 185, 184, 184, 183, 183, 182, 182, 182, 181, 180, 180, 178, 178, 176, 176, 175, 173, 172, 171, 169, 168, 168, 167, 166, 165, 165, 163, 159, 156, 152, 137, 121, 102, 83, 69, 64, 63, 62, 60, 54, 40, 36, 34, 48, 62, 61, 96, 140, 139, 138, 76, 30, 30, 31, 33, 36, 39, 40, 41, 42, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 41, 41, 42, 41, 40, 40, 38, 36, 34, 112, 114, 123, 133, 147, 165, 183, 194, 197, 195, 193, 194, 193, 190, 194, 198, 199, 198, 185, 181, 182, 181, 181, 181, 180, 180, 181, 189, 195, 194, 197, 198, 197, 198, 195, 181, 174, 167, 169, 167, 143, 47, 91, 168, 174, 88, 64, 59, 65, 87, 41, 38, 51, 57, 57, 57, 57, 71, 143, 176, 174, 167, 146, 132, 122, 107, 39, 67, 61, 108, 73, 115, 71, 148, 156, 119, 155, 130, 144, 151, 151, 150, 159, 173, 185, 186, 186, 186, 186, 186, 186, 187, 187, 189, 191, 197, 201, 205, 205, 205, 203, 201, 197, 194, 190, 188, 135, 32, 33, 32, 63, 93, 31, 29, 34, 97, 69, 58, 63, 63, 60, 50, 32, 39, 103, 38, 34, 33, 34, 28, 29, 29, 77, 152, 156, 151, 73, 68, 67, 67, 67, 67, 66, 43, 49, 48, 48, 48, 48, 48, 48, 49, 51, 45, 50, 60, 60, 60, 60, 60, 60, 57, 32, 32, 40, 51, 68, 71, 68, 67, 66, 64, 63, 62, 62, 68, 118, 174, 171, 178, 187, 187, 187, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 187, 187, 187, 187, 187, 187, 186, 186, 186, 185, 185, 184, 184, 183, 183, 183, 182, 182, 181, 181, 180, 179, 178, 178, 176, 175, 174, 173, 172, 171, 169, 168, 168, 168, 167, 166, 165, 164, 164, 162, 160, 158, 157, 157, 153, 146, 140, 137, 133, 133, 135, 139, 147, 161, 167, 112, 138, 139, 138, 140, 80, 30, 30, 31, 33, 36, 39, 40, 41, 42, 41, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 41, 41, 41, 42, 42, 41, 40, 40, 38, 35, 33, 110, 116, 128, 143, 161, 180, 193, 195, 197, 198, 195, 193, 190, 186, 190, 195, 196, 194, 185, 181, 183, 182, 181, 180, 174, 178, 183, 193, 197, 195, 195, 194, 197, 199, 194, 185, 179, 165, 161, 156, 107, 41, 131, 149, 100, 76, 59, 61, 88, 46, 37, 50, 57, 57, 57, 56, 72, 132, 127, 105, 86, 79, 81, 87, 91, 74, 82, 115, 124, 146, 152, 154, 160, 165, 172, 154, 157, 151, 152, 151, 151, 150, 152, 153, 172, 185, 186, 186, 186, 186, 186, 186, 186, 186, 188, 190, 193, 195, 197, 197, 197, 196, 194, 190, 189, 188, 125, 34, 33, 34, 42, 95, 31, 30, 32, 96, 65, 58, 60, 60, 59, 48, 33, 37, 111, 36, 35, 33, 34, 28, 31, 29, 47, 133, 155, 135, 67, 68, 67, 67, 67, 67, 67, 61, 43, 48, 48, 48, 48, 48, 48, 48, 51, 45, 48, 60, 60, 60, 60, 60, 60, 60, 38, 31, 38, 58, 65, 68, 67, 65, 63, 62, 61, 60, 59, 59, 86, 167, 171, 176, 187, 187, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 184, 184, 184, 183, 183, 182, 182, 181, 181, 180, 179, 178, 177, 176, 175, 174, 172, 171, 170, 169, 168, 168, 168, 167, 167, 166, 166, 165, 165, 165, 165, 164, 164, 164, 164, 165, 165, 166, 168, 180, 190, 199, 163, 137, 139, 138, 139, 140, 81, 30, 29, 31, 34, 36, 39, 40, 40, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 42, 42, 40, 40, 39, 38, 35, 33, 110, 121, 136, 156, 176, 192, 196, 196, 198, 199, 198, 195, 190, 183, 188, 193, 196, 194, 194, 188, 183, 181, 178, 173, 171, 180, 184, 194, 198, 196, 195, 195, 199, 199, 193, 174, 165, 161, 156, 150, 63, 59, 141, 104, 87, 59, 59, 86, 55, 37, 48, 57, 57, 57, 53, 53, 69, 87, 113, 138, 150, 152, 155, 156, 156, 108, 137, 156, 156, 156, 156, 155, 160, 153, 158, 152, 151, 151, 151, 152, 151, 151, 151, 149, 147, 157, 183, 186, 183, 186, 186, 186, 186, 186, 186, 186, 187, 187, 188, 191, 193, 192, 190, 189, 189, 188, 125, 36, 34, 34, 33, 89, 31, 31, 31, 92, 61, 57, 59, 59, 58, 45, 37, 42, 118, 38, 34, 34, 33, 28, 32, 30, 37, 73, 154, 120, 69, 68, 67, 67, 67, 67, 67, 67, 60, 43, 48, 48, 48, 48, 48, 48, 49, 45, 48, 60, 60, 60, 60, 60, 60, 60, 47, 31, 39, 60, 63, 66, 64, 63, 62, 60, 59, 58, 57, 57, 74, 131, 171, 175, 187, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 185, 184, 184, 183, 183, 182, 183, 182, 181, 180, 180, 179, 178, 176, 175, 174, 173, 172, 170, 170, 169, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 169, 170, 171, 172, 173, 174, 176, 187, 199, 204, 201, 140, 140, 138, 140, 140, 140, 82, 30, 29, 31, 33, 36, 39, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 39, 39, 38, 35, 33, 116, 129, 151, 172, 191, 197, 198, 198, 199, 200, 200, 198, 193, 188, 193, 196, 198, 195, 193, 189, 184, 181, 174, 168, 170, 178, 177, 192, 199, 198, 197, 197, 198, 198, 193, 167, 163, 157, 148, 119, 56, 102, 108, 98, 61, 59, 82, 67, 38, 45, 57, 57, 58, 52, 93, 130, 156, 166, 169, 176, 168, 162, 158, 157, 156, 89, 155, 157, 157, 156, 155, 153, 152, 151, 150, 151, 151, 151, 151, 152, 151, 151, 152, 144, 139, 56, 62, 120, 150, 166, 168, 175, 171, 156, 161, 180, 183, 186, 183, 184, 187, 189, 188, 189, 188, 188, 136, 39, 34, 34, 31, 77, 31, 32, 30, 80, 59, 57, 58, 58, 58, 41, 40, 71, 120, 40, 31, 34, 33, 28, 33, 31, 30, 50, 148, 111, 68, 67, 67, 67, 67, 67, 67, 67, 67, 59, 42, 48, 48, 48, 48, 48, 48, 44, 48, 60, 60, 60, 60, 60, 60, 60, 55, 32, 44, 60, 62, 64, 62, 61, 60, 59, 57, 57, 56, 56, 60, 108, 171, 173, 187, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 187, 187, 187, 187, 186, 186, 186, 186, 186, 185, 185, 185, 184, 184, 184, 183, 183, 183, 182, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 171, 170, 169, 169, 168, 168, 168, 168, 168, 169, 169, 170, 171, 172, 174, 175, 176, 177, 179, 187, 204, 208, 210, 169, 139, 139, 140, 140, 140, 140, 86, 30, 29, 31, 33, 35, 38, 40, 40, 41, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 40, 39, 37, 35, 33, 122, 142, 169, 188, 197, 198, 199, 200, 201, 201, 201, 200, 196, 191, 197, 198, 192, 187, 184, 184, 184, 182, 176, 170, 172, 183, 181, 193, 198, 198, 198, 196, 189, 189, 182, 165, 166, 147, 137, 131, 106, 105, 106, 71, 59, 77, 79, 38, 42, 56, 57, 57, 98, 151, 173, 166, 170, 171, 176, 173, 166, 162, 159, 157, 155, 108, 161, 161, 160, 159, 156, 154, 151, 151, 156, 153, 151, 151, 151, 152, 152, 153, 150, 129, 104, 33, 33, 41, 141, 156, 156, 157, 158, 161, 160, 155, 157, 168, 156, 151, 175, 177, 183, 163, 173, 153, 101, 51, 35, 35, 34, 64, 31, 32, 30, 65, 57, 57, 57, 57, 54, 38, 83, 107, 116, 40, 30, 34, 33, 28, 32, 31, 29, 42, 133, 102, 67, 66, 67, 67, 67, 67, 68, 67, 67, 66, 45, 43, 48, 48, 48, 49, 46, 43, 49, 60, 60, 60, 60, 60, 60, 60, 52, 35, 48, 60, 61, 62, 61, 59, 58, 57, 57, 56, 55, 55, 56, 81, 162, 172, 185, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 185, 185, 185, 184, 184, 184, 183, 183, 182, 182, 182, 181, 180, 179, 178, 177, 176, 174, 173, 172, 171, 170, 169, 169, 169, 169, 169, 169, 170, 170, 171, 173, 174, 175, 176, 177, 180, 186, 204, 209, 211, 195, 139, 139, 140, 140, 140, 140, 140, 89, 30, 30, 31, 33, 35, 38, 40, 41, 41, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 42, 41, 40, 40, 40, 38, 37, 35, 33, 130, 161, 184, 197, 198, 200, 200, 201, 201, 200, 201, 202, 199, 194, 197, 198, 187, 182, 182, 182, 183, 183, 185, 181, 174, 187, 194, 195, 198, 198, 197, 193, 172, 168, 168, 166, 153, 140, 153, 134, 105, 112, 88, 61, 74, 91, 40, 40, 55, 57, 60, 126, 162, 167, 174, 172, 174, 176, 176, 173, 167, 163, 160, 157, 150, 146, 163, 163, 162, 161, 158, 155, 157, 155, 167, 161, 152, 151, 151, 153, 154, 154, 151, 129, 44, 33, 33, 39, 143, 156, 157, 157, 158, 159, 157, 156, 157, 159, 156, 156, 148, 150, 152, 147, 150, 133, 105, 67, 36, 35, 51, 66, 32, 33, 29, 59, 57, 57, 57, 57, 50, 37, 105, 141, 109, 40, 31, 35, 33, 27, 31, 31, 29, 35, 114, 94, 66, 66, 66, 67, 67, 67, 67, 67, 66, 66, 52, 37, 45, 49, 49, 48, 45, 42, 50, 60, 60, 60, 60, 60, 61, 52, 41, 38, 54, 60, 61, 61, 59, 58, 56, 55, 56, 55, 55, 55, 55, 69, 139, 172, 184, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 186, 185, 185, 185, 184, 184, 184, 183, 183, 183, 182, 181, 181, 179, 179, 178, 176, 175, 174, 173, 172, 171, 170, 170, 169, 169, 169, 170, 171, 171, 173, 174, 175, 177, 178, 180, 186, 203, 210, 212, 204, 146, 139, 140, 140, 140, 142, 140, 140, 92, 30, 30, 31, 33, 35, 38, 39, 41, 41, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 42, 40, 40, 39, 39, 39, 37, 35, 33, 148, 176, 192, 196, 198, 200, 201, 201, 201, 200, 201, 201, 201, 199, 201, 200, 188, 182, 183, 182, 184, 187, 195, 186, 174, 191, 195, 181, 183, 193, 195, 191, 166, 165, 166, 147, 147, 154, 152, 115, 114, 101, 68, 78, 104, 52, 38, 52, 71, 77, 147, 163, 165, 168, 175, 176, 176, 176, 176, 171, 167, 164, 161, 162, 149, 160, 163, 163, 162, 161, 159, 155, 160, 157, 161, 166, 152, 153, 156, 159, 160, 158, 148, 95, 35, 35, 34, 86, 155, 159, 161, 159, 161, 164, 161, 161, 161, 161, 160, 159, 154, 151, 150, 151, 150, 133, 104, 80, 39, 37, 86, 93, 32, 33, 28, 58, 57, 57, 57, 57, 45, 39, 108, 149, 101, 39, 31, 34, 32, 27, 31, 31, 30, 31, 82, 91, 61, 65, 65, 65, 65, 65, 66, 66, 65, 65, 56, 43, 37, 46, 50, 48, 44, 42, 51, 60, 60, 60, 60, 60, 56, 41, 40, 38, 60, 60, 61, 61, 58, 57, 55, 55, 55, 55, 55, 55, 55, 58, 112, 172, 182, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 187, 187, 188, 187, 186, 186, 186, 186, 186, 186, 185, 185, 185, 185, 184, 184, 184, 183, 183, 183, 182, 181, 180, 179, 178, 176, 176, 174, 173, 172, 171, 171, 170, 170, 170, 170, 171, 172, 173, 175, 175, 177, 178, 180, 189, 204, 209, 212, 205, 149, 140, 141, 140, 140, 141, 142, 141, 141, 94, 30, 30, 31, 33, 35, 37, 39, 40, 41, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 42, 41, 40, 40, 40, 39, 38, 37, 35, 33, 169, 186, 192, 193, 195, 198, 200, 200, 200, 201, 201, 201, 202, 202, 202, 201, 190, 185, 187, 185, 187, 190, 198, 189, 180, 188, 186, 177, 178, 183, 184, 178, 162, 166, 150, 145, 156, 153, 127, 115, 106, 85, 79, 121, 75, 37, 48, 89, 138, 157, 163, 161, 165, 172, 176, 176, 176, 176, 176, 172, 168, 165, 164, 165, 143, 164, 163, 162, 162, 161, 160, 159, 161, 172, 169, 169, 157, 159, 161, 162, 162, 165, 144, 91, 36, 36, 52, 126, 156, 161, 168, 163, 163, 173, 171, 167, 171, 163, 161, 161, 161, 157, 151, 148, 145, 127, 104, 90, 43, 46, 107, 109, 30, 33, 28, 57, 57, 57, 57, 57, 40, 58, 133, 150, 97, 36, 30, 35, 31, 27, 30, 30, 30, 30, 39, 84, 52, 61, 64, 63, 65, 64, 64, 64, 64, 64, 61, 43, 43, 36, 48, 46, 44, 41, 52, 60, 60, 60, 60, 60, 48, 40, 40, 44, 60, 60, 61, 64, 58, 56, 55, 55, 55, 55, 55, 55, 55, 55, 78, 166, 180, 188, 189, 189, 189, 189, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 185, 185, 185, 184, 184, 184, 183, 183, 183, 182, 181, 181, 179, 178, 177, 176, 175, 174, 173, 173, 171, 171, 171, 171, 172, 173, 173, 174, 176, 177, 179, 181, 194, 206, 210, 212, 196, 144, 140, 140, 140, 140, 140, 140, 142, 142, 142, 98, 30, 30, 31, 32, 35, 37, 39, 40, 40, 41, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 42, 41, 40, 40, 40, 39, 38, 36, 35, 33, 184, 190, 191, 192, 193, 195, 196, 196, 198, 198, 199, 201, 202, 203, 202, 201, 192, 189, 191, 192, 192, 190, 193, 188, 181, 184, 187, 187, 184, 178, 169, 163, 163, 152, 152, 155, 154, 137, 112, 108, 99, 83, 124, 109, 40, 52, 97, 137, 157, 160, 165, 162, 169, 176, 178, 178, 178, 177, 176, 172, 168, 166, 166, 166, 146, 165, 163, 162, 161, 161, 161, 161, 160, 163, 173, 172, 168, 165, 161, 163, 163, 164, 135, 78, 38, 47, 105, 148, 159, 165, 174, 171, 168, 174, 175, 170, 171, 172, 166, 161, 167, 166, 157, 155, 150, 130, 104, 98, 53, 99, 148, 121, 31, 32, 29, 57, 57, 57, 57, 55, 37, 93, 155, 148, 83, 34, 27, 35, 29, 29, 30, 30, 30, 30, 30, 43, 41, 53, 58, 60, 62, 63, 63, 63, 63, 62, 62, 52, 52, 39, 36, 44, 43, 41, 53, 60, 60, 60, 60, 58, 42, 40, 40, 50, 60, 60, 60, 66, 59, 56, 55, 54, 54, 55, 55, 55, 55, 55, 69, 146, 177, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 187, 193, 187, 185, 185, 185, 184, 184, 184, 184, 183, 183, 182, 181, 180, 179, 177, 176, 175, 174, 173, 173, 172, 172, 172, 172, 173, 174, 176, 177, 179, 180, 186, 200, 208, 210, 210, 173, 138, 140, 140, 140, 140, 140, 140, 140, 141, 142, 143, 101, 31, 30, 31, 32, 35, 37, 39, 40, 40, 41, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 42, 42, 41, 40, 40, 39, 38, 37, 36, 34, 33, 189, 190, 192, 194, 196, 196, 195, 195, 196, 195, 196, 199, 201, 201, 201, 198, 190, 188, 190, 194, 196, 194, 193, 192, 184, 187, 193, 188, 185, 179, 173, 169, 155, 163, 169, 153, 144, 110, 114, 106, 97, 126, 133, 60, 77, 120, 141, 156, 157, 160, 159, 158, 167, 173, 176, 178, 179, 179, 178, 174, 170, 168, 168, 167, 146, 165, 163, 162, 162, 161, 161, 161, 161, 161, 171, 173, 172, 170, 165, 163, 170, 173, 144, 96, 40, 46, 119, 157, 161, 166, 173, 177, 174, 178, 177, 171, 167, 176, 172, 166, 176, 168, 160, 159, 154, 127, 104, 103, 71, 113, 156, 132, 30, 31, 30, 57, 57, 57, 57, 53, 67, 103, 159, 149, 78, 31, 30, 36, 27, 30, 30, 30, 30, 30, 30, 25, 35, 40, 51, 56, 58, 61, 62, 62, 61, 61, 59, 52, 57, 46, 37, 36, 42, 41, 54, 60, 60, 60, 60, 50, 42, 42, 38, 59, 60, 60, 60, 65, 63, 56, 55, 54, 55, 54, 54, 55, 55, 55, 58, 123, 174, 187, 189, 189, 189, 189, 189, 189, 189, 188, 189, 189, 189, 189, 189, 189, 189, 189, 188, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 196, 192, 186, 186, 185, 185, 185, 184, 184, 184, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 174, 173, 174, 174, 174, 175, 177, 179, 181, 184, 193, 204, 209, 211, 204, 152, 138, 140, 140, 140, 140, 140, 140, 140, 140, 141, 144, 143, 105, 32, 30, 31, 32, 34, 36, 39, 39, 41, 41, 42, 42, 41, 41, 41, 41, 41, 41, 41, 42, 42, 41, 40, 40, 40, 39, 38, 37, 36, 34, 33, 191, 193, 196, 199, 200, 199, 197, 194, 193, 192, 193, 194, 196, 196, 195, 191, 186, 184, 186, 192, 195, 197, 194, 193, 187, 188, 192, 187, 184, 180, 184, 173, 180, 193, 172, 149, 112, 119, 107, 107, 125, 138, 95, 43, 121, 152, 157, 157, 159, 162, 158, 159, 172, 173, 173, 174, 177, 177, 177, 176, 173, 171, 169, 167, 148, 164, 164, 163, 163, 163, 164, 164, 162, 166, 171, 168, 171, 170, 164, 164, 167, 171, 113, 53, 45, 47, 131, 169, 164, 166, 170, 177, 174, 177, 178, 175, 174, 178, 175, 174, 174, 162, 162, 161, 158, 121, 104, 104, 119, 146, 154, 141, 29, 32, 32, 57, 57, 57, 57, 50, 104, 142, 160, 151, 64, 30, 39, 35, 28, 30, 31, 30, 29, 30, 30, 30, 27, 35, 40, 48, 53, 58, 58, 58, 58, 57, 56, 50, 59, 49, 36, 33, 36, 41, 56, 60, 60, 60, 58, 42, 42, 41, 40, 60, 60, 60, 60, 64, 65, 58, 55, 54, 55, 55, 55, 55, 55, 55, 56, 88, 171, 187, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 189, 186, 186, 186, 185, 185, 185, 184, 184, 184, 183, 184, 183, 182, 181, 180, 179, 177, 177, 176, 175, 175, 175, 175, 175, 176, 178, 181, 184, 189, 200, 207, 209, 211, 198, 139, 138, 139, 140, 140, 140, 140, 140, 140, 140, 140, 141, 144, 142, 108, 32, 30, 30, 32, 34, 36, 38, 39, 40, 40, 42, 42, 42, 41, 41, 41, 41, 41, 41, 42, 42, 41, 40, 40, 39, 38, 38, 37, 36, 34, 33, 194, 198, 200, 201, 201, 200, 197, 193, 189, 189, 189, 191, 192, 192, 189, 185, 182, 182, 184, 189, 193, 193, 192, 190, 185, 183, 184, 183, 180, 178, 167, 174, 199, 203, 176, 124, 120, 109, 107, 122, 132, 122, 52, 58, 138, 155, 157, 158, 164, 163, 157, 164, 170, 170, 168, 172, 174, 176, 177, 177, 175, 172, 171, 169, 153, 159, 164, 165, 165, 165, 169, 169, 163, 168, 176, 171, 170, 168, 162, 163, 165, 166, 110, 57, 52, 54, 136, 173, 175, 169, 170, 172, 175, 176, 177, 175, 176, 178, 177, 175, 169, 161, 161, 161, 159, 107, 104, 109, 146, 156, 151, 147, 31, 31, 33, 57, 57, 57, 57, 48, 125, 154, 160, 154, 61, 34, 44, 32, 30, 32, 31, 31, 28, 30, 30, 30, 26, 32, 35, 38, 44, 53, 54, 54, 54, 53, 52, 45, 58, 53, 33, 33, 30, 38, 54, 59, 59, 58, 49, 41, 40, 36, 37, 58, 60, 60, 60, 63, 65, 62, 56, 55, 55, 55, 55, 55, 55, 55, 56, 72, 157, 184, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 184, 184, 184, 183, 183, 182, 181, 180, 179, 178, 177, 176, 176, 176, 176, 177, 178, 180, 184, 187, 196, 204, 208, 210, 211, 193, 133, 135, 139, 140, 140, 142, 141, 142, 141, 140, 141, 142, 142, 144, 143, 112, 33, 30, 30, 32, 33, 36, 38, 39, 40, 40, 41, 42, 42, 42, 41, 41, 41, 41, 42, 42, 42, 41, 40, 40, 39, 38, 37, 37, 35, 34, 33, 199, 201, 202, 201, 201, 199, 196, 192, 190, 188, 188, 188, 190, 190, 187, 184, 182, 181, 182, 185, 187, 187, 186, 184, 181, 179, 179, 178, 177, 166, 160, 179, 190, 193, 156, 117, 117, 106, 119, 123, 130, 85, 105, 140, 156, 156, 157, 160, 163, 159, 156, 159, 164, 163, 165, 165, 172, 175, 176, 178, 178, 174, 172, 172, 164, 152, 165, 165, 165, 168, 171, 171, 164, 163, 171, 171, 166, 166, 162, 164, 163, 171, 127, 63, 59, 59, 151, 175, 179, 178, 175, 173, 175, 175, 177, 175, 178, 178, 173, 168, 164, 161, 161, 162, 140, 101, 107, 132, 155, 152, 151, 150, 43, 32, 37, 57, 57, 57, 57, 59, 144, 160, 160, 153, 44, 45, 38, 28, 33, 33, 33, 33, 31, 28, 30, 30, 30, 26, 33, 34, 36, 40, 49, 48, 49, 48, 47, 41, 50, 57, 32, 33, 33, 33, 49, 57, 57, 55, 42, 41, 38, 42, 41, 41, 58, 60, 60, 62, 64, 64, 58, 55, 54, 55, 54, 55, 55, 56, 56, 62, 139, 182, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 185, 185, 185, 184, 184, 184, 183, 183, 182, 181, 180, 179, 178, 177, 178, 178, 178, 179, 182, 185, 192, 199, 205, 208, 209, 211, 192, 131, 131, 138, 140, 140, 140, 140, 143, 144, 142, 142, 141, 144, 146, 147, 146, 113, 34, 30, 30, 31, 34, 36, 38, 39, 40, 40, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 40, 40, 39, 38, 38, 37, 36, 35, 34, 32, 199, 202, 202, 202, 201, 200, 198, 195, 193, 191, 191, 191, 192, 191, 189, 186, 183, 182, 181, 181, 181, 181, 181, 180, 178, 178, 177, 177, 167, 158, 171, 174, 178, 172, 125, 129, 110, 114, 122, 118, 119, 59, 132, 155, 156, 160, 161, 163, 161, 158, 156, 156, 159, 157, 163, 161, 171, 175, 176, 178, 178, 180, 176, 173, 173, 151, 168, 166, 166, 170, 172, 172, 165, 163, 164, 167, 165, 169, 165, 164, 164, 175, 116, 71, 67, 64, 171, 177, 179, 179, 178, 177, 177, 176, 176, 177, 178, 178, 168, 169, 166, 164, 163, 164, 100, 105, 113, 153, 152, 151, 151, 150, 58, 33, 40, 57, 57, 57, 57, 91, 149, 161, 160, 116, 37, 52, 34, 28, 32, 33, 35, 33, 33, 29, 30, 30, 30, 30, 28, 32, 34, 34, 37, 41, 42, 42, 42, 35, 40, 59, 33, 33, 33, 32, 48, 53, 54, 48, 41, 41, 49, 50, 42, 41, 42, 58, 60, 61, 64, 64, 62, 56, 54, 55, 55, 55, 55, 55, 55, 56, 114, 179, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 184, 184, 184, 183, 183, 183, 182, 181, 180, 179, 179, 179, 179, 180, 184, 187, 193, 199, 203, 207, 209, 210, 195, 133, 131, 136, 139, 140, 140, 140, 138, 142, 144, 144, 146, 142, 147, 149, 149, 149, 114, 34, 30, 31, 32, 33, 36, 37, 39, 40, 40, 40, 42, 42, 42, 42, 42, 42, 42, 42, 41, 40, 40, 40, 39, 38, 37, 36, 36, 35, 34, 33, 200, 202, 202, 202, 202, 201, 201, 199, 197, 195, 195, 195, 194, 192, 190, 189, 187, 186, 184, 181, 180, 181, 180, 178, 177, 177, 177, 170, 158, 164, 171, 171, 169, 135, 128, 122, 109, 119, 108, 119, 97, 65, 147, 155, 159, 167, 170, 170, 166, 158, 157, 157, 158, 157, 160, 164, 173, 169, 168, 178, 178, 179, 181, 176, 174, 154, 171, 166, 166, 170, 172, 172, 166, 165, 164, 164, 166, 177, 173, 170, 168, 175, 141, 83, 74, 86, 179, 179, 180, 179, 175, 173, 171, 174, 168, 171, 176, 175, 167, 172, 172, 174, 173, 134, 100, 104, 153, 159, 152, 151, 151, 151, 62, 34, 43, 57, 57, 57, 53, 104, 154, 161, 145, 43, 55, 43, 29, 33, 32, 33, 37, 36, 34, 33, 29, 30, 30, 30, 30, 29, 31, 33, 33, 35, 35, 36, 36, 33, 37, 53, 38, 33, 33, 31, 45, 48, 48, 42, 40, 41, 60, 57, 42, 42, 43, 42, 58, 60, 63, 64, 63, 59, 55, 55, 55, 55, 55, 55, 55, 55, 81, 174, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 184, 184, 183, 183, 183, 182, 181, 181, 180, 180, 180, 182, 184, 187, 192, 198, 202, 205, 207, 209, 197, 134, 136, 138, 139, 140, 140, 139, 139, 140, 143, 144, 144, 147, 144, 147, 149, 149, 149, 118, 35, 30, 31, 32, 33, 36, 38, 39, 40, 40, 40, 41, 42, 42, 42, 42, 42, 42, 42, 41, 40, 40, 40, 39, 38, 37, 37, 36, 35, 33, 33, 200, 202, 202, 202, 202, 202, 202, 201, 200, 199, 199, 199, 196, 193, 191, 189, 189, 189, 187, 184, 182, 183, 182, 179, 178, 177, 173, 160, 158, 167, 167, 166, 142, 121, 132, 112, 112, 106, 102, 111, 78, 72, 130, 155, 163, 170, 173, 173, 171, 162, 166, 166, 163, 158, 161, 172, 173, 164, 168, 178, 178, 178, 180, 179, 175, 156, 171, 168, 165, 169, 171, 170, 165, 164, 165, 171, 172, 179, 179, 179, 171, 175, 168, 85, 79, 108, 170, 179, 180, 179, 176, 173, 167, 167, 163, 164, 176, 173, 165, 168, 171, 176, 140, 91, 103, 153, 166, 162, 156, 151, 151, 151, 67, 36, 46, 57, 57, 57, 52, 103, 160, 157, 72, 42, 60, 34, 28, 33, 33, 33, 37, 44, 37, 34, 32, 30, 30, 30, 30, 30, 30, 31, 32, 33, 33, 33, 33, 34, 39, 40, 46, 33, 33, 31, 40, 43, 42, 41, 40, 52, 60, 60, 48, 43, 44, 44, 43, 57, 63, 63, 63, 62, 56, 54, 54, 54, 55, 55, 55, 55, 69, 157, 187, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 184, 184, 184, 184, 183, 182, 182, 181, 181, 181, 182, 185, 187, 191, 196, 200, 203, 206, 207, 205, 142, 136, 139, 140, 140, 141, 139, 139, 139, 142, 142, 142, 144, 145, 147, 148, 149, 149, 149, 122, 35, 30, 31, 32, 34, 36, 38, 39, 40, 40, 40, 40, 42, 42, 42, 42, 42, 42, 41, 40, 40, 40, 40, 39, 37, 37, 36, 36, 35, 33, 32, 198, 201, 202, 202, 202, 202, 202, 202, 200, 199, 199, 200, 198, 194, 191, 189, 189, 189, 188, 187, 186, 186, 185, 181, 179, 177, 166, 158, 163, 164, 164, 151, 123, 128, 121, 106, 103, 95, 97, 94, 104, 102, 109, 152, 164, 171, 174, 175, 172, 171, 173, 176, 173, 163, 164, 178, 173, 166, 175, 178, 178, 179, 180, 179, 177, 173, 157, 172, 162, 168, 171, 170, 166, 164, 165, 173, 172, 178, 179, 179, 176, 178, 162, 81, 78, 120, 164, 179, 180, 179, 179, 179, 176, 172, 168, 167, 176, 171, 170, 165, 170, 136, 89, 103, 147, 167, 166, 163, 158, 153, 151, 151, 65, 39, 51, 57, 57, 55, 49, 127, 162, 101, 36, 56, 42, 29, 33, 36, 36, 34, 41, 53, 47, 36, 34, 32, 29, 30, 30, 30, 30, 30, 30, 30, 30, 31, 30, 35, 40, 36, 48, 36, 33, 33, 37, 40, 41, 41, 41, 60, 60, 60, 58, 43, 43, 44, 44, 42, 55, 63, 63, 63, 61, 55, 54, 54, 55, 55, 55, 55, 62, 139, 186, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 188, 189, 188, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 185, 185, 184, 184, 184, 184, 183, 183, 182, 182, 182, 183, 186, 188, 191, 195, 198, 201, 204, 205, 206, 162, 132, 139, 139, 140, 140, 140, 140, 139, 139, 141, 141, 140, 142, 145, 149, 149, 149, 153, 155, 124, 36, 30, 31, 32, 34, 36, 38, 39, 40, 40, 40, 40, 41, 42, 42, 42, 42, 41, 40, 40, 40, 40, 40, 38, 37, 36, 36, 35, 34, 33, 31, 195, 198, 199, 200, 200, 201, 201, 200, 198, 196, 196, 198, 198, 194, 191, 189, 189, 188, 187, 187, 187, 187, 185, 180, 179, 173, 163, 162, 167, 164, 157, 132, 122, 130, 110, 96, 90, 89, 91, 95, 140, 127, 106, 136, 165, 174, 176, 176, 175, 176, 176, 176, 176, 171, 170, 178, 179, 177, 178, 178, 179, 179, 180, 179, 177, 176, 156, 175, 166, 167, 170, 166, 166, 166, 164, 165, 170, 180, 179, 179, 180, 179, 149, 86, 97, 135, 164, 179, 180, 180, 179, 179, 180, 180, 179, 172, 173, 172, 176, 168, 120, 92, 103, 149, 161, 164, 166, 162, 158, 156, 154, 152, 61, 46, 55, 57, 57, 49, 39, 150, 122, 34, 51, 49, 33, 29, 34, 47, 39, 36, 47, 57, 58, 45, 36, 34, 32, 28, 30, 30, 30, 30, 30, 30, 30, 30, 28, 38, 40, 37, 39, 49, 33, 33, 35, 41, 41, 38, 57, 60, 60, 60, 60, 53, 41, 44, 44, 44, 41, 53, 63, 63, 63, 58, 54, 54, 55, 55, 55, 55, 56, 116, 188, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 190, 195, 194, 190, 188, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 184, 184, 183, 183, 184, 183, 183, 184, 186, 188, 192, 194, 197, 200, 202, 204, 205, 181, 131, 134, 139, 140, 139, 140, 140, 140, 140, 140, 140, 140, 140, 141, 146, 149, 149, 152, 162, 164, 133, 36, 30, 31, 32, 34, 36, 38, 39, 40, 40, 40, 40, 40, 41, 42, 42, 41, 40, 40, 40, 40, 40, 39, 38, 37, 36, 36, 35, 34, 33, 32, 193, 193, 195, 195, 197, 199, 199, 198, 195, 193, 193, 194, 194, 193, 190, 189, 187, 186, 185, 186, 187, 187, 183, 180, 178, 169, 164, 169, 170, 166, 144, 124, 130, 121, 96, 85, 82, 84, 97, 126, 154, 146, 114, 115, 159, 179, 178, 176, 176, 176, 176, 176, 176, 177, 177, 178, 180, 183, 180, 180, 179, 179, 179, 179, 177, 176, 170, 159, 173, 165, 171, 173, 172, 174, 166, 162, 172, 177, 179, 180, 180, 179, 168, 94, 110, 151, 177, 180, 180, 180, 180, 179, 180, 180, 180, 175, 172, 178, 163, 111, 95, 106, 156, 162, 163, 165, 168, 166, 161, 158, 159, 158, 59, 53, 57, 57, 57, 39, 85, 134, 37, 49, 52, 36, 27, 34, 37, 57, 41, 39, 50, 58, 60, 59, 49, 37, 34, 33, 29, 28, 30, 30, 30, 30, 30, 30, 26, 40, 40, 37, 40, 46, 39, 34, 35, 40, 41, 45, 60, 60, 60, 60, 60, 60, 46, 44, 44, 44, 44, 41, 51, 63, 63, 63, 56, 55, 54, 55, 54, 55, 55, 85, 185, 188, 189, 189, 189, 189, 189, 189, 189, 189, 188, 189, 189, 189, 188, 194, 202, 203, 200, 192, 189, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 184, 184, 184, 184, 184, 184, 185, 187, 189, 192, 194, 197, 198, 200, 202, 203, 193, 137, 137, 135, 137, 138, 138, 139, 139, 140, 140, 139, 141, 141, 141, 143, 148, 149, 149, 156, 171, 172, 141, 36, 30, 31, 33, 34, 36, 38, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 38, 37, 36, 36, 35, 34, 33, 32, 191, 190, 190, 190, 192, 193, 194, 193, 191, 190, 190, 191, 190, 189, 188, 186, 185, 183, 182, 183, 186, 185, 180, 178, 173, 169, 171, 179, 177, 163, 134, 124, 131, 108, 84, 76, 76, 81, 113, 147, 155, 158, 147, 114, 123, 165, 180, 177, 177, 176, 176, 176, 176, 177, 179, 178, 181, 183, 182, 179, 178, 178, 178, 177, 177, 176, 176, 156, 171, 172, 170, 173, 174, 176, 172, 167, 168, 170, 178, 179, 180, 179, 173, 95, 93, 148, 179, 180, 180, 180, 180, 180, 180, 180, 179, 178, 170, 141, 103, 93, 116, 161, 162, 162, 166, 170, 172, 173, 167, 161, 161, 156, 55, 56, 57, 57, 51, 34, 104, 45, 44, 55, 38, 31, 29, 34, 46, 61, 44, 40, 48, 54, 59, 60, 59, 50, 37, 34, 34, 34, 31, 30, 28, 28, 27, 27, 27, 40, 40, 38, 39, 38, 49, 32, 33, 40, 40, 55, 60, 60, 60, 60, 60, 60, 58, 42, 44, 44, 44, 44, 42, 48, 62, 62, 60, 55, 55, 54, 55, 54, 55, 71, 167, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 190, 198, 204, 204, 203, 200, 192, 189, 188, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 185, 185, 184, 184, 184, 184, 185, 185, 187, 189, 192, 194, 197, 198, 199, 202, 202, 200, 144, 138, 139, 137, 135, 137, 138, 139, 139, 139, 139, 141, 142, 144, 145, 147, 149, 150, 151, 160, 176, 175, 143, 36, 30, 31, 33, 34, 36, 38, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 38, 37, 36, 36, 35, 34, 33, 32, 189, 188, 187, 187, 187, 188, 188, 188, 187, 187, 186, 187, 186, 185, 184, 183, 182, 181, 180, 181, 182, 182, 180, 177, 171, 172, 183, 191, 186, 158, 131, 130, 122, 93, 73, 69, 69, 80, 121, 152, 156, 163, 170, 150, 117, 122, 160, 177, 176, 176, 176, 177, 177, 178, 179, 181, 183, 183, 182, 179, 178, 177, 177, 177, 177, 176, 176, 176, 150, 174, 170, 172, 173, 175, 176, 174, 165, 169, 174, 178, 179, 179, 171, 85, 76, 125, 179, 180, 180, 180, 180, 180, 180, 179, 179, 160, 108, 103, 88, 128, 176, 172, 165, 165, 164, 168, 174, 177, 171, 161, 161, 148, 55, 57, 57, 57, 41, 30, 42, 35, 53, 41, 34, 28, 32, 35, 60, 65, 53, 41, 44, 49, 54, 60, 60, 59, 49, 40, 36, 35, 36, 37, 36, 34, 33, 32, 32, 40, 40, 40, 37, 40, 41, 35, 31, 40, 43, 60, 60, 60, 60, 60, 60, 60, 60, 52, 44, 44, 44, 44, 44, 44, 45, 60, 62, 58, 54, 54, 54, 54, 55, 65, 147, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 196, 203, 204, 204, 203, 199, 190, 189, 189, 188, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 185, 185, 186, 186, 188, 190, 192, 194, 197, 198, 200, 201, 201, 202, 161, 138, 139, 140, 141, 136, 137, 138, 139, 139, 139, 139, 141, 146, 147, 148, 149, 149, 152, 159, 159, 175, 175, 139, 36, 30, 31, 32, 35, 36, 38, 39, 40, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 38, 36, 36, 36, 35, 34, 33, 32, 187, 188, 187, 185, 185, 184, 184, 183, 184, 184, 184, 183, 183, 183, 182, 182, 182, 182, 180, 180, 181, 181, 181, 178, 172, 178, 191, 196, 182, 151, 131, 131, 110, 80, 66, 64, 64, 86, 132, 154, 157, 165, 174, 175, 154, 120, 117, 150, 172, 177, 177, 178, 178, 179, 179, 183, 185, 183, 181, 179, 177, 177, 177, 177, 177, 176, 176, 176, 173, 150, 170, 166, 168, 174, 175, 175, 171, 174, 175, 175, 177, 179, 175, 87, 77, 95, 179, 180, 180, 180, 180, 179, 179, 168, 121, 97, 99, 81, 141, 176, 176, 177, 173, 171, 169, 165, 173, 176, 171, 164, 162, 133, 57, 57, 57, 52, 35, 34, 35, 43, 45, 33, 27, 33, 32, 38, 74, 73, 66, 43, 42, 46, 46, 54, 60, 60, 62, 57, 45, 41, 38, 38, 36, 35, 33, 32, 35, 40, 40, 40, 37, 40, 39, 36, 30, 42, 50, 60, 60, 60, 60, 60, 60, 60, 60, 60, 47, 44, 44, 44, 44, 44, 44, 43, 57, 61, 56, 54, 54, 53, 55, 77, 140, 188, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 197, 203, 203, 204, 202, 191, 189, 189, 189, 189, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 185, 186, 187, 189, 190, 192, 194, 197, 198, 199, 201, 202, 202, 178, 136, 138, 139, 140, 142, 138, 138, 138, 139, 140, 140, 139, 146, 148, 149, 149, 155, 156, 151, 160, 169, 174, 173, 135, 36, 30, 31, 33, 35, 36, 38, 39, 40, 40, 40, 40, 40, 40, 40, 40, 39, 40, 40, 40, 40, 40, 39, 38, 36, 36, 35, 35, 34, 33, 32, 186, 188, 187, 186, 185, 184, 182, 181, 183, 184, 184, 183, 182, 183, 183, 184, 185, 184, 182, 181, 182, 184, 184, 180, 175, 180, 194, 194, 170, 143, 131, 126, 97, 69, 60, 59, 61, 88, 136, 155, 158, 166, 174, 177, 176, 155, 123, 110, 130, 160, 176, 178, 179, 179, 180, 185, 187, 182, 179, 178, 178, 178, 178, 177, 177, 176, 176, 176, 176, 171, 146, 165, 164, 168, 175, 176, 175, 175, 174, 173, 173, 175, 178, 122, 82, 75, 172, 179, 179, 179, 179, 172, 131, 92, 100, 89, 95, 156, 178, 175, 176, 176, 175, 173, 170, 165, 166, 172, 172, 163, 161, 118, 59, 57, 57, 42, 34, 34, 35, 44, 35, 29, 32, 34, 33, 44, 85, 84, 73, 60, 41, 43, 44, 46, 53, 60, 62, 73, 75, 56, 50, 44, 40, 37, 34, 32, 37, 41, 40, 40, 37, 40, 40, 36, 33, 36, 58, 60, 60, 60, 60, 60, 60, 60, 60, 60, 58, 43, 44, 44, 44, 44, 44, 44, 42, 55, 60, 56, 55, 54, 66, 97, 169, 184, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 192, 200, 202, 199, 191, 189, 189, 189, 189, 189, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 186, 186, 186, 187, 189, 190, 192, 194, 197, 198, 200, 201, 202, 202, 187, 134, 136, 138, 139, 139, 142, 137, 139, 139, 141, 142, 142, 142, 147, 149, 149, 151, 167, 173, 167, 155, 175, 176, 173, 125, 35, 31, 32, 33, 35, 37, 38, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 39, 38, 37, 36, 36, 35, 34, 34, 33, 32, 186, 189, 189, 189, 188, 186, 184, 183, 186, 188, 188, 186, 185, 186, 186, 188, 188, 188, 186, 185, 186, 187, 188, 182, 176, 181, 194, 186, 158, 136, 131, 117, 87, 62, 55, 55, 58, 86, 135, 157, 160, 166, 173, 177, 177, 175, 162, 135, 113, 115, 138, 160, 172, 179, 183, 188, 192, 185, 179, 178, 178, 178, 179, 178, 178, 178, 176, 176, 176, 176, 174, 149, 156, 167, 168, 173, 175, 174, 173, 172, 171, 170, 175, 160, 81, 80, 156, 179, 179, 164, 138, 98, 109, 134, 111, 121, 171, 177, 178, 177, 173, 172, 171, 167, 165, 163, 162, 168, 171, 162, 161, 97, 58, 57, 53, 35, 34, 35, 37, 36, 35, 91, 33, 35, 34, 49, 89, 94, 80, 78, 51, 42, 44, 44, 45, 50, 62, 70, 85, 82, 64, 55, 53, 49, 43, 34, 40, 43, 41, 40, 38, 39, 40, 39, 35, 34, 60, 60, 60, 60, 60, 60, 59, 59, 59, 59, 58, 49, 45, 44, 44, 44, 44, 44, 44, 42, 49, 59, 57, 61, 90, 198, 169, 182, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 190, 191, 189, 189, 189, 189, 189, 189, 189, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 186, 187, 188, 189, 191, 192, 194, 197, 198, 200, 201, 202, 202, 193, 139, 134, 135, 137, 140, 140, 141, 136, 138, 140, 142, 142, 144, 147, 149, 149, 149, 149, 157, 169, 169, 164, 177, 177, 175, 126, 35, 31, 32, 33, 35, 37, 38, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 39, 38, 37, 36, 36, 35, 34, 34, 33, 32, 187, 193, 194, 194, 193, 191, 189, 188, 191, 193, 193, 191, 190, 191, 192, 192, 192, 192, 190, 189, 190, 192, 193, 186, 178, 180, 188, 171, 148, 130, 130, 109, 79, 56, 51, 51, 58, 93, 137, 158, 162, 165, 171, 175, 176, 177, 177, 171, 152, 128, 113, 113, 126, 143, 163, 185, 195, 192, 181, 178, 178, 178, 179, 178, 179, 178, 176, 176, 176, 176, 176, 175, 163, 148, 157, 169, 172, 173, 173, 169, 168, 171, 178, 179, 131, 91, 126, 137, 114, 126, 147, 166, 164, 117, 155, 178, 178, 178, 178, 178, 173, 163, 166, 165, 163, 164, 165, 167, 170, 164, 162, 67, 58, 57, 42, 34, 34, 35, 35, 35, 119, 84, 32, 46, 70, 50, 90, 99, 94, 90, 84, 46, 43, 44, 43, 44, 47, 63, 81, 80, 73, 58, 55, 55, 48, 39, 42, 43, 43, 40, 40, 37, 40, 40, 36, 43, 60, 60, 60, 60, 60, 59, 59, 58, 58, 58, 56, 55, 43, 45, 45, 44, 44, 44, 44, 44, 43, 44, 57, 82, 161, 239, 171, 185, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 187, 187, 189, 189, 191, 193, 194, 197, 198, 199, 201, 202, 202, 194, 142, 134, 138, 137, 138, 146, 142, 140, 139, 139, 140, 143, 143, 146, 146, 150, 149, 149, 149, 152, 161, 166, 167, 174, 177, 177, 133, 34, 31, 32, 33, 35, 37, 38, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 38, 37, 36, 35, 35, 35, 34, 32, 32, 188, 194, 196, 196, 196, 196, 195, 194, 197, 199, 199, 196, 195, 196, 197, 196, 197, 195, 194, 193, 193, 194, 196, 190, 182, 179, 175, 159, 139, 129, 127, 102, 72, 52, 49, 49, 64, 105, 146, 160, 163, 165, 170, 174, 176, 176, 177, 177, 176, 170, 155, 137, 122, 114, 113, 123, 143, 163, 173, 173, 175, 177, 178, 178, 177, 176, 176, 176, 176, 176, 177, 179, 177, 175, 167, 151, 150, 150, 153, 157, 156, 159, 158, 161, 154, 97, 89, 164, 180, 179, 178, 143, 140, 175, 178, 179, 178, 178, 177, 177, 172, 164, 166, 173, 166, 165, 165, 164, 167, 168, 155, 56, 57, 53, 35, 34, 34, 35, 34, 71, 144, 37, 38, 58, 128, 46, 89, 99, 100, 99, 99, 80, 44, 43, 43, 43, 43, 45, 50, 59, 63, 59, 56, 55, 46, 34, 43, 43, 44, 45, 41, 37, 40, 40, 39, 41, 60, 60, 60, 60, 59, 58, 57, 57, 57, 57, 54, 54, 49, 43, 45, 44, 45, 44, 44, 44, 44, 45, 50, 106, 231, 220, 175, 186, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 188, 189, 191, 192, 194, 196, 198, 199, 200, 201, 202, 193, 145, 136, 137, 139, 139, 140, 148, 146, 141, 140, 140, 140, 146, 143, 143, 145, 143, 149, 149, 150, 157, 172, 175, 170, 171, 177, 177, 129, 34, 31, 32, 33, 34, 37, 39, 40, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 38, 37, 36, 35, 35, 35, 34, 33, 31, 189, 193, 194, 195, 197, 199, 199, 200, 201, 202, 201, 200, 200, 201, 201, 201, 200, 199, 197, 195, 195, 197, 199, 196, 187, 180, 164, 148, 131, 131, 123, 97, 66, 49, 46, 47, 66, 110, 150, 161, 164, 168, 172, 176, 178, 178, 178, 177, 177, 177, 178, 177, 170, 162, 154, 148, 145, 139, 136, 138, 143, 153, 165, 173, 176, 176, 176, 176, 176, 176, 178, 180, 181, 176, 176, 176, 176, 174, 168, 169, 172, 176, 179, 179, 179, 158, 100, 117, 174, 167, 153, 175, 179, 179, 180, 178, 178, 177, 176, 175, 171, 164, 165, 174, 173, 165, 162, 161, 165, 171, 135, 58, 57, 41, 34, 34, 34, 34, 40, 136, 125, 35, 57, 98, 152, 38, 84, 96, 98, 97, 100, 99, 79, 45, 43, 43, 42, 42, 43, 45, 47, 50, 52, 51, 47, 37, 42, 43, 44, 53, 51, 38, 40, 40, 39, 42, 59, 60, 60, 59, 58, 57, 56, 56, 56, 55, 53, 53, 53, 44, 45, 45, 44, 44, 44, 44, 44, 47, 78, 189, 244, 187, 174, 184, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 189, 189, 189, 191, 192, 194, 196, 197, 199, 200, 201, 202, 188, 124, 139, 136, 138, 140, 140, 140, 146, 146, 142, 141, 140, 141, 146, 146, 142, 151, 151, 153, 149, 150, 152, 168, 176, 175, 172, 177, 177, 122, 33, 31, 32, 33, 34, 37, 38, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 38, 37, 37, 35, 35, 35, 34, 33, 33, 32, 188, 192, 192, 193, 196, 199, 202, 202, 202, 203, 201, 201, 201, 202, 202, 202, 201, 200, 198, 196, 196, 198, 200, 199, 191, 180, 158, 139, 128, 133, 121, 93, 61, 47, 45, 45, 63, 108, 149, 161, 166, 171, 174, 177, 180, 180, 180, 178, 177, 179, 184, 186, 182, 180, 181, 184, 190, 191, 189, 189, 193, 194, 185, 179, 177, 176, 176, 176, 176, 176, 176, 179, 181, 178, 176, 176, 176, 176, 174, 175, 177, 177, 178, 180, 179, 179, 149, 100, 108, 152, 179, 179, 179, 179, 180, 179, 177, 177, 174, 173, 173, 167, 168, 174, 175, 168, 164, 163, 167, 144, 81, 56, 52, 34, 34, 34, 39, 42, 114, 151, 101, 54, 82, 123, 162, 47, 72, 90, 88, 81, 83, 93, 98, 82, 49, 43, 42, 42, 42, 42, 42, 42, 43, 44, 43, 37, 42, 43, 45, 57, 60, 51, 37, 40, 37, 44, 57, 60, 60, 58, 57, 56, 55, 55, 55, 54, 51, 51, 51, 50, 43, 45, 44, 44, 44, 44, 44, 49, 106, 238, 211, 174, 173, 181, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 188, 189, 189, 190, 191, 192, 194, 196, 197, 199, 200, 201, 201, 176, 78, 115, 136, 138, 139, 142, 140, 141, 143, 144, 142, 142, 142, 142, 145, 150, 147, 154, 155, 159, 152, 151, 152, 163, 174, 177, 176, 177, 177, 115, 32, 31, 32, 33, 35, 37, 38, 40, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 39, 38, 37, 36, 35, 35, 35, 34, 33, 32, 32, 188, 191, 191, 193, 195, 199, 202, 202, 202, 202, 201, 201, 201, 202, 202, 201, 200, 198, 196, 195, 196, 198, 199, 198, 193, 178, 155, 134, 129, 133, 119, 88, 58, 45, 43, 43, 60, 103, 146, 164, 169, 173, 176, 177, 180, 182, 180, 179, 178, 180, 184, 185, 183, 184, 188, 188, 189, 190, 190, 187, 191, 193, 188, 182, 177, 176, 176, 176, 176, 176, 176, 177, 181, 177, 176, 176, 176, 176, 176, 177, 177, 177, 178, 179, 179, 176, 140, 115, 101, 104, 142, 171, 179, 179, 178, 177, 175, 174, 173, 173, 175, 176, 178, 178, 178, 177, 173, 147, 92, 60, 50, 56, 40, 34, 34, 34, 83, 124, 150, 151, 78, 82, 90, 136, 161, 88, 56, 84, 77, 70, 65, 62, 72, 82, 77, 54, 43, 42, 42, 42, 42, 42, 42, 42, 42, 39, 41, 42, 45, 59, 60, 59, 41, 40, 36, 45, 53, 60, 60, 57, 56, 55, 55, 54, 54, 51, 50, 49, 49, 50, 47, 44, 45, 44, 44, 44, 45, 62, 168, 230, 175, 174, 172, 182, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 187, 187, 187, 187, 187, 187, 187, 187, 188, 189, 189, 189, 190, 191, 192, 193, 195, 197, 198, 199, 200, 200, 152, 59, 56, 131, 136, 139, 140, 145, 145, 144, 145, 145, 146, 145, 143, 146, 151, 154, 155, 156, 157, 164, 162, 163, 154, 171, 175, 177, 177, 176, 177, 103, 32, 31, 32, 33, 35, 37, 38, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 40, 39, 38, 37, 36, 35, 35, 34, 34, 33, 31, 32, 189, 191, 192, 193, 195, 198, 201, 201, 201, 201, 201, 201, 201, 201, 201, 200, 197, 195, 194, 194, 194, 195, 196, 194, 190, 173, 150, 132, 132, 134, 117, 85, 56, 45, 42, 43, 62, 106, 147, 166, 172, 177, 179, 180, 183, 183, 182, 180, 180, 180, 181, 182, 182, 187, 192, 190, 189, 190, 190, 186, 187, 189, 193, 187, 178, 177, 176, 176, 176, 176, 176, 178, 181, 178, 176, 176, 176, 176, 177, 177, 178, 177, 177, 179, 156, 102, 142, 179, 167, 120, 100, 100, 124, 147, 165, 173, 173, 173, 173, 173, 176, 177, 178, 178, 177, 158, 101, 58, 98, 127, 56, 49, 34, 34, 34, 38, 120, 153, 151, 148, 78, 100, 90, 146, 157, 122, 45, 74, 75, 66, 63, 58, 50, 52, 60, 64, 57, 46, 42, 42, 42, 42, 42, 42, 42, 38, 41, 42, 46, 60, 60, 60, 45, 39, 36, 45, 49, 60, 59, 56, 55, 54, 54, 53, 53, 49, 49, 48, 48, 49, 49, 44, 45, 44, 44, 44, 48, 82, 211, 240, 173, 173, 171, 185, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 187, 187, 187, 187, 187, 187, 188, 189, 189, 189, 189, 189, 190, 191, 192, 193, 195, 196, 197, 198, 199, 188, 114, 49, 48, 88, 134, 141, 140, 141, 147, 148, 146, 144, 143, 148, 143, 150, 154, 155, 155, 156, 157, 159, 168, 171, 175, 163, 169, 174, 176, 177, 177, 178, 90, 31, 31, 32, 34, 35, 37, 38, 39, 40, 39, 40, 40, 40, 40, 40, 40, 40, 40, 39, 40, 39, 38, 37, 36, 35, 35, 35, 34, 33, 32, 31, 189, 191, 192, 192, 194, 196, 198, 199, 200, 200, 200, 201, 201, 201, 201, 198, 195, 193, 192, 191, 192, 192, 191, 188, 183, 165, 143, 130, 133, 135, 116, 83, 54, 44, 42, 45, 67, 110, 150, 166, 173, 180, 183, 186, 186, 186, 183, 182, 183, 183, 181, 183, 185, 189, 191, 191, 190, 190, 190, 191, 194, 195, 195, 192, 181, 178, 177, 177, 177, 178, 179, 181, 185, 179, 176, 176, 176, 176, 177, 178, 178, 178, 171, 124, 96, 159, 179, 179, 180, 179, 160, 129, 106, 104, 101, 109, 130, 141, 147, 149, 150, 150, 152, 154, 135, 117, 136, 159, 169, 118, 51, 37, 34, 34, 34, 68, 146, 154, 152, 141, 101, 97, 98, 143, 154, 150, 50, 58, 70, 66, 63, 62, 60, 52, 47, 46, 48, 49, 47, 43, 42, 42, 42, 42, 43, 37, 41, 41, 44, 59, 60, 60, 52, 37, 38, 43, 47, 57, 58, 55, 54, 53, 52, 52, 51, 48, 48, 48, 48, 48, 48, 50, 43, 44, 44, 45, 50, 114, 241, 244, 173, 173, 176, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 188, 188, 188, 189, 189, 189, 189, 189, 188, 189, 190, 191, 192, 193, 194, 196, 197, 198, 198, 159, 69, 48, 47, 47, 116, 139, 146, 144, 145, 144, 144, 146, 145, 143, 145, 146, 154, 157, 156, 156, 157, 159, 163, 168, 171, 177, 175, 171, 175, 169, 176, 177, 178, 73, 31, 31, 32, 34, 35, 38, 38, 40, 40, 39, 39, 40, 40, 40, 40, 40, 40, 39, 40, 39, 38, 38, 37, 36, 35, 35, 34, 33, 33, 32, 31, 189, 191, 191, 191, 192, 193, 194, 196, 198, 200, 201, 201, 201, 201, 200, 197, 194, 190, 188, 188, 189, 187, 183, 179, 173, 155, 137, 129, 136, 136, 114, 82, 54, 44, 41, 46, 67, 106, 147, 166, 173, 183, 189, 192, 189, 188, 184, 185, 188, 186, 187, 192, 193, 194, 193, 192, 193, 193, 194, 195, 197, 198, 196, 192, 188, 184, 182, 179, 179, 179, 180, 181, 183, 178, 177, 177, 176, 177, 178, 178, 178, 152, 91, 104, 169, 179, 180, 181, 186, 183, 181, 183, 179, 169, 157, 147, 141, 139, 140, 145, 145, 147, 152, 157, 160, 166, 167, 166, 164, 65, 38, 34, 34, 34, 48, 123, 154, 153, 152, 148, 106, 94, 103, 132, 153, 153, 110, 49, 59, 63, 63, 63, 62, 62, 61, 56, 48, 46, 46, 44, 41, 37, 70, 70, 124, 64, 40, 41, 44, 52, 60, 60, 57, 38, 40, 39, 45, 54, 57, 54, 52, 52, 51, 51, 50, 48, 47, 47, 47, 47, 47, 49, 48, 43, 45, 46, 58, 181, 245, 238, 173, 173, 172, 181, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 190, 192, 192, 193, 194, 196, 196, 197, 187, 159, 58, 48, 46, 47, 54, 134, 143, 147, 147, 147, 143, 145, 148, 148, 149, 146, 148, 157, 159, 159, 159, 161, 162, 165, 166, 167, 176, 177, 176, 172, 157, 171, 176, 176, 56, 31, 31, 32, 33, 36, 37, 39, 40, 40, 40, 39, 39, 40, 40, 40, 40, 39, 40, 40, 39, 38, 37, 36, 35, 35, 35, 34, 33, 33, 32, 31, 189, 191, 190, 190, 191, 192, 193, 194, 197, 200, 200, 201, 201, 200, 199, 196, 192, 188, 185, 184, 184, 180, 175, 170, 163, 148, 134, 130, 139, 138, 114, 82, 56, 44, 47, 54, 68, 96, 135, 165, 175, 186, 193, 195, 192, 189, 188, 189, 190, 189, 192, 200, 199, 197, 197, 197, 197, 197, 197, 197, 195, 194, 195, 195, 195, 194, 194, 190, 187, 184, 181, 181, 180, 178, 179, 178, 177, 178, 178, 173, 125, 80, 111, 173, 179, 179, 180, 180, 188, 189, 188, 190, 184, 181, 184, 179, 178, 176, 173, 171, 169, 162, 156, 156, 156, 156, 156, 156, 122, 36, 35, 34, 34, 34, 95, 155, 154, 152, 152, 149, 106, 92, 106, 143, 141, 151, 147, 61, 47, 60, 62, 63, 63, 63, 62, 61, 60, 56, 52, 49, 44, 37, 134, 153, 157, 134, 41, 40, 43, 46, 57, 60, 59, 43, 36, 37, 45, 48, 55, 54, 51, 51, 50, 50, 48, 47, 47, 46, 47, 47, 47, 48, 49, 46, 44, 47, 67, 222, 246, 213, 175, 173, 172, 173, 183, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 189, 190, 191, 192, 192, 193, 194, 195, 196, 190, 168, 164, 132, 47, 47, 47, 47, 100, 141, 143, 147, 147, 147, 142, 148, 149, 149, 149, 149, 149, 160, 162, 162, 163, 164, 166, 167, 165, 165, 170, 176, 171, 162, 151, 158, 166, 168, 37, 31, 32, 32, 34, 35, 37, 38, 40, 40, 40, 40, 39, 39, 39, 39, 39, 39, 40, 40, 39, 38, 36, 36, 35, 35, 34, 33, 33, 32, 32, 30, 191, 192, 191, 191, 192, 193, 194, 195, 197, 199, 200, 200, 200, 199, 199, 195, 191, 185, 181, 180, 178, 174, 168, 165, 158, 142, 132, 131, 142, 138, 116, 85, 57, 46, 56, 71, 80, 97, 125, 163, 177, 187, 195, 198, 196, 193, 192, 192, 191, 190, 195, 202, 201, 199, 201, 201, 201, 198, 198, 198, 195, 193, 195, 197, 198, 200, 201, 198, 193, 191, 183, 179, 179, 179, 179, 178, 177, 178, 162, 101, 79, 122, 176, 179, 180, 180, 183, 185, 188, 189, 192, 192, 186, 184, 190, 183, 179, 177, 174, 172, 171, 162, 156, 156, 156, 155, 155, 119, 33, 35, 34, 34, 34, 60, 149, 156, 155, 153, 152, 150, 118, 94, 108, 153, 134, 142, 151, 134, 46, 54, 62, 63, 63, 63, 63, 63, 63, 63, 62, 54, 41, 37, 143, 160, 159, 153, 57, 40, 43, 44, 48, 60, 60, 48, 36, 36, 45, 46, 52, 53, 50, 50, 50, 49, 47, 46, 46, 46, 46, 46, 46, 48, 49, 49, 45, 49, 110, 242, 241, 162, 145, 167, 172, 172, 175, 186, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 190, 190, 191, 192, 192, 193, 194, 195, 186, 168, 160, 168, 168, 73, 46, 47, 49, 52, 129, 147, 145, 147, 148, 146, 147, 151, 150, 150, 151, 150, 150, 155, 164, 165, 167, 168, 170, 168, 165, 165, 166, 169, 162, 154, 150, 158, 164, 156, 28, 31, 32, 32, 33, 35, 37, 38, 38, 40, 40, 40, 40, 39, 39, 39, 39, 40, 40, 40, 38, 37, 36, 36, 35, 34, 33, 34, 33, 32, 31, 65, 194, 195, 193, 194, 195, 195, 196, 196, 198, 199, 199, 199, 199, 199, 197, 195, 191, 185, 180, 176, 173, 170, 166, 162, 155, 140, 132, 133, 144, 139, 118, 88, 60, 48, 65, 91, 98, 101, 120, 159, 177, 185, 192, 196, 197, 195, 193, 192, 192, 191, 195, 201, 202, 201, 201, 202, 201, 198, 198, 199, 195, 191, 190, 193, 195, 199, 201, 199, 194, 190, 184, 180, 180, 180, 178, 178, 175, 148, 90, 81, 129, 177, 179, 180, 183, 187, 189, 190, 190, 188, 192, 190, 182, 186, 191, 185, 178, 177, 175, 173, 172, 162, 155, 156, 155, 154, 109, 36, 31, 35, 34, 34, 41, 138, 156, 156, 156, 155, 153, 155, 123, 99, 109, 154, 152, 135, 134, 151, 132, 54, 51, 60, 62, 63, 63, 61, 56, 49, 36, 32, 35, 33, 96, 154, 154, 153, 109, 41, 42, 44, 44, 54, 60, 53, 40, 34, 41, 45, 48, 52, 50, 49, 49, 49, 47, 46, 46, 46, 46, 46, 46, 47, 48, 49, 52, 60, 157, 238, 167, 147, 144, 133, 144, 169, 173, 180, 188, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 190, 190, 190, 191, 191, 192, 192, 192, 175, 160, 159, 167, 167, 167, 152, 46, 45, 46, 69, 126, 147, 146, 148, 148, 152, 152, 154, 155, 154, 153, 153, 150, 150, 152, 164, 165, 170, 171, 166, 163, 161, 165, 164, 164, 162, 159, 151, 161, 170, 152, 30, 31, 32, 33, 33, 35, 37, 38, 38, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 38, 37, 36, 35, 35, 34, 33, 34, 33, 32, 32, 96, 198, 198, 197, 198, 199, 200, 200, 199, 199, 199, 198, 198, 199, 198, 196, 194, 192, 188, 182, 177, 172, 170, 166, 164, 155, 140, 133, 135, 145, 141, 122, 92, 65, 49, 68, 99, 110, 107, 114, 150, 176, 181, 188, 191, 194, 194, 193, 193, 192, 192, 196, 201, 203, 202, 200, 200, 199, 198, 198, 197, 195, 191, 188, 187, 187, 190, 196, 194, 187, 184, 183, 181, 180, 179, 178, 173, 133, 84, 82, 134, 178, 179, 180, 182, 189, 191, 191, 190, 191, 191, 192, 190, 185, 189, 191, 184, 178, 177, 175, 173, 172, 158, 154, 153, 149, 93, 36, 30, 35, 34, 34, 34, 120, 156, 156, 157, 159, 160, 158, 153, 134, 104, 109, 155, 152, 152, 147, 130, 130, 130, 92, 48, 40, 43, 42, 41, 38, 30, 36, 33, 33, 33, 34, 105, 151, 151, 145, 54, 42, 43, 44, 46, 58, 57, 42, 37, 38, 45, 46, 50, 49, 49, 49, 48, 46, 46, 46, 46, 46, 46, 46, 46, 48, 49, 67, 112, 218, 236, 140, 146, 143, 143, 142, 133, 146, 166, 186, 187, 188, 188, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 190, 190, 191, 191, 191, 191, 180, 166, 156, 164, 167, 167, 167, 167, 167, 107, 46, 45, 45, 79, 137, 150, 153, 153, 155, 159, 154, 154, 152, 150, 150, 154, 150, 150, 153, 158, 157, 165, 169, 163, 163, 159, 165, 161, 162, 162, 161, 153, 157, 171, 144, 31, 31, 32, 33, 33, 35, 37, 38, 38, 39, 40, 40, 40, 40, 40, 40, 40, 40, 39, 38, 38, 36, 36, 35, 35, 34, 33, 33, 33, 32, 31, 116, 199, 201, 200, 201, 202, 202, 202, 201, 200, 200, 200, 199, 198, 197, 195, 193, 193, 189, 185, 180, 175, 172, 170, 168, 160, 144, 136, 137, 146, 142, 127, 99, 70, 52, 68, 103, 118, 112, 113, 139, 171, 179, 183, 187, 190, 193, 193, 193, 193, 195, 198, 202, 203, 201, 197, 197, 198, 199, 199, 197, 195, 193, 190, 185, 180, 181, 186, 186, 181, 179, 180, 179, 179, 178, 169, 124, 86, 91, 133, 177, 179, 180, 180, 180, 187, 191, 189, 188, 191, 191, 191, 188, 188, 189, 188, 180, 178, 177, 175, 174, 168, 152, 151, 141, 73, 35, 35, 29, 35, 34, 45, 103, 153, 154, 160, 166, 167, 163, 160, 159, 140, 103, 110, 155, 154, 152, 152, 151, 152, 146, 137, 133, 124, 54, 59, 61, 61, 56, 42, 35, 33, 32, 33, 35, 107, 150, 150, 118, 42, 43, 43, 44, 49, 59, 45, 40, 36, 44, 44, 48, 49, 49, 48, 48, 46, 46, 45, 45, 45, 45, 46, 46, 48, 65, 102, 212, 247, 230, 142, 144, 143, 143, 143, 143, 142, 138, 146, 161, 178, 187, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 189, 189, 189, 189, 190, 190, 190, 186, 176, 168, 162, 158, 166, 169, 168, 168, 167, 167, 167, 167, 140, 46, 45, 45, 45, 96, 148, 155, 155, 155, 159, 161, 152, 152, 149, 149, 149, 152, 149, 152, 160, 162, 162, 163, 165, 164, 162, 163, 165, 157, 159, 161, 160, 154, 153, 163, 131, 31, 31, 32, 33, 34, 35, 37, 38, 38, 38, 39, 40, 40, 40, 40, 40, 40, 39, 38, 38, 37, 36, 36, 35, 34, 33, 33, 33, 33, 32, 30, 133, 200, 201, 202, 202, 202, 202, 202, 202, 202, 201, 200, 200, 199, 196, 194, 193, 193, 191, 187, 182, 178, 175, 174, 172, 165, 150, 141, 139, 146, 143, 132, 106, 77, 56, 68, 105, 131, 123, 116, 128, 162, 178, 180, 184, 188, 191, 192, 192, 194, 198, 202, 203, 202, 200, 197, 196, 198, 201, 202, 199, 194, 191, 189, 184, 179, 179, 179, 180, 179, 179, 179, 178, 177, 164, 119, 88, 117, 154, 177, 182, 182, 186, 181, 180, 179, 184, 183, 184, 191, 191, 189, 183, 189, 190, 183, 179, 178, 177, 175, 173, 158, 151, 126, 52, 35, 35, 31, 34, 35, 59, 108, 152, 153, 159, 168, 168, 166, 164, 168, 163, 135, 102, 123, 156, 155, 152, 152, 152, 151, 151, 151, 151, 151, 139, 74, 87, 65, 62, 61, 54, 39, 33, 32, 32, 34, 101, 148, 147, 109, 43, 43, 43, 44, 55, 50, 41, 36, 44, 44, 46, 49, 48, 48, 47, 46, 45, 45, 45, 45, 45, 46, 46, 60, 102, 179, 244, 247, 196, 147, 144, 143, 143, 143, 143, 143, 143, 143, 144, 140, 141, 151, 160, 167, 176, 182, 185, 187, 188, 188, 188, 187, 184, 176, 170, 159, 155, 155, 163, 175, 189, 197, 197, 189, 175, 169, 169, 169, 167, 167, 167, 167, 93, 43, 43, 44, 50, 114, 154, 158, 156, 155, 160, 163, 152, 151, 149, 149, 149, 151, 150, 152, 163, 164, 164, 164, 164, 165, 165, 165, 163, 157, 154, 157, 156, 151, 150, 152, 111, 31, 32, 32, 32, 33, 35, 37, 37, 38, 38, 38, 39, 39, 40, 40, 39, 39, 38, 38, 38, 37, 36, 35, 35, 34, 33, 33, 33, 32, 32, 54, 145, 200, 202, 202, 203, 202, 202, 202, 202, 202, 202, 201, 201, 199, 196, 194, 193, 193, 192, 188, 183, 180, 179, 178, 177, 171, 155, 146, 140, 146, 145, 136, 114, 85, 63, 69, 109, 147, 144, 127, 124, 148, 175, 180, 184, 188, 190, 189, 190, 194, 199, 203, 204, 203, 202, 200, 199, 201, 202, 203, 201, 194, 190, 187, 182, 179, 179, 179, 179, 180, 179, 179, 178, 162, 116, 98, 131, 163, 179, 187, 191, 189, 190, 187, 180, 179, 183, 184, 186, 191, 191, 189, 187, 190, 189, 180, 178, 177, 176, 174, 166, 147, 100, 37, 35, 34, 35, 30, 39, 60, 113, 150, 151, 158, 167, 167, 167, 167, 168, 169, 162, 141, 107, 129, 154, 157, 155, 152, 152, 152, 151, 151, 151, 151, 154, 149, 129, 63, 75, 69, 63, 60, 47, 34, 31, 31, 31, 82, 140, 142, 77, 43, 43, 43, 46, 52, 42, 39, 40, 44, 45, 48, 48, 48, 47, 46, 45, 45, 45, 45, 45, 45, 55, 107, 175, 212, 247, 229, 146, 145, 143, 143, 143, 143, 143, 143, 143, 143, 144, 145, 146, 146, 147, 146, 145, 144, 145, 151, 163, 169, 170, 174, 176, 183, 188, 181, 172, 175, 187, 196, 198, 201, 204, 207, 210, 200, 180, 169, 168, 168, 168, 150, 45, 40, 40, 42, 105, 147, 162, 159, 156, 153, 154, 161, 155, 151, 149, 149, 150, 155, 157, 158, 162, 164, 163, 162, 163, 165, 165, 165, 164, 159, 151, 157, 159, 150, 149, 152, 97, 30, 32, 31, 32, 33, 35, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 37, 36, 35, 35, 34, 33, 34, 33, 33, 32, 32, 85, 148, 201, 201, 201, 202, 202, 202, 202, 202, 202, 201, 201, 201, 200, 197, 194, 193, 193, 191, 188, 185, 182, 182, 181, 180, 176, 162, 150, 143, 146, 146, 140, 122, 94, 69, 70, 107, 153, 166, 143, 130, 137, 166, 184, 189, 191, 192, 191, 190, 195, 201, 203, 204, 203, 203, 203, 203, 203, 204, 204, 202, 198, 193, 188, 183, 183, 185, 185, 184, 185, 184, 181, 160, 116, 91, 133, 170, 179, 186, 191, 193, 192, 192, 192, 189, 183, 189, 193, 192, 189, 190, 190, 190, 188, 183, 177, 176, 175, 173, 167, 135, 67, 35, 34, 34, 35, 60, 35, 60, 117, 147, 152, 157, 166, 167, 167, 167, 167, 168, 169, 164, 154, 137, 117, 142, 157, 158, 154, 153, 153, 151, 151, 151, 153, 157, 153, 155, 141, 146, 106, 74, 63, 62, 56, 44, 34, 33, 32, 52, 114, 109, 55, 42, 43, 44, 47, 43, 41, 38, 45, 45, 46, 48, 47, 47, 45, 45, 45, 45, 45, 45, 52, 106, 175, 183, 235, 229, 152, 146, 144, 143, 143, 143, 143, 143, 143, 143, 143, 145, 147, 147, 148, 148, 148, 150, 155, 165, 173, 176, 179, 182, 185, 187, 190, 192, 192, 191, 188, 193, 196, 199, 202, 205, 209, 212, 217, 220, 176, 147, 173, 162, 68, 37, 38, 39, 96, 144, 150, 167, 161, 156, 151, 151, 155, 157, 152, 149, 149, 152, 159, 162, 163, 163, 164, 161, 162, 159, 165, 166, 165, 165, 162, 156, 162, 164, 155, 150, 162, 81, 30, 32, 31, 32, 34, 35, 36, 36, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 37, 37, 36, 35, 35, 34, 33, 33, 33, 33, 32, 32, 105, 144, 201, 201, 201, 202, 202, 203, 202, 202, 201, 201, 201, 201, 200, 198, 196, 193, 192, 190, 188, 187, 186, 186, 185, 183, 180, 167, 154, 146, 144, 146, 142, 130, 105, 78, 69, 100, 148, 180, 162, 141, 136, 153, 183, 193, 197, 197, 195, 195, 198, 202, 203, 204, 204, 204, 204, 204, 204, 204, 204, 203, 201, 197, 191, 186, 186, 189, 190, 188, 188, 186, 165, 121, 86, 107, 158, 176, 180, 190, 192, 193, 192, 191, 194, 193, 190, 192, 193, 190, 183, 183, 186, 185, 185, 180, 174, 174, 171, 158, 105, 41, 35, 34, 34, 36, 100, 81, 36, 73, 148, 154, 155, 163, 166, 167, 167, 167, 167, 168, 169, 169, 160, 151, 134, 145, 157, 162, 160, 155, 154, 152, 152, 151, 156, 163, 152, 156, 156, 159, 155, 140, 102, 84, 107, 71, 56, 47, 38, 33, 32, 42, 40, 41, 42, 43, 45, 44, 41, 37, 44, 45, 46, 48, 47, 47, 45, 45, 45, 45, 45, 54, 107, 175, 180, 192, 208, 148, 146, 144, 143, 143, 143, 143, 143, 143, 143, 143, 144, 146, 151, 157, 159, 160, 163, 169, 172, 175, 178, 179, 181, 184, 186, 188, 191, 192, 192, 194, 194, 196, 197, 200, 203, 177, 181, 198, 192, 143, 107, 142, 146, 63, 35, 35, 37, 50, 137, 147, 152, 170, 164, 157, 151, 150, 151, 159, 153, 149, 149, 150, 161, 163, 164, 164, 163, 163, 164, 158, 163, 162, 166, 165, 161, 158, 163, 165, 159, 163, 170, 55, 31, 32, 31, 32, 34, 34, 36, 36, 36, 37, 37, 38, 37, 37, 38, 38, 38, 38, 37, 36, 35, 34, 34, 33, 34, 33, 33, 32, 32, 31, 121, 142, 202, 201, 201, 201, 201, 202, 202, 202, 202, 201, 201, 201, 201, 199, 197, 194, 192, 188, 188, 188, 188, 188, 188, 187, 183, 173, 159, 150, 143, 146, 144, 136, 116, 89, 71, 89, 133, 176, 182, 155, 143, 145, 168, 192, 199, 200, 198, 196, 197, 199, 201, 203, 204, 204, 204, 204, 204, 204, 204, 204, 202, 198, 192, 186, 186, 190, 189, 186, 184, 166, 126, 89, 87, 129, 172, 181, 185, 191, 193, 193, 192, 193, 192, 191, 191, 189, 189, 186, 180, 177, 179, 178, 179, 174, 164, 160, 131, 69, 36, 35, 58, 53, 82, 110, 128, 40, 36, 108, 154, 154, 158, 164, 167, 167, 167, 167, 167, 169, 170, 171, 167, 155, 137, 123, 134, 159, 163, 161, 156, 154, 152, 151, 163, 165, 151, 155, 154, 153, 157, 159, 157, 147, 149, 107, 66, 80, 56, 51, 43, 37, 31, 40, 42, 43, 44, 43, 41, 37, 44, 45, 46, 46, 47, 47, 45, 45, 45, 45, 52, 105, 175, 179, 180, 131, 145, 146, 144, 143, 143, 143, 143, 143, 143, 143, 143, 145, 148, 157, 166, 169, 170, 172, 175, 178, 179, 179, 179, 179, 181, 184, 187, 189, 191, 192, 193, 194, 160, 165, 174, 161, 115, 50, 53, 56, 60, 62, 60, 38, 33, 35, 35, 34, 59, 128, 147, 148, 150, 171, 168, 159, 154, 150, 150, 156, 155, 150, 149, 150, 158, 163, 162, 163, 162, 164, 164, 162, 163, 162, 161, 164, 162, 153, 157, 160, 166, 174, 172, 31, 31, 32, 32, 33, 33, 35, 35, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 36, 35, 34, 34, 34, 33, 33, 33, 31, 32, 29, 134, 142, 204, 201, 200, 200, 201, 201, 201, 201, 201, 201, 201, 200, 201, 200, 199, 196, 193, 190, 188, 188, 189, 190, 190, 188, 185, 179, 165, 155, 146, 143, 145, 140, 126, 102, 78, 79, 116, 162, 192, 175, 153, 146, 153, 179, 195, 196, 195, 193, 192, 193, 197, 202, 203, 204, 204, 204, 204, 204, 204, 204, 201, 199, 194, 189, 188, 191, 188, 182, 164, 129, 92, 81, 104, 148, 179, 190, 192, 193, 190, 188, 185, 188, 185, 180, 181, 180, 184, 186, 183, 180, 178, 176, 173, 161, 139, 95, 49, 35, 39, 80, 116, 138, 150, 151, 73, 41, 88, 153, 154, 155, 160, 165, 169, 170, 170, 171, 172, 173, 173, 172, 171, 159, 152, 126, 107, 150, 160, 166, 163, 156, 153, 152, 165, 157, 151, 151, 152, 151, 153, 155, 158, 158, 160, 158, 143, 142, 108, 62, 49, 42, 35, 34, 40, 42, 43, 43, 41, 40, 41, 44, 46, 46, 47, 47, 45, 45, 45, 45, 71, 167, 179, 179, 167, 137, 144, 144, 144, 143, 143, 143, 143, 143, 143, 144, 149, 158, 163, 167, 171, 174, 176, 178, 179, 179, 179, 179, 179, 179, 180, 167, 185, 190, 192, 193, 183, 126, 37, 37, 38, 43, 51, 54, 56, 56, 57, 58, 59, 53, 31, 34, 35, 54, 139, 147, 147, 148, 148, 168, 171, 163, 161, 154, 150, 153, 170, 162, 151, 150, 158, 164, 159, 155, 158, 164, 164, 163, 163, 163, 162, 162, 161, 154, 151, 154, 167, 175, 161, 29, 31, 32, 32, 33, 33, 34, 35, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 35, 34, 34, 34, 33, 33, 33, 33, 31, 31, 40, 141, 142, 204, 201, 199, 200, 200, 200, 200, 200, 199, 199, 200, 201, 200, 200, 199, 198, 194, 192, 189, 189, 189, 190, 190, 189, 186, 181, 171, 160, 151, 144, 142, 143, 135, 115, 90, 78, 106, 150, 190, 194, 168, 150, 147, 157, 181, 192, 189, 187, 185, 187, 191, 197, 201, 203, 203, 203, 204, 204, 204, 203, 202, 200, 197, 193, 190, 192, 188, 168, 133, 98, 81, 98, 129, 164, 183, 193, 193, 192, 182, 180, 179, 180, 182, 179, 175, 175, 180, 181, 185, 179, 173, 164, 146, 107, 65, 47, 35, 35, 43, 116, 140, 155, 154, 119, 49, 77, 150, 155, 154, 155, 160, 165, 168, 169, 172, 174, 174, 175, 175, 174, 175, 171, 161, 151, 116, 109, 148, 164, 168, 161, 154, 155, 163, 153, 151, 151, 151, 151, 151, 151, 152, 153, 157, 159, 156, 155, 158, 157, 151, 145, 139, 121, 57, 40, 42, 43, 41, 41, 39, 44, 46, 46, 46, 47, 45, 45, 45, 50, 133, 179, 179, 176, 136, 145, 144, 144, 144, 143, 143, 143, 143, 143, 145, 148, 159, 164, 167, 171, 175, 177, 178, 179, 179, 179, 179, 179, 179, 179, 148, 36, 47, 71, 86, 81, 44, 37, 39, 40, 43, 45, 48, 53, 55, 55, 56, 57, 58, 60, 42, 34, 70, 138, 147, 148, 148, 148, 148, 162, 170, 167, 165, 160, 153, 155, 170, 168, 158, 152, 158, 164, 160, 155, 158, 163, 164, 160, 161, 161, 162, 160, 154, 150, 151, 153, 163, 175, 146, 31, 31, 32, 32, 33, 33, 34, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 36, 36, 35, 35, 33, 34, 33, 33, 33, 33, 33, 31, 31, 62, 142, 140, 204, 200, 200, 200, 200, 200, 199, 197, 196, 196, 197, 199, 200, 200, 199, 199, 196, 193, 191, 190, 190, 190, 190, 189, 186, 182, 178, 168, 159, 150, 143, 141, 139, 127, 105, 86, 102, 138, 180, 201, 188, 162, 150, 148, 158, 178, 184, 182, 180, 181, 185, 190, 195, 199, 201, 203, 203, 203, 203, 203, 201, 200, 199, 194, 190, 189, 176, 142, 105, 82, 95, 125, 158, 177, 189, 194, 194, 190, 179, 176, 182, 181, 180, 180, 175, 173, 176, 168, 169, 162, 147, 113, 73, 57, 46, 35, 35, 51, 73, 130, 153, 154, 145, 64, 71, 143, 155, 156, 156, 156, 160, 164, 168, 171, 174, 175, 175, 175, 175, 176, 177, 177, 168, 160, 174, 165, 149, 157, 173, 166, 160, 167, 162, 155, 151, 151, 151, 151, 151, 151, 151, 152, 152, 155, 152, 152, 152, 153, 156, 154, 151, 149, 106, 50, 41, 42, 42, 41, 38, 44, 45, 46, 46, 47, 45, 45, 45, 73, 174, 179, 167, 134, 146, 145, 145, 144, 144, 144, 144, 145, 146, 148, 150, 160, 165, 168, 171, 175, 177, 178, 179, 179, 179, 179, 179, 179, 180, 166, 57, 37, 37, 36, 36, 35, 37, 38, 39, 41, 43, 45, 48, 52, 54, 55, 56, 57, 58, 59, 59, 85, 145, 148, 147, 148, 148, 148, 148, 156, 166, 167, 166, 166, 159, 160, 165, 161, 159, 154, 157, 163, 162, 162, 163, 164, 164, 157, 151, 151, 157, 158, 151, 149, 151, 153, 161, 174, 128, 31, 31, 32, 31, 33, 33, 34, 34, 35, 35, 35, 36, 35, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33, 33, 32, 32, 31, 83, 147, 140, 206, 202, 202, 202, 203, 201, 199, 196, 193, 192, 193, 195, 198, 199, 199, 198, 196, 193, 191, 189, 189, 189, 188, 188, 184, 181, 179, 176, 166, 158, 151, 144, 139, 134, 119, 100, 101, 125, 159, 188, 199, 183, 161, 151, 149, 157, 171, 178, 178, 178, 180, 184, 188, 193, 197, 201, 203, 203, 203, 201, 200, 198, 197, 192, 187, 179, 151, 116, 93, 98, 120, 153, 177, 189, 193, 194, 194, 191, 181, 176, 180, 180, 178, 174, 167, 164, 165, 157, 142, 113, 78, 59, 55, 46, 35, 39, 76, 126, 140, 153, 154, 153, 94, 70, 141, 154, 156, 161, 158, 157, 160, 163, 165, 173, 174, 175, 175, 175, 175, 178, 178, 177, 177, 172, 178, 179, 181, 181, 182, 176, 175, 173, 166, 160, 157, 153, 151, 151, 151, 151, 151, 152, 153, 151, 151, 151, 151, 151, 151, 150, 151, 148, 145, 106, 40, 41, 42, 41, 38, 43, 45, 46, 46, 46, 45, 45, 47, 139, 176, 140, 136, 146, 146, 147, 146, 146, 146, 148, 151, 159, 168, 173, 171, 171, 171, 173, 176, 178, 178, 179, 179, 179, 179, 179, 176, 171, 160, 72, 36, 36, 37, 38, 37, 35, 36, 37, 39, 41, 44, 45, 48, 52, 54, 55, 56, 57, 59, 60, 68, 90, 148, 148, 148, 148, 148, 150, 149, 151, 161, 176, 172, 172, 172, 167, 169, 160, 156, 156, 158, 163, 163, 169, 167, 164, 164, 160, 150, 149, 150, 153, 152, 150, 153, 154, 156, 166, 106, 31, 31, 32, 31, 32, 33, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 34, 33, 33, 33, 33, 33, 33, 33, 31, 32, 31, 99, 149, 146, 212, 208, 209, 208, 206, 201, 201, 201, 198, 195, 196, 199, 202, 204, 204, 203, 201, 199, 196, 193, 193, 193, 193, 192, 189, 187, 185, 185, 183, 175, 168, 161, 154, 148, 139, 125, 115, 126, 150, 177, 198, 204, 186, 166, 158, 159, 168, 179, 184, 184, 185, 186, 189, 192, 195, 199, 204, 206, 206, 204, 201, 198, 195, 191, 184, 163, 133, 111, 114, 130, 148, 172, 185, 193, 194, 192, 189, 185, 178, 171, 171, 174, 174, 167, 160, 152, 137, 110, 80, 60, 56, 55, 48, 41, 45, 82, 133, 153, 155, 155, 155, 126, 69, 141, 158, 158, 161, 168, 164, 161, 161, 162, 165, 173, 174, 174, 175, 177, 177, 178, 178, 178, 179, 179, 180, 182, 186, 190, 187, 180, 178, 173, 169, 164, 161, 157, 153, 152, 152, 152, 152, 156, 159, 153, 151, 151, 151, 151, 151, 152, 153, 149, 148, 140, 78, 44, 41, 41, 41, 40, 45, 46, 46, 46, 45, 45, 68, 174, 156, 143, 145, 145, 146, 147, 150, 151, 154, 170, 199, 205, 209, 216, 202, 180, 177, 177, 178, 179, 179, 179, 179, 179, 179, 179, 141, 45, 39, 37, 36, 36, 38, 39, 38, 37, 36, 38, 39, 42, 44, 47, 49, 53, 54, 55, 56, 57, 59, 72, 124, 142, 147, 147, 148, 148, 151, 159, 160, 157, 164, 174, 176, 185, 180, 171, 169, 163, 156, 155, 161, 164, 168, 177, 166, 164, 164, 160, 153, 149, 150, 153, 155, 157, 154, 154, 160, 170, 74, 31, 31, 32, 32, 31, 33, 33, 34, 34, 33, 34, 34, 35, 34, 35, 35, 34, 34, 34, 33, 33, 33, 33, 33, 33, 33, 33, 31, 32, 31, 108, 149, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] diff --git a/ableos/assets/kernel.toml b/ableos/assets/kernel.toml deleted file mode 100644 index 1f0ad21..0000000 --- a/ableos/assets/kernel.toml +++ /dev/null @@ -1,17 +0,0 @@ -[boot] -system_processes = [] -user_processes = ["shell"] - -[logging] -enabled = true -level = "Trace" -log_to_serial = true -log_to_vterm = false -filter = ["ableos::ps2_mouse", "ableos::vterm", "ableos::filesystem::vfs"] - - -# Exact paths required -[tests] -run_tests = false -run_demos = false -run_shader_tests = false diff --git a/ableos/assets/key_event.txt b/ableos/assets/key_event.txt deleted file mode 100644 index 0617522..0000000 --- a/ableos/assets/key_event.txt +++ /dev/null @@ -1,17 +0,0 @@ -pub struct KeyEvent{ - lctrl 1 - rctrl 2 - lalt 3 - ralt 4 - lsup 5 - rsup 6 - lshift 7 - rshift 8 - caps 9 - - down 10 - # Keycodes - key 11-32 -} - - diff --git a/ableos/json_targets/.rustc_info.json b/ableos/json_targets/.rustc_info.json deleted file mode 100644 index 29caa8f..0000000 --- a/ableos/json_targets/.rustc_info.json +++ /dev/null @@ -1 +0,0 @@ -{"rustc_fingerprint":3542195962280373086,"outputs":{"17598535894874457435":{"success":true,"status":"","code":0,"stdout":"rustc 1.58.0-nightly (efd048394 2021-10-20)\nbinary: rustc\ncommit-hash: efd0483949496b067cd5f7569d1b28cd3d5d3c72\ncommit-date: 2021-10-20\nhost: x86_64-unknown-linux-gnu\nrelease: 1.58.0-nightly\nLLVM version: 13.0.0\n","stderr":""},"2797684049618456168":{"success":false,"status":"exit status: 1","code":1,"stdout":"","stderr":"error: `-Csplit-debuginfo` is unstable on this platform\n\n"},"15537503139010883884":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n","stderr":""},"931469667778813386":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/elfein/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_has_atomic_equal_alignment=\"16\"\ntarget_has_atomic_equal_alignment=\"32\"\ntarget_has_atomic_equal_alignment=\"64\"\ntarget_has_atomic_equal_alignment=\"8\"\ntarget_has_atomic_equal_alignment=\"ptr\"\ntarget_has_atomic_load_store=\"16\"\ntarget_has_atomic_load_store=\"32\"\ntarget_has_atomic_load_store=\"64\"\ntarget_has_atomic_load_store=\"8\"\ntarget_has_atomic_load_store=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_thread_local\ntarget_vendor=\"unknown\"\nunix\n","stderr":""}},"successes":{}} \ No newline at end of file diff --git a/ableos/json_targets/aarch32-ableos.json b/ableos/json_targets/aarch32-ableos.json deleted file mode 100644 index 0fe31e6..0000000 --- a/ableos/json_targets/aarch32-ableos.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "llvm-target": "arm-none-eabihf", - "target-endian": "little", - "target-pointer-width": "32", - "target-c-int-width": "32", - "os": "ableos", - "env": "eabi", - "vendor": "unknown", - "arch": "arm", - "linker-flavor": "gcc", - "linker": "arm-none-eabi-gcc", - "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", - "executables": true, - "relocation-model": "static" -} diff --git a/ableos/json_targets/aarch64-ableos.json b/ableos/json_targets/aarch64-ableos.json deleted file mode 100644 index 77631b3..0000000 --- a/ableos/json_targets/aarch64-ableos.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "arch": "aarch64", - "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", - "disable-redzone": true, - "env": "", - "executables": true, - "features": "+strict-align,+neon,+fp-armv8", - "is-builtin": false, - "linker": "rust-lld", - "linker-flavor": "ld.lld", - "linker-is-gnu": true, - "pre-link-args": { - "ld.lld": ["-Tsrc/arch/aarch64/aarch64-qemu.ld"] - }, - "llvm-target": "aarch64-unknown-none", - "max-atomic-width": 128, - "os": "none", - "panic-strategy": "abort", - "relocation-model": "static", - "target-c-int-width": "32", - "target-endian": "little", - "target-pointer-width": "64", - "vendor": "" -} diff --git a/ableos/json_targets/arm-ableos.json b/ableos/json_targets/arm-ableos.json deleted file mode 100644 index 0fe31e6..0000000 --- a/ableos/json_targets/arm-ableos.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "llvm-target": "arm-none-eabihf", - "target-endian": "little", - "target-pointer-width": "32", - "target-c-int-width": "32", - "os": "ableos", - "env": "eabi", - "vendor": "unknown", - "arch": "arm", - "linker-flavor": "gcc", - "linker": "arm-none-eabi-gcc", - "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", - "executables": true, - "relocation-model": "static" -} diff --git a/ableos/keymaps/empty.keymap b/ableos/keymaps/empty.keymap deleted file mode 100644 index 996078b..0000000 --- a/ableos/keymaps/empty.keymap +++ /dev/null @@ -1,256 +0,0 @@ -0- -1- -2- -3- -4- -5- -6- -7- -8- -9- -10- -11- -12- -13- -14- -15- -16- -17- -18- -19- -20- -21- -22- -23- -24- -25- -26- -27- -28- -29- -30- -31- -32- -33- -34- -35- -36- -37- -38- -39- -40- -41- -42- -43- -44- -45- -46- -47- -48- -49- -50- -51- -52- -53- -54- -55- -56- -57- -58- -59- -60- -61- -62- -63- -64- -65- -66- -67- -68- -69- -70- -71- -72- -73- -74- -75- -76- -77- -78- -79- -80- -81- -82- -83- -84- -85- -86- -87- -88- -89- -90- -91- -92- -93- -94- -95- -96- -97- -98- -99- -100- -101- -102- -103- -104- -105- -106- -107- -108- -109- -110- -111- -112- -113- -114- -115- -116- -117- -118- -119- -120- -121- -122- -123- -124- -125- -126- -127- -128- -129- -130- -131- -132- -133- -134- -135- -136- -137- -138- -139- -140- -141- -142- -143- -144- -145- -146- -147- -148- -149- -150- -151- -152- -153- -154- -155- -156- -157- -158- -159- -160- -161- -162- -163- -164- -165- -166- -167- -168- -169- -170- -171- -172- -173- -174- -175- -176- -177- -178- -179- -180- -181- -182- -183- -184- -185- -186- -187- -188- -189- -190- -191- -192- -193- -194- -195- -196- -197- -198- -199- -200- -201- -202- -203- -204- -205- -206- -207- -208- -209- -210- -211- -212- -213- -214- -215- -216- -217- -218- -219- -220- -221- -222- -223- -224- -225- -226- -227- -228- -229- -230- -231- -232- -233- -234- -235- -236- -237- -238- -239- -240- -241- -242- -243- -244- -245- -246- -247- -248- -249- -250- -251- -252- -253- -254- -255- diff --git a/ableos/keymaps/qwerty.keymap b/ableos/keymaps/qwerty.keymap deleted file mode 100644 index 95db614..0000000 --- a/ableos/keymaps/qwerty.keymap +++ /dev/null @@ -1,252 +0,0 @@ -# Able doesn't have a full keyboard -0-NONE -1- -2- -3-BACKSPACE -4- -5- -6- -7- -8- -9-TAB -10- -11- -12- -13-ENTER -14- -15- -16-SHIFT -17-CONTROL -18-ALT -19-PAUSE -20-CAPS_LOCK -21- -22- -23- -24- -25- -26- -27- -28- -29- -30- -31- -32-SPACE -33-PAGE_UP -34-PAGE_DOWN -35-END -36-HOME -37-ARROW_LEFT -38-ARROW_UP -39-ARROW_RIGHT -40-ARROW_DOWN -41- -42- -43- -44- -45-INSERT -46-DELETE -47- -48-0 -49-1 -50-2 -51-3 -52-4 -53-5 -54-6 -55-7 -56-8 -57-9 -58- -59-SEMICOLON -60- -61-EQUAL -62- -63- -64- -65-a -66-b -67-c -68-d -69-e -70-f -71-g -72-h -73-i -74-j -75-k -76-l -77-m -78-n -79-o -80-p -81-q -82-r -83-s -84-t -85-u -86-v -87-w -88-x -89-y -90-z -91- -92- -93- -94- -95- -96- -97- -98- -99- -100- -101- -102- -103- -106- -107- -108- -109- -110- -111- -112-FUNCTION_1 -113-FUNCTION_2 -114-FUNCTION_3 -115-FUNCTION_4 -116-FUNCTION_5 -117-FUNCTION_6 -118-FUNCTION_7 -119-FUNCTION_8 -120-FUNCTION_9 -121-FUNCTION_10 -122-FUNCTION_11 -123-FUNCTION_12 -124- -125- -126- -127- -128- -129- -130- -131- -132- -134- -135- -136- -137- -138- -139- -140- -141- -142- -143- -145-SCROLL_LOCK -146- -147- -148- -149- -150- -151- -152- -153- -154- -155- -156- -157- -158- -159- -160- -161- -162- -163- -164- -165- -166- -167- -168- -169- -170- -171- -172- -173-MINUS -174- -175- -176- -177- -178- -179- -180- -181- -182- -183- -184- -185- -186- -187- -188-COMMA -189- -190-PERIOD -191-FORWARD_SLASH -192-GRAVE -193- -194- -195- -196- -197- -198- -199- -200- -201- -202- -203- -204- -205- -206- -207- -208- -209- -210- -211- -212- -213- -214- -215- -216- -218- -219-BRACKET_LEFT -220-BACK_SLASH -221-BRACKET_RIGHT -222-QUOTE -223- -224- -225- -226- -227- -228- -229- -230- -231- -232- -233- -234- -235- -236- -237- -238- -239- -240- -241- -242- -243- -244- -245- -246- -247- -248- -249- -250- -251- -252- -253- -254- -255- diff --git a/ableos/rust-toolchain b/ableos/rust-toolchain deleted file mode 100644 index bf867e0..0000000 --- a/ableos/rust-toolchain +++ /dev/null @@ -1 +0,0 @@ -nightly diff --git a/ableos/src/allocator/aalloc.rs b/ableos/src/allocator/aalloc.rs deleted file mode 100644 index fcf0f3f..0000000 --- a/ableos/src/allocator/aalloc.rs +++ /dev/null @@ -1,73 +0,0 @@ -//! The allocator to be implemented by ableOS -//! -//! NOTE: All memory regions are taken from https://wiki.osdev.org/Memory_Map_(x86) - -use alloc::alloc::{GlobalAlloc, Layout}; -use core::{fmt::Display, ptr::null_mut}; - -const HEAP_START: usize = 600_000_000; -const BLOCK_SIZE: usize = 1024; -const BLOCK_COUNT: usize = 512; -#[derive(Debug, Clone, Copy)] -pub struct MemoryRegion { - _start: usize, - _end: usize, -} -#[derive(Debug, Clone, Copy)] -pub struct AAlloc { - current_region: usize, - memory_regions: [Option<MemoryRegion>; 512], -} - -impl AAlloc { - pub fn add_region(&mut self, mem: MemoryRegion) { - self.memory_regions[self.current_region] = Some(mem); - self.current_region += 1; - } - - pub fn intialize() { - info!("Heap Start: {}", HEAP_START); - info!("Heap Size: {}", BLOCK_SIZE * BLOCK_COUNT); - info!("Heap End: {}", HEAP_START + BLOCK_SIZE * BLOCK_COUNT); - - let mut aalloc = AAlloc { - current_region: 0, - memory_regions: [None; 512], - }; - - aalloc.add_region(MemoryRegion { - _start: 0x00100000, - _end: 0x00EFFFFF, - }); - debug!("{}", aalloc); - } -} - -impl Display for AAlloc { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - write!(f, "AAlloc {{\n\tcurrent_region: {},\n", self.current_region)?; - - for x in 0..self.current_region { - if let Some(region) = self.memory_regions[x] { - write!(f, "\tRegion {}: {:?}\n", x, region)?; - } - } - write!(f, "}}")?; - Ok(()) - } -} - -unsafe impl GlobalAlloc for AAlloc { - unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { - println!("Allocating memory"); - - println!("{}", _layout.size()); - println!("{}", _layout.align()); - - null_mut() - } - - unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) { - panic!("dealloc should be never called") - } -} diff --git a/ableos/src/allocator/mod.rs b/ableos/src/allocator/mod.rs deleted file mode 100644 index 9f809fa..0000000 --- a/ableos/src/allocator/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -pub mod aalloc; -pub use aalloc::*; - -pub const HEAP_START: usize = 0x_4444_4444_0000; -pub const HEAP_MULTIPLIER: usize = 100000; -pub const HEAP_BASE: usize = 100; -pub const HEAP_SIZE: usize = HEAP_BASE * HEAP_MULTIPLIER; - -/* -#[global_allocator] -pub static ALLOCATOR: LockedHeap = LockedHeap::empty(); - -#[alloc_error_handler] -fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! { - panic!("allocation error: {:?}", layout) -} - - -*/ diff --git a/ableos/src/arch/aarch64/aarch64-qemu.ld b/ableos/src/arch/aarch64/aarch64-qemu.ld deleted file mode 100644 index 66ca0ce..0000000 --- a/ableos/src/arch/aarch64/aarch64-qemu.ld +++ /dev/null @@ -1,14 +0,0 @@ -ENTRY(_start) -SECTIONS -{ - . = 0x40000000; - .text.boot : { *(.text.boot) } - .text : { *(.text) } - .data : { *(.data) } - .rodata : { *(.rodata) } - .bss : { *(.bss) } - - . = ALIGN(8); - . = . + 0x4000; - LD_STACK_PTR = .; -} diff --git a/ableos/src/arch/aarch64/boot.s b/ableos/src/arch/aarch64/boot.s deleted file mode 100644 index 40680ed..0000000 --- a/ableos/src/arch/aarch64/boot.s +++ /dev/null @@ -1,15 +0,0 @@ -.globl _start -.extern LD_STACK_PTR - -.section ".text.boot" - -_start: - ldr x30, =LD_STACK_PTR - mov sp, x30 - bl not_main - -.equ PSCI_SYSTEM_OFF, 0x84000008 -.globl system_off -system_off: - ldr x0, =PSCI_SYSTEM_OFF - hvc #0 diff --git a/ableos/src/arch/aarch64/drivers/allocator.rs b/ableos/src/arch/aarch64/drivers/allocator.rs deleted file mode 100644 index cf68c09..0000000 --- a/ableos/src/arch/aarch64/drivers/allocator.rs +++ /dev/null @@ -1,13 +0,0 @@ -use alloc::alloc::{GlobalAlloc, Layout}; -use core::ptr::null_mut; - -pub struct Dummy; -unsafe impl GlobalAlloc for Dummy { - unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { - null_mut() - } - - unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) { - panic!("dealloc should be never called") - } -} diff --git a/ableos/src/arch/aarch64/drivers/graphics.rs b/ableos/src/arch/aarch64/drivers/graphics.rs deleted file mode 100644 index fddd6e2..0000000 --- a/ableos/src/arch/aarch64/drivers/graphics.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::driver_traits::graphics::{Graphics, Point, Rgb}; - -pub struct GraphicsBuffer; - -#[allow(unused)] -impl Graphics for GraphicsBuffer { - fn put_line(coords_start: Point, coords_end: Point, thickness: u32, color: Rgb) { - todo!() - } - - fn put_rect(coords_start: Point, coords_end: Point, color: Rgb) { - todo!() - } - - fn put_circle(coords: Point, radius: u32) { - todo!() - } - - fn put_triangle(coords_1: Point, coords_2: Point, coords_3: Point, thickness: u32, color: Rgb) { - todo!(); - } - - fn put_pixel(coords: Point, color: Rgb) { - todo!() - } - - fn paint_cursor(coords: Point) { - todo!() - } - - fn hide_cursor() {} - fn show_cursor() {} - fn draw() {} - fn clear() { - todo!() - } -} diff --git a/ableos/src/arch/aarch64/drivers/mod.rs b/ableos/src/arch/aarch64/drivers/mod.rs deleted file mode 100644 index e2e6ab6..0000000 --- a/ableos/src/arch/aarch64/drivers/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod allocator; -pub mod graphics; -pub mod nrf52; -pub mod serial; diff --git a/ableos/src/arch/aarch64/drivers/nrf52.rs b/ableos/src/arch/aarch64/drivers/nrf52.rs deleted file mode 100644 index 9675faf..0000000 --- a/ableos/src/arch/aarch64/drivers/nrf52.rs +++ /dev/null @@ -1,70 +0,0 @@ -//! A not-very-useful abstraction of GPIOs in Rust -#![allow(dead_code)] - -use core::sync::atomic::{AtomicBool, Ordering::SeqCst}; - -const REG_P0_PIN_CNF_BASE: *mut u32 = 0x5000_0700 as *mut u32; -const REG_P0_OUT_SET: *mut u32 = 0x5000_0508 as *mut u32; -const REG_P0_OUT_CLR: *mut u32 = 0x5000_050C as *mut u32; - -const PIN_CNF_DIR_OUTPUT: u32 = 0x0000_0001; -const PIN_CNF_INPUT_CONNECT: u32 = 0x0000_0000; -const PIN_CNF_PULL_DISABLED: u32 = 0x0000_0000; -const PIN_CNF_DRIVE_S0S1: u32 = 0x0000_0000; -const PIN_CNF_SENSE_DISABLED: u32 = 0x0000_0000; -/// A struct that represents an nRF52 Pin -pub struct Pin(u8); -impl Pin { - /// Set a pin to be a push pull output - pub fn set_push_pull_output(&mut self, level: Level) { - // set level - match level { - Level::High => self.set_high(), - Level::Low => self.set_low(), - } - - let set_val = PIN_CNF_DIR_OUTPUT - | PIN_CNF_INPUT_CONNECT - | PIN_CNF_PULL_DISABLED - | PIN_CNF_DRIVE_S0S1 - | PIN_CNF_SENSE_DISABLED; - - unsafe { - core::ptr::write_volatile(REG_P0_PIN_CNF_BASE.offset(self.0 as isize), set_val); - } - } - - /// Set a pin to output level low - pub fn set_low(&mut self) { - unsafe { core::ptr::write_volatile(REG_P0_OUT_SET, 1 << (self.0 as u32)) } - } - - /// Set a pin to output level high - pub fn set_high(&mut self) { - unsafe { core::ptr::write_volatile(REG_P0_OUT_CLR, 1 << (self.0 as u32)) } - } -} - -/// The level of a GPIO -#[derive(Copy, Clone)] -pub enum Level { - Low, - High, -} - -/// A struct that represents P0 of the nRF52 -pub struct Pins { - pub p0_31: Pin, -} - -impl Pins { - /// A function to obtain a Port 0 singleton structure - pub fn take() -> Self { - static TAKEN: AtomicBool = AtomicBool::new(false); - - // Enforce this as a singleton - assert!(!TAKEN.swap(true, SeqCst)); - - Self { p0_31: Pin(31) } - } -} diff --git a/ableos/src/arch/aarch64/drivers/serial.rs b/ableos/src/arch/aarch64/drivers/serial.rs deleted file mode 100644 index 0b3aa25..0000000 --- a/ableos/src/arch/aarch64/drivers/serial.rs +++ /dev/null @@ -1,13 +0,0 @@ -/// Prints to the host through the serial interface. -#[macro_export] -macro_rules! serial_print { - ($($arg:tt)*) => {}; -} - -/// Prints to the host through the serial interface, appending a newline. -#[macro_export] -macro_rules! serial_println { - () => {}; - ($fmt:expr) => {}; - ($fmt:expr, $($arg:tt)*) => {}; -} diff --git a/ableos/src/arch/aarch64/init.rs b/ableos/src/arch/aarch64/init.rs deleted file mode 100644 index 12cd021..0000000 --- a/ableos/src/arch/aarch64/init.rs +++ /dev/null @@ -1 +0,0 @@ -pub fn init() {} diff --git a/ableos/src/arch/aarch64/mod.rs b/ableos/src/arch/aarch64/mod.rs deleted file mode 100644 index 04aeecb..0000000 --- a/ableos/src/arch/aarch64/mod.rs +++ /dev/null @@ -1,66 +0,0 @@ -pub mod drivers; -pub mod init; - -use crate::arch::drivers::nrf52::{Level, Pins}; -use core::ptr; -use core::ptr::write_volatile; - -global_asm!(include_str!("boot.s")); - -fn delay(ticks: usize) { - static mut DUMMY: usize = 0; - - // Reduce the number of iterations when in debug mode - #[cfg(debug_assertions)] - let ticks = ticks / 128; - - for t in 0..ticks { - // Prevent the optimizer from removing this loop - unsafe { - write_volatile(&mut DUMMY, t); - } - } -} -use crate::print; - -#[no_mangle] -pub extern "C" fn not_main() { - const UART0: *mut u8 = 0x0900_0000 as *mut u8; - for byte in b"ableOS Arm 64" { - unsafe { - ptr::write_volatile(UART0, *byte); - } - } - - // let gpios = Pins::take(); - // let mut led = gpios.p0_31; - // - // loop { - // led.set_high(); - // delay(2_000_000); - // - // led.set_low(); - // delay(6_000_000); - // } - // - // led.set_push_pull_output(Level::Low); - - crate::kmain::kernel_main(); - sloop(); -} - -pub fn sloop() -> ! { - loop {} -} - -pub fn print() { - for byte in b"ableOS Arm 64" { - const UART0: *mut u8 = 0x0900_0000 as *mut u8; - - unsafe { - ptr::write_volatile(UART0, *byte); - } - } -} - -pub fn shutdown() {} diff --git a/ableos/src/arch/aarch64/run.sh b/ableos/src/arch/aarch64/run.sh deleted file mode 100644 index 494f5b8..0000000 --- a/ableos/src/arch/aarch64/run.sh +++ /dev/null @@ -1,4 +0,0 @@ -cargo build --target=json_targets/aarch64-ableos.json --release &&\ -qemu-system-aarch64 -machine virt -m 1024M -cpu cortex-a53 \ --kernel target/aarch64-ableos/release/ableos -serial stdio \ --device virtio-keyboard diff --git a/ableos/src/arch/riscv/drivers/allocator.rs b/ableos/src/arch/riscv/drivers/allocator.rs deleted file mode 100644 index cf68c09..0000000 --- a/ableos/src/arch/riscv/drivers/allocator.rs +++ /dev/null @@ -1,13 +0,0 @@ -use alloc::alloc::{GlobalAlloc, Layout}; -use core::ptr::null_mut; - -pub struct Dummy; -unsafe impl GlobalAlloc for Dummy { - unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { - null_mut() - } - - unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) { - panic!("dealloc should be never called") - } -} diff --git a/ableos/src/arch/riscv/drivers/graphics.rs b/ableos/src/arch/riscv/drivers/graphics.rs deleted file mode 100644 index fddd6e2..0000000 --- a/ableos/src/arch/riscv/drivers/graphics.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::driver_traits::graphics::{Graphics, Point, Rgb}; - -pub struct GraphicsBuffer; - -#[allow(unused)] -impl Graphics for GraphicsBuffer { - fn put_line(coords_start: Point, coords_end: Point, thickness: u32, color: Rgb) { - todo!() - } - - fn put_rect(coords_start: Point, coords_end: Point, color: Rgb) { - todo!() - } - - fn put_circle(coords: Point, radius: u32) { - todo!() - } - - fn put_triangle(coords_1: Point, coords_2: Point, coords_3: Point, thickness: u32, color: Rgb) { - todo!(); - } - - fn put_pixel(coords: Point, color: Rgb) { - todo!() - } - - fn paint_cursor(coords: Point) { - todo!() - } - - fn hide_cursor() {} - fn show_cursor() {} - fn draw() {} - fn clear() { - todo!() - } -} diff --git a/ableos/src/arch/riscv/drivers/mmio.rs b/ableos/src/arch/riscv/drivers/mmio.rs deleted file mode 100644 index a25e766..0000000 --- a/ableos/src/arch/riscv/drivers/mmio.rs +++ /dev/null @@ -1,35 +0,0 @@ -/// # Safety -/// -/// We label the mmio function unsafe since -/// we will be working with raw memory. Rust cannot -/// make any guarantees when we do this. -#[inline(always)] -fn mmio_write(address: usize, offset: usize, value: u8) { - // Set the pointer based off of the address - let reg = address as *mut u8; - - // write_volatile is a member of the *mut raw - // and we can use the .add() to give us another pointer - // at an offset based on the original pointer's memory - // address. NOTE: The add uses pointer arithmetic so it is - // new_pointer = old_pointer + sizeof(pointer_type) * offset - unsafe { - reg.add(offset).write_volatile(value); - } -} - -/// # Safety -/// -/// We label the mmio function unsafe since -/// we will be working with raw memory. Rust cannot -/// make any guarantees when we do this. -fn mmio_read(address: usize, offset: usize, value: u8) -> u8 { - // Set the pointer based off of the address - let reg = address as *mut u8; - - // read_volatile() is much like write_volatile() except it - // will grab 8-bits from the pointer and give that value to us. - // We don't add a semi-colon at the end here so that the value - // is "returned". - unsafe { reg.add(offset).read_volatile() } -} diff --git a/ableos/src/arch/riscv/drivers/mod.rs b/ableos/src/arch/riscv/drivers/mod.rs deleted file mode 100644 index 082f960..0000000 --- a/ableos/src/arch/riscv/drivers/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod allocator; -pub mod graphics; -pub mod mmio; -pub mod sysinfo; -pub mod uart; diff --git a/ableos/src/arch/riscv/drivers/sysinfo.rs b/ableos/src/arch/riscv/drivers/sysinfo.rs deleted file mode 100644 index 56ff155..0000000 --- a/ableos/src/arch/riscv/drivers/sysinfo.rs +++ /dev/null @@ -1,23 +0,0 @@ -pub fn sysinfo() {} -pub fn master() -> Option<Master> { - Some(Master { - brand_string: Some("riscv".to_string()), - }) -} - -pub struct Master { - // TODO: Rename struct - // version_information: Option<VersionInformation>, - // thermal_power_management_information: Option<ThermalPowerManagementInformation>, - // structured_extended_information: Option<StructuredExtendedInformation>, - // extended_processor_signature: Option<ExtendedProcessorSignature>, - pub brand_string: Option<String>, - // cache_line: Option<CacheLine>, - // time_stamp_counter: Option<TimeStampCounter>, - // physical_address_size: Option<PhysicalAddressSize>, -} -impl Master { - pub fn brand_string(&self) -> Option<&str> { - self.brand_string.as_deref() - } -} diff --git a/ableos/src/arch/riscv/drivers/uart.rs b/ableos/src/arch/riscv/drivers/uart.rs deleted file mode 100644 index 6751aa8..0000000 --- a/ableos/src/arch/riscv/drivers/uart.rs +++ /dev/null @@ -1,129 +0,0 @@ -use core::fmt::{Error, Write}; - -/// Initialize the UART driver by setting -/// the word length, FIFOs, and interrupts -pub fn uart_init(base_addr: usize) { - let ptr = base_addr as *mut u8; - unsafe { - // First, set the word length, which - // are bits 0, and 1 of the line control register (LCR) - // which is at base_address + 3 - // We can easily write the value 3 here or 0b11, but I'm - // extending it so that it is clear we're setting two individual - // fields - // Word 0 Word 1 - // ~~~~~~ ~~~~~~ - let lcr = (1 << 0) | (1 << 1); - ptr.add(3).write_volatile(lcr); - - // Now, enable the FIFO, which is bit index 0 of the FIFO - // control register (FCR at offset 2). - // Again, we can just write 1 here, but when we use left shift, - // it's easier to see that we're trying to write bit index #0. - ptr.add(2).write_volatile(1 << 0); - - // Enable receiver buffer interrupts, which is at bit index - // 0 of the interrupt enable register (IER at offset 1). - ptr.add(1).write_volatile(1 << 0); - - // If we cared about the divisor, the code below would set the divisor - // from a global clock rate of 22.729 MHz (22,729,000 cycles per second) - // to a signaling rate of 2400 (BAUD). We usually have much faster signalling - // rates nowadays, but this demonstrates what the divisor actually does. - // The formula given in the NS16500A specification for calculating the divisor - // is: - // divisor = ceil( (clock_hz) / (baud_sps x 16) ) - // So, we substitute our values and get: - // divisor = ceil( 22_729_000 / (2400 x 16) ) - // divisor = ceil( 22_729_000 / 38_400 ) - // divisor = ceil( 591.901 ) = 592 - - // The divisor register is two bytes (16 bits), so we need to split the value - // 592 into two bytes. Typically, we would calculate this based on measuring - // the clock rate, but again, for our purposes [qemu], this doesn't really do - // anything. - let divisor: u16 = 592; - let divisor_least: u8 = (divisor & 0xff).try_into().unwrap(); - let divisor_most: u8 = (divisor >> 8).try_into().unwrap(); - - // Notice that the divisor register DLL (divisor latch least) and DLM (divisor - // latch most) have the same base address as the receiver/transmitter and the - // interrupt enable register. To change what the base address points to, we - // open the "divisor latch" by writing 1 into the Divisor Latch Access Bit - // (DLAB), which is bit index 7 of the Line Control Register (LCR) which - // is at base_address + 3. - ptr.add(3).write_volatile(lcr | 1 << 7); - - // Now, base addresses 0 and 1 point to DLL and DLM, respectively. - // Put the lower 8 bits of the divisor into DLL - ptr.add(0).write_volatile(divisor_least); - ptr.add(1).write_volatile(divisor_most); - - // Now that we've written the divisor, we never have to touch this again. In - // hardware, this will divide the global clock (22.729 MHz) into one suitable - // for 2,400 signals per second. So, to once again get access to the - // RBR/THR/IER registers, we need to close the DLAB bit by clearing it to 0. - ptr.add(3).write_volatile(lcr); - } -} - -fn uart_get(base_addr: usize) -> Option<u8> { - let ptr = base_addr as *mut u8; - unsafe { - // Bit index #5 is the Line Control Register. - if ptr.add(5).read_volatile() & 1 == 0 { - // The DR bit is 0, meaning no data - None - } else { - // The DR bit is 1, meaning data! - Some(ptr.add(0).read_volatile()) - } - } -} - -fn uart_put(base_addr: usize, c: u8) { - let ptr = base_addr as *mut u8; - unsafe { - // If we get here, the transmitter is empty, so transmit - // our stuff! - ptr.add(0).write_volatile(c); - } -} - -pub struct Uart { - base_address: usize, -} - -impl Uart { - pub fn new(base_address: usize) -> Self { - Uart { base_address } - } - - pub fn get(&self) -> Option<u8> { - uart_get(self.base_address) - } - - pub fn put(&self, c: u8) { - uart_put(self.base_address, c); - } - - pub fn init(&self) { - uart_init(self.base_address); - } -} - -// This is a slightly different syntax. Write is this "trait", meaning it is much like -// an interface where we're just guaranteeing a certain function signature. In the Write -// trait, one is absolutely required to be implemented, which is write_str. There are other -// functions, but they all rely on write_str(), so their default implementation is OK for now. -impl Write for Uart { - // The trait Write expects us to write the function write_str - // which looks like: - fn write_str(&mut self, s: &str) -> Result<(), Error> { - for c in s.bytes() { - self.put(c); - } - // Return that we succeeded. - Ok(()) - } -} diff --git a/ableos/src/arch/riscv/firmwear/opensbi-riscv64-generic-fw_jump.bin b/ableos/src/arch/riscv/firmwear/opensbi-riscv64-generic-fw_jump.bin deleted file mode 100755 index 099967f..0000000 Binary files a/ableos/src/arch/riscv/firmwear/opensbi-riscv64-generic-fw_jump.bin and /dev/null differ diff --git a/ableos/src/arch/riscv/init.rs b/ableos/src/arch/riscv/init.rs deleted file mode 100644 index 12cd021..0000000 --- a/ableos/src/arch/riscv/init.rs +++ /dev/null @@ -1 +0,0 @@ -pub fn init() {} diff --git a/ableos/src/arch/riscv/mod.rs b/ableos/src/arch/riscv/mod.rs deleted file mode 100644 index a201dd2..0000000 --- a/ableos/src/arch/riscv/mod.rs +++ /dev/null @@ -1,99 +0,0 @@ -pub mod drivers; -pub mod init; - -use crate::print; -use crate::println; -use core::arch::asm; - -#[naked] -#[no_mangle] -unsafe extern "C" fn _boot() -> ! { - #[rustfmt::skip] - asm!(" - csrw sie, zero - csrci sstatus, 2 - - .option push - .option norelax - lla gp, __global_pointer$ - .option pop - - lla sp, __tmp_stack_top - - lla t0, __bss_start - lla t1, __bss_end - - 1: - beq t0, t1, 2f - sd zero, (t0) - addi t0, t0, 8 - j 1b - - 2: - j {} - ", - sym _start, options(noreturn)); -} - -extern "C" fn _start() -> ! { - use crate::serial_println; - - let uart = crate::arch::drivers::uart::Uart::new(0x1000_0000); - uart.init(); - log!("Hello, world!\r"); - - loop { - if let Some(c) = uart.get() { - match c { - 66 => break, - 10 | 13 => { - uart.put('\n' as u8); - uart.put('\r' as u8); - } - - /* - 91 => { - if let Some(ch) = uart.get() { - match ch as char { - 'A' => { - serial_println!("That's the up arrow!"); - } - 'B' => { - serial_println!("That's the down arrow!"); - } - 'C' => { - serial_println!("That's the right arrow!"); - } - 'D' => { - serial_println!("That's the left arrow!"); - } - _ => { - serial_println!("That's something else!"); - } - } - } - } - */ - _ => { - uart.put(c); - } - } - } - } - - serial_println!("Serial connection closed.\r"); - sloop() -} - -pub fn sloop() -> ! { - loop { - unsafe { - asm!("wfi"); - }; - } -} - -pub fn shutdown() {} -pub fn generate_process_pass() -> u128 { - 123 -} diff --git a/ableos/src/arch/riscv/virt.lds b/ableos/src/arch/riscv/virt.lds deleted file mode 100644 index c471c85..0000000 --- a/ableos/src/arch/riscv/virt.lds +++ /dev/null @@ -1,64 +0,0 @@ -OUTPUT_ARCH(riscv64gc) - -ENTRY(_boot); - - -SECTIONS { - . = 0x80200000; - .text : { - PROVIDE(__text_start = .); - PROVIDE(KERNEL_START = .); - *(.init.boot) - *(.init.rust) - *(.text .text.*) - . = ALIGN(4K); - PROVIDE(__text_end = .); - } - - .data : { - PROVIDE(__data_start = .); - *(.data .data.* .rodata .rodata.*) - . = ALIGN(8); - PROVIDE(__tmp_stack_bottom = .); - . += 1024 * 1024 * 4; - PROVIDE(__tmp_stack_top = .); - . += 4096; - PROVIDE(__scratch_stack = .); - . = ALIGN(8); - } - - . = ALIGN(8); - - .sdata : { - PROVIDE(__global_pointer$ = .); - *(.sdata .sdata.*) - . = ALIGN(4K); - PROVIDE(__data_end = .); - } - - PROVIDE(__bss_start = .); - .sbss : { - *(.sbss .sbss.*); - } - - .bss : { - *(.bss .bss.*) - } - . = ALIGN(4K); - PROVIDE(__bss_end = .); - - .tdata : { - . = ALIGN(4K); - PROVIDE(__tdata_start = .); - - *(.tdata .tdata.*) - - . = ALIGN(4K); - PROVIDE(__tdata_end = .); - } - - . = ALIGN(2M); - PROVIDE(KERNEL_END = .); - - /DISCARD/ : { *(.eh_frame_hdr .eh_frame) } -} diff --git a/ableos/src/arch/x86_64/drivers/allocator.rs b/ableos/src/arch/x86_64/drivers/allocator.rs deleted file mode 100644 index 8db70e5..0000000 --- a/ableos/src/arch/x86_64/drivers/allocator.rs +++ /dev/null @@ -1,48 +0,0 @@ -use alloc::alloc::{GlobalAlloc, Layout}; -use core::ptr::null_mut; -use kernel::allocator::{HEAP_SIZE, HEAP_START}; -use x86_64::{ - structures::paging::{ - mapper::MapToError, FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB, - }, - VirtAddr, -}; -pub struct Dummy; -unsafe impl GlobalAlloc for Dummy { - unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { - null_mut() - } - - unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) { - panic!("dealloc should be never called") - } -} - -pub fn init_heap( - mapper: &mut impl Mapper<Size4KiB>, - frame_allocator: &mut impl FrameAllocator<Size4KiB>, -) -> Result<(), MapToError<Size4KiB>> { - let page_range = { - let heap_start = VirtAddr::new(HEAP_START as u64); - let heap_end = heap_start + HEAP_SIZE - 1u64; - let heap_start_page = Page::containing_address(heap_start); - let heap_end_page = Page::containing_address(heap_end); - Page::range_inclusive(heap_start_page, heap_end_page) - }; - - for page in page_range { - let frame = frame_allocator - .allocate_frame() - .ok_or(MapToError::FrameAllocationFailed)?; - let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE; - unsafe { mapper.map_to(page, frame, flags, frame_allocator)?.flush() }; - } - - unsafe { - kernel::allocator::ALLOCATOR - .lock() - .init(HEAP_START, HEAP_SIZE); - } - - Ok(()) -} diff --git a/ableos/src/arch/x86_64/drivers/graphics.rs b/ableos/src/arch/x86_64/drivers/graphics.rs deleted file mode 100644 index 5933ed6..0000000 --- a/ableos/src/arch/x86_64/drivers/graphics.rs +++ /dev/null @@ -1,42 +0,0 @@ -use crate::driver_traits::graphics::{Graphics, Point, Rgb}; -use cpuio::outw; - -pub struct GraphicsBuffer; - -#[allow(unused)] -impl Graphics for GraphicsBuffer { - fn put_line(coords_start: Point, coords_end: Point, thickness: u32, color: Rgb) { - todo!() - } - - fn put_rect(coords_start: Point, coords_end: Point, color: Rgb) {} - - fn put_circle(coords: Point, radius: u32) { - todo!() - } - - fn put_triangle(coords_1: Point, coords_2: Point, coords_3: Point, thickness: u32, color: Rgb) { - todo!(); - } - - fn put_pixel(coords: Point, color: Rgb) { - todo!() - } - - fn paint_cursor(coords: Point) { - todo!() - } - - fn hide_cursor() { - unsafe { - outw(0x0A, 0x3D4); - outw(0x20, 0x3D5); - } - } - - fn show_cursor() {} - fn draw() {} - fn clear() { - todo!() - } -} diff --git a/ableos/src/arch/x86_64/drivers/mod.rs b/ableos/src/arch/x86_64/drivers/mod.rs deleted file mode 100644 index a16b28d..0000000 --- a/ableos/src/arch/x86_64/drivers/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -pub mod allocator; -// pub mod graphics; -pub mod serial; -pub mod sysinfo; -pub mod timer; - -#[deprecated(note = "The use of hardware specific drivers for VGA is discouraged")] -pub mod vga; diff --git a/ableos/src/arch/x86_64/drivers/serial.rs b/ableos/src/arch/x86_64/drivers/serial.rs deleted file mode 100644 index 64eee68..0000000 --- a/ableos/src/arch/x86_64/drivers/serial.rs +++ /dev/null @@ -1,36 +0,0 @@ -use spin::{Lazy, Mutex}; -use uart_16550::SerialPort; - -pub static SERIAL1: Lazy<Mutex<SerialPort>> = Lazy::new(|| { - let mut serial_port = unsafe { SerialPort::new(0x3F8) }; - serial_port.init(); - Mutex::new(serial_port) -}); - -#[doc(hidden)] -pub fn _print(args: ::core::fmt::Arguments) { - use core::fmt::Write; - // /* - SERIAL1 - .lock() - .write_fmt(args) - .expect("Printing to serial failed"); - // */ -} - -/// Prints to the host through the serial interface. -#[macro_export] -macro_rules! sprint { - ($($arg:tt)*) => { - $crate::arch::drivers::serial::_print(format_args!($($arg)*)); - }; -} - -/// Prints to the host through the serial interface, appending a newline. -#[macro_export] -macro_rules! sprintln { - () => ($crate::sprint!("\n")); - ($fmt:expr) => ($crate::sprint!(concat!($fmt, "\n"))); - ($fmt:expr, $($arg:tt)*) => ($crate::sprint!( - concat!($fmt, "\n"), $($arg)*)); -} diff --git a/ableos/src/arch/x86_64/drivers/sysinfo.rs b/ableos/src/arch/x86_64/drivers/sysinfo.rs deleted file mode 100644 index f7fef88..0000000 --- a/ableos/src/arch/x86_64/drivers/sysinfo.rs +++ /dev/null @@ -1,954 +0,0 @@ -//! ``` -//! extern crate cupid; -//! -//! fn main() { -//! let information = cupid::master(); -//! println!("{:#?}", information); -//! if let Some(information) = information { -//! if information.sse4_2() { -//! println!("SSE 4.2 Available"); -//! } -//! } -//! } -//! ``` - -#![cfg_attr( - not(any(target_arch = "x86_64", target_arch = "x86")), - allow(dead_code) -)] - -use core::arch::asm; -use core::ops::Deref; -use core::{fmt, slice, str}; - -// 3 calls of 4 registers of 4 bytes -const BRAND_STRING_LENGTH: usize = 3 * 4 * 4; - -macro_rules! bit { - ($reg:ident, {$($idx:expr => $name:ident),+ $(,)?}) => { - $(pub fn $name(self) -> bool { - ((self.$reg >> $idx) & 1) != 0 - })+ - } -} - -macro_rules! dump { - ($me:expr, $f: expr, $sname:expr, {$($name:ident),+ $(,)?}) => { - $f.debug_struct($sname) - $(.field(stringify!($name), &$me.$name()))+ - .finish() - } -} - -macro_rules! delegate_flag { - ($item:ident, {$($name:ident),+ $(,)?}) => { - $(pub fn $name(&self) -> bool { - self.$item.map(|i| i.$name()).unwrap_or(false) - })+ - } -} - -macro_rules! master_attr_reader { - ($name:ident, $kind:ty) => { - pub fn $name(&self) -> Option<&$kind> { - self.$name.as_ref() - } - }; -} - -#[repr(u32)] -pub enum RequestType { - BasicInformation = 0x00000000, - VersionInformation = 0x00000001, - ThermalPowerManagementInformation = 0x00000006, - StructuredExtendedInformation = 0x00000007, - ExtendedFunctionInformation = 0x80000000, - ExtendedProcessorSignature = 0x80000001, - BrandString1 = 0x80000002, - BrandString2 = 0x80000003, - BrandString3 = 0x80000004, - // reserved = 0x80000005, - CacheLine = 0x80000006, - TimeStampCounter = 0x80000007, - PhysicalAddressSize = 0x80000008, -} - -#[derive(Copy, Clone)] -pub struct VersionInformation { - eax: u32, - ebx: u32, - ecx: u32, - edx: u32, -} - -impl VersionInformation { - pub fn new() -> VersionInformation { - let (a, b, c, d) = cpuid(RequestType::VersionInformation); - VersionInformation { - eax: a, - ebx: b, - ecx: c, - edx: d, - } - } - - pub fn family_id(self) -> u32 { - let family_id = bits_of(self.eax, 8, 11); - let extended_family_id = bits_of(self.eax, 20, 27); - - if family_id != 0x0F { - family_id - } else { - extended_family_id + family_id - } - } - - pub fn model_id(self) -> u32 { - let family_id = self.family_id(); - let model_id = bits_of(self.eax, 4, 7); - let extended_model_id = bits_of(self.eax, 16, 19); - - if family_id == 0x06 || family_id == 0x0F { - (extended_model_id << 4) + model_id - } else { - model_id - } - } - - pub fn stepping(self) -> u32 { - bits_of(self.eax, 0, 3) - } - - fn processor_signature(self) -> u32 { - self.eax - } - - pub fn brand_string(self) -> Option<&'static str> { - let brand_index = bits_of(self.ebx, 0, 7); - let processor_signature = self.processor_signature(); - - match brand_index { - 0x00 => None, - 0x01 => Some("Intel(R) Celeron(R)"), - 0x02 => Some("Intel(R) Pentium(R) III"), - 0x03 => { - if processor_signature == 0x06B1 { - Some("Intel(R) Celeron(R)") - } else { - Some("Intel(R) Pentium(R) III Xeon(R)") - } - } - 0x04 => Some("Intel(R) Pentium(R) III"), - 0x06 => Some("Mobile Intel(R) Pentium(R) III-M"), - 0x07 => Some("Mobile Intel(R) Celeron(R)"), - 0x08 => Some("Intel(R) Pentium(R) 4"), - 0x09 => Some("Intel(R) Pentium(R) 4"), - 0x0A => Some("Intel(R) Celeron(R)"), - 0x0B => { - if processor_signature == 0x0F13 { - Some("Intel(R) Xeon(R) MP") - } else { - Some("Intel(R) Xeon(R)") - } - } - 0x0C => Some("Intel(R) Xeon(R) MP"), - 0x0E => { - if processor_signature == 0x0F13 { - Some("Intel(R) Xeon(R)") - } else { - Some("Mobile Intel(R) Pentium(R) 4-M") - } - } - 0x0F => Some("Mobile Intel(R) Celeron(R)"), - 0x11 => Some("Mobile Genuine Intel(R)"), - 0x12 => Some("Intel(R) Celeron(R) M"), - 0x13 => Some("Mobile Intel(R) Celeron(R)"), - 0x14 => Some("Intel(R) Celeron(R)"), - 0x15 => Some("Mobile Genuine Intel(R)"), - 0x16 => Some("Intel(R) Pentium(R) M"), - 0x17 => Some("Mobile Intel(R) Celeron(R)"), - _ => None, - } - } - - bit!(ecx, { - 0 => sse3, - 1 => pclmulqdq, - 2 => dtes64, - 3 => monitor, - 4 => ds_cpl, - 5 => vmx, - 6 => smx, - 7 => eist, - 8 => tm2, - 9 => ssse3, - 10 => cnxt_id, - 11 => sdbg, - 12 => fma, - 13 => cmpxchg16b, - 14 => xtpr_update_control, - 15 => pdcm, - // 16 - reserved - 17 => pcid, - 18 => dca, - 19 => sse4_1, - 20 => sse4_2, - 21 => x2apic, - 22 => movbe, - 23 => popcnt, - 24 => tsc_deadline, - 25 => aesni, - 26 => xsave, - 27 => osxsave, - 28 => avx, - 29 => f16c, - 30 => rdrand, - // 31 - unused, - }); - - bit!(edx, { - 0 => fpu, - 1 => vme, - 2 => de, - 3 => pse, - 4 => tsc, - 5 => msr, - 6 => pae, - 7 => mce, - 8 => cx8, - 9 => apic, - // 10 - reserved - 11 => sep, - 12 => mtrr, - 13 => pge, - 14 => mca, - 15 => cmov, - 16 => pat, - 17 => pse_36, - 18 => psn, - 19 => clfsh, - // 20 - reserved - 21 => ds, - 22 => acpi, - 23 => mmx, - 24 => fxsr, - 25 => sse, - 26 => sse2, - 27 => ss, - 28 => htt, - 29 => tm, - // 30 -reserved - 31 => pbe, - }); -} - -impl Default for VersionInformation { - fn default() -> Self { - Self::new() - } -} - -impl fmt::Debug for VersionInformation { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - dump!(self, f, "VersionInformation", { - family_id, - model_id, - stepping, - brand_string, - sse3, - pclmulqdq, - dtes64, - monitor, - ds_cpl, - vmx, - smx, - eist, - tm2, - ssse3, - cnxt_id, - sdbg, - fma, - cmpxchg16b, - xtpr_update_control, - pdcm, - pcid, - dca, - sse4_1, - sse4_2, - x2apic, - movbe, - popcnt, - tsc_deadline, - aesni, - xsave, - osxsave, - avx, - f16c, - rdrand, - fpu, - vme, - de, - pse, - tsc, - msr, - pae, - mce, - cx8, - apic, - sep, - mtrr, - pge, - mca, - cmov, - pat, - pse_36, - psn, - clfsh, - ds, - acpi, - mmx, - fxsr, - sse, - sse2, - ss, - htt, - tm, - pbe, - }) - } -} - -#[derive(Copy, Clone)] -pub struct ExtendedProcessorSignature { - ecx: u32, - edx: u32, -} - -impl ExtendedProcessorSignature { - fn new() -> ExtendedProcessorSignature { - let (_, _, c, d) = cpuid(RequestType::ExtendedProcessorSignature); - ExtendedProcessorSignature { ecx: c, edx: d } - } - - bit!(ecx, { - 0 => lahf_sahf_in_64_bit, - // 1-4 reserved - 5 => lzcnt, - // 6-7 reserved - 8 => prefetchw, - // 9-31 reserved - }); - - bit!(edx, { - // 0-10 reserved - 11 => syscall_sysret_in_64_bit, - // 12-19 reserved - 20 => execute_disable, - // 21-25 reserved - 26 => gigabyte_pages, - 27 => rdtscp_and_ia32_tsc_aux, - // 28 reserved - 29 => intel_64_bit_architecture, - // 30-31 reserved - }); -} - -impl fmt::Debug for ExtendedProcessorSignature { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - dump!(self, f, "ThermalPowerManagementInformation", { - lahf_sahf_in_64_bit, - lzcnt, - prefetchw, - syscall_sysret_in_64_bit, - execute_disable, - gigabyte_pages, - rdtscp_and_ia32_tsc_aux, - intel_64_bit_architecture, - }) - } -} - -pub struct BrandString { - bytes: [u8; BRAND_STRING_LENGTH], -} - -impl BrandString { - fn new() -> BrandString { - fn append_bytes(a: RequestType, bytes: &mut [u8]) { - let (a, b, c, d) = cpuid(a); - - let result_bytes = as_bytes(&a) - .iter() - .chain(as_bytes(&b).iter()) - .chain(as_bytes(&c).iter()) - .chain(as_bytes(&d).iter()); - - for (output, input) in bytes.iter_mut().zip(result_bytes) { - *output = *input - } - } - - let mut brand_string = BrandString { - bytes: [0; BRAND_STRING_LENGTH], - }; - append_bytes(RequestType::BrandString1, &mut brand_string.bytes[0..]); - append_bytes(RequestType::BrandString2, &mut brand_string.bytes[16..]); - append_bytes(RequestType::BrandString3, &mut brand_string.bytes[32..]); - brand_string - } -} - -impl Clone for BrandString { - fn clone(&self) -> Self { - let mut bytes = [0; BRAND_STRING_LENGTH]; - for (d, s) in bytes.iter_mut().zip(self.bytes.iter()) { - *d = *s; - } - BrandString { bytes } - } -} - -impl Deref for BrandString { - type Target = str; - - fn deref(&self) -> &str { - let nul_terminator = self.bytes.iter().position(|&b| b == 0).unwrap_or(0); - let usable_bytes = &self.bytes[..nul_terminator]; - unsafe { str::from_utf8_unchecked(usable_bytes) }.trim() - } -} - -impl fmt::Display for BrandString { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - (self as &str).fmt(f) - } -} - -impl fmt::Debug for BrandString { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - (self as &str).fmt(f) - } -} - -#[derive(Copy, Clone)] -pub struct ThermalPowerManagementInformation { - eax: u32, - ebx: u32, - ecx: u32, -} - -impl ThermalPowerManagementInformation { - fn new() -> ThermalPowerManagementInformation { - let (a, b, c, _) = cpuid(RequestType::ThermalPowerManagementInformation); - ThermalPowerManagementInformation { - eax: a, - ebx: b, - ecx: c, - } - } - - bit!(eax, { - 0 => digital_temperature_sensor, - 1 => intel_turbo_boost, - 2 => arat, - // 3 - reserved - 4 => pln, - 5 => ecmd, - 6 => ptm, - 7 => hwp, - 8 => hwp_notification, - 9 => hwp_activity_window, - 10 => hwp_energy_performance_preference, - // 12 - reserved - 13 => hdc, - }); - - pub fn number_of_interrupt_thresholds(self) -> u32 { - bits_of(self.ebx, 0, 3) - } - - bit!(ecx, { - 0 => hardware_coordination_feedback, - // 1-2 - reserved - 3 => performance_energy_bias - }); -} - -impl fmt::Debug for ThermalPowerManagementInformation { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - dump!(self, f, "ThermalPowerManagementInformation", { - digital_temperature_sensor, - intel_turbo_boost, - arat, - pln, - ecmd, - ptm, - hwp, - hwp_notification, - hwp_activity_window, - hwp_energy_performance_preference, - hdc, - number_of_interrupt_thresholds, - hardware_coordination_feedback, - performance_energy_bias - }) - } -} - -#[derive(Copy, Clone)] -pub struct StructuredExtendedInformation { - ebx: u32, - ecx: u32, -} - -impl StructuredExtendedInformation { - fn new() -> StructuredExtendedInformation { - let (_, b, c, _) = cpuid(RequestType::StructuredExtendedInformation); - StructuredExtendedInformation { ebx: b, ecx: c } - } - - bit!(ebx, { - 0 => fsgsbase, - 1 => ia32_tsc_adjust_msr, - // 2 - reserved - 3 => bmi1, - 4 => hle, - 5 => avx2, - // 6 - reserved - 7 => smep, - 8 => bmi2, - 9 => enhanced_rep_movsb_stosb, - 10 => invpcid, - 11 => rtm, - 12 => pqm, - 13 => deprecates_fpu_cs_ds, - // 14 - reserved - 15 => pqe, - // 16-17 - reserved - 18 => rdseed, - 19 => adx, - 20 => smap, - // 21-24 - reserved - 25 => intel_processor_trace, - // 26-31 - reserved - }); - - bit!(ecx, { - 0 => prefetchwt1 - }); -} - -impl fmt::Debug for StructuredExtendedInformation { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - dump!(self, f, "StructuredExtendedInformation", { - fsgsbase, - ia32_tsc_adjust_msr, - bmi1, - hle, - avx2, - smep, - bmi2, - enhanced_rep_movsb_stosb, - invpcid, - rtm, - pqm, - deprecates_fpu_cs_ds, - pqe, - rdseed, - adx, - smap, - intel_processor_trace, - prefetchwt1, - }) - } -} - -#[derive(Debug, Copy, Clone)] -pub enum CacheLineAssociativity { - Disabled, - DirectMapped, - TwoWay, - FourWay, - EightWay, - SixteenWay, - Full, -} - -#[derive(Copy, Clone)] -pub struct CacheLine(u32); -impl CacheLine { - fn new() -> CacheLine { - let (_, _, c, _) = cpuid(RequestType::CacheLine); - CacheLine(c) - } - - pub fn cache_line_size(self) -> u32 { - bits_of(self.0, 0, 7) - } - - pub fn l2_associativity(self) -> Option<CacheLineAssociativity> { - match bits_of(self.0, 12, 15) { - 0x00 => Some(CacheLineAssociativity::Disabled), - 0x01 => Some(CacheLineAssociativity::DirectMapped), - 0x02 => Some(CacheLineAssociativity::TwoWay), - 0x04 => Some(CacheLineAssociativity::FourWay), - 0x06 => Some(CacheLineAssociativity::EightWay), - 0x08 => Some(CacheLineAssociativity::SixteenWay), - 0x0F => Some(CacheLineAssociativity::Full), - _ => None, - } - } - - pub fn cache_size(self) -> u32 { - bits_of(self.0, 16, 31) - } -} - -impl fmt::Debug for CacheLine { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - dump!(self, f, "CacheLine", { - cache_line_size, - l2_associativity, - cache_size - }) - } -} - -#[derive(Copy, Clone)] -pub struct TimeStampCounter { - edx: u32, -} - -impl TimeStampCounter { - fn new() -> TimeStampCounter { - let (_, _, _, d) = cpuid(RequestType::TimeStampCounter); - TimeStampCounter { edx: d } - } - - bit!(edx, { - // 0-7 - reserved - 8 => invariant_tsc - // 9-31 - reserved - }); -} - -impl fmt::Debug for TimeStampCounter { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - dump!(self, f, "TimeStampCounter", { invariant_tsc }) - } -} - -#[derive(Copy, Clone)] -pub struct PhysicalAddressSize(u32); -impl PhysicalAddressSize { - fn new() -> PhysicalAddressSize { - let (a, _, _, _) = cpuid(RequestType::PhysicalAddressSize); - PhysicalAddressSize(a) - } - - pub fn physical_address_bits(self) -> u32 { - bits_of(self.0, 0, 7) - } - - pub fn linear_address_bits(self) -> u32 { - bits_of(self.0, 8, 15) - } -} - -impl fmt::Debug for PhysicalAddressSize { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - dump!(self, f, "PhysicalAddressSize", { - physical_address_bits, - linear_address_bits - }) - } -} - -/// Information about the currently running processor -/// -/// Feature flags match the feature mnemonic listed in the Intel -/// Instruction Set Reference. This struct provides a facade for flags -/// so the consumer doesn't need to worry about which particular CPUID -/// leaf provides the information. -/// -/// For data beyond simple feature flags, you will need to retrieve -/// the nested struct and call the appropriate methods on it. -#[derive(Debug, Clone)] -pub struct Master { - // TODO: Rename struct - version_information: Option<VersionInformation>, - thermal_power_management_information: Option<ThermalPowerManagementInformation>, - structured_extended_information: Option<StructuredExtendedInformation>, - extended_processor_signature: Option<ExtendedProcessorSignature>, - brand_string: Option<BrandString>, - cache_line: Option<CacheLine>, - time_stamp_counter: Option<TimeStampCounter>, - physical_address_size: Option<PhysicalAddressSize>, -} - -impl Master { - pub fn new() -> Master { - fn when_supported<F, T>(max: u32, kind: RequestType, then: F) -> Option<T> - where - F: FnOnce() -> T, - { - if max >= kind as u32 { - Some(then()) - } else { - None - } - } - - let (max_value, _, _, _) = cpuid(RequestType::BasicInformation); - - let vi = when_supported(max_value, RequestType::VersionInformation, || { - VersionInformation::new() - }); - let tpm = when_supported( - max_value, - RequestType::ThermalPowerManagementInformation, - ThermalPowerManagementInformation::new, - ); - let sei = when_supported( - max_value, - RequestType::StructuredExtendedInformation, - StructuredExtendedInformation::new, - ); - - // Extended information - - let (max_value, _, _, _) = cpuid(RequestType::ExtendedFunctionInformation); - - let eps = when_supported(max_value, RequestType::ExtendedProcessorSignature, || { - ExtendedProcessorSignature::new() - }); - let brand_string = when_supported(max_value, RequestType::BrandString3, BrandString::new); - let cache_line = when_supported(max_value, RequestType::CacheLine, CacheLine::new); - let tsc = when_supported(max_value, RequestType::TimeStampCounter, || { - TimeStampCounter::new() - }); - let pas = when_supported(max_value, RequestType::PhysicalAddressSize, || { - PhysicalAddressSize::new() - }); - - Master { - version_information: vi, - thermal_power_management_information: tpm, - structured_extended_information: sei, - extended_processor_signature: eps, - brand_string, - cache_line, - time_stamp_counter: tsc, - physical_address_size: pas, - } - } - - master_attr_reader!(version_information, VersionInformation); - master_attr_reader!( - thermal_power_management_information, - ThermalPowerManagementInformation - ); - master_attr_reader!( - structured_extended_information, - StructuredExtendedInformation - ); - master_attr_reader!(extended_processor_signature, ExtendedProcessorSignature); - master_attr_reader!(cache_line, CacheLine); - master_attr_reader!(time_stamp_counter, TimeStampCounter); - master_attr_reader!(physical_address_size, PhysicalAddressSize); - - pub fn brand_string(&self) -> Option<&str> { - self.brand_string - .as_ref() - .map(|bs| bs as &str) - .or_else(|| self.version_information.and_then(|vi| vi.brand_string())) - } - - delegate_flag!(version_information, { - sse3, - pclmulqdq, - dtes64, - monitor, - ds_cpl, - vmx, - smx, - eist, - tm2, - ssse3, - cnxt_id, - sdbg, - fma, - cmpxchg16b, - xtpr_update_control, - pdcm, - pcid, - dca, - sse4_1, - sse4_2, - x2apic, - movbe, - popcnt, - tsc_deadline, - aesni, - xsave, - osxsave, - avx, - f16c, - rdrand, - fpu, - vme, - de, - pse, - tsc, - msr, - pae, - mce, - cx8, - apic, - sep, - mtrr, - pge, - mca, - cmov, - pat, - pse_36, - psn, - clfsh, - ds, - acpi, - mmx, - fxsr, - sse, - sse2, - ss, - htt, - tm, - pbe, - }); - - delegate_flag!(thermal_power_management_information, { - digital_temperature_sensor, - intel_turbo_boost, - arat, - pln, - ecmd, - ptm, - hwp, - hwp_notification, - hwp_activity_window, - hwp_energy_performance_preference, - hdc, - hardware_coordination_feedback, - performance_energy_bias, - }); - - delegate_flag!(structured_extended_information, { - fsgsbase, - ia32_tsc_adjust_msr, - bmi1, - hle, - avx2, - smep, - bmi2, - enhanced_rep_movsb_stosb, - invpcid, - rtm, - pqm, - deprecates_fpu_cs_ds, - pqe, - rdseed, - adx, - smap, - intel_processor_trace, - prefetchwt1 - }); - - delegate_flag!(extended_processor_signature, { - lahf_sahf_in_64_bit, - lzcnt, - prefetchw, - syscall_sysret_in_64_bit, - execute_disable, - gigabyte_pages, - rdtscp_and_ia32_tsc_aux, - intel_64_bit_architecture, - }); - - delegate_flag!(time_stamp_counter, { invariant_tsc }); -} - -impl Default for Master { - fn default() -> Self { - Self::new() - } -} - -/// The main entrypoint to the CPU information -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] -pub fn master() -> Option<Master> { - Some(Master::new()) -} - -pub fn sysinfo() {} - -pub fn as_bytes(v: &u32) -> &[u8] { - let start = v as *const u32 as *const u8; - // TODO: use u32::BYTES - unsafe { slice::from_raw_parts(start, 4) } -} - -pub fn cpuid(code: RequestType) -> (u32, u32, u32, u32) { - let eax; - let ebx; - let ecx; - let edx; - - unsafe { - asm!( - "movq %rbx, {0:r}", - "cpuid", - "xchgq %rbx, {0:r}", - lateout(reg) ebx, - inlateout("eax") code as u32 => eax, - inlateout("ecx") 0 => ecx, - lateout("edx") edx, - options(nostack, preserves_flags, att_syntax), - ); - } - - (eax, ebx, ecx, edx) -} - -// This matches the Intel Architecture guide, with bits 31 -> 0. -// The bit positions are inclusive. -fn bits_of(val: u32, start_bit: u8, end_bit: u8) -> u32 { - let mut silly = 0; - for _ in start_bit..end_bit + 1 { - silly <<= 1; - silly |= 1; - } - - (val >> start_bit) & silly -} - -/* -cfg_if! { - if #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] { - - #[test] - fn basic_genuine_intel() { - let (_, b, c, d) = cpuid(RequestType::BasicInformation); - - assert_eq!(b"Genu", as_bytes(&b)); - assert_eq!(b"ntel", as_bytes(&c)); - assert_eq!(b"ineI", as_bytes(&d)); - } - - #[test] - fn brand_string_contains_intel() { - assert!(master().unwrap().brand_string().unwrap().contains("Intel(R)")) - } - - } else {} -} -*/ diff --git a/ableos/src/arch/x86_64/drivers/timer.rs b/ableos/src/arch/x86_64/drivers/timer.rs deleted file mode 100644 index 83d32a7..0000000 --- a/ableos/src/arch/x86_64/drivers/timer.rs +++ /dev/null @@ -1,2 +0,0 @@ -/// This magic value is the herts of the timer interupts normalized -pub const TIMER_INTERRUPT_HERTZ: f64 = 1193182.0; diff --git a/ableos/src/arch/x86_64/drivers/vga.rs b/ableos/src/arch/x86_64/drivers/vga.rs deleted file mode 100644 index 8b13789..0000000 --- a/ableos/src/arch/x86_64/drivers/vga.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ableos/src/arch/x86_64/drivers/virtio/mod.rs b/ableos/src/arch/x86_64/drivers/virtio/mod.rs deleted file mode 100644 index e69de29..0000000 diff --git a/ableos/src/arch/x86_64/gdt.rs b/ableos/src/arch/x86_64/gdt.rs deleted file mode 100644 index 5758117..0000000 --- a/ableos/src/arch/x86_64/gdt.rs +++ /dev/null @@ -1,47 +0,0 @@ -use spin::Lazy; -use x86_64::structures::gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector}; -use x86_64::structures::tss::TaskStateSegment; -use x86_64::VirtAddr; - -pub const DOUBLE_FAULT_IST_INDEX: u16 = 0; - -struct Selectors { - code_selector: SegmentSelector, - tss_selector: SegmentSelector, -} - -static TSS: Lazy<TaskStateSegment> = Lazy::new(|| { - let mut tss = TaskStateSegment::new(); - tss.interrupt_stack_table[DOUBLE_FAULT_IST_INDEX as usize] = { - const STACK_SIZE: usize = 4096 * 5; - static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE]; - - let stack_start = VirtAddr::from_ptr(unsafe { &STACK }); - stack_start + STACK_SIZE - }; - tss -}); - -static GDT: Lazy<(GlobalDescriptorTable, Selectors)> = Lazy::new(|| { - let mut gdt = GlobalDescriptorTable::new(); - let code_selector = gdt.add_entry(Descriptor::kernel_code_segment()); - let tss_selector = gdt.add_entry(Descriptor::tss_segment(&TSS)); - ( - gdt, - Selectors { - code_selector, - tss_selector, - }, - ) -}); - -pub fn init() { - use x86_64::instructions::segmentation::{Segment, CS}; - use x86_64::instructions::tables::load_tss; - - GDT.0.load(); - unsafe { - CS::set_reg(GDT.1.code_selector); - load_tss(GDT.1.tss_selector); - } -} diff --git a/ableos/src/arch/x86_64/init.rs b/ableos/src/arch/x86_64/init.rs deleted file mode 100644 index 88344bc..0000000 --- a/ableos/src/arch/x86_64/init.rs +++ /dev/null @@ -1,31 +0,0 @@ -// #![allow(clippy::print_literal)] -use super::{gdt, interrupts}; -use crate::{logger, serial_println, TERM}; - -/// x86_64 initialization -pub fn init() { - // use crate::{network::socket::SimpleSock, relib::network::socket::Socket}; - - // let mut log_socket_id = SimpleSock::new(); - // log_socket_id.register_protocol("Logger".to_string()); - - let result = logger::init(); - match result { - Ok(_) => { - info!("Logger initialized"); - } - Err(err) => serial_println!("{}", err), - } - - let mut term = TERM.lock(); - // term.initialize(); - term.set_dirty(true); - term.draw_term(); - drop(term); - - gdt::init(); - - interrupts::init_idt(); - unsafe { interrupts::PICS.lock().initialize() }; - x86_64::instructions::interrupts::enable(); -} diff --git a/ableos/src/arch/x86_64/interrupts.rs b/ableos/src/arch/x86_64/interrupts.rs deleted file mode 100644 index 16b5de6..0000000 --- a/ableos/src/arch/x86_64/interrupts.rs +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright (c) 2022, able <abl3theabove@gmail.com> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -use core::panic::PanicInfo; - -use crate::{arch::gdt, println, rhai_shell::KEYBUFF}; -use cpuio::outb; -use pic8259::ChainedPics; -use qrcode::QrCode; -use seq_macro::seq; -use spin::Lazy; -use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; - -use super::sloop; - -pub const PIC_1_OFFSET: u8 = 32; -pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8; - -pub static PICS: spin::Mutex<ChainedPics> = - spin::Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) }); - -/// Interrupt offsets. -#[derive(Debug, Clone, Copy)] -#[repr(u8)] -pub enum InterruptIndex { - Timer = PIC_1_OFFSET, - Keyboard, - /// Mouse offset - Mouse = 44, - - /// Disk offset - Disk = 46, - - // SecondInterrupt = PIC_2_OFFSET, - Cmos = 0x70, -} - -impl InterruptIndex { - fn as_u8(self) -> u8 { - self as u8 - } - fn as_usize(self) -> usize { - usize::from(self.as_u8()) - } -} - -static IDT: Lazy<InterruptDescriptorTable> = Lazy::new(|| { - reset_pit_for_cpu(); - let mut idt = InterruptDescriptorTable::new(); - - seq!(N in 32..=255 { - idt[N].set_handler_fn(undefined_handler_~N); - }); - - idt.breakpoint.set_handler_fn(breakpoint_handler); - unsafe { - idt.double_fault - .set_handler_fn(double_fault_handler) - .set_stack_index(gdt::DOUBLE_FAULT_IST_INDEX); - } - - idt[InterruptIndex::Timer.as_usize()].set_handler_fn(timer_interrupt_handler); - idt[InterruptIndex::Keyboard.as_usize()].set_handler_fn(keyboard_interrupt_handler); - idt[InterruptIndex::Mouse.as_usize()].set_handler_fn(crate::hardware::mouse_interrupt_handler); - - // run `a + b + l + e + o + s print;` in ablescript and its 54 thats why this seemingly arbitrary number was chosen - idt[54].set_handler_fn(software_int_handler); - - idt -}); - -seq!(N in 32..=255 { - extern "x86-interrupt" fn undefined_handler_~N(stack_frame: InterruptStackFrame) { - error!("INT {}: {:?}", N, stack_frame); - unsafe { - PICS.lock() - .notify_end_of_interrupt(N); - } - } -}); - -extern "x86-interrupt" fn software_int_handler(stack_frame: InterruptStackFrame) { - trace!("EXCEPTION: SOFTWARE INT\n{:#?}", stack_frame); - unsafe { - PICS.lock().notify_end_of_interrupt(54); - } -} - -extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) { - trace!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame); -} - -extern "x86-interrupt" fn double_fault_handler( - stack_frame: InterruptStackFrame, - // NOTE(able): ignore this always is 0 - _error_code: u64, -) -> ! { - bsod(BSODSource::DoubleFault(&stack_frame)); - // panic!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); -} - -/* SAFETY -* DO NOT TOUCH -* The `#[naked]` macro removes various error/bounds checks that -* the Rust compiler would normally add. -* *Early return* and *enabling interrupts* in this function are -* undefined behavior. -* As long as nothing in this function does something that would -* normally trigger an error, this function is relatively safe. -*/ -extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFrame) { - crate::kmain::tick(); - unsafe { - PICS.lock() - .notify_end_of_interrupt(InterruptIndex::Timer.as_u8()); - } -} - -extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStackFrame) { - use pc_keyboard::{ - layouts::Us104Key, DecodedKey, HandleControl, KeyCode, Keyboard, ScancodeSet1, - }; - use spin::Mutex; - use x86_64::instructions::port::Port; - - static KEYBOARD: Lazy<Mutex<Keyboard<Us104Key, ScancodeSet1>>> = - Lazy::new(|| Mutex::new(Keyboard::new(Us104Key, ScancodeSet1, HandleControl::Ignore))); - - let mut keyboard = KEYBOARD.lock(); - if let Ok(Some(key)) = keyboard - .add_byte(unsafe { Port::new(0x60).read() }) - .map(|x| x.and_then(|ev| keyboard.process_keyevent(ev))) - { - // trace!("{key:?}"); - match key { - DecodedKey::Unicode(chr) => match chr { - '\n' => { - KEYBUFF.lock().push('\n'); - } - // Backspace - '\u{8}' => { - // TODO: Fix this and apply to new term - - KEYBUFF.lock().push(8.into()); - // trace!("8"); - // print!("\u{8}"); - } - // '^' => KERNEL_STATE.lock().shutdown(), - chr => { - KEYBUFF.lock().push(chr); - // trace!("{chr}"); - // print!("{chr}"); - } - }, - DecodedKey::RawKey(key) => { - use KeyCode::*; - match KeyCode::from(key) { - AltLeft | AltRight => (), - ArrowDown | ArrowRight | ArrowLeft | ArrowUp => { - // warn!("ArrowKeys are unsupported currently"); - } - - _kc => { - // trace!("Unprintable key: {kc:?}"), - } - }; - } - } - } - - unsafe { - PICS.lock() - .notify_end_of_interrupt(InterruptIndex::Keyboard.as_u8()); - } -} - -pub fn init_idt() { - IDT.load(); -} - -/// https://wiki.osdev.org/Pit -/// -const PIT_MAX_FREQ: u32 = 1193182; - -pub fn set_pit_frequency(pit: u16, freq: u32) { - // Dividing the maximum frequency by the desired frequency - // gives roughly what the maximum value for the timer - // counter should be to run at the desired frequency. - let ret = (PIT_MAX_FREQ / freq).try_into(); - - // Type-bounded counter maximum. - let divisor: u16 = match ret { - Ok(div) => div, - Err(err) => { - error!("{}", err); - - warn!("Defaulting to 1000 on PIT{}", pit); - 1000 - } - }; - - unsafe { - outb(0x36, 0x43); - - outb((divisor & 0xFF) as u8, 0x39 + pit); - outb((divisor >> 8) as u8, 0x40 + pit); - } -} -pub fn set_pit_1(freq: u32) { - set_pit_frequency(1, freq); -} -pub fn set_pit_2(freq: u32) { - set_pit_frequency(2, freq); -} - -pub fn set_pit_3(freq: u32) { - set_pit_frequency(3, freq); -} - -pub fn reset_pit_for_cpu() { - set_pit_1(1000); - set_pit_2(1000); - set_pit_3(1000); -} -pub fn bsod(src: BSODSource) -> ! { - let src1 = match src { - BSODSource::DoubleFault(_) => "DoubleFault".to_string(), - BSODSource::Panic(panic_info) => { - let strr = format!("PANIC: {}", panic_info); - strr - } - }; - - let st = format!( - "We fucked up ඞ : \n{}\nThe following qr code will link you to the wiki which hopefully solves your problems", - src1 - ); - - println!("\n{}", st); - - // let sf = format!("https://git.ablecorp.us/able/ableos/wiki/Double-Faults"); - - let sd = match src { - BSODSource::DoubleFault(_) => "https://git.ablecorp.us/able/ableos/wiki/Double-Faults", - BSODSource::Panic(_) => { - trace!("panic"); - "https://git.ablecorp.us/able/ableos/wiki/Panic" - } - }; - - let code = QrCode::new(sd).unwrap(); - - let image = code - .render::<char>() - .quiet_zone(false) - .module_dimensions(1, 1) - .build(); - - println!("{}", image); - - sloop(); -} - -#[derive(Debug)] -pub enum BSODSource<'a> { - DoubleFault(&'a InterruptStackFrame), - Panic(&'a PanicInfo<'a>), -} diff --git a/ableos/src/arch/x86_64/memory.rs b/ableos/src/arch/x86_64/memory.rs deleted file mode 100644 index df43bb3..0000000 --- a/ableos/src/arch/x86_64/memory.rs +++ /dev/null @@ -1,118 +0,0 @@ -use bootloader::bootinfo::{MemoryMap, MemoryRegionType}; -use x86_64::{ - structures::paging::{ - FrameAllocator, FrameDeallocator, Mapper, OffsetPageTable, Page, PageTable, PhysFrame, - Size4KiB, - }, - PhysAddr, VirtAddr, -}; - -pub unsafe fn init(physical_memory_offset: VirtAddr) -> OffsetPageTable<'static> { - let level_4_table = active_level_4_table(physical_memory_offset); - OffsetPageTable::new(level_4_table, physical_memory_offset) -} - -unsafe fn active_level_4_table(physical_memory_offset: VirtAddr) -> &'static mut PageTable { - use x86_64::registers::control::Cr3; - - let (level_4_table_frame, _) = Cr3::read(); - - let phys = level_4_table_frame.start_address(); - let virt = physical_memory_offset + phys.as_u64(); - let page_table_ptr: *mut PageTable = virt.as_mut_ptr(); - - // THIS IS UNSAFE - &mut *page_table_ptr -} - -fn translate_addr_inner(addr: VirtAddr, physical_memory_offset: VirtAddr) -> Option<PhysAddr> { - use x86_64::registers::control::Cr3; - use x86_64::structures::paging::page_table::FrameError; - - let (level_4_table_frame, _) = Cr3::read(); - - let table_indexes = [ - addr.p4_index(), - addr.p3_index(), - addr.p2_index(), - addr.p1_index(), - ]; - let mut frame = level_4_table_frame; - - for &index in &table_indexes { - // convert the frame into a page table reference - let virt = physical_memory_offset + frame.start_address().as_u64(); - let table_ptr: *const PageTable = virt.as_ptr(); - let table = unsafe { &*table_ptr }; - - let entry = &table[index]; - frame = match entry.frame() { - Ok(frame) => frame, - Err(FrameError::FrameNotPresent) => return None, - Err(FrameError::HugeFrame) => panic!["huge pages not supported"], - }; - } - - Some(frame.start_address() + u64::from(addr.page_offset())) -} - -pub unsafe fn translate_addr(addr: VirtAddr, physical_memory_offset: VirtAddr) -> Option<PhysAddr> { - translate_addr_inner(addr, physical_memory_offset) -} - -pub fn create_example_mapping( - page: Page, - mapper: &mut OffsetPageTable, - frame_allocator: &mut impl FrameAllocator<Size4KiB>, -) { - use x86_64::structures::paging::PageTableFlags as Flags; - - let frame = PhysFrame::containing_address(PhysAddr::new(0xb8000)); - let flags = Flags::PRESENT | Flags::WRITABLE; - - let map_to_result = unsafe { mapper.map_to(page, frame, flags, frame_allocator) }; - map_to_result.expect("map_to failed").flush(); -} - -pub struct EmptyFrameAllocator; -unsafe impl FrameAllocator<Size4KiB> for EmptyFrameAllocator { - fn allocate_frame(&mut self) -> Option<PhysFrame<Size4KiB>> { - None - } -} - -pub struct BootInfoFrameAllocator { - memory_map: &'static MemoryMap, - next: usize, -} - -impl BootInfoFrameAllocator { - pub unsafe fn init(memory_map: &'static MemoryMap) -> Self { - Self { - memory_map, - next: 0, - } - } - - fn usable_frames(&self) -> impl Iterator<Item = PhysFrame> { - let regions = self.memory_map.iter(); - let usable_regions = regions.filter(|r| r.region_type == MemoryRegionType::Usable); - let addr_range = usable_regions.map(|r| r.range.start_addr()..r.range.end_addr()); - let frame_address = addr_range.flat_map(|r| r.step_by(4096)); - frame_address.map(|addr| PhysFrame::containing_address(PhysAddr::new(addr))) - } -} - -unsafe impl FrameAllocator<Size4KiB> for BootInfoFrameAllocator { - fn allocate_frame(&mut self) -> Option<PhysFrame<Size4KiB>> { - let frame = self.usable_frames().nth(self.next); - self.next += 1; - frame - } -} - -impl FrameDeallocator<Size4KiB> for BootInfoFrameAllocator { - unsafe fn deallocate_frame(&mut self, _frame: PhysFrame<Size4KiB>) { - // TODO - } -} diff --git a/ableos/src/arch/x86_64/mod.rs b/ableos/src/arch/x86_64/mod.rs deleted file mode 100644 index cabb6bb..0000000 --- a/ableos/src/arch/x86_64/mod.rs +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2022, able <abl3theabove@gmail.com> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -pub mod drivers; -pub mod gdt; -pub mod init; -pub mod interrupts; -pub mod memory; - -use crate::arch::drivers::allocator; -use bootloader::{entry_point, BootInfo}; -use x86_64::{instructions::hlt, VirtAddr}; - -#[cfg(not(test))] -entry_point![start]; - -#[cfg(not(test))] -#[no_mangle] -pub fn start(boot_info: &'static BootInfo) -> ! { - let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset); - - let mut mapper = unsafe { memory::init(phys_mem_offset) }; - let mut frame_allocator = - unsafe { memory::BootInfoFrameAllocator::init(&boot_info.memory_map) }; - - // let page = Page::containing_address(VirtAddr::new(0xdeadbeaf000)); - // memory::create_example_mapping(page, &mut mapper, &mut frame_allocator); - // - // let page_ptr: *mut u64 = page.start_address().as_mut_ptr(); - // unsafe { page_ptr.offset(400).write_volatile(0xf021_f077_f065_804e) }; - - allocator::init_heap(&mut mapper, &mut frame_allocator).expect("heap initialization failed"); - - crate::kmain::kernel_main(mapper, frame_allocator); -} - -#[allow(unused)] -pub fn shutdown() -> ! { - info!("Shutting down"); - unsafe { - cpuio::outw(0x2000, 0x604); - } - - sloop(); -} - -pub fn sloop() -> ! { - loop { - hlt(); - } -} - -// TODO: Split up into the randomness and the password generation -pub fn generate_process_pass() -> u128 { - // TODO: Move this into entropy_pool module - use rdrand::RdRand; - let gen = RdRand::new().unwrap(); - - (gen.try_next_u64().unwrap() as u128) << 64 | (gen.try_next_u64().unwrap() as u128) -} diff --git a/ableos/src/boot_conf.rs b/ableos/src/boot_conf.rs deleted file mode 100644 index f3248c2..0000000 --- a/ableos/src/boot_conf.rs +++ /dev/null @@ -1,70 +0,0 @@ -use log::LevelFilter; -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Debug, Deserialize)] -pub enum LogLevel { - /// A level lower than all log levels. - Off, - /// Corresponds to the `Error` log level. - Error, - /// Corresponds to the `Warn` log level. - Warn, - /// Corresponds to the `Info` log level. - Info, - /// Corresponds to the `Debug` log level. - Debug, - /// Corresponds to the `Trace` log level. - Trace, -} - -#[derive(Serialize, Debug, Deserialize)] -pub struct KernelConfig { - pub boot: BootConfig, - pub logging: LoggingConfig, - pub tests: TestsConfig, -} - -impl KernelConfig { - pub fn new() -> Self { - toml::from_str(include_str!("../assets/kernel.toml")).unwrap() - } - - pub fn log_level(&self) -> LevelFilter { - use LevelFilter::*; - match self.logging.level { - LogLevel::Off => Off, - LogLevel::Error => Error, - LogLevel::Warn => Warn, - LogLevel::Info => Info, - LogLevel::Debug => Debug, - LogLevel::Trace => Trace, - } - } -} - -impl Default for KernelConfig { - fn default() -> Self { - Self::new() - } -} - -#[derive(Serialize, Debug, Deserialize)] -pub struct LoggingConfig { - pub enabled: bool, - pub log_to_serial: bool, - pub log_to_vterm: bool, - pub level: LogLevel, - pub filter: Vec<String>, -} -#[derive(Serialize, Debug, Deserialize)] -pub struct TestsConfig { - pub run_tests: bool, - pub run_demos: bool, - pub run_shader_tests: bool, -} - -#[derive(Serialize, Debug, Deserialize)] -pub struct BootConfig { - pub system_processes: Vec<String>, - pub user_processes: Vec<String>, -} diff --git a/ableos/src/device_interface/block.rs b/ableos/src/device_interface/block.rs deleted file mode 100644 index 9a24cc3..0000000 --- a/ableos/src/device_interface/block.rs +++ /dev/null @@ -1,6 +0,0 @@ -//! Block device interface - -/// Block device interface -pub trait BlockDevice { - // TODO -} diff --git a/ableos/src/device_interface/character/mod.rs b/ableos/src/device_interface/character/mod.rs deleted file mode 100644 index 97d4050..0000000 --- a/ableos/src/device_interface/character/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -//! - -/// Character device interface. -pub trait CharacterDevice { - /// Returns true if the device can be read from. - fn can_read(&self) -> bool; - - /// Returns true if the device can be written to - fn can_write(&self) -> bool; - - /// Reads a single character from the device - fn read_char(&mut self) -> Option<char>; - - /// Writes a single character to the device and returns true if the write was successful - fn write_char(&mut self, c: char) -> bool; - - /// Reset the device to its initial state - fn reset(&mut self); - - /// initializes the device, returns true if successful - fn initialize(&mut self) -> bool; -} diff --git a/ableos/src/device_interface/mod.rs b/ableos/src/device_interface/mod.rs deleted file mode 100644 index 5306d1b..0000000 --- a/ableos/src/device_interface/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! Platform Agnostic Device - -mod block; -mod character; - -pub use block::BlockDevice; -pub use character::CharacterDevice; diff --git a/ableos/src/devices/character_devs/dev_null.rs b/ableos/src/devices/character_devs/dev_null.rs deleted file mode 100644 index 1643b49..0000000 --- a/ableos/src/devices/character_devs/dev_null.rs +++ /dev/null @@ -1,29 +0,0 @@ -use crate::device_interface::CharacterDevice; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct DevNull; -impl CharacterDevice for DevNull { - fn can_read(&self) -> bool { - true - } - - fn can_write(&self) -> bool { - true - } - - fn read_char(&mut self) -> Option<char> { - Some(0x00 as char) - } - - fn write_char(&mut self, _: char) -> bool { - true - } - - fn reset(&mut self) { - todo!() - } - - fn initialize(&mut self) -> bool { - todo!() - } -} diff --git a/ableos/src/devices/character_devs/dev_unicode.rs b/ableos/src/devices/character_devs/dev_unicode.rs deleted file mode 100644 index c3aafef..0000000 --- a/ableos/src/devices/character_devs/dev_unicode.rs +++ /dev/null @@ -1,49 +0,0 @@ -use crate::device_interface::CharacterDevice; - -#[derive(Debug)] -pub struct DevUnicode { - pub next_write_char: char, - pub next_read_char: char, -} - -impl CharacterDevice for DevUnicode { - fn can_read(&self) -> bool { - true - } - - fn can_write(&self) -> bool { - true - } - - fn read_char(&mut self) -> Option<char> { - let c = self.next_read_char; - self.next_read_char = add1_char(c); - - Some(c) - } - - fn write_char(&mut self, c: char) -> bool { - if self.next_write_char != c { - return false; - } - - true - } - - fn reset(&mut self) { - self.next_write_char = 0x00 as char; - self.next_read_char = 0x00 as char; - } - - fn initialize(&mut self) -> bool { - true - } -} - -fn add1_char(c: char) -> char { - if c == char::MAX { - return 0x00 as char; - } - - char::from_u32(c as u32 + 1).unwrap() -} diff --git a/ableos/src/devices/character_devs/dev_zero.rs b/ableos/src/devices/character_devs/dev_zero.rs deleted file mode 100644 index b6a6844..0000000 --- a/ableos/src/devices/character_devs/dev_zero.rs +++ /dev/null @@ -1,27 +0,0 @@ -use crate::device_interface::CharacterDevice; - -#[derive(Debug)] -pub struct DevZero; -impl CharacterDevice for DevZero { - fn can_read(&self) -> bool { - true - } - - fn can_write(&self) -> bool { - true - } - - fn read_char(&mut self) -> Option<char> { - Some(0 as char) - } - - fn write_char(&mut self, _: char) -> bool { - true - } - - fn reset(&mut self) {} - - fn initialize(&mut self) -> bool { - true - } -} diff --git a/ableos/src/devices/character_devs/mod.rs b/ableos/src/devices/character_devs/mod.rs deleted file mode 100644 index 806d284..0000000 --- a/ableos/src/devices/character_devs/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod dev_null; -pub mod dev_unicode; -pub mod dev_zero; - -pub use crate::device_interface::CharacterDevice; diff --git a/ableos/src/devices/dev_vterm.rs b/ableos/src/devices/dev_vterm.rs deleted file mode 100644 index ec4082c..0000000 --- a/ableos/src/devices/dev_vterm.rs +++ /dev/null @@ -1,265 +0,0 @@ -// ! A virtual terminal device. - -use crate::device_interface::CharacterDevice; -use core::ops::Not; -use core::sync::atomic::AtomicU32; -use core::sync::atomic::Ordering; - -use crate::pixel_format::Rgba64; - -pub const VTERM_HEIGHT: u32 = 40; -pub const VTERM_WIDTH: u32 = 100; - -pub static VIRTUAL_TERMINAL_COUNT: AtomicU32 = AtomicU32::new(0); - -/// Fg and bg colors for vterm -pub type ColorCharacter = (Rgba64, Rgba64); - -/// A vterm representation of a character -#[derive(Debug, Clone, Copy)] -pub struct VtermCharacter { - pub character: char, - // - pub style: Style, - // - pub char_color: ColorCharacter, -} - -#[derive(Default, Debug, Clone, Copy)] - -pub struct Style(pub u8); -impl Style { - pub fn bold(&self) -> bool { - (self.0 & 0x01) > 0 - } - - pub fn underlined(&self) -> bool { - (self.0 & 0x02) > 0 - } - - pub fn italic(&self) -> bool { - (self.0 & 0x04) > 0 - } - - pub fn blinking(&self) -> bool { - (self.0 & 0x08) > 0 - } - - pub fn reversed(&self) -> bool { - (self.0 & 0x10) > 0 - } - - pub fn struck(&self) -> bool { - (self.0 & 0x20) > 0 - } - - #[must_use] - pub fn set_bold(mut self, v: bool) -> Self { - if v { - self.0 |= 0x01; - } else { - self.0 &= 0x01u8.not(); - } - self - } - - #[must_use] - pub fn set_underlined(mut self, v: bool) -> Self { - if v { - self.0 |= 0x02; - } else { - self.0 &= 0x02u8.not(); - } - self - } - - #[must_use] - pub fn set_italic(mut self, v: bool) -> Self { - if v { - self.0 |= 0x04; - } else { - self.0 &= 0x04u8.not(); - } - self - } - - #[must_use] - pub fn set_blinking(mut self, v: bool) -> Self { - if v { - self.0 |= 0x08; - } else { - self.0 &= 0x08u8.not(); - } - self - } - - #[must_use] - pub fn set_reversed(mut self, v: bool) -> Self { - if v { - self.0 |= 0x10; - } else { - self.0 &= 0x10u8.not(); - } - self - } - - #[must_use] - pub fn set_struck(mut self, v: bool) -> Self { - if v { - self.0 |= 0x20; - } else { - self.0 &= 0x20u8.not(); - } - self - } -} - -#[derive(Debug)] -pub struct VTerm { - pub characters: [[VtermCharacter; VTERM_WIDTH as usize]; VTERM_HEIGHT as usize], - pub cursor_visible: bool, - - /// Internal ID of the vterm - iid: u32, - - /// The internal representation of the vterm - style: Style, - - /// The cursor position in layout x,y - cursor_position: (u32, u32), - key_buff: Vec<char>, -} - -impl Default for VTerm { - fn default() -> Self { - VTerm { - iid: 0, - characters: [[VtermCharacter { - character: 0x00 as char, - char_color: (0xff_ff_ff_ff, 0x00_00_00_00), - style: Style::default(), - }; VTERM_WIDTH as usize]; VTERM_HEIGHT as usize], - cursor_position: (0, 0), - cursor_visible: true, - style: Style::default(), - key_buff: vec![], - } - } -} - -/// The primitive interface for a vterm -impl VTerm { - pub fn new() -> Self { - let mut vterm = VTerm::default(); - let mut vtc = VIRTUAL_TERMINAL_COUNT.load(Ordering::Relaxed); - vterm.iid = vtc; - vtc += 1; - VIRTUAL_TERMINAL_COUNT.store(vtc, Ordering::Relaxed); - - vterm - } - /// Set the vterm cursor to the given position - pub fn set_cursor_position(&mut self, x: u32, y: u32) { - if x > VTERM_WIDTH { - self.cursor_position.0 = VTERM_WIDTH; - error!("Cursor x position out of bounds"); - } else { - self.cursor_position.0 = x; - } - if y > VTERM_HEIGHT { - error!("Cursor y position out of bounds"); - self.cursor_position.1 = VTERM_HEIGHT; - } else { - self.cursor_position.1 = y; - } - } - - /// Set the vterm style - pub fn set_vterm_style(&mut self, style: Style) { - self.style = style; - } -} - -impl CharacterDevice for VTerm { - fn can_read(&self) -> bool { - true - } - - fn can_write(&self) -> bool { - true - } - - fn read_char(&mut self) -> Option<char> { - if let Some(c) = self.key_buff.pop() { - return Some(c); - } - None - } - - fn write_char(&mut self, c: char) -> bool { - match c { - '\n' => { - self.cursor_position.1 += 1; - self.cursor_position.0 = 0; - true - } - '\r' => { - self.cursor_position.0 = 0; - true - } - '\t' => { - self.cursor_position.0 += 4; - true - } - '\x08' => { - self.cursor_position.0 -= 1; - self.characters[self.cursor_position.1 as usize][self.cursor_position.0 as usize] - .character = ' '; - true - } - // This is a form feed, which is used to clear the screen - '\x0c' => { - self.characters = [[VtermCharacter { - character: ' ', - char_color: (0xff_ff_ff_ff, 0x00_00_00_00), - style: Style::default(), - }; VTERM_WIDTH as usize]; VTERM_HEIGHT as usize]; - true - } - - _ => { - self.characters[self.cursor_position.1 as usize][self.cursor_position.0 as usize] - .character = c; - self.characters[self.cursor_position.1 as usize][self.cursor_position.0 as usize] - .char_color = (0xff_ff_ff_ff, 0x00_00_00_00); - self.characters[self.cursor_position.1 as usize][self.cursor_position.0 as usize] - .style = self.style; - - if self.cursor_position.0 < VTERM_WIDTH { - self.cursor_position.0 += 1; - true - } else { - self.cursor_position.0 = 0; - self.cursor_position.1 += 1; - true - } - } - } - } - - fn reset(&mut self) { - self.characters = [[VtermCharacter { - character: ' ', - char_color: (0xff_ff_ff_ff, 0x00_00_00_00), - style: Style::default(), - }; VTERM_WIDTH as usize]; VTERM_HEIGHT as usize]; - - self.cursor_position = (0, 0); - self.cursor_visible = true; - self.style = Style::default(); - } - - fn initialize(&mut self) -> bool { - true - } -} diff --git a/ableos/src/devices/id.rs b/ableos/src/devices/id.rs deleted file mode 100644 index cfff8a2..0000000 --- a/ableos/src/devices/id.rs +++ /dev/null @@ -1,14 +0,0 @@ -#[derive(Debug)] -pub enum Vendor { - Unknown = 0, - Ati = 1002, -} - -pub fn match_vendor(id: u16) -> Vendor { - use Vendor::*; - - match id { - 1002 => Ati, - _ => Unknown, - } -} diff --git a/ableos/src/devices/mod.rs b/ableos/src/devices/mod.rs deleted file mode 100644 index d69885c..0000000 --- a/ableos/src/devices/mod.rs +++ /dev/null @@ -1,59 +0,0 @@ -pub mod character_devs; -mod dev_vterm; - -pub mod id; -pub mod pci; - -pub use self::Device::*; - -use crate::device_interface::{BlockDevice, CharacterDevice}; -use crate::devices::dev_vterm::VTerm; -use character_devs::{dev_null::DevNull, dev_unicode::DevUnicode, dev_zero::DevZero}; -use hashbrown::HashMap; -use spin::Lazy; - -pub static DEVICE_TABLE: Lazy<spin::Mutex<DeviceTable>> = - Lazy::new(|| spin::Mutex::new(DeviceTable::new())); - -// FIXME: This is a hack to hold a device. -// #[derive(Debug)] -pub enum Device { - Block(Box<dyn BlockDevice>), - Character(Box<dyn CharacterDevice>), - Vterm(Box<VTerm>), -} - -unsafe impl Sync for Device {} -unsafe impl Send for Device {} - -pub struct DeviceTable { - pub devices: HashMap<String, Device>, -} - -impl DeviceTable { - pub fn new() -> Self { - DeviceTable { - devices: [ - ("null", Character(Box::new(DevNull))), - ("zero", Character(Box::new(DevZero))), - ( - "unicode", - Character(Box::new(DevUnicode { - next_write_char: 0x00 as char, - next_read_char: 0x00 as char, - })), - ), - ("kvterm", Vterm(Box::new(VTerm::new()))), - ] - .into_iter() - .map(|(k, v)| (k.to_string(), v)) - .collect(), - } - } -} - -impl Default for DeviceTable { - fn default() -> Self { - Self::new() - } -} diff --git a/ableos/src/devices/pci/class.rs b/ableos/src/devices/pci/class.rs deleted file mode 100644 index f676a8f..0000000 --- a/ableos/src/devices/pci/class.rs +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (c) 2022, able <abl3theabove@gmail.com> - * Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -use core::fmt::Display; - -#[allow(non_camel_case_types, dead_code)] -#[derive(Debug, Clone, Copy, PartialEq)] -#[repr(C)] -/// Class specification for a PCI device -pub enum PciClass { - Unclassified = 0x00, - MassStorage = 0x01, - Network = 0x02, - Display = 0x03, - Multimedia = 0x04, - Memory = 0x05, - Bridge = 0x06, - Unknown = 0xFF, -} - -impl From<u8> for PciClass { - /// Convert a u8 into the corresponding PciClass - fn from(n: u8) -> Self { - use PciClass::*; - match n { - 0x00 => Unclassified, - 0x01 => MassStorage, - 0x02 => Network, - 0x03 => Display, - 0x04 => Multimedia, - 0x05 => Memory, - 0x06 => Bridge, - _ => Unknown, - } - } -} - -#[allow(non_camel_case_types, dead_code)] -#[derive(Debug, Clone, Copy, PartialEq)] -#[repr(C)] -/// Full class specification (type and subtype) for a PCI device. -/// -/// Uses non-camel-case types for readability. -pub enum PciFullClass { - Unclassified_NonVgaCompatible = 0x0000, - Unclassified_VgaCompatible = 0x0001, - - MassStorage_ScsiBus = 0x0100, - MassStorage_IDE = 0x0101, - MassStorage_Floppy = 0x0102, - MassStorage_IpiBus = 0x0103, - MassStorage_RAID = 0x0104, - MassStorage_ATA = 0x0105, - MassStorage_SATA = 0x0106, - MassStorage_SerialSCSI = 0x0107, - MassStorage_NVM = 0x0108, - MassStorage_Other = 0x0180, - - Network_Ethernet = 0x0200, - Network_TokenRing = 0x0201, - Network_FDDI = 0x0202, - Network_ATM = 0x0203, - Network_ISDN = 0x0204, - Network_WorldFlip = 0x0205, - Network_PICMG = 0x0206, - Network_Infiniband = 0x0207, - Network_Fabric = 0x0208, - Network_Other = 0x0280, - - Display_VGA = 0x0300, - Display_XGA = 0x0301, - Display_3D = 0x0302, - Display_Other = 0x0380, - - Multimedia_Video = 0x0400, - Multimedia_AudioController = 0x0401, - Multimedia_Telephony = 0x0402, - Multimedia_AudioDevice = 0x0403, - Multimedia_Other = 0x0480, - - Memory_RAM = 0x0500, - Memory_Flash = 0x0501, - Memory_Other = 0x0580, - - Bridge_Host = 0x0600, - Bridge_ISA = 0x0601, - Bridge_EISA = 0x0602, - Bridge_MCA = 0x0603, - Bridge_PciToPci = 0x0604, - Bridge_PCMCIA = 0x0605, - Bridge_NuBus = 0x0606, - Bridge_CardBus = 0x0607, - Bridge_RACEway = 0x0608, - Bridge_PciToPciSemiTransparent = 0x0609, - Bridge_InfinibandToPci = 0x060A, - Bridge_Other = 0x0680, - - Unknown = 0xFFFF, -} - -impl PciFullClass { - // listen, i know this sucks, but i didn't want to include - // `num`, `num-traits` and `num-derive` as dependencies for - // this crate just for a convenience function - /// Convert a u16 into the corresponding PciFullClass - pub fn from_u16(n: u16) -> PciFullClass { - match n { - 0x0000 => PciFullClass::Unclassified_NonVgaCompatible, - 0x0001 => PciFullClass::Unclassified_VgaCompatible, - - 0x0100 => PciFullClass::MassStorage_ScsiBus, - 0x0101 => PciFullClass::MassStorage_IDE, - 0x0102 => PciFullClass::MassStorage_Floppy, - 0x0103 => PciFullClass::MassStorage_IpiBus, - 0x0104 => PciFullClass::MassStorage_RAID, - 0x0105 => PciFullClass::MassStorage_ATA, - 0x0106 => PciFullClass::MassStorage_SATA, - 0x0107 => PciFullClass::MassStorage_SerialSCSI, - 0x0108 => PciFullClass::MassStorage_NVM, - 0x0180 => PciFullClass::MassStorage_Other, - - 0x0200 => PciFullClass::Network_Ethernet, - 0x0201 => PciFullClass::Network_TokenRing, - 0x0202 => PciFullClass::Network_FDDI, - 0x0203 => PciFullClass::Network_ATM, - 0x0204 => PciFullClass::Network_ISDN, - 0x0205 => PciFullClass::Network_WorldFlip, - 0x0206 => PciFullClass::Network_PICMG, - 0x0207 => PciFullClass::Network_Infiniband, - 0x0208 => PciFullClass::Network_Fabric, - 0x0280 => PciFullClass::Network_Other, - - 0x0300 => PciFullClass::Display_VGA, - 0x0301 => PciFullClass::Display_XGA, - 0x0302 => PciFullClass::Display_3D, - 0x0380 => PciFullClass::Display_Other, - - 0x0400 => PciFullClass::Multimedia_Video, - 0x0401 => PciFullClass::Multimedia_AudioController, - 0x0402 => PciFullClass::Multimedia_Telephony, - 0x0403 => PciFullClass::Multimedia_AudioDevice, - 0x0480 => PciFullClass::Multimedia_Other, - - 0x0500 => PciFullClass::Memory_RAM, - 0x0501 => PciFullClass::Memory_Flash, - 0x0580 => PciFullClass::Memory_Other, - - 0x0600 => PciFullClass::Bridge_Host, - 0x0601 => PciFullClass::Bridge_ISA, - 0x0602 => PciFullClass::Bridge_EISA, - 0x0603 => PciFullClass::Bridge_MCA, - 0x0604 => PciFullClass::Bridge_PciToPci, - 0x0605 => PciFullClass::Bridge_PCMCIA, - 0x0606 => PciFullClass::Bridge_NuBus, - 0x0607 => PciFullClass::Bridge_CardBus, - 0x0608 => PciFullClass::Bridge_RACEway, - 0x0609 => PciFullClass::Bridge_PciToPciSemiTransparent, - 0x060A => PciFullClass::Bridge_InfinibandToPci, - 0x0680 => PciFullClass::Bridge_Other, - - _ => PciFullClass::Unknown, - } - } - - /// Convert a PciFullClass to its u16 representation - pub fn as_u16(&self) -> u16 { - *self as u16 - } -} - -impl From<u16> for PciFullClass { - /// Convert a u16 into the corresponding PciFullClass - fn from(n: u16) -> Self { - Self::from_u16(n) - } -} - -impl Display for PciFullClass { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, " Class: ")?; - - match self { - PciFullClass::Unclassified_NonVgaCompatible => write!(f, "\u{001A}LIGHTBLUE\u{001A}")?, - PciFullClass::Unclassified_VgaCompatible => write!(f, "\u{001A}LIGHTBLUE\u{001A}")?, - PciFullClass::MassStorage_ScsiBus => write!(f, "\u{001A}CYAN\u{001A}")?, - PciFullClass::MassStorage_IDE => write!(f, "\u{001A}CYAN\u{001A}")?, - PciFullClass::MassStorage_Floppy => write!(f, "\u{001A}CYAN\u{001A}")?, - PciFullClass::MassStorage_IpiBus => write!(f, "\u{001A}CYAN\u{001A}")?, - PciFullClass::MassStorage_RAID => write!(f, "\u{001A}CYAN\u{001A}")?, - PciFullClass::MassStorage_ATA => write!(f, "\u{001A}CYAN\u{001A}")?, - PciFullClass::MassStorage_SATA => write!(f, "\u{001A}CYAN\u{001A}")?, - PciFullClass::MassStorage_SerialSCSI => write!(f, "\u{001A}CYAN\u{001A}")?, - PciFullClass::MassStorage_NVM => write!(f, "\u{001A}CYAN\u{001A}")?, - PciFullClass::MassStorage_Other => write!(f, "\u{001A}CYAN\u{001A}")?, - PciFullClass::Network_Ethernet => write!(f, "\u{001A}MAGENTA\u{001A}")?, - PciFullClass::Network_TokenRing => write!(f, "\u{001A}MAGENTA\u{001A}")?, - PciFullClass::Network_FDDI => write!(f, "\u{001A}MAGENTA\u{001A}")?, - PciFullClass::Network_ATM => write!(f, "\u{001A}MAGENTA\u{001A}")?, - PciFullClass::Network_ISDN => write!(f, "\u{001A}MAGENTA\u{001A}")?, - PciFullClass::Network_WorldFlip => write!(f, "\u{001A}MAGENTA\u{001A}")?, - PciFullClass::Network_PICMG => write!(f, "\u{001A}MAGENTA\u{001A}")?, - PciFullClass::Network_Infiniband => write!(f, "\u{001A}MAGENTA\u{001A}")?, - PciFullClass::Network_Fabric => write!(f, "\u{001A}MAGENTA\u{001A}")?, - PciFullClass::Network_Other => write!(f, "\u{001A}MAGENTA\u{001A}")?, - PciFullClass::Display_VGA => write!(f, "\u{001A}YELLOW\u{001A}")?, - PciFullClass::Display_XGA => write!(f, "\u{001A}YELLOW\u{001A}")?, - PciFullClass::Display_3D => write!(f, "\u{001A}YELLOW\u{001A}")?, - PciFullClass::Display_Other => write!(f, "\u{001A}YELLOW\u{001A}")?, - PciFullClass::Multimedia_Video => write!(f, "\u{001A}LIGHTBLUE\u{001A}")?, - PciFullClass::Multimedia_AudioController => write!(f, "\u{001A}LIGHTBLUE\u{001A}")?, - PciFullClass::Multimedia_Telephony => write!(f, "\u{001A}LIGHTBLUE\u{001A}")?, - PciFullClass::Multimedia_AudioDevice => write!(f, "\u{001A}LIGHTBLUE\u{001A}")?, - PciFullClass::Multimedia_Other => write!(f, "\u{001A}LIGHTBLUE\u{001A}")?, - PciFullClass::Memory_RAM => write!(f, "\u{001A}BLUE\u{001A}")?, - PciFullClass::Memory_Flash => write!(f, "\u{001A}WHITE\u{001A}")?, - PciFullClass::Memory_Other => write!(f, "\u{001A}LIGHTGREY\u{001A}")?, - PciFullClass::Bridge_Host => write!(f, "\u{001A}GREEN\u{001A}")?, - PciFullClass::Bridge_ISA => write!(f, "\u{001A}GREEN\u{001A}")?, - PciFullClass::Bridge_EISA => write!(f, "\u{001A}GREEN\u{001A}")?, - PciFullClass::Bridge_MCA => write!(f, "\u{001A}GREEN\u{001A}")?, - PciFullClass::Bridge_PciToPci => write!(f, "\u{001A}GREEN\u{001A}")?, - PciFullClass::Bridge_PCMCIA => write!(f, "\u{001A}GREEN\u{001A}")?, - PciFullClass::Bridge_NuBus => write!(f, "\u{001A}GREEN\u{001A}")?, - PciFullClass::Bridge_CardBus => write!(f, "\u{001A}GREEN\u{001A}")?, - PciFullClass::Bridge_RACEway => write!(f, "\u{001A}GREEN\u{001A}")?, - PciFullClass::Bridge_PciToPciSemiTransparent => write!(f, "\u{001A}GREEN\u{001A}")?, - PciFullClass::Bridge_InfinibandToPci => write!(f, "\u{001A}GREEN\u{001A}")?, - PciFullClass::Bridge_Other => write!(f, "\u{001A}GREEN\u{001A}")?, - PciFullClass::Unknown => write!(f, "\u{001A}RED\u{001A}")?, - } - - write!( - f, - "{:?} ({:#06X})\u{001A}RESET\u{001A}", - self, - self.as_u16() - )?; - - Ok(()) - } -} diff --git a/ableos/src/devices/pci/device.rs b/ableos/src/devices/pci/device.rs deleted file mode 100644 index e9469ef..0000000 --- a/ableos/src/devices/pci/device.rs +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (c) 2022, able <abl3theabove@gmail.com> - * Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -use core::fmt; - -use x86_64::instructions::port::Port; - -use super::{ - vendors::Vendor::{self, *}, - PciClass, PciFullClass, -}; - -// FIXME: Unknown class -pub const S3_TRIO64V2: DeviceID = DeviceID::new(S3Inc, 0x8900); - -// MassStorage_IDE (0x0101) -pub const INTEL_PIIX3_IDE: DeviceID = DeviceID::new(IntelCorp, 0x7010); -pub const INTEL_PIIX4_IDE: DeviceID = DeviceID::new(IntelCorp, 0x7111); - -// Display_VGA (0x0300) -pub const VMWARE_SVGA2: DeviceID = DeviceID::new(VMWareInc, 0x0405); - -#[derive(Copy, Clone, Debug)] -/// A struct containing info about a PCI device. -pub struct PciDeviceInfo { - pub header_type: u8, - pub device: u8, - pub bus: u8, - pub device_id: DeviceID, - pub full_class: PciFullClass, - pub rev_id: u8, -} - -impl PciDeviceInfo { - /// Get the class of the PCI device as a PciClass - pub fn class(&self) -> PciClass { - (((self.full_class.as_u16() >> 8) & 0xFF) as u8).into() - } - - /// Get the bar, 0-indexed - pub fn bar(&self, bar: u8) -> u32 { - assert!(bar < 6); - unsafe { self.read(0, 0x10 + bar * 4) } - } - - /// Get the interrupt pin - pub fn interrupt_pin(&self) -> u8 { - let last_row = unsafe { self.read(0, 0x3C) }; - ((last_row >> 8) & 0xFF) as u8 - } - - /// Enable bus mastering. This allows the PCI device to do DMA - pub fn enable_bus_mastering(&self) { - let command = unsafe { self.read(0, 4) } | 1 << 2; - unsafe { self.write(0, 4, command) } - } - - /// Read from configuration space - pub unsafe fn read(&self, func: u8, offset: u8) -> u32 { - pci_config_read(self.bus, self.device, func, offset) - } - - /// Write to IO space - pub unsafe fn write(&self, func: u8, offset: u8, value: u32) { - pci_config_write(self.bus, self.device, func, offset, value) - } -} - -impl fmt::Display for PciDeviceInfo { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - let vendor_name = &self.device_id.vendor; - let device_id = &self.device_id.id; - writeln!( - f, - "Device: {} | Bus: 0x{:X} | Vendor: {} | Device ID: 0x{:X}", - self.device, self.bus, vendor_name, device_id, - )?; - writeln!(f, "{}", self.full_class)?; - writeln!(f, " Header type: 0x{:X}", self.header_type)?; - writeln!(f, " Revision ID: {}", self.rev_id)?; - // write!(f, " Supported functions: 0")?; - // for (i, b) in self.supported_fns.iter().enumerate().skip(1) { - // if *b { - // write!(f, ", {}", i)?; - // } - // } - // writeln!(f)?; - // write!(f, " BARs: [ ")?; - // for i in self.bars.iter() { - // if *i == 0 { - // write!(f, "0x0 ")?; - // } else { - // write!(f, "{:#010X} ", i)?; - // } - // } - // writeln!(f, "]")?; - // writeln!( - // f, - // " Interrupt line / pin: {} / {}", - // self.interrupt_line, self.interrupt_pin - // )?; - Ok(()) - } -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub struct DeviceID { - pub vendor: Vendor, - pub id: u16, -} - -impl DeviceID { - pub const fn new(vendor: Vendor, id: u16) -> Self { - Self { vendor, id } - } -} - -pub fn check_device(bus: u8, device: u8) -> Option<PciDeviceInfo> { - assert!(device < 32); - let (device_id, vendor_id) = get_ids(bus, device, 0); - if vendor_id == 0xFFFF { - // Device doesn't exist - return None; - } - - let reg2 = unsafe { pci_config_read(bus, device, 0, 0x8) }; - let class = ((reg2 >> 16) & 0x0000FFFF) as u16; - let pci_class = PciFullClass::from_u16(class); - let header_type = get_header_type(bus, device, 0); - - Some(PciDeviceInfo { - header_type, - device, - bus, - device_id: DeviceID { - vendor: vendor_id.into(), - id: device_id, - }, - full_class: pci_class, - rev_id: (reg2 & 0x000000FF) as u8, - }) -} - -unsafe fn pci_config_read(bus: u8, device: u8, func: u8, offset: u8) -> u32 { - let bus = bus as u32; - let device = device as u32; - let func = func as u32; - let offset = offset as u32; - // construct address param - let address = - ((bus << 16) | (device << 11) | (func << 8) | (offset & 0xfc) | 0x80000000) as u32; - - // write address - Port::new(0xCF8).write(address); - - // read data - Port::new(0xCFC).read() -} - -unsafe fn pci_config_write(bus: u8, device: u8, func: u8, offset: u8, value: u32) { - let bus = bus as u32; - let device = device as u32; - let func = func as u32; - let offset = offset as u32; - // construct address param - let address = - ((bus << 16) | (device << 11) | (func << 8) | (offset & 0xfc) | 0x80000000) as u32; - - // write address - Port::new(0xCF8).write(address); - - // write data - Port::new(0xCFC).write(value); -} - -fn get_header_type(bus: u8, device: u8, function: u8) -> u8 { - assert!(device < 32); - assert!(function < 8); - let res = unsafe { pci_config_read(bus, device, function, 0x0C) }; - ((res >> 16) & 0xFF) as u8 -} - -fn get_ids(bus: u8, device: u8, function: u8) -> (u16, u16) { - assert!(device < 32); - assert!(function < 8); - let res = unsafe { pci_config_read(bus, device, function, 0) }; - let dev_id = ((res >> 16) & 0xFFFF) as u16; - let vnd_id = (res & 0xFFFF) as u16; - (dev_id, vnd_id) -} diff --git a/ableos/src/devices/pci/ide.rs b/ableos/src/devices/pci/ide.rs deleted file mode 100644 index 9855964..0000000 --- a/ableos/src/devices/pci/ide.rs +++ /dev/null @@ -1,675 +0,0 @@ -/* - * Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -use core::num::TryFromIntError; - -// FIXME: platform agnostic-ify these -use x86_64::instructions::{interrupts, port::Port}; -use x86_64::structures::paging::{mapper::MapToError, Mapper, Page, PhysFrame, Size4KiB}; -use x86_64::structures::paging::{FrameAllocator, FrameDeallocator}; -use x86_64::VirtAddr; - -use crate::arch::memory::BootInfoFrameAllocator; -use crate::devices::pci::check_device; - -use super::PciDeviceInfo; - -// FIXME: un-hardcode these -const PRDT_START: u64 = 0xffff_ffff_0000_0000; -const BUFFER_START: u64 = 0xffff_ffff_0000_1000; - -/// ATA logical sector size, in bytes -const SECTOR_SIZE: u16 = 512; - -/// Bus Master IDE Command -const BMIC_OFFSET: u16 = 0; -/// Bus Master IDE Status -const BMIS_OFFSET: u16 = 2; -/// Bus Master IDE Descriptor Table Pointer -const BMIDTP_OFFSET: u16 = 4; - -/// Bus Master IDE Secondary Offset -const BMI_SECONDARY: u16 = 8; - -/// Primary command block offset -const PRIMARY_COMMAND: u16 = 0x01F0; - -/// Secondary command block offset -const SECONDARY_COMMAND: u16 = 0x0170; - -/// Data register offset -const DATA_OFFSET: u16 = 0; - -/// Sector count register offset -const SECCOUNT_OFFSET: u16 = 2; - -/// LBA0 register offset -const LBA0_OFFSET: u16 = 3; - -/// LBA1 register offset -const LBA1_OFFSET: u16 = 4; - -/// LBA2 register offset -const LBA2_OFFSET: u16 = 5; - -/// Drive/Head register offset -const DRIVE_HEAD_OFFSET: u16 = 6; - -/// Command/status register offset -const COMMAND_STATUS_OFFSET: u16 = 7; - -/// Secondary control block offset -const SECONDARY_CONTROL: u16 = 0x0374; - -/// Primary control block offset -const PRIMARY_CONTROL: u16 = 0x03F4; - -/// Alternative status offset -const ALT_STATUS_OFFSET: u16 = 2; - -/// ATA identification command -const CMD_IDENTIFY: u8 = 0xEC; - -/// ATA read using LBA28 DMA command -const CMD_READ_DMA: u8 = 0xC8; - -/// ATA write using LBA28 DMA command -const CMD_WRITE_DMA: u8 = 0xCA; - -/// ATA read using LBA48 DMA command -const CMD_READ_DMA_EXT: u8 = 0x25; - -/// ATA write using LBA48 DMA command -const CMD_WRITE_DMA_EXT: u8 = 0x35; -#[derive(Debug)] -pub struct PciIde { - device_info: PciDeviceInfo, - ide_devices: Vec<IdeDevice>, - prdt_frame: Option<PhysFrame>, - buffer_frames: Option<Vec<PhysFrame>>, - bmiba: u16, -} - -impl PciIde { - // FIXME: make this return a Result - pub fn new(bus: u8, device: u8) -> Option<Self> { - let device_info = check_device(bus, device)?; - device_info.enable_bus_mastering(); - let idetim = unsafe { device_info.read(0, 0x40) }; - trace!("idetim: {idetim:b}"); - // FIXME: enable the right bits in idetim (and sidetim) to use fast timings - - let mut ide_devices = Vec::with_capacity(4); - for ch in 0..2 { - let channel = if ch == 0 { - Channel::Primary - } else { - Channel::Secondary - }; - 'drive: for dr in 0..2 { - let drive = if dr == 0 { Drive::Master } else { Drive::Slave }; - - unsafe { - select_drive(drive, channel); - // FIXME: clear sector count and lba0, lba1, lba2 registers - let status = ata_send_command(CMD_IDENTIFY, channel); - if status == 0 { - continue; // If status = 0, no device - } - - loop { - let status = { - let addr = if channel.secondary() { - SECONDARY_COMMAND - } else { - PRIMARY_COMMAND - } + COMMAND_STATUS_OFFSET; - Port::<u8>::new(addr).read() - }; - - if status & 1 == 1 { - // if error (bit 0), device is not ATA - // FIXME: ATAPI devices - continue 'drive; - } - if !((status >> 7) & 1 == 1) && (status >> 3) & 1 == 1 { - // BSY cleared, DRQ set, everything is right - break; - } - } - - // Read identification space of device - let addr = if channel.secondary() { - SECONDARY_COMMAND - } else { - PRIMARY_COMMAND - } + DATA_OFFSET; - let mut buffer = [0_u8; 512]; - read_dword_buffer(addr, buffer.as_mut_ptr() as *mut _, 128); - // for (i, byte) in buffer.iter().enumerate() { - // if byte.is_ascii() { - // trace!("byte {i}: {byte:b}, ascii: {}", *byte as char); - // } else { - // trace!("byte {i}: {byte:b}"); - // } - // } - - if buffer[99] & 1 != 1 { - // FIXME: PIO mode support - error!("IDE drive {channel:?}/{drive:?} does not support DMA"); - continue; - } - - // FIXME: CHS support - let lba48 = (buffer[167] >> 2) & 1 == 1; - - let size = buffer[200] as u64 - | (buffer[201] as u64) << 8 - | (buffer[202] as u64) << 16 - | (buffer[203] as u64) << 24 - | (buffer[204] as u64) << 32 - | (buffer[205] as u64) << 40 - | (buffer[206] as u64) << 48 - | (buffer[207] as u64) << 54; - trace!("IDE drive {channel:?}/{drive:?} has {size} sectors"); - - ide_devices.push(IdeDevice { - channel, - drive, - size, - lba48_support: lba48, - }); - } - } - } - - let bmiba = device_info.bar(4) & 0xFFFFFFFC; - - Some(Self { - device_info, - ide_devices, - prdt_frame: None, - buffer_frames: None, - bmiba: bmiba.try_into().ok()?, - }) - } - - pub fn allocate_dma_frame( - &mut self, - mapper: &mut impl Mapper<Size4KiB>, - frame_allocator: &mut BootInfoFrameAllocator, - ) -> Result<(), MapToError<Size4KiB>> { - use x86_64::structures::paging::PageTableFlags as Flags; - - let prdt_frame = frame_allocator - .allocate_frame() - .ok_or(MapToError::FrameAllocationFailed)?; - - let buffer_frames = { - let mut frame = frame_allocator - .allocate_frame() - .ok_or(MapToError::FrameAllocationFailed)?; - while !frame.start_address().is_aligned(0x10000u64) { - unsafe { - frame_allocator.deallocate_frame(frame); - } - - frame = frame_allocator - .allocate_frame() - .ok_or(MapToError::FrameAllocationFailed)?; - } - - let mut frames = Vec::with_capacity(16); - frames.push(frame); - for _ in 0..15 { - let frame = frame_allocator - .allocate_frame() - .ok_or(MapToError::FrameAllocationFailed)?; - frames.push(frame); - } - - frames - }; - let flags = Flags::NO_CACHE | Flags::PRESENT | Flags::WRITABLE; - - unsafe { - mapper - .map_to( - Page::containing_address(VirtAddr::new(PRDT_START)), - prdt_frame, - flags, - frame_allocator, - )? - .flush(); - - for (i, frame) in buffer_frames.iter().enumerate() { - mapper - .map_to( - Page::containing_address(VirtAddr::new(BUFFER_START + i as u64 * 0x1000)), - *frame, - flags, - frame_allocator, - )? - .flush() - } - } - - self.prdt_frame = Some(prdt_frame); - self.buffer_frames = Some(buffer_frames); - Ok(()) - } - - pub fn read( - &mut self, - channel: Channel, - drive: Drive, - lba: u64, - sector_count: u16, - buffer: &mut Vec<u8>, - ) -> Result<(), TryFromIntError> { - let lba48_support = self - .ide_devices - .iter() - .find(|d| d.channel == channel && d.drive == drive) - .map(|d| d.lba48_support) - .unwrap(); // FIXME: make this an error - let lba48 = lba > 0xFFFFFFF && lba48_support; - - // FIXME: make this an error - assert!((lba48 && lba > 0xFFFFFFF) || (!lba48 && lba <= 0xFFFFFFF)); - - let byte_count = sector_count * SECTOR_SIZE; - - // prepare PRD table - let prd = PRDT_START as *mut PhysRegionDescriptor; - unsafe { - (*prd).data_buffer = self.buffer_frames.as_ref().unwrap()[0] - .start_address() - .as_u64() - .try_into()?; - (*prd).byte_count = byte_count; - // this is the end of table - (*prd).eot = 1 << 7; - // this byte is reserved, we should probably set it to 0 - (*prd)._0 = 0; - } - - unsafe { - self.load_prdt(channel); - self.stop(channel); - self.set_read(channel); - self.clear_bmi_status(channel); - select_drive(drive, channel); - set_lba(channel, lba, sector_count, lba48); - - if lba48 { - ata_send_command(CMD_READ_DMA_EXT, channel); - } else { - ata_send_command(CMD_READ_DMA, channel); - } - - self.start(channel); - } - - loop { - let status = unsafe { self.bmi_status(channel) }; - - // FIXME: error handling - - // Bit 2 (INT) set? - if (status >> 2) & 1 == 1 { - break; - } - } - - unsafe { - // Stop DMA - self.stop(channel); - - // Clear the interrupt bit - self.clear_bmi_status(channel); - } - - for i in 0..byte_count as u64 { - let addr = (BUFFER_START + i) as *mut u8; - buffer.push(unsafe { *addr }); - } - - Ok(()) - } - - pub fn write( - &mut self, - channel: Channel, - drive: Drive, - lba: u64, - data: &[u8], - ) -> Result<(), TryFromIntError> { - // FIXME: make this an error - assert!(data.len() % SECTOR_SIZE as usize == 0); - - let lba48_support = self - .ide_devices - .iter() - .find(|d| d.channel == channel && d.drive == drive) - .map(|d| d.lba48_support) - .unwrap(); // FIXME: make this an error - let lba48 = lba > 0xFFFFFFF && lba48_support; - - // FIXME: make this an error - assert!((lba48 && lba > 0xFFFFFFF) || (!lba48 && lba <= 0xFFFFFFF)); - - let byte_count = data.len() as u16; - let sector_count = byte_count / SECTOR_SIZE; - - // prepare PRD table - let prd = PRDT_START as *mut PhysRegionDescriptor; - unsafe { - (*prd).data_buffer = self.buffer_frames.as_ref().unwrap()[0] - .start_address() - .as_u64() - .try_into()?; - (*prd).byte_count = byte_count; - // this is the end of table - (*prd).eot = 1 << 7; - // this byte is reserved, we should probably set it to 0 - (*prd)._0 = 0; - } - - // copy the data over to the DMA buffer - for i in 0..byte_count { - let addr = (BUFFER_START + i as u64) as *mut u8; - unsafe { - *addr = *data.get(i as usize).unwrap_or(&0); - } - } - - unsafe { - self.load_prdt(channel); - self.stop(channel); - self.set_write(channel); - self.clear_bmi_status(channel); - select_drive(drive, channel); - set_lba(channel, lba, sector_count, lba48); - - if lba48 { - ata_send_command(CMD_WRITE_DMA_EXT, channel); - } else { - ata_send_command(CMD_WRITE_DMA, channel); - } - - self.start(channel); - } - - loop { - let status = unsafe { self.bmi_status(channel) }; - - // FIXME: error handling - - // Bit 2 (INT) set? - if (status >> 2) & 1 == 1 { - break; - } - } - - unsafe { - // Stop DMA - self.stop(channel); - - // Clear the interrupt bit - self.clear_bmi_status(channel); - } - - Ok(()) - } - - pub fn device_info(&self) -> PciDeviceInfo { - self.device_info - } - - unsafe fn load_prdt(&self, channel: Channel) { - let addr = if channel.secondary() { - BMI_SECONDARY - } else { - 0 - } + self.bmiba - + BMIDTP_OFFSET; - Port::<u32>::new(addr).write( - self.prdt_frame - .unwrap() - .start_address() - .as_u64() - .try_into() - .unwrap(), - ); - } - - unsafe fn start(&self, channel: Channel) { - let addr = if channel.secondary() { - BMI_SECONDARY - } else { - 0 - } + self.bmiba - + BMIC_OFFSET; - let mut port: Port<u8> = Port::new(addr); - let mut bmic = port.read(); - // start transfer - bmic |= 1; - // write the new bmic - port.write(bmic); - } - - unsafe fn stop(&self, channel: Channel) { - let addr = if channel.secondary() { - BMI_SECONDARY - } else { - 0 - } + self.bmiba - + BMIC_OFFSET; - let mut port: Port<u8> = Port::new(addr); - let mut bmic = port.read(); - // stop ongoing transfer - bmic &= !1; - // write the new bmic - port.write(bmic); - } - - unsafe fn set_read(&self, channel: Channel) { - let addr = if channel.secondary() { - BMI_SECONDARY - } else { - 0 - } + self.bmiba - + BMIC_OFFSET; - let mut port: Port<u8> = Port::new(addr); - let mut bmic = port.read(); - // mark bit 3 as 0 (read) - bmic &= !(1 << 3); - // write the new bmic - port.write(bmic); - } - - unsafe fn set_write(&self, channel: Channel) { - let addr = if channel.secondary() { - BMI_SECONDARY - } else { - 0 - } + self.bmiba - + BMIC_OFFSET; - let mut port: Port<u8> = Port::new(addr); - let mut bmic = port.read(); - // mark bit 3 as 1 (write) - bmic |= 1 << 3; - // write the new bmic - port.write(bmic); - } - - unsafe fn bmi_status(&self, channel: Channel) -> u8 { - let addr = if channel.secondary() { - BMI_SECONDARY - } else { - 0 - } + self.bmiba - + BMIS_OFFSET; - let mut port = Port::new(addr); - port.read() - } - - unsafe fn clear_bmi_status(&self, channel: Channel) { - let addr = if channel.secondary() { - BMI_SECONDARY - } else { - 0 - } + self.bmiba - + BMIS_OFFSET; - let mut port: Port<u8> = Port::new(addr); - let mut bmis = port.read(); - // write 1 to bits 1 (DMA error) and 2 (int status) which clears them - bmis |= 1 << 1 | 1 << 2; - // write the new bmis - port.write(bmis); - } -} - -unsafe fn select_drive(drive: Drive, channel: Channel) { - let addr = if channel.secondary() { - SECONDARY_COMMAND - } else { - PRIMARY_COMMAND - } + DRIVE_HEAD_OFFSET; - let mut port: Port<u8> = Port::new(addr); - // FIXME: CHS support - let drive_command = if drive.slave() { - // slave & LBA - 0b11110000 - } else { - // master & LBA - 0b11100000 - }; - - // write the new drive/head register - port.write(drive_command); - ata_delay(channel); -} - -/// Send ATA command and read status afterwards -unsafe fn ata_send_command(command: u8, channel: Channel) -> u8 { - let addr = if channel.secondary() { - SECONDARY_COMMAND - } else { - PRIMARY_COMMAND - } + COMMAND_STATUS_OFFSET; - let mut port = Port::new(addr); - port.write(command); - ata_delay(channel); - port.read() -} - -/// Read the alternate status register 14 times to create a ~420ns delay -unsafe fn ata_delay(channel: Channel) { - let addr = if channel.secondary() { - SECONDARY_CONTROL - } else { - PRIMARY_CONTROL - } + ALT_STATUS_OFFSET; - let mut port: Port<u8> = Port::new(addr); - for _ in 0..14 { - port.read(); - } -} - -/// Set LBA and sector count registers. sector_count of 0 means 65536 sectors -unsafe fn set_lba(channel: Channel, lba: u64, sector_count: u16, lba48: bool) { - let command_block = if channel.secondary() { - SECONDARY_COMMAND - } else { - PRIMARY_COMMAND - }; - - let mut seccount = Port::new(command_block + SECCOUNT_OFFSET); - let mut lba0 = Port::new(command_block + LBA0_OFFSET); - let mut lba1 = Port::new(command_block + LBA1_OFFSET); - let mut lba2 = Port::new(command_block + LBA2_OFFSET); - let mut head = Port::new(command_block + DRIVE_HEAD_OFFSET); - let head_value: u8 = head.read(); - - let lba_bytes = lba.to_le_bytes(); - let sector_count_bytes = sector_count.to_le_bytes(); - - // write the new LBA & sector count registers - // FIXME: CHS support - if lba48 { - seccount.write(sector_count_bytes[1]); - lba0.write(lba_bytes[3]); - lba1.write(lba_bytes[4]); - lba2.write(lba_bytes[5]); - } else { - head.write(head_value | (lba_bytes[3] & 0x0F)); - } - seccount.write(sector_count_bytes[0]); - lba0.write(lba_bytes[0]); - lba1.write(lba_bytes[1]); - lba2.write(lba_bytes[2]); -} - -unsafe fn read_dword_buffer(port: u16, buffer: *mut u32, mut count: u32) { - // FIXME: this assumes x86-64 - interrupts::without_interrupts(|| { - asm!(" - cld - repne - insd", - in("di") buffer, - in("dx") port, - inout("cx") count, - ) - }); -} - -#[derive(Debug)] -struct IdeDevice { - pub channel: Channel, - pub drive: Drive, - pub size: u64, // in sectors - pub lba48_support: bool, - // FIXME: model -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum Channel { - Primary, - Secondary, -} - -impl Channel { - fn secondary(&self) -> bool { - matches!(self, Self::Secondary) - } -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum Drive { - Master, - Slave, -} - -impl Drive { - fn slave(&self) -> bool { - matches!(self, Self::Slave) - } -} - -#[repr(C, packed)] -struct PhysRegionDescriptor { - /// Pointer to the data buffer - pub data_buffer: u32, - /// Byte count, 64K maximum per PRD transfer. 0 means 64K - pub byte_count: u16, - /// Reserved byte - pub _0: u8, - /// MSB marks end of transfer - pub eot: u8, -} diff --git a/ableos/src/devices/pci/mod.rs b/ableos/src/devices/pci/mod.rs deleted file mode 100644 index 7ab395e..0000000 --- a/ableos/src/devices/pci/mod.rs +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -pub mod class; -pub mod device; -pub mod vendors; - -// MassStorage_IDE (0x0101) -pub mod ide; - -use alloc::sync::Arc; -pub use class::*; -pub use device::*; -use lazy_static::lazy_static; -use spin::Mutex; -use x86_64::structures::paging::{Mapper, Size4KiB}; - -use crate::arch::memory::BootInfoFrameAllocator; - -// MassStorage_IDE (0x0101) -use self::ide::PciIde; - -lazy_static! { - pub static ref PCI_DEVICES: Mutex<Vec<Arc<Mutex<PciDevice>>>> = Default::default(); -} - -#[non_exhaustive] -#[derive(Debug)] -pub enum PciDevice { - Ide(PciIde), - // Variant so that we aren't about irrefutable if-let patterns - // FIXME: remove as soon as we have other variants - _0, -} - -/// Enumerate PCI devices and run initialisation routines on ones we support -pub fn init(mapper: &mut impl Mapper<Size4KiB>, frame_allocator: &mut BootInfoFrameAllocator) { - for bus in 0..=255 { - for device in 0..32 { - if let Some(device_info) = device::check_device(bus, device) { - trace!("{device_info}"); - println!("{device_info}"); - match device_info.device_id { - // FIXME: Unknown class - S3_TRIO64V2 => {} - - // MassStorage_IDE (0x0101) - ide_controller if device_info.full_class == PciFullClass::MassStorage_IDE => { - if !matches!(ide_controller, INTEL_PIIX3_IDE | INTEL_PIIX4_IDE) { - // not one of our tested IDE controllers, but - // we shouldn't have any problems - warn!("Unsupported PCI IDE controller device {device} on bus {bus}") - } - - let mut ide = PciIde::new(bus, device).unwrap(); - ide.allocate_dma_frame(mapper, frame_allocator).unwrap(); - let mut devices = PCI_DEVICES.lock(); - devices.push(Arc::new(Mutex::new(PciDevice::Ide(ide)))); - } - - // Display_VGA (0x0300) - VMWARE_SVGA2 => {} - _ => { - trace!("Unknown PCI device {device} on bus {bus}") - } - } - } - } - } -} diff --git a/ableos/src/devices/pci/vendors.rs b/ableos/src/devices/pci/vendors.rs deleted file mode 100644 index 1112a40..0000000 --- a/ableos/src/devices/pci/vendors.rs +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2022, able <abl3theabove@gmail.com> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -use core::fmt::Display; - -#[derive(PartialEq, Debug, Copy, Clone, Eq)] -#[repr(u16)] -pub enum Vendor { - ThreeDfxInteractiveInc = 0x121a, - ThreeDLabs = 0x3d3d, - AllianceSemiconductorCorp = 0x1142, - ARKLogicInc = 0xedd8, - ATITechnologiesInc = 0x1002, - AvanceLogicIncALI = 0x1005, - ChipsandTechnologies = 0x102c, - CirrusLogic = 0x1013, - Compaq = 0x0e11, - CyrixCorp = 0x1078, - DiamondMultimediaSystems = 0x1092, - DigitalEquipmentCorp = 0x1011, - Iit = 0x1061, - IntegratedMicroSolutionsInc = 0x10e0, - IntelCorp = 0x8086, - IntergraphicsSystems = 0x10ea, - MacronixInc = 0x10d9, - MatroxGraphicsInc = 0x102b, - MiroComputersProductsAG = 0x1031, - NationalSemiconductorCorp = 0x100b, - NeoMagicCorp = 0x10c8, - Number9ComputerCompany = 0x105d, - NVidiaCorporation = 0x10de, - NVidiaSgsthomson = 0x12d2, - OakTechnologyInc = 0x104e, - Qemu = 0x1234, - QuantumDesignsHKLtd = 0x1098, - Real3D = 0x003d, - Rendition = 0x1163, - S3Inc = 0x5333, - SierraSemiconductor = 0x10a8, - SiliconIntegratedSystemsSiS = 0x1039, - SiliconMotionInc = 0x126f, - STBSystemsInc = 0x10b4, - TexasInstruments = 0x104c, - ToshibaAmericaInfoSystems = 0x1179, - TridentMicrosystems = 0x1023, - TsengLabsInc = 0x100c, - TundraSemiconductorCorp = 0x10e3, - VIATechnologiesInc = 0x1106, - VirtIO = 0x1AF4, - VMWareInc = 0x15ad, - Weitek = 0x100e, - Unknown(u16), -} - -impl From<u16> for Vendor { - fn from(vendor_id: u16) -> Self { - use Vendor::*; - match vendor_id { - 0x121a => ThreeDfxInteractiveInc, - 0x3d3d => ThreeDLabs, - 0x1142 => AllianceSemiconductorCorp, - 0xedd8 => ARKLogicInc, - 0x1002 => ATITechnologiesInc, - 0x1005 => AvanceLogicIncALI, - 0x102c => ChipsandTechnologies, - 0x1013 => CirrusLogic, - 0x0e11 => Compaq, - 0x1078 => CyrixCorp, - 0x1092 => DiamondMultimediaSystems, - 0x1011 => DigitalEquipmentCorp, - 0x1061 => Iit, - 0x10e0 => IntegratedMicroSolutionsInc, - 0x8086 => IntelCorp, - 0x10ea => IntergraphicsSystems, - 0x10d9 => MacronixInc, - 0x102b => MatroxGraphicsInc, - 0x1031 => MiroComputersProductsAG, - 0x100b => NationalSemiconductorCorp, - 0x10c8 => NeoMagicCorp, - 0x105d => Number9ComputerCompany, - 0x10de => NVidiaCorporation, - 0x12d2 => NVidiaSgsthomson, - 0x104e => OakTechnologyInc, - 0x1234 => Qemu, - 0x1098 => QuantumDesignsHKLtd, - 0x003d => Real3D, - 0x1163 => Rendition, - 0x5333 => S3Inc, - 0x10a8 => SierraSemiconductor, - 0x1039 => SiliconIntegratedSystemsSiS, - 0x126f => SiliconMotionInc, - 0x10b4 => STBSystemsInc, - 0x104c => TexasInstruments, - 0x1179 => ToshibaAmericaInfoSystems, - 0x1023 => TridentMicrosystems, - 0x100c => TsengLabsInc, - 0x10e3 => TundraSemiconductorCorp, - 0x1106 => VIATechnologiesInc, - 0x1AF4 => VirtIO, - 0x15ad => VMWareInc, - 0x100e => Weitek, - id => Unknown(id), - } - } -} - -impl Into<u16> for Vendor { - fn into(self) -> u16 { - use Vendor::*; - match self { - ThreeDfxInteractiveInc => 0x121a, - ThreeDLabs => 0x3d3d, - AllianceSemiconductorCorp => 0x1142, - ARKLogicInc => 0xedd8, - ATITechnologiesInc => 0x1002, - AvanceLogicIncALI => 0x1005, - ChipsandTechnologies => 0x102c, - CirrusLogic => 0x1013, - Compaq => 0x0e11, - CyrixCorp => 0x1078, - DiamondMultimediaSystems => 0x1092, - DigitalEquipmentCorp => 0x1011, - Iit => 0x1061, - IntegratedMicroSolutionsInc => 0x10e0, - IntelCorp => 0x8086, - IntergraphicsSystems => 0x10ea, - MacronixInc => 0x10d9, - MatroxGraphicsInc => 0x102b, - MiroComputersProductsAG => 0x1031, - NationalSemiconductorCorp => 0x100b, - NeoMagicCorp => 0x10c8, - Number9ComputerCompany => 0x105d, - NVidiaCorporation => 0x10de, - NVidiaSgsthomson => 0x12d2, - OakTechnologyInc => 0x104e, - Qemu => 0x1234, - QuantumDesignsHKLtd => 0x1098, - Real3D => 0x003d, - Rendition => 0x1163, - S3Inc => 0x5333, - SierraSemiconductor => 0x10a8, - SiliconIntegratedSystemsSiS => 0x1039, - SiliconMotionInc => 0x126f, - STBSystemsInc => 0x10b4, - TexasInstruments => 0x104c, - ToshibaAmericaInfoSystems => 0x1179, - TridentMicrosystems => 0x1023, - TsengLabsInc => 0x100c, - TundraSemiconductorCorp => 0x10e3, - VIATechnologiesInc => 0x1106, - VirtIO => 0x1AF4, - VMWareInc => 0x15ad, - Weitek => 0x100e, - Unknown(id) => id, - } - } -} - -impl Display for Vendor { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - use Vendor::*; - - match self { - Qemu => write!(f, "{}", "\u{001A}PINK\u{001A}QEMU (0x1234)"), - VirtIO => write!(f, "{}", "\u{001A}PINK\u{001A}VirtIO (0x1AF4)"), - VMWareInc => write!(f, "{}", "\u{001A}PINK\u{001A}VMWARE (0x15AD)"), - S3Inc => write!(f, "{}", "\u{001A}YELLOW\u{001A}S3 Incorporated (0x5333)"), - IntelCorp => write!(f, "{}", "\u{001A}BLUE\u{001A}Intel Corp. (0x8086)"), - ATITechnologiesInc => write!(f, "{}", "\u{001A}RED\u{001A}ATI (0x1002)"), - Unknown(id) => write!(f, "\u{001A}RED\u{001A}Unknown ({:#6})", id), - other => write!(f, "{other:?}"), - }?; - - write!(f, "\u{001A}RESET\u{001A}")?; - Ok(()) - } -} diff --git a/ableos/src/driver_traits/graphics.rs b/ableos/src/driver_traits/graphics.rs deleted file mode 100644 index 8d171e2..0000000 --- a/ableos/src/driver_traits/graphics.rs +++ /dev/null @@ -1,44 +0,0 @@ -#![allow(unused)] - -pub const REFRESH_RATE: u8 = 60; - -pub type RefreshRate = u8; -pub type Resolution = (usize, usize); -pub type Point = (GCoord, GCoord); -pub type GCoord = usize; - -pub enum GModes { - Vga800x600, - Custom(u16, u16), -} - -// TODO remap to a bitmasked u32 -// REASON: More effecient memory wise so less overhead on the wasm memory -// Current: u32+u32+u32 -// Proposed: u32 with bitmaps -pub struct Rgb { - pub r: u32, - pub g: u32, - pub b: u32, -} - -impl Rgb { - fn to_vga_color() { - todo!(); - } -} - -pub struct FrameBuffer; -pub trait Graphics { - fn put_line(coords_start: Point, coords_end: Point, thickness: u32, color: Rgb); - fn put_rect(coords_start: Point, coords_end: Point, color: Rgb); - fn put_circle(coords: Point, radius: u32); - fn put_pixel(coords: Point, color: Rgb); - fn put_triangle(coords_1: Point, coords_2: Point, coords_3: Point, thickness: u32, color: Rgb); - fn paint_cursor(coords: Point); - fn hide_cursor(); - fn show_cursor(); - /// Actually move the double buffer to the single buffer and "update" the screen - fn draw(); - fn clear(); -} diff --git a/ableos/src/driver_traits/mod.rs b/ableos/src/driver_traits/mod.rs deleted file mode 100644 index b832ebf..0000000 --- a/ableos/src/driver_traits/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod graphics; -pub mod serial; diff --git a/ableos/src/driver_traits/mouse.rs b/ableos/src/driver_traits/mouse.rs deleted file mode 100644 index 89e0f07..0000000 --- a/ableos/src/driver_traits/mouse.rs +++ /dev/null @@ -1,16 +0,0 @@ -// TODO: Bitmasking -pub enum Mouse { - Button1, - Button2, - Button3, - Button4, - Button5, - X(i8), - Y(i8), - Wheel(i8), -} - -pub trait PS2Mouse { - fn movement(); - fn button(); -} diff --git a/ableos/src/driver_traits/serial.rs b/ableos/src/driver_traits/serial.rs deleted file mode 100644 index 336442e..0000000 --- a/ableos/src/driver_traits/serial.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::device_interface::CharacterDevice; - -pub struct Serial { - pub base: usize, -} - -impl CharacterDevice for Serial { - fn can_read(&self) -> bool { - true - } - - fn can_write(&self) -> bool { - true - } - - fn read_char(&mut self) -> Option<char> { - todo!() - } - - fn write_char(&mut self, _c: char) -> bool { - todo!() - } - - fn reset(&mut self) { - todo!() - } - - fn initialize(&mut self) -> bool { - false - } -} - -pub fn new_serial_test() { - let mut serial = Serial { base: 0x3F8 }; - serial.initialize(); - serial.write_char('a'); -} diff --git a/ableos/src/experiments/EXPLAIN.md b/ableos/src/experiments/EXPLAIN.md deleted file mode 100644 index 8dd9fe8..0000000 --- a/ableos/src/experiments/EXPLAIN.md +++ /dev/null @@ -1 +0,0 @@ -Anything in experiments is heavily unstable and likely to change diff --git a/ableos/src/experiments/absi.rs b/ableos/src/experiments/absi.rs deleted file mode 100644 index 6c63f81..0000000 --- a/ableos/src/experiments/absi.rs +++ /dev/null @@ -1,107 +0,0 @@ -use logos::{Lexer, Logos}; - -// TODO improve tokenizer/parser -pub fn colorify(eval: &str) { - let y = eval.split('$'); - for z in y { - match z { - "BLACK" => { - // set_vga_color(Color::Black, Color::Black); - } - "RED" => { - // set_vga_color(Color::Red, Color::Black); - } - "GREEN" => { - // set_vga_color(Color::Green, Color::Black); - } - "BLUE" => { - // set_vga_color(Color::Blue, Color::Black); - } - "CYAN" => { - // set_vga_color(Color::Cyan, Color::Black); - } - "MAGENTA" => { - // set_vga_color(Color::Magenta, Color::Black); - } - "BROWN" => { - // set_vga_color(Color::Brown, Color::Black); - } - "LIGHTGRAY" => { - // set_vga_color(Color::LightGray, Color::Black); - } - "DARKGRAY" => { - // set_vga_color(Color::DarkGray, Color::Black); - } - "LIGHTBLUE" => { - // set_vga_color(Color::LightBlue, Color::Black); - } - "LIGHTGREEN" => { - // set_vga_color(Color::LightGreen, Color::Black); - } - "LIGHTCYAN" => { - // set_vga_color(Color::LightCyan, Color::Black); - } - "LIGHTRED" => { - // set_vga_color(Color::LightRed, Color::Black); - } - "PINK" => { - // set_vga_color(Color::Pink, Color::Black); - } - "YELLOW" => { - // set_vga_color(Color::Yellow, Color::Black); - } - "WHITE" => { - // set_vga_color(Color::White, Color::Black); - } - "RESET" => { - // set_vga_color(Color::White, Color::Black); - } - _elk => { - // kprint!("{}", elk); - } - } - } -} - -#[derive(Logos, Debug, PartialEq)] -pub enum Token { - // Hex(u32), - #[regex(r"\$RED\$")] - Red, - - #[regex(r"\$RESET\$")] - Reset, - - #[regex("[a-zA-Z!@#$%^&*\">()\n ]+", parse_text, priority = 2)] - Text(String), - - #[error] - #[regex(r"[ \t\n\f]+", logos::skip)] - Error, -} - -pub fn colorify_2(eval: &str) { - let lexer = Token::lexer(eval); - for token in lexer { - use Token::*; - match token { - Red => { - // set_vga_color(Color::Red, Color::Black); - } - Reset => { - // set_vga_color(Color::White, Color::Black); - } - Text(_text) => { - // kprint!("{}", text); - } - err => { - error!("Error parsing {:?}", err); - } - } - } -} - -fn parse_text(lex: &mut Lexer<Token>) -> Option<String> { - let slice = lex.slice(); - Some(String::from(slice)) -} diff --git a/ableos/src/experiments/banner.txt b/ableos/src/experiments/banner.txt deleted file mode 100644 index fdea73b..0000000 --- a/ableos/src/experiments/banner.txt +++ /dev/null @@ -1,7 +0,0 @@ - ##### ##### - ## ##### # ###### ## ## # # - # # # # # # # # # -# # ##### # ##### # # ##### -###### # # # # # # # -# # # # # # ## ## # # -# # ##### ###### ###### ##### ##### diff --git a/ableos/src/experiments/clip.rs b/ableos/src/experiments/clip.rs deleted file mode 100644 index 9dd3eb7..0000000 --- a/ableos/src/experiments/clip.rs +++ /dev/null @@ -1,53 +0,0 @@ -use alloc::{string::String, vec, vec::Vec}; - -pub static CLIPBOARD: spin::Mutex<Clipboard> = spin::Mutex::new(Clipboard::new()); - -#[derive(Debug)] -pub enum Mime { - None, - Text(String), -} - -// ctrl+v paste but not pop and pastes -// ctrl+shift+v pops from the stack and pastes -// ctrl+c pushes to the stack -// ctrl+shift+< move stack pointer left -// ctrl+shift+> move stack pointer right - -pub struct Clipboard { - pub index: usize, - pub pages: Vec<Mime>, -} - -impl Clipboard { - pub const fn new() -> Clipboard { - Clipboard { - index: 0, - pages: vec![], - } - } - - pub fn clear(&mut self) { - self.pages = vec![]; - } - - pub fn set_index(&mut self, index_new: usize) { - self.index = index_new; - } - - pub fn clip_end(&mut self) { - self.index = 0; - } - - pub fn clip_home(&mut self) { - self.index = self.pages.len(); - } - - pub fn copy(&mut self, copy_mime: Mime) { - self.pages.push(copy_mime); - } - - pub fn paste(&mut self) -> &Mime { - &self.pages[self.index] as _ - } -} diff --git a/ableos/src/experiments/file.rs b/ableos/src/experiments/file.rs deleted file mode 100644 index bb0a5d3..0000000 --- a/ableos/src/experiments/file.rs +++ /dev/null @@ -1,22 +0,0 @@ -struct Permissions { - write_files: bool, - read_files: bool, - execute_files: bool, - // Every other user is part of global - global_write_files: bool, - global_read_files: bool, - global_execute_files: bool, -} - -pub struct File { - owner: u8, - permissions: Permissions, - data: Vec<u8>, -} - -pub struct Folder { - owner: u8, - permissions: Permissions, - folders: Vec<Folder>, - files: Vec<File>, -} diff --git a/ableos/src/experiments/filesystem.txt b/ableos/src/experiments/filesystem.txt deleted file mode 100644 index f1fe2cd..0000000 --- a/ableos/src/experiments/filesystem.txt +++ /dev/null @@ -1,15 +0,0 @@ -<user>/home/app1 -<user>/conf/app1 -<user>/apps/app1 - -file:app1 -conf:app1 -apps:app1 -// Discouraged -raw: - -/<user>/<protocol>/app1 -protocol.toml - - -hi = "" diff --git a/ableos/src/experiments/futex.rs b/ableos/src/experiments/futex.rs deleted file mode 100644 index 3252d6f..0000000 --- a/ableos/src/experiments/futex.rs +++ /dev/null @@ -1,57 +0,0 @@ -use core::time::Duration; - -pub struct AtomicU32(u32); -impl AtomicU32 { - //if v != current value - pub fn wait(&self, _v: u32) { - todo!(); - } - - pub fn wait_timeout(&self, _v: u32, _timeout: Duration) -> bool { - todo!(); - } - pub fn wake_single(&self) { - todo!(); - } - pub fn wake_all(&self) { - todo!(); - } -} -/* -// SUPER HANDWAVEY -// YOU WILL NEED LOCKING THAT I DIDNT WRITE OUT (you == zuurr#9735) - -// all the red is by design -pub fn futex_wait(atom: &AtomicU32, value: usize, current_thread: ThreadID) { - let address = atomic as *const _ as usize; - let waiters = waiters_for(address); // Hold lock - waiters.add(current_thread); - if self.load() == value { - current_thread.sleep(); - } else { - waiters.remove(current_thread); - } -} - -pub fn futex_wake(atom: &AtomicU32, threads_to_wake: usize) { - let address = atomic as *const _ as usize; - let waiters = waiters_for(address); - for waiting_thread in waiters.into_iter().take(threads_to_wake) { - waiting_thread.wake() - } -} -*/ - -struct FutexWaitlist { - address: u8, - // data: Vec<ThreadID>, -} - -impl FutexWaitlist { - pub fn remove(&mut self) { - todo!(); - } - pub fn add(&mut self) { - todo!(); - } -} diff --git a/ableos/src/experiments/kinfo.rs b/ableos/src/experiments/kinfo.rs deleted file mode 100644 index fdacbb2..0000000 --- a/ableos/src/experiments/kinfo.rs +++ /dev/null @@ -1,75 +0,0 @@ -use super::systeminfo::SystemMemory; -use crate::arch::drivers::sysinfo::master; -use core::fmt::Display; -use kernel::allocator::ALLOCATOR; -use versioning::Version; -use x86_64::instructions::interrupts::{disable, enable}; - -pub enum CpuType { - RiscV(String), - X86_64(String), -} -impl Display for CpuType { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!( - f, - "{}", - match self { - CpuType::RiscV(s) => s, - CpuType::X86_64(s) => s, - } - ) - } -} - -/// simple info you would want to know in a neofetch like program -pub struct KernelInfo { - // os: String, - // host: String, - pub kernel_version: Version, - pub cpu: CpuType, - // gpu: String, - pub memory: SystemMemory, -} - -impl KernelInfo { - pub fn get() -> KernelInfo { - disable(); - let allocator = ALLOCATOR.lock(); - let total = allocator.size(); - let used = allocator.used(); - enable(); - - let cpu = CpuType::X86_64(master().unwrap().brand_string().unwrap().to_string()); - KernelInfo { - kernel_version: Version { - major: 0, - minor: 0, - patch: 0, - }, - cpu, - memory: SystemMemory { total, used }, - } - } -} - -impl Display for KernelInfo { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!( - f, - " - OS: AbleOS - Host: {{}} - Kernel: {}.{}.{} - CPU: {} - Memory: {}/{} - ", - self.kernel_version.major, - self.kernel_version.minor, - self.kernel_version.patch, - self.cpu, - self.memory.used, - self.memory.total - ) - } -} diff --git a/ableos/src/experiments/mail.rs b/ableos/src/experiments/mail.rs deleted file mode 100644 index 06bdfda..0000000 --- a/ableos/src/experiments/mail.rs +++ /dev/null @@ -1,113 +0,0 @@ -#![allow(dead_code)] -// TODO: Evaluate variable sized mailboxes - -pub struct MailBoxes { - flags: u8, - mailboxes: [u64; 4], -} - -impl MailBoxes { - pub fn new() -> Self { - Self { - flags: 0b0000_0000, - mailboxes: [0; 4], - } - } - - pub fn reset(&mut self) { - self.flags = 0b0000_0000; - self.mailboxes = [0; 4]; - } - - pub fn set_mailbox(&mut self, mailbox_num: u8, mailbox_data: u64) { - if let 0..=3 = mailbox_num { - self.mailboxes[mailbox_num as usize] = mailbox_data - } - } - - pub fn set_flag(&mut self, flag_num: u8) { - match flag_num { - 0 => { - self.flags |= 0b0000_0001; - } - 1 => { - self.flags |= 0b0000_0010; - } - 2 => { - self.flags |= 0b0000_0100; - } - 3 => { - self.flags |= 0b0000_1000; - } - 4 => { - self.flags |= 0b0001_0000; - } - 5 => { - self.flags |= 0b0010_0000; - } - 6 => { - self.flags |= 0b0100_0000; - } - 7 => { - self.flags |= 0b1000_0000; - } - - _ => {} - } - } - pub fn dump_flags(&self) { - trace!( - "Flag 0: {:08b} | {}", - self.flags & 0b0000_0001, - self.flags & 0b0000_0001 - ); - - trace!( - "Flag 1: {:08b} | {}", - self.flags & 0b0000_0010, - self.flags >> 1 & 0b0000_0001 - ); - - trace!( - "Flag 2: {:08b} | {}", - self.flags & 0b0000_0100, - self.flags >> 2 & 0b0000_0001 - ); - - trace!( - "Flag 3: {:08b} | {}", - self.flags & 0b0000_1000, - self.flags >> 3 & 0b0000_0001 - ); - - trace!( - "Flag 4: {:08b} | {}", - self.flags & 0b0001_0000, - self.flags >> 4 & 0b0000_0001 - ); - - trace!( - "Flag 5: {:08b} | {}", - self.flags & 0b0010_0000, - self.flags >> 5 & 0b0000_0001 - ); - - trace!( - "Flag 6: {:08b} | {}", - self.flags & 0b0100_0000, - self.flags >> 6 & 0b0000_0001 - ); - - trace!( - "Flag 7: {:08b} | {}", - self.flags & 0b1000_0000, - self.flags >> 7 & 0b0000_0001 - ); - } -} - -impl Default for MailBoxes { - fn default() -> Self { - Self::new() - } -} diff --git a/ableos/src/experiments/mod.rs b/ableos/src/experiments/mod.rs deleted file mode 100644 index 134b35d..0000000 --- a/ableos/src/experiments/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![allow(dead_code)] - -pub mod absi; -pub mod clip; -pub mod futex; -pub mod kinfo; -pub mod mail; -pub mod server; -pub mod systeminfo; -pub mod virtual_memory; -pub mod y_compositor; - -pub const BANNER: &str = include_str!("banner.txt"); diff --git a/ableos/src/experiments/notification.rs b/ableos/src/experiments/notification.rs deleted file mode 100644 index fc49825..0000000 --- a/ableos/src/experiments/notification.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub type thumbnail = u8; - -pub struct Notification { - thumbnail: thumbnail, - text_body: String, - time: u64, -} diff --git a/ableos/src/experiments/pkg.rs b/ableos/src/experiments/pkg.rs deleted file mode 100644 index a0f9512..0000000 --- a/ableos/src/experiments/pkg.rs +++ /dev/null @@ -1,45 +0,0 @@ -use crate::experiments::kinfo::SemanticVersion; - -// Scuffed -pub type Hash = u8; -pub type PackageName = String; - -pub struct MetaPackage { - pub name: u8, - pub version: SemanticVersion, - pub authors: [u8; 8], - pub support_email: u8, - pub hash: Hash, -} - -impl MetaPackage { - pub fn new() -> Self { - Self { - name: 0, - version: SemanticVersion { - major: 0, - minor: 0, - patch: 0, - }, - authors: [0; 8], - support_email: 8, - hash: 0, - } - } - - fn validate_hash(&self) {} -} - -impl core::fmt::Display { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - write!( - f, - "Packname: {} -Version: {} -Authors: {:?} -Support Email: {} -Hash: {}", - self.name, self.version, self.authors, self.support_email, self.hash - ) - } -} diff --git a/ableos/src/experiments/server.rs b/ableos/src/experiments/server.rs deleted file mode 100644 index 4e8f217..0000000 --- a/ableos/src/experiments/server.rs +++ /dev/null @@ -1,13 +0,0 @@ -pub trait Server { - /// Initialize the server and return a number - fn initialize() -> u32; - - /// kill the server - fn kill() -> bool; - - // put data in the servers outbox - fn send(); - - // put data in the servers inbox and notify it - fn recieve(); -} diff --git a/ableos/src/experiments/syscalls.md b/ableos/src/experiments/syscalls.md deleted file mode 100644 index b5e654a..0000000 --- a/ableos/src/experiments/syscalls.md +++ /dev/null @@ -1,39 +0,0 @@ - -| low \\ high | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | -| ----------- | ------------------- | ------------------------ | ------------------------------------------------------------------------------------------ | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | -| 0 | **kill** | <sub>reserved</sub> | **sleep** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| 1 | **stdout_reset** | <sub>reserved</sub> | **sleep_until** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| 2 | **stdin** | <sub>reserved</sub> | [**nanosleep**](https://www.reddit.com/r/anime/comments/e7sg7g/nichijou_trouble_sleeping/) | **aes_encrypt** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| 3 | **stdout** | <sub>reserved</sub> | **nanosleep_until** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| 4 | **stdin_get_title** | <sub>reserved</sub> | **get_time** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| 5 | **stdin_set_title** | <sub>reserved</sub> | **set_time** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| 6 | **get_pid** | **make_directory** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| 7 | **pinfo** | **delete_directory** | **socket_bind** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| 8 | <sub>reserved</sub> | **rename_directory** | **socket_connect** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| 9 | <sub>reserved</sub> | **set_directory_access** | **socket_disconnect** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| A | **set_priority** | **make_file** | **socket_send** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| B | **get_priority** | **delete_file** | **socket_receive** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| C | **get_hostname** | **rename_file** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| D | **set_hostname** | **set_file_access** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| E | <sub>reserved</sub> | **file_read** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| F | <sub>reserved</sub> | **file_write** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | - -| low \\ high | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 1A | 1B | 1C | 1D | 1E | 1F | -| ----------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | -| 0 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| 1 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| 2 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| 3 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| 4 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| 5 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| 6 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| 7 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| 8 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| 9 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| A | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| B | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| C | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| D | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| E | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | -| F | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | - diff --git a/ableos/src/experiments/systeminfo.rs b/ableos/src/experiments/systeminfo.rs deleted file mode 100644 index 06fda4e..0000000 --- a/ableos/src/experiments/systeminfo.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Can be standardized -// NOTE: move the file to the src/ dir - -pub const KERNEL_VERSION: &str = env!("CARGO_PKG_VERSION"); -#[cfg(debug_assertions)] -/// A constant to check if the kernel is in debug mode -pub const RELEASE_TYPE: &str = "debug"; -#[cfg(not(debug_assertions))] -/// A constant to check if the kernel is in release mode -pub const RELEASE_TYPE: &str = "release"; - -pub struct SystemMemory { - pub used: usize, - pub total: usize, -} - -impl core::fmt::Display for SystemMemory { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - write!(f, "{} Bytes / {} Bytes", self.used, self.total) - } -} diff --git a/ableos/src/experiments/user.rs b/ableos/src/experiments/user.rs deleted file mode 100644 index 645a57a..0000000 --- a/ableos/src/experiments/user.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub struct User { - id: u8, - clipboard: Clipboard, -} diff --git a/ableos/src/experiments/virtual_memory.rs b/ableos/src/experiments/virtual_memory.rs deleted file mode 100644 index 7cbf37a..0000000 --- a/ableos/src/experiments/virtual_memory.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![allow(dead_code)] - -pub struct Scheduler { - executables: usize, -} - -pub struct RunQueue; diff --git a/ableos/src/experiments/y_compositor/compositor.rs b/ableos/src/experiments/y_compositor/compositor.rs deleted file mode 100644 index ee5e63b..0000000 --- a/ableos/src/experiments/y_compositor/compositor.rs +++ /dev/null @@ -1,12 +0,0 @@ -pub struct Compositor; -impl Compositor { - pub fn new() -> Self { - Self - } -} - -impl Default for Compositor { - fn default() -> Self { - Self::new() - } -} diff --git a/ableos/src/experiments/y_compositor/mod.rs b/ableos/src/experiments/y_compositor/mod.rs deleted file mode 100644 index 32bd838..0000000 --- a/ableos/src/experiments/y_compositor/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -//! -pub mod compositor; -pub mod window; diff --git a/ableos/src/experiments/y_compositor/window.rs b/ableos/src/experiments/y_compositor/window.rs deleted file mode 100644 index 1c8d56f..0000000 --- a/ableos/src/experiments/y_compositor/window.rs +++ /dev/null @@ -1,37 +0,0 @@ -// use crate::driver_traits::graphics::Point; - -pub type MenuBar = Vec<MenuOption>; - -pub struct MenuOption { - symbol: char, -} - -pub struct Window { - title: String, - // position: Point, - fullscreen: bool, -} - -// all of these should return a result -impl Window { - pub fn new(title: String, /*position: Point,*/ fullscreen: bool) -> Self { - Self { - title, - // position, - fullscreen, - } - } - - pub fn fullscreen(&mut self) { - self.fullscreen = true; - } - pub fn revert_fullscreen(&mut self) { - self.fullscreen = false; - } - pub fn set_title(&mut self) { - todo!(); - } - pub fn set_position(&mut self /*pos: Point*/) { - // self.position = pos; - } -} diff --git a/ableos/src/experiments/y_compositor/wm.rs b/ableos/src/experiments/y_compositor/wm.rs deleted file mode 100644 index e69de29..0000000 diff --git a/ableos/src/filesystem/errors.rs b/ableos/src/filesystem/errors.rs deleted file mode 100644 index 84c3e6c..0000000 --- a/ableos/src/filesystem/errors.rs +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -use core::fmt::Display; - -#[derive(Copy, Clone, Debug)] -pub enum FsError { - EndOfFile, - InodeNotFound, - InvalidDevice, - InvalidPath, - IsDirectory, - NotAbsolute, - NotADirectory, - NotFound, - Recursion, - UnsupportedOperation, -} -impl Display for FsError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "{:?}", self) - } -} - -impl Into<FsError> for ext2::error::Error { - fn into(self) -> FsError { - match self { - ext2::error::Error::Other(_) => todo!(), - ext2::error::Error::BadMagic { magic: _ } => todo!(), - ext2::error::Error::OutOfBounds { index: _ } => todo!(), - ext2::error::Error::AddressOutOfBounds { - sector: _, - offset: _, - size: _, - } => todo!(), - ext2::error::Error::BadBlockGroupCount { - by_blocks: _, - by_inodes: _, - } => todo!(), - ext2::error::Error::InodeNotFound { inode: _ } => FsError::InodeNotFound, - ext2::error::Error::NotADirectory { inode: _, name: _ } => FsError::NotADirectory, - ext2::error::Error::NotAbsolute { name: _ } => todo!(), - ext2::error::Error::NotFound { name: _ } => FsError::NotFound, - } - } -} diff --git a/ableos/src/filesystem/ext2.rs b/ableos/src/filesystem/ext2.rs deleted file mode 100644 index 76dc14f..0000000 --- a/ableos/src/filesystem/ext2.rs +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -use alloc::sync::{Arc, Weak}; -use ext2::fs::{sync::Synced, Ext2}; -use ext2::sector::SectorSize; -use ext2::sys::inode::TypePerm; -use ext2::volume::Volume; - -use crate::handle::{Handle, HandleResource}; - -use super::errors::FsError; -use super::vfs::{DirectoryEntry, FsFlags, VirtualFileSystem, VFS}; -use super::{FsNode, FsResult as Result, StorageDevice}; - -pub struct Ext2StorageDevice<S, V> -where - S: SectorSize, - V: Volume<u8, S>, -{ - fs: Synced<Ext2<S, V>>, - device_handle: Handle, - root_handle: Handle, -} - -impl<S, V> Ext2StorageDevice<S, V> -where - S: SectorSize, - V: Volume<u8, S>, -{ - pub fn new(volume: V) -> Result<Self> { - let fs = Synced::new(volume).map_err(|e| e.into())?; - let root_inode = fs.root_inode(); - let device_handle = Handle::new(HandleResource::StorageDevice); - let root = Arc::new(FsNode::new( - FsFlags::DIRECTORY, - root_inode.size(), - 2, - device_handle, - Weak::new(), - )); - - let mut vfs = VFS.lock(); - let root_handle = vfs.add_fs_node(root.clone()); - - Ok(Self { - fs, - device_handle, - root_handle, - }) - } -} - -impl<S, V> StorageDevice for Ext2StorageDevice<S, V> -where - S: SectorSize + Send, - V: Volume<u8, S> + Send, -{ - fn read(&self, node: &FsNode, offset: usize, size: usize, buffer: &mut Vec<u8>) -> Result<()> { - let inode = self - .fs - .inode_nth(node.inode() as usize) - .ok_or_else(|| FsError::InodeNotFound)?; - - // FIXME: I don't really know how Ext2 works, so for now we don't - // support non-zero offsets and buffer sizes that don't match - // the file length. We always read the whole file. - if offset > 0 || size != inode.size() { - Err(FsError::UnsupportedOperation)?; - } - - inode.read_to_end(buffer).map_err(|e| e.into())?; - Ok(()) - } - - fn write(&self, _node: &FsNode, _offset: usize, _buffer: &[u8]) -> Result<()> { - todo!() - } - - fn read_dir(&self, node: &FsNode, index: usize) -> Result<DirectoryEntry> { - let inode = self - .fs - .inode_nth(node.inode() as usize) - .ok_or_else(|| FsError::InodeNotFound)?; - let mut dir = inode.directory().ok_or_else(|| FsError::NotADirectory)?; - let entry = dir - .nth(index) - .ok_or_else(|| FsError::InodeNotFound)? - .map_err(|e| e.into())?; - let entry_inode = self - .fs - .inode_nth(entry.inode) - .ok_or_else(|| FsError::InodeNotFound)?; - let mut vfs = VFS.lock(); - let entry_node_handle = vfs - .find_fs_node(entry.inode, self.device_handle) - .unwrap_or_else(|| { - vfs.add_fs_node(Arc::new(FsNode::new( - ext2_type_to_fs_flags(entry_inode.type_perm()), - entry_inode.size(), - entry.inode, - self.device_handle, - Weak::new(), - ))) - }); - - Ok(DirectoryEntry::new( - entry.file_name_string(), - entry_node_handle, - )) - } - - fn find_dir(&self, vfs: &mut VirtualFileSystem, node: &FsNode, name: &str) -> Result<Handle> { - let inode = self - .fs - .inode_nth(node.inode() as usize) - .ok_or_else(|| FsError::InodeNotFound)?; - let dir = inode.directory().ok_or_else(|| FsError::NotADirectory)?; - let mut found_node = Err(FsError::NotFound); - for entry in dir { - if entry.is_err() { - continue; - } - - let entry = entry.unwrap(); - let entry_inode = self - .fs - .inode_nth(entry.inode as usize) - .ok_or_else(|| FsError::InodeNotFound)?; - if entry.file_name_string() == name { - found_node = Ok(vfs - .find_fs_node(entry.inode, self.device_handle) - .unwrap_or_else(|| { - vfs.add_fs_node(Arc::new(FsNode::new( - ext2_type_to_fs_flags(entry_inode.type_perm()), - entry_inode.size(), - entry.inode, - self.device_handle, - Weak::new(), - ))) - })); - break; - } - } - - found_node - } - - fn root(&self) -> Handle { - self.root_handle - } - - fn device_handle(&self) -> Handle { - self.device_handle - } -} - -fn ext2_type_to_fs_flags(type_perm: TypePerm) -> FsFlags { - trace!("{type_perm:?}"); - let is_directory = type_perm & TypePerm::DIRECTORY == TypePerm::DIRECTORY; - let is_symlink = type_perm & TypePerm::SYMLINK == TypePerm::SYMLINK; - let t = if is_directory { - FsFlags::DIRECTORY - } else { - FsFlags::FILE - }; - let s = if is_symlink { - FsFlags::SYMBOLIC_LINK - } else { - FsFlags::empty() - }; - - t | s -} diff --git a/ableos/src/filesystem/mod.rs b/ableos/src/filesystem/mod.rs deleted file mode 100644 index c735064..0000000 --- a/ableos/src/filesystem/mod.rs +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -pub mod errors; -pub mod ext2; -pub mod vfs; - -use ::ext2::sector::Size1024; -use alloc::sync::Arc; - -use crate::{filesystem::vfs::VFS, handle::Handle, KERNEL_STATE}; - -use self::{ - errors::FsError, - ext2::Ext2StorageDevice, - vfs::{DirectoryEntry, FsNode, VirtualFileSystem}, -}; -use FsResult as Result; - -pub type FsResult<T> = core::result::Result<T, FsError>; - -/// The methods on this trait are to be used internally. -pub trait StorageDevice -where - Self: Send, -{ - fn read(&self, node: &FsNode, offset: usize, size: usize, buffer: &mut Vec<u8>) -> Result<()>; - fn write(&self, node: &FsNode, offset: usize, buffer: &[u8]) -> Result<()>; - fn read_dir(&self, node: &FsNode, index: usize) -> Result<DirectoryEntry>; - fn find_dir(&self, vfs: &mut VirtualFileSystem, node: &FsNode, name: &str) -> Result<Handle>; - // TODO: flush to disk - - fn root(&self) -> Handle; - fn device_handle(&self) -> Handle; -} - -pub fn init() -> Result<()> { - let mut state = KERNEL_STATE.lock(); - let fs = load_fs()?; - let mut vfs = VFS.lock(); - vfs.set_root(fs.root())?; - state.add_storage_device(fs); - Ok(()) -} - -fn load_fs() -> Result<Ext2StorageDevice<Size1024, Vec<u8>>> { - let mut volume = Vec::new(); - volume.extend_from_slice(include_bytes!("../../../userland/root_fs/ext2.img")); - - Ext2StorageDevice::new(volume) -} - -pub fn tree(path: &str) -> Result<()> { - let dir = { - let mut vfs = VFS.lock(); - let handle = vfs.resolve(path)?; - vfs.fs_node(handle).ok_or_else(|| FsError::NotFound)? - }; - - tree_inner( - dir, - if path.starts_with('/') { - &path[1..] - } else { - path - }, - ); - Ok(()) -} - -fn tree_inner<S: Into<String>>(dir: Arc<FsNode>, path: S) { - let path = path.into(); - if let Some(dir) = dir.directory() { - for entry in dir { - let fs_node = { - let vfs = VFS.lock(); - vfs.fs_node(entry.node()).unwrap() - }; - - println!("{}/{} => {}", path, entry.name(), fs_node.inode()); - trace!("{entry:#?}"); - if entry.name() != "." && entry.name() != ".." { - tree_inner(fs_node, format!("{}/{}", path, entry.name())); - } - } - } -} diff --git a/ableos/src/filesystem/vfs.rs b/ableos/src/filesystem/vfs.rs deleted file mode 100644 index 9f03b39..0000000 --- a/ableos/src/filesystem/vfs.rs +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -use core::cmp; - -use alloc::sync::{Arc, Weak}; -use hashbrown::HashMap; -use lazy_static::lazy_static; -use spin::Mutex; - -use super::{errors::FsError, FsResult as Result}; -use crate::{ - handle::{Handle, HandleResource}, - KERNEL_STATE, -}; - -/// The limit for symlink recursion. In POSIX, this is at least 8. In Linux, this is 40. -const SYMLINK_RECURSION_LIMIT: u8 = 8; - -lazy_static! { - pub static ref VFS: Mutex<VirtualFileSystem> = Default::default(); -} - -pub struct VirtualFileSystem { - fs_nodes: HashMap<Handle, Arc<FsNode>>, - root_node: Weak<FsNode>, - root_handle: Option<Handle>, -} - -impl VirtualFileSystem { - /// Sets the VFS root to the given VFS node handle. - pub fn set_root(&mut self, handle: Handle) -> Result<()> { - let root_node = self.fs_node(handle).ok_or_else(|| FsError::NotFound)?; - self.root_node = Arc::downgrade(&root_node); - self.root_handle = Some(handle); - Ok(()) - } - - /// Resolves the path to a handle. If the resulting node is a symlink, - /// the symlink itself is returned. All symlinks but the resulting node - /// are traversed. - /// - /// Requires a mutable reference because internally it might open new VFS - /// nodes while resolving the path. - pub fn resolve<S: AsRef<str>>(&mut self, path: S) -> Result<Handle> { - // TODO: caching - let path = path.as_ref(); - - if !path.starts_with('/') { - // FIXME: use current process working directory for relative paths? - error!("Nonabsolute path {}", path); - Err(FsError::NotAbsolute)?; - } - trace!("Splitting path up"); - let mut components = path.split_terminator('/'); - components.next(); // throw the empty string caused by the root / - // will be initialised beforehand so okay to unwrap - let mut resolved_node = self.root_handle.unwrap(); - // let mut symlink_recursion_level = 0; - for component in components { - trace!("iterating through split up path"); - // if symlink_recursion_level >= SYMLINK_RECURSION_LIMIT { - // Err(FsError::Recursion)?; - // } - - if component == "" { - error!("Invalid Path {}", path); - Err(FsError::InvalidPath)?; - } - trace!("Getting parent of file"); - // checked by previous iteration so okay to unwrap - let parent = self.fs_node(resolved_node).unwrap(); - - // TODO: permission checks - - // FIXME: find_dir checks that this is a directory already but - // that's just more boilerplate in StorageDevice impls - // we should probably check that here instead to reduce - // required boilerplate - if !parent.is_dir() { - error!("file parent {:?} is not a directory", parent); - Err(FsError::NotADirectory)?; - } - - // FIXME: handle mount points - // FIXME: handle symlinks - trace!("resolving node"); - resolved_node = parent.find_dir(self, component)?; - } - - trace!("returning resolved node"); - Ok(resolved_node) - } - - pub fn add_fs_node(&mut self, fs_node: Arc<FsNode>) -> Handle { - let handle = Handle::new(HandleResource::FsNode); - self.fs_nodes.insert(handle, fs_node); - handle - } - - pub fn find_fs_node(&mut self, inode: usize, device_handle: Handle) -> Option<Handle> { - self.fs_nodes.iter().find_map(|(handle, fs_node)| { - if fs_node.inode == inode && fs_node.device_handle == device_handle { - Some(*handle) - } else { - None - } - }) - } - - pub fn fs_node(&self, handle: Handle) -> Option<Arc<FsNode>> { - trace!("Cloning file node and returning"); - self.fs_nodes.get(&handle).cloned() - } - - pub fn root_node(&self) -> Arc<FsNode> { - // okay to unwrap since this should never be called before init - self.root_node.upgrade().unwrap() - } -} - -impl Default for VirtualFileSystem { - fn default() -> Self { - Self { - fs_nodes: HashMap::new(), - root_node: Weak::new(), - root_handle: None, - } - } -} - -/// A VFS node, that can either be a file or a directory. -/// -/// VFS nodes are created whenever a file that doesn't have an open VFS node is -/// opened. When there are no open file descriptors to a file, the associated -/// VFS node is dropped. -#[derive(Debug)] -pub struct FsNode { - flags: FsFlags, - size: usize, // in bytes - inode: usize, // implementation specific identifier for the node - device_handle: Handle, // uniquely assigned device handle - ptr: Weak<FsNode>, // used by mountpoints and symlinks - // TODO: permissions mask - // TODO: owning user/group -} - -impl FsNode { - pub fn new( - flags: FsFlags, - size: usize, - inode: usize, - device_handle: Handle, - ptr: Weak<FsNode>, - ) -> Self { - Self { - flags, - size, - inode, - device_handle, - ptr, - } - } - - /// This method opens a new file descriptor for this VFS node. - // TODO: make this take flags - pub fn open(self: Arc<Self>) -> Result<Handle> { - let mut state = KERNEL_STATE.lock(); - let handle = state.open_file_descriptor(self); - - Ok(handle) - } - - /// This method reads from the VFS node without opening a new file - /// descriptor. This is intended to be used internally, if you're trying to - /// read a file then you probably want to read from a file descriptor. - pub fn read(&self, offset: usize, size: usize, buffer: &mut Vec<u8>) -> Result<usize> { - let state = KERNEL_STATE.lock(); - let device = state - .storage_device(self.device_handle) - .ok_or_else(|| FsError::InvalidDevice)?; - - if self.is_dir() { - Err(FsError::IsDirectory)?; - } - - if offset > self.size { - Err(FsError::EndOfFile)?; - } - - let readable_size = cmp::min(size, self.size - offset); - device.read(self, offset, readable_size, buffer)?; - Ok(readable_size) - } - - /// This method writes to the VFS node without opening a new file - /// descriptor. This is intended to be used internally, if you're trying to - /// write to a file then you probably want to write to a file descriptor. - pub fn write(&self, offset: usize, buffer: &[u8]) -> Result<()> { - let state = KERNEL_STATE.lock(); - let device = state - .storage_device(self.device_handle) - .ok_or_else(|| FsError::InvalidDevice)?; - - device.write(self, offset, buffer) - } - - pub fn read_dir(&self, index: usize) -> Result<DirectoryEntry> { - let state = KERNEL_STATE.lock(); - let device = state - .storage_device(self.device_handle) - .ok_or_else(|| FsError::InvalidDevice)?; - - device.read_dir(self, index) - } - - pub fn find_dir(&self, vfs: &mut VirtualFileSystem, name: &str) -> Result<Handle> { - trace!("Locking the kernel state"); - let state = KERNEL_STATE.lock(); - trace!("Grabbing storage device"); - let device = state - .storage_device(self.device_handle) - .ok_or_else(|| FsError::InvalidDevice)?; - trace!("locating directory"); - let ret = device.find_dir(vfs, self, name); - trace!("returning directory"); - ret - } - - pub fn directory(self: Arc<Self>) -> Option<Directory> { - if self.is_dir() { - Some(Directory::new(self)) - } else { - None - } - } - - pub fn is_dir(&self) -> bool { - (self.flags & FsFlags::DIRECTORY) == FsFlags::DIRECTORY - } - - pub fn inode(&self) -> usize { - self.inode - } - - pub fn size(&self) -> usize { - self.size - } -} - -impl Drop for FsNode { - fn drop(&mut self) { - trace!("dropping VFS node: {self:#?}"); - // TODO: flush to disk here - } -} - -bitflags! { - /// Flags associated with VFS nodes and file descriptors - /// - /// 0x00000MST \ - /// T is set to 0 for files, 1 for directories \ - /// S is set when the file is a symbolic link \ - /// M is set if the file is an active mount point - pub struct FsFlags: u8 { - const FILE = 0b00000000; - const DIRECTORY = 0b00000001; - const SYMBOLIC_LINK = 0b00000010; - const MOUNT_POINT = 0b00000100; - } -} - -pub struct Directory { - node: Arc<FsNode>, - index: usize, -} - -impl Directory { - fn new(node: Arc<FsNode>) -> Self { - Self { node, index: 0 } - } -} - -impl Iterator for Directory { - type Item = DirectoryEntry; - - fn next(&mut self) -> Option<Self::Item> { - let value = self.node.read_dir(self.index).ok(); - self.index += 1; - value - } -} - -#[derive(Clone, Debug)] -pub struct DirectoryEntry { - name: String, - node: Handle, -} - -impl DirectoryEntry { - pub(super) fn new(name: String, node: Handle) -> Self { - Self { name, node } - } - - pub fn name(&self) -> String { - self.name.clone() - } - - pub fn node(&self) -> Handle { - self.node - } -} diff --git a/ableos/src/graphics/mod.rs b/ableos/src/graphics/mod.rs deleted file mode 100644 index e408029..0000000 --- a/ableos/src/graphics/mod.rs +++ /dev/null @@ -1,342 +0,0 @@ -pub mod pixel_format; - -use spin::Lazy; -use vga::{colors::Color16, writers::GraphicsWriter}; - -use crate::vga_e::VGAE; - -use pixel_format::*; - -pub static SCREEN_BUFFER: Lazy<spin::Mutex<ScreenBuffer>> = - Lazy::new(|| spin::Mutex::new(ScreenBuffer::new(640, 480))); - -const FONT_SCALE: f32 = 1.6; - -const GLYPH_HEIGHT: f32 = 18.0; -const GLYPH_WIDTH: f32 = 10.0; - -#[derive(Debug)] -pub struct ScreenSize { - pub x: usize, - pub y: usize, -} - -impl ScreenSize { - pub fn new(x: usize, y: usize) -> Self { - Self { x, y } - } -} - -pub enum GraphicsReturn { - Ok, - ImproperScreenSize, -} - -pub struct ScreenBuffer { - pub size: ScreenSize, - pub clear_color: Rgba64, - pub buff: Box<[Rgba64]>, -} - -impl ScreenBuffer { - // Add optional size later - pub fn new(x: usize, y: usize) -> Self { - Self { - size: ScreenSize::new(x, y), - clear_color: 0, - buff: vec![0u64; x * y].into_boxed_slice(), - } - } - - pub fn draw_filled_circle(&mut self, cx: i32, cy: i32, radius: usize, color: Rgba64) { - let r = radius as i32 * 2; - for y in 0..640 { - for x in 0..480 { - let dx = cx - x as i32 * 2 - 1; - let dy = cy - y as i32 * 2 - 1; - - if dx * dx + dy * dy <= r * r { - self.set_pixel(x, y, color); - }; - } - } - } - - #[inline] - pub fn set_pixel(&mut self, x: usize, y: usize, color: Rgba64) { - self.buff[y * self.size.x + x] = color; - } - - pub fn clear(&mut self) { - self.buff = vec![0u64; self.buff.len()].into_boxed_slice(); - } - - pub fn blit(&mut self, _width: usize, _height: usize) {} - - pub fn draw_filled_rect(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, color: Rgba64) { - for y in y1..y2 { - for x in x1..x2 { - self.set_pixel(x, y, color); - } - } - } - pub fn draw_unfilled_rect( - &mut self, - x1: usize, - y1: usize, - x2: usize, - y2: usize, - color: Rgba64, - ) { - // x1 y1 => x2 y1 => x2 y2 => x1 y2 => x1 y1 - self.draw_line(x1, y1, x2, y1, color); - self.draw_line(x2, y1, x2, y2, color); - self.draw_line(x2, y2, x1, y2, color); - self.draw_line(x1, y2, x1, y1, color); - } - - #[inline] - pub fn draw_line(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, color: Rgba64) { - let x = crate::graphics::get_coordinates( - x1.try_into().unwrap(), - y1.try_into().unwrap(), - x2.try_into().unwrap(), - y2.try_into().unwrap(), - ); - - for coord in x { - self.set_pixel(coord.0, coord.1, color); - } - } - - // pub fn shade(&mut self) { - // for y in 0..100 { - // for x in 0..100 { - // let rgba_ret = evaluate_shader(x, y, self.buff[y * self.size.x + x]); - // match rgba_ret { - // Ok(pixel) => { - // // info!("{:?}", pixel); - // self.set_pixel(x, y, pixel); - // } - - // Err(err) => error!("{}", err), - // } - // } - // } - - // info!("Shaders done"); - // } - - // TODO force clear - pub fn force_redraw(&mut self) { - let vga = VGAE.lock(); - vga.set_mode(); - vga.clear_screen(vga::colors::Color16::Black); - } -} - -pub fn get_coordinates(x1: i32, y1: i32, x2: i32, y2: i32) -> Vec<(usize, usize)> { - let mut coordinates: Vec<(usize, usize)> = vec![]; - let dx: i32 = i32::abs(x2 - x1); - let dy: i32 = i32::abs(y2 - y1); - let sx: i32 = { - if x1 < x2 { - 1 - } else { - -1 - } - }; - let sy: i32 = { - if y1 < y2 { - 1 - } else { - -1 - } - }; - let mut error: i32 = (if dx > dy { dx } else { -dy }) / 2; - let mut current_x: i32 = x1; - let mut current_y: i32 = y1; - loop { - coordinates.push((current_x as usize, current_y as usize)); - // info!("0 {:?}", (current_x, current_y)); - - if current_x == x2 && current_y == y2 { - break; - } - - let error2: i32 = error; - - if error2 > -dx { - error -= dy; - current_x += sx; - } - if error2 < dy { - error += dx; - current_y += sy; - } - } - - coordinates -} - -pub trait VgaBuffer { - fn copy_to_buffer(&self) -> GraphicsReturn; -} -impl VgaBuffer for ScreenBuffer { - fn copy_to_buffer(&self) -> GraphicsReturn { - let mode = VGAE.lock(); - for y in 0..self.size.y { - for x in 0..self.size.x { - let vga_color = into_vga_16(self.buff[y * self.size.x + x]); - if into_vga_16(self.clear_color) != vga_color { - mode.set_pixel(x, y, vga_color); - } - } - } - GraphicsReturn::Ok - } -} - -pub fn into_vga_16(rgba_64: Rgba64) -> Color16 { - use pixel_format::ChannelValue::*; - use vga::colors::Color16::*; - match ( - get_r(rgba_64).into(), - get_g(rgba_64).into(), - get_b(rgba_64).into(), - ) { - (Dark, Dark, Dark) => Black, - (Dark, Dark, Low) => Black, - (Dark, Dark, Mid) => Blue, - (Dark, Dark, High) => Blue, - (Dark, Low, Dark) => Black, - (Dark, Low, Low) => Black, - (Dark, Low, Mid) => Blue, - (Dark, Low, High) => Blue, - (Dark, Mid, Dark) => Green, - (Dark, Mid, Low) => Green, - (Dark, Mid, Mid) => Cyan, - (Dark, Mid, High) => Cyan, - (Dark, High, Dark) => Green, - (Dark, High, Low) => Green, - (Dark, High, Mid) => Green, - (Dark, High, High) => Cyan, - (Low, Dark, Dark) => Black, - (Low, Dark, Low) => Black, - (Low, Dark, Mid) => Blue, - (Low, Dark, High) => Blue, - (Low, Low, Dark) => Black, - (Low, Low, Low) => DarkGrey, - (Low, Low, Mid) => LightGrey, - (Low, Low, High) => Blue, - (Low, Mid, Dark) => DarkGrey, - (Low, Mid, Low) => LightGrey, - (Low, Mid, Mid) => Cyan, - (Low, Mid, High) => Cyan, - (Low, High, Dark) => Green, - (Low, High, Low) => Green, - (Low, High, Mid) => Cyan, - (Low, High, High) => Cyan, - (Mid, Dark, Dark) => Red, - (Mid, Dark, Low) => Red, - (Mid, Dark, Mid) => Magenta, - (Mid, Dark, High) => Magenta, - (Mid, Low, Dark) => Brown, - (Mid, Low, Low) => Red, - (Mid, Low, Mid) => DarkGrey, - (Mid, Low, High) => LightBlue, - (Mid, Mid, Dark) => Brown, - (Mid, Mid, Low) => Brown, - (Mid, Mid, Mid) => LightGrey, - (Mid, Mid, High) => LightBlue, - (Mid, High, Dark) => Green, - (Mid, High, Low) => Green, - (Mid, High, Mid) => LightGreen, - (Mid, High, High) => LightCyan, - (High, Dark, Dark) => Red, - (High, Dark, _) => Magenta, - (High, Low, Dark) => Red, - (High, Low, Low) => LightRed, - (High, Low, Mid) => Pink, - (High, Low, High) => Magenta, - (High, Mid, Dark) => Yellow, - (High, Mid, Low) => Yellow, - (High, Mid, Mid) => LightRed, - (High, Mid, High) => Pink, - (High, High, Dark) => Yellow, - (High, High, Low) => White, - (High, High, Mid) => White, - (High, High, High) => White, - } -} - -// TODO: Incorporate this into the ableos vga crate -// /// Draw a glyph on the screen at the given position -// /// -// /// # Arguments -// /// * `x` - the x position of the glyph -// /// * `y` - the y position of the glyph -// /// * `glyph` - the glyph to draw -// /// * `color` - the color of the glyph -// pub fn draw_char(&mut self, mut x: u32, mut y: u32, character: char, color: Rgba64) { -// // trace!["Judy Hopps is thicc af"]; -// // let mode = *VGAE.lock(); -// // trace!["She got them bouncy bunny buns"]; - -// let basic_multingual_plane = FontRef::try_from_slice(include_bytes!( -// "../../../ableos/assets/fonts/unifont-14.0.01.ttf" -// )) -// .unwrap(); - -// let supplementary_multilingual_plane = FontRef::try_from_slice(include_bytes!( -// "../../../ableos/assets/fonts/unifont_upper-14.0.01.ttf" -// )) -// .unwrap(); - -// // let mut has_char = false; -// // for x in font.codepoint_ids() { -// // if x.1 == character { -// // has_char = true; -// // break; -// // } -// // } - -// let in_supp_plane = character as u32 > 0xffff; - -// let plane = match in_supp_plane { -// false => basic_multingual_plane, -// true => supplementary_multilingual_plane, -// }; - -// match character { -// '\n' => { -// // x = 0; -// // y += (GLYPH_HEIGHT * FONT_SCALE) as u32; -// } -// _ => { -// let q_glyph: Glyph = plane.glyph_id(character).with_scale_and_position( -// 20.0 * FONT_SCALE, -// ab_glyph::point(GLYPH_WIDTH * FONT_SCALE, GLYPH_HEIGHT * FONT_SCALE), -// ); - -// // elf: I don't know if GLYPH_HEIGHT is in the right units here. I'm just guessing. -// if x as usize > self.size.x { -// x = 0; -// y += (GLYPH_HEIGHT * FONT_SCALE) as u32; -// } - -// if let Some(q) = plane.outline_glyph(q_glyph) { -// q.draw(|gx, gy, c| { -// if c > 0.0015 { -// let corner = q.px_bounds().min; -// self.set_pixel( -// gx as usize + corner.x as usize + x as usize, -// gy as usize + corner.y as usize + y as usize, -// color, -// ); -// } -// }); -// } -// } -// } -// } diff --git a/ableos/src/graphics/pixel_format.rs b/ableos/src/graphics/pixel_format.rs deleted file mode 100644 index 7553e59..0000000 --- a/ableos/src/graphics/pixel_format.rs +++ /dev/null @@ -1,55 +0,0 @@ -use core::ops::{BitAnd, BitOr, Shr}; -pub type Rgba64 = u64; -pub enum ChannelValue { - Dark, - Low, - Mid, - High, -} -impl From<u8> for ChannelValue { - fn from(b: u8) -> Self { - use ChannelValue::*; - match b { - 0x00..=0x3f => Dark, - 0x40..=0x7f => Low, - 0x80..=0xbf => Mid, - 0xc0..=0xff => High, - } - } -} -pub fn get_r(rgba: Rgba64) -> u8 { - rgba.bitand(0xff_00_00_00).shr(0o30) as u8 -} -pub fn get_g(rgba: Rgba64) -> u8 { - rgba.bitand(0xff_00_00).shr(0o20) as u8 -} -pub fn get_b(rgba: Rgba64) -> u8 { - rgba.bitand(0xff_00).shr(0o10) as u8 -} -pub fn get_a(rgba: Rgba64) -> u8 { - (rgba & 0xff) as u8 -} -pub fn set_r(rgba: Rgba64, r: u8) -> Rgba64 { - rgba.bitand(0xffffffff_00_ff_ff_ff) - .bitor((r as Rgba64).shr(0o30)) -} -pub fn set_g(rgba: Rgba64, g: u8) -> Rgba64 { - rgba.bitand(0xffffffff_ff_00_ff_ff) - .bitor((g as Rgba64).shr(0o20)) -} -pub fn set_b(rgba: Rgba64, b: u8) -> Rgba64 { - rgba.bitand(0xffffffff_ff_ff_00_ff) - .bitor((b as Rgba64).shr(0o10)) -} -pub fn set_a(rgba: Rgba64, a: u8) -> Rgba64 { - rgba.bitand(0xffffffff_ff_ff_ff_00).bitor(a as Rgba64) -} -pub fn rgba_div(a: Rgba64, b: Rgba64) -> Rgba64 { - set_r(0, get_r(a) / get_r(b)) - | set_g(0, get_g(a) / get_g(b)) - | set_g(0, get_b(a) / get_b(b)) - | set_g(0, get_a(a) / get_a(b)) -} -pub fn new_rgba64(r: u8, g: u8, b: u8, a: u8) -> Rgba64 { - set_r(0, r) | set_g(0, g) | set_b(0, b) | set_a(0, a) -} diff --git a/ableos/src/handle.rs b/ableos/src/handle.rs deleted file mode 100644 index 4c30c73..0000000 --- a/ableos/src/handle.rs +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -//! A handle is a u128 with a set of permissions -//! and a resource connected to it - -use crate::arch::generate_process_pass; -use core::fmt::Display; - -#[derive(Debug)] -pub struct BinaryData { - _name: String, - _data: Vec<u8>, -} - -#[derive(Debug, Eq, Hash, PartialEq, Clone, Copy)] -pub enum HandleResource { - Channel, - Socket, - BinaryData, - StorageDevice, - FileDescriptor, - FsNode, -} - -#[derive(Debug, Eq, Hash, PartialEq, Clone, Copy)] -pub struct Handle { - pub inner: u128, - pub res: HandleResource, -} - -impl Display for Handle { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "Handle-{:032x}", self.inner)?; - match &self.res { - HandleResource::Channel => write!(f, "-Channel")?, - HandleResource::BinaryData => write!(f, "-Binary")?, - HandleResource::Socket => write!(f, "-Socket")?, - HandleResource::StorageDevice => write!(f, "-StorageDevice")?, - HandleResource::FileDescriptor => write!(f, "-FileDescriptor")?, - HandleResource::FsNode => write!(f, "-FsNode")?, - } - - Ok(()) - } -} - -impl Handle { - pub fn new(htype: HandleResource) -> Self { - // FIXME: check if inner collides - Self { - inner: generate_process_pass(), - res: htype, - } - } -} diff --git a/ableos/src/hardware/mod.rs b/ableos/src/hardware/mod.rs deleted file mode 100644 index dd39a86..0000000 --- a/ableos/src/hardware/mod.rs +++ /dev/null @@ -1,126 +0,0 @@ -use crate::arch::interrupts::InterruptIndex; -use crate::arch::interrupts::PICS; -use crate::ps2_mouse::{Mouse, MouseState}; -use lazy_static::lazy_static; -use spin::Mutex; -use x86_64::instructions::port::PortReadOnly; -use x86_64::structures::idt::InterruptStackFrame; - -const MOUSE_MAX_X: u16 = 638; -const MOUSE_MAX_Y: u16 = 478; - -lazy_static! { - pub static ref _MOUSE: Mutex<Mouse> = Mutex::new(Mouse::new()); - pub static ref MOUSE: Mutex<OnScreenMouse> = Mutex::new(OnScreenMouse::default()); -} - -#[derive(Default)] -pub struct OnScreenMouse { - // absolute position on screen - x: u16, - // absolute position on screen - y: u16, -} - -impl OnScreenMouse { - pub fn get_x(&self) -> u16 { - return self.x; - } - - pub fn get_y(&self) -> u16 { - return self.y; - } - - pub fn change_x(&mut self, delta_x: i16) { - if delta_x.is_negative() { - self.x = self.x.saturating_sub((-delta_x) as u16) - } else { - self.x = self.x.saturating_add(delta_x as u16) - } - } - - pub fn change_y(&mut self, delta_y: i16) { - if delta_y.is_negative() { - self.y = self.y.saturating_add((-delta_y) as u16) - } else { - self.y = self.y.saturating_sub(delta_y as u16) - } - } - pub fn set_x(&mut self, x: u16) { - if x >= MOUSE_MAX_X { - self.x = MOUSE_MAX_X - 1; - } else { - self.x = x; - } - } - pub fn set_y(&mut self, y: u16) { - if y >= MOUSE_MAX_Y { - self.y = MOUSE_MAX_Y - 1; - } else { - self.y = y; - } - } -} - -// Initialize the mouse and set the on complete event. -pub fn init_mouse() { - let mut mouse = _MOUSE.lock(); - // debug!("Trying to initialize mouse"); - mouse.init().unwrap(); - mouse.set_on_complete(on_complete); - // info!("Mouse initialized"); -} - -// This will be fired when a packet is finished being processed. -fn on_complete(mouse_state: MouseState) { - // how much the cursor has moved - let delta_x = mouse_state.get_x(); - let delta_y = mouse_state.get_y(); - /* - trace!("MOUSE CHANGE: X{{{}}} Y{{{}}}", delta_x, delta_y); - trace!( - "MOUSE BUTTONS: LEFT{{{}}} RIGHT{{{}}}", - mouse_state._left_button_down(), - mouse_state._right_button_down() - ); - */ - - let mut mouse = MOUSE.lock(); - if mouse.get_x() >= MOUSE_MAX_X { - mouse.set_x(MOUSE_MAX_X - 1); - } else { - mouse.change_x(delta_x); - } - - if mouse.get_y() >= MOUSE_MAX_Y { - mouse.set_y(MOUSE_MAX_Y - 1); - } else { - mouse.change_y(delta_y); - } - // only move the cursor when delta_x is in some range - // i.e. if the cursor moves too fast, ignore it. - // if the mouse moves too fast the delta will overflow - mouse.change_y(delta_y); - - x86_64::instructions::interrupts::without_interrupts(|| { - use crate::TERM; - let mut term = TERM.lock(); - term.set_dirty(true); - }); - - // draw_mouse((mouse.get_x() as usize, mouse.get_y() as usize)); -} - -// An example interrupt based on https://os.phil-opp.com/hardware-interrupts/. -// The ps2 mouse is configured to fire -// interrupts at PIC offset 12. -pub extern "x86-interrupt" fn mouse_interrupt_handler(_stack_frame: InterruptStackFrame) { - let mut port = PortReadOnly::new(0x60); - let packet = unsafe { port.read() }; - _MOUSE.lock().process_packet(packet); - - unsafe { - PICS.lock() - .notify_end_of_interrupt(InterruptIndex::Mouse as u8); - } -} diff --git a/ableos/src/ipc/channel.rs b/ableos/src/ipc/channel.rs deleted file mode 100644 index d711d8e..0000000 --- a/ableos/src/ipc/channel.rs +++ /dev/null @@ -1,75 +0,0 @@ -use alloc::collections::VecDeque; - -use super::IPCError; - -#[derive(Debug)] - -pub struct ChannelPermission { - pub owner: bool, - pub producer: bool, - - pub consumer: bool, - /// Whether or not the process can be destructive about reading - pub distructive_consumer: bool, -} - -#[derive(Debug)] -pub struct Channel { - pub public: bool, - _name: String, - inner: VecDeque<ChannelMessage>, -} - -impl Channel { - pub fn new<S: Into<String>>(name: S, public: bool) -> Self { - let deq = VecDeque::from([]); - - Self { - public, - _name: name.into(), - inner: deq, - } - } - - pub fn read(&mut self) -> Result<ChannelMessage, IPCError> { - if let Some(msg) = self.inner.pop_front() { - return Ok(msg); - } - return Err(IPCError::EmptyChannel); - } - - pub fn write(&mut self, data: ChannelMessage) -> Result<(), IPCError> { - self.inner.push_back(data); - - Ok(()) - } -} - -pub enum ChannelError { - EmptyBuffer, - InvalidPermissions, -} - -#[derive(Debug)] -pub struct ChannelMessage { - inner: [u8; 4096], -} - -impl ChannelMessage { - pub fn new<S: Into<String>>(data: S) -> Result<Self, IPCError> { - let data = data.into(); - let mut message = Self { inner: [0; 4096] }; - - if data.len() > 4096 { - return Err(IPCError::InvalidMessage); - } else { - let mut idx = 0; - for b in data.bytes() { - message.inner[idx] = b; - idx += 1; - } - } - - Ok(message) - } -} diff --git a/ableos/src/ipc/mod.rs b/ableos/src/ipc/mod.rs deleted file mode 100644 index 9973217..0000000 --- a/ableos/src/ipc/mod.rs +++ /dev/null @@ -1,161 +0,0 @@ -use hashbrown::HashMap; - -use crate::handle::{Handle, HandleResource}; - -use self::{ - channel::{Channel, ChannelMessage}, - socket::Socket, -}; - -pub mod channel; -pub mod socket; - -lazy_static::lazy_static! { - pub static ref IPC: spin::Mutex<IPCService> = spin::Mutex::new(IPCService { - sockets: HashMap::new(), - channels: HashMap::new(), - public_board: vec![], - }); -} -pub struct IPCService { - pub sockets: HashMap<Handle, Socket>, - pub channels: HashMap<Handle, Channel>, - // TODO: Add a public board of each down below which use some method of pointing to the above - pub public_board: Vec<Handle>, -} - -impl IPCService { - pub fn examine_board(&self) -> Vec<Handle> { - self.public_board.clone() - } -} - -// Socket Related Impl -impl IPCService { - pub fn create_socket<S: Into<String>>(&mut self, name: S, public: bool) -> Handle { - let handle = Handle::new(crate::handle::HandleResource::Socket); - - let mut sock = Socket::new(name.into()); - if public { - sock.public = true; - - self.public_board.push(handle); - } - - self.sockets.insert(handle.clone(), sock); - - handle - } - pub fn send_socket<S: Into<Vec<u8>>>( - &mut self, - handle: Handle, - data: S, - ) -> Result<(), IPCError> { - trace!("Sending data to {}", handle); - match handle { - Handle { - inner: _inner, - res: HandleResource::Socket, - } => { - let sock = self.sockets.get_mut(&handle); - - match sock { - Some(socket) => { - return socket.write(data.into()); - } - None => return Err(IPCError::NonexistantSocket), - } - } - _ => return Err(IPCError::InvalidHandle), - } - } - - pub fn read_socket(&mut self, handle: Handle) -> Result<Vec<u8>, IPCError> { - trace!("Reading data from {}", handle); - - match handle { - Handle { - inner: _inner, - res: HandleResource::Socket, - } => { - let sock = self.sockets.get_mut(&handle); - - match sock { - Some(socket) => { - return socket.read(); - } - None => return Err(IPCError::NonexistantSocket), - } - } - _ => return Err(IPCError::InvalidHandle), - } - } -} - -impl IPCService { - pub fn create_channel<S: Into<String>>(&mut self, name: S, public: bool) -> Handle { - let handle = Handle::new(crate::handle::HandleResource::Channel); - - let mut chan = Channel::new(name.into(), public); - if public { - chan.public = true; - - self.public_board.push(handle); - } - - self.channels.insert(handle.clone(), chan); - - handle - } - - pub fn read_channel(&mut self, handle: Handle) -> Result<ChannelMessage, IPCError> { - trace!("Reading data from {}", handle); - - match handle { - Handle { - inner: _inner, - res: HandleResource::Channel, - } => { - let sock = self.channels.get_mut(&handle); - - match sock { - Some(socket) => { - return socket.read(); - } - None => return Err(IPCError::NonexistantSocket), - } - } - _ => return Err(IPCError::InvalidHandle), - } - } - - pub fn send_channel(&mut self, handle: Handle, data: ChannelMessage) -> Result<(), IPCError> { - trace!("Sending data to {}", handle); - match handle { - Handle { - inner: _inner, - res: HandleResource::Channel, - } => { - let sock = self.channels.get_mut(&handle); - - match sock { - Some(socket) => { - return socket.write(data); - } - None => return Err(IPCError::NonexistantSocket), - } - } - _ => return Err(IPCError::InvalidHandle), - } - } -} - -#[derive(Debug)] -#[non_exhaustive] -pub enum IPCError { - InvalidHandle, - NonexistantSocket, - EmptySocket, - EmptyChannel, - InvalidMessage, -} diff --git a/ableos/src/ipc/socket.rs b/ableos/src/ipc/socket.rs deleted file mode 100644 index 5956d67..0000000 --- a/ableos/src/ipc/socket.rs +++ /dev/null @@ -1,43 +0,0 @@ -// SEEALSO: https://git.ablecorp.us/able/ableos/src/branch/master/ableos/src/relib/network/socket.rs - -use super::IPCError; - -#[derive(Debug)] -pub struct Socket { - pub public: bool, - name: String, - stream: Vec<u8>, -} - -impl Socket { - pub fn new<S: Into<String>>(name: S) -> Self { - Self { - public: false, - name: name.into(), - stream: vec![], - } - } - - // <S: Into<String>>(name: S) - - pub fn write<S: Into<Vec<u8>>>(&mut self, data: S) -> Result<(), IPCError> { - for c in data.into() { - self.stream.push(c as u8); - } - - Ok(()) - } - pub fn read(&mut self) -> Result<Vec<u8>, IPCError> { - if self.stream.len() != 0 { - let skt = self.stream.clone(); - self.stream = vec![]; - - return Ok(skt); - } - return Err(IPCError::EmptySocket); - } - - pub fn rename(&mut self, name: String) { - self.name = name; - } -} diff --git a/ableos/src/kernel_state.rs b/ableos/src/kernel_state.rs deleted file mode 100644 index 9b40ece..0000000 --- a/ableos/src/kernel_state.rs +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -use alloc::sync::Arc; -use hashbrown::HashMap; -use spin::Lazy; - -use crate::{ - filesystem::{vfs::FsNode, StorageDevice}, - handle::{Handle, HandleResource}, -}; - -pub static KERNEL_STATE: Lazy<spin::Mutex<KernelInternalState>> = - Lazy::new(|| spin::Mutex::new(KernelInternalState::new())); - -pub struct KernelInternalState { - pub hostname: String, - pub storage_devices: HashMap<Handle, Box<dyn StorageDevice>>, - // FIXME: should this be per-process? - file_table: HashMap<Handle, FileTableEntry>, - should_shutdown: bool, -} - -impl KernelInternalState { - pub fn new() -> Self { - Self { - should_shutdown: false, - storage_devices: HashMap::new(), - file_table: HashMap::new(), - hostname: "".to_string(), - } - } - - pub fn set_hostname(&mut self, hostname: String) { - self.hostname = hostname; - } - - pub fn add_storage_device(&mut self, device: impl StorageDevice + Send + 'static) { - let device = Box::new(device); - self.storage_devices.insert(device.device_handle(), device); - } - - pub fn storage_device(&self, handle: Handle) -> Option<&dyn StorageDevice> { - self.storage_devices.get(&handle).map(|d| &**d) - } - - // TODO: implement flags here - pub fn open_file_descriptor(&mut self, fs_node: Arc<FsNode>) -> Handle { - let handle = Handle::new(HandleResource::FileDescriptor); - self.file_table.insert(handle, FileTableEntry::new(fs_node)); - handle - } - - pub fn file_descriptor(&self, handle: Handle) -> Option<&FileTableEntry> { - self.file_table.get(&handle) - } - - pub fn close_file_descriptor(&mut self, handle: Handle) { - self.file_table.remove(&handle); - } - - pub fn shutdown(&mut self) { - self.should_shutdown = true; - } - - pub fn update_state(&mut self) { - if self.should_shutdown { - crate::arch::shutdown(); - } - } -} - -impl Default for KernelInternalState { - fn default() -> Self { - Self::new() - } -} - -pub struct FileTableEntry { - fs_node: Arc<FsNode>, - // TODO: permissions, flags, owner, maybe cache stuff here? -} - -impl FileTableEntry { - fn new(fs_node: Arc<FsNode>) -> Self { - Self { fs_node } - } - - pub fn fs_node(&self) -> Arc<FsNode> { - self.fs_node.clone() - } -} diff --git a/ableos/src/keyboard/abstractions/custom_layout.rs b/ableos/src/keyboard/abstractions/custom_layout.rs deleted file mode 100644 index 956be88..0000000 --- a/ableos/src/keyboard/abstractions/custom_layout.rs +++ /dev/null @@ -1,444 +0,0 @@ -use crate::{ - DecodedKey, HandleControl, KeyCode, KeyboardLayout, LayoutEntry, LayoutEntryKind, Modifiers, -}; - -pub struct CustomLayout { - mapping: [LayoutEntry; 256], -} - -impl Default for CustomLayout { - fn default() -> Self { - Self::new_us104key() - } -} - -impl CustomLayout { - pub fn new_us104key() -> Self { - let mut mapping = Self { - mapping: [LayoutEntry::default(); 256], - }; - - mapping.set( - KeyCode::BackTick, - LayoutEntry::regular().unshifted('`').shifted('`'), - ); - mapping.set(KeyCode::Escape, LayoutEntry::regular().unshifted('\x1B')); - mapping.set( - KeyCode::Key0, - LayoutEntry::regular().unshifted('0').shifted(')'), - ); - mapping.set( - KeyCode::Key1, - LayoutEntry::regular().unshifted('1').shifted('!'), - ); - mapping.set( - KeyCode::Key2, - LayoutEntry::regular().unshifted('2').shifted('@'), - ); - mapping.set( - KeyCode::Key3, - LayoutEntry::regular().unshifted('3').shifted('#'), - ); - mapping.set( - KeyCode::Key4, - LayoutEntry::regular().unshifted('4').shifted('$'), - ); - mapping.set( - KeyCode::Key5, - LayoutEntry::regular().unshifted('5').shifted('%'), - ); - mapping.set( - KeyCode::Key6, - LayoutEntry::regular().unshifted('6').shifted('^'), - ); - mapping.set( - KeyCode::Key7, - LayoutEntry::regular().unshifted('7').shifted('&'), - ); - mapping.set( - KeyCode::Key8, - LayoutEntry::regular().unshifted('8').shifted('*'), - ); - mapping.set( - KeyCode::Key9, - LayoutEntry::regular().unshifted('9').shifted('('), - ); - mapping.set( - KeyCode::Minus, - LayoutEntry::regular().unshifted('-').shifted('_'), - ); - mapping.set( - KeyCode::Equals, - LayoutEntry::regular().unshifted('=').shifted('+'), - ); - mapping.set(KeyCode::Backspace, LayoutEntry::regular().all('\x08')); - mapping.set(KeyCode::Tab, LayoutEntry::regular().all('\x09')); - mapping.set( - KeyCode::Q, - LayoutEntry::alphabet() - .low('q') - .high('Q') - .raw_unicode('\u{0011}'), - ); - mapping.set( - KeyCode::W, - LayoutEntry::alphabet() - .low('w') - .high('W') - .raw_unicode('\u{0017}'), - ); - mapping.set( - KeyCode::E, - LayoutEntry::alphabet() - .low('e') - .high('E') - .raw_unicode('\u{0005}'), - ); - mapping.set( - KeyCode::R, - LayoutEntry::alphabet() - .low('r') - .high('R') - .raw_unicode('\u{0012}'), - ); - mapping.set( - KeyCode::T, - LayoutEntry::alphabet() - .low('t') - .high('T') - .raw_unicode('\u{0014}'), - ); - mapping.set( - KeyCode::Y, - LayoutEntry::alphabet() - .low('y') - .high('Y') - .raw_unicode('\u{0019}'), - ); - mapping.set( - KeyCode::U, - LayoutEntry::alphabet() - .low('u') - .high('U') - .raw_unicode('\u{0015}'), - ); - mapping.set( - KeyCode::I, - LayoutEntry::alphabet() - .low('i') - .high('I') - .raw_unicode('\u{0009}'), - ); - mapping.set( - KeyCode::O, - LayoutEntry::alphabet() - .low('o') - .high('O') - .raw_unicode('\u{000F}'), - ); - mapping.set( - KeyCode::P, - LayoutEntry::alphabet() - .low('p') - .high('P') - .raw_unicode('\u{0010}'), - ); - mapping.set( - KeyCode::A, - LayoutEntry::alphabet() - .low('a') - .high('A') - .raw_unicode('\u{0001}'), - ); - mapping.set( - KeyCode::S, - LayoutEntry::alphabet() - .low('s') - .high('S') - .raw_unicode('\u{0013}'), - ); - mapping.set( - KeyCode::D, - LayoutEntry::alphabet() - .low('d') - .high('D') - .raw_unicode('\u{0004}'), - ); - mapping.set( - KeyCode::F, - LayoutEntry::alphabet() - .low('f') - .high('F') - .raw_unicode('\u{0006}'), - ); - mapping.set( - KeyCode::G, - LayoutEntry::alphabet() - .low('g') - .high('G') - .raw_unicode('\u{0007}'), - ); - mapping.set( - KeyCode::H, - LayoutEntry::alphabet() - .low('h') - .high('H') - .raw_unicode('\u{0008}'), - ); - mapping.set( - KeyCode::J, - LayoutEntry::alphabet() - .low('j') - .high('J') - .raw_unicode('\u{000A}'), - ); - mapping.set( - KeyCode::K, - LayoutEntry::alphabet() - .low('k') - .high('K') - .raw_unicode('\u{000B}'), - ); - mapping.set( - KeyCode::L, - LayoutEntry::alphabet() - .low('l') - .high('L') - .raw_unicode('\u{000C}'), - ); - mapping.set( - KeyCode::Z, - LayoutEntry::alphabet() - .low('z') - .high('Z') - .raw_unicode('\u{001A}'), - ); - mapping.set( - KeyCode::X, - LayoutEntry::alphabet() - .low('x') - .high('X') - .raw_unicode('\u{0018}'), - ); - mapping.set( - KeyCode::C, - LayoutEntry::alphabet() - .low('c') - .high('C') - .raw_unicode('\u{0003}'), - ); - mapping.set( - KeyCode::V, - LayoutEntry::alphabet() - .low('v') - .high('V') - .raw_unicode('\u{0016}'), - ); - mapping.set( - KeyCode::B, - LayoutEntry::alphabet() - .low('b') - .high('B') - .raw_unicode('\u{0002}'), - ); - mapping.set( - KeyCode::N, - LayoutEntry::alphabet() - .low('n') - .high('N') - .raw_unicode('\u{000E}'), - ); - mapping.set( - KeyCode::M, - LayoutEntry::alphabet() - .low('m') - .high('M') - .raw_unicode('\u{000D}'), - ); - mapping.set( - KeyCode::BracketSquareLeft, - LayoutEntry::regular().unshifted('{').shifted('['), - ); - mapping.set( - KeyCode::BracketSquareRight, - LayoutEntry::regular().unshifted('}').shifted(']'), - ); - mapping.set( - KeyCode::BackSlash, - LayoutEntry::regular().unshifted('|').shifted('\\'), - ); - mapping.set( - KeyCode::SemiColon, - LayoutEntry::regular().unshifted(';').shifted(':'), - ); - mapping.set( - KeyCode::Quote, - LayoutEntry::regular().unshifted('\'').shifted('"'), - ); - mapping.set(KeyCode::Enter, LayoutEntry::regular().all('\x0A')); - mapping.set( - KeyCode::Comma, - LayoutEntry::regular().unshifted(',').shifted('<'), - ); - mapping.set( - KeyCode::Fullstop, - LayoutEntry::regular().unshifted('.').shifted('>'), - ); - mapping.set( - KeyCode::Slash, - LayoutEntry::regular().unshifted('/').shifted('?'), - ); - mapping.set(KeyCode::Spacebar, LayoutEntry::regular().all(' ')); - mapping.set(KeyCode::Delete, LayoutEntry::regular().all('\x7F')); - mapping.set(KeyCode::NumpadSlash, LayoutEntry::numpad().all('/')); - mapping.set(KeyCode::NumpadStar, LayoutEntry::numpad().all('*')); - mapping.set(KeyCode::NumpadMinus, LayoutEntry::numpad().all('-')); - mapping.set( - KeyCode::Numpad7, - LayoutEntry::numpad().low('7').high(KeyCode::Home), - ); - mapping.set( - KeyCode::Numpad8, - LayoutEntry::numpad().low('8').high(KeyCode::ArrowUp), - ); - mapping.set( - KeyCode::Numpad9, - LayoutEntry::numpad().low('9').high(KeyCode::PageUp), - ); - mapping.set(KeyCode::NumpadPlus, LayoutEntry::numpad().all('+')); - mapping.set( - KeyCode::Numpad4, - LayoutEntry::numpad().low('4').high(KeyCode::ArrowLeft), - ); - mapping.set(KeyCode::Numpad5, LayoutEntry::numpad().all('5')); - mapping.set( - KeyCode::Numpad6, - LayoutEntry::numpad().low('6').high(KeyCode::ArrowRight), - ); - mapping.set( - KeyCode::Numpad1, - LayoutEntry::numpad().low('1').high(KeyCode::End), - ); - mapping.set( - KeyCode::Numpad2, - LayoutEntry::numpad().low('2').high(KeyCode::ArrowDown), - ); - mapping.set( - KeyCode::Numpad3, - LayoutEntry::numpad().low('3').high(KeyCode::PageDown), - ); - mapping.set( - KeyCode::Numpad0, - LayoutEntry::numpad().low('0').high(KeyCode::Insert), - ); - mapping.set( - KeyCode::NumpadPeriod, - LayoutEntry::numpad().low('.').high('\x7F'), - ); - mapping.set(KeyCode::NumpadEnter, LayoutEntry::numpad().all('\x0A')); - mapping - } - pub fn new_us105key() -> Self { - let mut mapping = Self::new_us104key(); - mapping.set( - KeyCode::BackTick, - LayoutEntry::regular() - .unshifted('`') - .shifted('¬') - .altgr('|'), - ); - mapping.set( - KeyCode::Key2, - LayoutEntry::regular().unshifted('2').shifted('"'), - ); - mapping.set( - KeyCode::Quote, - LayoutEntry::regular().unshifted('\'').shifted('@'), - ); - mapping.set( - KeyCode::Key3, - LayoutEntry::regular().unshifted('3').shifted('£'), - ); - mapping.set( - KeyCode::BackTick, - LayoutEntry::regular() - .unshifted('4') - .shifted('$') - .altgr('€'), - ); - mapping.set( - KeyCode::HashTilde, - LayoutEntry::regular().unshifted('#').shifted('~'), - ); - mapping - } - - pub fn set(&mut self, pos: KeyCode, entry: LayoutEntry) { - self.mapping[pos as usize] = entry; - } -} - -impl KeyboardLayout for CustomLayout { - fn map_keycode( - &self, - keycode: KeyCode, - modifiers: &Modifiers, - handle_ctrl: HandleControl, - ) -> DecodedKey { - let map_to_unicode = handle_ctrl == HandleControl::MapLettersToUnicode; - let spot = &self.mapping[keycode as usize]; - if let Some(k) = if map_to_unicode && modifiers.is_ctrl() { - match spot.kind { - LayoutEntryKind::Regular => spot.raw_unicode, - LayoutEntryKind::Numlockable => None, - LayoutEntryKind::Capslockable => spot.raw_unicode, - } - } else if modifiers.alt_gr { - match spot.kind { - LayoutEntryKind::Regular => spot.altgr, - LayoutEntryKind::Numlockable => None, - LayoutEntryKind::Capslockable => spot.altgr, - } - } else if modifiers.is_shifted() { - match spot.kind { - LayoutEntryKind::Regular => spot.shifted, - LayoutEntryKind::Numlockable => { - if modifiers.numlock { - spot.locked_shifted - } else { - spot.shifted - } - } - LayoutEntryKind::Capslockable => { - if modifiers.is_caps() { - spot.locked_shifted - } else { - spot.shifted - } - } - } - } else { - match spot.kind { - LayoutEntryKind::Regular => spot.unshifted, - LayoutEntryKind::Numlockable => { - if modifiers.numlock { - spot.locked - } else { - spot.unshifted - } - } - LayoutEntryKind::Capslockable => { - if modifiers.is_caps() { - spot.locked - } else { - spot.unshifted - } - } - } - } { - k - } else { - DecodedKey::RawKey(keycode as u8) - } - } -} diff --git a/ableos/src/keyboard/abstractions/custom_scancode_set.rs b/ableos/src/keyboard/abstractions/custom_scancode_set.rs deleted file mode 100644 index 25b08e2..0000000 --- a/ableos/src/keyboard/abstractions/custom_scancode_set.rs +++ /dev/null @@ -1,262 +0,0 @@ -use crate::{ - keyboard::EXTENDED_KEY_CODE, DecodeState, Error, KeyCode, KeyEvent, KeyState, ScancodeSet, -}; - -pub struct CustomScancodeSet { - single_byte: [Option<KeyCode>; 256], - extended: [Option<KeyCode>; 256], -} - -impl Default for CustomScancodeSet { - fn default() -> Self { - Self::scancode_set1() - } -} - -impl CustomScancodeSet { - pub fn scancode_set1() -> Self { - let mut scancode_set = Self { - single_byte: [None; 256], - extended: [None; 256], - }; - - scancode_set.single_byte[0x01] = Some(KeyCode::Escape); // 01 - scancode_set.single_byte[0x02] = Some(KeyCode::Key1); // 02 - scancode_set.single_byte[0x03] = Some(KeyCode::Key2); // 03 - scancode_set.single_byte[0x04] = Some(KeyCode::Key3); // 04 - scancode_set.single_byte[0x05] = Some(KeyCode::Key4); // 05 - scancode_set.single_byte[0x06] = Some(KeyCode::Key5); // 06 - scancode_set.single_byte[0x07] = Some(KeyCode::Key6); // 07 - scancode_set.single_byte[0x08] = Some(KeyCode::Key7); // 08 - scancode_set.single_byte[0x09] = Some(KeyCode::Key8); // 09 - scancode_set.single_byte[0x0A] = Some(KeyCode::Key9); // 0A - scancode_set.single_byte[0x0B] = Some(KeyCode::Key0); // 0B - scancode_set.single_byte[0x0C] = Some(KeyCode::Minus); // 0C - scancode_set.single_byte[0x0D] = Some(KeyCode::Equals); // 0D - scancode_set.single_byte[0x0E] = Some(KeyCode::Backspace); // 0E - scancode_set.single_byte[0x0F] = Some(KeyCode::Tab); // 0F - scancode_set.single_byte[0x10] = Some(KeyCode::Q); // 10 - scancode_set.single_byte[0x11] = Some(KeyCode::W); // 11 - scancode_set.single_byte[0x12] = Some(KeyCode::E); // 12 - scancode_set.single_byte[0x13] = Some(KeyCode::R); // 13 - scancode_set.single_byte[0x14] = Some(KeyCode::T); // 14 - scancode_set.single_byte[0x15] = Some(KeyCode::Y); // 15 - scancode_set.single_byte[0x16] = Some(KeyCode::U); // 16 - scancode_set.single_byte[0x17] = Some(KeyCode::I); // 17 - scancode_set.single_byte[0x18] = Some(KeyCode::O); // 18 - scancode_set.single_byte[0x19] = Some(KeyCode::P); // 19 - scancode_set.single_byte[0x1A] = Some(KeyCode::BracketSquareLeft); // 1A - scancode_set.single_byte[0x1B] = Some(KeyCode::BracketSquareRight); // 1B - scancode_set.single_byte[0x1C] = Some(KeyCode::Enter); // 1C - scancode_set.single_byte[0x1D] = Some(KeyCode::ControlLeft); // 1D - scancode_set.single_byte[0x1E] = Some(KeyCode::A); // 1E - scancode_set.single_byte[0x1F] = Some(KeyCode::S); // 1F - scancode_set.single_byte[0x20] = Some(KeyCode::D); // 20 - scancode_set.single_byte[0x21] = Some(KeyCode::F); // 21 - scancode_set.single_byte[0x22] = Some(KeyCode::G); // 22 - scancode_set.single_byte[0x23] = Some(KeyCode::H); // 23 - scancode_set.single_byte[0x24] = Some(KeyCode::J); // 24 - scancode_set.single_byte[0x25] = Some(KeyCode::K); // 25 - scancode_set.single_byte[0x26] = Some(KeyCode::L); // 26 - scancode_set.single_byte[0x27] = Some(KeyCode::SemiColon); // 27 - scancode_set.single_byte[0x28] = Some(KeyCode::Quote); // 28 - scancode_set.single_byte[0x29] = Some(KeyCode::BackTick); // 29 - scancode_set.single_byte[0x2A] = Some(KeyCode::ShiftLeft); // 2A - scancode_set.single_byte[0x2B] = Some(KeyCode::BackSlash); // 2B - scancode_set.single_byte[0x2C] = Some(KeyCode::Z); // 2C - scancode_set.single_byte[0x2D] = Some(KeyCode::X); // 2D - scancode_set.single_byte[0x2E] = Some(KeyCode::C); // 2E - scancode_set.single_byte[0x2F] = Some(KeyCode::V); // 2F - scancode_set.single_byte[0x30] = Some(KeyCode::B); // 30 - scancode_set.single_byte[0x31] = Some(KeyCode::N); // 31 - scancode_set.single_byte[0x32] = Some(KeyCode::M); // 32 - scancode_set.single_byte[0x33] = Some(KeyCode::Comma); // 33 - scancode_set.single_byte[0x34] = Some(KeyCode::Fullstop); // 34 - scancode_set.single_byte[0x35] = Some(KeyCode::Slash); // 35 - scancode_set.single_byte[0x36] = Some(KeyCode::ShiftRight); // 36 - scancode_set.single_byte[0x37] = Some(KeyCode::NumpadStar); // 37 - scancode_set.single_byte[0x38] = Some(KeyCode::AltLeft); // 38 - scancode_set.single_byte[0x39] = Some(KeyCode::Spacebar); // 39 - scancode_set.single_byte[0x3A] = Some(KeyCode::CapsLock); // 3A - scancode_set.single_byte[0x3B] = Some(KeyCode::F1); // 3B - scancode_set.single_byte[0x3C] = Some(KeyCode::F2); // 3C - scancode_set.single_byte[0x3D] = Some(KeyCode::F3); // 3D - scancode_set.single_byte[0x3E] = Some(KeyCode::F4); // 3E - scancode_set.single_byte[0x3F] = Some(KeyCode::F5); // 3F - scancode_set.single_byte[0x40] = Some(KeyCode::F6); // 40 - scancode_set.single_byte[0x41] = Some(KeyCode::F7); // 41 - scancode_set.single_byte[0x42] = Some(KeyCode::F8); // 42 - scancode_set.single_byte[0x43] = Some(KeyCode::F9); // 43 - scancode_set.single_byte[0x44] = Some(KeyCode::F10); // 44 - scancode_set.single_byte[0x45] = Some(KeyCode::NumpadLock); // 45 - scancode_set.single_byte[0x46] = Some(KeyCode::ScrollLock); // 46 - scancode_set.single_byte[0x47] = Some(KeyCode::Numpad7); // 47 - scancode_set.single_byte[0x48] = Some(KeyCode::Numpad8); // 48 - scancode_set.single_byte[0x49] = Some(KeyCode::Numpad9); // 49 - scancode_set.single_byte[0x4A] = Some(KeyCode::NumpadMinus); // 4A - scancode_set.single_byte[0x4B] = Some(KeyCode::Numpad4); // 4B - scancode_set.single_byte[0x4C] = Some(KeyCode::Numpad5); // 4C - scancode_set.single_byte[0x4D] = Some(KeyCode::Numpad6); // 4D - scancode_set.single_byte[0x4E] = Some(KeyCode::NumpadPlus); // 4E - scancode_set.single_byte[0x4F] = Some(KeyCode::Numpad1); // 4F - scancode_set.single_byte[0x50] = Some(KeyCode::Numpad2); // 50 - scancode_set.single_byte[0x51] = Some(KeyCode::Numpad3); // 51 - scancode_set.single_byte[0x52] = Some(KeyCode::Numpad0); // 52 - scancode_set.single_byte[0x53] = Some(KeyCode::NumpadPeriod); // 53 - // 0x54 - // 0x55 - // 0x56 - scancode_set.single_byte[0x57] = Some(KeyCode::F11); // 57 - scancode_set.single_byte[0x58] = Some(KeyCode::F12); // 58 - for i in 0x81..=0xD8 { - scancode_set.single_byte[i] = scancode_set.single_byte[i - 0x80]; - } - scancode_set.extended[0x10] = Some(KeyCode::PrevTrack); // E010 - //0x11 - //0x12 - //0x13 - //0x14 - //0x15 - //0x16 - //0x17 - //0x18 - scancode_set.extended[0x19] = Some(KeyCode::NextTrack); // E019 - //0x1A - //0x1B - scancode_set.extended[0x1C] = Some(KeyCode::NumpadEnter); // E01C - scancode_set.extended[0x1D] = Some(KeyCode::ControlRight); // E01D - //0x1E - //0x1F - scancode_set.extended[0x20] = Some(KeyCode::Mute); // E020 - scancode_set.extended[0x21] = Some(KeyCode::Calculator); // E021 - scancode_set.extended[0x22] = Some(KeyCode::Play); // E022 - //0x23 - scancode_set.extended[0x24] = Some(KeyCode::Stop); // E024 - //0x25 - //0x26 - //0x27 - //0x28 - //0x29 - //0x2A - //0x2B - //0x2C - //0x2D - scancode_set.extended[0x2E] = Some(KeyCode::VolumeDown); // E02E - //0x2F - scancode_set.extended[0x30] = Some(KeyCode::VolumeUp); // E030 - //0x31 - scancode_set.extended[0x32] = Some(KeyCode::WWWHome); // E032 - //0x33 - //0x34 - scancode_set.extended[0x35] = Some(KeyCode::NumpadSlash); // E035 - //0x36 - //0x37 - scancode_set.extended[0x38] = Some(KeyCode::AltRight); // E038 - //0x39 - //0x3A - //0x3B - //0x3C - //0x3D - //0x3E - //0x3F - //0x40 - //0x41 - //0x42 - //0x43 - //0x44 - //0x45 - //0x46 - scancode_set.extended[0x47] = Some(KeyCode::Home); // E047 - scancode_set.extended[0x48] = Some(KeyCode::ArrowUp); // E048 - scancode_set.extended[0x49] = Some(KeyCode::PageUp); // E049 - //0x4A - scancode_set.extended[0x4B] = Some(KeyCode::ArrowLeft); // E04B - //0x4C - scancode_set.extended[0x4D] = Some(KeyCode::ArrowRight); // E04D - //0x4E - scancode_set.extended[0x4F] = Some(KeyCode::End); // E04F - scancode_set.extended[0x50] = Some(KeyCode::ArrowDown); // E050 - scancode_set.extended[0x51] = Some(KeyCode::PageDown); // E051 - scancode_set.extended[0x52] = Some(KeyCode::Insert); // E052 - scancode_set.extended[0x53] = Some(KeyCode::Delete); // E053 - for i in 0x90..=0xED { - scancode_set.extended[i] = scancode_set.extended[i - 0x80]; - } - scancode_set - } - - pub fn scancode_set2() -> Self { - Self { - single_byte: [None; 256], - extended: [None; 256], - } - } -} - -impl ScancodeSet for CustomScancodeSet { - fn advance_state(&self, state: &mut DecodeState, code: u8) -> Result<Option<KeyEvent>, Error> { - match *state { - DecodeState::Start => { - match code { - EXTENDED_KEY_CODE => { - *state = DecodeState::Extended; - Ok(None) - } - 0x80..=0xFF => { - // Release codes - Ok(Some(KeyEvent::new( - self.map_scancode(code - 0x80)?, - KeyState::Up, - ))) - } - _ => { - // Normal codes - Ok(Some(KeyEvent::new( - self.map_scancode(code)?, - KeyState::Down, - ))) - } - } - } - DecodeState::Extended => { - *state = DecodeState::Start; - match code { - 0x80..=0xFF => { - // Extended Release codes - Ok(Some(KeyEvent::new( - self.map_extended_scancode(code - 0x80)?, - KeyState::Up, - ))) - } - _ => { - // Normal release codes - Ok(Some(KeyEvent::new( - self.map_extended_scancode(code)?, - KeyState::Down, - ))) - } - } - } - _ => { - // Can't get in to this state - unimplemented!(); - } - } - } - - fn map_scancode(&self, code: u8) -> Result<KeyCode, Error> { - if let Some(kc) = self.single_byte[code as usize] { - Ok(kc) - } else { - Err(Error::UnknownKeyCode) - } - } - - fn map_extended_scancode(&self, code: u8) -> Result<KeyCode, Error> { - if let Some(kc) = self.extended[code as usize] { - Ok(kc) - } else { - Err(Error::UnknownKeyCode) - } - } -} diff --git a/ableos/src/keyboard/abstractions/layout_entry.rs b/ableos/src/keyboard/abstractions/layout_entry.rs deleted file mode 100644 index e338def..0000000 --- a/ableos/src/keyboard/abstractions/layout_entry.rs +++ /dev/null @@ -1,115 +0,0 @@ -use crate::DecodedKey; - -#[derive(Debug, Clone, Copy)] -pub enum LayoutEntryKind { - Regular, - Numlockable, - Capslockable, -} - -impl Default for LayoutEntryKind { - fn default() -> Self { - Self::Regular - } -} - -#[derive(Debug, Clone, Copy, Default)] -pub struct LayoutEntry { - pub kind: LayoutEntryKind, - pub unshifted: Option<DecodedKey>, - pub shifted: Option<DecodedKey>, - pub locked: Option<DecodedKey>, - pub locked_shifted: Option<DecodedKey>, - pub altgr: Option<DecodedKey>, - pub raw_unicode: Option<DecodedKey>, -} - -impl LayoutEntry { - #[must_use] - pub fn regular() -> Self { - Self { - kind: LayoutEntryKind::Regular, - ..Default::default() - } - } - - #[must_use] - pub fn numpad() -> Self { - Self { - kind: LayoutEntryKind::Numlockable, - ..Default::default() - } - } - - #[must_use] - pub fn alphabet() -> Self { - Self { - kind: LayoutEntryKind::Capslockable, - ..Default::default() - } - } - - #[must_use] - pub fn unshifted(mut self, c: impl Into<DecodedKey>) -> Self { - self.unshifted = Some(c.into()); - self - } - - #[must_use] - pub fn shifted(mut self, c: impl Into<DecodedKey>) -> Self { - self.shifted = Some(c.into()); - self - } - - #[must_use] - pub fn altgr(mut self, c: impl Into<DecodedKey>) -> Self { - self.altgr = Some(c.into()); - self - } - - #[must_use] - pub fn raw_unicode(mut self, c: impl Into<DecodedKey>) -> Self { - self.raw_unicode = Some(c.into()); - self - } - - #[must_use] - pub fn locked(mut self, c: impl Into<DecodedKey>) -> Self { - self.locked = Some(c.into()); - self - } - - #[must_use] - pub fn locked_shifted(mut self, c: impl Into<DecodedKey>) -> Self { - self.locked_shifted = Some(c.into()); - self - } - - #[must_use] - pub fn common(self, c: impl Into<DecodedKey> + Clone) -> Self { - self.unshifted(c.clone()) - .shifted(c.clone()) - .locked(c.clone()) - .locked_shifted(c) - } - - #[must_use] - pub fn low(self, c: impl Into<DecodedKey> + Clone) -> Self { - self.unshifted(c.clone()).locked_shifted(c) - } - - #[must_use] - pub fn high(self, c: impl Into<DecodedKey> + Clone) -> Self { - self.shifted(c.clone()).locked(c) - } - - #[must_use] - pub fn all(self, c: impl Into<DecodedKey> + Clone) -> Self { - self.unshifted(c.clone()) - .shifted(c.clone()) - .locked(c.clone()) - .locked_shifted(c.clone()) - .altgr(c.clone()) - .raw_unicode(c) - } -} diff --git a/ableos/src/keyboard/abstractions/mod.rs b/ableos/src/keyboard/abstractions/mod.rs deleted file mode 100644 index d80e687..0000000 --- a/ableos/src/keyboard/abstractions/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod custom_layout; -mod custom_scancode_set; -mod layout_entry; - -pub use custom_layout::CustomLayout; -pub use custom_scancode_set::CustomScancodeSet; -pub use layout_entry::{LayoutEntry, LayoutEntryKind}; diff --git a/ableos/src/keyboard/mod.rs b/ableos/src/keyboard/mod.rs deleted file mode 100644 index 5ca5bca..0000000 --- a/ableos/src/keyboard/mod.rs +++ /dev/null @@ -1,290 +0,0 @@ -#![allow(dead_code)] - -mod abstractions; -mod small_types; -mod traits; - -pub use abstractions::*; -pub use small_types::*; -pub use traits::*; - -const EXTENDED_KEY_CODE: u8 = 0xE0; -const KEYCODE_BITS: u8 = 11; -const KEY_RELEASE_CODE: u8 = 0xF0; - -#[derive(Debug)] -pub struct Keyboard<T, S> -where - T: KeyboardLayout, - S: ScancodeSet, -{ - register: u16, - num_bits: u8, - decode_state: DecodeState, - handle_ctrl: HandleControl, - modifiers: Modifiers, - layout: T, - set: S, -} - -impl<T, S> Keyboard<T, S> -where - T: KeyboardLayout + Default, - S: ScancodeSet + Default, -{ - /// Make a new Keyboard object with the given layout. - pub fn new(_layout: T, _set: S, handle_ctrl: HandleControl) -> Keyboard<T, S> { - Keyboard { - register: 0, - num_bits: 0, - decode_state: DecodeState::Start, - handle_ctrl, - modifiers: Modifiers { - lshift: false, - rshift: false, - lctrl: false, - rctrl: false, - numlock: true, - capslock: false, - alt_gr: false, - }, - layout: T::default(), - set: S::default(), - } - } - - /// Change the Ctrl key mapping. - pub fn set_ctrl_handling(&mut self, new_value: HandleControl) { - self.handle_ctrl = new_value; - } - - /// Get the current Ctrl key mapping. - pub fn get_ctrl_handling(&self) -> HandleControl { - self.handle_ctrl - } - - /// Clears the bit register. - /// - /// Call this when there is a timeout reading data from the keyboard. - pub fn clear(&mut self) { - self.register = 0; - self.num_bits = 0; - self.decode_state = DecodeState::Start; - } - - /// Processes a 16-bit word from the keyboard. - /// - /// * The start bit (0) must be in bit 0. - /// * The data octet must be in bits 1..8, with the LSB in bit 1 and the - /// MSB in bit 8. - /// * The parity bit must be in bit 9. - /// * The stop bit (1) must be in bit 10. - pub fn add_word(&mut self, word: u16) -> Result<Option<KeyEvent>, Error> { - let byte = self.check_word(word)?; - self.add_byte(byte) - } - - /// Processes an 8-bit byte from the keyboard. - /// - /// We assume the start, stop and parity bits have been processed and - /// verified. - pub fn add_byte(&mut self, byte: u8) -> Result<Option<KeyEvent>, Error> { - self.set.advance_state(&mut self.decode_state, byte) - } - - /// Shift a bit into the register. - /// - /// Call this /or/ call `add_word` - don't call both. - /// Until the last bit is added you get Ok(None) returned. - pub fn add_bit(&mut self, bit: bool) -> Result<Option<KeyEvent>, Error> { - self.register |= (bit as u16) << self.num_bits; - self.num_bits += 1; - if self.num_bits == KEYCODE_BITS { - let word = self.register; - self.register = 0; - self.num_bits = 0; - self.add_word(word) - } else { - Ok(None) - } - } - - /// Processes a `KeyEvent` returned from `add_bit`, `add_byte` or `add_word` - /// and produces a decoded key. - /// - /// For example, the KeyEvent for pressing the '5' key on your keyboard - /// gives a DecodedKey of unicode character '5', unless the shift key is - /// held in which case you get the unicode character '%'. - pub fn process_keyevent(&mut self, ev: KeyEvent) -> Option<DecodedKey> { - match ev { - KeyEvent { - code: KeyCode::ShiftLeft, - state: KeyState::Down, - } => { - self.modifiers.lshift = true; - None - } - KeyEvent { - code: KeyCode::ShiftRight, - state: KeyState::Down, - } => { - self.modifiers.rshift = true; - None - } - KeyEvent { - code: KeyCode::ShiftLeft, - state: KeyState::Up, - } => { - self.modifiers.lshift = false; - None - } - KeyEvent { - code: KeyCode::ShiftRight, - state: KeyState::Up, - } => { - self.modifiers.rshift = false; - None - } - KeyEvent { - code: KeyCode::CapsLock, - state: KeyState::Down, - } => { - self.modifiers.capslock = !self.modifiers.capslock; - None - } - KeyEvent { - code: KeyCode::NumpadLock, - state: KeyState::Down, - } => { - self.modifiers.numlock = !self.modifiers.numlock; - None - } - KeyEvent { - code: KeyCode::ControlLeft, - state: KeyState::Down, - } => { - self.modifiers.lctrl = true; - None - } - KeyEvent { - code: KeyCode::ControlLeft, - state: KeyState::Up, - } => { - self.modifiers.lctrl = false; - None - } - KeyEvent { - code: KeyCode::ControlRight, - state: KeyState::Down, - } => { - self.modifiers.rctrl = true; - None - } - KeyEvent { - code: KeyCode::ControlRight, - state: KeyState::Up, - } => { - self.modifiers.rctrl = false; - None - } - KeyEvent { - code: KeyCode::AltRight, - state: KeyState::Down, - } => { - self.modifiers.alt_gr = true; - None - } - KeyEvent { - code: KeyCode::AltRight, - state: KeyState::Up, - } => { - self.modifiers.alt_gr = false; - None - } - KeyEvent { - code: c, - state: KeyState::Down, - } => Some( - self.layout - .map_keycode(c, &self.modifiers, self.handle_ctrl), - ), - _ => None, - } - } - - fn get_bit(&self, word: u16, offset: usize) -> bool { - ((word >> offset) & 0x0001) != 0 - } - - fn has_even_number_bits(&self, data: u8) -> bool { - (data.count_ones() % 2) == 0 - } - - /// Check 11-bit word has 1 start bit, 1 stop bit and an odd parity bit. - fn check_word(&self, word: u16) -> Result<u8, Error> { - let start_bit = self.get_bit(word, 0); - let parity_bit = self.get_bit(word, 9); - let stop_bit = self.get_bit(word, 10); - let data = ((word >> 1) & 0xFF) as u8; - if start_bit { - return Err(Error::BadStartBit); - } - if !stop_bit { - return Err(Error::BadStopBit); - } - let need_parity = self.has_even_number_bits(data); - // Odd parity, so these must not match - if need_parity != parity_bit { - return Err(Error::ParityError); - } - - Ok(data) - } -} - -pub fn parse_format() { - let test = include_str!("../../keymaps/qwerty.keymap").lines(); - // r#"0-NONE\n1-HI#Says HI"# - for x in test { - for y in x.split('-') { - if y.parse::<u64>().is_ok() { - todo![]; - // NOTE: this unwrap is ok bcause of the above check - // println!("NUM: {:?}", y.parse::<u64>().unwrap()); - // serial_println!("NUM: {:?}", y.parse::<u64>().unwrap()); - } else if y.starts_with('#') { - // ignore all # delimeted lines - } else { - // println!("STR: {:?}", y); - // serial_println!("STR: {:?}", y); - match y.trim() { - "NONE" => {} - "TAB" => {} - "SHIFT" => {} - "SCROLL_LOCK" => {} - "FUNCTION_1" => {} - "FUNCTION_2" => {} - "FUNCTION_3" => {} - "FUNCTION_4" => {} - "FUNCTION_5" => {} - "FUNCTION_6" => {} - "FUNCTION_7" => {} - "FUNCTION_8" => {} - "FUNCTION_9" => {} - "FUNCTION_10" => {} - "FUNCTION_11" => {} - "FUNCTION_12" => {} - "COMMA" => {} - "PERIOD" => {} - "FORWARDSLASH" => {} - "GRAVE" => {} - "BRACKET_LEFT" => {} - "BACK_SLASH" => {} - "BRACKET_RIGHT" => {} - "QUOTE" => {} - _ => {} - } - } - } - } -} diff --git a/ableos/src/keyboard/small_types.rs b/ableos/src/keyboard/small_types.rs deleted file mode 100644 index 31661a6..0000000 --- a/ableos/src/keyboard/small_types.rs +++ /dev/null @@ -1,296 +0,0 @@ -#![allow(non_snake_case)] - -#[derive(Debug)] -pub struct Modifiers { - pub lshift: bool, - pub rshift: bool, - pub lctrl: bool, - pub rctrl: bool, - pub numlock: bool, - pub capslock: bool, - pub alt_gr: bool, -} - -impl Modifiers { - pub fn is_shifted(&self) -> bool { - self.lshift | self.rshift - } - - pub fn is_ctrl(&self) -> bool { - self.lctrl | self.rctrl - } - - pub fn is_caps(&self) -> bool { - self.capslock - } -} - -#[derive(Debug, PartialEq, Eq, Copy, Clone)] -pub enum KeyState { - Up, - Down, -} -#[derive(Debug, PartialEq, Eq, Clone)] -pub struct KeyEvent { - pub code: KeyCode, - pub state: KeyState, -} - -impl KeyEvent { - pub fn new(code: KeyCode, state: KeyState) -> KeyEvent { - KeyEvent { code, state } - } -} - -#[derive(Debug, PartialEq, Eq, Copy, Clone)] -pub enum HandleControl { - /// If either Ctrl key is held down, convert the letters A through Z into - /// Unicode chars U+0001 through U+001A. If the Ctrl keys are not held - /// down, letters go through normally. - MapLettersToUnicode, - /// Don't do anything special - send through the Ctrl key up/down events, - /// and leave the letters as letters. - Ignore, -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub enum DecodeState { - Start, - Extended, - Release, - ExtendedRelease, -} - -/// Indicates different error conditions. -#[derive(Debug, PartialEq, Eq, Copy, Clone)] -pub enum Error { - BadStartBit, - BadStopBit, - ParityError, - UnknownKeyCode, - InvalidState, -} - -#[derive(Debug, PartialEq, Eq, Copy, Clone)] -#[repr(u8)] -pub enum DecodedKeyKind { - RawKey = 0, - Unicode = 1, -} -#[derive(Debug, PartialEq, Eq, Copy, Clone)] -#[repr(C)] -pub struct DecodedKey { - pub kind: DecodedKeyKind, - pub value: u32, -} - -impl From<char> for DecodedKey { - fn from(ch: char) -> Self { - Self { - kind: DecodedKeyKind::Unicode, - value: ch as u32, - } - } -} - -impl From<KeyCode> for DecodedKey { - fn from(kc: KeyCode) -> Self { - Self { - kind: DecodedKeyKind::RawKey, - value: kc as u32, - } - } -} - -impl DecodedKey { - pub const ZERO: Self = Self { - kind: DecodedKeyKind::Unicode, - value: 0, - }; - pub fn Unicode(ch: char) -> Self { - Self { - kind: DecodedKeyKind::Unicode, - value: ch.into(), - } - } - pub fn RawKey(byte: u8) -> Self { - Self { - kind: DecodedKeyKind::RawKey, - value: byte.into(), - } - } -} - -macro_rules! keycode_enum { - (@get_last $Variant:ident) => { - Self::$Variant - }; - (@get_last $Variant:ident, $($VariantTail:ident),*) => { - keycode_enum![@get_last $($VariantTail),*] - }; - ($($Variant:ident=$Value:expr,)*) => { - #[derive(Debug, PartialEq, Eq, Clone, Copy)] - #[repr(u8)] - pub enum KeyCode { - $($Variant = $Value),* - } - - impl core::convert::From<u32> for KeyCode { - fn from(n: u32) -> Self { - match n { - $($Value => Self::$Variant),*, - _ => keycode_enum![@get_last $($Variant),*] - } - } - } - }; - ($($Variant:ident=$Value:expr),* ) => { - keycode_enum!($($Variant=$Value,)* ); - }; -} - -// This will be a way to map keys to other keys / keyyngs / macros -keycode_enum! { - AltLeft = 0x00, - AltRight = 0x01, - - ArrowDown = 0x02, - ArrowLeft = 0x03, - ArrowRight = 0x04, - ArrowUp = 0x05, - - BackSlash = 0x06, - Backspace = 0x07, - BackTick = 0x08, - - BracketSquareLeft = 0x09, - BracketSquareRight = 0x0A, - - CapsLock = 0x0B, - - Comma = 0x0C, - - ControlLeft = 0x0D, - ControlRight = 0x0E, - - Delete = 0x0F, - End = 0x10, - Enter = 0x11, - Escape = 0x12, - Equals = 0x13, - - F1 = 0x14, - F2 = 0x15, - F3 = 0x16, - F4 = 0x17, - F5 = 0x18, - F6 = 0x19, - F7 = 0x1A, - F8 = 0x1B, - F9 = 0x1C, - F10 = 0x1D, - F11 = 0x1E, - F12 = 0x1F, - - Fullstop = 0x20, - - Home = 0x21, - - Insert = 0x22, - - Key1 = 0x23, - Key2 = 0x24, - Key3 = 0x25, - Key4 = 0x26, - Key5 = 0x27, - Key6 = 0x28, - Key7 = 0x29, - Key8 = 0x2A, - Key9 = 0x2B, - Key0 = 0x2C, - - Menus = 0x2D, - - Minus = 0x2E, - - Numpad0 = 0x2F, - Numpad1 = 0x30, - Numpad2 = 0x31, - Numpad3 = 0x32, - Numpad4 = 0x33, - Numpad5 = 0x34, - Numpad6 = 0x35, - Numpad7 = 0x36, - Numpad8 = 0x37, - Numpad9 = 0x38, - - NumpadEnter = 0x39, - NumpadLock = 0x3A, - NumpadSlash = 0x3B, - NumpadStar = 0x3C, - NumpadMinus = 0x3D, - NumpadPeriod = 0x3E, - NumpadPlus = 0x3F, - - PageDown = 0x40, - PageUp = 0x41, - - PauseBreak = 0x42, - PrintScreen = 0x43, - ScrollLock = 0x44, - SemiColon = 0x45, - - ShiftLeft = 0x46, - ShiftRight = 0x47, - - Slash = 0x48, - Spacebar = 0x49, - Tab = 0x4A, - Quote = 0x4B, - WindowsLeft = 0x4C, - WindowsRight = 0x4D, - - A = 0x4E, - B = 0x4F, - C = 0x50, - D = 0x51, - E = 0x52, - F = 0x53, - G = 0x54, - H = 0x55, - I = 0x56, - J = 0x57, - K = 0x58, - L = 0x59, - M = 0x5A, - N = 0x5B, - O = 0x5C, - P = 0x5D, - Q = 0x5E, - R = 0x5F, - S = 0x60, - T = 0x61, - U = 0x62, - V = 0x63, - W = 0x64, - X = 0x65, - Y = 0x66, - Z = 0x67, - - HashTilde = 0x68, - - PrevTrack = 0x69, - NextTrack = 0x6A, - - Mute = 0x6B, - - Calculator = 0x6C, - - Play = 0x6D, - Stop = 0x6E, - VolumeDown = 0x6F, - VolumeUp = 0x70, - - WWWHome = 0x71, - PowerOnTestOk = 0x72, -} diff --git a/ableos/src/keyboard/traits.rs b/ableos/src/keyboard/traits.rs deleted file mode 100644 index 9be9296..0000000 --- a/ableos/src/keyboard/traits.rs +++ /dev/null @@ -1,26 +0,0 @@ -use super::Error; -use crate::{DecodeState, DecodedKey, HandleControl, KeyCode, KeyEvent, Modifiers}; - -pub trait ScancodeSet { - /// Handles the state logic for the decoding of scan codes into key events. - fn advance_state(&self, state: &mut DecodeState, code: u8) -> Result<Option<KeyEvent>, Error>; - - /// Convert a Scan Code set X byte to our 'KeyType' enum - fn map_scancode(&self, code: u8) -> Result<KeyCode, Error>; - - /// Convert a Scan Code Set X extended byte (prefixed E0) to our `KeyType` - /// enum. - fn map_extended_scancode(&self, code: u8) -> Result<KeyCode, Error>; -} - -pub trait KeyboardLayout { - /// Convert a `KeyType` enum to a Unicode character, if possible. - /// `KeyType::A` maps to `Some('a')` (or `Some('A')` if shifted), while - /// `KeyType::AltLeft` returns `None` - fn map_keycode( - &self, - keycode: KeyCode, - modifiers: &Modifiers, - handle_ctrl: HandleControl, - ) -> DecodedKey; -} diff --git a/ableos/src/kmain.rs b/ableos/src/kmain.rs deleted file mode 100644 index 5bf23c6..0000000 --- a/ableos/src/kmain.rs +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -#![allow(clippy::empty_loop)] - -use core::sync::atomic::AtomicU64; - -use crate::arch::memory::BootInfoFrameAllocator; -use crate::arch::{drivers::sysinfo::master, init, sloop}; -use crate::devices::pci; -use crate::relib::network::socket::{SimpleSock, Socket}; -use crate::{boot_conf::KernelConfig, scratchpad, systeminfo::RELEASE_TYPE, TERM}; -use crate::{filesystem, hardware}; -use kernel::KERNEL_VERSION; -use spin::Lazy; - -// FIXME: platform agnostic paging stuff -use x86_64::structures::paging::{Mapper, Size4KiB}; - -// TODO: Change this structure to allow for multiple cores loaded -pub static KERNEL_CONF: Lazy<KernelConfig> = Lazy::new(KernelConfig::new); - -/// The main entry point of the kernel -pub fn kernel_main( - mut mapper: impl Mapper<Size4KiB>, - mut frame_allocator: BootInfoFrameAllocator, -) -> ! { - init::init(); - - // /* - if KERNEL_CONF.logging.enabled { - log::set_max_level(KERNEL_CONF.log_level()); - // println!("{:#?}", *KERNEL_CONF); - } else { - log::set_max_level(log::LevelFilter::Off); - } - // */ - // let mut term = TERM.lock(); - // term.initialize(); - // term.set_dirty(true); - // term.draw_term(); - // drop(term); - - pci::init(&mut mapper, &mut frame_allocator); - - x86_64::instructions::interrupts::without_interrupts(|| { - hardware::init_mouse(); - }); - - filesystem::init().unwrap(); - - /* - - // println!("abc"); - let mut ipc_service = IPC.lock(); - // create some channels or whatever here then drop it - let log_handle = ipc_service.create_channel("LOG", true); - let log_sock_handle = ipc_service.create_socket("LOG", true); - - for handle in ipc_service.examine_board() { - // println!("Discovered: {}", handle); - } - - drop(ipc_service); - - - */ - - // use x86_ata::{init, ATA_BLOCK_SIZE}; - // 1. Initialise ATA Subsystem. (Perform Once, on boot) - // init().expect("Failed To Start ATA..."); - // let mut buffer: [u8; ATA_BLOCK_SIZE] = [0; ATA_BLOCK_SIZE]; - // FIXME: Calls to read panic the kernel - // read(0, 0, 0, &mut buffer); - - // for abc in list() { - // trace!("{:?}", abc); - // } - /* - log_version_data(); - // */ - scratchpad(); - sloop() -} - -pub fn traceloop() { - // TODO: Having an empty function double faults - - // let mut last_time = 0.0; - /* - loop { - // FIXME: the following double faults - /* - let time = fetch_time(); - if time > last_time { - last_time = time; - trace!("Timer"); - } - */ - } - - */ - - /* TODO: This also double faults - let fs = &*crate::filesystem::FILE_SYSTEM.lock(); - let path = format!("/home/able/bins/aos_test.wasm"); - - let home_exec_file = fs.open(&path.as_bytes(), OpenOptions::new().read(true)); - - drop(fs); - let mut binary_prog: Vec<u8> = vec![]; - - match home_exec_file { - Ok(file) => { - let ret = file.read_to_end(&mut binary_prog).unwrap(); - } - _ => {} - } - - wasm_jumploader::run_program(&binary_prog); - */ -} - -pub fn cpu_socket_startup() { - let mut cpu_info_socket = SimpleSock::new(); - cpu_info_socket.register_protocol("CPU_INFO".to_string()); - - // let x = master().unwrap(); - // let _xyz = x.brand_string().unwrap(); -} - -pub fn log_version_data() { - info!("{} v{}", RELEASE_TYPE, KERNEL_VERSION); - info!( - "Brand String: {}", - master().unwrap().brand_string().unwrap() - ); -} - -pub static TICK: AtomicU64 = AtomicU64::new(0); - -pub fn tick() { - x86_64::instructions::interrupts::without_interrupts(|| { - let mut term = TERM.lock(); - - term.draw_term(); - use core::sync::atomic::Ordering::Relaxed; - - let mut data = TICK.load(Relaxed); - data = data.wrapping_add(1); - - TICK.store(data, Relaxed); - }); -} diff --git a/ableos/src/lib.rs b/ableos/src/lib.rs deleted file mode 100644 index 985e40f..0000000 --- a/ableos/src/lib.rs +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2022, Able <able@ablecorp.us> - * Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -//! main library for the AbleOS kernel. -//! exposing all the kernel functionality to the rest of the kernel. -//! -//! - -#![no_std] -#![feature( - abi_x86_interrupt, - alloc_error_handler, - arbitrary_enum_discriminant, - asm_sym, // Needed for RISC-V - custom_test_frameworks, - naked_functions, - prelude_import, -)] -#![reexport_test_harness_main = "test_main"] -#![test_runner(crate::test_runner)] - -#[macro_use] -pub extern crate log; - -#[macro_use] -pub extern crate bitflags; - -pub extern crate alloc; -pub extern crate externc_libm as libm; - -/// Contains architecture specific code for aarch64. -#[cfg(target_arch = "aarch64")] -#[path = "arch/aarch64/mod.rs"] -pub mod arch; - -/// Contains architecture specific code for riscv64. -#[cfg(target_arch = "riscv64")] -#[path = "arch/riscv/mod.rs"] -pub mod arch; - -/// Contains architecture specific code for x86_64. -#[cfg(target_arch = "x86_64")] -#[path = "arch/x86_64/mod.rs"] -pub mod arch; - -#[cfg(target_arch = "x86_64")] -pub mod port_io; - -#[macro_use] -pub mod print; - -#[macro_use] -pub mod serial_print; - -pub mod boot_conf; -pub mod device_interface; -pub mod devices; -pub mod driver_traits; -pub mod experiments; -pub mod filesystem; -pub mod graphics; -pub mod kernel_state; -pub mod keyboard; -pub mod kmain; -pub mod logger; -pub mod prelude; -pub mod ps2_mouse; -pub mod relib; -pub mod rhai_shell; -pub mod scratchpad; -pub mod stdio; -pub mod time; -pub mod utils; -pub mod virtio; -pub mod wasm; -pub mod wasm_jumploader; - -pub mod allocator; - -// pub use allocator as aalloc; -pub mod handle; -pub mod hardware; -pub mod ipc; -pub mod panic; -mod unicode_utils; -pub mod vga_e; -pub mod vterm; -// pub mod vgai; - -#[prelude_import] -pub use prelude::rust_2021::*; - -pub use driver_traits::*; -pub use experiments::*; -pub use graphics::*; -pub use kernel; -// pub use kernel::panic; -pub use kernel_state::*; -pub use keyboard::*; -pub use logger::*; -pub use relib::*; -pub use scratchpad::*; -pub use utils::*; -pub use virtio::*; -pub use wasm::*; - -#[cfg(test)] -pub mod tests; - -#[cfg(test)] -pub use tests::test_kernel_main; - -#[cfg(test)] -use crate::tests::test_runner; diff --git a/ableos/src/logger.rs b/ableos/src/logger.rs deleted file mode 100644 index 1dd878e..0000000 --- a/ableos/src/logger.rs +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2022, Able <able@ablecorp.us> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -use crate::{kmain::KERNEL_CONF, time::fetch_time}; -use lliw::Fg; -use log::{Level, LevelFilter, Metadata, Record, SetLoggerError}; - -static LOGGER: SimpleLogger = SimpleLogger; -// TODO: Rebuild this to take advantage of sockets -// DETAIL: Log to a socket instead of the screen -// So that we can log in the kernel and display it in userland -struct SimpleLogger; -impl log::Log for SimpleLogger { - fn enabled(&self, metadata: &Metadata) -> bool { - metadata.level() <= Level::Trace - } - fn log(&self, record: &Record) { - x86_64::instructions::interrupts::without_interrupts(|| { - if self.enabled(record.metadata()) { - let time_float = fetch_time(); - use Fg::*; - - let color = match record.level() { - log::Level::Error => (Fg::Red, "\0RED\0"), - log::Level::Warn => (Fg::LightYellow, "\0LIGHTYELLOW\0"), - log::Level::Info => (Fg::LightWhite, "\0LIGHTGREY\0"), - log::Level::Debug => (Fg::Blue, "\0BLUE\0"), - log::Level::Trace => (Fg::Yellow, "\0YELLOW\0"), - }; - - let mod_path = match record.module_path() { - Some(p) => { - if KERNEL_CONF.logging.filter.contains(&p.to_string()) { - return; - } - - p - } - None => "unknown", - }; - - let line = match record.line() { - Some(line_number) => line_number, - None => 0, - }; - - if KERNEL_CONF.logging.log_to_vterm { - let msg = format!( - // "[{}{}$RESET$][$GREEN${}$RESET$]{}\n", - "[{}{:05}\0RESET\0][\0GREEN\0{}\0RESET\0][\0BLUE\0{}@{}\0RESET\0] {}", - color.1, - record.level(), - time_float, - mod_path, - line, - record.args(), - ); - - println!("{msg}"); - } - - if KERNEL_CONF.logging.log_to_serial { - serial_println!( - "[{}{:05}{}][{}{}{}][{}{}@{}{}] {}", - color.0, - record.level(), - Reset, - Green, - time_float, - Reset, - Blue, - mod_path, - line, - Reset, - record.args() - ); - } - } - }); - } - /// Clear the log buffer - fn flush(&self) {} -} - -pub fn init() -> Result<(), SetLoggerError> { - log::set_logger(&LOGGER).map(|()| log::set_max_level(LevelFilter::Trace)) - // ?; - - // trace!("Logger started"); - - // Ok(()) -} diff --git a/ableos/src/panic.rs b/ableos/src/panic.rs deleted file mode 100644 index 609b2a6..0000000 --- a/ableos/src/panic.rs +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2022, able <abl3theabove@gmail.com> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -use core::panic::PanicInfo; -use log::error; - -use crate::arch::interrupts::{bsod, BSODSource}; -#[cfg(not(test))] -#[panic_handler] -fn panic_handler(info: &PanicInfo) -> ! { - error!("{:?}", info); - - bsod(BSODSource::Panic(info)); -} diff --git a/ableos/src/port_io.rs b/ableos/src/port_io.rs deleted file mode 100644 index 95bb1a2..0000000 --- a/ableos/src/port_io.rs +++ /dev/null @@ -1,24 +0,0 @@ -use cpuio::{inb, inl, inw, outb, outl, outw}; - -pub fn read32(reg: u16) -> u32 { - unsafe { inl(reg) } -} -pub fn read16(reg: u16) -> u16 { - unsafe { inw(reg) as u16 } -} - -pub fn read8(reg: u16) -> u8 { - unsafe { inb(reg) } -} - -pub fn write32(reg: u16, val: u32) { - unsafe { outl(val, reg) } -} - -pub fn write16(reg: u16, val: u16) { - unsafe { outw(val, reg) } -} - -pub fn write8(reg: u16, val: u8) { - unsafe { outb(val, reg) } -} diff --git a/ableos/src/prelude/mod.rs b/ableos/src/prelude/mod.rs deleted file mode 100644 index 9d3a594..0000000 --- a/ableos/src/prelude/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod rust_2021; - -pub use core::assert; -pub use core::option::Option::Some; -pub use core::option::*; diff --git a/ableos/src/prelude/rust_2021.rs b/ableos/src/prelude/rust_2021.rs deleted file mode 100644 index 2e95f7d..0000000 --- a/ableos/src/prelude/rust_2021.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub use crate::print::*; -pub use crate::serial_print::*; -pub use alloc::{boxed::Box, format, string::*, vec, vec::*}; -pub use core::arch::asm; - -pub use core::prelude::rust_2021::*; -pub use core::prelude::v1::*; -pub use core::result::Result::*; -pub use log::{debug, info, trace, warn}; diff --git a/ableos/src/print.rs b/ableos/src/print.rs deleted file mode 100644 index 6af2a8f..0000000 --- a/ableos/src/print.rs +++ /dev/null @@ -1,79 +0,0 @@ -// TODO: refactor this file -// TODO: make STDOUT redirect to a socket owned -// by the process named "stdout" - -use core::fmt::{Arguments, Error}; - -pub struct Stdout; -impl Stdout { - pub fn write_fmt(&mut self, arg: Arguments<'_>) /*-> Result<(), Error> */ - { - let _ = core::fmt::Write::write_fmt(self, arg); - // Ok(()) - } -} - -impl core::fmt::Write for Stdout { - #[cfg(target_arch = "aarch64")] - fn write_str(&mut self, s: &str) -> Result<(), Error> { - // Don't actually print anything yet lmao - Ok(()) - } - #[cfg(target_arch = "x86_64")] - fn write_str(&mut self, s: &str) -> Result<(), Error> { - // use mini_backtrace::Backtrace; - - use crate::TERM; - - // Capture up to 16 frames. This is returned using an ArrayVec that doesn't - // perform any dynamic memory allocation. - /* - let bt = Backtrace::<16>::capture(); - trace!("Backtrace:"); - for frame in bt.frames { - trace!(" {:#x}", frame); - } - if bt.frames_omitted { - trace!(" ... <frames omitted>"); - } - */ - - // trace!("printing"); - // x86_64::instructions::interrupts::without_interrupts(|| { - let mut term = TERM.lock(); - - term.set_dirty(true); - term.print(s); - - drop(term); - // }); - // trace!("Finished printing"); - Ok(()) - } - #[cfg(target_arch = "riscv64")] - fn write_str(&mut self, s: &str) -> Result<(), Error> { - Ok(()) - } - fn write_char(&mut self, c: char) -> core::fmt::Result { - self.write_str(c.encode_utf8(&mut [0; 4])) - } - fn write_fmt(mut self: &mut Self, args: Arguments<'_>) -> core::fmt::Result { - core::fmt::write(&mut self, args) - } -} - -#[macro_export] -macro_rules! print { - () => { - ::core::writeln!($crate::print::Stdout, "") - }; - ($($tt:tt)*) => { - ::core::write!($crate::print::Stdout, $($tt)*) - }; -} -#[macro_export] -macro_rules! println { - ($($tt:tt)*) => { - ::core::writeln!($crate::print::Stdout, $($tt)*) - }; -} diff --git a/ableos/src/ps2_mouse.rs b/ableos/src/ps2_mouse.rs deleted file mode 100644 index aa61930..0000000 --- a/ableos/src/ps2_mouse.rs +++ /dev/null @@ -1,300 +0,0 @@ -use bitflags::bitflags; -use x86_64::instructions::port::Port; - -const ADDRESS_PORT_ADDRESS: u16 = 0x64; -const DATA_PORT_ADDRESS: u16 = 0x60; -const GET_STATUS_BYTE: u8 = 0x20; -const SET_STATUS_BYTE: u8 = 0x60; - -const DISABLE_FIRST: u8 = 0xAD; -const DISABLE_SECOND: u8 = 0xA7; -const ENABLE_FIRST: u8 = 0xAE; -const ENABLE_SECOND: u8 = 0xA8; - -bitflags! { - /// Represents the flags currently set for the mouse. - #[derive(Default)] - pub struct MouseFlags: u8 { - /// Whether or not the left mouse button is pressed. - const LEFT_BUTTON = 0b0000_0001; - - /// Whether or not the right mouse button is pressed. - const RIGHT_BUTTON = 0b0000_0010; - - /// Whether or not the middle mouse button is pressed. - const MIDDLE_BUTTON = 0b0000_0100; - - /// Whether or not the packet is valid or not. - const ALWAYS_ONE = 0b0000_1000; - - /// Whether or not the x delta is negative. - const X_SIGN = 0b0001_0000; - - /// Whether or not the y delta is negative. - const Y_SIGN = 0b0010_0000; - - /// Whether or not the x delta overflowed. - const X_OVERFLOW = 0b0100_0000; - - /// Whether or not the y delta overflowed. - const Y_OVERFLOW = 0b1000_0000; - } -} - -#[repr(u8)] -enum Command { - EnablePacketStreaming = 0xF4, - SetDefaults = 0xF6, -} - -/// A basic interface to interact with a PS2 mouse. -#[derive(Debug)] -pub struct Mouse { - command_port: Port<u8>, - data_port: Port<u8>, - current_packet: u8, - current_state: MouseState, - completed_state: MouseState, - on_complete: Option<fn(MouseState)>, -} - -impl Default for Mouse { - fn default() -> Mouse { - Mouse::new() - } -} - -/// A snapshot of the mouse flags, x delta and y delta. -#[derive(Debug, Copy, Clone, Default)] -pub struct MouseState { - flags: MouseFlags, - x: i16, - y: i16, -} - -impl MouseState { - /// Returns a new `MouseState`. - pub const fn new() -> MouseState { - MouseState { - flags: MouseFlags::empty(), - x: 0, - y: 0, - } - } - - /// Returns true if the left mouse button is currently down. - pub fn _left_button_down(&self) -> bool { - self.flags.contains(MouseFlags::LEFT_BUTTON) - } - - /// Returns true if the left mouse button is currently up. - pub fn _left_button_up(&self) -> bool { - !self.flags.contains(MouseFlags::LEFT_BUTTON) - } - - /// Returns true if the right mouse button is currently down. - pub fn _right_button_down(&self) -> bool { - self.flags.contains(MouseFlags::RIGHT_BUTTON) - } - - /// Returns true if the right mouse button is currently up. - pub fn _right_button_up(&self) -> bool { - !self.flags.contains(MouseFlags::RIGHT_BUTTON) - } - - /// Returns true if the x axis has moved. - pub fn _x_moved(&self) -> bool { - self.x != 0 - } - - /// Returns true if the y axis has moved. - pub fn _y_moved(&self) -> bool { - self.y != 0 - } - - /// Returns true if the x or y axis has moved. - pub fn _moved(&self) -> bool { - self._x_moved() || self._y_moved() - } - - /// Returns the x delta of the mouse state. - pub fn get_x(&self) -> i16 { - self.x - } - - /// Returns the y delta of the mouse state. - pub fn get_y(&self) -> i16 { - self.y - } -} - -impl Mouse { - /// Creates a new `Mouse`. - pub const fn new() -> Mouse { - Mouse { - command_port: Port::new(ADDRESS_PORT_ADDRESS), - data_port: Port::new(DATA_PORT_ADDRESS), - current_packet: 0, - current_state: MouseState::new(), - completed_state: MouseState::new(), - on_complete: None, - } - } - - /// Returns the last completed state of the mouse. - pub fn _get_state(&self) -> MouseState { - self.completed_state - } - - // super helpful resource, albeit in C - // https://github.com/29jm/SnowflakeOS/blob/master/kernel/src/devices/ps2.c#L18 - /// Attempts to initialize a `Mouse`. If successful, interrupts will be generated - /// as `PIC offset + 12`. - pub fn init(&mut self) -> Result<(), &'static str> { - // Disable both PS/2 device ports - // Even if only one is present, disabling the second is harmless - self.write_command_port(DISABLE_FIRST)?; - self.write_command_port(DISABLE_SECOND)?; - - // Flush output buffer: if the controller had anything to say, ignore it - unsafe { - self.data_port.read(); - } - - debug!("mouse driver: writing GET_STATUS to port..."); - self.write_command_port(GET_STATUS_BYTE)?; - debug!("mouse driver: reading status from port..."); - let status = self.read_data_port()? | 0x02; - - debug!("Got status {}", status); - - // self.write_command_port(0xa8)?; - - self.write_command_port(SET_STATUS_BYTE)?; - - self.write_data_port(status & 0xDF)?; - - self.send_command(Command::SetDefaults)?; - self.send_command(Command::EnablePacketStreaming)?; - - self.write_command_port(ENABLE_FIRST)?; - self.write_command_port(ENABLE_SECOND)?; - - // Some keyboards actually send a reply, flush it - unsafe { - self.data_port.read(); - } - - Ok(()) - } - - /// Attempts to process a packet. - pub fn process_packet(&mut self, packet: u8) { - match self.current_packet { - 0 => { - let flags = MouseFlags::from_bits_truncate(packet); - if !flags.contains(MouseFlags::ALWAYS_ONE) { - return; - } - self.current_state.flags = flags; - } - 1 => self.process_x_movement(packet), - 2 => { - self.process_y_movement(packet); - self.completed_state = self.current_state; - if let Some(on_complete) = self.on_complete { - on_complete(self.completed_state); - } - } - _ => unreachable!(), - } - self.current_packet = (self.current_packet + 1) % 3; - } - - /// Sets the `on_complete` function to be called when a packet is completed. - pub fn set_on_complete(&mut self, handler: fn(MouseState)) { - self.on_complete = Some(handler); - } - - fn process_x_movement(&mut self, packet: u8) { - if !self.current_state.flags.contains(MouseFlags::X_OVERFLOW) { - self.current_state.x = if self.current_state.flags.contains(MouseFlags::X_SIGN) { - self.sign_extend(packet) - } else { - packet as i16 - }; - } - } - - fn process_y_movement(&mut self, packet: u8) { - if !self.current_state.flags.contains(MouseFlags::Y_OVERFLOW) { - self.current_state.y = if self.current_state.flags.contains(MouseFlags::Y_SIGN) { - self.sign_extend(packet) - } else { - packet as i16 - }; - } - } - - fn read_data_port(&mut self) -> Result<u8, &'static str> { - // INFO: What the fuck - debug!("owo"); - self.wait_for_read()?; - // HERESY: Stop - debug!("what's this"); - Ok(unsafe { self.data_port.read() }) - } - - fn send_command(&mut self, command: Command) -> Result<(), &'static str> { - self.write_command_port(0xD4)?; - self.write_data_port(command as u8)?; - if self.read_data_port()? != 0xFA { - return Err("mouse did not respond to the command"); - } - Ok(()) - } - - fn sign_extend(&self, packet: u8) -> i16 { - ((packet as u16) | 0xFF00) as i16 - } - - fn write_command_port(&mut self, value: u8) -> Result<(), &'static str> { - debug!("mouse driver: waiting for write"); - self.wait_for_write()?; - unsafe { - self.command_port.write(value); - } - debug!("mouse driver: command written"); - Ok(()) - } - - fn write_data_port(&mut self, value: u8) -> Result<(), &'static str> { - self.wait_for_write()?; - unsafe { - self.data_port.write(value); - } - Ok(()) - } - - fn wait_for_read(&mut self) -> Result<(), &'static str> { - let timeout = 100_000; - for _x in 0..timeout { - let value = unsafe { self.command_port.read() }; - if (value & 0x1) == 0x1 { - return Ok(()); - } - } - Err("wait for mouse read timeout") - } - - fn wait_for_write(&mut self) -> Result<(), &'static str> { - let timeout = 100_000; - for _ in 0..timeout { - let value = unsafe { self.command_port.read() }; - if (value & 0x2) == 0x0 { - return Ok(()); - } - } - Err("wait for mouse write timeout") - } -} diff --git a/ableos/src/relib/clparse/mod.rs b/ableos/src/relib/clparse/mod.rs deleted file mode 100644 index d280f2f..0000000 --- a/ableos/src/relib/clparse/mod.rs +++ /dev/null @@ -1,63 +0,0 @@ -/// # clparse -/// simple command line parser for ableOS - -#[derive(Debug, Clone)] -pub struct Argument { - key: String, - value: String, -} - -#[derive(Debug, Clone)] -pub struct Command { - pub root_command: String, - // arguments: HashMap<String, String>, - pub arguments: Vec<Argument>, -} - -impl Command { - pub fn parse(command: String) -> Command { - let split_command = command.split('?'); - let mut root = "".to_string(); - let mut args: Vec<Argument> = vec![]; - for (root_count, subcommand) in split_command.enumerate() { - match root_count { - 0 => root = subcommand.to_string(), - 1 => { - for subarg in subcommand.split('&') { - let mut arg1 = ""; - let mut arg2 = ""; - for (n, arg) in subarg.split('=').enumerate() { - if n == 0 { - arg1 = arg; - } else { - arg2 = arg; - } - } - let arg_struct = Argument { - key: arg1.to_string(), - value: arg2.to_string(), - }; - args.push(arg_struct); - } - } - _ => {} - } - } - - Command { - root_command: root, - arguments: args, - } - } -} - -pub fn test() { - let x = Command::parse("hi?there=uwu&hi=abc".to_string()); - - let y = &x.arguments[0]; - - trace!("{}", x.root_command); - trace!("{:?}", y); - trace!("{}", y.key); - trace!("{}", y.value); -} diff --git a/ableos/src/relib/encoding/bin.rs b/ableos/src/relib/encoding/bin.rs deleted file mode 100644 index ad3cb14..0000000 --- a/ableos/src/relib/encoding/bin.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub struct BinCodeWriter { - pub stream: Box<u8>, -} diff --git a/ableos/src/relib/encoding/mod.rs b/ableos/src/relib/encoding/mod.rs deleted file mode 100644 index e8f2524..0000000 --- a/ableos/src/relib/encoding/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod bin; -pub mod rle; diff --git a/ableos/src/relib/encoding/rle.rs b/ableos/src/relib/encoding/rle.rs deleted file mode 100644 index f1d4953..0000000 --- a/ableos/src/relib/encoding/rle.rs +++ /dev/null @@ -1,42 +0,0 @@ -pub fn encode(bytes: &[u8]) -> Vec<u8> { - let mut encoding = if bytes.first().is_none() { - return vec![]; - } else { - vec![*bytes.first().unwrap()] - }; - - let mut occurrences = 1; - - for byte in bytes.iter().skip(1) { - if byte == encoding.last().unwrap() && occurrences < 255 { - occurrences += 1; - } else { - encoding.extend(&[occurrences, *byte]); - occurrences = 1; - } - } - - encoding.push(occurrences); - encoding -} - -/// Read a run-length encoding and return its decoded contents. -/// -/// - `bytes` - The bytes to be decoded. -pub fn decode(bytes: &[u8]) -> Vec<u8> { - let mut decoding = Vec::<u8>::new(); - - for (i, byte) in bytes.iter().enumerate() { - if i % 2 != 0 { - continue; - } - - // Repeat bytes[i], bytes[i+1] times in a row. - // e.g.: "!!" equals to 33 times "!" ("!" value in ASCII). - for _j in 0..bytes[i + 1] { - decoding.push(*byte) - } - } - - decoding -} diff --git a/ableos/src/relib/image/mod.rs b/ableos/src/relib/image/mod.rs deleted file mode 100644 index 51c18fa..0000000 --- a/ableos/src/relib/image/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod mono_bitmap; diff --git a/ableos/src/relib/image/mono_bitmap.rs b/ableos/src/relib/image/mono_bitmap.rs deleted file mode 100644 index 6995620..0000000 --- a/ableos/src/relib/image/mono_bitmap.rs +++ /dev/null @@ -1,40 +0,0 @@ -use crate::relib::encoding::rle::{decode, encode}; -use crate::vga_e::VGAE; - -use vga::writers::GraphicsWriter; - -pub fn bruh() { - #[rustfmt::skip] - let xyz_new = encode(&[255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,255,255,254,254,254,255,254,254,254,254,255,255,255,254,254,254,255,255,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,254,253,254,254,253,254,254,254,254,254,254,254,254,254,254,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,253,253,253,253,254,254,253,253,254,253,253,254,255,254,254,254,254,253,253,253,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,254,254,252,251,251,251,251,252,250,251,252,252,252,252,251,253,254,254,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,252,247,241,226,209,201,201,197,190,200,211,198,187,187,179,162,157,164,191,220,234,242,250,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,254,254,254,254,253,247,241,233,209,174,149,130,105,112,123,100,70,69,80,80,74,60,43,30,29,34,54,79,96,131,180,211,234,250,254,254,254,254,254,254,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,254,253,254,254,254,249,234,199,140,106,106,97,53,36,37,27,25,40,41,16,7,5,8,12,10,4,1,1,2,5,7,7,12,37,82,103,141,203,241,253,254,253,253,253,253,253,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,251,244,230,201,117,66,56,36,21,28,30,25,9,3,3,4,4,1,1,1,2,2,5,6,5,7,10,3,1,3,6,5,9,12,11,30,92,172,224,247,253,253,253,253,253,252,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,249,244,235,211,174,118,51,56,109,61,10,6,29,71,40,8,1,0,0,0,1,3,4,2,3,5,9,14,16,7,2,4,9,6,1,2,5,33,61,55,69,133,204,244,253,253,254,252,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,255,254,254,254,254,254,254,254,254,255,254,253,252,239,190,163,175,178,138,71,43,49,85,53,9,2,12,48,51,12,1,1,0,0,0,2,7,6,3,3,6,9,6,5,5,2,3,10,5,8,30,78,86,37,12,25,71,149,229,252,253,253,253,255,255,255,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,254,254,254,254,254,253,254,253,254,254,250,223,175,126,66,37,38,46,55,74,75,25,10,11,15,25,22,11,9,2,5,16,19,12,12,9,12,27,46,43,20,12,9,11,14,8,6,15,29,44,56,42,25,24,41,55,40,32,100,193,239,253,254,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,249,247,251,254,253,250,227,166,83,35,15,15,12,6,1,4,25,46,16,0,2,24,73,54,21,4,6,39,74,75,115,115,51,35,76,152,168,99,72,90,96,69,38,17,18,33,25,15,25,38,58,93,61,25,28,45,70,119,196,244,252,253,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,253,253,247,221,216,227,240,242,190,107,50,36,17,4,9,30,39,19,1,2,3,12,8,9,23,36,18,12,15,41,88,120,150,212,210,153,145,177,213,221,201,200,216,198,172,142,100,50,23,19,41,88,100,98,93,49,36,77,58,30,40,87,159,218,246,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,253,246,216,184,181,184,179,150,81,30,27,64,61,25,25,63,119,80,8,2,10,35,25,27,38,30,37,75,119,163,196,216,234,247,250,247,247,250,251,252,252,252,253,250,247,244,235,207,139,78,54,44,35,34,42,41,61,136,122,90,79,55,46,85,169,237,252,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,245,198,149,136,143,121,61,36,33,20,11,33,80,103,68,50,95,110,39,30,80,105,63,79,109,116,158,212,241,251,253,253,254,252,253,254,253,253,254,254,254,253,253,254,253,253,254,254,249,224,161,81,40,30,35,38,40,41,36,42,51,41,27,30,56,129,206,242,253,255,254,254,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,253,252,215,130,90,95,75,32,11,9,18,20,9,9,27,54,30,10,22,53,61,77,118,158,155,184,221,236,249,253,254,254,254,254,254,254,254,254,254,254,254,255,254,254,254,255,254,254,254,255,254,252,247,216,156,80,25,16,12,4,1,5,17,30,28,25,34,53,87,139,207,242,252,254,253,253,253,252,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,247,196,118,83,66,25,7,3,3,15,29,38,37,23,12,5,1,6,28,69,103,153,212,238,247,253,253,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,253,253,253,241,186,79,25,6,1,2,9,20,32,37,65,76,29,19,34,78,146,211,247,253,253,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,225,160,113,65,22,10,4,3,3,11,39,110,142,63,16,28,30,32,70,146,200,238,252,254,254,254,253,254,254,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,253,254,254,253,251,224,149,54,12,30,60,75,80,90,174,116,12,1,3,7,18,66,148,215,247,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,252,207,100,39,12,3,2,3,5,7,7,19,88,130,58,30,105,152,167,212,246,253,254,254,254,253,253,254,254,254,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,254,254,254,254,250,214,146,118,125,125,117,88,80,29,5,4,4,3,0,4,22,60,139,207,245,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,254,254,253,249,167,38,7,4,2,0,2,5,7,6,8,33,53,45,78,156,221,246,253,254,254,254,254,254,254,254,254,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,255,254,254,253,246,212,156,84,29,8,4,6,36,30,8,5,16,38,49,46,32,56,145,233,251,254,254,254,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,252,254,250,198,66,14,14,7,2,1,2,4,3,4,5,9,25,86,181,238,252,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,252,241,191,85,17,4,2,29,40,12,12,73,112,102,100,46,30,67,136,193,241,253,253,253,254,253,253,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,252,253,253,253,207,72,12,27,21,6,0,1,2,3,4,2,3,12,81,197,249,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,252,254,252,235,179,110,37,12,30,51,56,51,34,23,30,35,69,110,77,66,146,223,245,252,254,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,251,234,144,35,11,12,5,1,2,6,2,0,2,3,9,44,137,227,253,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,253,253,252,242,192,107,56,56,56,29,21,20,17,15,19,28,24,18,42,87,135,204,245,252,252,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,252,250,210,113,61,22,10,3,0,0,1,3,1,1,0,11,38,80,151,231,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,253,251,233,179,105,41,23,24,23,14,9,5,5,7,7,14,21,37,102,189,236,251,253,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,253,253,254,252,212,80,8,10,11,11,6,2,2,0,0,0,1,1,15,70,151,191,235,252,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,255,254,254,254,254,254,252,226,147,64,25,11,6,5,6,7,8,6,11,14,11,34,85,141,210,247,253,254,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,252,253,252,253,253,226,108,18,6,14,36,46,25,11,5,0,1,0,3,6,24,103,215,232,244,253,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,249,217,141,65,22,8,2,1,3,6,9,11,8,8,12,46,132,212,247,253,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,253,252,227,125,81,54,25,37,89,110,55,18,7,5,7,12,19,49,67,86,133,171,221,250,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,252,242,201,115,43,12,2,3,6,5,5,6,5,5,23,89,160,196,242,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,234,125,37,39,42,33,27,29,42,59,33,9,8,23,28,22,59,61,33,35,70,150,233,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,252,253,252,229,167,90,38,12,7,5,2,2,2,5,12,33,59,102,190,245,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,253,242,154,83,63,28,18,15,6,2,10,42,36,20,27,49,55,20,19,27,15,8,24,86,201,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,253,254,253,253,242,196,106,38,14,6,4,2,6,15,21,22,41,89,140,203,246,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,253,253,253,253,254,246,170,85,93,61,22,9,6,4,3,4,9,22,60,71,99,98,34,45,83,53,21,30,72,172,247,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,244,186,90,43,20,9,5,11,27,23,12,27,74,113,136,199,249,253,254,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,253,253,253,253,251,186,54,40,56,32,12,7,11,18,7,2,2,46,125,110,84,48,30,83,123,70,33,42,77,145,236,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,252,241,171,82,41,25,32,32,22,14,19,30,30,55,95,147,225,253,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,253,252,218,80,12,9,18,12,7,7,23,42,16,5,38,164,205,147,80,34,12,28,34,30,56,119,147,151,221,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,252,253,253,232,137,61,50,85,72,28,21,42,40,11,17,73,132,193,247,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,254,233,107,17,12,6,3,5,5,7,16,29,18,45,179,247,223,129,54,22,11,12,9,14,59,156,181,154,205,252,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,253,253,251,215,125,69,72,58,30,30,37,25,25,36,73,155,203,227,252,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,235,136,27,3,7,10,5,3,4,3,3,6,30,160,249,253,236,142,51,23,24,25,16,12,30,81,113,131,194,249,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,250,210,110,56,27,9,7,17,32,80,102,96,128,172,196,241,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,246,140,27,1,0,3,9,8,4,4,5,8,30,126,237,253,253,250,200,113,68,58,34,30,25,14,30,70,126,205,250,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,246,176,83,36,12,6,10,12,21,33,36,46,75,133,210,251,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,252,181,30,1,0,2,7,12,30,28,17,19,60,161,235,252,253,253,253,244,198,144,103,54,61,56,25,32,76,118,186,244,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,252,212,110,69,61,32,7,2,1,2,10,27,51,90,165,238,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,252,209,61,4,2,10,25,25,27,76,112,96,88,162,247,253,253,254,253,253,245,196,160,127,93,84,85,90,82,76,66,122,225,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,253,253,240,154,109,115,56,7,3,0,0,7,25,48,73,128,213,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,224,92,14,10,10,30,65,55,33,30,54,87,133,221,253,253,253,254,253,254,249,201,155,129,108,90,103,121,65,25,38,119,221,252,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,251,209,142,98,38,5,3,1,0,2,12,25,53,105,193,247,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,253,247,154,33,23,27,19,24,46,41,17,3,10,70,187,249,254,254,254,254,254,254,253,233,178,136,110,107,103,56,17,25,89,159,221,250,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,234,151,70,24,8,6,6,2,5,10,11,30,88,157,229,253,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,217,90,37,30,30,17,7,10,12,6,8,28,134,240,253,254,255,255,255,254,254,254,251,235,187,137,87,38,10,30,109,162,184,224,251,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,245,168,71,41,30,18,16,25,33,23,12,33,77,90,179,249,253,253,254,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,244,168,72,25,12,21,29,25,20,24,37,82,113,215,252,253,254,255,255,255,254,254,254,253,252,239,203,98,25,17,73,153,159,169,219,251,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,253,216,119,67,50,22,8,46,38,12,32,61,51,59,162,245,253,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,249,191,90,76,71,51,64,84,71,42,49,93,174,215,250,252,253,254,255,255,255,254,254,254,254,254,247,196,100,64,77,95,112,122,151,217,251,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,242,178,85,46,27,11,18,9,2,14,30,24,59,164,236,251,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,255,254,254,254,253,224,109,38,41,61,73,58,45,30,15,12,40,178,251,253,254,254,254,255,255,255,255,254,253,254,254,242,171,120,137,165,136,115,116,155,224,247,245,246,246,242,242,244,245,247,253,254,254,255,254,254,254,254,254,254,255,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,252,224,132,76,64,39,10,1,0,1,7,24,71,100,165,237,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,236,134,36,14,8,11,19,14,11,14,30,51,105,227,255,255,255,255,255,255,255,255,255,255,255,255,255,246,203,184,180,177,189,170,153,167,184,178,163,175,212,204,181,165,160,161,167,175,186,201,229,247,253,253,252,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,246,181,107,72,46,17,6,3,1,2,10,28,37,85,189,250,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,254,249,176,56,20,19,15,11,12,12,15,17,40,99,199,251,255,255,255,255,255,255,255,255,255,255,255,255,255,253,242,230,214,197,180,140,121,93,102,137,128,93,110,108,87,79,76,61,37,32,42,64,99,138,181,232,251,254,254,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,220,144,84,58,44,30,15,3,0,3,8,19,48,141,241,253,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,254,223,96,32,38,64,83,72,30,15,10,8,20,116,233,253,255,255,255,255,255,255,255,255,255,255,255,255,255,254,252,251,246,221,140,73,56,37,79,165,137,44,23,18,19,19,15,9,4,4,12,46,61,41,49,123,229,244,250,253,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,242,171,106,80,60,37,17,6,4,12,18,23,54,141,236,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,247,160,53,40,51,88,125,107,36,7,4,6,44,184,250,253,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,252,224,153,109,51,25,9,36,87,70,23,5,3,4,2,0,0,3,33,74,141,115,39,16,46,133,155,191,235,250,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,251,214,168,141,78,27,12,9,10,34,54,68,122,167,209,249,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,253,227,129,100,73,40,45,37,27,23,25,37,61,151,242,254,254,255,255,255,255,255,255,255,255,254,254,253,254,254,254,253,221,113,38,17,8,10,4,2,2,3,14,22,9,1,0,0,2,17,70,87,100,66,21,5,7,18,38,88,159,206,229,249,253,254,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,250,231,200,121,49,20,15,16,25,51,132,186,133,115,216,252,254,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,246,183,151,168,93,49,53,28,15,30,66,112,161,227,252,254,254,255,255,255,255,255,255,255,255,254,254,254,253,254,254,244,152,59,21,2,2,14,8,0,0,3,19,33,12,2,2,3,8,16,12,6,5,5,2,1,1,0,8,29,65,149,195,218,250,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,252,216,135,93,63,33,29,39,17,14,56,97,88,90,177,245,253,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,252,209,99,95,100,51,38,34,12,4,11,20,68,181,247,253,254,254,255,255,255,255,255,255,255,255,254,254,254,253,253,250,210,145,122,78,18,6,12,7,0,1,3,4,12,12,15,27,29,17,8,1,0,0,1,3,3,1,0,1,5,24,93,144,168,226,252,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,253,217,100,53,42,28,30,34,7,0,10,36,76,115,164,231,253,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,242,157,49,39,46,36,19,6,5,10,8,12,85,220,253,252,254,254,255,255,255,255,255,255,255,255,254,254,254,253,249,205,118,82,63,38,20,14,14,10,5,6,5,8,23,50,90,118,105,76,59,46,30,14,6,16,42,56,30,3,1,9,30,68,117,181,242,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,245,174,106,100,103,93,58,30,25,23,33,61,112,165,221,251,253,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,252,216,127,33,10,17,25,18,6,7,24,53,80,164,246,253,254,254,254,255,255,255,255,255,255,255,255,254,254,254,253,218,96,25,17,14,19,37,40,25,18,14,30,54,88,142,186,215,221,220,218,212,204,187,113,30,11,17,35,27,9,2,1,4,24,85,164,235,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,253,234,164,119,133,132,56,74,110,65,37,43,73,131,197,244,253,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,242,147,66,17,5,9,18,20,12,12,30,71,141,223,253,254,254,254,255,255,255,255,255,255,255,255,255,254,254,254,249,169,43,9,10,20,38,66,76,58,34,15,43,144,224,245,251,253,253,254,254,253,252,247,179,60,17,5,1,2,6,4,1,2,12,50,136,230,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,250,197,117,93,79,37,61,96,53,38,49,68,105,168,231,253,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,254,253,204,67,17,12,14,11,15,17,15,18,15,33,160,246,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,244,161,64,30,33,42,46,50,65,64,39,18,55,184,252,253,253,255,255,255,255,254,253,252,200,78,30,17,8,4,3,6,11,8,12,35,115,221,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,234,168,105,56,28,24,25,21,33,51,68,100,160,224,251,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,247,162,46,14,16,19,14,14,18,16,19,11,56,209,252,254,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,249,221,166,106,76,51,25,20,29,23,18,40,106,213,253,253,253,255,255,255,255,254,254,253,217,119,82,61,37,21,15,15,33,23,25,68,154,225,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,251,220,151,82,33,7,3,6,12,15,24,56,134,214,247,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,254,246,176,70,15,6,14,23,34,37,24,29,55,157,247,253,254,255,255,255,255,255,255,255,255,255,255,255,255,254,254,255,246,233,197,123,68,35,18,19,25,22,19,79,179,241,253,253,254,255,255,255,255,254,253,253,231,175,159,103,34,28,38,30,25,40,61,98,183,240,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,252,218,139,82,46,16,2,1,1,1,4,24,84,164,221,251,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,250,219,165,99,28,7,15,44,71,58,30,44,107,221,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,241,207,137,59,21,11,12,25,42,61,72,116,179,238,253,253,254,254,254,254,249,246,253,253,234,158,128,85,25,12,34,37,23,42,64,83,170,244,253,254,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,230,140,68,54,48,14,0,0,1,15,48,83,117,172,241,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,253,253,219,109,35,25,20,6,8,36,64,49,24,37,134,245,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,221,129,53,19,9,7,10,18,39,100,144,123,152,231,254,253,253,253,252,240,195,184,225,244,219,83,22,22,29,11,14,16,15,15,29,77,177,245,253,253,254,253,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,246,183,85,55,58,22,3,1,4,19,51,77,100,156,227,252,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,245,156,50,22,17,11,8,6,11,14,11,14,78,200,252,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,223,126,49,25,15,8,7,21,36,77,121,123,155,230,254,253,253,253,244,184,110,103,137,163,156,55,8,4,9,5,3,2,2,3,14,58,163,238,253,252,253,252,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,251,232,148,78,53,33,20,12,5,4,16,37,67,126,196,244,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,252,218,97,49,64,41,22,36,25,11,7,10,51,159,241,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,238,166,80,30,12,7,12,32,41,54,95,135,171,229,253,253,251,242,177,95,58,63,82,93,88,71,59,25,5,2,3,3,0,1,3,8,38,115,191,238,251,253,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,253,250,196,84,35,33,23,8,2,1,4,14,33,69,134,217,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,251,176,61,35,45,44,63,90,42,15,15,32,110,212,252,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,242,184,99,30,9,10,23,30,27,41,86,100,120,178,217,227,207,138,49,24,33,60,89,109,95,90,93,42,11,5,3,4,2,0,4,12,11,12,37,106,207,246,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,253,253,217,95,38,30,20,7,1,1,4,10,17,32,71,170,247,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,255,254,254,254,247,158,65,27,9,28,90,96,39,25,33,59,139,231,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,254,254,252,242,176,98,45,22,15,17,12,5,18,38,17,14,33,76,128,96,21,1,7,38,87,105,129,131,67,22,10,9,6,3,3,1,1,16,61,55,20,7,23,99,154,193,240,253,254,254,253,254,254,254,254,254,253,254,254,254,254,253,254,253,254,254,254,254,254,254,254,254,254,254,254,254,255,255,255,255,255,255,255,255,255,254,254,254,254,236,166,115,58,28,12,4,3,10,18,17,20,44,136,238,254,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,254,254,253,240,160,112,83,36,28,49,68,80,73,56,71,175,247,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,245,181,82,46,30,15,4,2,1,5,6,1,1,2,12,21,9,1,6,17,45,61,28,16,23,30,20,10,3,2,1,2,6,9,23,72,73,29,12,19,28,34,60,138,219,249,253,253,253,253,252,252,252,253,254,254,254,253,253,253,253,253,253,253,253,253,253,254,253,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,254,249,216,166,75,24,12,7,8,16,25,24,22,54,134,227,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,254,249,196,100,82,105,82,35,17,30,83,72,37,75,210,252,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,250,190,76,34,33,24,8,3,3,1,0,0,4,16,5,1,1,5,30,34,24,18,3,0,0,4,23,37,14,3,3,6,9,16,16,14,15,12,17,34,27,21,29,61,129,209,249,253,253,253,253,253,253,251,242,227,214,206,203,205,215,231,239,242,250,252,252,253,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,251,200,116,55,28,19,7,1,4,23,42,65,90,136,212,252,253,254,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,253,229,141,69,44,51,58,25,4,4,19,23,27,105,236,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,253,235,152,71,38,17,6,2,1,0,0,0,3,11,0,0,1,5,11,11,9,6,1,0,1,1,6,19,28,21,8,5,18,48,30,15,5,5,16,23,18,17,24,49,99,165,238,253,253,253,253,249,226,194,168,123,95,81,71,63,71,92,108,150,199,209,227,244,253,254,253,253,253,255,255,255,255,255,255,255,255,255,255,255,255,255,254,221,142,93,61,38,19,8,9,24,49,93,106,121,183,247,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,251,205,110,58,25,15,18,24,29,25,22,50,115,203,251,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,253,240,187,112,46,12,4,0,0,6,25,24,4,0,2,10,4,1,3,9,7,10,24,21,7,3,8,40,65,36,35,134,207,162,93,39,18,14,17,21,41,79,115,155,209,247,253,253,253,239,179,110,87,129,128,88,56,45,50,39,15,16,53,100,90,90,110,157,214,242,252,254,254,254,254,254,255,255,255,255,255,255,255,255,255,254,242,183,106,58,48,45,25,9,11,22,48,53,61,127,232,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,254,242,165,65,34,24,12,6,7,18,22,25,64,159,242,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,249,226,171,102,48,19,11,29,59,39,10,12,25,22,12,18,20,23,35,68,123,113,39,12,12,23,38,45,123,234,252,250,233,180,116,56,36,65,120,172,194,213,242,252,253,253,241,162,97,77,51,58,65,51,48,93,131,80,16,5,7,16,22,18,15,30,60,108,180,235,251,253,254,253,254,255,255,255,255,255,255,255,254,254,251,207,108,51,35,22,8,2,2,7,17,27,46,103,212,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,226,110,20,11,23,25,9,1,0,1,10,44,144,244,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,250,233,186,122,72,51,44,25,20,44,61,28,37,67,49,46,99,113,118,99,38,19,25,44,48,103,215,252,253,254,253,251,236,195,139,122,134,168,213,239,252,253,253,242,179,123,92,53,28,20,20,20,34,79,77,35,18,15,3,3,12,11,6,14,18,18,41,116,200,242,253,253,254,255,255,255,255,255,255,255,254,254,253,227,151,93,36,7,2,1,1,1,7,30,60,105,201,252,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,251,194,78,7,0,9,22,14,4,2,2,12,58,173,251,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,254,254,254,253,242,219,169,123,103,100,97,67,35,44,42,29,46,88,50,20,9,4,8,38,109,161,221,250,252,252,254,253,253,253,254,249,229,201,201,233,250,253,253,247,183,74,69,53,20,10,8,6,8,8,9,4,2,18,33,12,7,22,19,10,20,42,34,16,37,93,184,249,254,254,255,255,255,255,255,255,255,254,254,254,241,177,106,46,17,5,3,0,0,6,41,72,110,195,247,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,238,148,61,9,2,2,2,4,9,12,16,39,112,219,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,253,253,252,247,242,239,194,116,96,64,23,17,28,30,15,7,5,5,12,42,129,223,252,253,253,253,254,254,254,253,254,254,253,254,254,253,253,254,252,207,105,29,21,21,12,11,12,4,6,20,18,11,9,17,18,9,9,14,19,27,46,68,49,24,41,84,161,237,250,254,255,255,255,255,255,255,255,254,254,254,242,157,53,38,34,12,5,3,0,3,32,78,115,174,241,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,219,103,30,6,6,5,3,3,10,25,45,74,161,242,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,254,254,254,253,246,221,210,152,75,54,56,54,58,56,37,41,73,132,217,251,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,236,138,54,15,22,49,35,23,38,16,8,23,61,74,51,34,23,21,19,9,12,27,35,25,20,19,39,73,107,144,204,247,254,254,254,254,254,254,254,254,254,254,247,198,82,25,18,17,12,12,9,2,12,50,100,163,236,253,254,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,252,199,83,23,22,39,25,14,20,42,75,84,103,198,250,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,252,241,203,181,173,137,103,93,90,109,167,227,252,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,219,100,37,17,23,61,61,49,65,48,20,12,63,107,98,75,80,105,107,63,38,25,9,1,1,4,15,41,53,56,135,231,254,254,254,253,254,254,254,253,254,254,252,220,116,46,27,20,12,23,35,11,6,23,73,150,225,252,254,254,254,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,241,140,42,23,80,127,60,23,53,132,133,89,135,231,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,250,240,205,159,150,183,221,245,252,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,253,251,211,125,92,66,20,16,45,63,41,55,41,50,141,199,214,213,217,227,229,206,138,43,3,0,0,0,3,18,35,55,128,218,252,254,254,254,253,253,253,253,254,252,251,210,118,84,41,10,5,15,27,18,7,16,54,119,189,239,251,253,254,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,219,90,30,21,46,66,42,35,55,80,55,58,166,247,254,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,253,253,251,246,245,249,252,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,253,239,191,180,181,144,38,7,12,18,11,21,51,119,221,251,252,253,253,253,238,181,93,25,7,7,5,6,6,6,17,60,137,212,250,253,253,253,253,253,251,249,242,224,187,127,61,38,20,9,5,2,3,5,11,30,69,85,110,150,186,221,245,252,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,252,217,106,48,22,10,9,19,34,34,20,18,65,198,252,254,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,253,254,254,253,253,253,254,254,254,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,253,233,197,210,196,134,25,2,1,3,5,20,61,143,237,253,254,253,253,254,242,152,58,23,38,54,22,16,12,11,20,53,119,203,249,253,253,252,247,229,198,186,179,131,75,38,17,8,9,18,10,1,1,1,7,23,41,43,53,56,59,105,170,216,246,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,250,219,155,96,51,23,27,22,12,9,9,33,110,226,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,255,255,254,254,255,255,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,253,231,165,120,79,49,15,6,10,15,16,28,48,121,235,253,254,253,254,254,247,158,61,34,56,82,42,30,34,34,37,60,103,177,242,242,224,197,160,102,55,63,77,50,25,12,6,3,5,11,4,0,0,0,1,4,3,5,9,16,37,78,112,152,218,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,237,171,118,99,95,123,160,61,5,0,11,63,152,239,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,252,214,107,46,34,30,27,24,19,15,16,25,40,112,231,253,254,254,254,254,250,177,97,71,58,41,24,23,34,53,65,75,90,131,173,120,73,61,58,30,8,4,3,5,8,8,2,2,1,0,0,0,0,0,0,3,2,7,18,38,87,150,176,207,242,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,227,138,51,22,46,140,150,46,7,6,21,69,171,247,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,252,210,95,30,18,25,36,25,9,3,12,42,65,125,227,253,254,254,254,254,251,198,123,81,51,22,10,7,9,30,58,61,59,71,84,34,10,7,10,7,1,0,0,1,3,7,11,10,2,0,0,0,0,0,0,1,1,9,43,85,140,193,210,242,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,218,112,21,3,18,69,38,8,11,28,49,99,203,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,227,139,56,20,22,34,28,19,16,24,48,66,125,223,253,254,255,254,254,253,216,123,48,23,20,17,9,3,8,17,17,22,36,44,15,4,3,0,0,1,2,6,3,0,2,7,9,4,0,0,0,0,0,0,0,0,5,34,77,119,184,231,252,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,247,187,83,14,3,4,6,2,5,14,25,51,123,223,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,247,210,122,61,25,25,60,109,132,75,29,42,123,224,253,253,254,254,254,252,223,133,46,20,30,39,27,19,12,6,3,1,4,4,3,6,7,5,12,28,11,3,2,1,0,3,6,6,2,0,0,2,1,1,4,11,24,65,146,210,240,252,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,254,223,122,51,28,14,9,4,6,32,54,27,34,123,230,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,251,219,137,73,25,15,38,83,115,80,35,56,138,211,246,253,253,254,254,247,193,166,170,79,18,15,20,22,12,11,10,1,0,0,2,8,12,19,45,54,18,2,3,12,19,20,12,8,5,1,1,8,21,10,9,24,61,128,217,253,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,253,193,82,46,51,37,32,23,24,54,69,46,72,160,241,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,226,122,60,46,30,10,7,8,12,24,43,74,134,213,250,253,254,253,221,98,84,134,49,5,3,5,5,3,8,11,3,0,0,1,5,10,21,32,27,24,32,27,49,84,85,59,39,17,4,2,12,27,14,11,32,93,163,229,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,249,168,67,34,30,27,30,36,46,58,46,61,156,221,251,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,240,163,138,149,75,12,1,0,0,2,7,30,75,150,232,253,252,234,135,51,36,24,9,0,0,0,0,0,3,3,1,0,0,1,5,12,12,12,18,28,51,86,139,184,195,162,109,46,15,6,6,6,9,21,44,89,160,229,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,246,157,61,12,2,5,8,24,58,59,40,59,160,237,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,249,207,181,171,110,33,8,3,1,4,15,36,48,90,183,240,200,115,35,44,35,7,0,2,0,0,0,0,0,0,0,5,15,25,45,51,35,42,76,97,131,207,245,252,242,194,135,68,28,14,8,3,5,18,25,41,120,217,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,242,163,74,25,12,10,15,40,59,37,32,69,144,231,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,238,176,123,132,66,14,3,5,22,30,19,28,81,143,158,80,34,15,22,25,10,0,2,1,0,0,0,3,10,30,76,112,138,153,153,153,181,220,239,247,253,254,254,237,150,82,46,23,18,27,23,9,10,16,38,115,213,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,240,152,93,93,88,51,39,34,33,32,51,103,179,242,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,250,212,125,98,78,45,22,14,17,12,5,15,58,96,72,38,27,17,14,20,12,2,6,5,4,3,8,35,76,131,192,224,237,240,241,246,251,253,254,254,254,254,254,239,148,73,44,25,11,11,29,30,34,43,48,109,209,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,225,138,115,156,179,110,49,18,12,25,60,123,204,247,255,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,247,195,90,86,123,122,66,12,4,8,10,12,18,23,41,48,50,38,23,14,18,35,42,30,30,66,120,187,225,244,252,253,253,254,253,254,254,254,253,254,254,253,245,197,132,66,25,20,23,29,21,25,43,53,103,209,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,216,156,126,90,78,65,24,7,6,12,38,110,211,249,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,254,250,191,128,142,153,98,27,11,16,9,2,0,1,11,33,68,83,61,53,93,109,79,88,162,216,236,252,254,254,254,254,254,253,254,254,254,254,253,254,254,253,239,184,148,67,14,49,100,63,15,12,29,60,125,216,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,251,206,134,78,29,11,14,11,8,9,16,40,120,220,251,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,253,247,218,163,84,36,23,23,25,15,6,3,3,2,6,19,41,51,88,173,167,113,163,242,253,254,253,254,254,254,253,254,254,254,255,254,253,254,254,254,253,233,159,112,46,18,60,139,116,41,20,27,66,134,213,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,250,184,77,30,14,3,2,10,14,24,51,85,146,227,253,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,254,250,220,126,43,23,19,20,30,28,22,25,18,16,32,46,54,86,134,155,191,240,254,254,255,255,254,254,254,254,254,254,255,255,254,253,253,255,254,254,233,161,92,33,20,27,56,90,90,74,63,88,146,212,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,247,157,42,24,27,11,6,15,24,46,113,148,155,223,252,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,253,252,241,187,112,53,23,37,51,58,75,71,87,106,99,107,123,148,201,244,253,254,255,255,255,255,255,255,255,255,255,255,255,255,254,254,255,254,254,234,157,75,19,9,2,3,29,137,206,157,136,180,229,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,241,141,43,29,28,16,18,41,35,37,87,117,136,219,252,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,253,252,253,244,210,148,84,53,48,61,67,93,100,97,123,161,203,242,252,254,254,255,255,255,255,255,255,255,255,255,255,255,255,254,254,255,254,254,234,131,46,12,6,1,1,12,84,143,127,122,179,239,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,237,140,60,34,18,8,21,59,51,21,24,49,117,223,252,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,254,253,252,253,253,247,220,165,112,81,88,122,134,129,147,190,234,252,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,254,254,255,254,254,236,127,42,27,22,8,6,8,15,28,44,86,169,238,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,239,170,97,45,19,10,10,22,30,12,9,30,119,229,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,254,253,254,254,254,252,240,217,206,221,232,232,236,245,252,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,241,176,119,92,84,71,53,32,30,24,21,53,147,232,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,253,235,181,119,61,35,30,20,11,20,17,20,48,125,229,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,254,245,217,200,163,106,89,70,56,69,65,51,77,161,236,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,227,157,135,126,93,48,25,22,42,23,17,37,110,227,254,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,254,242,187,139,81,28,25,34,30,35,51,82,132,196,242,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,231,171,163,145,82,24,11,15,28,11,6,23,110,235,254,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,254,231,152,71,19,4,7,18,19,23,30,60,109,173,238,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,252,234,174,110,49,12,3,5,5,3,2,8,35,139,244,254,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,253,210,117,51,12,7,11,11,24,37,33,29,49,126,230,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,252,211,99,28,8,4,9,28,32,16,18,40,69,151,245,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,252,187,81,38,14,8,11,9,9,17,24,29,51,138,235,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,250,201,100,39,18,17,24,40,61,68,72,79,90,155,244,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,252,189,86,34,9,9,14,8,5,9,17,32,77,167,241,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,250,199,120,70,48,53,49,28,44,88,99,85,95,170,247,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,255,252,201,106,38,7,5,8,8,7,7,9,30,102,189,245,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,249,198,102,54,49,56,41,19,23,46,61,65,97,189,251,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,251,194,110,68,35,15,12,14,11,5,5,29,121,205,250,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,247,204,109,49,23,12,9,15,19,20,30,51,93,189,251,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,251,187,117,99,63,20,15,23,20,16,24,46,107,200,250,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,247,211,148,65,17,3,7,16,16,12,22,46,90,189,250,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,251,189,120,85,44,18,23,38,33,37,74,89,93,193,250,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,247,206,158,73,27,18,20,18,11,12,19,44,102,203,251,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,247,167,86,44,18,25,44,55,44,30,58,85,112,204,251,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,244,190,108,61,45,25,18,19,14,11,16,41,115,219,253,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,239,141,51,16,8,25,46,48,51,28,17,46,134,223,252,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,244,184,81,38,25,9,9,24,28,17,16,43,113,215,252,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,235,164,79,21,6,12,28,30,38,46,56,66,120,227,253,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,245,178,69,30,21,7,5,12,17,12,18,53,123,216,253,254,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,234,174,115,45,11,12,20,18,12,30,92,144,172,240,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,237,150,68,43,23,6,2,6,7,4,12,44,99,203,254,254,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,252,212,116,95,78,32,15,14,12,8,15,48,133,227,252,254,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,234,136,59,33,12,3,2,10,20,17,21,36,80,201,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,249,178,56,42,82,72,16,8,7,27,48,67,135,233,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,236,148,59,21,7,3,4,16,48,83,92,75,105,216,253,253,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,244,161,39,16,40,41,8,4,5,21,37,65,137,227,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,234,158,73,25,12,17,23,21,37,74,112,115,142,224,254,253,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,236,154,67,28,18,14,7,8,12,8,11,44,130,233,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,230,144,69,25,19,42,55,22,12,9,32,97,157,219,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,220,136,113,59,21,22,28,27,33,24,34,76,164,246,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,232,133,45,15,12,21,25,21,27,27,45,108,174,230,253,254,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,250,193,90,46,19,7,12,42,68,64,55,61,100,198,252,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,241,160,64,25,19,18,23,37,71,76,74,100,151,227,253,254,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,237,148,48,11,10,11,11,25,56,59,39,46,112,223,254,254,254,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,244,186,112,68,48,43,56,70,63,39,33,46,88,206,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,204,98,45,30,30,25,12,8,18,27,35,95,186,246,253,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,242,198,159,113,55,23,37,80,64,23,15,28,76,201,254,254,253,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,247,157,61,46,58,67,50,25,23,23,22,55,122,209,252,253,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,244,191,127,71,25,6,11,35,33,18,16,41,107,217,253,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,254,253,237,128,51,45,74,72,37,17,19,17,12,40,126,225,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,242,171,84,30,11,5,7,8,7,6,15,51,125,223,253,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,254,253,220,118,55,46,64,45,16,8,4,3,4,43,168,245,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,236,159,92,45,17,5,7,18,22,9,33,74,126,217,254,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,252,253,249,191,90,38,25,19,14,14,15,8,6,15,93,224,252,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,240,173,116,72,29,6,6,35,71,42,79,132,165,227,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,252,237,128,30,8,5,3,5,8,15,19,25,45,138,244,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,240,170,86,51,32,14,4,9,25,30,59,102,153,224,254,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,250,196,53,5,2,2,3,5,11,12,9,23,77,199,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,242,176,95,59,45,24,5,1,1,12,25,54,122,218,253,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,254,252,225,129,25,2,3,10,9,12,36,50,21,44,134,242,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,244,189,133,103,64,22,3,1,3,19,39,61,122,220,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,247,153,55,40,25,39,72,51,28,39,56,71,149,218,253,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,245,184,109,64,28,5,2,6,18,46,78,83,108,201,253,254,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,252,233,110,41,80,93,65,65,48,30,39,67,116,210,249,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,242,172,75,25,10,4,4,19,35,48,61,63,78,174,250,254,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,247,174,77,49,79,89,34,16,14,18,39,92,150,226,253,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,241,157,61,33,30,23,16,20,22,15,20,43,82,175,247,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,253,253,252,203,63,23,25,28,23,17,22,17,11,22,82,197,247,254,255,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,239,144,59,41,38,30,23,20,14,7,20,67,128,199,249,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,253,253,239,146,38,8,4,4,9,30,61,46,22,17,97,236,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,242,178,84,24,8,8,19,25,22,16,41,84,130,200,250,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,253,246,181,83,34,14,6,3,5,18,32,36,39,50,170,252,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,247,211,115,25,4,3,10,12,15,46,55,59,100,199,251,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,252,253,252,205,73,14,8,9,12,16,11,16,18,30,71,148,238,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,249,200,100,41,24,12,2,1,9,61,51,42,103,215,252,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,253,253,231,134,48,16,12,24,35,30,12,9,9,19,100,223,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,250,201,102,60,45,27,9,6,8,24,36,49,89,184,247,253,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,254,253,253,244,135,50,42,23,25,45,39,14,7,12,15,41,180,250,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,252,221,139,72,30,16,25,19,7,5,30,46,51,123,234,253,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,254,253,253,221,76,12,12,12,30,60,37,5,6,16,29,123,240,253,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,238,175,79,17,5,22,17,4,3,16,22,32,100,221,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,253,253,235,189,86,11,5,9,23,35,18,5,8,18,87,223,251,253,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,232,161,75,37,21,5,3,3,8,6,17,53,130,221,253,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,239,146,61,32,17,16,18,8,2,3,12,27,74,201,252,253,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,225,131,74,85,80,24,12,20,15,10,33,77,131,216,252,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,245,176,71,15,9,15,14,12,8,7,15,40,78,175,247,254,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,232,129,56,50,73,92,72,51,20,27,48,65,112,207,250,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,252,251,174,49,21,20,19,12,11,15,29,56,65,61,144,237,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,244,159,56,15,12,37,40,29,32,60,71,80,117,198,246,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,251,204,50,4,12,30,43,32,16,14,25,45,37,84,227,252,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,247,183,87,34,7,2,2,4,16,41,66,84,110,171,239,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,252,201,73,9,36,51,32,23,25,21,10,9,12,48,192,253,253,252,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,251,200,136,107,46,5,3,4,6,14,27,43,73,141,230,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,231,108,25,50,107,83,25,8,19,40,29,12,36,152,247,253,253,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,217,142,123,74,16,11,15,15,12,11,18,46,121,216,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,253,244,174,92,77,95,80,43,25,20,22,38,34,34,136,238,253,255,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,224,103,44,25,17,17,28,40,30,18,25,60,125,205,250,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,253,252,231,142,100,117,105,37,16,30,49,40,19,7,21,121,235,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,230,112,38,17,16,36,73,55,21,14,27,78,143,207,249,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,252,225,123,37,16,22,30,12,15,43,50,19,7,15,102,231,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,253,253,241,151,77,49,35,45,88,39,7,8,25,65,121,184,244,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,234,118,34,17,5,1,2,5,11,25,25,11,9,73,210,252,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,249,191,140,126,78,41,53,38,32,30,29,44,93,152,231,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,255,254,230,127,46,24,9,2,4,5,14,12,8,7,6,55,192,252,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,229,179,123,82,64,46,70,95,61,36,59,112,148,221,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,255,255,253,253,252,216,102,37,33,14,4,3,15,33,38,22,8,2,42,187,250,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,253,240,174,98,65,45,27,50,71,43,35,73,127,168,224,252,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,254,254,253,251,213,100,25,25,35,23,12,12,25,33,25,20,22,56,173,247,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,253,240,164,95,54,14,6,14,25,21,23,44,82,150,224,252,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,253,251,211,92,27,17,22,35,30,21,17,14,9,7,15,80,193,249,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,254,253,253,247,177,90,49,12,3,7,14,12,10,16,38,97,183,242,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,254,249,205,86,32,44,36,17,12,11,9,5,2,2,10,63,187,249,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,251,199,100,58,38,17,16,14,7,4,15,41,68,115,212,252,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,254,254,254,253,239,183,100,42,48,71,46,12,6,10,18,29,25,30,84,197,249,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,225,139,77,51,30,18,7,2,5,14,23,41,80,174,244,253,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,252,254,253,252,253,251,226,133,53,27,19,14,14,10,11,23,42,71,116,125,139,207,250,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,244,184,93,35,29,19,4,0,6,12,8,19,48,123,221,252,252,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,252,253,249,206,93,15,5,6,6,10,19,28,35,48,75,89,87,148,223,252,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,251,214,110,60,49,25,7,2,2,5,12,29,68,122,196,247,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,241,177,85,17,1,4,9,12,25,56,66,43,40,58,74,118,212,251,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,239,170,126,82,43,25,16,6,10,44,69,87,122,178,238,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,254,253,247,218,133,56,36,18,4,6,9,9,16,38,46,24,23,51,130,218,251,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,251,221,166,92,46,46,56,42,40,97,85,60,82,141,211,250,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,253,254,254,240,183,95,33,17,21,27,10,4,7,14,17,17,19,25,51,117,215,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,238,171,100,49,37,61,71,59,69,39,28,53,99,166,240,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,253,251,227,137,51,24,27,21,12,32,18,10,25,43,24,12,34,110,177,227,252,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,246,187,137,98,51,27,25,18,6,5,19,54,85,129,212,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,253,253,250,227,191,142,51,11,18,50,45,27,30,20,23,45,32,6,21,103,219,247,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,251,213,159,142,116,61,30,17,7,4,9,29,61,113,198,250,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,252,241,187,110,67,46,24,12,16,42,78,51,11,5,12,16,14,34,92,192,247,253,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,252,254,237,171,112,93,66,45,45,37,12,3,8,32,105,205,242,253,254,254,254,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,255,254,254,254,249,226,174,83,25,10,10,19,32,23,15,30,25,3,1,1,3,25,116,205,247,255,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,251,216,121,58,46,54,56,29,10,3,5,27,77,132,187,241,252,254,253,253,254,253,253,254,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,254,254,254,254,251,242,227,186,110,58,42,43,35,32,29,34,34,21,6,3,5,9,17,54,147,232,251,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,253,253,246,201,146,93,43,18,8,5,6,14,30,34,46,112,187,239,253,253,253,254,253,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,253,254,254,253,253,249,230,184,125,82,56,34,32,51,61,41,33,22,12,12,11,4,6,27,61,117,194,244,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,254,253,253,246,215,123,37,9,12,19,23,16,10,6,12,37,67,136,213,242,250,252,253,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,253,252,240,216,178,122,60,23,12,15,32,37,21,12,7,9,10,8,6,12,22,33,78,162,227,250,253,254,253,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,251,210,108,49,42,40,61,77,29,3,1,2,5,3,10,51,106,151,193,235,251,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,247,231,215,201,141,84,51,24,7,7,12,17,24,12,1,0,0,2,4,7,16,56,100,126,187,242,253,254,253,253,254,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,255,255,254,253,239,167,118,110,54,61,154,139,67,29,6,1,0,1,2,5,11,30,82,139,200,240,252,254,254,254,254,254,254,254,254,254,254,254,253,254,254,254,254,254,254,254,254,254,254,253,253,254,254,254,254,254,254,254,254,253,253,254,254,254,254,253,252,250,244,230,211,199,201,175,100,72,77,48,16,4,3,12,20,12,4,0,1,3,8,16,12,7,10,37,122,203,234,252,254,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,240,205,134,51,40,123,184,164,119,39,3,1,2,4,5,3,4,12,24,55,135,210,246,253,253,253,253,253,254,253,253,254,254,253,253,254,253,253,253,254,254,253,253,253,253,253,253,254,253,253,252,253,252,250,249,246,242,233,223,212,196,177,161,132,95,69,75,113,109,39,17,21,37,21,2,5,18,8,1,0,3,18,36,56,85,63,41,56,119,210,247,253,253,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,250,216,151,95,63,65,82,83,40,9,7,10,12,17,14,12,17,23,36,75,153,229,252,253,253,253,254,254,253,253,253,254,253,254,254,253,253,253,253,252,251,252,251,247,245,242,238,226,210,210,212,203,191,184,167,134,105,82,66,55,41,29,19,14,14,19,37,46,22,11,16,58,45,5,3,4,1,1,1,16,48,56,54,70,93,136,192,235,252,253,253,254,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,252,254,253,247,221,143,61,30,27,18,11,14,16,17,29,30,39,72,85,88,127,204,247,253,253,252,254,253,251,249,247,245,235,227,224,217,212,214,215,197,172,172,203,194,143,116,148,170,129,77,75,85,70,50,46,34,18,12,9,7,14,25,11,2,5,7,3,1,1,1,1,1,9,9,3,2,7,6,4,16,45,75,85,100,137,194,240,253,254,253,253,253,254,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,253,253,253,253,249,196,88,49,46,36,30,39,34,45,66,88,121,154,169,217,247,245,230,217,211,216,225,196,168,165,161,120,88,75,83,116,161,138,65,50,65,95,84,43,23,51,110,113,73,43,33,29,19,7,2,2,30,61,51,33,25,20,7,2,1,1,0,0,0,0,0,0,8,36,56,71,58,38,61,100,132,177,221,242,253,254,254,254,253,254,254,254,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,255,254,254,253,253,251,218,121,74,77,93,90,72,76,85,105,134,147,148,183,198,195,211,207,160,100,77,93,123,108,97,93,74,41,17,14,59,105,115,79,33,43,67,46,23,12,9,14,40,63,74,43,18,24,34,4,3,17,75,107,70,23,4,5,7,1,0,0,0,1,3,4,7,18,49,103,110,80,59,56,102,160,205,241,253,253,254,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,237,138,45,42,44,39,39,39,56,98,143,181,162,113,146,143,75,79,117,113,56,20,17,22,24,36,42,34,22,7,9,44,51,25,23,48,45,39,16,4,5,11,15,10,11,23,19,9,24,56,16,17,64,51,19,8,1,0,1,5,4,2,2,5,19,28,33,58,79,81,90,93,74,80,129,198,237,251,254,254,254,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,242,157,48,14,15,15,10,5,2,5,17,51,88,73,33,40,46,15,9,14,20,18,7,3,1,0,1,8,30,32,12,3,2,2,0,3,12,3,0,0,0,7,34,36,8,4,8,12,12,17,41,37,25,51,19,3,2,2,0,2,10,45,80,66,46,61,63,63,89,102,93,107,162,199,223,247,253,251,252,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,252,184,68,18,10,8,8,7,8,2,3,2,2,3,3,1,2,9,8,11,7,1,2,2,3,6,12,6,2,4,7,8,2,0,0,0,0,0,0,0,0,1,5,17,12,3,3,12,37,36,18,15,30,22,19,12,8,8,8,7,16,50,150,201,148,108,130,131,133,159,191,213,233,249,252,253,254,253,253,253,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,217,79,19,11,10,7,4,3,2,1,2,1,0,0,0,0,0,0,1,7,12,11,4,7,16,22,45,20,1,0,1,4,4,1,0,0,1,1,3,4,3,7,9,8,4,5,7,14,44,51,34,27,43,50,45,35,27,25,39,61,87,137,203,215,190,187,217,231,239,246,251,253,254,254,253,254,254,254,254,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,254,244,110,8,1,3,5,3,1,0,0,0,0,0,0,0,0,0,0,0,0,1,15,34,25,16,20,12,15,12,15,20,14,7,6,14,28,19,8,21,35,19,24,41,37,28,36,46,43,38,46,66,80,96,117,131,133,143,156,164,181,205,223,239,247,249,250,251,253,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,251,187,34,3,2,2,3,2,0,0,0,1,4,4,4,4,4,4,6,5,3,6,19,46,46,27,22,15,20,38,80,115,80,41,44,93,146,138,117,127,128,115,123,141,149,155,167,183,190,187,192,205,218,227,236,242,247,249,252,254,254,254,253,253,253,253,253,253,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,254,252,227,110,22,8,9,9,9,5,1,1,3,5,7,18,28,32,35,39,32,21,19,24,42,61,63,61,73,70,79,103,145,176,160,151,168,207,233,235,233,236,236,239,240,244,246,247,249,251,252,252,252,252,254,254,254,254,254,253,254,254,254,254,254,253,253,253,253,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,246,160,63,46,27,25,34,42,28,10,2,7,22,30,56,93,109,113,122,122,108,110,120,131,141,153,173,200,209,215,221,233,241,242,246,251,252,252,254,253,252,253,253,254,254,253,253,254,254,254,254,253,253,254,254,254,254,254,253,253,254,255,254,254,254,253,253,253,254,254,254,255,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,254,254,253,205,89,81,123,85,54,48,50,45,30,18,54,146,179,196,215,224,226,232,239,239,242,246,247,249,252,254,254,254,254,254,254,254,254,254,254,254,254,254,255,254,254,254,255,254,254,254,254,254,254,254,255,255,254,254,255,254,254,254,254,254,255,254,254,255,255,255,254,254,255,255,255,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,253,253,253,241,150,113,113,67,32,35,36,30,42,53,60,153,242,253,253,254,253,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,252,254,253,253,252,209,118,119,88,25,19,56,54,29,37,51,102,223,253,254,254,254,254,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,253,253,227,120,53,41,36,48,69,105,78,32,27,56,175,251,254,254,254,254,254,253,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,255,254,254,254,254,254,254,254,254,254,254,255,255,255,255,255,254,254,255,254,254,254,254,254,254,255,254,254,254,254,254,253,253,242,145,30,8,4,14,53,60,34,30,20,24,110,238,253,254,254,254,254,253,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,254,254,253,253,254,253,253,253,253,253,253,254,254,254,254,254,254,253,254,253,253,253,253,254,254,254,253,253,254,254,253,254,252,207,112,46,14,6,5,6,8,4,10,18,50,181,252,253,254,254,255,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,252,253,253,254,253,254,253,252,253,252,253,254,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,252,253,254,252,253,235,128,98,44,9,10,18,18,14,22,51,90,152,239,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,253,254,253,254,254,251,244,225,200,190,198,211,215,213,216,213,207,204,204,200,197,201,223,238,211,195,204,207,197,189,193,196,190,174,99,21,21,16,23,42,74,93,72,77,96,153,232,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,253,242,214,179,148,108,83,72,76,88,97,95,102,103,93,79,64,56,69,89,98,135,127,73,43,51,69,74,69,51,30,16,4,1,1,4,29,46,65,88,61,51,71,187,251,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,252,249,225,166,100,79,86,72,59,44,39,49,59,42,39,43,48,40,30,25,41,53,21,23,56,48,22,16,28,35,30,17,5,2,8,10,2,1,6,11,12,15,12,27,120,237,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,254,252,231,183,139,95,64,78,109,90,46,21,23,32,30,18,23,25,25,24,30,29,14,11,2,0,3,16,33,19,4,2,2,3,2,6,21,23,12,3,0,0,0,0,3,56,206,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,253,249,201,110,63,71,75,76,97,100,71,37,20,19,14,2,12,53,36,12,11,27,38,16,14,9,2,0,2,8,5,0,1,2,2,4,9,9,6,11,8,11,19,17,11,39,160,247,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,244,199,117,49,35,61,67,44,25,12,7,22,30,21,8,1,7,33,10,0,1,6,18,32,49,41,11,2,1,2,2,6,15,28,29,18,10,5,6,9,20,37,64,83,95,164,239,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,255,255,254,254,255,255,255,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,253,246,183,80,46,48,59,35,16,7,3,2,6,14,23,25,12,1,1,3,3,2,4,5,11,25,46,48,19,6,6,14,16,18,37,90,96,44,16,11,18,34,55,61,74,110,173,238,252,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,255,254,254,254,254,254,254,254,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,254,254,253,242,176,69,18,44,50,25,5,2,1,1,2,9,10,27,54,39,12,11,14,25,51,76,83,85,110,136,84,39,39,56,71,61,44,58,110,107,69,61,65,48,53,76,103,130,177,239,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,252,253,253,254,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,254,254,247,162,54,17,30,67,38,11,5,7,7,3,4,16,35,81,145,167,154,145,144,162,186,184,179,184,194,198,166,152,170,184,190,190,170,155,169,172,160,155,154,152,156,171,194,227,247,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,252,253,253,253,253,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,253,252,213,80,21,22,37,25,19,19,24,33,25,15,30,64,113,177,223,242,247,247,247,249,250,247,245,246,247,247,245,246,247,249,249,250,249,244,246,247,246,244,242,246,247,247,251,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,252,247,233,240,247,252,254,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,252,253,231,120,37,20,25,25,10,25,39,53,53,51,88,135,174,220,246,253,253,254,254,253,253,253,254,254,253,254,253,254,254,253,253,253,253,253,254,254,253,254,254,254,253,254,253,253,252,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,242,206,165,184,205,221,238,247,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,252,242,149,33,12,12,17,21,27,28,36,44,36,69,196,242,249,254,254,254,254,254,254,254,254,253,254,254,253,254,253,253,254,254,253,254,254,254,254,254,254,254,254,254,254,254,253,254,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,247,213,153,107,123,151,171,200,227,249,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,218,106,50,33,18,17,34,30,14,11,21,42,132,238,252,253,254,254,254,254,254,254,255,255,254,254,254,254,255,254,254,254,254,254,255,255,254,254,255,255,255,254,254,254,254,254,255,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,235,192,142,93,90,115,142,171,203,236,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,251,203,106,60,48,32,19,23,27,23,14,38,97,198,252,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,230,178,137,100,79,82,107,132,160,203,246,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,246,175,80,22,21,27,18,11,24,40,46,58,113,216,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,234,170,116,93,65,45,56,92,143,191,234,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,239,160,85,32,12,12,18,22,35,51,56,65,140,234,253,253,253,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,245,199,135,80,44,28,36,65,103,146,195,244,254,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,230,157,100,71,34,19,25,29,30,50,48,72,164,242,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,251,220,143,56,27,25,34,44,56,85,143,225,252,253,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,232,164,102,84,72,54,37,29,28,33,37,84,181,247,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,247,197,113,51,35,36,28,25,41,70,118,203,247,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,244,200,128,82,103,100,56,46,55,18,22,89,194,250,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,245,176,103,74,61,44,18,14,42,81,117,181,239,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,247,221,162,103,107,113,75,53,54,20,28,79,190,251,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,249,192,113,63,37,24,16,15,32,56,79,138,215,250,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,223,164,129,113,107,90,51,20,25,51,58,79,187,252,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,254,253,234,172,78,33,35,35,23,28,30,36,82,179,241,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,250,193,105,76,84,73,41,17,17,63,86,59,93,201,252,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,246,200,112,59,49,56,84,85,50,30,50,112,196,250,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,244,159,70,25,14,18,17,12,16,45,45,58,121,218,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,241,184,130,87,46,38,73,74,45,41,65,88,157,242,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,236,137,60,14,2,5,10,10,21,32,25,73,169,238,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,247,193,122,93,69,34,28,30,30,46,76,103,166,239,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,231,135,68,25,10,14,15,17,41,68,54,105,198,247,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,252,224,150,103,88,46,29,32,48,70,92,126,196,245,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,227,134,89,73,42,24,23,29,46,73,79,127,201,247,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,247,214,134,69,54,44,46,72,129,162,148,180,221,250,254,254,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,254,253,216,107,83,103,64,22,15,18,16,20,49,122,207,251,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,247,201,128,84,60,29,22,44,108,146,120,125,181,241,253,254,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,254,252,207,90,40,29,23,19,12,7,5,20,64,143,231,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,249,181,109,100,60,15,7,20,55,81,84,86,144,225,252,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,254,251,212,103,30,14,12,12,11,11,19,70,143,183,242,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,251,191,92,59,32,12,9,10,20,56,85,71,102,184,242,254,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,254,242,159,72,32,22,16,15,23,30,33,82,161,191,242,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,215,113,53,24,22,22,12,6,25,56,46,65,138,226,253,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,253,230,117,39,29,23,14,24,33,25,14,25,82,163,242,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,232,156,95,41,22,18,9,5,7,18,24,43,105,203,251,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,252,225,110,33,22,16,12,28,39,30,25,25,64,166,247,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,244,190,138,71,32,18,15,12,6,5,18,50,92,179,247,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,251,216,108,32,12,12,28,39,40,50,56,53,81,200,252,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,250,198,135,103,84,63,50,40,20,12,37,86,108,158,231,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,247,192,98,41,12,17,72,66,29,25,39,64,120,233,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,252,214,149,128,116,88,66,49,32,39,71,98,93,119,205,253,254,254,254,254,254,255,255,255,255,255,254,254,254,254,254,253,253,249,209,134,103,86,40,33,59,43,20,17,32,100,196,250,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,235,189,133,73,46,44,35,22,28,46,61,65,93,180,249,253,253,254,254,254,254,254,254,254,254,253,254,253,253,254,253,246,187,83,43,73,116,98,67,34,25,49,79,79,163,240,253,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,240,178,113,51,30,32,39,24,8,7,27,74,120,178,242,252,252,252,252,251,250,249,247,247,247,247,247,247,247,244,223,169,76,20,12,12,30,86,131,97,78,60,55,122,226,253,254,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,247,190,110,64,44,34,37,50,36,14,25,86,160,174,167,172,178,187,209,207,180,156,137,128,142,168,183,183,174,159,120,61,25,20,12,3,7,35,61,72,122,82,50,177,250,253,254,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,251,219,144,109,99,65,39,77,97,41,30,53,109,138,121,109,89,81,99,96,73,53,41,34,48,90,99,72,51,46,33,19,15,12,8,6,12,20,12,14,56,90,148,239,253,253,253,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,253,237,170,150,161,110,49,48,50,16,8,12,23,42,69,63,33,14,10,12,16,15,11,10,12,30,25,8,2,2,3,7,10,5,4,12,25,20,15,16,35,121,227,252,253,254,254,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,253,244,183,145,135,85,33,12,3,0,0,0,0,0,1,1,0,0,0,1,2,3,2,1,2,2,3,1,0,0,0,4,5,5,14,24,20,19,54,79,117,209,251,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,254,251,219,146,80,34,12,6,2,3,5,5,4,2,1,2,2,3,4,3,1,0,2,2,1,0,0,0,1,2,2,2,6,12,20,21,15,32,90,164,227,251,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,255,254,250,220,146,76,32,12,4,2,4,6,7,4,3,9,21,25,23,9,3,4,8,10,6,5,4,5,17,30,22,15,14,17,21,29,61,113,175,234,252,253,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,242,220,175,103,51,20,8,6,4,3,3,12,41,67,49,25,17,16,12,15,25,24,19,25,59,97,73,51,56,69,68,79,144,211,245,253,253,253,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,253,254,254,247,218,169,103,64,51,48,43,41,49,56,46,40,49,58,40,43,61,51,43,54,86,100,79,82,112,134,152,190,235,252,254,254,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,250,242,219,200,189,176,164,157,157,158,164,175,186,181,177,179,175,175,184,194,195,189,199,219,233,244,251,253,253,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,253,253,253,253,253,252,250,247,247,247,247,249,251,251,252,251,250,250,251,251,253,252,251,253,253,253,253,253,253,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,253,253,254,254,254,253,253,253,254,253,253,253,253,253,252,253,253,254,254,254,253,254,253,253,254,252,254,254,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,254,254,255,255,254,254,254,253,254,254,254,253,254,254,254,253,253,254,254,254,254,254,254,253,254,254,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,255,254,254,254,254,255,255,254,254,254,254,255,255,254,254,254,254,254,254,254,254,254,255,255,254,254,254,254,255,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,]); - - let xyz_old = decode(&xyz_new); - - println!("{}", xyz_new.len()); - println!("{}", xyz_old.len()); - - let screen_lock = VGAE.lock(); - screen_lock.set_mode(); - for y in 0..8 { - for x in 0..8 { - // trace!(""); - info!("x{} | y{}", x, y); - - // Stops at 419 - match xyz_old[y * 290 + x] { - 221..=255 => { - screen_lock.set_pixel(x, y, vga::colors::Color16::Red); - } - 170..=220 => { - screen_lock.set_pixel(x, y, vga::colors::Color16::DarkGrey); - } - - 100..=169 => { - screen_lock.set_pixel(x, y, vga::colors::Color16::LightGrey); - } - _ => { - // VGAE.lock().set_pixel(x, y, Color16::Red); - } - } - } - } -} diff --git a/ableos/src/relib/math/ciphers/mod.rs b/ableos/src/relib/math/ciphers/mod.rs deleted file mode 100644 index 8b13789..0000000 --- a/ableos/src/relib/math/ciphers/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ableos/src/relib/math/mod.rs b/ableos/src/relib/math/mod.rs deleted file mode 100644 index bb39ef7..0000000 --- a/ableos/src/relib/math/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -//! A standard implementation of common math functions - -pub mod ciphers; diff --git a/ableos/src/relib/mod.rs b/ableos/src/relib/mod.rs deleted file mode 100644 index 4cea1c9..0000000 --- a/ableos/src/relib/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! A simple reimplimentation of the the rust standard library - -pub mod clparse; -pub mod encoding; -pub mod image; -pub mod math; -pub mod network; -pub mod time; - -pub struct VectorTwo { - pub x: i32, - pub y: i32, -} diff --git a/ableos/src/relib/network/mod.rs b/ableos/src/relib/network/mod.rs deleted file mode 100644 index d22cc84..0000000 --- a/ableos/src/relib/network/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod socket; diff --git a/ableos/src/relib/network/socket.rs b/ableos/src/relib/network/socket.rs deleted file mode 100644 index b1187e2..0000000 --- a/ableos/src/relib/network/socket.rs +++ /dev/null @@ -1,151 +0,0 @@ -pub static SOCKETS: spin::Mutex<SocketState> = spin::Mutex::new(vec![]); - -pub type SocketState = Vec<SimpleSock>; -pub type Stream = Vec<u8>; - -#[derive(Debug)] -pub struct SocketID { - pub id: usize, -} - -impl SocketID { - pub fn protocol(self) -> Option<String> { - SOCKETS.lock()[self.id].protocol.clone() - } -} - -impl Socket for SocketID { - fn peek(&mut self) -> SocketReturns { - SOCKETS.lock()[self.id].peek() - } - - fn read(&mut self, length: usize) -> SocketReturns { - SOCKETS.lock()[self.id].read(length) - } - - fn write(&mut self, stream: Stream) -> SocketReturns { - SOCKETS.lock()[self.id].write(stream) - } - fn register_protocol(&mut self, protocol_name: String) { - SOCKETS.lock()[self.id].protocol = Some(protocol_name); - } - - fn check_protocol(&mut self, protocol_name: String) -> bool { - SOCKETS.lock()[self.id].check_protocol(protocol_name) - } -} - -pub trait Socket { - fn peek(&mut self) -> SocketReturns; - - /// Reads from the socket and removes read bytes from the socket - fn read(&mut self, length: usize) -> SocketReturns; - - fn write(&mut self, stream: Stream) -> SocketReturns; - fn register_protocol(&mut self, protocol_name: String); - fn check_protocol(&mut self, protocol_name: String) -> bool; - - fn close(&mut self) {} -} - -#[derive(Debug)] -pub enum SocketReturns { - ReadOk(Stream), - ReadIndexOutOfBounds, - WriteOk, -} - -impl SocketReturns { - pub fn unwrap(self) -> Stream { - match self { - SocketReturns::ReadOk(stream) => stream, - SocketReturns::ReadIndexOutOfBounds => panic!("Read Index Out Of Bounds"), - SocketReturns::WriteOk => vec![1], - } - } -} - -pub struct SimpleSock { - stream: Vec<u8>, - protocol: Option<String>, -} - -impl SimpleSock { - pub fn new() -> SocketID { - let sock = SimpleSock { - stream: vec![], - protocol: None, - }; - let mut sock_lock = SOCKETS.lock(); - sock_lock.push(sock); - - SocketID { - id: sock_lock.len() - 1, - } - } - pub fn regrab_sock(id: usize) -> SocketID { - SocketID { id } - } - - pub fn grab_socket(protocol_name: String) -> Option<SocketID> { - let socket_handle = SOCKETS.lock(); - let socket_count = socket_handle.len(); - drop(socket_handle); - - let return_sock = None; - for socket_id in 0..socket_count { - let mut id = SimpleSock::regrab_sock(socket_id); - - if id.check_protocol(protocol_name.clone()) { - return Some(id); - } - } - - return_sock - } -} - -impl Socket for SimpleSock { - fn peek(&mut self) -> SocketReturns { - let mut return_vec = vec![]; - - for x in &self.stream { - return_vec.push(*x); - } - SocketReturns::ReadOk(return_vec) - } - - fn read(&mut self, length: usize) -> SocketReturns { - let mut return_vec = vec![]; - if length > self.stream.len() { - SocketReturns::ReadIndexOutOfBounds - } else { - for _ in 0..length { - return_vec.push(self.stream[0]); - self.stream.remove(0); - } - SocketReturns::ReadOk(return_vec) - } - } - - fn register_protocol(&mut self, protocol_name: String) { - self.protocol = Some(protocol_name); - } - - fn check_protocol(&mut self, protocol_name: String) -> bool { - if self.protocol == Some(protocol_name) { - return true; - } - - false - } - - fn write(&mut self, stream: Stream) -> SocketReturns { - for byte in stream { - self.stream.push(byte); - } - SocketReturns::WriteOk - } - - fn close(&mut self) {} -} diff --git a/ableos/src/relib/security/mod.rs b/ableos/src/relib/security/mod.rs deleted file mode 100644 index 71c79f1..0000000 --- a/ableos/src/relib/security/mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copilot module -// Language: rust - -//! Security module. -//! -//! This module provides a security interface for AbleOS. -//! -//! # Examples -//! ``` -//! use crate::security::Security; -//! -//! let mut security = Security::new(); -//! security.add_user("admin", "password"); -//! security.add_user("user", "password"); -//! security.add_user("guest", "password"); -//! -//! assert_eq!(security.authenticate("admin", "password"), true); -//! assert_eq!(security.authenticate("user", "password"), true); -//! assert_eq!(security.authenticate("guest", "password"), true); -//! assert_eq!(security.authenticate("admin", "password2"), false); -//! assert_eq!(security.authenticate("user", "password2"), false); -//! assert_eq!(security.authenticate("guest", "password2"), false); -//! ``` diff --git a/ableos/src/relib/time/kilotime.rs b/ableos/src/relib/time/kilotime.rs deleted file mode 100644 index 06cae00..0000000 --- a/ableos/src/relib/time/kilotime.rs +++ /dev/null @@ -1,61 +0,0 @@ -use super::Time; -use core::fmt::{Display, Error, Formatter}; - -#[derive(Debug, Clone, Copy)] -#[repr(transparent)] -pub struct Kilosecond(u32); -impl Kilosecond { - pub fn from_ms(ms: u32) -> Self { - Self(ms) - } - - pub fn from_sec(sec: u32) -> Self { - Self(sec * 1000) - } - - pub fn from_minutes(min: u32) -> Self { - Self(min * 60 * 1000) - } - - pub fn from_hours(hrs: u32) -> Self { - Self(hrs * 60 * 60 * 1000) - } - - pub fn from_days(days: u32) -> Self { - Self(days * 24 * 60 * 60 * 1000) - } - - pub fn s(&self) -> u32 { - (self.0 % 1000) - } - - pub fn k(&self) -> u32 { - self.0 / 1000 - } -} - -impl Display for Kilosecond { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write![f, "{}K {}S", self.k(), self.s()] - } -} - -impl core::ops::Add for Kilosecond { - type Output = Self; - fn add(self, rhs: Self) -> Self { - Self(self.0 + rhs.0) - } -} - -impl core::ops::Sub for Kilosecond { - type Output = Self; - fn sub(self, rhs: Self) -> Self { - Self(self.0 - rhs.0) - } -} - -impl From<Time> for Kilosecond { - fn from(t: Time) -> Self { - Self((t.hour as u32 * 3600 + t.minutes as u32 * 60 + t.seconds as u32) * 1000) - } -} diff --git a/ableos/src/relib/time/mod.rs b/ableos/src/relib/time/mod.rs deleted file mode 100644 index ff00de8..0000000 --- a/ableos/src/relib/time/mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -pub mod kilotime; - -use core::fmt; - -pub struct Time { - pub year: u16, - pub month: u16, - pub day: u16, - pub hour: u16, - pub minutes: u16, - pub seconds: u16, - pub microseconds: u32, -} - -impl fmt::Display for Time { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "{:?}/{:?}/{:?} {:02}:{:02}:{:02}", - self.year, self.month, self.day, self.hour, self.minutes, self.seconds - ) - } -} diff --git a/ableos/src/rhai_shell/balloon.txt b/ableos/src/rhai_shell/balloon.txt deleted file mode 100644 index a44994c..0000000 --- a/ableos/src/rhai_shell/balloon.txt +++ /dev/null @@ -1,11 +0,0 @@ - ,-""""-. OS: AbleOS - ,'\ _ _`. Host: {} - / \)_)-)_)-\ Kernel: AKern-{}-v{} -: : Uptime: {} -\ / Packages: None - \ / Shell: RhaiShell - `. ,' Resolution: 640x480 - `. ,' Terminal: VGABuffer - `.,' CPU: {} - /\`. ,-._ GPU: VGA Compatible - `-' Memory: {}/{} \ No newline at end of file diff --git a/ableos/src/rhai_shell/mod.rs b/ableos/src/rhai_shell/mod.rs deleted file mode 100644 index 9873aae..0000000 --- a/ableos/src/rhai_shell/mod.rs +++ /dev/null @@ -1,217 +0,0 @@ -use crate::arch::drivers::sysinfo::master; -use crate::systeminfo::{KERNEL_VERSION, RELEASE_TYPE}; -use crate::{time::fetch_time, KERNEL_STATE}; -// use genfs::{Fs, OpenOptions}; -use kernel::allocator::ALLOCATOR; -// use rhai::Engine; -use spin::Lazy; -use x86_64::instructions::interrupts::{disable, enable}; - -pub const RHAISHELL_VERSION: &str = "0.1.0"; - -pub static KEYBUFF: spin::Mutex<Vec<char>> = spin::Mutex::new(Vec::new()); -pub static CURRENT_DIR: Lazy<spin::Mutex<String>> = Lazy::new(|| spin::Mutex::new("/".to_string())); - -#[cfg(target_arch = "riscv64")] -pub fn shell() {} - -// #[cfg(target_arch = "x86_64")] -// pub fn shell() { -// let _current_dir = "/".to_string(); -// let engine = engine_construction(); -// let mut scope = rhai::Scope::new(); - -// println!("Rhaishell v{}", RHAISHELL_VERSION); - -// let mut buf = String::new(); -// print!("> "); - -// loop { -// match x86_64::instructions::interrupts::without_interrupts(|| KEYBUFF.lock().pop()) { -// Some('\n') => { -// if buf == "quit" { -// println!("Bye!"); -// break; -// } - -// match engine.eval_with_scope::<rhai::Dynamic>(&mut scope, &buf) { -// Ok(o) => println!("{o}"), - -// Err(e) => println!("Eval error: {e}"), -// }; - -// buf.clear(); -// print!("> "); -// } -// Some('\u{0008}') => { -// buf.pop(); -// } - -// Some('\u{0009}') => { -// buf.push(' '); -// buf.push(' '); -// buf.push(' '); -// buf.push(' '); -// } - -// Some(chr) => buf.push(chr), -// None => (), -// } -// } -// } - -pub fn afetch() { - let kstate = KERNEL_STATE.lock(); - - let tick_time = fetch_time(); - - disable(); - let allocator = ALLOCATOR.lock(); - let size = allocator.size(); - let used = allocator.used(); - enable(); - - println!( - include_str!("balloon.txt"), - kstate.hostname, - RELEASE_TYPE, - KERNEL_VERSION, - tick_time, - master().unwrap().brand_string().unwrap(), - // "", - // mem - used, - size - ); - drop(kstate); -} - -pub fn set_hostname(name: String) { - let mut kstate = KERNEL_STATE.lock(); - kstate.hostname = name; -} - -/// Examine a memory pointer -pub fn peek_memory(ptr: i64) -> i64 { - unsafe { *(ptr as *const u8) as _ } -} - -pub fn poke_memory(ptr: i64, val: i64) { - match val.try_into() { - Ok(val) => unsafe { *(ptr as *mut u8) = val }, - Err(_) => error!("{val} cannot be converted into u8"), - } -} - -// pub fn ls() { -// let current_dir = CURRENT_DIR.lock(); - -// let fs = &*FILE_SYSTEM.lock(); - -// let file = fs -// .open(current_dir.as_bytes(), OpenOptions::new().read(true)) -// .unwrap(); - -// let mut files = file.directory().unwrap(); -// println!("current dir: {}", *current_dir); -// while let Some(Ok(entry)) = files.next() { -// let inode_name = entry.name; -// let s = String::from_utf8_lossy(&inode_name); -// println!("{}", s); -// } -// } - -pub fn log_dump() { - use crate::network::socket::SimpleSock; - use crate::relib::network::socket::Socket; - let log_socket_id = SimpleSock::grab_socket("Logger".to_string()); - match log_socket_id { - Some(mut log_socket_id) => { - let log = log_socket_id.peek(); - - match log { - crate::network::socket::SocketReturns::ReadOk(ok) => { - for x in ok.iter() { - print!("{}", *x as char); - } - } - - crate::network::socket::SocketReturns::ReadIndexOutOfBounds => todo!(), - crate::network::socket::SocketReturns::WriteOk => todo!(), - } - } - None => warn!("No socket found for Logger"), - } -} - -// pub fn echo_file(path: String) { -// let mut current_dir = CURRENT_DIR.lock(); - -// let fs = &*FILE_SYSTEM.lock(); - -// current_dir.push_str(&path); - -// let file = fs -// .open(current_dir.as_bytes(), OpenOptions::new().read(true)) -// .unwrap(); - -// if file.is_dir() { -// println!("{} is a directory", path); -// } else { -// let mut file_contents = Vec::new(); - -// let _ret = file.read_to_end(&mut file_contents).unwrap(); - -// let file_contents_str = String::from_utf8_lossy(&file_contents); - -// println!("{}", file_contents_str); -// } -// } - -// pub fn change_directory(path: String) { -// let mut current_dir = CURRENT_DIR.lock(); - -// let _fs = &*FILE_SYSTEM.lock(); -// if path == "." || path == ".." { -// let mut split_dir = current_dir.split('/').collect::<Vec<&str>>(); -// let mut new_dir = String::new(); -// split_dir.remove(split_dir.len() - 1); -// println!("{:?}", split_dir); -// if split_dir.is_empty() { -// new_dir = "/".to_string(); -// } else { -// for x in split_dir { -// new_dir.push_str(x); -// new_dir.push('/'); -// } -// } -// *current_dir = new_dir; -// } else { -// if !current_dir.ends_with('/') { -// current_dir.push('/'); -// } -// current_dir.push_str(&path); -// } -// } - -// fn engine_construction() -> Engine { -// let mut engine = rhai::Engine::new(); - -// engine.on_print(|x| println!("{}", x)); -// engine.on_debug(|x, src, pos| { -// let src = src.unwrap_or("unknown"); -// println!("DEBUG: {} at {:?}: {}", src, pos, x); -// debug!("{} at {:?}: {}", src, pos, x); -// }); - -// engine.register_fn("afetch", afetch); -// engine.register_fn("set_hostname", set_hostname); -// engine.register_fn("shutdown", shutdown); -// engine.register_fn("peek", peek_memory); -// engine.register_fn("poke", poke_memory); -// engine.register_fn("sloop", sloop); -// engine.register_fn("log_dump", log_dump); -// // engine.register_fn("ls", ls); - -// engine -// } diff --git a/ableos/src/scratchpad.rs b/ableos/src/scratchpad.rs deleted file mode 100644 index 8144910..0000000 --- a/ableos/src/scratchpad.rs +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright (c) 2022, Able <able@ablecorp.us> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -use crate::arch::drivers::sysinfo::master; -use crate::arch::interrupts::{reset_pit_for_cpu, set_pit_2}; -use crate::devices::pci::ide::{Channel, Drive}; -use crate::devices::pci::{PciDevice, PCI_DEVICES}; -use crate::filesystem; -use crate::filesystem::vfs::VFS; -use crate::systeminfo::{KERNEL_VERSION, RELEASE_TYPE}; -use crate::time::fetch_time; -use crate::{ - arch::shutdown, rhai_shell::KEYBUFF, vterm::VTerm, wasm_jumploader::run_program, KERNEL_STATE, -}; - -use acpi::{AcpiTables, PlatformInfo}; -use cpuio::{inb, outb}; -use kernel::allocator::ALLOCATOR; -use spin::Lazy; -use x86_64::instructions::interrupts::{disable, enable}; - -pub const BANNER_WIDTH: &str = - "================================================================================"; - -// TODO: move to a better place -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct AcpiStruct {} -impl acpi::AcpiHandler for AcpiStruct { - unsafe fn map_physical_region<T>( - &self, - physical_address: usize, - size: usize, - ) -> acpi::PhysicalMapping<Self, T> { - info!("PHYS ADDR: {:?}", physical_address); - info!("Size: {:?}", size); - todo!("map_physical_region"); - } - fn unmap_physical_region<T>(_region: &acpi::PhysicalMapping<Self, T>) { - todo!("unmap_physical_region"); - } -} - -pub static TERM: Lazy<spin::Mutex<VTerm>> = Lazy::new(|| spin::Mutex::new(VTerm::new())); - -#[derive(Debug)] -pub struct Path { - pub path: Vec<String>, -} - -impl Path { - pub fn new(path: String) -> Self { - let mut path_vec_string = vec![]; - - for part in path.split(&['\\', '/'][..]) { - path_vec_string.push(part.to_string()); - } - - Path { - path: path_vec_string, - } - } -} - -/// Experimental scratchpad for testing. -pub fn scratchpad() { - // bruh(); - // panic!(":>"); - - // for c in 0..144_697 { - // trace!("{:?}", char::from_u32(c)); - // } - - // bruh(); - - disable(); - let tick_time = fetch_time(); - let hostname = KERNEL_STATE.lock().hostname.clone(); - - let allocator = ALLOCATOR.lock(); - let size = allocator.size(); - let used = allocator.used(); - drop(allocator); - enable(); - - println!( - "{} - ,-------. OS: \u{001A}BLUE\u{001A}AbleOS\u{001A}RESET\u{001A} - ,'\\ _ _`. Host: \u{001A}PINK\u{001A}{}\u{001A}RESET\u{001A} - / \\)_)-)_)-\\ Kernel: \u{001A}RED\u{001A}AKern-{}-v{}\u{001A}RESET\u{001A} -: : Uptime: \u{001A}GREEN\u{001A}{}\u{001A}RESET\u{001A} -\\ / Packages: None - \\ / Shell: BuiltinShell - `. ,' Resolution: 640x480 - `. ,' Terminal: VGABuffer - `.,' CPU: {} - /\\`. ,-._ GPU: VGA Compatible - `-' Memory: {}/{} -{}", - // include_str!("../assets/balloon.txt"), - // kstate.hostname, - BANNER_WIDTH, - hostname, - RELEASE_TYPE, - KERNEL_VERSION, - tick_time, - master().unwrap().brand_string().unwrap(), - // "", - // mem - used, - size, - BANNER_WIDTH - ); - - let pci_ide_device = { - let pci_devices = PCI_DEVICES.lock(); - pci_devices - .iter() - .find_map(|device_ref| { - let device = device_ref.lock(); - if let PciDevice::Ide(dev) = &*device { - println!("IDE Device found: {}", dev.device_info()); - Some(device_ref.clone()) - } else { - None - } - }) - .unwrap() - }; - - { - let mut pci_ide_device = pci_ide_device.lock(); - if let PciDevice::Ide(device) = &mut *pci_ide_device { - let mut first_sector = Vec::with_capacity(512); - device - .read(Channel::Primary, Drive::Master, 0, 1, &mut first_sector) - .unwrap(); - // trace!("IDE Primary/Master sector 0: {first_sector:?}"); - } - } - - real_shell(); -} - -pub fn acpi() { - let acpi_handler = AcpiStruct {}; - let _table; - unsafe { - _table = AcpiTables::search_for_rsdp_bios(acpi_handler); - } - match _table.unwrap().platform_info().unwrap() { - PlatformInfo { - power_profile, - interrupt_model, - .. - } => { - info!("{:?}", power_profile); - info!("{:?}", interrupt_model); - // info!("{:?}", processor_info.unwrap()); - // info!("{:?}", pm_timer.unwrap()); - } - } -} - -pub fn real_shell() { - let prompt = "-> "; - - let _current_dir = "/".to_string(); - let current_user = "able".to_string(); - - let mut buf = String::new(); - print!("{}", prompt); - // panic!(":<"); - loop { - match x86_64::instructions::interrupts::without_interrupts(|| KEYBUFF.lock().pop()) { - Some('\n') => { - // panic!(); - println!(); - // match engine.eval_with_scope::<rhai::Dynamic>(&mut scope, &buf) { - // Ok(o) => println!("{o}"), - - // Err(e) => println!("Eval error: {e}"), - // }; - if !buf.is_empty() { - command_parser(current_user.clone(), buf.clone()); - } - - buf.clear(); - print!("{}", prompt); - } - Some('\u{8}') => { - print!("\u{8}"); - - buf.pop(); - } - - Some('\u{0009}') => { - buf.push(' '); - buf.push(' '); - buf.push(' '); - buf.push(' '); - } - - Some(chr) => { - buf.push(chr); - print!("{}", chr); - } - None => { - // trace!("{}", buf); - } - } - } -} - -pub fn command_parser(user: String, command: String) { - let mut iter = command.split_whitespace(); - - let current_path = Path::new("/home/able".to_string()); - trace!("Current path: {:?}", current_path); - let current_path = "/home/able/"; - - let bin_name = iter.next().unwrap(); - - let mut strin = String::new(); - for stri in iter.clone() { - trace!("{}", stri); - strin.push_str(stri); - } - let conf_args; - match clparse::Arguments::parse_from_string(strin) { - Ok(ok) => conf_args = ok, - Err(err) => { - println!("ERROR: {}", err); - error!("{}", err); - return; - } - }; - - match bin_name { - // note: able asked for rhaish to stay in the repo but will be removed - // in the future so just comment it out for now - // "rhai" => { - // shell(); - // } - "list" | "ls" => { - let mut vfs = VFS.lock(); - let handle = vfs.resolve(current_path).unwrap(); - let dir = vfs.fs_node(handle).unwrap(); - drop(vfs); - for dir_entry in dir.directory().unwrap() { - println!("{}", dir_entry.name()); - } - } - - "echo" => match conf_args.1.arguments.get("p") { - Some(path) => echo_file(path.to_string()), - None => println!("No path provided"), - }, - "test" => {} - "quit" => shutdown(), - "tree" => filesystem::tree("/").unwrap(), - - _ => { - let file = { - let mut vfs = VFS.lock(); - let path = format!("/home/{user}/bins/{bin_name}.wasm"); - let handle = if let Ok(file) = vfs.resolve(path) { - file - } else { - let path = format!("/shared/bins/{bin_name}.wasm"); - if let Ok(file) = vfs.resolve(path) { - file - } else { - let path = format!("/system/bins/{bin_name}.wasm"); - match vfs.resolve(path) { - Ok(file) => file, - Err(error) => { - trace!("{:?}", error); - println!("No such binary: {}", bin_name); - error!("No such binary: {}", bin_name); - return; - } - } - } - }; - - vfs.fs_node(handle).unwrap() - }; - - let mut binary = vec![]; - file.read(0, file.size(), &mut binary).unwrap(); - - let args = iter.collect::<Vec<&str>>(); - println!("{:?}", args); - run_program(&binary); - } - } -} - -pub fn sound(n_frequency: u32) { - let div: u32; - let tmp: u8; - - div = 1193180 / n_frequency; - unsafe { - outb(0xb6, 0x43); - - set_pit_2(div); - - // And play the sound using the PC speaker - tmp = inb(0x61); - if tmp != (tmp | 3) { - outb(tmp | 3, 0x61); - } - } -} - -pub fn sound_off() { - unsafe { - let tmp = inb(0x61) & 0xFC; - outb(tmp, 0x61) - }; - reset_pit_for_cpu(); -} - -pub fn echo_file(path: String) { - println!("{}", path); - let mut current_path = String::from(""); - current_path.push_str(&path); - debug!("Aquiring lock"); - let mut vfs = VFS.lock(); - debug!("Resolving path"); - let maybe_handle = vfs.resolve(¤t_path); - match maybe_handle { - Ok(handle) => { - debug!("Loading file"); - let maybe_file = vfs.fs_node(handle); - - match maybe_file { - Some(file) => { - trace!("checking is directory"); - if file.is_dir() { - println!( - "\u{001A}RED\u{001A}ERROR\u{001A}RESET\u{001A} {} is a directory", - path - ); - error!("{} is a directory", path); - } else { - trace!("allocating buffer for file contents"); - let mut file_contents = Vec::new(); - trace!("Reading file {} into buffer", path); - file.read(0, file.size(), &mut file_contents).unwrap(); - trace!("Converting file bytes into string"); - let file_contents_str = String::from_utf8_lossy(&file_contents); - println!("{}", file_contents_str); - } - } - - None => { - error!("File {} doesn't exist", path); - println!( - "\u{001A}RED\u{001A}ERROR\u{001A}RESET\u{001A}: File {} doesn't exist", - path - ); - } - } - } - Err(err) => { - println!( - "\u{001A}RED\u{001A}ERROR\u{001A}RESET\u{001A}: path {} Error {}", - path, err - ); - error!("path {} Error {}", path, err); - } - } -} diff --git a/ableos/src/serial_print.rs b/ableos/src/serial_print.rs deleted file mode 100644 index aec8c66..0000000 --- a/ableos/src/serial_print.rs +++ /dev/null @@ -1,51 +0,0 @@ -use core::fmt::{Arguments, Error}; - -pub struct Serialout; -impl Serialout { - pub fn write_fmt(&mut self, arg: Arguments<'_>) /*-> Result<(), Error> */ - { - let _ = core::fmt::Write::write_fmt(self, arg); - // Ok(()) - } -} - -impl core::fmt::Write for Serialout { - #[cfg(target_arch = "aarch64")] - fn write_str(&mut self, s: &str) -> Result<(), Error> { - // Don't actually print anything yet lmao - Ok(()) - } - #[cfg(target_arch = "x86_64")] - fn write_str(&mut self, s: &str) -> Result<(), Error> { - crate::arch::drivers::serial::_print(format_args!("{}", s)); - - Ok(()) - } - #[cfg(target_arch = "riscv64")] - fn write_str(&mut self, s: &str) -> Result<(), Error> { - write!(crate::arch::drivers::uart::Uart::new(0x1000_0000), "{}", s) - } - fn write_char(&mut self, c: char) -> core::fmt::Result { - self.write_str(c.encode_utf8(&mut [0; 4])) - } - fn write_fmt(mut self: &mut Self, args: Arguments<'_>) -> core::fmt::Result { - core::fmt::write(&mut self, args) - } -} - -#[macro_export] -macro_rules! serial_print { - () => { - ::core::write!($crate::serial_print::Serialout, "") - }; - ($($tt:tt)*) => { - ::core::write!($crate::serial_print::Serialout, $($tt)*) - }; -} - -#[macro_export] -macro_rules! serial_println { - ($($tt:tt)*) => { - ::core::writeln!($crate::serial_print::Serialout, $($tt)*) - }; -} diff --git a/ableos/src/stdio.rs b/ableos/src/stdio.rs deleted file mode 100644 index f94360d..0000000 --- a/ableos/src/stdio.rs +++ /dev/null @@ -1,61 +0,0 @@ -use { - crate::device_interface::CharacterDevice, - crate::devices::Device::{Block, Character, Vterm}, - core::fmt::{Arguments, Error, Write}, -}; - -#[derive(Debug, Clone)] -pub struct StdIo { - device: String, -} - -impl StdIo { - pub fn new(device: String) -> StdIo { - StdIo { device } - } - pub fn write(&mut self, args: Arguments) -> Result<(), Error> { - use crate::devices::DEVICE_TABLE; - let mut dt = DEVICE_TABLE.lock(); - let key_device = dt.devices.get_mut(&self.device).unwrap(); - - match key_device { - Character(dev) => { - let mut buf = String::new(); - write!(buf, "{}", args).unwrap(); - for c in buf.chars() { - dev.write_char(c); - } - Ok(()) - } - Vterm(vterm) => { - let mut buf = String::new(); - write!(buf, "{}", args).unwrap(); - for c in buf.chars() { - vterm.write_char(c); - } - Ok(()) - } - Block(_) => todo!(), - } - } - - pub fn read(&mut self) { - use crate::devices::DEVICE_TABLE; - let mut dt = DEVICE_TABLE.lock(); - let key_device = dt.devices.get_mut(&self.device).unwrap(); - - match key_device { - Character(dev) => { - let mut buf = String::new(); - dev.read_char().map(|c| buf.push(c)); - println!("{}", buf); - } - Vterm(vterm) => { - let mut buf = String::new(); - vterm.read_char().map(|c| buf.push(c)); - println!("{}", buf); - } - Block(_) => todo!(), - } - } -} diff --git a/ableos/src/tests/mod.rs b/ableos/src/tests/mod.rs deleted file mode 100644 index ca8643a..0000000 --- a/ableos/src/tests/mod.rs +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2022, able <abl3theabove@gmail.com> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -use core::panic::PanicInfo; - -use kernel::arch::arch::sloop; -pub trait Testable { - fn run(&self) -> (); -} - -impl<T> Testable for T -where - T: Fn(), -{ - fn run(&self) { - serial_print!("{}...\t", core::any::type_name::<T>()); - self(); - serial_println!("[ok]"); - } -} - -pub fn test_runner(tests: &[&dyn Testable]) { - serial_println!("Running {} tests", tests.len()); - for test in tests { - test.run(); - } - exit_qemu(QemuExitCode::Success); -} - -pub fn test_panic_handler(info: &PanicInfo) -> ! { - serial_println!("[failed]\n"); - serial_println!("Error: {}\n", info); - exit_qemu(QemuExitCode::Failed); -} - -#[panic_handler] -fn panic(info: &PanicInfo) -> ! { - test_panic_handler(info); -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[repr(u32)] -pub enum QemuExitCode { - Success = 0x10, - Failed = 0x11, -} - -pub fn exit_qemu(exit_code: QemuExitCode) -> ! { - use x86_64::instructions::port::Port; - - unsafe { - let mut port = Port::new(0xf4); - port.write(exit_code as u32); - } - loop {} -} - -entry_point!(test_kernel_main); -/// Entry point for `cargo test` -pub fn test_kernel_main(boot_info: &'static BootInfo) -> ! { - // init(boot_info.physical_memory_offset); - test_main(); - loop {} -} -use bootloader::{entry_point, BootInfo}; diff --git a/ableos/src/tests/old_tests.rs b/ableos/src/tests/old_tests.rs deleted file mode 100644 index c041774..0000000 --- a/ableos/src/tests/old_tests.rs +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2022, able <abl3theabove@gmail.com> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -use crate::{ - kmain::KERNEL_CONF, - network::socket::{SimpleSock, Socket, SocketReturns}, - num_to_vga16, VgaBuffer, SCREEN_BUFFER, -}; -use kernel::TICK; -use picorand::PicoRandGenerate; -use rkyv::{ser::serializers::AllocSerializer, Deserialize}; -use vga::colors::Color16; -use y_compositor_protocol::Version; - -pub fn run_tests() { - if KERNEL_CONF.tests.run_tests { - // quick and dirty testing framework - screen_writer_test(); - socket_test(); - graphics_pipe_test(); - socket_startup_rng(); - socket_test_rng(); - } - - if KERNEL_CONF.tests.run_demos { - graphics_api_demo(); - } - - if KERNEL_CONF.tests.run_shader_tests { - shader_tests(); - } -} - -pub fn socket_test() { - let mut xyz = SimpleSock::new(); - - xyz.peek(); - - xyz.write(vec![0, 1, 2, 3]); - - let x = "simple 🧦".to_string().into_bytes(); - xyz.write(x); - - info!("{:?}", &xyz.read(4).unwrap()); - - match &xyz.peek() { - SocketReturns::ReadOk(strr) => { - let out = String::from_utf8_lossy(strr); - - info!("{}", out); - } - SocketReturns::ReadIndexOutOfBounds => todo!(), - SocketReturns::WriteOk => todo!(), - } -} - -pub fn socket_test_rng() { - let mut test_sock = SimpleSock::grab_socket("RNGProvider".to_string()).unwrap(); - info!( - "Recieving {} from protocol {}", - test_sock.read(1).unwrap()[0], - test_sock.protocol().unwrap() - ); -} - -pub fn socket_startup_rng() { - use picorand::{WyRand, RNG}; - let mut random_socket = SimpleSock::new(); - - random_socket.register_protocol("RNGProvider".to_string()); - let bruh = TICK.load(core::sync::atomic::Ordering::Relaxed); - - let mut rng = RNG::<WyRand, u8>::new(bruh); - - for _ in 0..512 { - let x = rng.generate(); - random_socket.write(vec![x]); - } -} - -pub fn screen_writer_test() { - let mut sock_print_id = SimpleSock::new(); - - sock_print_id.register_protocol("Screen Printer".to_string()); - // sock_print_id.write(format!("a原 b画 cフ dァ eイ fル 集").into()); - // sock_print_id.write(format!("⋮").into()); - - sock_print_id.write(format!("λ³ Half Life 3 booting up ㎣").into()); - // sock_print_id.write(format!("Happy birthday 🎉").into()); - // sock_print_id.write(format!("I look forward to ur ai stuff :^>").into()); - // sock_print_id.write(format!("1....2....3....4....5....6....7....8....9").into()); - - let mut mode = SCREEN_BUFFER.lock(); - for current in (*String::from_utf8_lossy(&sock_print_id.peek().unwrap())).chars() { - mode.draw_char(0, 0, current, from_vga_16(Color16::Red)); - } - mode.copy_to_buffer(); -} - -pub fn vga_boot_screen() { - let mut abcde = SCREEN_BUFFER.lock(); - - for y in 0..480 { - for x in 0..640 { - let segment_x = x * 4 / 640; - let segment_y = y * 4 / 480; - let segment = segment_x + segment_y * 4; - - abcde.set_pixel(x, y, from_vga_16(num_to_vga16(segment as u8))); - } - } -} - -pub fn graphics_pipe_test() { - let mut graphics_pipe = SimpleSock::grab_socket("YCompositor".to_string()).unwrap(); - - let version = Version { - major: 13, - minor: 123, - patch: 0, - }; - use rkyv::ser::Serializer; - let mut serializer = AllocSerializer::<0>::default(); - serializer.serialize_value(&version).unwrap(); - // let bytes = serializer.into_serializer().into_inner(); - - // info!("{:?}", bytes); - let bytes = serializer.into_serializer().into_inner(); - graphics_pipe.write(bytes.into_vec()); - unsafe { - let the_bytes = graphics_pipe.read(3).unwrap(); - let archived = rkyv::archived_root::<Version>(&the_bytes); - let deserialized: Version = archived.deserialize(&mut rkyv::Infallible).unwrap(); - trace!("{:?}", deserialized); - } -} - -pub fn graphics_pipe_startup() { - let mut graphics_pipe = SimpleSock::new(); - - graphics_pipe.register_protocol("YCompositor".to_string()); -} - -pub fn graphics_api_demo() { - let mut abcde = SCREEN_BUFFER.lock(); - abcde.force_redraw(); - - abcde.draw_filled_circle(100, 100, 300, 0x0000ff00); - abcde.draw_unfilled_rect(100, 100, 400, 200, 0xff000000); - abcde.draw_filled_rect(300, 300, 400, 400, 0xff000000); - abcde.draw_line(100, 100, 400, 200, 0xff000000); - abcde.copy_to_buffer(); -} - -pub fn shader_tests() { - let mut graphics = SCREEN_BUFFER.lock(); - - graphics.clear(); - graphics.force_redraw(); - graphics.draw_filled_rect(25, 25, 50, 50, 0xff000000); - graphics.set_pixel(50, 50, 0xffffff00); - graphics.shade(); - - graphics.copy_to_buffer(); - - // drop(graphics) -} - -pub fn ser_de_test() { - let mut proc_1 = SimpleSock::new(); - proc_1.register_protocol("ProcessSpawner".to_string()); - - let version = 0; - use rkyv::ser::Serializer; - let mut serializer = AllocSerializer::<0>::default(); - serializer.serialize_value(&version).unwrap(); - - let bytes = serializer.into_serializer().into_inner(); - proc_1.write(bytes.into_vec()); - unsafe { - let the_bytes = proc_1.read(3).unwrap(); - let archived = rkyv::archived_root::<Version>(&the_bytes); - let deserialized: Version = archived.deserialize(&mut rkyv::Infallible).unwrap(); - trace!("{:?}", deserialized); - } -} diff --git a/ableos/src/time.rs b/ableos/src/time.rs deleted file mode 100644 index 49462d2..0000000 --- a/ableos/src/time.rs +++ /dev/null @@ -1,16 +0,0 @@ -use crate::kmain::TICK; -use core::sync::atomic::Ordering; - -#[cfg(target_arch = "x86_64")] -pub fn fetch_time() -> f64 { - let time = x86_64::instructions::interrupts::without_interrupts(|| { - TICK.load(Ordering::Relaxed) as f64 - }); - time -} - -#[cfg(target_arch = "riscv64")] -pub fn fetch_time() -> f64 { - let time = TICK.load(Ordering::Relaxed) as f64; - time -} diff --git a/ableos/src/unicode_utils.rs b/ableos/src/unicode_utils.rs deleted file mode 100644 index 45d1930..0000000 --- a/ableos/src/unicode_utils.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![allow(dead_code)] - -pub const CONSOLE: &str = "\u{E795}"; -pub const POWER_SIGN: &str = "\u{23FB}"; -pub const LAMBDA: &str = "λ"; diff --git a/ableos/src/usb/mod.rs b/ableos/src/usb/mod.rs deleted file mode 100644 index 2feda21..0000000 --- a/ableos/src/usb/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -//! - -pub enum UsbSpeed { - /// Super-speed functions operate at up to 5 Gb/s. - Super, - - /// High-speed functions operate at up to 480 Mb/s. - High, - - /// Full-speed functions operate at up to 12 Mb/s. - Full, - - /// Low-speed functions operate at up to 1.5 Mb/s. - Low, -} diff --git a/ableos/src/utils.rs b/ableos/src/utils.rs deleted file mode 100644 index 183d6db..0000000 --- a/ableos/src/utils.rs +++ /dev/null @@ -1,36 +0,0 @@ -//! Small generic utilities - -#[inline] -pub fn type_of<T>(_: &T) -> &str { - core::any::type_name::<T>() -} - -#[no_mangle] -#[allow(unconditional_recursion)] -pub extern "C" fn stack_overflow() -> u8 { - stack_overflow(); - // meme number - 69 // NOTE: Any specific reason for this number aside from memes? -} - -#[cfg(test)] -mod tests { - use super::*; - - // #[test] - fn test_type_of() { - assert_eq!(type_of(&1), "i32"); - } -} - -pub const fn kb(x: usize) -> usize { - x * 1024 -} - -pub const fn mb(x: usize) -> usize { - x * 1024 * 1024 -} - -pub const fn gb(x: usize) -> usize { - x * 1024 * 1024 * 1024 -} diff --git a/ableos/src/vga_e.rs b/ableos/src/vga_e.rs deleted file mode 100644 index 72c0043..0000000 --- a/ableos/src/vga_e.rs +++ /dev/null @@ -1,35 +0,0 @@ -use vga::{colors::Color16, writers::Graphics640x480x16}; - -pub static VGAE_BUFF_OFFSET_X: spin::Mutex<u8> = spin::Mutex::new(0); -pub static VGAE_BUFF_OFFSET_Y: spin::Mutex<u8> = spin::Mutex::new(0); -pub static VGAE: spin::Mutex<Graphics640x480x16> = { - let xyz = Graphics640x480x16::new(); - // xyz.set_mode(); - spin::Mutex::new(xyz) -}; - -/// Converts a number to ... i forgor 💀 -pub const fn num_to_vga16(num: u8) -> Color16 { - use Color16::*; - - match num { - 0 => Black, - 1 => Blue, - 2 => Green, - 3 => Cyan, - 4 => Red, - 5 => Magenta, - 6 => Brown, - 7 => LightGrey, - 8 => DarkGrey, - 9 => LightBlue, - 10 => LightGreen, - 11 => LightCyan, - 12 => LightRed, - 13 => Pink, - 14 => Yellow, - 15 => White, - // NOTE: Leasve the in - _ => Color16::Pink, - } -} diff --git a/ableos/src/virtio/mod.rs b/ableos/src/virtio/mod.rs deleted file mode 100644 index 802a722..0000000 --- a/ableos/src/virtio/mod.rs +++ /dev/null @@ -1,94 +0,0 @@ -//! virtio device -//! -//! This module contains the virtio device structural code. -//! -//! # Notes -//! <https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-20001> - -pub struct VirtioDevice { - _status: VirtioDeviceStatus, -} - -use crate::devices::pci::PciDeviceInfo; - -pub fn device_handler(device: PciDeviceInfo) { - use crate::devices::pci::PciClass::*; - match device.class() { - // Unclassified => todo!(), - // MassStorage => todo!(), - // Network => todo!(), - Display => { - trace!("Display found"); - println!("{}", device.interrupt_pin()); - } - // Multimedia => todo!(), - // Memory => todo!(), - // Bridge => todo!(), - // Other => todo!(), - _ => {} - } -} - -#[repr(C)] -pub enum VirtioDeviceStatus { - // Indicates that the guest OS has found the device and recognized it as a valid virtio device. - Acknowleged = 1, - // Indicates that the guest OS knows how to drive the device. Note: There could be a significant (or infinite) delay before setting this bit. For example, under Linux, drivers can be loadable modules. - Driver = 2, - // Indicates that the driver has acknowledged all the features it understands, and feature negotiation is complete. - FeaturesOk = 8, - // Indicates that the device is set up and ready to drive the device. - DriverOk = 4, - // Indicates that the device needs to be reset. - DeviceNeedsReset = 64, - // Indicates that the device has failed. - Failed = 128, -} - -pub struct FeaturesBits(u64); -impl FeaturesBits { - // bit mask the first 23 bits and return a u64 - // 0 to 23 - // Feature bits for the specific device type - pub fn device_type_features(&self) -> u64 { - 0 - } - - // bit mask the 24th bit to the 37th bit and return a u64 - // 24 to 37 - // Feature bits reserved for extensions to the queue and feature negotiation mechanisms - pub fn extension_features(&self) -> u64 { - 0 - } - - // bit mask the 38th bit to the 63th bit and return a u64 - // 38 and above - // Feature bits reserved for future extensions. - pub fn future_features(&self) -> u64 { - 0 - } -} - -// configuration change notification -// available buffer notification -// used buffer notification. - -#[repr(C)] -pub struct VirtioDeviceNotification { - pub type_: u32, - pub index: u32, - pub value: u32, -} - -pub struct Vring { - pub addr: u64, - pub len: u32, - pub flags: u16, - pub next: u16, -} - -pub struct VringAvail { - pub flags: u16, - pub idx: u16, - pub ring: [u16; 0xFFFF], -} diff --git a/ableos/src/vterm.rs b/ableos/src/vterm.rs deleted file mode 100644 index a904551..0000000 --- a/ableos/src/vterm.rs +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 2022, Able <able@ablecorp.us> - * - * SPDX-License-Identifier: MPL-2.0 - */ -#![deny(missing_docs)] -//! The VTerm is a terminal with nice - -use crate::{hardware::MOUSE, vga_e::VGAE}; -use ab_glyph::{Font, FontRef, Glyph}; -use logos::{Lexer, Logos}; -use spin::Lazy; -use vga::{colors::Color16, writers::GraphicsWriter}; - -const TERM_MINUS_ONE_LINE: usize = 4720; -const CURSOR_COLOR: Color16 = Color16::Cyan; - -#[derive(Debug)] -/// A VTerm -pub struct VTerm { - dirty: bool, - color: Color16, - term: [(char, Color16); 80 * 60], - back_buffer: [u8; 640 * 480], - x: u8, -} -impl VTerm { - /// Construct a new VTerm - pub fn new() -> Self { - let mode = VGAE.lock(); - mode.set_mode(); - // let fb = mode.get_frame_buffer(); - drop(mode); - - Self { - dirty: false, - x: 0, - back_buffer: [0; 640 * 480], - term: [('\u{001A}', Color16::DarkGrey); 80 * 60], - color: Color16::White, - } - } - /// Check the dirty state of the VTerm - pub fn is_dirty(&self) -> bool { - self.dirty - } - - /// Set the dirty state of the VTerm - pub fn set_dirty(&mut self, dirty: bool) { - self.dirty = dirty - } - - /// Append a &str to the VTerm - pub fn print(&mut self, data: &str) { - let mut lex = Token::lexer(data); - - for toke in lex { - match toke { - Token::Reset => { - self.color = Color16::White; - } - Token::Error => {} - Token::TBlack => self.color = Color16::Black, - Token::TBlue => self.color = Color16::Blue, - Token::TGreen => self.color = Color16::Green, - Token::TCyan => self.color = Color16::Cyan, - Token::TRed => self.color = Color16::Red, - Token::TMagenta => self.color = Color16::Magenta, - Token::TBrown => self.color = Color16::Brown, - Token::TLightGrey => self.color = Color16::LightGrey, - Token::TDarkGrey => self.color = Color16::DarkGrey, - Token::TLightBlue => self.color = Color16::LightBlue, - Token::TLightGreen => self.color = Color16::LightGreen, - Token::TLightCyan => self.color = Color16::LightCyan, - Token::TLightRed => self.color = Color16::LightRed, - Token::TPink => self.color = Color16::Pink, - Token::TYellow => self.color = Color16::Yellow, - Token::TWhite => self.color = Color16::White, - // Token::Space => { - // self.term[TERM_MINUS_ONE_LINE + (self.x as usize)] = (' ', self.color); - // self.x += 1; - // } - Token::Text(st) => { - for c in st.chars() { - if self.x == 80 { - // trace!("X too big moving up"); - self.move_up(); - } - // trace!("C"); - match c { - '\u{001A}' => { - self.term[TERM_MINUS_ONE_LINE + (self.x as usize)] = - (c, self.color); - self.x += 1; - } - - '\u{08}' => { - if self.x == 0 { - trace!("IMPOSSIBLE BACKSPACE"); - return; - } - self.x -= 1; - self.term[TERM_MINUS_ONE_LINE + (self.x as usize)] = - ('\u{001A}', Color16::LightGrey); - } - '\n' => { - self.move_up(); - self.x = 0; - } - - c => { - self.term[TERM_MINUS_ONE_LINE + (self.x as usize)] = - (c, self.color); - self.x += 1; - } - } - } - } - } - } - } - - /// Move the VTerm up by one line - pub fn move_up(&mut self) { - self.term.rotate_left(80); - for x in 0..80 { - self.term[TERM_MINUS_ONE_LINE + x] = ('\u{001A}', Color16::DarkGrey); - } - self.x = 0; - } - - /// Redraw the VTerm to the VGA buffer - pub fn draw_term(&mut self) { - if self.is_dirty() { - // trace!("Redrawing"); - use Color16::*; - let mode = VGAE.lock(); - mode.clear_screen(DarkGrey); - let mut x = 0; - let mut y = 0; - - for c in self.term { - mode.draw_character(x * 8, y * 8, c.0, c.1); - // mode.draw_unicode_char(x, y, c.0, c.1); - if x == 79 { - y += 1; - - x = 0; - } else { - x += 1 - } - } - - { - let mouse_coord = x86_64::instructions::interrupts::without_interrupts(|| { - let cursor = MOUSE.lock(); - - (cursor.get_x() as usize, cursor.get_y() as usize) - }); - - mode.draw_line( - (mouse_coord.0 as isize + 0, mouse_coord.1 as isize + 0), - (mouse_coord.0 as isize + 10, mouse_coord.1 as isize + 10), - CURSOR_COLOR, - ); - mode.draw_line( - (mouse_coord.0 as isize + 0, mouse_coord.1 as isize + 0), - (mouse_coord.0 as isize + 5, mouse_coord.1 as isize + 0), - CURSOR_COLOR, - ); - mode.draw_line( - (mouse_coord.0 as isize + 0, mouse_coord.1 as isize + 0), - (mouse_coord.0 as isize + 0, mouse_coord.1 as isize + 5), - CURSOR_COLOR, - ); - } - - drop(mode); - - /* - let mut x = 0; - let mut y = 0; - for c in ['b'; 80 * 60] - // "abcdefghijklmnopqrstuvwxyzabcdefghijk\nabcd jkjhgkjhgkjhgefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz12" - // .chars() - { - if c == '\n' { - y += 1; - x = 0; - continue; - } - - self.draw_char(x, y, c, Color16::Red); - if x == 80 { - y += 1; - x = 1; - } else { - x += 1; - } - } - */ - self.set_dirty(false); - // trace!("Finished drawing"); - } - } -} - -#[derive(Logos, Debug, Clone, PartialEq)] -enum Token { - #[regex(r"", logos::skip)] - #[error] - Error, - - #[token("\u{001A}RESET\u{001A}", priority = 10)] - Reset, - - #[token("\u{001A}BLACK\u{001A}", priority = 10)] - TBlack, - #[regex("\u{001A}BLUE\u{001A}", priority = 10)] - TBlue, - #[token("\u{001A}GREEN\u{001A}", priority = 10)] - TGreen, - #[token("\u{001A}CYAN\u{001A}", priority = 10)] - TCyan, - #[token("\u{001A}RED\u{001A}", priority = 10)] - TRed, - #[token("\u{001A}MAGENTA\u{001A}", priority = 10)] - TMagenta, - #[token("\u{001A}BROWN\u{001A}", priority = 10)] - TBrown, - #[token("\u{001A}LIGHTGREY\u{001A}", priority = 10)] - TLightGrey, - #[token("\u{001A}DARKGREY\u{001A}", priority = 10)] - TDarkGrey, - #[token("\u{001A}LIGHTBLUE\u{001A}", priority = 10)] - TLightBlue, - #[token("\u{001A}LIGHTGREEN\u{001A}", priority = 10)] - TLightGreen, - #[token("\u{001A}LIGHTCYAN\u{001A}", priority = 10)] - TLightCyan, - #[token("\u{001A}LIGHTRED\u{001A}", priority = 10)] - TLightRed, - #[token("\u{001A}PINK\u{001A}", priority = 10)] - TPink, - #[token("\u{001A}YELLOW\u{001A}", priority = 10)] - TYellow, - #[token("\u{001A}WHITE\u{001A}", priority = 10)] - TWhite, - - // #[token(" ")] - - // Space, - #[regex("[\t\n\u{8}█!-\u{10FFFF} ]+", text_lex, priority = 0)] - /// A printable string - Text(String), -} - -fn text_lex(lex: &mut Lexer<Token>) -> String { - lex.slice().into() -} diff --git a/ableos/src/wasm/mod.rs b/ableos/src/wasm/mod.rs deleted file mode 100644 index 7d55849..0000000 --- a/ableos/src/wasm/mod.rs +++ /dev/null @@ -1,110 +0,0 @@ -/// `NULL a s m` as an array of 4 bytes -pub const WASM_BINARY_MAGIC: [u8; 4] = [0x00, 0x61, 0x73, 0x6d]; - -/// `1 0 0 0` as an array of 4 bytes -pub const WASM_VERSION: [u8; 4] = [0x01, 0x00, 0x00, 0x00]; - -/// A wasm section -/// -/// # Examples -/// ``` -/// use wasm_loader::wasm::WasmSection; -/// let section = WasmSection::new(0, vec![0x00, 0x01, 0x02, 0x03]); -/// assert_eq!(section.id, 0); -/// assert_eq!(section.data, vec![0x00, 0x01, 0x02, 0x03]); -/// ``` -/// # Notes -/// The wasm spec defines the following section types: -/// * `0`: custom -/// * `1`: type -/// * `2`: import -/// * `3`: function -/// * `4`: table -/// * `5`: memory -/// * `6`: global -/// * `7`: export -/// * `8`: start -/// * `9`: element -/// * `10`: code -/// * `11`: data -pub enum SectionType { - None = 0, - Type = 1, - Import = 2, - Function = 3, - Table = 4, - Memory = 5, - Global = 6, - Export = 7, - Start = 8, - Element = 9, - Code = 10, - Data = 11, -} - -pub struct Section { - /// The section type - _stype: SectionType, - _section_size: u8, -} - -/// A wasm type -/// # Examples -/// ``` -/// use wasm_loader::wasm::WasmType; -/// let type_ = WasmType::new(vec![0x00, 0x01, 0x02, 0x03]); -/// assert_eq!(type_.subtypes, vec![0x00, 0x01, 0x02, 0x03]); -/// ``` -/// # Notes -/// The wasm spec defines the following type subtypes: -/// * `0`: anyfunc -/// * `1`: func -/// * `2`: block -/// * `3`: i32 -/// * `4`: i64 -/// * `5`: f32 -/// * `6`: f64 -pub enum WasmType { - Anyfunc = 0, - Func = 1, - Block = 2, - I32 = 3, - I64 = 4, - F32 = 5, - F64 = 6, -} - -pub struct WasmProgram { - raw_bytes: Vec<u8>, -} - -impl WasmProgram { - pub fn new_from_bytes(bytes: &[u8]) -> Self { - Self { - raw_bytes: bytes.to_vec(), - } - } - /// Returns the a tuple of two bools - /// The first bool is true if the wasm binary is valid - /// The second bool is true if the wasm binary version is 1 - /// - /// # Examples - /// ``` - /// use wasm_loader::wasm::WasmProgram; - /// let wasm_program = WasmProgram::new_from_bytes(b"\0\0\0\01\0\0\0"); - /// assert_eq!(wasm_program.is_valid(), (true, false)); - /// ``` - pub fn validate_header(self) -> (bool, bool) { - let mut byte_magic_valid = false; - let mut byte_version_valid = false; - - if self.raw_bytes[0..4] == WASM_BINARY_MAGIC { - byte_magic_valid = true; - } - - if self.raw_bytes[4..8] == WASM_VERSION { - byte_version_valid = true; - } - (byte_magic_valid, byte_version_valid) - } -} diff --git a/ableos/src/wasm_jumploader/host_functions.rs b/ableos/src/wasm_jumploader/host_functions.rs deleted file mode 100644 index f560d3a..0000000 --- a/ableos/src/wasm_jumploader/host_functions.rs +++ /dev/null @@ -1,178 +0,0 @@ -use crate::{arch::generate_process_pass, ipc::channel::ChannelMessage, rhai_shell::KEYBUFF}; -use wasmi::{ - Error, Externals, FuncInstance, FuncRef, ModuleImportResolver, RuntimeArgs, RuntimeValue, - Signature, Trap, ValueType, -}; - -macro_rules! wasmi_type { - (bool) => { - ValueType::I32 - }; - (u8) => { - ValueType::I32 - }; - (u16) => { - ValueType::I32 - }; - (u32) => { - ValueType::I32 - }; - (u64) => { - ValueType::I64 - }; - (i8) => { - ValueType::I32 - }; - (i16) => { - ValueType::I32 - }; - (i32) => { - ValueType::I32 - }; - (i64) => { - ValueType::I64 - }; - (f32) => { - ValueType::F32 - }; - (f64) => { - ValueType::F64 - }; -} - -macro_rules! wasmi_return_type { - () => { - None - }; - ($type: ident) => { - Some(wasmi_type!($type)) - }; -} - -macro_rules! host_externals { - ( - $($index: literal: $name: ident ($($arg_name: ident: $arg_type: ident),* $(,)?) $(-> $return_type: ident)? $block: block)* - ) => { - pub struct HostExternals; - impl Externals for HostExternals { - fn invoke_index( - &mut self, - index: usize, - args: RuntimeArgs - ) -> Result<Option<RuntimeValue>, Trap> { - match index { - $( - $index => match args.as_ref() { - [$($arg_name),*] => { - $( - let $arg_name: $arg_type = (*$arg_name) - .try_into() - .ok_or(wasmi::TrapKind::UnexpectedSignature)?; - )* - $block - }, - _ => return Err(wasmi::TrapKind::UnexpectedSignature.into()), - } - ),* - _ => { - error!("Unimplemented function at {index}"); - Err(Trap::new(wasmi::TrapKind::Unreachable)) - } - } - } - } - - impl ModuleImportResolver for HostExternals { - fn resolve_func(&self, field_name: &str, signature: &Signature) -> Result<FuncRef, Error> { - let (index, param_types, return_type): (usize, &[ValueType], Option<ValueType>) = - match field_name { - $( - stringify!($name) => ( - $index, - &[$(wasmi_type!($arg_type)),*], - wasmi_return_type!($($return_type)?), - ), - )* - _ => { - return Err(Error::Instantiation(format!( - "Export {field_name} not found", - ))); - }, - }; - - if !(param_types.len() != signature.params().len() || return_type != signature.return_type()) - && param_types - .iter() - .zip(signature.params()) - .find(|(ty, param)| ty != param) - .is_none() - { - trace!("Resolved export {field_name} at func {index}"); - Ok(FuncInstance::alloc_host(signature.clone(), index)) - } else { - Err(Error::Instantiation(format!( - "Export {field_name} has a bad signature {signature:?}", - ))) - } - } - } - }; -} - -host_externals! { - 0: add(a: u32, b: u32) -> u32 { - let result = a + b; - trace!("SYSCALL: {} + {} = {}", a, b, result); - Ok(Some(result.into())) - } - - 1: send_signal(pid: u32, signal: u32) -> i32 { - trace!("SYSCALL: send signal {} to pid {}", signal, pid); - Ok(Some(0.into())) - } - - 2: get_time() -> u32 { - use core::sync::atomic::Ordering::*; - trace!("SYSCALL: get time"); - - x86_64::instructions::interrupts::disable(); - let tick_time = crate::kmain::TICK.load(Relaxed); - x86_64::instructions::interrupts::enable(); - - let ret: u32 = tick_time.try_into().unwrap(); - Ok(Some(ret.into())) - } - - 3: get_random() -> i32 { - trace!("SYSCALL: get random"); - let rand = generate_process_pass() as i32; - Ok(Some(rand.into())) - } - - 4: get_input() -> i32 { - let input = None; - x86_64::instructions::interrupts::without_interrupts(|| KEYBUFF.lock().pop()); - if let Some(chr) = input { - trace!("SYSCALL: input: {}", chr); - } - - let ret = input.unwrap_or(0x00 as char) as i32; - Ok(Some(ret.into())) - } - - 5: print_char(chr: u8) { - trace!("SYSCALL: print: {}", chr); - print!("{}", char::from(chr)); - Ok(None) - } - - - - // TODO: Send a message to a channel - 6: send_channel_message(){ - - - Ok(None) - - } -} diff --git a/ableos/src/wasm_jumploader/mod.rs b/ableos/src/wasm_jumploader/mod.rs deleted file mode 100644 index 21e7df9..0000000 --- a/ableos/src/wasm_jumploader/mod.rs +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me> - * - * SPDX-License-Identifier: MPL-2.0 - */ - -pub mod host_functions; - -use crate::wasm_jumploader::host_functions::HostExternals; -use wasmi::{ImportsBuilder, ModuleInstance}; - -pub fn interp() { - trace!("Interpreting..."); - // let fs = &*FILE_SYSTEM.lock(); - // trace!("Got filesystem"); - // let file = fs - // .open( - // b"/home/able/bins/aos_test.wasm", - // OpenOptions::new().read(true), - // ) - // .unwrap(); - - // let mut wasm_binary = Vec::new(); - - // let ret = file.read_to_end(&mut wasm_binary).unwrap(); - // trace!("Binary size {}", ret); - // // Load wasm binary and prepare it for instantiation. - // let module = wasmi::Module::from_buffer(&wasm_binary).expect("failed to load wasm"); - // trace!("Loaded wasm binary"); - // let imports = ImportsBuilder::new().with_resolver("env", &host_functions::HostExternals {}); - // trace!("Created imports"); - - // // Instantiate a module with empty imports and - // // assert that there is no `start` function. - // let instance = ModuleInstance::new(&module, &imports); // .expect("failed to instantiate wasm module") - - // match instance { - // Ok(inst) => { - // let instance = inst.assert_no_start(); - // let mut is_driver = false; - // let _is_program = false; - // let mut has_driver_entry = false; - // let mut has_driver_exit = false; - // let mut has_start = false; - - // if let Some(_val) = instance.export_by_name("driver_entry") { - // has_driver_entry = true; - // } - - // if let Some(_val) = instance.export_by_name("driver_exit") { - // has_driver_exit = true; - // } - - // match instance.export_by_name("start") { - // Some(_val) => { - // trace!("Program start function found"); - // has_start = true; - // } - // None => debug!("No start function found"), - // } - - // match instance.export_by_name("main") { - // Some(_val) => { - // trace!("Program main function found"); - // has_start = true; - // } - // None => debug!("No main function found"), - // } - - // match (has_driver_entry, has_driver_exit) { - // (true, true) => { - // trace!("Valid driver entry and exit functions found"); - // is_driver = true; - // } - // (true, false) => error!("Driver entry function found but no driver exit function"), - // (false, true) => error!("Driver exit function found but no driver entry function"), - // (false, false) => { - // trace!("No driver entry or exit functions found"); - // } - // } - - // if has_start && has_driver_entry { - // error!( - // "A program should not have both a start function and a driver entry function. It Will be treated as a program." - // ); - // } - - // if has_start { - // let ret = instance - // .invoke_export("start", &[], &mut HostExternals {}) - // .expect("failed to execute export"); - - // println!("collected wasm return value: {:?}", ret); - // } else if is_driver { - // let ret = instance - // .invoke_export("driver_entry", &[], &mut HostExternals {}) - // .expect("failed to execute export"); - - // println!("collected wasm return value: {:?}", ret); - // } - // } - // Err(err) => error!("{}", err), - // } -} - -pub fn run_program(program: &[u8]) { - // Load wasm binary and prepare it for instantiation. - let module = wasmi::Module::from_buffer(program).expect("failed to load wasm"); - - trace!("Loaded wasm binary"); - let imports = ImportsBuilder::new().with_resolver("env", &host_functions::HostExternals {}); - trace!("Created imports"); - - // Instantiate a module with empty imports and - // assert that there is no `start` function. - let instance = ModuleInstance::new(&module, &imports); - - // .expect("failed to instantiate wasm module") - - match instance { - Ok(inst) => { - let instance = inst.assert_no_start(); - let mut is_driver = false; - let _is_program = false; - let mut has_driver_entry = false; - let mut has_driver_exit = false; - let mut has_start = false; - - if let Some(_val) = instance.export_by_name("driver_entry") { - has_driver_entry = true; - } - - if let Some(_val) = instance.export_by_name("driver_exit") { - has_driver_exit = true; - } - - match instance.export_by_name("start") { - Some(_val) => { - trace!("Program start function found"); - has_start = true; - } - None => debug!("No start function found"), - } - - match instance.export_by_name("main") { - Some(_val) => { - trace!("Program main function found"); - has_start = false; - } - None => debug!("No main function found"), - } - - match (has_driver_entry, has_driver_exit) { - (true, true) => { - trace!("Valid driver entry and exit functions found"); - is_driver = true; - } - (true, false) => error!("Driver entry function found but no driver exit function"), - (false, true) => error!("Driver exit function found but no driver entry function"), - (false, false) => { - trace!("No driver entry or exit functions found"); - } - } - - if has_start && has_driver_entry { - error!( - "A program should not have both a start function and a driver entry function. It Will be treated as a program." - ); - } - - if has_start { - let ret = instance - .invoke_export("start", &[], &mut HostExternals {}) - .expect("failed to execute export"); - - println!("collected wasm return value: {:?}", ret); - } else if is_driver { - let ret = instance - .invoke_export("driver_entry", &[], &mut HostExternals {}) - .expect("failed to execute export"); - - println!("collected wasm return value: {:?}", ret); - } else { - println!("ERROR: No start or driver entry function found, invalid program"); - } - } - Err(err) => error!("{}", err), - } -} diff --git a/api/file.axel b/api/file.axel deleted file mode 100644 index 111c92e..0000000 --- a/api/file.axel +++ /dev/null @@ -1,12 +0,0 @@ -file { - val= - name: "Hi" - extension: "txt" - size: 123 - - fn| - open: (None)->() - read: (Num)->(String) - write: (Num, String)->(Bool) - close: (None)->(Bool) -} diff --git a/asl/Cargo.toml b/asl/Cargo.toml deleted file mode 100644 index b01793c..0000000 --- a/asl/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "asl" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] - -[dependencies.logos] -version = "0.12.1" -default-features = false diff --git a/asl/assets/asl/asl_simple.asl b/asl/assets/asl/asl_simple.asl deleted file mode 100644 index 7d18aa5..0000000 --- a/asl/assets/asl/asl_simple.asl +++ /dev/null @@ -1,10 +0,0 @@ -DefinitionBlock ("test.aml", "DSDT", 1, "OEMID ", "TABLEID ", 0x00000000) -{ - Scope (_SB) - { - Device (PCI0) - { - Name (_HID, EisaId ("PNP0A03")) - } - } -} \ No newline at end of file diff --git a/asl/src/lib.rs b/asl/src/lib.rs deleted file mode 100644 index da05710..0000000 --- a/asl/src/lib.rs +++ /dev/null @@ -1,35 +0,0 @@ -use logos::{Lexer, Logos}; - -#[derive(Logos, Debug, Clone, Copy, PartialEq)] -enum Token { - #[regex(r"[ \t\n\f]+", logos::skip)] - #[error] - Error, - - #[regex("[1-9]+", num_parser)] - Num(isize), -} -fn num_parser(lex: &mut Lexer<Token>) -> isize { - let slice = lex.slice(); - let num_str: String = slice.into(); - let num = num_str.parse::<isize>(); - num.unwrap() -} - -#[test] -pub fn num_test() { - let mut lex = Token::lexer("5 42 75"); - assert_eq!(lex.next(), Some(Token::Num(5))); - assert_eq!(lex.next(), Some(Token::Num(42))); - assert_eq!(lex.next(), Some(Token::Num(75))); -} - -#[test] -pub fn asl_simple_test() { - let lex = Token::lexer(include_str!("../assets/asl/asl_simple.asl")); - - for token in lex { - // println!("{:?}", token); - assert_ne!(Token::Error, token); - } -} diff --git a/disk.img b/disk.img deleted file mode 100644 index bbe4df9..0000000 Binary files a/disk.img and /dev/null differ diff --git a/ext2-rs/Cargo.toml b/ext2-rs/Cargo.toml deleted file mode 100644 index f72ff11..0000000 --- a/ext2-rs/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "ext2" -version = "0.1.1" -authors = ["Szymon Walter <walter.szymon.98@gmail.com>", -"able <abl3theabove@gmail.com>"] - - -[dependencies] -bitflags = "1.0" -rlibc = { version = "1.0", optional = true } -spin = "0.9.2" -genfs = "^0.1.4" - -[features] -default = ["no_std"] -no_std = ["rlibc"] diff --git a/ext2-rs/LICENSE.md b/ext2-rs/LICENSE.md deleted file mode 100644 index 9894777..0000000 --- a/ext2-rs/LICENSE.md +++ /dev/null @@ -1,22 +0,0 @@ -# ext2-rs -## an ext2 implementation - -Copyright © 2018, Szymon Walter - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from -the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not - be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -#### walter.szymon.98@gmail.com diff --git a/ext2-rs/README.md b/ext2-rs/README.md deleted file mode 100644 index 8dd53d6..0000000 --- a/ext2-rs/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# ext2-rs - -An OS and architecture independent implementation of ext2 in pure Rust. diff --git a/ext2-rs/rustfmt.toml b/ext2-rs/rustfmt.toml deleted file mode 100644 index 3450fc4..0000000 --- a/ext2-rs/rustfmt.toml +++ /dev/null @@ -1,2 +0,0 @@ -max_width = 80 -wrap_comments = true diff --git a/ext2-rs/src/error.rs b/ext2-rs/src/error.rs deleted file mode 100644 index f506ae9..0000000 --- a/ext2-rs/src/error.rs +++ /dev/null @@ -1,124 +0,0 @@ -//! Errors -use { - alloc::string::String, - core::fmt::{self, Display}, -}; - -#[cfg(any(test, not(feature = "no_std")))] -use std::io; - -/// The set of all possible errors -#[derive(Debug)] -pub enum Error { - /// Generic error - Other(String), - /// Bad magic number - BadMagic { - /// The magic number - magic: u16, - }, - /// Out of bounds error - OutOfBounds { - /// index - index: usize, - }, - /// Address out of bounds - AddressOutOfBounds { - /// - sector: u32, - /// - offset: u32, - - /// - size: usize, - }, - /// Bad block group count - BadBlockGroupCount { - /// - by_blocks: u32, - /// - by_inodes: u32, - }, - /// Inode Not Found - InodeNotFound { - /// inode number - inode: u32, - }, - /// Inode is not a directory - NotADirectory { - /// inode number - inode: u32, - /// inode name - name: String, - }, - /// Not Absolute Path - NotAbsolute { - /// path name - name: String, - }, - - /// Not Found - NotFound { - /// inode name - name: String, - }, - // #[cfg(any(test, not(feature = "no_std")))] - // Io { inner: io::Error }, -} - -impl Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Error::Other(ref msg) => write!(f, "{}", msg), - Error::BadMagic { - magic, - } => write!(f, "invalid magic value: {}", magic), - Error::OutOfBounds { - index, - } => write!(f, "index ouf of bounds: {}", index), - Error::AddressOutOfBounds { - sector, - offset, - size, - } => write!(f, "address ouf of bounds: {}:{} with a block size of: {}", - sector, offset, size), - Error::BadBlockGroupCount { - by_blocks, - by_inodes, - } => write!(f, "conflicting block group count data; by blocks: {}, by inodes: {}", by_blocks, by_inodes), - Error::InodeNotFound { - inode, - } => write!(f, "couldn't find inode no. {}", &inode), - Error::NotADirectory { - inode, - ref name, - } => write!(f, "inode no. {} at: {} is not a directory", inode, &name), - Error::NotAbsolute { - ref name, - } => write!(f, "{} is not an absolute path", &name), - Error::NotFound { - ref name, - } => write!(f, "couldn't find {}", &name), - #[cfg(any(test, not(feature = "no_std")))] - Error::Io { - ref inner, - } => write!(f, "io error: {}", inner), - } - } -} - -impl From<Infallible> for Error { - fn from(_: Infallible) -> Error { - unreachable!() - } -} - -#[cfg(any(test, not(feature = "no_std")))] -impl From<io::Error> for Error { - fn from(inner: io::Error) -> Error { - Error::Io { inner } - } -} - -/// Infalliable -pub enum Infallible {} diff --git a/ext2-rs/src/fs/mod.rs b/ext2-rs/src/fs/mod.rs deleted file mode 100644 index 1844e31..0000000 --- a/ext2-rs/src/fs/mod.rs +++ /dev/null @@ -1,177 +0,0 @@ -//! - -use { - alloc::vec::Vec, - core::mem, - error::Error, - sector::{Address, SectorSize}, - sys::{ - block_group::BlockGroupDescriptor, inode::Inode as RawInode, - superblock::Superblock, - }, - volume::Volume, -}; - -pub mod sync; - -#[allow(dead_code)] -pub(crate) struct Struct<T, S: SectorSize> { - pub inner: T, - pub offset: Address<S>, -} - -impl<T, S: SectorSize> From<(T, Address<S>)> for Struct<T, S> { - #[inline] - fn from((inner, offset): (T, Address<S>)) -> Struct<T, S> { - Struct { inner, offset } - } -} - -/// Safe wrapper for raw sys structs -pub struct Ext2<S: SectorSize, V: Volume<u8, S>> { - // TODO: should this have some different vis? - pub(crate) volume: V, - pub(crate) superblock: Struct<Superblock, S>, - pub(crate) block_groups: Struct<Vec<BlockGroupDescriptor>, S>, -} - -impl<S: SectorSize, V: Volume<u8, S>> Ext2<S, V> { - /// - pub fn new(volume: V) -> Result<Ext2<S, V>, Error> { - let superblock = unsafe { Struct::from(Superblock::find(&volume)?) }; - let block_groups_offset = Address::with_block_size( - superblock.inner.first_data_block + 1, - 0, - superblock.inner.log_block_size + 10, - ); - let block_groups_count = superblock - .inner - .block_group_count() - .map(|count| count as usize) - .map_err(|(a, b)| Error::BadBlockGroupCount { - by_blocks: a, - by_inodes: b, - })?; - let block_groups = unsafe { - BlockGroupDescriptor::find_descriptor_table( - &volume, - block_groups_offset, - block_groups_count, - )? - }; - let block_groups = Struct::from(block_groups); - Ok(Ext2 { - volume, - superblock, - block_groups, - }) - } - /// Return the version of the filesystem - pub fn version(&self) -> (u32, u16) { - ( - self.superblock.inner.rev_major, - self.superblock.inner.rev_minor, - ) - } - /// Return inode size - pub fn inode_size(&self) -> usize { - if self.version().0 == 0 { - mem::size_of::<RawInode>() - } else { - // note: inodes bigger than 128 are not supported - self.superblock.inner.inode_size as usize - } - } - /// - pub fn inodes_count(&self) -> usize { - self.superblock.inner.inodes_per_group as _ - } - /// - pub fn total_inodes_count(&self) -> usize { - self.superblock.inner.inodes_count as _ - } - /// - pub fn block_group_count(&self) -> Result<usize, Error> { - self.superblock - .inner - .block_group_count() - .map(|count| count as usize) - .map_err(|(a, b)| Error::BadBlockGroupCount { - by_blocks: a, - by_inodes: b, - }) - } - /// - pub fn total_block_count(&self) -> usize { - self.superblock.inner.blocks_count as _ - } - /// - pub fn free_block_count(&self) -> usize { - self.superblock.inner.free_blocks_count as _ - } - /// - pub fn block_size(&self) -> usize { - self.superblock.inner.block_size() - } - /// - pub fn log_block_size(&self) -> u32 { - self.superblock.inner.log_block_size + 10 - } - /// - pub fn sector_size(&self) -> usize { - S::SIZE - } - /// - pub fn log_sector_size(&self) -> u32 { - S::LOG_SIZE - } -} - -#[cfg(test)] -mod tests { - use std::cell::RefCell; - use std::fs::File; - - use sector::{Address, Size512}; - use volume::Volume; - - use super::Ext2; - - #[test] - fn file_len() { - let file = RefCell::new(File::open("ext2.img").unwrap()); - assert_eq!( - Address::<Size512>::from(2048_u64) - - Address::<Size512>::from(1024_u64), - Address::<Size512>::new(2, 0) - ); - assert_eq!( - unsafe { - file.slice_unchecked( - Address::<Size512>::from(1024_u64) - ..Address::<Size512>::from(2048_u64), - ) - .len() - }, - 1024 - ); - } - - #[test] - fn file() { - let file = RefCell::new(File::open("ext2.img").unwrap()); - let fs = Ext2::<Size512, _>::new(file); - - assert!( - fs.is_ok(), - "Err({:?})", - fs.err().unwrap_or_else(|| unreachable!()), - ); - - let fs = fs.unwrap(); - - let vers = fs.version(); - println!("version: {}.{}", vers.0, vers.1); - assert_eq!(128, fs.inode_size()); - } -} diff --git a/ext2-rs/src/fs/sync.rs b/ext2-rs/src/fs/sync.rs deleted file mode 100644 index bda8360..0000000 --- a/ext2-rs/src/fs/sync.rs +++ /dev/null @@ -1,905 +0,0 @@ -//! - -use crate::sys::inode::TypePerm; - -use { - super::Ext2, - alloc::{ - sync::Arc, - {string::String, vec::Vec}, - }, - core::{ - fmt::{self, Debug}, - iter::Iterator, - num::NonZeroU32, - }, - error::Error, - genfs::*, - sector::{Address, SectorSize}, - spin::{Mutex, MutexGuard}, - sys::inode::Inode as RawInode, - volume::Volume, -}; -/// DOCME: what is this? -pub struct Synced<T> { - inner: Arc<Mutex<T>>, -} - -impl<T> Synced<T> { - /// DOCME: what is this? - pub fn with_inner(inner: T) -> Synced<T> { - Synced { - inner: Arc::new(Mutex::new(inner)), - } - } - - /// DOCME: what is this? - pub fn inner<'a>(&'a self) -> MutexGuard<'a, T> { - self.inner.lock() - } -} - -impl<T> Clone for Synced<T> { - fn clone(&self) -> Self { - Synced { - inner: self.inner.clone(), - } - } -} - -impl<S: SectorSize, V: Volume<u8, S>> Synced<Ext2<S, V>> { - /// DOCME: what is this? - pub fn new(volume: V) -> Result<Synced<Ext2<S, V>>, Error> { - Ext2::new(volume).map(Synced::with_inner) - } - /// Get the root inode. - pub fn root_inode(&self) -> Inode<S, V> { - self.inode_nth(2).unwrap() - } - /// Get the inode at the given index. - pub fn inode_nth(&self, index: usize) -> Option<Inode<S, V>> { - self.inodes_nth(index).next() - } - /// DOCME: what is this? - pub fn inodes(&self) -> Inodes<S, V> { - self.inodes_nth(1) - } - /// DOCME: what is this? - pub fn inodes_nth(&self, index: usize) -> Inodes<S, V> { - assert!(index > 0, "inodes are 1-indexed"); - let inner = self.inner(); - Inodes { - fs: self.clone(), - log_block_size: inner.log_block_size(), - inode_size: inner.inode_size(), - inodes_per_group: inner.inodes_count(), - inodes_count: inner.total_inodes_count(), - index, - } - } - /// DOCME: what is this? - pub fn sector_size(&self) -> usize { - S::SIZE - } - /// DOCME: what is this? - pub fn log_sector_size(&self) -> u32 { - S::LOG_SIZE - } -} - -impl<S: SectorSize, V: Volume<u8, S>> Fs for Synced<Ext2<S, V>> { - type Path = [u8]; - type PathOwned = Vec<u8>; - type File = Inode<S, V>; - type Dir = Directory<S, V>; - type DirEntry = DirectoryEntry; - type Metadata = (); // TODO - type Permissions = (); // TODO - type Error = Error; - - fn open( - &self, - abs_path: &Self::Path, - _options: &OpenOptions<Self::Permissions>, - ) -> Result<Self::File, Self::Error> { - fn inner<'a, S, V, I>( - fs: &Synced<Ext2<S, V>>, - inode: Inode<S, V>, - mut path: I, - abs_path: &[u8], - ) -> Result<Inode<S, V>, Error> - where - S: SectorSize, - V: Volume<u8, S>, - I: Iterator<Item = &'a [u8]>, - { - let name = match path.next() { - Some(name) => name, - None => return Ok(inode), - }; - - let mut dir = - inode.directory().ok_or_else(|| Error::NotADirectory { - inode: inode.num, - name: String::from_utf8_lossy(abs_path).into_owned(), - })?; - - let entry = dir - .find(|entry| { - entry.is_err() || entry.as_ref().unwrap().name == name - }) - .ok_or_else(|| Error::NotFound { - name: String::from_utf8_lossy(abs_path).into_owned(), - })??; - - let inode = fs - .inode_nth(entry.inode) - .ok_or(Error::InodeNotFound { inode: inode.num })?; - - inner(fs, inode, path, abs_path) - } - - if abs_path.is_empty() || abs_path[0] != b'/' { - return Err(Error::NotAbsolute { - name: String::from_utf8_lossy(abs_path).into_owned(), - }); - } - - if abs_path == b"/" { - return Ok(self.root_inode()); - } - - let mut path = abs_path.split(|byte| *byte == b'/'); - path.next(); - let root = self.root_inode(); - - inner(self, root, path, abs_path) - } - - fn remove_file(&mut self, _path: &Self::Path) -> Result<(), Self::Error> { - unimplemented!() - } - - fn metadata( - &self, - _path: &Self::Path, - ) -> Result<Self::Metadata, Self::Error> { - unimplemented!() - } - - fn symlink_metadata( - &self, - _path: &Self::Path, - ) -> Result<Self::Metadata, Self::Error> { - unimplemented!() - } - - fn rename( - &mut self, - _from: &Self::Path, - _to: &Self::Path, - ) -> Result<(), Self::Error> { - unimplemented!() - } - - fn copy( - &mut self, - _from: &Self::Path, - _to: &Self::Path, - ) -> Result<u64, Self::Error> { - unimplemented!() - } - - fn hard_link( - &mut self, - _src: &Self::Path, - _dst: &Self::Path, - ) -> Result<(), Self::Error> { - unimplemented!() - } - - fn symlink( - &mut self, - _src: &Self::Path, - _dst: &Self::Path, - ) -> Result<(), Self::Error> { - unimplemented!() - } - - fn read_link( - &self, - _path: &Self::Path, - ) -> Result<Self::PathOwned, Self::Error> { - unimplemented!() - } - - fn canonicalize( - &self, - _path: &Self::Path, - ) -> Result<Self::PathOwned, Self::Error> { - unimplemented!() - } - - fn create_dir( - &mut self, - _path: &Self::Path, - _options: &DirOptions<Self::Permissions>, - ) -> Result<(), Self::Error> { - unimplemented!() - } - - fn remove_dir(&mut self, _path: &Self::Path) -> Result<(), Self::Error> { - unimplemented!() - } - - fn remove_dir_all( - &mut self, - _path: &Self::Path, - ) -> Result<(), Self::Error> { - unimplemented!() - } - - fn read_dir(&self, path: &Self::Path) -> Result<Self::Dir, Self::Error> { - let inode = self.open(path, OpenOptions::new().read(true))?; - inode.directory().ok_or(Error::NotADirectory { - inode: inode.num, - name: String::from_utf8_lossy(path).into_owned(), - }) - } - - fn set_permissions( - &mut self, - _path: &Self::Path, - _perm: Self::Permissions, - ) -> Result<(), Self::Error> { - unimplemented!() - } -} - -impl<S: SectorSize, V: Volume<u8, S>> Debug for Synced<Ext2<S, V>> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Synced<Ext2<{}>>", S::SIZE) - } -} - -#[derive(Debug, Clone)] -/// A collection of inodes. -pub struct Inodes<S: SectorSize, V: Volume<u8, S>> { - fs: Synced<Ext2<S, V>>, - log_block_size: u32, - inode_size: usize, - inodes_per_group: usize, - inodes_count: usize, - index: usize, -} - -impl<S: SectorSize, V: Volume<u8, S>> Iterator for Inodes<S, V> { - type Item = Inode<S, V>; - - fn next(&mut self) -> Option<Self::Item> { - if self.index < self.inodes_count { - let block_group = (self.index - 1) / self.inodes_per_group; - let index = (self.index - 1) % self.inodes_per_group; - self.index += 1; - - let fs = self.fs.inner(); - - let inodes_block = - fs.block_groups.inner[block_group].inode_table_block; - - let offset = Address::with_block_size( - inodes_block, - (index * self.inode_size) as i32, - self.log_block_size, - ); - let raw = unsafe { - RawInode::find_inode(&fs.volume, offset, self.inode_size).ok() - }; - raw.map(|(raw, offset)| { - Inode::new( - self.fs.clone(), - raw, - offset, - (self.index - 1) as u32, - ) - }) - } else { - None - } - } -} - -#[derive(Debug)] -/// A single inode in an ext2 filesystem. -pub struct Inode<S: SectorSize, V: Volume<u8, S>> { - fs: Synced<Ext2<S, V>>, - inner: RawInode, - addr: Address<S>, - num: u32, -} - -impl<S: SectorSize, V: Volume<u8, S>> Clone for Inode<S, V> { - fn clone(&self) -> Self { - Inode { - fs: self.fs.clone(), - inner: self.inner, - addr: self.addr, - num: self.num, - } - } -} - -impl<S: SectorSize, V: Volume<u8, S>> Inode<S, V> { - /// - pub fn new( - fs: Synced<Ext2<S, V>>, - inner: RawInode, - addr: Address<S>, - num: u32, - ) -> Inode<S, V> { - Inode { - fs, - inner, - addr, - num, - } - } - /// Read to the end of a buffer. - pub fn read_to_end(&self, buf: &mut Vec<u8>) -> Result<usize, Error> { - let total_size = self.size(); - let capacity = buf.capacity(); - if capacity < total_size { - buf.reserve_exact(total_size - capacity); - } - unsafe { - buf.set_len(total_size); - } - let size = self.read(&mut buf[..]); - size.map(|size| { - unsafe { - buf.set_len(size); - } - size - }) - .map_err(|err| { - unsafe { - buf.set_len(0); - } - err - }) - } - /// Return blocks on a sector - pub fn blocks(&self) -> InodeBlocks<S, V> { - InodeBlocks { - inode: self.clone(), - index: 0, - } - } - /// return a directory iterator - pub fn directory(&self) -> Option<Directory<S, V>> { - if self.is_dir() { - Some(Directory { - blocks: self.blocks(), - offset: 0, - buffer: None, - block_size: { - let fs = self.fs.inner(); - fs.block_size() - }, - }) - } else { - None - } - } - /// Determine if an inode is a directory - pub fn is_dir(&self) -> bool { - { self.inner.type_perm }.contains(TypePerm::DIRECTORY) - // self.inner.type_perm.contains(TypePerm::DIRECTORY) - } - /// - pub fn block(&self, index: usize) -> Option<NonZeroU32> { - self.try_block(index).ok().and_then(|block| block) - } - /// Try to get a block - pub fn try_block( - &self, - mut index: usize, - ) -> Result<Option<NonZeroU32>, Error> { - // number of blocks in direct table: 12 - // number of blocks in indirect table: block_size/4 - // why? - // - a block is n bytes long - // - a block address occupies 32 bits, or 4 bytes - // - thus, n/4 - // number of blocks in doubly table: (block_size/4)^2 - // why? - // - every entry in the doubly table points to another block - // - that's n/4 blocks, where n is the block size - // - every block contains n/4 block pointers - // - that's n/4 blocks with n/4 pointers each = (n/4)^2 - // number of blocks in triply table: (block_size/4)^3 - - fn block_index<S: SectorSize, V: Volume<u8, S>>( - volume: &V, - block: u32, - index: usize, - log_block_size: u32, - ) -> Result<Option<NonZeroU32>, Error> { - let offset = (index * 4) as i32; - let end = offset + 4; - let addr = Address::with_block_size(block, offset, log_block_size); - let end = Address::with_block_size(block, end, log_block_size); - let block = volume.slice(addr..end); - match block { - Ok(block) => unsafe { - Ok(NonZeroU32::new(block.dynamic_cast::<u32>().0)) - }, - Err(err) => Err(err.into()), - } - } - - let fs = self.fs.inner(); - - let bs4 = fs.block_size() / 4; - let log_block_size = fs.log_block_size(); - - if index < 12 { - return Ok(NonZeroU32::new(self.inner.direct_pointer[index])); - } - - index -= 12; - - if index < bs4 { - let block = self.inner.indirect_pointer; - return block_index(&fs.volume, block, index, log_block_size); - } - - index -= bs4; - - if index < bs4 * bs4 { - let indirect_index = index >> (log_block_size + 2); - let block = match block_index( - &fs.volume, - self.inner.doubly_indirect, - indirect_index, - log_block_size, - ) { - Ok(Some(block)) => block.get(), - Ok(None) => return Ok(None), - Err(err) => return Err(err), - }; - return block_index( - &fs.volume, - block, - index & (bs4 - 1), - log_block_size, - ); - } - - index -= bs4 * bs4; - - if index < bs4 * bs4 * bs4 { - let doubly_index = index >> (2 * log_block_size + 4); - let indirect = match block_index( - &fs.volume, - self.inner.triply_indirect, - doubly_index, - log_block_size, - ) { - Ok(Some(block)) => block.get(), - Ok(None) => return Ok(None), - Err(err) => return Err(err), - }; - let indirect_index = (index >> (log_block_size + 2)) & (bs4 - 1); - let block = match block_index( - &fs.volume, - indirect as u32, - indirect_index, - log_block_size, - ) { - Ok(Some(block)) => block.get(), - Ok(None) => return Ok(None), - Err(err) => return Err(err), - }; - return block_index( - &fs.volume, - block, - index & (bs4 - 1), - log_block_size, - ); - } - - Ok(None) - } - /// - pub fn in_use(&self) -> bool { - self.inner.hard_links > 0 - } - /// return the uid - pub fn uid(&self) -> u16 { - self.inner.uid - } - /// - pub fn sectors(&self) -> usize { - self.inner.sectors_count as usize - } - /// - pub fn size32(&self) -> u32 { - self.inner.size_low - } - /// - pub fn size64(&self) -> u64 { - self.inner.size_low as u64 | (self.inner.size_high as u64) << 32 - } - /// - #[cfg(target_pointer_width = "64")] - #[inline] - pub fn size(&self) -> usize { - self.size64() as usize - } - - #[cfg(target_pointer_width = "32")] - #[inline] - pub fn size(&self) -> usize { - self.size32() as usize - } - - /// ableOS: expose type_perm - pub fn type_perm(&self) -> TypePerm { - self.inner.type_perm - } -} - -impl<S: SectorSize, V: Volume<u8, S>> File for Inode<S, V> { - type Error = Error; - - fn read(&self, buf: &mut [u8]) -> Result<usize, Error> { - let total_size = self.size(); - let block_size = { - let fs = self.fs.inner(); - fs.block_size() - }; - let mut offset = 0; - - for block in self.blocks() { - match block { - Ok((data, _)) => { - let data_size = block_size - .min(total_size - offset) - .min(buf.len() - offset); - let end = offset + data_size; - buf[offset..end].copy_from_slice(&data[..data_size]); - offset += data_size; - } - Err(err) => return Err(err), - } - } - - Ok(offset) - } - - fn write(&mut self, _buf: &[u8]) -> Result<usize, Self::Error> { - unimplemented!() - } - - fn flush(&mut self) -> Result<(), Self::Error> { - unimplemented!() - } - - fn seek(&mut self, _pos: SeekFrom) -> Result<u64, Self::Error> { - unimplemented!() - } -} - -/// -#[derive(Debug, Clone)] -pub struct InodeBlocks<S: SectorSize, V: Volume<u8, S>> { - inode: Inode<S, V>, - index: usize, -} - -impl<S: SectorSize, V: Volume<u8, S>> Iterator for InodeBlocks<S, V> { - type Item = Result<(Vec<u8>, Address<S>), Error>; - - fn next(&mut self) -> Option<Self::Item> { - let block = self.inode.try_block(self.index); - let block = match block { - Ok(Some(ok)) => ok, - Ok(None) => return None, - Err(err) => return Some(Err(err)), - }; - - self.index += 1; - let fs = self.inode.fs.inner(); - - let block = block.get(); - let log_block_size = fs.log_block_size(); - let offset = Address::with_block_size(block, 0, log_block_size); - let end = Address::with_block_size(block + 1, 0, log_block_size); - - let slice = fs - .volume - .slice(offset..end) - .map(|slice| (slice.to_vec(), offset)) - .map_err(|err| err.into()); - Some(slice) - } -} - -#[derive(Debug, Clone)] -/// A directory structure -pub struct Directory<S: SectorSize, V: Volume<u8, S>> { - blocks: InodeBlocks<S, V>, - offset: usize, - buffer: Option<Vec<u8>>, - block_size: usize, -} - -impl<S: SectorSize, V: Volume<u8, S>> Dir<DirectoryEntry, Error> - for Directory<S, V> -{ -} - -impl<S: SectorSize, V: Volume<u8, S>> Iterator for Directory<S, V> { - type Item = Result<DirectoryEntry, Error>; - - fn next(&mut self) -> Option<Self::Item> { - if self.buffer.is_none() || self.offset >= self.block_size { - self.buffer = match self.blocks.next() { - None => return None, - Some(Ok((block, _))) => Some(block), - Some(Err(err)) => return Some(Err(err)), - }; - - self.offset = 0; - } - - let buffer = &self.buffer.as_ref().unwrap()[self.offset..]; - - let inode = buffer[0] as u32 - | (buffer[1] as u32) << 8 - | (buffer[2] as u32) << 16 - | (buffer[3] as u32) << 24; - if inode == 0 { - return None; - } - - let size = buffer[4] as u16 | (buffer[5] as u16) << 8; - let len = buffer[6]; - let ty = buffer[7]; - - let name = buffer[8..8 + len as usize].to_vec(); - - self.offset += size as usize; - - Some(Ok(DirectoryEntry { - name, - inode: inode as usize, - ty, - })) - } -} - -#[derive(Clone)] -/// A directory entry -pub struct DirectoryEntry { - /// The name of the entry - pub name: Vec<u8>, - /// The inode of the entry - pub inode: usize, - /// - pub ty: u8, -} - -impl DirEntry for DirectoryEntry { - type Path = [u8]; - type PathOwned = Vec<u8>; - type Metadata = (); // TODO - type FileType = u8; // TODO: enum FileType - type Error = Error; - - fn path(&self) -> Self::PathOwned { - unimplemented!() - } - - fn metadata(&self) -> Result<Self::Metadata, Self::Error> { - unimplemented!() - } - - fn file_type(&self) -> Result<Self::FileType, Self::Error> { - Ok(self.ty) - } - - fn file_name(&self) -> &Self::Path { - &self.name - } -} - -impl DirectoryEntry { - /// Turns a filename into a string for display - pub fn file_name_string(&self) -> String { - let mut filename = String::new(); - for ch in &self.name { - filename.push(*ch as char); - } - filename - } -} - -#[cfg(test)] -mod tests { - use std::cell::RefCell; - use std::fs::File; - - use genfs::{File as GenFile, Fs, OpenOptions}; - - use sector::{SectorSize, Size512}; - use volume::Volume; - - use super::{Ext2, Inode, Synced}; - - #[test] - fn file() { - let file = RefCell::new(File::open("ext2.img").unwrap()); - let fs = Synced::<Ext2<Size512, _>>::new(file); - - assert!( - fs.is_ok(), - "Err({:?})", - fs.err().unwrap_or_else(|| unreachable!()), - ); - - let fs = fs.unwrap(); - let inner = fs.inner(); - - let vers = inner.version(); - println!("version: {}.{}", vers.0, vers.1); - assert_eq!(128, inner.inode_size()); - } - - #[test] - fn inodes() { - let file = RefCell::new(File::open("ext2.img").unwrap()); - let fs = Synced::<Ext2<Size512, _>>::new(file); - - assert!( - fs.is_ok(), - "Err({:?})", - fs.err().unwrap_or_else(|| unreachable!()), - ); - - let fs = fs.unwrap(); - - let inodes = fs.inodes().filter(|inode| inode.in_use()); - for inode in inodes { - println!("{:?}", inode); - } - } - - #[test] - fn inode_blocks() { - use std::str; - let file = RefCell::new(File::open("ext2.img").unwrap()); - let fs = Synced::<Ext2<Size512, _>>::new(file).unwrap(); - - let inodes = fs.inodes().filter(|inode| { - inode.in_use() && inode.uid() == 1000 && inode.size() < 1024 - }); - for inode in inodes { - println!("{:?}", inode); - let size = inode.size(); - for block in inode.blocks() { - let (data, _) = block.unwrap(); - assert_eq!(data.len(), { - let fs = fs.inner(); - fs.block_size() - }); - println!("{:?}", &data[..size]); - let _ = str::from_utf8(&data[..size]) - .map(|string| println!("{}", string)); - } - } - } - - #[test] - fn read_inode() { - let file = RefCell::new(File::open("ext2.img").unwrap()); - let fs = Synced::<Ext2<Size512, _>>::new(file).unwrap(); - - let inodes = fs.inodes().filter(|inode| { - inode.in_use() && inode.uid() == 1000 && inode.size() < 1024 - }); - for inode in inodes { - let mut buf = Vec::with_capacity(inode.size()); - unsafe { - buf.set_len(inode.size()); - } - let size = inode.read(&mut buf[..]); - assert!(size.is_ok()); - let size = size.unwrap(); - assert_eq!(size, inode.size()); - unsafe { - buf.set_len(size); - } - } - } - - #[test] - fn read_big() { - let file = RefCell::new(File::open("ext2.img").unwrap()); - let fs = Synced::<Ext2<Size512, _>>::new(file).unwrap(); - - let inodes = fs.inodes().filter(|inode| { - inode.in_use() && inode.uid() == 1000 && inode.size() == 537600 - }); - for inode in inodes { - let mut buf = Vec::with_capacity(inode.size()); - unsafe { - buf.set_len(inode.size()); - } - let size = inode.read(&mut buf[..]); - assert!(size.is_ok()); - let size = size.unwrap(); - assert_eq!(size, inode.size()); - unsafe { - buf.set_len(size); - } - - for (i, &x) in buf.iter().enumerate() { - if i & 1 == 0 { - assert_eq!(x, b'u', "{}", i); - } else { - assert_eq!(x, b'\n', "{}", i); - } - } - } - } - - #[test] - fn walkdir() { - use std::str; - - fn walk<'vol, S: SectorSize, V: Volume<u8, S>>( - fs: &'vol Synced<Ext2<S, V>>, - inode: Inode<S, V>, - name: String, - ) { - inode.directory().map(|dir| { - for entry in dir { - assert!(entry.is_ok()); - let entry = entry.unwrap(); - let entry_name = str::from_utf8(&entry.name).unwrap_or("?"); - println!("{}/{} => {}", name, entry_name, entry.inode,); - if entry_name != "." && entry_name != ".." { - walk( - fs, - fs.inode_nth(entry.inode).unwrap(), - format!("{}/{}", name, entry_name), - ); - } - } - }); - } - - let file = RefCell::new(File::open("ext2.img").unwrap()); - let fs = Synced::<Ext2<Size512, _>>::new(file).unwrap(); - - let root = fs.root_inode(); - walk(&fs, root, String::new()); - } - - #[test] - fn find() { - use std::str; - let file = RefCell::new(File::open("ext2.img").unwrap()); - let fs = Synced::<Ext2<Size512, _>>::new(file).unwrap(); - - let found = fs.open(b"/home/funky/README.md", &OpenOptions::new()); - - assert!(found.is_ok()); - let inode = found.unwrap(); - let mut vec = Vec::new(); - assert!(inode.read_to_end(&mut vec).is_ok()); - println!("{}", str::from_utf8(&vec).unwrap()); - } -} diff --git a/ext2-rs/src/lib.rs b/ext2-rs/src/lib.rs deleted file mode 100644 index 506163a..0000000 --- a/ext2-rs/src/lib.rs +++ /dev/null @@ -1,36 +0,0 @@ -//! Ext2 crate for ableOS - -#![deny(missing_docs)] -#![feature(min_specialization, step_trait, associated_type_defaults)] -#![cfg_attr(all(not(test), feature = "no_std"), no_std)] - -extern crate alloc; - -#[macro_use] -extern crate bitflags; -extern crate genfs; -extern crate spin; - -#[cfg(any(test, not(feature = "no_std")))] -extern crate core; - -pub mod error; -pub mod fs; -pub mod sector; -pub mod sys; -pub mod volume; - -#[cfg(test)] -mod tests { - use sys::block_group::*; - use sys::inode::*; - use sys::superblock::*; - - #[test] - fn sizes() { - use std::mem::size_of; - assert_eq!(size_of::<Superblock>(), 1024); - assert_eq!(size_of::<BlockGroupDescriptor>(), 32); - assert_eq!(size_of::<Inode>(), 128); - } -} diff --git a/ext2-rs/src/sector.rs b/ext2-rs/src/sector.rs deleted file mode 100644 index f657e3a..0000000 --- a/ext2-rs/src/sector.rs +++ /dev/null @@ -1,242 +0,0 @@ -//! Sector data. - -use core::{ - fmt::{self, Debug, Display, LowerHex}, - iter::Step, - marker::PhantomData, - ops::{Add, Sub}, -}; -/// Size of a sector in bytes -pub trait SectorSize: Clone + Copy + PartialEq + PartialOrd + 'static { - /// DOCME: What is this? - const LOG_SIZE: u32; - /// DOCME: What is this? - const SIZE: usize = 1 << Self::LOG_SIZE; - /// DOCME: What is this? - const OFFSET_MASK: u32 = (Self::SIZE - 1) as u32; -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] -/// DOCME: What is this? -pub struct Size512; -impl SectorSize for Size512 { - const LOG_SIZE: u32 = 9; -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] -/// DOCME: What is this? -pub struct Size1024; -impl SectorSize for Size1024 { - const LOG_SIZE: u32 = 10; -} -/// DOCME: What is this? -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] -pub struct Size2048; -impl SectorSize for Size2048 { - const LOG_SIZE: u32 = 11; -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] -/// DOCME: What is this? -pub struct Size4096; -impl SectorSize for Size4096 { - const LOG_SIZE: u32 = 12; -} - -/// Address in a physical sector -#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] -pub struct Address<S: SectorSize> { - sector: u32, - offset: u32, - _phantom: PhantomData<S>, -} - -impl<S: SectorSize> Address<S> { - /// - pub unsafe fn new_unchecked(sector: u32, offset: u32) -> Address<S> { - assert!((offset as usize) < S::SIZE, "offset out of sector bounds"); - let _phantom = PhantomData; - Address { - sector, - offset, - _phantom, - } - } - /// - pub fn new(sector: u32, offset: i32) -> Address<S> { - let sector = (sector as i32 + (offset >> S::LOG_SIZE)) as u32; - let offset = offset.unsigned_abs() & S::OFFSET_MASK; - unsafe { Address::new_unchecked(sector, offset) } - } - /// - pub fn with_block_size( - block: u32, - offset: i32, - log_block_size: u32, - ) -> Address<S> { - let block = (block as i32 + (offset >> log_block_size)) as u32; - let offset = offset.unsigned_abs() & ((1 << log_block_size) - 1); - - let log_diff = log_block_size as i32 - S::LOG_SIZE as i32; - let top_offset = offset >> S::LOG_SIZE; - let offset = offset & ((1 << S::LOG_SIZE) - 1); - let sector = block << log_diff | top_offset; - unsafe { Address::new_unchecked(sector, offset) } - } - /// - pub fn into_index(&self) -> u64 { - ((self.sector as u64) << S::LOG_SIZE) + self.offset as u64 - } - /// Get the size of the sector - pub const fn sector_size(&self) -> usize { - S::SIZE - } - /// DOCME: What is this? - pub const fn log_sector_size(&self) -> u32 { - S::LOG_SIZE - } - /// Return the sector number - pub fn sector(&self) -> u32 { - self.sector - } - /// Return the offset in the sector - pub fn offset(&self) -> u32 { - self.offset - } -} - -impl<S: SectorSize> Step for Address<S> { - fn steps_between(start: &Self, end: &Self) -> Option<usize> { - if end.sector >= start.sector { - Some(end.sector as usize - start.sector as usize) - } else { - None - } - } - - /* - fn replace_one(&mut self) -> Self { - mem::replace(self, Address::new(1, 0)) - } - - fn replace_zero(&mut self) -> Self { - mem::replace(self, Address::new(0, 0)) - } - - fn add_one(&self) -> Self { - Address::new(self.sector + 1, 0) - } - - fn sub_one(&self) -> Self { - Address::new(self.sector - 1, 0) - } - - fn add_usize(&self, n: usize) -> Option<Self> { - self.sector - .checked_add(n as u32) - .map(|sector| Address::new(sector, 0)) - } - */ - - fn forward_checked(_start: Self, count: usize) -> Option<Self> { - todo!("forward_checked: count: {}", count); - } - - fn backward_checked(_start: Self, count: usize) -> Option<Self> { - todo!("backward_checked count: {}", count); - } -} - -impl<S: SectorSize> Display for Address<S> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}:{}", self.sector, self.offset) - } -} - -impl<S: SectorSize> LowerHex for Address<S> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:x}:{:x}", self.sector, self.offset) - } -} - -impl<S: SectorSize> From<u64> for Address<S> { - fn from(idx: u64) -> Address<S> { - let sector = idx >> S::LOG_SIZE; - let offset = idx & S::OFFSET_MASK as u64; - Address::new(sector as u32, offset as i32) - } -} - -impl<S: SectorSize> From<usize> for Address<S> { - fn from(idx: usize) -> Address<S> { - let sector = idx >> S::LOG_SIZE; - let offset = idx & S::OFFSET_MASK as usize; - Address::new(sector as u32, offset as i32) - } -} - -impl<S: SectorSize> Add for Address<S> { - type Output = Address<S>; - fn add(self, rhs: Address<S>) -> Address<S> { - Address::new( - self.sector + rhs.sector, - (self.offset + rhs.offset) as i32, - ) - } -} - -impl<S: SectorSize> Sub for Address<S> { - type Output = Address<S>; - fn sub(self, rhs: Address<S>) -> Address<S> { - Address::new( - self.sector - rhs.sector, - self.offset as i32 - rhs.offset as i32, - ) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn conv() { - assert_eq!(Address::<Size512>::new(0, 1024).into_index(), 1024); - assert_eq!(Address::<Size512>::from(1024_u64).into_index(), 1024); - assert_eq!( - Address::<Size512>::with_block_size(1, 256, 10).into_index(), - 1024 + 256 - ); - assert_eq!( - Address::<Size512>::with_block_size(2, 0, 10).into_index(), - 2048 - ); - assert_eq!( - Address::<Size512>::with_block_size(0, 1792, 10).into_index(), - 1792 - ); - } - - #[test] - fn arithmetic() { - assert_eq!( - Address::<Size512>::new(0, 512), - Address::<Size512>::new(1, 0), - ); - - assert_eq!( - Address::<Size512>::new(2, -256), - Address::<Size512>::new(1, 256), - ); - - let a = Address::<Size2048>::new(0, 1024); - let b = Address::<Size2048>::new(0, 1024); - assert_eq!(a + b, Address::<Size2048>::new(1, 0)); - assert_eq!((a + b).into_index(), 2048); - - let a = Address::<Size512>::new(0, 2048); - let b = Address::<Size512>::new(0, 256); - assert_eq!(a - b, Address::<Size512>::new(3, 256)); - assert_eq!((a - b).into_index(), 1792); - } -} diff --git a/ext2-rs/src/sys/block_group.rs b/ext2-rs/src/sys/block_group.rs deleted file mode 100644 index 90bf165..0000000 --- a/ext2-rs/src/sys/block_group.rs +++ /dev/null @@ -1,116 +0,0 @@ -//! - -use { - alloc::vec::Vec, - core::{fmt::Debug, mem}, - error::Error, - sector::{Address, SectorSize}, - volume::Volume, -}; - -/// The Block Group Descriptor Table contains a descriptor for each block group -/// within the file system. The number of block groups within the file system, -/// and correspondingly, the number of entries in the Block Group Descriptor -/// Table, is described above. Each descriptor contains information regarding -/// where important data structures for that group are located. -/// -/// The (`BlockGroupDescriptor`) table is located in the block immediately -/// following the Superblock. So if the block size (determined from a field in -/// the superblock) is 1024 bytes per block, the Block Group Descriptor Table -/// will begin at block 2. For any other block size, it will begin at block 1. -/// Remember that blocks are numbered starting at 0, and that block numbers -/// don't usually correspond to physical block addresses. -#[repr(C, packed)] -#[derive(Clone, Debug, Copy)] -pub struct BlockGroupDescriptor { - /// Block address of block usage bitmap - pub block_usage_addr: u32, - /// Block address of inode usage bitmap - pub inode_usage_addr: u32, - /// Starting block address of inode table - pub inode_table_block: u32, - /// Number of unallocated blocks in group - pub free_blocks_count: u16, - /// Number of unallocated inodes in group - pub free_inodes_count: u16, - /// Number of directories in group - pub dirs_count: u16, - #[doc(hidden)] - _reserved: [u8; 14], -} - -impl BlockGroupDescriptor { - /// Find a descriptor in a descriptor table - pub unsafe fn find_descriptor<S: SectorSize, V: Volume<u8, S>>( - haystack: &V, - offset: Address<S>, - ) -> Result<(BlockGroupDescriptor, Address<S>), Error> { - let end = - offset + Address::from(mem::size_of::<BlockGroupDescriptor>()); - if haystack.size() < end { - return Err(Error::AddressOutOfBounds { - sector: end.sector(), - offset: end.offset(), - size: end.sector_size(), - }); - } - - let descr = haystack - .slice_unchecked(offset..end) - .dynamic_cast::<BlockGroupDescriptor>(); - - Ok(descr) - } - /// find a descriptor table - pub unsafe fn find_descriptor_table<S: SectorSize, V: Volume<u8, S>>( - haystack: &V, - offset: Address<S>, - count: usize, - ) -> Result<(Vec<BlockGroupDescriptor>, Address<S>), Error> { - let end = offset - + Address::from(count * mem::size_of::<BlockGroupDescriptor>()); - if haystack.size() < end { - return Err(Error::AddressOutOfBounds { - sector: end.sector(), - offset: end.offset(), - size: end.sector_size(), - }); - } - - let mut vec = Vec::with_capacity(count); - for i in 0..count { - let offset = offset - + Address::from(i * mem::size_of::<BlockGroupDescriptor>()); - vec.push({ - BlockGroupDescriptor::find_descriptor(haystack, offset)?.0 - }); - } - - Ok((vec, offset)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use sector::{Address, Size512}; - - #[test] - fn find() { - let volume = vec![0_u8; 4096]; - let table = unsafe { - BlockGroupDescriptor::find_descriptor_table( - &volume, - Address::<Size512>::new(4, 0), - 8, - ) - }; - assert!( - table.is_ok(), - "Err({:?})", - table.err().unwrap_or_else(|| unreachable!()), - ); - let table = table.unwrap_or_else(|_| unreachable!()); - assert_eq!(table.0.len(), 8); - } -} diff --git a/ext2-rs/src/sys/inode.rs b/ext2-rs/src/sys/inode.rs deleted file mode 100644 index 0a129b6..0000000 --- a/ext2-rs/src/sys/inode.rs +++ /dev/null @@ -1,188 +0,0 @@ -//! -use { - core::{fmt::Debug, mem}, - error::Error, - sector::{Address, SectorSize}, - volume::Volume, -}; - -/// An inode is a structure on the disk that represents a file, directory, -/// symbolic link, etc. Inodes do not contain the data of the file / directory / -/// etc. that they represent. Instead, they link to the blocks that actually -/// contain the data. This lets the inodes themselves have a well-defined size -/// which lets them be placed in easily indexed arrays. Each block group has an -/// array of inodes it is responsible for, and conversely every inode within a -/// file system belongs to one of such tables (and one of such block groups). -#[repr(C, packed)] -#[derive(Clone, Debug, Copy)] -pub struct Inode { - /// Type and Permissions (see below) - pub type_perm: TypePerm, - /// User ID - pub uid: u16, - /// Lower 32 bits of size in bytes - pub size_low: u32, - /// Last Access Time (in POSIX time) - pub atime: u32, - /// Creation Time (in POSIX time) - pub ctime: u32, - /// Last Modification time (in POSIX time) - pub mtime: u32, - /// Deletion time (in POSIX time) - pub dtime: u32, - /// Group ID - pub gid: u16, - /// Count of hard links (directory entries) to this inode. When this - /// reaches 0, the data blocks are marked as unallocated. - pub hard_links: u16, - /// Count of disk sectors (not Ext2 blocks) in use by this inode, not - /// counting the actual inode structure nor directory entries linking - /// to the inode. - pub sectors_count: u32, - /// Flags - pub flags: Flags, - /// Operating System Specific value #1 - pub _os_specific_1: [u8; 4], - /// Direct block pointers - pub direct_pointer: [u32; 12], - /// Singly Indirect Block Pointer (Points to a block that is a list of - /// block pointers to data) - pub indirect_pointer: u32, - /// Doubly Indirect Block Pointer (Points to a block that is a list of - /// block pointers to Singly Indirect Blocks) - pub doubly_indirect: u32, - /// Triply Indirect Block Pointer (Points to a block that is a list of - /// block pointers to Doubly Indirect Blocks) - pub triply_indirect: u32, - /// Generation number (Primarily used for NFS) - pub gen_number: u32, - /// In Ext2 version 0, this field is reserved. In version >= 1, - /// Extended attribute block (File ACL). - pub ext_attribute_block: u32, - /// In Ext2 version 0, this field is reserved. In version >= 1, Upper - /// 32 bits of file size (if feature bit set) if it's a file, - /// Directory ACL if it's a directory - pub size_high: u32, - /// Block address of fragment - pub frag_block_addr: u32, - /// Operating System Specific Value #2 - pub _os_specific_2: [u8; 12], -} - -impl Inode { - /// Discover the inode location on the disk. - pub unsafe fn find_inode<S: SectorSize, V: Volume<u8, S>>( - haystack: &V, - offset: Address<S>, - size: usize, - ) -> Result<(Inode, Address<S>), Error> { - if size != mem::size_of::<Inode>() { - unimplemented!("inodes with a size != 128"); - } - - let end = offset + Address::from(size); - if haystack.size() < end { - return Err(Error::AddressOutOfBounds { - sector: end.sector(), - offset: end.offset(), - size: end.sector_size(), - }); - } - - let inode = haystack - .slice_unchecked(offset..end) - .dynamic_cast::<Inode>(); - - Ok(inode) - } -} - -bitflags! { - /// - // #[derive(Copy)] - pub struct TypePerm: u16 { - /// FIFO - const FIFO = 0x1000; - /// Character device - const CHAR_DEVICE = 0x2000; - /// Directory - const DIRECTORY = 0x4000; - /// Block device - const BLOCK_DEVICE = 0x6000; - /// Regular file - const FILE = 0x8000; - /// Symbolic link - const SYMLINK = 0xA000; - /// Unix socket - const SOCKET = 0xC000; - /// Other—execute permission - const O_EXEC = 0x001; - /// Other—write permission - const O_WRITE = 0x002; - /// Other—read permission - const O_READ = 0x004; - /// Group—execute permission - const G_EXEC = 0x008; - /// Group—write permission - const G_WRITE = 0x010; - /// Group—read permission - const G_READ = 0x020; - /// User—execute permission - const U_EXEC = 0x040; - /// User—write permission - const U_WRITE = 0x080; - /// User—read permission - const U_READ = 0x100; - /// Sticky Bit - const STICKY = 0x200; - /// Set group ID - const SET_GID = 0x400; - /// Set user ID - const SET_UID = 0x800; - } -} - -bitflags! { - /// Flags - pub struct Flags: u32 { - /// Secure deletion (not used) - const SECURE_DEL = 0x00000001; - /// Keep a copy of data when deleted (not used) - const KEEP_COPY = 0x00000002; - /// File compression (not used) - const COMPRESSION = 0x00000004; - /// Synchronous updates—new data is written immediately to disk - const SYNC_UPDATE = 0x00000008; - /// Immutable file (content cannot be changed) - const IMMUTABLE = 0x00000010; - /// Append only - const APPEND_ONLY = 0x00000020; - /// File is not included in 'dump' command - const NODUMP = 0x00000040; - /// Last accessed time should not updated - const DONT_ATIME = 0x00000080; - /// Hash indexed directory - const HASH_DIR = 0x00010000; - /// AFS directory - const AFS_DIR = 0x00020000; - /// Journal file data - const JOURNAL_DATA = 0x00040000; - } -} - -/// Unknown entry type -pub const UNKNOWN: u8 = 0; -/// FIFO entry type -pub const FIFO: u8 = 1; -/// Character device entry type -pub const CHAR_DEVICE: u8 = 2; -/// Directory entry type -pub const DIRECTORY: u8 = 3; -/// Block device entry type -pub const BLOCK_DEVICE: u8 = 4; -/// Regular file entry type -pub const FILE: u8 = 5; -/// Symbolic link entry type -pub const SYMLINK: u8 = 6; -/// Unix socket entry type -pub const SOCKET: u8 = 7; diff --git a/ext2-rs/src/sys/mod.rs b/ext2-rs/src/sys/mod.rs deleted file mode 100644 index 32ec8fb..0000000 --- a/ext2-rs/src/sys/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! - -pub mod block_group; -pub mod inode; -pub mod superblock; diff --git a/ext2-rs/src/sys/superblock.rs b/ext2-rs/src/sys/superblock.rs deleted file mode 100644 index d97952e..0000000 --- a/ext2-rs/src/sys/superblock.rs +++ /dev/null @@ -1,284 +0,0 @@ -//! Superblock information - -use { - core::{fmt::Debug, mem}, - error::Error, - sector::{Address, SectorSize}, - volume::Volume, -}; - -/// Ext2 signature (0xef53), used to help confirm the presence of Ext2 on a -/// volume -pub const EXT2_MAGIC: u16 = 0xef53; - -/// Filesystem is free of errors -pub const FS_CLEAN: u16 = 1; -/// Filesystem has errors -pub const FS_ERR: u16 = 2; - -/// Ignore errors -pub const ERR_IGNORE: u16 = 1; -/// Remount as read-only on error -pub const ERR_RONLY: u16 = 2; -/// Panic on error -pub const ERR_PANIC: u16 = 3; - -/// Creator OS is Linux -pub const OS_LINUX: u32 = 0; -/// Creator OS is Hurd -pub const OS_HURD: u32 = 1; -/// Creator OS is Masix -pub const OS_MASIX: u32 = 2; -/// Creator OS is FreeBSD -pub const OS_FREEBSD: u32 = 3; -/// Creator OS is a BSD4.4-Lite derivative -pub const OS_LITE: u32 = 4; - -/// The Superblock contains all information about the layout of the file system -/// and possibly contains other important information like what optional -/// features were used to create the file system. -/// -/// The Superblock is always located at byte 1024 from the beginning of the -/// volume and is exactly 1024 bytes in length. For example, if the disk uses -/// 512 byte sectors, the Superblock will begin at LBA 2 and will occupy all of -/// sector 2 and 3. -#[repr(C, packed)] -#[derive(Clone, Debug, Copy)] -pub struct Superblock { - // taken from https://wiki.osdev.org/Ext2 - /// Total number of inodes in file system - pub inodes_count: u32, - /// Total number of blocks in file system - pub blocks_count: u32, - /// Number of blocks reserved for superuser (see offset 80) - pub r_blocks_count: u32, - /// Total number of unallocated blocks - pub free_blocks_count: u32, - /// Total number of unallocated inodes - pub free_inodes_count: u32, - /// Block number of the block containing the superblock - pub first_data_block: u32, - /// log2 (block size) - 10. (In other words, the number to shift 1,024 - /// to the left by to obtain the block size) - pub log_block_size: u32, - /// log2 (fragment size) - 10. (In other words, the number to shift - /// 1,024 to the left by to obtain the fragment size) - pub log_frag_size: i32, - /// Number of blocks in each block group - pub blocks_per_group: u32, - /// Number of fragments in each block group - pub frags_per_group: u32, - /// Number of inodes in each block group - pub inodes_per_group: u32, - /// Last mount time (in POSIX time) - pub mtime: u32, - /// Last written time (in POSIX time) - pub wtime: u32, - /// Number of times the volume has been mounted since its last - /// consistency check (fsck) - pub mnt_count: u16, - /// Number of mounts allowed before a consistency check (fsck) must be - /// done - pub max_mnt_count: i16, - /// Ext2 signature (0xef53), used to help confirm the presence of Ext2 - /// on a volume - pub magic: u16, - /// File system state (see `FS_CLEAN` and `FS_ERR`) - pub state: u16, - /// What to do when an error is detected (see `ERR_IGNORE`, `ERR_RONLY` and - /// `ERR_PANIC`) - pub errors: u16, - /// Minor portion of version (combine with Major portion below to - /// construct full version field) - pub rev_minor: u16, - /// POSIX time of last consistency check (fsck) - pub lastcheck: u32, - /// Interval (in POSIX time) between forced consistency checks (fsck) - pub checkinterval: u32, - /// Operating system ID from which the filesystem on this volume was - /// created - pub creator_os: u32, - /// Major portion of version (combine with Minor portion above to - /// construct full version field) - pub rev_major: u32, - /// User ID that can use reserved blocks - pub block_uid: u16, - /// Group ID that can use reserved blocks - pub block_gid: u16, - - /// First non-reserved inode in file system. - pub first_inode: u32, - /// SectorSize of each inode structure in bytes. - pub inode_size: u16, - /// Block group that this superblock is part of (if backup copy) - pub block_group: u16, - /// Optional features present (features that are not required to read - /// or write, but usually result in a performance increase) - pub features_opt: FeaturesOptional, - /// Required features present (features that are required to be - /// supported to read or write) - pub features_req: FeaturesRequired, - /// Features that if not supported, the volume must be mounted - /// read-only) - pub features_ronly: FeaturesROnly, - /// File system ID (what is output by blkid) - pub fs_id: [u8; 16], - /// Volume name (C-style string: characters terminated by a 0 byte) - pub volume_name: [u8; 16], - /// Path volume was last mounted to (C-style string: characters - /// terminated by a 0 byte) - pub last_mnt_path: [u8; 64], - /// Compression algorithms used (see Required features above) - pub compression: u32, - /// Number of blocks to preallocate for files - pub prealloc_blocks_files: u8, - /// Number of blocks to preallocate for directories - pub prealloc_blocks_dirs: u8, - #[doc(hidden)] - _unused: [u8; 2], - /// Journal ID (same style as the File system ID above) - pub journal_id: [u8; 16], - /// Journal inode - pub journal_inode: u32, - /// Journal device - pub journal_dev: u32, - /// Head of orphan inode list - pub journal_orphan_head: u32, - #[doc(hidden)] - _reserved: [u8; 788], -} -impl Superblock { - /// Discover the location of the superblock in the given block device. - pub unsafe fn find<S: SectorSize, V: Volume<u8, S>>( - haystack: &V, - ) -> Result<(Superblock, Address<S>), Error> { - let offset = Address::from(1024_usize); - let end = offset + Address::from(mem::size_of::<Superblock>()); - if haystack.size() < end { - return Err(Error::AddressOutOfBounds { - sector: end.sector(), - offset: end.offset(), - size: end.sector_size(), - }); - } - - let superblock = { - haystack - .slice_unchecked(offset..end) - .dynamic_cast::<Superblock>() - }; - - if superblock.0.magic != EXT2_MAGIC { - Err(Error::BadMagic { - magic: superblock.0.magic, - }) - } else { - Ok(superblock) - } - } - - #[inline] - /// Return the block size - pub fn block_size(&self) -> usize { - 1024 << self.log_block_size - } - - #[inline] - /// Return the fragment size - pub fn frag_size(&self) -> usize { - 1024 << self.log_frag_size - } - /// Return the number of blocks per group - pub fn block_group_count(&self) -> Result<u32, (u32, u32)> { - let blocks_mod = self.blocks_count % self.blocks_per_group; - let inodes_mod = self.inodes_count % self.inodes_per_group; - let blocks_inc = if blocks_mod == 0 { 0 } else { 1 }; - let inodes_inc = if inodes_mod == 0 { 0 } else { 1 }; - let by_blocks = self.blocks_count / self.blocks_per_group + blocks_inc; - let by_inodes = self.inodes_count / self.inodes_per_group + inodes_inc; - if by_blocks == by_inodes { - Ok(by_blocks) - } else { - Err((by_blocks, by_inodes)) - } - } -} - -bitflags! { - /// Optional features - pub struct FeaturesOptional: u32 { - /// Preallocate some number of (contiguous?) blocks (see - /// `Superblock::prealloc_blocks_dirs`) to a directory when creating a new one - const PREALLOCATE = 0x0001; - /// AFS server inodes exist - const AFS = 0x0002; - /// File system has a journal (Ext3) - const JOURNAL = 0x0004; - /// Inodes have extended attributes - const EXTENDED_INODE = 0x0008; - /// File system can resize itself for larger partitions - const SELF_RESIZE = 0x0010; - /// Directories use hash index - const HASH_INDEX = 0x0020; - } -} - -bitflags! { - /// Required features. If these are not supported; can't mount - pub struct FeaturesRequired: u32 { - /// Compression is used - const REQ_COMPRESSION = 0x0001; - /// Directory entries contain a type field - const REQ_DIRECTORY_TYPE = 0x0002; - /// File system needs to replay its journal - const REQ_REPLAY_JOURNAL = 0x0004; - /// File system uses a journal device - const REQ_JOURNAL_DEVICE = 0x0008; - } -} - -bitflags! { - /// ROnly features. If these are not supported; remount as read-only - pub struct FeaturesROnly: u32 { - /// Sparse superblocks and group descriptor tables - const RONLY_SPARSE = 0x0001; - /// File system uses a 64-bit file size - const RONLY_FILE_SIZE_64 = 0x0002; - /// Directory contents are stored in the form of a Binary Tree - const RONLY_BTREE_DIRECTORY = 0x0004; - } -} - -#[cfg(test)] -mod tests { - use super::*; - use sector::Size512; - - #[test] - fn find() { - let mut volume = vec![0_u8; 4096]; - // magic - volume[1024 + 56] = EXT2_MAGIC as u8; - volume[1024 + 57] = (EXT2_MAGIC >> 8) as u8; - let superblock = unsafe { Superblock::find::<Size512, _>(&volume) }; - assert!( - superblock.is_ok(), - "Err({:?})", - superblock.err().unwrap_or_else(|| unreachable!()), - ); - } - - #[test] - fn superblock() { - use std::cell::RefCell; - use std::fs::File; - - let file = RefCell::new(File::open("ext2.img").unwrap()); - let superblock = unsafe { Superblock::find::<Size512, _>(&file) }; - assert!( - superblock.is_ok(), - "Err({:?})", - superblock.err().unwrap_or_else(|| unreachable!()), - ); - } -} diff --git a/ext2-rs/src/volume/mod.rs b/ext2-rs/src/volume/mod.rs deleted file mode 100644 index d3d23b6..0000000 --- a/ext2-rs/src/volume/mod.rs +++ /dev/null @@ -1,371 +0,0 @@ -#![allow(missing_docs)] -use { - alloc::{ - borrow::{Cow, ToOwned}, - boxed::Box, - vec::Vec, - }, - core::{ - mem, - ops::{Deref, DerefMut, Range}, - slice, - }, - error::Error, - sector::{Address, SectorSize}, -}; - -pub mod size; -use self::size::Size; - -pub trait Volume<T: Clone, S: SectorSize> { - type Error: Into<Error>; - - fn size(&self) -> Size<S>; - fn commit( - &mut self, - slice: Option<VolumeCommit<T, S>>, - ) -> Result<(), Self::Error>; - unsafe fn slice_unchecked<'a>( - &'a self, - range: Range<Address<S>>, - ) -> VolumeSlice<'a, T, S>; - - fn slice<'a>( - &'a self, - range: Range<Address<S>>, - ) -> Result<VolumeSlice<'a, T, S>, Self::Error>; -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct VolumeSlice<'a, T: 'a + Clone, S: SectorSize> { - inner: Cow<'a, [T]>, - index: Address<S>, -} - -impl<T: Clone, S: SectorSize> VolumeSlice<'static, T, S> { - pub fn with_static(inner: &'static [T]) -> VolumeSlice<'static, T, S> { - VolumeSlice { - inner: Cow::Borrowed(inner), - index: Address::new(0, 0), - } - } - - pub fn new_owned( - inner: <[T] as ToOwned>::Owned, - index: Address<S>, - ) -> VolumeSlice<'static, T, S> { - VolumeSlice { - inner: Cow::Owned(inner), - index, - } - } -} - -impl<'a, T: Clone, S: SectorSize> VolumeSlice<'a, T, S> { - pub fn new(inner: &'a [T], index: Address<S>) -> VolumeSlice<'a, T, S> { - VolumeSlice { - inner: Cow::Borrowed(inner), - index, - } - } - - pub fn is_mutated(&self) -> bool { - match self.inner { - Cow::Borrowed(_) => false, - Cow::Owned(_) => true, - } - } - - pub fn address(&self) -> Address<S> { - self.index - } -} - -impl<'a, S: SectorSize> VolumeSlice<'a, u8, S> { - pub unsafe fn dynamic_cast<T: Copy>(&self) -> (T, Address<S>) { - assert!(self.inner.len() >= mem::size_of::<T>()); - let index = self.index; - let cast = self.inner.as_ptr().cast::<T>().read_unaligned(); - - // mem::transmute_copy(self.inner.as_ptr().as_ref().unwrap()); - (cast, index) - } - - pub fn from_cast<T: Copy>( - cast: &'a T, - index: Address<S>, - ) -> VolumeSlice<'a, u8, S> { - let len = mem::size_of::<T>(); - let ptr = cast as *const T as *const u8; - let slice = unsafe { slice::from_raw_parts(ptr, len) }; - VolumeSlice::new(slice, index) - } -} - -impl<'a, T: Clone, S: SectorSize> VolumeSlice<'a, T, S> { - pub fn commit(self) -> Option<VolumeCommit<T, S>> { - if self.is_mutated() { - Some(VolumeCommit::new(self.inner.into_owned(), self.index)) - } else { - None - } - } -} - -impl<'a, T: Clone, S: SectorSize> AsRef<[T]> for VolumeSlice<'a, T, S> { - fn as_ref(&self) -> &[T] { - self.inner.as_ref() - } -} - -impl<'a, T: Clone, S: SectorSize> AsMut<[T]> for VolumeSlice<'a, T, S> { - fn as_mut(&mut self) -> &mut [T] { - self.inner.to_mut().as_mut() - } -} - -impl<'a, T: Clone, S: SectorSize> Deref for VolumeSlice<'a, T, S> { - type Target = [T]; - - fn deref(&self) -> &Self::Target { - self.as_ref() - } -} - -impl<'a, T: Clone, S: SectorSize> DerefMut for VolumeSlice<'a, T, S> { - fn deref_mut(&mut self) -> &mut Self::Target { - self.as_mut() - } -} - -pub struct VolumeCommit<T, S: SectorSize> { - inner: Vec<T>, - index: Address<S>, -} - -impl<T: Clone, S: SectorSize> VolumeCommit<T, S> { - pub fn with_vec(inner: Vec<T>) -> VolumeCommit<T, S> { - VolumeCommit { - inner, - index: Address::new(0, 0), - } - } -} - -impl<T: Clone, S: SectorSize> VolumeCommit<T, S> { - pub fn new(inner: Vec<T>, index: Address<S>) -> VolumeCommit<T, S> { - VolumeCommit { inner, index } - } - - pub fn into_inner(self) -> Vec<T> { - self.inner - } - - pub fn address(&self) -> Address<S> { - self.index - } -} - -impl<T: Clone, S: SectorSize> AsRef<[T]> for VolumeCommit<T, S> { - fn as_ref(&self) -> &[T] { - self.inner.as_ref() - } -} - -impl<T: Clone, S: SectorSize> AsMut<[T]> for VolumeCommit<T, S> { - fn as_mut(&mut self) -> &mut [T] { - self.inner.as_mut() - } -} - -impl<T: Clone, S: SectorSize> Deref for VolumeCommit<T, S> { - type Target = [T]; - - fn deref(&self) -> &Self::Target { - self.as_ref() - } -} - -impl<T: Clone, S: SectorSize> DerefMut for VolumeCommit<T, S> { - fn deref_mut(&mut self) -> &mut Self::Target { - self.as_mut() - } -} - -macro_rules! impl_slice { - (@inner $volume:ty $( , $lt:lifetime )* ) => { - impl<$( $lt, )* T: Clone, S: SectorSize> Volume<T, S> - for $volume - { - type Error = Error; - - fn size(&self) -> Size<S> { - Size::Bounded( - Address::from(<Self as AsRef<[T]>>::as_ref(self).len()) - ) - } - - fn commit( - &mut self, - slice: Option<VolumeCommit<T, S>>, - ) -> Result<(), Self::Error> { - slice.map(|slice| { - let index = slice.address().into_index() as usize; - let end = index + slice.as_ref().len(); - // XXX: it would be much better to drop the contents of dst - // and move the contents of slice instead of cloning - let dst = - &mut <Self as AsMut<[T]>>::as_mut(self)[index..end]; - dst.clone_from_slice(slice.as_ref()); - }); - Ok(()) - } - - unsafe fn slice_unchecked<'a>( - &'a self, - range: Range<Address<S>>, - ) -> VolumeSlice<'a, T, S> { - let index = range.start; - let range = range.start.into_index() as usize - ..range.end.into_index() as usize; - VolumeSlice::new( - <Self as AsRef<[T]>>::as_ref(self).get_unchecked(range), - index, - ) - } - - fn slice<'a>( - &'a self, - range: Range<Address<S>>, - ) -> Result<VolumeSlice<'a, T, S>, Self::Error> { - if self.size() >= range.end { - unsafe { Ok(self.slice_unchecked(range)) } - } else { - Err(Error::AddressOutOfBounds { - sector: range.end.sector(), - offset: range.end.offset(), - size: range.end.sector_size() - }) - } - } - } - }; - ($volume:ty) => { - impl_slice!(@inner $volume); - }; - ($volume:ty $( , $lt:lifetime )* ) => { - impl_slice!(@inner $volume $( , $lt )* ); - }; -} - -impl_slice!(&'b mut [T], 'b); -impl_slice!(Vec<T>); -impl_slice!(Box<[T]>); - -#[cfg(any(test, not(feature = "no_std")))] -mod file { - use std::cell::RefCell; - use std::fs::File; - use std::io::{self, Read, Seek, SeekFrom, Write}; - use std::ops::Range; - - use sector::{Address, SectorSize}; - - use super::size::Size; - use super::{Volume, VolumeCommit, VolumeSlice}; - - impl<S: SectorSize> Volume<u8, S> for RefCell<File> { - type Error = io::Error; - - fn size(&self) -> Size<S> { - Size::Bounded( - self.borrow() - .metadata() - .map(|data| Address::from(data.len())) - .unwrap_or(Address::new(0, 0)), - ) - } - - fn commit( - &mut self, - slice: Option<VolumeCommit<u8, S>>, - ) -> Result<(), Self::Error> { - slice - .map(|slice| { - let index = slice.address(); - let mut refmut = self.borrow_mut(); - refmut - .seek(SeekFrom::Start(index.into_index())) - .and_then(|_| refmut.write(slice.as_ref())) - .map(|_| ()) - }) - .unwrap_or(Ok(())) - } - - unsafe fn slice_unchecked<'a>( - &'a self, - range: Range<Address<S>>, - ) -> VolumeSlice<'a, u8, S> { - let index = range.start; - let len = range.end - range.start; - let mut vec = Vec::with_capacity(len.into_index() as usize); - vec.set_len(len.into_index() as usize); - let mut refmut = self.borrow_mut(); - refmut - .seek(SeekFrom::Start(index.into_index())) - .and_then(|_| refmut.read_exact(&mut vec[..])) - .unwrap_or_else(|err| { - panic!("could't read from File Volume: {:?}", err) - }); - VolumeSlice::new_owned(vec, index) - } - - fn slice<'a>( - &'a self, - range: Range<Address<S>>, - ) -> Result<VolumeSlice<'a, u8, S>, Self::Error> { - let index = range.start; - let mut vec = Vec::with_capacity( - (range.end - range.start).into_index() as usize, - ); - unsafe { - vec.set_len((range.end - range.start).into_index() as usize); - } - let mut refmut = self.borrow_mut(); - refmut - .seek(SeekFrom::Start(index.into_index())) - .and_then(|_| refmut.read_exact(&mut vec[..])) - .map(move |_| VolumeSlice::new_owned(vec, index)) - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use sector::{Address, Size512}; - - #[test] - fn volume() { - let mut volume = vec![0; 1024]; - let commit = { - let mut slice = volume - .slice( - Address::<Size512>::from(256_u64) - ..Address::<Size512>::from(512_u64), - ) - .unwrap(); - slice.iter_mut().for_each(|x| *x = 1); - slice.commit() - }; - assert!(volume.commit(commit).is_ok()); - - for (i, &x) in volume.iter().enumerate() { - if i < 256 || i >= 512 { - assert_eq!(x, 0); - } else { - assert_eq!(x, 1); - } - } - } -} diff --git a/ext2-rs/src/volume/size.rs b/ext2-rs/src/volume/size.rs deleted file mode 100644 index b8b5b26..0000000 --- a/ext2-rs/src/volume/size.rs +++ /dev/null @@ -1,115 +0,0 @@ -//! - -use { - core::{ - cmp::Ordering, - fmt::{self, Display}, - }, - sector::{Address, SectorSize}, -}; - -#[derive(Clone, Copy, Debug, Hash)] -/// A size -pub enum Size<S: SectorSize> { - /// An unbounded size - Unbounded, - /// A bounded size - Bounded(Address<S>), -} - -impl<S: SectorSize> Size<S> { - /// Try to get the length of the sector - pub fn try_len(&self) -> Option<Address<S>> { - match *self { - Size::Unbounded => None, - Size::Bounded(n) => Some(n), - } - } - /// Get the length of the sector unsafely - /// - /// # Safety - /// - /// This function is unsafe because it does not check that the size is - /// bounded. - pub unsafe fn len(&self) -> Address<S> { - match *self { - Size::Unbounded => panic!( - "attempt to convert `Size::Unbounded` to a concrete length" - ), - Size::Bounded(n) => n, - } - } -} - -impl<S: SectorSize> Size<S> { - /// Check if the size is unbounded - pub fn is_bounded(&self) -> bool { - match *self { - Size::Unbounded => false, - Size::Bounded(_) => true, - } - } -} - -impl<S: SectorSize> Display for Size<S> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Size::Unbounded => write!(f, "Unbounded"), - Size::Bounded(n) => write!(f, "Bounded({})", n), - } - } -} - -impl<S: SectorSize> PartialEq for Size<S> { - fn eq(&self, rhs: &Self) -> bool { - match (self, rhs) { - (&Size::Unbounded, _) => false, - (_, &Size::Unbounded) => false, - (&Size::Bounded(ref a), &Size::Bounded(ref b)) => a.eq(b), - } - } - - fn ne(&self, rhs: &Self) -> bool { - match (self, rhs) { - (&Size::Unbounded, _) => false, - (_, &Size::Unbounded) => false, - (&Size::Bounded(ref a), &Size::Bounded(ref b)) => a.ne(b), - } - } -} - -impl<S: SectorSize> PartialEq<Address<S>> for Size<S> { - fn eq(&self, rhs: &Address<S>) -> bool { - match *self { - Size::Unbounded => false, - Size::Bounded(ref n) => n.eq(rhs), - } - } - - fn ne(&self, rhs: &Address<S>) -> bool { - match *self { - Size::Unbounded => false, - Size::Bounded(ref n) => n.eq(rhs), - } - } -} - -impl<S: SectorSize> PartialOrd for Size<S> { - fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> { - match (self, rhs) { - (&Size::Unbounded, &Size::Unbounded) => None, - (&Size::Unbounded, _) => Some(Ordering::Greater), - (_, &Size::Unbounded) => Some(Ordering::Less), - (&Size::Bounded(ref a), &Size::Bounded(ref b)) => a.partial_cmp(b), - } - } -} - -impl<S: SectorSize> PartialOrd<Address<S>> for Size<S> { - fn partial_cmp(&self, rhs: &Address<S>) -> Option<Ordering> { - match *self { - Size::Unbounded => Some(Ordering::Greater), - Size::Bounded(ref n) => n.partial_cmp(rhs), - } - } -} diff --git a/facepalm/Cargo.toml b/facepalm/Cargo.toml deleted file mode 100644 index 00a78e6..0000000 --- a/facepalm/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "facepalm" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -log = "0.4.0" \ No newline at end of file diff --git a/facepalm/readme.md b/facepalm/readme.md deleted file mode 100644 index 172c720..0000000 --- a/facepalm/readme.md +++ /dev/null @@ -1 +0,0 @@ -Facepalm is the general purpose debugger bundled with ableOS \ No newline at end of file diff --git a/facepalm/src/lib.rs b/facepalm/src/lib.rs deleted file mode 100644 index 1d140a1..0000000 --- a/facepalm/src/lib.rs +++ /dev/null @@ -1,19 +0,0 @@ -#![no_std] - -use log::*; - -pub const VERSION: &str = env!("CARGO_PKG_VERSION"); - -#[cfg(debug_assertions)] -pub const RELEASE_TYPE: &str = "debug"; - -#[cfg(not(debug_assertions))] -pub const RELEASE_TYPE: &str = "release"; - -pub fn start_facepalm() { - info!("facepalm 🤦 launched!"); - info!("facepalm 🤦 version: {}", VERSION); - info!("facepalm 🤦 {} mode", RELEASE_TYPE); - - // Drop into a debug shell -} diff --git a/kernel/.cargo/config.toml b/kernel/.cargo/config.toml index 0277493..5e82bd2 100644 --- a/kernel/.cargo/config.toml +++ b/kernel/.cargo/config.toml @@ -1,2 +1,9 @@ +[unstable] +build-std = ["core", "compiler_builtins", "alloc"] +build-std-features = ["compiler-builtins-mem"] + [build] -target = "./json_targets/x86_64-ableos.json" +target = "./targets/x86_64-ableos.json" + +[target.'cfg(target_arch = "x86_64")'] +rustflags = ["-C", "target-feature=+rdrand"] diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 7d56e3d..1c23509 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -1,18 +1,41 @@ [package] edition = "2021" name = "kernel" -version = "0.1.2" +version = "0.2.0" [dependencies] -linked_list_allocator = "0.9" -log = "0.4.14" -slab = { version = "0.4", default-features = false } -spin = "0.9" +error-stack = { version = "0.3", default-features = false} +log = "0.4" +spin = "0.9" +uart_16550 = "0.2" +slab = { version = "0.4", default-features = false } +versioning = { git = "https://git.ablecorp.us/able/aos_userland" } [dependencies.crossbeam-queue] version = "0.3" default-features = false features = ["alloc"] -[dependencies.versioning] -git = "https://git.ablecorp.us/able/aos_userland" +[dependencies.derive_more] +version = "0.99" +default-features = false +features = [ + "add", + "add_assign", + "constructor", + "display", + "from", + "into", + "mul", + "mul_assign", + "not", + "sum", +] + +[target.'cfg(target_arch = "x86_64")'.dependencies] +limine = { version = "0.1", git = "https://github.com/limine-bootloader/limine-rs" } +x86_64 = "0.14" +x2apic = "0.4" + +[target.'cfg(target_arch = "riscv64")'.dependencies] +sbi = "0.2.0" diff --git a/kernel/data/⑨. バカ b/kernel/data/⑨. バカ new file mode 100644 index 0000000..c9058b9 --- /dev/null +++ b/kernel/data/⑨. バカ @@ -0,0 +1,33 @@ + + .//// *(#### + (####((/, (########, + (##%##(###(( ,(#########%# + #%%%%###(###((. *((####%%&%%%%# + .#####%%%%%####((. *(####%&&&&&%%%%# + #(((((((##%%&&%#((/ /#(##%&&%########## + /######%%%%%%%(..........(#%%%%%%#####%%# + ,#%%%%%%#/...... ..............,&&&%%###. + ,%%#(#(...........................(#&&%%# + .###%...............................%%#(#. + #%&.................................%# + ,%&&*.................................&&%( + %%#//........./............*/..,......&&&%# + .......,..............*,*.,,,,,,. + ......./....,.........*,,,,.,,,,,, + ,...../..(###%,.....&*&%###/..,.,,. + ,,..../%(((#(,.....,%%%%###,..,..,. + .,,*.../..,#,.........,(&(,,**.,,,,, + ,/((..,*..........,,.,,,,,**.,##(( + /(((%%%,,,,,.,,,,,,,,,,,#/##(,(/ + .***..(,.#%%%&&#/%,,(%*,,**# + **,...,(#%%%%&#%%%#%%%%,,.,,***. + .....,*,*#%%%%%###%##%%%&,,*,,.... + ......,*/. (############%%%&&&&#*,,.... + ...,*,..,(((((((((((#((((((((((((&&&#*, + ,##///////(((((((((((((#///#///(##/. + /*/**//... ...**(((((((,. .,*...... + ....... ......,,/*,. ........... + ,..,,,,...... .. .... ,,....... ..,,, + ........,.,.,*//////*,......,. + ...,,,, ,,,,,, + diff --git a/kernel/lds/riscv64-virt.ld b/kernel/lds/riscv64-virt.ld new file mode 100644 index 0000000..bec4f7b --- /dev/null +++ b/kernel/lds/riscv64-virt.ld @@ -0,0 +1,66 @@ +OUTPUT_ARCH(riscv) +ENTRY(_start) +START_ADDRESS = 0x80200000; + +SECTIONS { + . = START_ADDRESS; + + .text : { + PROVIDE(_text_start = .); + *(.text.entry) + + . = ALIGN(4K); + + *(.text .text.*) + PROVIDE(_text_end = .); + } + + . = ALIGN(4K); + + .rodata : { + PROVIDE(_rodata_start = .); + *(.rodata .rodata.*) + PROVIDE(_rodata_end = .); + } + + . = ALIGN(4K); + + .data : { + PROVIDE(_data_start = .); + *(.data .data.*) + PROVIDE(_data_end = .); + } + + . = ALIGN(4K); + + .sdata : { + PROVIDE(_sdata_start = .); + *(.sdata) + *(.sdata.*) + *(.srodata.*) + *(.gnu.linkonce.s.*) + PROVIDE(_sdata_end = .); + } + + . = ALIGN(4K); + + .bss : { + PROVIDE(_bss_start = .); + *(.sbss*) + *(.bss.stack) + *(.bss .bss.*) + PROVIDE(_initial_kernel_heap_start = .); + PROVIDE(_initial_kernel_heap_size = 1024 * 1024); + . += _initial_kernel_heap_size; + PROVIDE(_bss_end = .); + } + + /* FIXME: Currently this has to be aligned to PAGE_SIZE << MAX_ORDER */ + PROVIDE(_usable_memory_start = ALIGN(4M)); + PROVIDE(_usable_memory_size = 0x88000000 - _usable_memory_start); + + /DISCARD/ : { + *(.comment) + *(.eh_frame) + } +} diff --git a/kernel/lds/x86_64.ld b/kernel/lds/x86_64.ld new file mode 100644 index 0000000..e430d28 --- /dev/null +++ b/kernel/lds/x86_64.ld @@ -0,0 +1,53 @@ +/* Tell the linker that we want an x86_64 ELF64 output file */ +OUTPUT_FORMAT(elf64-x86-64) +OUTPUT_ARCH(i386:x86-64) + +ENTRY(_kernel_start) + +/* Define the program headers we want so the bootloader gives us the right */ +/* MMU permissions */ +PHDRS +{ + null PT_NULL FLAGS(0) ; /* Null segment */ + text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */ + rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */ + data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */ +} + +SECTIONS +{ + /* We wanna be placed in the topmost 2GiB of the address space, for optimisations */ + /* and because that is what the Limine spec mandates. */ + /* Any address in this region will do, but often 0xffffffff80000000 is chosen as */ + /* that is the beginning of the region. */ + . = 0xffffffff80000000; + + .text : { + *(.text .text.*) + } :text + + /* Align .rodata to page boundary */ + . = ALIGN(4K); + + .rodata : { + *(.rodata .rodata.*) + } :rodata + + /* Align .data to page boundary */ + . = ALIGN(4K); + + .data : { + *(.data .data.*) + } :data + + .bss : { + *(COMMON) + *(.bss .bss.*) + + /* Align initial kernel heap to page boundary */ + . = ALIGN(4K); + PROVIDE(_initial_kernel_heap_start = .); + PROVIDE(_initial_kernel_heap_size = 1024 * 1024); + . += _initial_kernel_heap_size; + } :data +} diff --git a/kernel/src/allocator.rs b/kernel/src/allocator.rs index 3c177d4..e3985c5 100644 --- a/kernel/src/allocator.rs +++ b/kernel/src/allocator.rs @@ -1,24 +1,329 @@ //! Memory allocator +/* + * This file incorporates work covered by the following license notice: + * + * Copyright (c) 2020, the SerenityOS developers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ -use linked_list_allocator::LockedHeap; +use core::{ + alloc::{GlobalAlloc, Layout}, + mem, + ptr::{self, NonNull}, +}; -/// -pub const HEAP_START: usize = 0x_4444_4444_0000; +use spin::Mutex; -/// -pub const HEAP_MULTIPLIER: usize = 100000; +struct Allocator(Mutex<Option<Heap>>); -/// -pub const HEAP_BASE: usize = 100; +unsafe impl GlobalAlloc for Allocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + let mut lock = self.0.lock(); + let allocator = lock.as_mut().expect("heap allocator should be initialized"); -/// -pub const HEAP_SIZE: usize = HEAP_BASE * HEAP_MULTIPLIER; + match allocator.allocate(layout.size(), layout.align()) { + Some(ptr) => ptr.as_ptr(), + None => ptr::null_mut(), + } + } + + unsafe fn dealloc(&self, ptr: *mut u8, _: Layout) { + let mut lock = self.0.lock(); + let allocator = lock.as_mut().expect("heap allocator should be initialized"); + allocator.deallocate(ptr); + } +} -/// Global allocator #[global_allocator] -pub static ALLOCATOR: LockedHeap = LockedHeap::empty(); +static ALLOCATOR: Allocator = Allocator(Mutex::new(None)); + +// FIXME: umm is `memory` VirtualAddress or PhysicalAddress? both? +pub fn init(memory: *mut u8, memory_size: usize) { + log::info!("Initialising kernel heap allocator"); + *ALLOCATOR.0.lock() = Some(unsafe { Heap::new(memory, memory_size) }); +} + +// FIXME: these are arch-specific +const CHUNK_SIZE: usize = 16; +const MINIMUM_ALIGNMENT: usize = 8; + +struct Header { + size_in_chunks: usize, +} + +// compile-time assertions to make sure that AllocationHeader's size is a power of two +// and CHUNK_SIZE is bigger than AllocationHeader's size +const _: () = { + assert!(mem::size_of::<Header>().is_power_of_two()); + assert!(CHUNK_SIZE >= mem::size_of::<Header>()); +}; + +/// A first-fit heap allocator, with CHUNK_SIZE chunks and a set size +/// In the future these will become subheaps and the actual heap allocator will create more +/// subheaps as needed +struct Heap { + total_chunks: usize, + allocated_chunks: usize, + chunks: *mut u8, + bitmap: *mut u8, +} + +impl Heap { + /// # Safety + /// This function assumes that the pointer given points at a valid memory address + unsafe fn new(memory: *mut u8, memory_size: usize) -> Self { + let total_chunks = Self::calculate_chunks(memory_size); + assert!(total_chunks * CHUNK_SIZE + (total_chunks + 7) / 8 <= memory_size); + Self { + total_chunks, + allocated_chunks: 0, + chunks: memory, + bitmap: unsafe { memory.add(total_chunks * CHUNK_SIZE) }, + } + } + + fn allocate(&mut self, size: usize, alignment: usize) -> Option<NonNull<u8>> { + assert!(alignment.is_power_of_two()); + let alignment = if alignment < MINIMUM_ALIGNMENT { + MINIMUM_ALIGNMENT + } else { + alignment + }; + + // We need space for the header as well + let size = size + mem::size_of::<Header>(); + let chunks_needed = (size + CHUNK_SIZE - 1) / CHUNK_SIZE; + let chunk_alignment = (alignment + CHUNK_SIZE - 1) / CHUNK_SIZE; + + if chunks_needed + chunk_alignment > self.free_chunks() { + return None; + } + + // FIXME: should utilize the alignment directly instead of trying to allocate `size + alignment` + let first_chunk = self.find_first_fit(chunks_needed + chunk_alignment)?; + let chunks_addr = self.chunks as usize; + let addr_unaligned = chunks_addr + first_chunk * CHUNK_SIZE; + + // Align the starting address and verify that we haven't gone outside the calculated free area + let addr = + addr_unaligned + alignment - (addr_unaligned + mem::size_of::<Header>()) % alignment; + let aligned_first_chunk = (addr - chunks_addr) / CHUNK_SIZE; + assert!(first_chunk <= aligned_first_chunk); + assert!( + aligned_first_chunk + chunks_needed <= first_chunk + chunks_needed + chunk_alignment + ); + + let header = addr as *mut Header; + unsafe { + (*header).size_in_chunks = chunks_needed; + } + + self.bitmap_set_range(aligned_first_chunk, chunks_needed, true); + + self.allocated_chunks += chunks_needed; + + let ptr: *mut u8 = unsafe { mem::transmute(header.add(1)) }; + // FIXME: zero or scrub memory? + assert!(ptr.is_aligned_to(alignment)); + NonNull::new(ptr) + } + + fn deallocate(&mut self, ptr: *mut u8) { + let header = Self::allocation_header(ptr); + let start = (header as usize - self.chunks as usize) / CHUNK_SIZE; + assert!(self.bitmap_get(start)); + let size = unsafe { (*header).size_in_chunks }; + self.bitmap_set_range(start, size, false); + self.allocated_chunks -= size; + // FIXME: zero or scrub memory? + } + + /// Finds first hole that can fit an allocation of `size` chunks, returns the start of the + /// found free chunks + fn find_first_fit(&self, size: usize) -> Option<usize> { + let mut start_of_free_chunks = 0; + let mut free_chunks = 0; + for i in 0..self.total_chunks / usize::BITS as usize { + if free_chunks >= size { + return Some(start_of_free_chunks); + } + + let mut bucket = unsafe { *self.bitmap.cast::<usize>().add(i) }; + if bucket == usize::MAX { + // Skip over completely full bucket + free_chunks = 0; + continue; + } + if bucket == 0 { + // Skip over completely empty bucket + if free_chunks == 0 { + start_of_free_chunks = i * usize::BITS as usize; + } + + free_chunks += usize::BITS as usize; + continue; + } + + let mut viewed_bits = 0; + while viewed_bits < usize::BITS as usize { + if bucket == 0 { + if free_chunks == 0 { + start_of_free_chunks = i * usize::BITS as usize + viewed_bits; + } + + free_chunks += usize::BITS as usize - viewed_bits; + viewed_bits = usize::BITS as usize; + } else { + let trailing_zeros = bucket.trailing_zeros() as usize; + bucket >>= trailing_zeros; + + if free_chunks == 0 { + start_of_free_chunks = i * usize::BITS as usize + viewed_bits; + } + + free_chunks += trailing_zeros; + viewed_bits += trailing_zeros; + + if free_chunks >= size { + return Some(start_of_free_chunks); + } + + let trailing_ones = bucket.trailing_ones() as usize; + bucket >>= trailing_ones; + viewed_bits += trailing_ones; + free_chunks = 0; + } + } + } + + if free_chunks >= size { + return Some(start_of_free_chunks); + } + + let first_trailing_bit = (self.total_chunks / usize::BITS as usize) * usize::BITS as usize; + let trailing_bits = self.total_chunks % usize::BITS as usize; + for i in 0..trailing_bits { + if self.bitmap_get(first_trailing_bit + i) { + free_chunks = 0; + continue; + } + + if free_chunks == 0 { + start_of_free_chunks = first_trailing_bit + i; + } + + free_chunks += 1; + if free_chunks >= size { + return Some(start_of_free_chunks); + } + } + + None + } + + fn bitmap_set_range(&mut self, start: usize, length: usize, value: bool) { + assert!(start + length <= self.total_chunks); + if length == 0 { + return; + } + + const BITMASK_FIRST_BYTE: [u8; 8] = [0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80]; + const BITMASK_LAST_BYTE: [u8; 8] = [0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F]; + let first = unsafe { self.bitmap.add(start / 8) }; + let last = unsafe { self.bitmap.add((start + length) / 8) }; + let mut byte_mask = BITMASK_FIRST_BYTE[start % 8]; + if first == last { + byte_mask &= BITMASK_LAST_BYTE[(start + length) % 8]; + if value { + unsafe { + *first |= byte_mask; + } + } else { + unsafe { + *first &= !byte_mask; + } + } + } else { + if value { + unsafe { + *first |= byte_mask; + } + } else { + unsafe { + *first &= !byte_mask; + } + } + + byte_mask = BITMASK_LAST_BYTE[(start + length) % 8]; + if value { + unsafe { + *last |= byte_mask; + } + } else { + unsafe { + *last &= !byte_mask; + } + } + + let first = unsafe { first.add(1) }; + if first >= last { + return; + } + + if value { + unsafe { + first.write_bytes(0xFF, last.sub_ptr(first)); + } + } else { + unsafe { + first.write_bytes(0, last.sub_ptr(first)); + } + } + } + } + + fn bitmap_get(&self, index: usize) -> bool { + assert!(index < self.total_chunks); + (unsafe { *self.bitmap.add(index / 8) } & (1 << (index % 8))) != 0 + } + + const fn free_chunks(&self) -> usize { + self.total_chunks - self.allocated_chunks + } + + fn allocation_header(ptr: *mut u8) -> *mut Header { + unsafe { mem::transmute::<_, *mut Header>(ptr).sub(1) } + } + + const fn calculate_chunks(memory_size: usize) -> usize { + memory_size / (CHUNK_SIZE + 1) + } +} + +unsafe impl Send for Heap {} #[alloc_error_handler] fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! { - panic!("allocation error: {:?}", layout) + crate::arch::sloop() } diff --git a/kernel/src/arch/mod.rs b/kernel/src/arch/mod.rs index 649461a..c1a5e1b 100644 --- a/kernel/src/arch/mod.rs +++ b/kernel/src/arch/mod.rs @@ -5,7 +5,7 @@ macro_rules! arch_cond { #[cfg(target_arch = $str)] pub mod $arch; #[cfg(target_arch = $str)] - pub use $arch::*; + pub use self::$arch::*; )*}; } diff --git a/kernel/src/arch/riscv64/entry.s b/kernel/src/arch/riscv64/entry.s new file mode 100644 index 0000000..822036c --- /dev/null +++ b/kernel/src/arch/riscv64/entry.s @@ -0,0 +1,31 @@ + .section .text.entry + .global _start +_start: + # load stack_top to sp register + la sp, stack_top + + # The BSS section is expected to be zero + la a0, _bss_start + la a1, _bss_end + bgeu a0, a1, 2f +1: + sd zero, (a0) + addi a0, a0, 8 + bltu a0, a1, 1b +2: + call _kernel_start + + .section .bss.stack + .global stack +stack: + # alloc stack memory + .space 4096 * 16 + .global stack_top +stack_top: + .section .bss.heap + .global _initial_kernel_heap_start +_initial_kernel_heap_start: + # alloc initial kmalloc memory + .space 4096 * 64 + .global _initial_kernel_heap_end +_initial_kernel_heap_end: diff --git a/kernel/src/arch/riscv64/memory.rs b/kernel/src/arch/riscv64/memory.rs new file mode 100644 index 0000000..b6411d7 --- /dev/null +++ b/kernel/src/arch/riscv64/memory.rs @@ -0,0 +1,268 @@ +use core::num; + +use alloc::boxed::Box; +use spin::{Mutex, Once}; +use crate::memory::{MemoryManager, PhysicalAddress, VirtualAddress}; + +use super::PAGE_SIZE; + +pub enum PageSize { + Size4KiB, + Size2MiB, + Size1GiB, + // FIXME: SV48 support + // Size512GiB, + // FIXME: SV57 support + // Size256TiB, +} + +impl PageSize { + fn level(&self) -> usize { + match self { + PageSize::Size4KiB => 0, + PageSize::Size2MiB => 1, + PageSize::Size1GiB => 2, + // FIXME: SV48 and SV57 support + } + } +} + +pub struct PageTable { + entries: [PageEntry; 512] +} + +impl PageTable { + /// Walk the page table to convert a virtual address to a physical address. + /// If a page fault would occur, this returns None. Otherwise, it returns the physical address. + pub fn virt_to_phys(&self, vaddr: VirtualAddress) -> Option<PhysicalAddress> { + let vpn = vaddr.vpns(); + + let mut v = &self.entries[vpn[2]]; + for i in (0..=2).rev() { + if v.is_invalid() { + // This is an invalid entry, page fault. + break; + } else if v.is_leaf() { + // In RISC-V, a leaf can be at any level. + + // The offset mask masks off the PPN. Each PPN is 9 bits and they start at bit #12. + // So, our formula 12 + i * 9 + let off_mask = (1 << (12 + i * 9)) - 1; + let vaddr_pgoff = vaddr.as_addr() & off_mask; + let addr = ((v.entry() << 2) as usize) & !off_mask; + return Some((addr | vaddr_pgoff).into()); + } + // Set v to the next entry which is pointed to by this entry. + // However, the address was shifted right by 2 places when stored in the page table + // entry, so we shift it left to get it back into place. + let entry = v.addr().as_ptr::<PageEntry>(); + // We do i - 1 here, however we should get None or Some() above + // before we do 0 - 1 = -1. + v = unsafe { entry.add(vpn[i - 1]).as_ref().unwrap() }; + } + + // If we get here, we've exhausted all valid tables and haven't + // found a leaf. + None + } + + /// Maps a virtual address to a physical address + /// flags should contain only the following: + /// Read, Write, Execute, User, and/or Global + /// flags MUST include one or more of the following: + /// Read, Write, Execute + /// The valid bit automatically gets added + pub fn map(&mut self, vaddr: VirtualAddress, paddr: PhysicalAddress, flags: PageEntryFlags, page_size: PageSize) { + assert!(flags as usize & 0xe != 0); + + let vpn = vaddr.vpns(); + let ppn = paddr.ppns(); + let level = page_size.level(); + + let mut v = &mut self.entries[vpn[2]]; + + // Now, we're going to traverse the page table and set the bits properly. We expect the root + // to be valid, however we're required to create anything beyond the root + for i in (level..2).rev() { + if v.is_invalid() { + let mut mm = MEMORY_MANAGER.get().unwrap().lock(); + let page = mm.zallocate_pages(1).unwrap().as_addr(); + v.set_entry((page as usize >> 2) | PageEntryFlags::Valid as usize); + } + + let entry = v.addr().as_mut_ptr::<PageEntry>(); + v = unsafe { entry.add(vpn[i]).as_mut().unwrap() }; + } + + // When we get here, we should be at VPN[0] and v should be pointing to our entry. + // The entry structure is Figure 4.18 in the RISC-V Privileged Specification + let entry = (ppn[2] << 28) as usize // PPN[2] = [53:28] + | (ppn[1] << 19) as usize // PPN[1] = [27:19] + | (ppn[0] << 10) as usize // PPN[0] = [18:10] + | flags as usize // Specified bits, such as User, Read, Write, etc. + | PageEntryFlags::Valid as usize; + v.set_entry(entry); + } + + /// Identity maps a page of memory + pub fn identity_map(&mut self, addr: PhysicalAddress, flags: PageEntryFlags, page_size: PageSize) { + // log::debug!("identity mapped {addr}"); + self.map(addr.as_addr().into(), addr, flags, page_size); + } + + /// Identity maps a range of contiguous memory + /// This assumes that start <= end + pub fn identity_map_range(&mut self, start: PhysicalAddress, end: PhysicalAddress, flags: PageEntryFlags) { + log::debug!("start: {start}, end: {end}"); + let mut mem_addr = start.as_addr() & !(PAGE_SIZE - 1); + let num_pages = (align_val(end.as_addr(), 12) - mem_addr - 1) / PAGE_SIZE + 1; + + for _ in 0..num_pages { + // FIXME: we can merge these page entries if possible into Size2MiB or larger entries + self.identity_map(mem_addr.into(), flags, PageSize::Size4KiB); + mem_addr += 1 << 12; + } + } + + /// Unmaps a page of memory at vaddr + pub fn unmap(&mut self, vaddr: VirtualAddress) { + let vpn = vaddr.vpns(); + + // Now, we're going to traverse the page table and clear the bits + let mut v = &mut self.entries[vpn[2]]; + for i in (0..2).rev() { + if v.is_invalid() { + // This is an invalid entry, page is already unmapped + return; + } else if v.is_leaf() { + // This is a leaf, which can be at any level + // In order to make this page unmapped, we need to clear the entry + v.set_entry(0); + return; + } + + let entry = v.addr().as_mut_ptr::<PageEntry>(); + v = unsafe { entry.add(vpn[i]).as_mut().unwrap() }; + } + + // If we're here this is an unmapped page + return; + } + + /// Unmaps a range of contiguous memory + /// This assumes that start <= end + pub fn unmap_range(&mut self, start: VirtualAddress, end: VirtualAddress) { + let mut mem_addr = start.as_addr() & !(PAGE_SIZE - 1); + let num_pages = (align_val(end.as_addr(), 12) - mem_addr) / PAGE_SIZE; + + for _ in 0..num_pages { + self.unmap(mem_addr.into()); + mem_addr += 1 << 12; + } + } + + /// Frees all memory associated with a table. + /// NOTE: This does NOT free the table directly. This must be freed manually. + fn destroy(&mut self) { + for entry in &mut self.entries { + entry.destroy() + } + } +} + +#[repr(usize)] +#[derive(Clone, Copy, Debug)] +pub enum PageEntryFlags { + None = 0, + Valid = 1, + Read = 1 << 1, + Write = 1 << 2, + Execute = 1 << 3, + User = 1 << 4, + Global = 1 << 5, + Access = 1 << 6, + Dirty = 1 << 7, + + // for convenience + ReadWrite = Self::Read as usize | Self::Write as usize, + ReadExecute = Self::Read as usize | Self::Execute as usize, + ReadWriteExecute = Self::Read as usize | Self::Write as usize | Self::Execute as usize, + UserReadWrite = Self::User as usize | Self::ReadWrite as usize, + UserReadExecute = Self::User as usize | Self::ReadExecute as usize, + UserReadWriteExecute = Self::User as usize | Self::ReadWriteExecute as usize, +} + +struct PageEntry(usize); + +impl PageEntry { + fn is_valid(&self) -> bool { + self.0 & PageEntryFlags::Valid as usize != 0 + } + + fn is_invalid(&self) -> bool { + !self.is_valid() + } + + fn is_leaf(&self) -> bool { + self.0 & PageEntryFlags::ReadWriteExecute as usize != 0 + } + + fn is_branch(&self) -> bool { + !self.is_leaf() + } + + fn entry(&self) -> usize { + self.0 + } + + fn set_entry(&mut self, entry: usize) { + self.0 = entry; + } + + fn clear_flag(&mut self, flag: PageEntryFlags) { + self.0 &= !(flag as usize); + } + + fn set_flag(&mut self, flag: PageEntryFlags) { + self.0 |= flag as usize; + } + + fn addr(&self) -> PhysicalAddress { + ((self.entry() as usize & !0x3ff) << 2).into() + } + + fn destroy(&mut self) { + if self.is_valid() && self.is_branch() { + // This is a valid entry so drill down and free + let memaddr = self.addr(); + let table = memaddr.as_mut_ptr::<PageTable>(); + unsafe { + (*table).destroy(); + let mut mm = MEMORY_MANAGER.get().unwrap().lock(); + mm.deallocate_pages(memaddr.into(), 0); + } + } + } +} + +// FIXME: PageTable should be integrated into MemoryManager *somehow* +pub static MEMORY_MANAGER: Once<Mutex<MemoryManager>> = Once::new(); +pub static PAGE_TABLE: Once<Mutex<PhysicalAddress>> = Once::new(); + +pub fn init(start_addr: PhysicalAddress, page_count: usize) { + let mut memory_manager = MemoryManager::new(); + + unsafe { + memory_manager.add_range(start_addr, page_count); + PAGE_TABLE.call_once(|| Mutex::new(memory_manager.zallocate_pages(0).unwrap())); + } + + MEMORY_MANAGER.call_once(|| Mutex::new(memory_manager)); +} + +/// Align (set to a multiple of some power of two) +/// This function always rounds up. +fn align_val(val: usize, order: usize) -> usize { + let o = (1 << order) - 1; + (val + o) & !o +} diff --git a/kernel/src/arch/riscv64/memory_regions.s b/kernel/src/arch/riscv64/memory_regions.s new file mode 100644 index 0000000..efb55d7 --- /dev/null +++ b/kernel/src/arch/riscv64/memory_regions.s @@ -0,0 +1,30 @@ +.section .rodata +.global TEXT_START +.global TEXT_END +.global RODATA_START +.global RODATA_END +.global DATA_START +.global DATA_END +.global SDATA_START +.global SDATA_END +.global BSS_START +.global BSS_END +.global INITIAL_KERNEL_HEAP_START +.global INITIAL_KERNEL_HEAP_SIZE +.global USABLE_MEMORY_START +.global USABLE_MEMORY_SIZE + +TEXT_START: .quad _text_start +TEXT_END: .quad _text_end +RODATA_START: .quad _rodata_start +RODATA_END: .quad _rodata_end +DATA_START: .quad _data_start +DATA_END: .quad _data_end +SDATA_START: .quad _sdata_start +SDATA_END: .quad _sdata_end +BSS_START: .quad _bss_start +BSS_END: .quad _bss_end +INITIAL_KERNEL_HEAP_START: .quad _initial_kernel_heap_start +INITIAL_KERNEL_HEAP_SIZE: .quad _initial_kernel_heap_size +USABLE_MEMORY_START: .quad _usable_memory_start +USABLE_MEMORY_SIZE: .quad _usable_memory_size diff --git a/kernel/src/arch/riscv64/mod.rs b/kernel/src/arch/riscv64/mod.rs index cfeed09..8ef40da 100644 --- a/kernel/src/arch/riscv64/mod.rs +++ b/kernel/src/arch/riscv64/mod.rs @@ -1 +1,90 @@ -//! \ No newline at end of file +mod memory; + +use core::{arch::{asm, global_asm}, fmt::Write}; +use alloc::boxed::Box; +use sbi::system_reset::{ResetType, ResetReason, system_reset}; +use spin::{Mutex, Once}; +use uart_16550::MmioSerialPort; + +use crate::{allocator, memory::PhysicalAddress, arch::riscv64::memory::{PAGE_TABLE, PageEntryFlags, PageSize, PageTable}}; + +global_asm!(include_str!("entry.s")); +global_asm!(include_str!("memory_regions.s")); + +pub const PAGE_SIZE: usize = 4096; + +extern { + static TEXT_START: PhysicalAddress; + static TEXT_END: PhysicalAddress; + + static RODATA_START: PhysicalAddress; + static RODATA_END: PhysicalAddress; + + static DATA_START: PhysicalAddress; + static DATA_END: PhysicalAddress; + + static SDATA_START: PhysicalAddress; + static SDATA_END: PhysicalAddress; + + static BSS_START: PhysicalAddress; + static BSS_END: PhysicalAddress; + + static INITIAL_KERNEL_HEAP_START: PhysicalAddress; + static INITIAL_KERNEL_HEAP_SIZE: usize; + + static USABLE_MEMORY_START: PhysicalAddress; + static USABLE_MEMORY_SIZE: usize; +} + +static SERIAL_CONSOLE: Once<Mutex<MmioSerialPort>> = Once::new(); + +#[no_mangle] +unsafe extern fn _kernel_start() -> ! { + SERIAL_CONSOLE.call_once(|| Mutex::new(unsafe { MmioSerialPort::new(0x1000_0000) })); + crate::logger::init().expect("failed to set logger"); + log::info!("Initialising AKern {}", crate::VERSION); + + allocator::init(INITIAL_KERNEL_HEAP_START.as_mut_ptr::<u8>(), INITIAL_KERNEL_HEAP_SIZE); + memory::init(USABLE_MEMORY_START.into(), USABLE_MEMORY_SIZE / PAGE_SIZE); + + let mut page_table_addr = PAGE_TABLE.get().unwrap().lock(); + let mut page_table = page_table_addr.as_mut_ptr::<PageTable>().as_mut().unwrap(); + + // Map text (executable) section + page_table.identity_map_range(TEXT_START, TEXT_END, PageEntryFlags::ReadExecute); + // Map rodata section + page_table.identity_map_range(RODATA_START, RODATA_END, PageEntryFlags::Read); + // Map data section + page_table.identity_map_range(DATA_START, DATA_END, PageEntryFlags::ReadWrite); + // Map sdata section + page_table.identity_map_range(SDATA_START, SDATA_END, PageEntryFlags::ReadWrite); + // Map bss section (includes stack and initial kernel heap) + page_table.identity_map_range(BSS_START, BSS_END, PageEntryFlags::ReadWrite); + // Map usable memory range (as rw so not executable) + page_table.identity_map_range(USABLE_MEMORY_START, USABLE_MEMORY_START + USABLE_MEMORY_SIZE.into(), PageEntryFlags::ReadWrite); + // Map Uart so we can continue using serial + page_table.identity_map(0x1000_0000_usize.into(), PageEntryFlags::ReadWrite, PageSize::Size4KiB); + + let table_ppn = page_table_addr.as_addr() as usize >> 12; + let satp_value = 8 << 60 | table_ppn; + log::info!("Enabling MMU"); + + asm!( + "csrw satp, {}", + "sfence.vma", + in(reg) satp_value, + ); + + crate::kmain::kmain("baka=9", None); +} + +/// Spin loop +pub fn sloop() -> ! { + loop { + unsafe { asm!("wfi") } + } +} + +pub fn log(args: core::fmt::Arguments<'_>) -> core::fmt::Result { + SERIAL_CONSOLE.get().unwrap().lock().write_fmt(args) +} diff --git a/kernel/src/arch/x86_64/gdt.rs b/kernel/src/arch/x86_64/gdt.rs new file mode 100644 index 0000000..83c3779 --- /dev/null +++ b/kernel/src/arch/x86_64/gdt.rs @@ -0,0 +1,51 @@ +use spin::Lazy; +use x86_64::{ + structures::{ + gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector}, + tss::TaskStateSegment, + }, + VirtAddr, +}; + +pub const DOUBLE_FAULT_IX: u16 = 0; + +pub unsafe fn init() { + use x86_64::instructions::segmentation::{Segment, CS, SS}; + use x86_64::instructions::tables::load_tss; + + log::info!("Initialising GDT"); + GDT.0.load(); + CS::set_reg(GDT.1.kcode); + SS::set_reg(GDT.1.kdata); + load_tss(GDT.1.tss); +} + +struct Selectors { + kcode: SegmentSelector, + kdata: SegmentSelector, + tss: SegmentSelector, +} + +static TSS: Lazy<TaskStateSegment> = Lazy::new(|| { + let mut tss = TaskStateSegment::new(); + tss.interrupt_stack_table[usize::from(DOUBLE_FAULT_IX)] = { + const SIZE: usize = 5 * 1024; + let stack = unsafe { + alloc::alloc::alloc_zeroed( + alloc::alloc::Layout::from_size_align(SIZE, 1).expect("stack pointer"), + ) + }; + VirtAddr::from_ptr(stack) + SIZE + }; + tss +}); + +static GDT: Lazy<(GlobalDescriptorTable, Selectors)> = Lazy::new(|| { + let mut gdt = GlobalDescriptorTable::new(); + let sels = Selectors { + kcode: gdt.add_entry(Descriptor::kernel_code_segment()), + kdata: gdt.add_entry(Descriptor::kernel_data_segment()), + tss: gdt.add_entry(Descriptor::tss_segment(&TSS)), + }; + (gdt, sels) +}); diff --git a/kernel/src/arch/x86_64/interrupts.rs b/kernel/src/arch/x86_64/interrupts.rs new file mode 100644 index 0000000..b3accc8 --- /dev/null +++ b/kernel/src/arch/x86_64/interrupts.rs @@ -0,0 +1,67 @@ +use spin::{Lazy, Mutex}; +use x2apic::lapic::{LocalApic, LocalApicBuilder}; +use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode}; + +pub unsafe fn init() { + log::info!("Initialising IDT"); + IDT.load(); + Lazy::force(&LAPIC); + x86_64::instructions::interrupts::enable(); +} + +#[repr(u8)] +enum Interrupt { + Timer = 32, + ApicErr = u8::MAX - 1, + Spurious = u8::MAX, +} + +static LAPIC: Lazy<Mutex<LocalApic>> = Lazy::new(|| { + let mut lapic = LocalApicBuilder::new() + .timer_vector(Interrupt::Timer as usize) + .error_vector(Interrupt::ApicErr as usize) + .spurious_vector(Interrupt::Spurious as usize) + .set_xapic_base( + unsafe { x2apic::lapic::xapic_base() } + + super::memory::HHDM_OFFSET.load(core::sync::atomic::Ordering::Relaxed), + ) + .build() + .expect("failed to setup Local APIC"); + unsafe { lapic.enable() }; + Mutex::new(lapic) +}); + +static IDT: Lazy<InterruptDescriptorTable> = Lazy::new(|| { + let mut idt = InterruptDescriptorTable::new(); + unsafe { + idt.double_fault + .set_handler_fn(double_fault) + .set_stack_index(super::gdt::DOUBLE_FAULT_IX); + } + idt.page_fault.set_handler_fn(page_fault); + idt[Interrupt::Timer as usize].set_handler_fn(timer); + idt +}); + +extern "x86-interrupt" fn double_fault(stack_frame: InterruptStackFrame, error_code: u64) -> ! { + panic!("Double fault: error code {error_code} \n{stack_frame:#?}") +} + +extern "x86-interrupt" fn page_fault( + stack_frame: InterruptStackFrame, + error_code: PageFaultErrorCode, +) { + panic!("Page fault ({error_code:?}): {stack_frame:?}") +} + +extern "x86-interrupt" fn timer(_: InterruptStackFrame) { + unsafe { LAPIC.lock().end_of_interrupt() }; +} + +extern "x86-interrupt" fn apic_err(_: InterruptStackFrame) { + panic!("Internal APIC error"); +} + +extern "x86-interrupt" fn spurious(_: InterruptStackFrame) { + unsafe { LAPIC.lock().end_of_interrupt() }; +} diff --git a/kernel/src/arch/x86_64/logging.rs b/kernel/src/arch/x86_64/logging.rs new file mode 100644 index 0000000..5f64096 --- /dev/null +++ b/kernel/src/arch/x86_64/logging.rs @@ -0,0 +1,46 @@ +//! Logging (as in terms of console / serial output) + +use core::fmt::Write; +use limine::{TerminalRequest, TerminalResponse}; +use spin::{Lazy, Mutex}; +use uart_16550::SerialPort; + +static SERIAL_CONSOLE: Mutex<SerialPort> = Mutex::new(unsafe { SerialPort::new(0x3f8) }); +static TERMINAL_LOGGER: Lazy<Mutex<TermLogger>> = Lazy::new(|| Mutex::new(TermLogger::new())); + +pub fn init() { + SERIAL_CONSOLE.lock().init(); + Lazy::force(&TERMINAL_LOGGER); +} + +pub fn log(args: core::fmt::Arguments<'_>) -> core::fmt::Result { + x86_64::instructions::interrupts::without_interrupts(|| { + TERMINAL_LOGGER.lock().write_fmt(args)?; + SERIAL_CONSOLE.lock().write_fmt(args) + }) +} + +struct TermLogger(&'static TerminalResponse); +unsafe impl Send for TermLogger {} +impl TermLogger { + pub fn new() -> Self { + static TERM_REQ: TerminalRequest = TerminalRequest::new(0); + Self( + TERM_REQ + .get_response() + .get() + .expect("failed to get terminal response"), + ) + } +} + +impl Write for TermLogger { + fn write_str(&mut self, s: &str) -> core::fmt::Result { + if let (Some(w), ts) = (self.0.write(), self.0.terminals()) { + for term in ts { + w(term, s); + } + } + Ok(()) + } +} diff --git a/kernel/src/arch/x86_64/memory.rs b/kernel/src/arch/x86_64/memory.rs new file mode 100644 index 0000000..3d1f9e4 --- /dev/null +++ b/kernel/src/arch/x86_64/memory.rs @@ -0,0 +1,54 @@ +use crate::memory::{MemoryManager, MAX_ORDER}; +use core::sync::atomic::AtomicU64; +use limine::{MemmapEntry, MemoryMapEntryType, NonNullPtr}; +use spin::{Mutex, Once}; +use x86_64::{structures::paging::OffsetPageTable, VirtAddr}; + +pub const PAGE_SIZE: usize = 4096; + +pub static MEMORY_MANAGER: Once<Mutex<MemoryManager>> = Once::new(); +pub static HHDM_OFFSET: AtomicU64 = AtomicU64::new(0); +static PAGE_TABLE: Once<Mutex<OffsetPageTable>> = Once::new(); + +/// Initialise page table +pub unsafe fn init_pt(phys_base: VirtAddr) { + log::info!("Retrieving page table"); + HHDM_OFFSET.store(phys_base.as_u64(), core::sync::atomic::Ordering::Relaxed); + PAGE_TABLE.call_once(|| { + Mutex::new(OffsetPageTable::new( + &mut *((phys_base + + x86_64::registers::control::Cr3::read() + .0 + .start_address() + .as_u64()) + .as_mut_ptr()), + phys_base, + )) + }); +} + +/// Initialise memory manager +pub fn initialize(mmap: &'static [NonNullPtr<MemmapEntry>]) { + let mut memory_manager = MemoryManager::new(); + + for entry in mmap { + if entry.typ != MemoryMapEntryType::Usable { + continue; + } + + let alignment = PAGE_SIZE << MAX_ORDER; + let start_addr_unaligned = entry.base as usize; + let diff = alignment - start_addr_unaligned % alignment; + if diff > entry.len as usize { + continue; + } + let start_addr = start_addr_unaligned + diff; + let page_count = (entry.len as usize - diff) / PAGE_SIZE; + + unsafe { + memory_manager.add_range(start_addr.into(), page_count); + } + } + + MEMORY_MANAGER.call_once(|| Mutex::new(memory_manager)); +} diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index cfeed09..d212e8d 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -1 +1,83 @@ -//! \ No newline at end of file +pub mod memory; + +mod gdt; +mod interrupts; +mod logging; + +pub use logging::log; +pub use memory::PAGE_SIZE; + +use crate::allocator; +use limine::{HhdmRequest, KernelFileRequest, MemmapRequest, ModuleRequest}; +use x86_64::VirtAddr; + +extern "C" { + fn _initial_kernel_heap_start(); + fn _initial_kernel_heap_size(); +} + +const INITIAL_KERNEL_HEAP_START: *mut u8 = _initial_kernel_heap_start as _; +const INITIAL_KERNEL_HEAP_SIZE: *const () = _initial_kernel_heap_size as _; + +#[no_mangle] +unsafe extern "C" fn _kernel_start() -> ! { + logging::init(); + crate::logger::init().expect("failed to set logger"); + log::info!("Initialising AKern {}", crate::VERSION); + + static HDHM_REQ: HhdmRequest = HhdmRequest::new(0); + memory::init_pt(VirtAddr::new( + HDHM_REQ + .get_response() + .get() + .expect("tried to get physical memory mapping offset from Limine") + .offset, + )); + + allocator::init(INITIAL_KERNEL_HEAP_START, INITIAL_KERNEL_HEAP_SIZE as _); + + static MMAP_REQ: MemmapRequest = MemmapRequest::new(0); + memory::initialize( + MMAP_REQ + .get_response() + .get() + .expect("tried to get memory map from Limine") + .memmap(), + ); + + gdt::init(); + interrupts::init(); + + static KFILE_REQ: KernelFileRequest = KernelFileRequest::new(0); + static MOD_REQ: ModuleRequest = ModuleRequest::new(0); + crate::kmain::kmain( + KFILE_REQ + .get_response() + .get() + .and_then(|r| r.kernel_file.get()) + .expect("failed to get kernel file from Limine") + .cmdline + .to_str() + .map(core::ffi::CStr::to_str) + .transpose() + .expect("expected valid cmdline string") + .unwrap_or_default(), + MOD_REQ + .get_response() + .get() + .and_then(|m| m.modules().get(0)) + .map(|file| unsafe { + core::slice::from_raw_parts( + file.base.as_ptr().expect("invalid initrd"), + file.length as usize, + ) + }), + ) +} + +/// Spin loop +pub fn sloop() -> ! { + loop { + x86_64::instructions::hlt(); + } +} diff --git a/kernel/src/kmain.rs b/kernel/src/kmain.rs new file mode 100644 index 0000000..79f1392 --- /dev/null +++ b/kernel/src/kmain.rs @@ -0,0 +1,15 @@ +//! AbleOS Kernel Entrypoint + +pub fn kmain(cmdline: &str, bootstrap: Option<&'static [u8]>) -> ! { + log::debug!("Entered kmain"); + + // TODO: Actual cmdline parsing (Serde?) + if cmdline.contains("baka=9") { + let _ = crate::arch::log(format_args!(include_str!("../data/⑨. バカ"))); + } + + log::info!("Cmdline: \"{cmdline}\""); + let bootstrap = bootstrap.expect("no bootstrap found"); + + crate::arch::sloop() +} diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index d783ab5..9e644da 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -1,20 +1,48 @@ //! The ableOS kernel. -#![feature(alloc_error_handler, prelude_import)] +#![feature( + abi_x86_interrupt, + alloc_error_handler, + inline_const, + panic_info_message, + pointer_is_aligned, + prelude_import, + ptr_sub_ptr +)] #![no_std] -#![deny(missing_docs)] extern crate alloc; -pub mod allocator; -pub mod arch; -pub mod task; +mod allocator; +mod arch; +mod kmain; +mod logger; +mod memory; +mod task; use versioning::Version; /// Kernel's version -pub const KERNEL_VERSION: Version = Version { +pub const VERSION: Version = Version { major: 0, - minor: 1, - patch: 2, + minor: 2, + patch: 0, }; + +#[panic_handler] +fn panic(info: &core::panic::PanicInfo) -> ! { + if let Some(loc) = info.location() { + let _ = crate::arch::log(format_args!( + "Location: {}: {}, {}\r\n", + loc.file(), + loc.line(), + loc.column() + )); + } + + if let Some(msg) = info.message() { + let _ = crate::arch::log(format_args!("{msg}\r\n")); + } + + loop {} +} diff --git a/kernel/src/logger.rs b/kernel/src/logger.rs new file mode 100644 index 0000000..f0bfa0a --- /dev/null +++ b/kernel/src/logger.rs @@ -0,0 +1,33 @@ +use log::{Level, SetLoggerError}; + +pub fn init() -> Result<(), SetLoggerError> { + log::set_logger(&crate::logger::Logger)?; + log::set_max_level(log::LevelFilter::Trace); + Ok(()) +} + +struct Logger; +impl log::Log for Logger { + fn enabled(&self, metadata: &log::Metadata) -> bool { + true + } + + fn log(&self, record: &log::Record) { + let lvl = record.level(); + crate::arch::log(format_args!( + "\x1b[38;5;{}m{lvl}\x1b[0m [{}]: {}\r\n", + match lvl { + Level::Error => "160", + Level::Warn => "172", + Level::Info => "47", + Level::Debug => "25", + Level::Trace => "103", + }, + record.module_path().unwrap_or_default(), + record.args(), + )) + .expect("write to serial console"); + } + + fn flush(&self) {} +} diff --git a/ableos/src/main.rs b/kernel/src/main.rs similarity index 53% rename from ableos/src/main.rs rename to kernel/src/main.rs index f4e9d7e..973e301 100644 --- a/ableos/src/main.rs +++ b/kernel/src/main.rs @@ -1,4 +1,4 @@ #![no_std] #![no_main] -pub use ableos::*; +extern crate kernel; diff --git a/kernel/src/memory.rs b/kernel/src/memory.rs new file mode 100644 index 0000000..15b5db1 --- /dev/null +++ b/kernel/src/memory.rs @@ -0,0 +1,231 @@ +//! The Memory Manager + +use alloc::collections::VecDeque; +use derive_more::*; + +pub use crate::arch::PAGE_SIZE; +pub const MAX_ORDER: usize = 10; + +#[repr(transparent)] +#[derive( + Add, + AddAssign, + Binary, + BitAnd, + BitAndAssign, + BitOr, + BitOrAssign, + BitXor, + BitXorAssign, + Clone, + Constructor, + Copy, + Display, + Div, + DivAssign, + Eq, + From, + LowerHex, + Mul, + MulAssign, + Not, + Octal, + Ord, + PartialEq, + PartialOrd, + Rem, + RemAssign, + Shl, + ShlAssign, + Shr, + ShrAssign, + Sub, + SubAssign, + Sum, + UpperHex, +)] +#[display(fmt = "0x{:x}", _0)] +#[from(forward)] +pub struct VirtualAddress(usize); + +impl VirtualAddress { + #[cfg(target_arch = "riscv64")] + /// Returns an array of Virtual Page Numbers + // FIXME: SV48 and SV57 support + pub fn vpns(&self) -> [usize; 3] { + [ + // [20:12] + (self.0 >> 12) & 0x1ff, + // [29:21] + (self.0 >> 21) & 0x1ff, + // [38:30] + (self.0 >> 30) & 0x1ff, + ] + } + + pub fn as_addr(&self) -> usize { + self.0 + } + + pub fn as_ptr<T>(&self) -> *const T { + self.0 as _ + } + + pub fn as_mut_ptr<T>(&mut self) -> *mut T { + self.0 as _ + } +} + +#[repr(transparent)] +#[derive( + Add, + AddAssign, + Binary, + BitAnd, + BitAndAssign, + BitOr, + BitOrAssign, + BitXor, + BitXorAssign, + Clone, + Constructor, + Copy, + Display, + Div, + DivAssign, + Eq, + From, + LowerHex, + Mul, + MulAssign, + Not, + Octal, + Ord, + PartialEq, + PartialOrd, + Rem, + RemAssign, + Shl, + ShlAssign, + Shr, + ShrAssign, + Sub, + SubAssign, + Sum, + UpperHex, +)] +#[display(fmt = "0x{:x}", _0)] +#[from(forward)] +pub struct PhysicalAddress(usize); + +impl PhysicalAddress { + #[cfg(target_arch = "riscv64")] + /// Returns an array of Physical Page Numbers + // FIXME: SV48 and SV57 support + pub fn ppns(&self) -> [usize; 3] { + [ + // [20:12] + (self.0 >> 12) & 0x1ff, + // [29:21] + (self.0 >> 21) & 0x1ff, + // [55:30] + (self.0 >> 30) & 0x3ffffff, + ] + } + + pub fn as_addr(&self) -> usize { + self.0 + } + + pub fn as_ptr<T>(&self) -> *const T { + self.0 as _ + } + + pub fn as_mut_ptr<T>(&self) -> *mut T { + self.0 as _ + } +} + +pub struct MemoryManager { + free_lists: [VecDeque<PhysicalAddress>; MAX_ORDER + 1], +} + +impl MemoryManager { + pub const fn new() -> Self { + Self { + free_lists: [const { VecDeque::new() }; MAX_ORDER + 1], + } + } + + // FIXME: this method should take a length and turn that into an order + pub fn allocate_pages(&mut self, order: usize) -> Option<PhysicalAddress> { + self.get_free_pages(order) + } + + // FIXME: this method should take a length and turn that into an order + pub fn zallocate_pages(&mut self, order: usize) -> Option<PhysicalAddress> { + let alloc = self.allocate_pages(order)?; + unsafe { + alloc.as_mut_ptr::<u8>().write_bytes(0, PAGE_SIZE << order); + } + Some(alloc) + } + + /// # Safety + /// This method assumes that `address` is in range of this allocator + // FIXME: this method should take a length and turn that into an order + pub unsafe fn deallocate_pages(&mut self, address: PhysicalAddress, order: usize) { + self.free_lists[order].push_front(address); + self.merge_buddies(order, address) + } + + /// # Safety + /// This method assumes that the given address range, + /// a) starts and ends at an address aligned to page boundaries, + /// b) are valid free pages not already added, + /// FIXME: c) starts and ends at an address aligned to `PAGE_SIZE << MAX_ORDER` + pub unsafe fn add_range(&mut self, start_addr: PhysicalAddress, page_count: usize) { + for i in 0..page_count / 1024 { + self.free_lists[MAX_ORDER].push_back(start_addr + (i * 1024 * PAGE_SIZE).into()); + } + } + + fn get_free_pages(&mut self, order: usize) -> Option<PhysicalAddress> { + // We can't get such a page! + if order > MAX_ORDER { + return None; + } + + if self.free_lists[order].len() > 0 { + return self.free_lists[order].pop_front(); + } + + self.get_free_pages(order + 1).map(|addr| { + self.free_lists[order].push_front(addr ^ (PAGE_SIZE << order).into()); + addr + }) + } + + fn merge_buddies(&mut self, order: usize, address: PhysicalAddress) { + // if we can't have any higher order blocks, we can't merge + if order > MAX_ORDER - 1 { + return; + } + + let buddy_address = address ^ (PAGE_SIZE << order).into(); + log::debug!("merge buddy: 0x{buddy_address:x}"); + if let Some(buddy_index) = self.free_lists[order] + .iter() + .position(|blk| *blk == buddy_address) + { + self.free_lists[order].pop_front(); + self.free_lists[order].remove(buddy_index); + let new_address = address.min(buddy_address); + log::debug!( + "Merging 0x{address:x} @ {order} with 0x{buddy_address:x} at 0x{new_address:x}" + ); + self.free_lists[order + 1].push_front(new_address); + self.merge_buddies(order + 1, new_address) + } + } +} diff --git a/kernel/targets/riscv64-virt-ableos.json b/kernel/targets/riscv64-virt-ableos.json new file mode 100644 index 0000000..deeca60 --- /dev/null +++ b/kernel/targets/riscv64-virt-ableos.json @@ -0,0 +1,22 @@ +{ + "arch": "riscv64", + "code-model": "medium", + "cpu": "generic-rv64", + "data-layout": "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", + "eh-frame-header": false, + "emit-debug-gdb-scripts": false, + "features": "+m,+a,+f,+d,+c", + "linker": "rust-lld", + "linker-flavor": "ld.lld", + "llvm-abiname": "lp64d", + "llvm-target": "riscv64", + "max-atomic-width": 64, + "panic-strategy": "abort", + "relocation-model": "static", + "target-pointer-width": "64", + "pre-link-args": { + "ld.lld": [ + "--script=kernel/lds/riscv64-virt.ld" + ] + } +} diff --git a/ableos/json_targets/x86_64-ableos.json b/kernel/targets/x86_64-ableos.json similarity index 65% rename from ableos/json_targets/x86_64-ableos.json rename to kernel/targets/x86_64-ableos.json index 346fefd..cd32752 100644 --- a/ableos/json_targets/x86_64-ableos.json +++ b/kernel/targets/x86_64-ableos.json @@ -11,5 +11,12 @@ "linker": "rust-lld", "panic-strategy": "abort", "disable-redzone": true, - "features": "-mmx,-sse,+soft-float" + "features": "-mmx,-sse,+soft-float", + "code-model": "kernel", + "pre-link-args": { + "ld.lld": [ + "--gc-sections", + "--script=kernel/lds/x86_64.ld" + ] + } } \ No newline at end of file diff --git a/qmp.py b/qmp.py deleted file mode 100644 index 9210da5..0000000 --- a/qmp.py +++ /dev/null @@ -1,243 +0,0 @@ -# QEMU Monitor Protocol Python class -# -# Copyright (C) 2009, 2010 Red Hat Inc. -# -# Authors: -# Luiz Capitulino <lcapitulino@redhat.com> -# -# This work is licensed under the terms of the GNU GPL, version 2. See -# the COPYING file in the top-level directory. - -import json -import errno -import socket -import logging - - -class QMPError(Exception): - pass - - -class QMPConnectError(QMPError): - pass - - -class QMPCapabilitiesError(QMPError): - pass - - -class QMPTimeoutError(QMPError): - pass - - -class QEMUMonitorProtocol(object): - - #: Logger object for debugging messages - logger = logging.getLogger('QMP') - #: Socket's error class - error = socket.error - #: Socket's timeout - timeout = socket.timeout - - def __init__(self, address, server=False): - """ - Create a QEMUMonitorProtocol class. - @param address: QEMU address, can be either a unix socket path (string) - or a tuple in the form ( address, port ) for a TCP - connection - @param server: server mode listens on the socket (bool) - @raise socket.error on socket connection errors - @note No connection is established, this is done by the connect() or - accept() methods - """ - self.__events = [] - self.__address = address - self.__sock = self.__get_sock() - self.__sockfile = None - if server: - self.__sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - self.__sock.bind(self.__address) - self.__sock.listen(1) - - def __get_sock(self): - if isinstance(self.__address, tuple): - family = socket.AF_INET - else: - family = socket.AF_UNIX - return socket.socket(family, socket.SOCK_STREAM) - - def __negotiate_capabilities(self): - greeting = self.__json_read() - if greeting is None or "QMP" not in greeting: - raise QMPConnectError - # Greeting seems ok, negotiate capabilities - resp = self.cmd('qmp_capabilities') - if "return" in resp: - return greeting - raise QMPCapabilitiesError - - def __json_read(self, only_event=False): - while True: - data = self.__sockfile.readline() - if not data: - return - resp = json.loads(data) - if 'event' in resp: - self.logger.debug("<<< %s", resp) - self.__events.append(resp) - if not only_event: - continue - return resp - - def __get_events(self, wait=False): - """ - Check for new events in the stream and cache them in __events. - @param wait (bool): block until an event is available. - @param wait (float): If wait is a float, treat it as a timeout value. - @raise QMPTimeoutError: If a timeout float is provided and the timeout - period elapses. - @raise QMPConnectError: If wait is True but no events could be - retrieved or if some other error occurred. - """ - - # Check for new events regardless and pull them into the cache: - self.__sock.setblocking(0) - try: - self.__json_read() - except socket.error as err: - if err[0] == errno.EAGAIN: - # No data available - pass - self.__sock.setblocking(1) - - # Wait for new events, if needed. - # if wait is 0.0, this means "no wait" and is also implicitly false. - if not self.__events and wait: - if isinstance(wait, float): - self.__sock.settimeout(wait) - try: - ret = self.__json_read(only_event=True) - except socket.timeout: - raise QMPTimeoutError("Timeout waiting for event") - except: - raise QMPConnectError("Error while reading from socket") - if ret is None: - raise QMPConnectError("Error while reading from socket") - self.__sock.settimeout(None) - - def connect(self, negotiate=True): - """ - Connect to the QMP Monitor and perform capabilities negotiation. - @return QMP greeting dict - @raise socket.error on socket connection errors - @raise QMPConnectError if the greeting is not received - @raise QMPCapabilitiesError if fails to negotiate capabilities - """ - self.__sock.connect(self.__address) - self.__sockfile = self.__sock.makefile() - if negotiate: - return self.__negotiate_capabilities() - - def accept(self): - """ - Await connection from QMP Monitor and perform capabilities negotiation. - @return QMP greeting dict - @raise socket.error on socket connection errors - @raise QMPConnectError if the greeting is not received - @raise QMPCapabilitiesError if fails to negotiate capabilities - """ - self.__sock.settimeout(15) - self.__sock, _ = self.__sock.accept() - self.__sockfile = self.__sock.makefile() - return self.__negotiate_capabilities() - - def cmd_obj(self, qmp_cmd): - """ - Send a QMP command to the QMP Monitor. - @param qmp_cmd: QMP command to be sent as a Python dict - @return QMP response as a Python dict or None if the connection has - been closed - """ - self.logger.debug(">>> %s", qmp_cmd) - try: - self.__sock.sendall(json.dumps(qmp_cmd).encode('utf-8')) - except socket.error as err: - if err[0] == errno.EPIPE: - return - raise socket.error(err) - resp = self.__json_read() - self.logger.debug("<<< %s", resp) - return resp - - def cmd(self, name, args=None, cmd_id=None): - """ - Build a QMP command and send it to the QMP Monitor. - @param name: command name (string) - @param args: command arguments (dict) - @param cmd_id: command id (dict, list, string or int) - """ - qmp_cmd = {'execute': name} - if args: - qmp_cmd['arguments'] = args - if cmd_id: - qmp_cmd['id'] = cmd_id - return self.cmd_obj(qmp_cmd) - - def command(self, cmd, **kwds): - """ - Build and send a QMP command to the monitor, report errors if any - """ - ret = self.cmd(cmd, kwds) - if "error" in ret: - raise Exception(ret['error']['desc']) - return ret['return'] - - def pull_event(self, wait=False): - """ - Pulls a single event. - @param wait (bool): block until an event is available. - @param wait (float): If wait is a float, treat it as a timeout value. - @raise QMPTimeoutError: If a timeout float is provided and the timeout - period elapses. - @raise QMPConnectError: If wait is True but no events could be - retrieved or if some other error occurred. - @return The first available QMP event, or None. - """ - self.__get_events(wait) - - if self.__events: - return self.__events.pop(0) - return None - - def get_events(self, wait=False): - """ - Get a list of available QMP events. - @param wait (bool): block until an event is available. - @param wait (float): If wait is a float, treat it as a timeout value. - @raise QMPTimeoutError: If a timeout float is provided and the timeout - period elapses. - @raise QMPConnectError: If wait is True but no events could be - retrieved or if some other error occurred. - @return The list of available QMP events. - """ - self.__get_events(wait) - return self.__events - - def clear_events(self): - """ - Clear current list of pending events. - """ - self.__events = [] - - def close(self): - self.__sock.close() - self.__sockfile.close() - - def settimeout(self, timeout): - self.__sock.settimeout(timeout) - - def get_sock_fd(self): - return self.__sock.fileno() - - def is_scm_available(self): - return self.__sock.family == socket.AF_UNIX \ No newline at end of file diff --git a/qprofiler.py b/qprofiler.py deleted file mode 100644 index 1170b67..0000000 --- a/qprofiler.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/python -# -# QProfiler is a QEMU profiler based on QMP -# -# Copyright (c) 2019-2022 Matias Vara <matiasevara@gmail.com> -# All Rights Reserved -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -from __future__ import print_function -import sys, os, re -from qmp import QEMUMonitorProtocol -from time import sleep -import subprocess - -def main(args): - path = None - filename = None - - # duration of the test in seconds - duration = 5 - - # sampling frequency in seconds - frequency = 0.05 - - while len(args): - arg = args[0] - - if arg.startswith('--'): - arg = arg[2:] - if arg.find('=') == -1: - value = True - else: - arg, value = arg.split('=', 1) - - if arg in ['path']: - if type(value) == str: - path = value - elif arg in ['duration']: - duration = int(value) - elif arg in ['frequency']: - frequency = float(value) - elif arg in ['filename']: - filename = value - else: - print('Unknown argument "%s"' % arg) - return 1 - - args = args[1:] - else: - break - - if not path: - print("Path isn't set, use --path=qmp-monitor-address") - return 1 - - def do_command(srv, cmd, **kwds): - rsp = srv.cmd(cmd, kwds) - if 'error' in rsp: - raise Exception(rsp['error']['desc']) - return rsp['return'] - - srv = QEMUMonitorProtocol(path) - srv.connect() - - arguments = {} - command = 'human-monitor-command' - - r = int(duration // frequency) - - rip_hash = {} - - for i in range(r): - arguments['command-line'] = 'info registers' - rsp = do_command(srv, command, **arguments) - - regs = re.search(r'RIP=([\w]+)\s', rsp) - rip = regs.group(1) - - if rip in rip_hash: - rip_hash[rip] += 1 - else: - rip_hash[rip] = 1 - - sleep(frequency) - - srv.close() - rip_hash_name = {} - - for i in rip_hash: - with open(os.devnull, 'w') as devnull: - # pass - tmp = subprocess.check_output("addr2line --demangle -p -s -f -e " - + filename - + " " - + i , shell=True, stderr=devnull).rstrip() - - if tmp in rip_hash_name: - rip_hash_name[tmp] += rip_hash[i] - else: - rip_hash_name[tmp] = rip_hash[i] - - for i in rip_hash_name: - print('{:>8} {}'.format(rip_hash_name[i], i)) - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) \ No newline at end of file diff --git a/qrcode-rust/Cargo.toml b/qrcode-rust/Cargo.toml deleted file mode 100644 index f442da3..0000000 --- a/qrcode-rust/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "qrcode" -description = "QR code encoder in Rust" -license = "MIT OR Apache-2.0" -version = "0.12.0" -edition = "2018" -authors = ["kennytm <kennytm@gmail.com>"] -keywords = ["qrcode"] - - -[dependencies] -# checked_int_cast = "1" - - -[features] -default = [] -bench = [] -svg = [] - -[[bin]] -name = "qrencode" diff --git a/qrcode-rust/rustfmt.toml b/qrcode-rust/rustfmt.toml deleted file mode 100644 index acd2021..0000000 --- a/qrcode-rust/rustfmt.toml +++ /dev/null @@ -1,3 +0,0 @@ -max_width = 120 -use_small_heuristics = "Max" -use_field_init_shorthand = true diff --git a/qrcode-rust/src/bin/qrencode.rs b/qrcode-rust/src/bin/qrencode.rs deleted file mode 100644 index 4837828..0000000 --- a/qrcode-rust/src/bin/qrencode.rs +++ /dev/null @@ -1,8 +0,0 @@ -use std::env; - -pub fn main() { - let arg = env::args().nth(1).unwrap(); - let code = qrcode::QrCode::new(arg.as_bytes()).unwrap(); - - print!("{}", code.render().dark_color("\x1b[7m \x1b[0m").light_color("\x1b[49m \x1b[0m").build()); -} diff --git a/qrcode-rust/src/bits.rs b/qrcode-rust/src/bits.rs deleted file mode 100644 index 9cc951c..0000000 --- a/qrcode-rust/src/bits.rs +++ /dev/null @@ -1,982 +0,0 @@ -//! The `bits` module encodes binary data into raw bits used in a QR code. - -use core::cmp::min; - -#[cfg(feature = "bench")] -extern crate test; - -use alloc::vec::Vec; - -use crate::cast::{As, Truncate}; -use crate::optimize::{total_encoded_len, Optimizer, Parser, Segment}; -use crate::types::{EcLevel, Mode, QrError, QrResult, Version}; - -//------------------------------------------------------------------------------ -//{{{ Bits - -/// The `Bits` structure stores the encoded data for a QR code. -pub struct Bits { - data: Vec<u8>, - bit_offset: usize, - version: Version, -} - -impl Bits { - /// Constructs a new, empty bits structure. - pub fn new(version: Version) -> Self { - Self { data: Vec::new(), bit_offset: 0, version } - } - - /// Pushes an N-bit big-endian integer to the end of the bits. - /// - /// Note: It is up to the developer to ensure that `number` really only is - /// `n` bit in size. Otherwise the excess bits may stomp on the existing - /// ones. - fn push_number(&mut self, n: usize, number: u16) { - debug_assert!(n == 16 || n < 16 && number < (1 << n), "{} is too big as a {}-bit number", number, n); - - let b = self.bit_offset + n; - let last_index = self.data.len().wrapping_sub(1); - match (self.bit_offset, b) { - (0, 0..=8) => { - self.data.push((number << (8 - b)).truncate_as_u8()); - } - (0, _) => { - self.data.push((number >> (b - 8)).truncate_as_u8()); - self.data.push((number << (16 - b)).truncate_as_u8()); - } - (_, 0..=8) => { - self.data[last_index] |= (number << (8 - b)).truncate_as_u8(); - } - (_, 9..=16) => { - self.data[last_index] |= (number >> (b - 8)).truncate_as_u8(); - self.data.push((number << (16 - b)).truncate_as_u8()); - } - _ => { - self.data[last_index] |= (number >> (b - 8)).truncate_as_u8(); - self.data.push((number >> (b - 16)).truncate_as_u8()); - self.data.push((number << (24 - b)).truncate_as_u8()); - } - } - self.bit_offset = b & 7; - } - - /// Pushes an N-bit big-endian integer to the end of the bits, and check - /// that the number does not overflow the bits. - /// - /// Returns `Err(QrError::DataTooLong)` on overflow. - fn push_number_checked(&mut self, n: usize, number: usize) -> QrResult<()> { - if n > 16 || number >= (1 << n) { - Err(QrError::DataTooLong) - } else { - self.push_number(n, number.as_u16()); - Ok(()) - } - } - - /// Reserves `n` extra bits of space for pushing. - fn reserve(&mut self, n: usize) { - let extra_bytes = (n + (8 - self.bit_offset) % 8) / 8; - self.data.reserve(extra_bytes); - } - - /// Convert the bits into a bytes vector. - pub fn into_bytes(self) -> Vec<u8> { - self.data - } - - /// Total number of bits currently pushed. - pub fn len(&self) -> usize { - if self.bit_offset == 0 { - self.data.len() * 8 - } else { - (self.data.len() - 1) * 8 + self.bit_offset - } - } - - /// Whether there are any bits pushed. - pub fn is_empty(&self) -> bool { - self.data.is_empty() - } - - /// The maximum number of bits allowed by the provided QR code version and - /// error correction level. - /// - /// # Errors - /// - /// Returns `Err(QrError::InvalidVersion)` if it is not valid to use the - /// `ec_level` for the given version (e.g. `Version::Micro(1)` with - /// `EcLevel::H`). - pub fn max_len(&self, ec_level: EcLevel) -> QrResult<usize> { - self.version.fetch(ec_level, &DATA_LENGTHS) - } - - /// Version of the QR code. - pub fn version(&self) -> Version { - self.version - } -} - -#[test] -fn test_push_number() { - let mut bits = Bits::new(Version::Normal(1)); - - bits.push_number(3, 0b010); // 0:0 .. 0:3 - bits.push_number(3, 0b110); // 0:3 .. 0:6 - bits.push_number(3, 0b101); // 0:6 .. 1:1 - bits.push_number(7, 0b001_1010); // 1:1 .. 2:0 - bits.push_number(4, 0b1100); // 2:0 .. 2:4 - bits.push_number(12, 0b1011_0110_1101); // 2:4 .. 4:0 - bits.push_number(10, 0b01_1001_0001); // 4:0 .. 5:2 - bits.push_number(15, 0b111_0010_1110_0011); // 5:2 .. 7:1 - - let bytes = bits.into_bytes(); - - assert_eq!( - bytes, - vec![ - 0b0101_1010, // 90 - 0b1001_1010, // 154 - 0b1100_1011, // 203 - 0b0110_1101, // 109 - 0b01_1001_00, // 100 - 0b0111_1001, // 121 - 0b0111_0001, // 113 - 0b1000_0000, // 128 - ] - ); -} - -#[cfg(feature = "bench")] -#[bench] -fn bench_push_splitted_bytes(bencher: &mut test::Bencher) { - bencher.iter(|| { - let mut bits = Bits::new(Version::Normal(40)); - bits.push_number(4, 0b0101); - for _ in 0..1024 { - bits.push_number(8, 0b10101010); - } - bits.into_bytes() - }); -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Mode indicator - -/// An "extended" mode indicator, includes all indicators supported by QR code -/// beyond those bearing data. -#[derive(Copy, Clone)] -pub enum ExtendedMode { - /// ECI mode indicator, to introduce an ECI designator. - Eci, - - /// The normal mode to introduce data. - Data(Mode), - - /// FNC-1 mode in the first position. - Fnc1First, - - /// FNC-1 mode in the second position. - Fnc1Second, - - /// Structured append. - StructuredAppend, -} - -impl Bits { - /// Push the mode indicator to the end of the bits. - /// - /// # Errors - /// - /// If the mode is not supported in the provided version, this method - /// returns `Err(QrError::UnsupportedCharacterSet)`. - pub fn push_mode_indicator(&mut self, mode: ExtendedMode) -> QrResult<()> { - #[allow(clippy::match_same_arms)] - let number = match (self.version, mode) { - (Version::Micro(1), ExtendedMode::Data(Mode::Numeric)) => return Ok(()), - (Version::Micro(_), ExtendedMode::Data(Mode::Numeric)) => 0, - (Version::Micro(_), ExtendedMode::Data(Mode::Alphanumeric)) => 1, - (Version::Micro(_), ExtendedMode::Data(Mode::Byte)) => 0b10, - (Version::Micro(_), ExtendedMode::Data(Mode::Kanji)) => 0b11, - (Version::Micro(_), _) => return Err(QrError::UnsupportedCharacterSet), - (_, ExtendedMode::Data(Mode::Numeric)) => 0b0001, - (_, ExtendedMode::Data(Mode::Alphanumeric)) => 0b0010, - (_, ExtendedMode::Data(Mode::Byte)) => 0b0100, - (_, ExtendedMode::Data(Mode::Kanji)) => 0b1000, - (_, ExtendedMode::Eci) => 0b0111, - (_, ExtendedMode::Fnc1First) => 0b0101, - (_, ExtendedMode::Fnc1Second) => 0b1001, - (_, ExtendedMode::StructuredAppend) => 0b0011, - }; - let bits = self.version.mode_bits_count(); - self.push_number_checked(bits, number).or(Err(QrError::UnsupportedCharacterSet)) - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ ECI - -impl Bits { - /// Push an ECI (Extended Channel Interpretation) designator to the bits. - /// - /// An ECI designator is a 6-digit number to specify the character set of - /// the following binary data. After calling this method, one could call - /// `.push_byte_data()` or similar methods to insert the actual data, e.g. - /// - /// #![allow(unused_must_use)] - /// - /// use qrcode::bits::Bits; - /// use qrcode::types::Version; - /// - /// let mut bits = Bits::new(Version::Normal(1)); - /// bits.push_eci_designator(9); // 9 = ISO-8859-7 (Greek). - /// bits.push_byte_data(b"\xa1\xa2\xa3\xa4\xa5"); // ΑΒΓΔΕ - /// - /// - /// The full list of ECI designator values can be found from - /// <http://strokescribe.com/en/ECI.html>. Some example values are: - /// - /// ECI # | Character set - /// ------|------------------------------------- - /// 3 | ISO-8859-1 (Western European) - /// 20 | Shift JIS (Japanese) - /// 23 | Windows 1252 (Latin 1) (Western European) - /// 25 | UTF-16 Big Endian - /// 26 | UTF-8 - /// 28 | Big 5 (Traditional Chinese) - /// 29 | GB-18030 (Simplified Chinese) - /// 30 | EUC-KR (Korean) - /// - /// # Errors - /// - /// If the QR code version does not support ECI, this method will return - /// `Err(QrError::UnsupportedCharacterSet)`. - /// - /// If the designator is outside of the expected range, this method will - /// return `Err(QrError::InvalidECIDesignator)`. - pub fn push_eci_designator(&mut self, eci_designator: u32) -> QrResult<()> { - self.reserve(12); // assume the common case that eci_designator <= 127. - self.push_mode_indicator(ExtendedMode::Eci)?; - match eci_designator { - 0..=127 => { - self.push_number(8, eci_designator.as_u16()); - } - 128..=16383 => { - self.push_number(2, 0b10); - self.push_number(14, eci_designator.as_u16()); - } - 16384..=999_999 => { - self.push_number(3, 0b110); - self.push_number(5, (eci_designator >> 16).as_u16()); - self.push_number(16, (eci_designator & 0xffff).as_u16()); - } - _ => return Err(QrError::InvalidEciDesignator), - } - Ok(()) - } -} - -#[cfg(test)] -mod eci_tests { - use crate::bits::Bits; - use crate::types::{QrError, Version}; - - #[test] - fn test_9() { - let mut bits = Bits::new(Version::Normal(1)); - assert_eq!(bits.push_eci_designator(9), Ok(())); - assert_eq!(bits.into_bytes(), vec![0b0111_0000, 0b1001_0000]); - } - - #[test] - fn test_899() { - let mut bits = Bits::new(Version::Normal(1)); - assert_eq!(bits.push_eci_designator(899), Ok(())); - assert_eq!(bits.into_bytes(), vec![0b0111_1000, 0b00111000, 0b0011_0000]); - } - - #[test] - fn test_999999() { - let mut bits = Bits::new(Version::Normal(1)); - assert_eq!(bits.push_eci_designator(999999), Ok(())); - assert_eq!(bits.into_bytes(), vec![0b0111_1100, 0b11110100, 0b00100011, 0b1111_0000]); - } - - #[test] - fn test_invalid_designator() { - let mut bits = Bits::new(Version::Normal(1)); - assert_eq!(bits.push_eci_designator(1000000), Err(QrError::InvalidEciDesignator)); - } - - #[test] - fn test_unsupported_character_set() { - let mut bits = Bits::new(Version::Micro(4)); - assert_eq!(bits.push_eci_designator(9), Err(QrError::UnsupportedCharacterSet)); - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Mode::Numeric mode - -impl Bits { - fn push_header(&mut self, mode: Mode, raw_data_len: usize) -> QrResult<()> { - let length_bits = mode.length_bits_count(self.version); - self.reserve(length_bits + 4 + mode.data_bits_count(raw_data_len)); - self.push_mode_indicator(ExtendedMode::Data(mode))?; - self.push_number_checked(length_bits, raw_data_len)?; - Ok(()) - } - - /// Encodes a numeric string to the bits. - /// - /// The data should only contain the characters 0 to 9. - /// - /// # Errors - /// - /// Returns `Err(QrError::DataTooLong)` on overflow. - pub fn push_numeric_data(&mut self, data: &[u8]) -> QrResult<()> { - self.push_header(Mode::Numeric, data.len())?; - for chunk in data.chunks(3) { - let number = chunk.iter().map(|b| u16::from(*b - b'0')).fold(0, |a, b| a * 10 + b); - let length = chunk.len() * 3 + 1; - self.push_number(length, number); - } - Ok(()) - } -} - -#[cfg(test)] -mod numeric_tests { - use crate::bits::Bits; - use crate::types::{QrError, Version}; - - #[test] - fn test_iso_18004_2006_example_1() { - let mut bits = Bits::new(Version::Normal(1)); - assert_eq!(bits.push_numeric_data(b"01234567"), Ok(())); - assert_eq!(bits.into_bytes(), vec![0b0001_0000, 0b001000_00, 0b00001100, 0b01010110, 0b0110_0001, 0b1000_0000]); - } - - #[test] - fn test_iso_18004_2000_example_2() { - let mut bits = Bits::new(Version::Normal(1)); - assert_eq!(bits.push_numeric_data(b"0123456789012345"), Ok(())); - assert_eq!( - bits.into_bytes(), - vec![ - 0b0001_0000, - 0b010000_00, - 0b00001100, - 0b01010110, - 0b0110_1010, - 0b0110_1110, - 0b000101_00, - 0b11101010, - 0b0101_0000, - ] - ); - } - - #[test] - fn test_iso_18004_2006_example_2() { - let mut bits = Bits::new(Version::Micro(3)); - assert_eq!(bits.push_numeric_data(b"0123456789012345"), Ok(())); - assert_eq!( - bits.into_bytes(), - vec![0b0010_0000, 0b00000110, 0b0010_1011, 0b0011_0101, 0b0011_0111, 0b0000_1010, 0b01110101, 0b0010_1000,] - ); - } - - #[test] - fn test_data_too_long_error() { - let mut bits = Bits::new(Version::Micro(1)); - assert_eq!(bits.push_numeric_data(b"12345678"), Err(QrError::DataTooLong)); - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Mode::Alphanumeric mode - -/// In QR code `Mode::Alphanumeric` mode, a pair of alphanumeric characters will -/// be encoded as a base-45 integer. `alphanumeric_digit` converts each -/// character into its corresponding base-45 digit. -/// -/// The conversion is specified in ISO/IEC 18004:2006, §8.4.3, Table 5. -#[inline] -fn alphanumeric_digit(character: u8) -> u16 { - match character { - b'0'..=b'9' => u16::from(character - b'0'), - b'A'..=b'Z' => u16::from(character - b'A') + 10, - b' ' => 36, - b'$' => 37, - b'%' => 38, - b'*' => 39, - b'+' => 40, - b'-' => 41, - b'.' => 42, - b'/' => 43, - b':' => 44, - _ => 0, - } -} - -impl Bits { - /// Encodes an alphanumeric string to the bits. - /// - /// The data should only contain the charaters A to Z (excluding lowercase), - /// 0 to 9, space, `$`, `%`, `*`, `+`, `-`, `.`, `/` or `:`. - /// - /// # Errors - /// - /// Returns `Err(QrError::DataTooLong)` on overflow. - pub fn push_alphanumeric_data(&mut self, data: &[u8]) -> QrResult<()> { - self.push_header(Mode::Alphanumeric, data.len())?; - for chunk in data.chunks(2) { - let number = chunk.iter().map(|b| alphanumeric_digit(*b)).fold(0, |a, b| a * 45 + b); - let length = chunk.len() * 5 + 1; - self.push_number(length, number); - } - Ok(()) - } -} - -#[cfg(test)] -mod alphanumeric_tests { - use crate::bits::Bits; - use crate::types::{QrError, Version}; - - #[test] - fn test_iso_18004_2006_example() { - let mut bits = Bits::new(Version::Normal(1)); - assert_eq!(bits.push_alphanumeric_data(b"AC-42"), Ok(())); - assert_eq!(bits.into_bytes(), vec![0b0010_0000, 0b0010_1001, 0b11001110, 0b11100111, 0b0010_0001, 0b0000_0000]); - } - - #[test] - fn test_micro_qr_unsupported() { - let mut bits = Bits::new(Version::Micro(1)); - assert_eq!(bits.push_alphanumeric_data(b"A"), Err(QrError::UnsupportedCharacterSet)); - } - - #[test] - fn test_data_too_long() { - let mut bits = Bits::new(Version::Micro(2)); - assert_eq!(bits.push_alphanumeric_data(b"ABCDEFGH"), Err(QrError::DataTooLong)); - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Mode::Byte mode - -impl Bits { - /// Encodes 8-bit byte data to the bits. - /// - /// # Errors - /// - /// Returns `Err(QrError::DataTooLong)` on overflow. - pub fn push_byte_data(&mut self, data: &[u8]) -> QrResult<()> { - self.push_header(Mode::Byte, data.len())?; - for b in data { - self.push_number(8, u16::from(*b)); - } - Ok(()) - } -} - -#[cfg(test)] -mod byte_tests { - use crate::bits::Bits; - use crate::types::{QrError, Version}; - - #[test] - fn test() { - let mut bits = Bits::new(Version::Normal(1)); - assert_eq!(bits.push_byte_data(b"\x12\x34\x56\x78\x9a\xbc\xde\xf0"), Ok(())); - assert_eq!( - bits.into_bytes(), - vec![ - 0b0100_0000, - 0b1000_0001, - 0b0010_0011, - 0b0100_0101, - 0b0110_0111, - 0b1000_1001, - 0b1010_1011, - 0b1100_1101, - 0b1110_1111, - 0b0000_0000, - ] - ); - } - - #[test] - fn test_micro_qr_unsupported() { - let mut bits = Bits::new(Version::Micro(2)); - assert_eq!(bits.push_byte_data(b"?"), Err(QrError::UnsupportedCharacterSet)); - } - - #[test] - fn test_data_too_long() { - let mut bits = Bits::new(Version::Micro(3)); - assert_eq!(bits.push_byte_data(b"0123456701234567"), Err(QrError::DataTooLong)); - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Mode::Kanji mode - -impl Bits { - /// Encodes Shift JIS double-byte data to the bits. - /// - /// # Errors - /// - /// Returns `Err(QrError::DataTooLong)` on overflow. - /// - /// Returns `Err(QrError::InvalidCharacter)` if the data is not Shift JIS - /// double-byte data (e.g. if the length of data is not an even number). - pub fn push_kanji_data(&mut self, data: &[u8]) -> QrResult<()> { - self.push_header(Mode::Kanji, data.len() / 2)?; - for kanji in data.chunks(2) { - if kanji.len() != 2 { - return Err(QrError::InvalidCharacter); - } - let cp = u16::from(kanji[0]) * 256 + u16::from(kanji[1]); - let bytes = if cp < 0xe040 { cp - 0x8140 } else { cp - 0xc140 }; - let number = (bytes >> 8) * 0xc0 + (bytes & 0xff); - self.push_number(13, number); - } - Ok(()) - } -} - -#[cfg(test)] -mod kanji_tests { - use crate::bits::Bits; - use crate::types::{QrError, Version}; - - #[test] - fn test_iso_18004_example() { - let mut bits = Bits::new(Version::Normal(1)); - assert_eq!(bits.push_kanji_data(b"\x93\x5f\xe4\xaa"), Ok(())); - assert_eq!(bits.into_bytes(), vec![0b1000_0000, 0b0010_0110, 0b11001111, 0b1110_1010, 0b1010_1000]); - } - - #[test] - fn test_micro_qr_unsupported() { - let mut bits = Bits::new(Version::Micro(2)); - assert_eq!(bits.push_kanji_data(b"?"), Err(QrError::UnsupportedCharacterSet)); - } - - #[test] - fn test_data_too_long() { - let mut bits = Bits::new(Version::Micro(3)); - assert_eq!(bits.push_kanji_data(b"\x93_\x93_\x93_\x93_\x93_\x93_\x93_\x93_"), Err(QrError::DataTooLong)); - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ FNC1 mode - -impl Bits { - /// Encodes an indicator that the following data are formatted according to - /// the UCC/EAN Application Identifiers standard. - /// - /// #![allow(unused_must_use)] - /// - /// use qrcode::bits::Bits; - /// use qrcode::types::Version; - /// - /// let mut bits = Bits::new(Version::Normal(1)); - /// bits.push_fnc1_first_position(); - /// bits.push_numeric_data(b"01049123451234591597033130128"); - /// bits.push_alphanumeric_data(b"%10ABC123"); - /// - /// In QR code, the character `%` is used as the data field separator (0x1D). - /// - /// # Errors - /// - /// If the mode is not supported in the provided version, this method - /// returns `Err(QrError::UnsupportedCharacterSet)`. - pub fn push_fnc1_first_position(&mut self) -> QrResult<()> { - self.push_mode_indicator(ExtendedMode::Fnc1First) - } - - /// Encodes an indicator that the following data are formatted in accordance - /// with specific industry or application specifications previously agreed - /// with AIM International. - /// - /// #![allow(unused_must_use)] - /// - /// use qrcode::bits::Bits; - /// use qrcode::types::Version; - /// - /// let mut bits = Bits::new(Version::Normal(1)); - /// bits.push_fnc1_second_position(37); - /// bits.push_alphanumeric_data(b"AA1234BBB112"); - /// bits.push_byte_data(b"text text text text\r"); - /// - /// If the application indicator is a single Latin alphabet (a–z / A–Z), - /// please pass in its ASCII value + 100: - /// - /// ```ignore - /// bits.push_fnc1_second_position(b'A' + 100); - /// ``` - /// - /// # Errors - /// - /// If the mode is not supported in the provided version, this method - /// returns `Err(QrError::UnsupportedCharacterSet)`. - pub fn push_fnc1_second_position(&mut self, application_indicator: u8) -> QrResult<()> { - self.push_mode_indicator(ExtendedMode::Fnc1Second)?; - self.push_number(8, u16::from(application_indicator)); - Ok(()) - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Finish - -// This table is copied from ISO/IEC 18004:2006 §6.4.10, Table 7. -static DATA_LENGTHS: [[usize; 4]; 44] = [ - // Normal versions - [152, 128, 104, 72], - [272, 224, 176, 128], - [440, 352, 272, 208], - [640, 512, 384, 288], - [864, 688, 496, 368], - [1088, 864, 608, 480], - [1248, 992, 704, 528], - [1552, 1232, 880, 688], - [1856, 1456, 1056, 800], - [2192, 1728, 1232, 976], - [2592, 2032, 1440, 1120], - [2960, 2320, 1648, 1264], - [3424, 2672, 1952, 1440], - [3688, 2920, 2088, 1576], - [4184, 3320, 2360, 1784], - [4712, 3624, 2600, 2024], - [5176, 4056, 2936, 2264], - [5768, 4504, 3176, 2504], - [6360, 5016, 3560, 2728], - [6888, 5352, 3880, 3080], - [7456, 5712, 4096, 3248], - [8048, 6256, 4544, 3536], - [8752, 6880, 4912, 3712], - [9392, 7312, 5312, 4112], - [10208, 8000, 5744, 4304], - [10960, 8496, 6032, 4768], - [11744, 9024, 6464, 5024], - [12248, 9544, 6968, 5288], - [13048, 10136, 7288, 5608], - [13880, 10984, 7880, 5960], - [14744, 11640, 8264, 6344], - [15640, 12328, 8920, 6760], - [16568, 13048, 9368, 7208], - [17528, 13800, 9848, 7688], - [18448, 14496, 10288, 7888], - [19472, 15312, 10832, 8432], - [20528, 15936, 11408, 8768], - [21616, 16816, 12016, 9136], - [22496, 17728, 12656, 9776], - [23648, 18672, 13328, 10208], - // Micro versions - [20, 0, 0, 0], - [40, 32, 0, 0], - [84, 68, 0, 0], - [128, 112, 80, 0], -]; - -impl Bits { - /// Pushes the ending bits to indicate no more data. - /// - /// # Errors - /// - /// Returns `Err(QrError::DataTooLong)` on overflow. - /// - /// Returns `Err(QrError::InvalidVersion)` if it is not valid to use the - /// `ec_level` for the given version (e.g. `Version::Micro(1)` with - /// `EcLevel::H`). - pub fn push_terminator(&mut self, ec_level: EcLevel) -> QrResult<()> { - let terminator_size = match self.version { - Version::Micro(a) => a.as_usize() * 2 + 1, - _ => 4, - }; - - let cur_length = self.len(); - let data_length = self.max_len(ec_level)?; - if cur_length > data_length { - return Err(QrError::DataTooLong); - } - - let terminator_size = min(terminator_size, data_length - cur_length); - if terminator_size > 0 { - self.push_number(terminator_size, 0); - } - - if self.len() < data_length { - const PADDING_BYTES: &[u8] = &[0b1110_1100, 0b0001_0001]; - - self.bit_offset = 0; - let data_bytes_length = data_length / 8; - let padding_bytes_count = data_bytes_length - self.data.len(); - let padding = PADDING_BYTES.iter().cloned().cycle().take(padding_bytes_count); - self.data.extend(padding); - } - - if self.len() < data_length { - self.data.push(0); - } - - Ok(()) - } -} - -#[cfg(test)] -mod finish_tests { - use crate::bits::Bits; - use crate::types::{EcLevel, QrError, Version}; - - #[test] - fn test_hello_world() { - let mut bits = Bits::new(Version::Normal(1)); - assert_eq!(bits.push_alphanumeric_data(b"HELLO WORLD"), Ok(())); - assert_eq!(bits.push_terminator(EcLevel::Q), Ok(())); - assert_eq!( - bits.into_bytes(), - vec![ - 0b00100000, 0b01011011, 0b00001011, 0b01111000, 0b11010001, 0b01110010, 0b11011100, 0b01001101, - 0b01000011, 0b01000000, 0b11101100, 0b00010001, 0b11101100, - ] - ); - } - - #[test] - fn test_too_long() { - let mut bits = Bits::new(Version::Micro(1)); - assert_eq!(bits.push_numeric_data(b"9999999"), Ok(())); - assert_eq!(bits.push_terminator(EcLevel::L), Err(QrError::DataTooLong)); - } - - #[test] - fn test_no_terminator() { - let mut bits = Bits::new(Version::Micro(1)); - assert_eq!(bits.push_numeric_data(b"99999"), Ok(())); - assert_eq!(bits.push_terminator(EcLevel::L), Ok(())); - assert_eq!(bits.into_bytes(), vec![0b1011_1111, 0b0011_1110, 0b0011_0000]); - } - - #[test] - fn test_no_padding() { - let mut bits = Bits::new(Version::Micro(1)); - assert_eq!(bits.push_numeric_data(b"9999"), Ok(())); - assert_eq!(bits.push_terminator(EcLevel::L), Ok(())); - assert_eq!(bits.into_bytes(), vec![0b1001_1111, 0b0011_1100, 0b1000_0000]); - } - - #[test] - fn test_micro_version_1_half_byte_padding() { - let mut bits = Bits::new(Version::Micro(1)); - assert_eq!(bits.push_numeric_data(b"999"), Ok(())); - assert_eq!(bits.push_terminator(EcLevel::L), Ok(())); - assert_eq!(bits.into_bytes(), vec![0b0111_1111, 0b0011_1000, 0b0000_0000]); - } - - #[test] - fn test_micro_version_1_full_byte_padding() { - let mut bits = Bits::new(Version::Micro(1)); - assert_eq!(bits.push_numeric_data(b""), Ok(())); - assert_eq!(bits.push_terminator(EcLevel::L), Ok(())); - assert_eq!(bits.into_bytes(), vec![0b0000_0000, 0b11101100, 0]); - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Front end. - -impl Bits { - /// Push a segmented data to the bits, and then terminate it. - /// - /// # Errors - /// - /// Returns `Err(QrError::DataTooLong)` on overflow. - /// - /// Returns `Err(QrError::InvalidData)` if the segment refers to incorrectly - /// encoded byte sequence. - pub fn push_segments<I>(&mut self, data: &[u8], segments_iter: I) -> QrResult<()> - where - I: Iterator<Item = Segment>, - { - for segment in segments_iter { - let slice = &data[segment.begin..segment.end]; - match segment.mode { - Mode::Numeric => self.push_numeric_data(slice), - Mode::Alphanumeric => self.push_alphanumeric_data(slice), - Mode::Byte => self.push_byte_data(slice), - Mode::Kanji => self.push_kanji_data(slice), - }?; - } - Ok(()) - } - - /// Pushes the data the bits, using the optimal encoding. - /// - /// # Errors - /// - /// Returns `Err(QrError::DataTooLong)` on overflow. - pub fn push_optimal_data(&mut self, data: &[u8]) -> QrResult<()> { - let segments = Parser::new(data).optimize(self.version); - self.push_segments(data, segments) - } -} - -#[cfg(test)] -mod encode_tests { - use alloc::vec::Vec; - - use crate::bits::Bits; - use crate::types::{EcLevel, QrError, QrResult, Version}; - - fn encode(data: &[u8], version: Version, ec_level: EcLevel) -> QrResult<Vec<u8>> { - let mut bits = Bits::new(version); - bits.push_optimal_data(data)?; - bits.push_terminator(ec_level)?; - Ok(bits.into_bytes()) - } - - #[test] - fn test_alphanumeric() { - let res = encode(b"HELLO WORLD", Version::Normal(1), EcLevel::Q); - assert_eq!( - res, - Ok(vec![ - 0b00100000, 0b01011011, 0b00001011, 0b01111000, 0b11010001, 0b01110010, 0b11011100, 0b01001101, - 0b01000011, 0b01000000, 0b11101100, 0b00010001, 0b11101100, - ]) - ); - } - - #[test] - fn test_auto_mode_switch() { - let res = encode(b"123A", Version::Micro(2), EcLevel::L); - assert_eq!(res, Ok(vec![0b0001_1000, 0b1111_0111, 0b0010_0101, 0b0000_0000, 0b11101100])); - } - - #[test] - fn test_too_long() { - let res = encode(b">>>>>>>>", Version::Normal(1), EcLevel::H); - assert_eq!(res, Err(QrError::DataTooLong)); - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Auto version minimization - -/// Automatically determines the minimum version to store the data, and encode -/// the result. -/// -/// This method will not consider any Micro QR code versions. -/// -/// # Errors -/// -/// Returns `Err(QrError::DataTooLong)` if the data is too long to fit even the -/// highest QR code version. -pub fn encode_auto(data: &[u8], ec_level: EcLevel) -> QrResult<Bits> { - let segments = Parser::new(data).collect::<Vec<Segment>>(); - for version in &[Version::Normal(9), Version::Normal(26), Version::Normal(40)] { - let opt_segments = Optimizer::new(segments.iter().cloned(), *version).collect::<Vec<_>>(); - let total_len = total_encoded_len(&opt_segments, *version); - let data_capacity = version.fetch(ec_level, &DATA_LENGTHS).expect("invalid DATA_LENGTHS"); - if total_len <= data_capacity { - let min_version = find_min_version(total_len, ec_level); - let mut bits = Bits::new(min_version); - bits.reserve(total_len); - bits.push_segments(data, opt_segments.into_iter())?; - bits.push_terminator(ec_level)?; - return Ok(bits); - } - } - Err(QrError::DataTooLong) -} - -/// Finds the smallest version (QR code only) that can store N bits of data -/// in the given error correction level. -fn find_min_version(length: usize, ec_level: EcLevel) -> Version { - let mut base = 0_usize; - let mut size = 39; - while size > 1 { - let half = size / 2; - let mid = base + half; - // mid is always in [0, size). - // mid >= 0: by definition - // mid < size: mid = size / 2 + size / 4 + size / 8 ... - base = if DATA_LENGTHS[mid][ec_level as usize] > length { base } else { mid }; - size -= half; - } - // base is always in [0, mid) because base <= mid. - base = if DATA_LENGTHS[base][ec_level as usize] >= length { base } else { base + 1 }; - Version::Normal((base + 1).as_i16()) -} - -#[cfg(test)] -mod encode_auto_tests { - use crate::bits::{encode_auto, find_min_version}; - use crate::types::{EcLevel, Version}; - - #[test] - fn test_find_min_version() { - assert_eq!(find_min_version(60, EcLevel::L), Version::Normal(1)); - assert_eq!(find_min_version(200, EcLevel::L), Version::Normal(2)); - assert_eq!(find_min_version(200, EcLevel::H), Version::Normal(3)); - assert_eq!(find_min_version(20000, EcLevel::L), Version::Normal(37)); - assert_eq!(find_min_version(640, EcLevel::L), Version::Normal(4)); - assert_eq!(find_min_version(641, EcLevel::L), Version::Normal(5)); - assert_eq!(find_min_version(999999, EcLevel::H), Version::Normal(40)); - } - - #[test] - fn test_alpha_q() { - let bits = encode_auto(b"HELLO WORLD", EcLevel::Q).unwrap(); - assert_eq!(bits.version(), Version::Normal(1)); - } - - #[test] - fn test_alpha_h() { - let bits = encode_auto(b"HELLO WORLD", EcLevel::H).unwrap(); - assert_eq!(bits.version(), Version::Normal(2)); - } - - #[test] - fn test_mixed() { - let bits = encode_auto(b"This is a mixed data test. 1234567890", EcLevel::H).unwrap(); - assert_eq!(bits.version(), Version::Normal(4)); - } -} - -#[cfg(feature = "bench")] -#[bench] -fn bench_find_min_version(bencher: &mut test::Bencher) { - use test::black_box; - - bencher.iter(|| { - black_box(find_min_version(60, EcLevel::L)); - black_box(find_min_version(200, EcLevel::L)); - black_box(find_min_version(200, EcLevel::H)); - black_box(find_min_version(20000, EcLevel::L)); - black_box(find_min_version(640, EcLevel::L)); - black_box(find_min_version(641, EcLevel::L)); - black_box(find_min_version(999999, EcLevel::H)); - }) -} - -//}}} -//------------------------------------------------------------------------------ diff --git a/qrcode-rust/src/canvas.rs b/qrcode-rust/src/canvas.rs deleted file mode 100644 index 0e974ce..0000000 --- a/qrcode-rust/src/canvas.rs +++ /dev/null @@ -1,2010 +0,0 @@ -//! The `canvas` module puts raw bits into the QR code canvas. -//! -//! use qrcode::types::{Version, EcLevel}; -//! use qrcode::canvas::{Canvas, MaskPattern}; -//! -//! let mut c = Canvas::new(Version::Normal(1), EcLevel::L); -//! c.draw_all_functional_patterns(); -//! c.draw_data(b"data_here", b"ec_code_here"); -//! c.apply_mask(MaskPattern::Checkerboard); -//! let bools = c.to_bools(); - -use core::cmp::max; - -use alloc::boxed::Box; -use alloc::vec::Vec; - -use crate::cast::As; -use crate::types::{Color, EcLevel, Version}; - -//------------------------------------------------------------------------------ -//{{{ Modules - -/// The color of a module (pixel) in the QR code. -#[derive(PartialEq, Eq, Clone, Copy, Debug)] -pub enum Module { - /// The module is empty. - Empty, - - /// The module is of functional patterns which cannot be masked, or pixels - /// which have been masked. - Masked(Color), - - /// The module is of data and error correction bits before masking. - Unmasked(Color), -} - -impl From<Module> for Color { - fn from(module: Module) -> Self { - match module { - Module::Empty => Color::Light, - Module::Masked(c) | Module::Unmasked(c) => c, - } - } -} - -impl Module { - /// Checks whether a module is dark. - pub fn is_dark(self) -> bool { - Color::from(self) == Color::Dark - } - - /// Apply a mask to the unmasked modules. - /// - /// use qrcode::canvas::Module; - /// use qrcode::types::Color; - /// - /// assert_eq!(Module::Unmasked(Color::Light).mask(true), Module::Masked(Color::Dark)); - /// assert_eq!(Module::Unmasked(Color::Dark).mask(true), Module::Masked(Color::Light)); - /// assert_eq!(Module::Unmasked(Color::Light).mask(false), Module::Masked(Color::Light)); - /// assert_eq!(Module::Masked(Color::Dark).mask(true), Module::Masked(Color::Dark)); - /// assert_eq!(Module::Masked(Color::Dark).mask(false), Module::Masked(Color::Dark)); - /// - pub fn mask(self, should_invert: bool) -> Self { - match (self, should_invert) { - (Module::Empty, true) => Module::Masked(Color::Dark), - (Module::Empty, false) => Module::Masked(Color::Light), - (Module::Unmasked(c), true) => Module::Masked(!c), - (Module::Unmasked(c), false) | (Module::Masked(c), _) => Module::Masked(c), - } - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Canvas - -/// `Canvas` is an intermediate helper structure to render error-corrected data -/// into a QR code. -#[derive(Clone)] -pub struct Canvas { - /// The width and height of the canvas (cached as it is needed frequently). - width: i16, - - /// The version of the QR code. - version: Version, - - /// The error correction level of the QR code. - ec_level: EcLevel, - - /// The modules of the QR code. Modules are arranged in left-to-right, then - /// top-to-bottom order. - modules: Vec<Module>, -} - -#[cfg(test)] -use alloc::string::String; - -impl Canvas { - /// Constructs a new canvas big enough for a QR code of the given version. - pub fn new(version: Version, ec_level: EcLevel) -> Self { - let width = version.width(); - Self { width, version, ec_level, modules: vec![Module::Empty; (width * width).as_usize()] } - } - - /// Converts the canvas into a human-readable string. - #[cfg(test)] - - fn to_debug_str(&self) -> String { - let width = self.width; - let mut res = String::with_capacity((width * (width + 1)) as usize); - for y in 0..width { - res.push('\n'); - for x in 0..width { - res.push(match self.get(x, y) { - Module::Empty => '?', - Module::Masked(Color::Light) => '.', - Module::Masked(Color::Dark) => '#', - Module::Unmasked(Color::Light) => '-', - Module::Unmasked(Color::Dark) => '*', - }); - } - } - res - } - - fn coords_to_index(&self, x: i16, y: i16) -> usize { - let x = if x < 0 { x + self.width } else { x }.as_usize(); - let y = if y < 0 { y + self.width } else { y }.as_usize(); - y * self.width.as_usize() + x - } - - /// Obtains a module at the given coordinates. For convenience, negative - /// coordinates will wrap around. - pub fn get(&self, x: i16, y: i16) -> Module { - self.modules[self.coords_to_index(x, y)] - } - - /// Obtains a mutable module at the given coordinates. For convenience, - /// negative coordinates will wrap around. - pub fn get_mut(&mut self, x: i16, y: i16) -> &mut Module { - let index = self.coords_to_index(x, y); - &mut self.modules[index] - } - - /// Sets the color of a functional module at the given coordinates. For - /// convenience, negative coordinates will wrap around. - pub fn put(&mut self, x: i16, y: i16, color: Color) { - *self.get_mut(x, y) = Module::Masked(color); - } -} - -#[cfg(test)] -mod basic_canvas_tests { - use crate::canvas::{Canvas, Module}; - use crate::types::{Color, EcLevel, Version}; - - #[test] - fn test_index() { - let mut c = Canvas::new(Version::Normal(1), EcLevel::L); - - assert_eq!(c.get(0, 4), Module::Empty); - assert_eq!(c.get(-1, -7), Module::Empty); - assert_eq!(c.get(21 - 1, 21 - 7), Module::Empty); - - c.put(0, 0, Color::Dark); - c.put(-1, -7, Color::Light); - assert_eq!(c.get(0, 0), Module::Masked(Color::Dark)); - assert_eq!(c.get(21 - 1, -7), Module::Masked(Color::Light)); - assert_eq!(c.get(-1, 21 - 7), Module::Masked(Color::Light)); - } - - #[test] - fn test_debug_str() { - let mut c = Canvas::new(Version::Normal(1), EcLevel::L); - - for i in 3_i16..20 { - for j in 3_i16..20 { - *c.get_mut(i, j) = match ((i * 3) ^ j) % 5 { - 0 => Module::Empty, - 1 => Module::Masked(Color::Light), - 2 => Module::Masked(Color::Dark), - 3 => Module::Unmasked(Color::Light), - 4 => Module::Unmasked(Color::Dark), - _ => unreachable!(), - }; - } - } - - assert_eq!( - &*c.to_debug_str(), - "\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????####****....---?\n\ - ???--.##-..##?..#??.?\n\ - ???#*?-.*?#.-*#?-*.??\n\ - ?????*?*?****-*-*---?\n\ - ???*.-.-.-?-?#?#?#*#?\n\ - ???.*#.*.*#.*#*#.*#*?\n\ - ?????.#-#--??.?.#---?\n\ - ???-.?*.-#?-.?#*-#?.?\n\ - ???##*??*..##*--*..??\n\ - ?????-???--??---?---?\n\ - ???*.#.*.#**.#*#.#*#?\n\ - ???##.-##..##..?#..??\n\ - ???.-?*.-?#.-?#*-?#*?\n\ - ????-.#?-.**#?-.#?-.?\n\ - ???**?-**??--**?-**??\n\ - ???#?*?#?*#.*-.-*-.-?\n\ - ???..-...--??###?###?\n\ - ?????????????????????" - ); - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Finder patterns - -impl Canvas { - /// Draws a single finder pattern with the center at (x, y). - fn draw_finder_pattern_at(&mut self, x: i16, y: i16) { - let (dx_left, dx_right) = if x >= 0 { (-3, 4) } else { (-4, 3) }; - let (dy_top, dy_bottom) = if y >= 0 { (-3, 4) } else { (-4, 3) }; - for j in dy_top..=dy_bottom { - for i in dx_left..=dx_right { - self.put( - x + i, - y + j, - #[allow(clippy::match_same_arms)] - match (i, j) { - (4, _) | (_, 4) | (-4, _) | (_, -4) => Color::Light, - (3, _) | (_, 3) | (-3, _) | (_, -3) => Color::Dark, - (2, _) | (_, 2) | (-2, _) | (_, -2) => Color::Light, - _ => Color::Dark, - }, - ); - } - } - } - - /// Draws the finder patterns. - /// - /// The finder patterns is are 7×7 square patterns appearing at the three - /// corners of a QR code. They allows scanner to locate the QR code and - /// determine the orientation. - fn draw_finder_patterns(&mut self) { - self.draw_finder_pattern_at(3, 3); - - match self.version { - Version::Micro(_) => {} - Version::Normal(_) => { - self.draw_finder_pattern_at(-4, 3); - self.draw_finder_pattern_at(3, -4); - } - } - } -} - -#[cfg(test)] -mod finder_pattern_tests { - use crate::canvas::Canvas; - use crate::types::{EcLevel, Version}; - - #[test] - fn test_qr() { - let mut c = Canvas::new(Version::Normal(1), EcLevel::L); - c.draw_finder_patterns(); - assert_eq!( - &*c.to_debug_str(), - "\n\ - #######.?????.#######\n\ - #.....#.?????.#.....#\n\ - #.###.#.?????.#.###.#\n\ - #.###.#.?????.#.###.#\n\ - #.###.#.?????.#.###.#\n\ - #.....#.?????.#.....#\n\ - #######.?????.#######\n\ - ........?????........\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ........?????????????\n\ - #######.?????????????\n\ - #.....#.?????????????\n\ - #.###.#.?????????????\n\ - #.###.#.?????????????\n\ - #.###.#.?????????????\n\ - #.....#.?????????????\n\ - #######.?????????????" - ); - } - - #[test] - fn test_micro_qr() { - let mut c = Canvas::new(Version::Micro(1), EcLevel::L); - c.draw_finder_patterns(); - assert_eq!( - &*c.to_debug_str(), - "\n\ - #######.???\n\ - #.....#.???\n\ - #.###.#.???\n\ - #.###.#.???\n\ - #.###.#.???\n\ - #.....#.???\n\ - #######.???\n\ - ........???\n\ - ???????????\n\ - ???????????\n\ - ???????????" - ); - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Alignment patterns - -impl Canvas { - /// Draws a alignment pattern with the center at (x, y). - fn draw_alignment_pattern_at(&mut self, x: i16, y: i16) { - if self.get(x, y) != Module::Empty { - return; - } - for j in -2..=2 { - for i in -2..=2 { - self.put( - x + i, - y + j, - match (i, j) { - (2, _) | (_, 2) | (-2, _) | (_, -2) | (0, 0) => Color::Dark, - _ => Color::Light, - }, - ); - } - } - } - - /// Draws the alignment patterns. - /// - /// The alignment patterns are 5×5 square patterns inside the QR code symbol - /// to help the scanner create the square grid. - fn draw_alignment_patterns(&mut self) { - match self.version { - Version::Micro(_) | Version::Normal(1) => {} - Version::Normal(2..=6) => self.draw_alignment_pattern_at(-7, -7), - Version::Normal(a) => { - let positions = ALIGNMENT_PATTERN_POSITIONS[(a - 7).as_usize()]; - for x in positions.iter() { - for y in positions.iter() { - self.draw_alignment_pattern_at(*x, *y); - } - } - } - } - } -} - -#[cfg(test)] -mod alignment_pattern_tests { - use crate::canvas::Canvas; - use crate::types::{EcLevel, Version}; - - #[test] - fn test_draw_alignment_patterns_1() { - let mut c = Canvas::new(Version::Normal(1), EcLevel::L); - c.draw_finder_patterns(); - c.draw_alignment_patterns(); - assert_eq!( - &*c.to_debug_str(), - "\n\ - #######.?????.#######\n\ - #.....#.?????.#.....#\n\ - #.###.#.?????.#.###.#\n\ - #.###.#.?????.#.###.#\n\ - #.###.#.?????.#.###.#\n\ - #.....#.?????.#.....#\n\ - #######.?????.#######\n\ - ........?????........\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ........?????????????\n\ - #######.?????????????\n\ - #.....#.?????????????\n\ - #.###.#.?????????????\n\ - #.###.#.?????????????\n\ - #.###.#.?????????????\n\ - #.....#.?????????????\n\ - #######.?????????????" - ); - } - - #[test] - fn test_draw_alignment_patterns_3() { - let mut c = Canvas::new(Version::Normal(3), EcLevel::L); - c.draw_finder_patterns(); - c.draw_alignment_patterns(); - assert_eq!( - &*c.to_debug_str(), - "\n\ - #######.?????????????.#######\n\ - #.....#.?????????????.#.....#\n\ - #.###.#.?????????????.#.###.#\n\ - #.###.#.?????????????.#.###.#\n\ - #.###.#.?????????????.#.###.#\n\ - #.....#.?????????????.#.....#\n\ - #######.?????????????.#######\n\ - ........?????????????........\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ????????????????????#####????\n\ - ........????????????#...#????\n\ - #######.????????????#.#.#????\n\ - #.....#.????????????#...#????\n\ - #.###.#.????????????#####????\n\ - #.###.#.?????????????????????\n\ - #.###.#.?????????????????????\n\ - #.....#.?????????????????????\n\ - #######.?????????????????????" - ); - } - - #[test] - fn test_draw_alignment_patterns_7() { - let mut c = Canvas::new(Version::Normal(7), EcLevel::L); - c.draw_finder_patterns(); - c.draw_alignment_patterns(); - assert_eq!( - &*c.to_debug_str(), - "\n\ - #######.?????????????????????????????.#######\n\ - #.....#.?????????????????????????????.#.....#\n\ - #.###.#.?????????????????????????????.#.###.#\n\ - #.###.#.?????????????????????????????.#.###.#\n\ - #.###.#.????????????#####????????????.#.###.#\n\ - #.....#.????????????#...#????????????.#.....#\n\ - #######.????????????#.#.#????????????.#######\n\ - ........????????????#...#????????????........\n\ - ????????????????????#####????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ????#####???????????#####???????????#####????\n\ - ????#...#???????????#...#???????????#...#????\n\ - ????#.#.#???????????#.#.#???????????#.#.#????\n\ - ????#...#???????????#...#???????????#...#????\n\ - ????#####???????????#####???????????#####????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ????????????????????#####???????????#####????\n\ - ........????????????#...#???????????#...#????\n\ - #######.????????????#.#.#???????????#.#.#????\n\ - #.....#.????????????#...#???????????#...#????\n\ - #.###.#.????????????#####???????????#####????\n\ - #.###.#.?????????????????????????????????????\n\ - #.###.#.?????????????????????????????????????\n\ - #.....#.?????????????????????????????????????\n\ - #######.?????????????????????????????????????" - ); - } -} - -/// `ALIGNMENT_PATTERN_POSITIONS` describes the x- and y-coordinates of the -/// center of the alignment patterns. Since the QR code is symmetric, only one -/// coordinate is needed. -static ALIGNMENT_PATTERN_POSITIONS: [&[i16]; 34] = [ - &[6, 22, 38], - &[6, 24, 42], - &[6, 26, 46], - &[6, 28, 50], - &[6, 30, 54], - &[6, 32, 58], - &[6, 34, 62], - &[6, 26, 46, 66], - &[6, 26, 48, 70], - &[6, 26, 50, 74], - &[6, 30, 54, 78], - &[6, 30, 56, 82], - &[6, 30, 58, 86], - &[6, 34, 62, 90], - &[6, 28, 50, 72, 94], - &[6, 26, 50, 74, 98], - &[6, 30, 54, 78, 102], - &[6, 28, 54, 80, 106], - &[6, 32, 58, 84, 110], - &[6, 30, 58, 86, 114], - &[6, 34, 62, 90, 118], - &[6, 26, 50, 74, 98, 122], - &[6, 30, 54, 78, 102, 126], - &[6, 26, 52, 78, 104, 130], - &[6, 30, 56, 82, 108, 134], - &[6, 34, 60, 86, 112, 138], - &[6, 30, 58, 86, 114, 142], - &[6, 34, 62, 90, 118, 146], - &[6, 30, 54, 78, 102, 126, 150], - &[6, 24, 50, 76, 102, 128, 154], - &[6, 28, 54, 80, 106, 132, 158], - &[6, 32, 58, 84, 110, 136, 162], - &[6, 26, 54, 82, 110, 138, 166], - &[6, 30, 58, 86, 114, 142, 170], -]; - -//}}} -//------------------------------------------------------------------------------ -//{{{ Timing patterns - -impl Canvas { - /// Draws a line from (x1, y1) to (x2, y2), inclusively. - /// - /// The line must be either horizontal or vertical, i.e. - /// `x1 == x2 || y1 == y2`. Additionally, the first coordinates must be less - /// then the second ones. - /// - /// On even coordinates, `color_even` will be plotted; on odd coordinates, - /// `color_odd` will be plotted instead. Thus the timing pattern can be - /// drawn using this method. - /// - fn draw_line(&mut self, x1: i16, y1: i16, x2: i16, y2: i16, color_even: Color, color_odd: Color) { - debug_assert!(x1 == x2 || y1 == y2); - - if y1 == y2 { - // Horizontal line. - for x in x1..=x2 { - self.put(x, y1, if x % 2 == 0 { color_even } else { color_odd }); - } - } else { - // Vertical line. - for y in y1..=y2 { - self.put(x1, y, if y % 2 == 0 { color_even } else { color_odd }); - } - } - } - - /// Draws the timing patterns. - /// - /// The timing patterns are checkboard-colored lines near the edge of the QR - /// code symbol, to establish the fine-grained module coordinates when - /// scanning. - fn draw_timing_patterns(&mut self) { - let width = self.width; - let (y, x1, x2) = match self.version { - Version::Micro(_) => (0, 8, width - 1), - Version::Normal(_) => (6, 8, width - 9), - }; - self.draw_line(x1, y, x2, y, Color::Dark, Color::Light); - self.draw_line(y, x1, y, x2, Color::Dark, Color::Light); - } -} - -#[cfg(test)] -mod timing_pattern_tests { - use crate::canvas::Canvas; - use crate::types::{EcLevel, Version}; - - #[test] - fn test_draw_timing_patterns_qr() { - let mut c = Canvas::new(Version::Normal(1), EcLevel::L); - c.draw_timing_patterns(); - assert_eq!( - &*c.to_debug_str(), - "\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ????????#.#.#????????\n\ - ?????????????????????\n\ - ??????#??????????????\n\ - ??????.??????????????\n\ - ??????#??????????????\n\ - ??????.??????????????\n\ - ??????#??????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????" - ); - } - - #[test] - fn test_draw_timing_patterns_micro_qr() { - let mut c = Canvas::new(Version::Micro(1), EcLevel::L); - c.draw_timing_patterns(); - assert_eq!( - &*c.to_debug_str(), - "\n\ - ????????#.#\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - #??????????\n\ - .??????????\n\ - #??????????" - ); - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Format info & Version info - -impl Canvas { - /// Draws a big-endian integer onto the canvas with the given coordinates. - /// - /// The 1 bits will be plotted with `on_color` and the 0 bits with - /// `off_color`. The coordinates will be extracted from the `coords` - /// iterator. It will start from the most significant bits first, so - /// *trailing* zeros will be ignored. - fn draw_number(&mut self, number: u32, bits: u32, on_color: Color, off_color: Color, coords: &[(i16, i16)]) { - let mut mask = 1 << (bits - 1); - for &(x, y) in coords { - let color = if (mask & number) == 0 { off_color } else { on_color }; - self.put(x, y, color); - mask >>= 1; - } - } - - /// Draws the format info patterns for an encoded number. - fn draw_format_info_patterns_with_number(&mut self, format_info: u16) { - let format_info = u32::from(format_info); - match self.version { - Version::Micro(_) => { - self.draw_number(format_info, 15, Color::Dark, Color::Light, &FORMAT_INFO_COORDS_MICRO_QR); - } - Version::Normal(_) => { - self.draw_number(format_info, 15, Color::Dark, Color::Light, &FORMAT_INFO_COORDS_QR_MAIN); - self.draw_number(format_info, 15, Color::Dark, Color::Light, &FORMAT_INFO_COORDS_QR_SIDE); - self.put(8, -8, Color::Dark); // Dark module. - } - } - } - - /// Reserves area to put in the format information. - fn draw_reserved_format_info_patterns(&mut self) { - self.draw_format_info_patterns_with_number(0); - } - - /// Draws the version information patterns. - fn draw_version_info_patterns(&mut self) { - match self.version { - Version::Micro(_) | Version::Normal(1..=6) => {} - Version::Normal(a) => { - let version_info = VERSION_INFOS[(a - 7).as_usize()]; - self.draw_number(version_info, 18, Color::Dark, Color::Light, &VERSION_INFO_COORDS_BL); - self.draw_number(version_info, 18, Color::Dark, Color::Light, &VERSION_INFO_COORDS_TR); - } - } - } -} - -#[cfg(test)] -mod draw_version_info_tests { - use crate::canvas::Canvas; - use crate::types::{Color, EcLevel, Version}; - - #[test] - fn test_draw_number() { - let mut c = Canvas::new(Version::Micro(1), EcLevel::L); - c.draw_number(0b10101101, 8, Color::Dark, Color::Light, &[(0, 0), (0, -1), (-2, -2), (-2, 0)]); - assert_eq!( - &*c.to_debug_str(), - "\n\ - #????????.?\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ?????????#?\n\ - .??????????" - ); - } - - #[test] - fn test_draw_version_info_1() { - let mut c = Canvas::new(Version::Normal(1), EcLevel::L); - c.draw_version_info_patterns(); - assert_eq!( - &*c.to_debug_str(), - "\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????" - ); - } - - #[test] - fn test_draw_version_info_7() { - let mut c = Canvas::new(Version::Normal(7), EcLevel::L); - c.draw_version_info_patterns(); - - assert_eq!( - &*c.to_debug_str(), - "\n\ - ??????????????????????????????????..#????????\n\ - ??????????????????????????????????.#.????????\n\ - ??????????????????????????????????.#.????????\n\ - ??????????????????????????????????.##????????\n\ - ??????????????????????????????????###????????\n\ - ??????????????????????????????????...????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ....#.???????????????????????????????????????\n\ - .####.???????????????????????????????????????\n\ - #..##.???????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????" - ); - } - - #[test] - fn test_draw_reserved_format_info_patterns_qr() { - let mut c = Canvas::new(Version::Normal(1), EcLevel::L); - c.draw_reserved_format_info_patterns(); - assert_eq!( - &*c.to_debug_str(), - "\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ?????????????????????\n\ - ????????.????????????\n\ - ......?..????........\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ????????#????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????.????????????" - ); - } - - #[test] - fn test_draw_reserved_format_info_patterns_micro_qr() { - let mut c = Canvas::new(Version::Micro(1), EcLevel::L); - c.draw_reserved_format_info_patterns(); - assert_eq!( - &*c.to_debug_str(), - "\n\ - ???????????\n\ - ????????.??\n\ - ????????.??\n\ - ????????.??\n\ - ????????.??\n\ - ????????.??\n\ - ????????.??\n\ - ????????.??\n\ - ?........??\n\ - ???????????\n\ - ???????????" - ); - } -} - -static VERSION_INFO_COORDS_BL: [(i16, i16); 18] = [ - (5, -9), - (5, -10), - (5, -11), - (4, -9), - (4, -10), - (4, -11), - (3, -9), - (3, -10), - (3, -11), - (2, -9), - (2, -10), - (2, -11), - (1, -9), - (1, -10), - (1, -11), - (0, -9), - (0, -10), - (0, -11), -]; - -static VERSION_INFO_COORDS_TR: [(i16, i16); 18] = [ - (-9, 5), - (-10, 5), - (-11, 5), - (-9, 4), - (-10, 4), - (-11, 4), - (-9, 3), - (-10, 3), - (-11, 3), - (-9, 2), - (-10, 2), - (-11, 2), - (-9, 1), - (-10, 1), - (-11, 1), - (-9, 0), - (-10, 0), - (-11, 0), -]; - -static FORMAT_INFO_COORDS_QR_MAIN: [(i16, i16); 15] = [ - (0, 8), - (1, 8), - (2, 8), - (3, 8), - (4, 8), - (5, 8), - (7, 8), - (8, 8), - (8, 7), - (8, 5), - (8, 4), - (8, 3), - (8, 2), - (8, 1), - (8, 0), -]; - -static FORMAT_INFO_COORDS_QR_SIDE: [(i16, i16); 15] = [ - (8, -1), - (8, -2), - (8, -3), - (8, -4), - (8, -5), - (8, -6), - (8, -7), - (-8, 8), - (-7, 8), - (-6, 8), - (-5, 8), - (-4, 8), - (-3, 8), - (-2, 8), - (-1, 8), -]; - -static FORMAT_INFO_COORDS_MICRO_QR: [(i16, i16); 15] = [ - (1, 8), - (2, 8), - (3, 8), - (4, 8), - (5, 8), - (6, 8), - (7, 8), - (8, 8), - (8, 7), - (8, 6), - (8, 5), - (8, 4), - (8, 3), - (8, 2), - (8, 1), -]; - -static VERSION_INFOS: [u32; 34] = [ - 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, 0x0f928, 0x10b78, 0x1145d, 0x12a17, - 0x13532, 0x149a6, 0x15683, 0x168c9, 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75, - 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64, 0x27541, 0x28c69, -]; - -//}}} -//------------------------------------------------------------------------------ -//{{{ All functional patterns before data placement - -impl Canvas { - /// Draw all functional patterns, before data placement. - /// - /// All functional patterns (e.g. the finder pattern) *except* the format - /// info pattern will be filled in. The format info pattern will be filled - /// with light modules instead. Data bits can then put in the empty modules. - /// with `.draw_data()`. - pub fn draw_all_functional_patterns(&mut self) { - self.draw_finder_patterns(); - self.draw_alignment_patterns(); - self.draw_reserved_format_info_patterns(); - self.draw_timing_patterns(); - self.draw_version_info_patterns(); - } -} - -/// Gets whether the module at the given coordinates represents a functional -/// module. -pub fn is_functional(version: Version, width: i16, x: i16, y: i16) -> bool { - debug_assert!(width == version.width()); - - let x = if x < 0 { x + width } else { x }; - let y = if y < 0 { y + width } else { y }; - - match version { - Version::Micro(_) => x == 0 || y == 0 || (x < 9 && y < 9), - Version::Normal(a) => { - let non_alignment_test = x == 6 || y == 6 || // Timing patterns - (x < 9 && y < 9) || // Top-left finder pattern - (x < 9 && y >= width-8) || // Bottom-left finder pattern - (x >= width-8 && y < 9); // Top-right finder pattern - if non_alignment_test { - true - } else if a == 1 { - false - } else if (2..=6).contains(&a) { - (width - 7 - x).abs() <= 2 && (width - 7 - y).abs() <= 2 - } else { - let positions = ALIGNMENT_PATTERN_POSITIONS[(a - 7).as_usize()]; - let last = positions.len() - 1; - for (i, align_x) in positions.iter().enumerate() { - for (j, align_y) in positions.iter().enumerate() { - if i == 0 && (j == 0 || j == last) || (i == last && j == 0) { - continue; - } - if (*align_x - x).abs() <= 2 && (*align_y - y).abs() <= 2 { - return true; - } - } - } - false - } - } - } -} - -#[cfg(test)] -mod all_functional_patterns_tests { - use crate::canvas::{is_functional, Canvas}; - use crate::types::{EcLevel, Version}; - - #[test] - fn test_all_functional_patterns_qr() { - let mut c = Canvas::new(Version::Normal(2), EcLevel::L); - c.draw_all_functional_patterns(); - assert_eq!( - &*c.to_debug_str(), - "\n\ - #######..????????.#######\n\ - #.....#..????????.#.....#\n\ - #.###.#..????????.#.###.#\n\ - #.###.#..????????.#.###.#\n\ - #.###.#..????????.#.###.#\n\ - #.....#..????????.#.....#\n\ - #######.#.#.#.#.#.#######\n\ - .........????????........\n\ - ......#..????????........\n\ - ??????.??????????????????\n\ - ??????#??????????????????\n\ - ??????.??????????????????\n\ - ??????#??????????????????\n\ - ??????.??????????????????\n\ - ??????#??????????????????\n\ - ??????.??????????????????\n\ - ??????#?????????#####????\n\ - ........#???????#...#????\n\ - #######..???????#.#.#????\n\ - #.....#..???????#...#????\n\ - #.###.#..???????#####????\n\ - #.###.#..????????????????\n\ - #.###.#..????????????????\n\ - #.....#..????????????????\n\ - #######..????????????????" - ); - } - - #[test] - fn test_all_functional_patterns_micro_qr() { - let mut c = Canvas::new(Version::Micro(1), EcLevel::L); - c.draw_all_functional_patterns(); - assert_eq!( - &*c.to_debug_str(), - "\n\ - #######.#.#\n\ - #.....#..??\n\ - #.###.#..??\n\ - #.###.#..??\n\ - #.###.#..??\n\ - #.....#..??\n\ - #######..??\n\ - .........??\n\ - #........??\n\ - .??????????\n\ - #??????????" - ); - } - - #[test] - fn test_is_functional_qr_1() { - let version = Version::Normal(1); - assert!(is_functional(version, version.width(), 0, 0)); - assert!(is_functional(version, version.width(), 10, 6)); - assert!(!is_functional(version, version.width(), 10, 5)); - assert!(!is_functional(version, version.width(), 14, 14)); - assert!(is_functional(version, version.width(), 6, 11)); - assert!(!is_functional(version, version.width(), 4, 11)); - assert!(is_functional(version, version.width(), 4, 13)); - assert!(is_functional(version, version.width(), 17, 7)); - assert!(!is_functional(version, version.width(), 17, 17)); - } - - #[test] - fn test_is_functional_qr_3() { - let version = Version::Normal(3); - assert!(is_functional(version, version.width(), 0, 0)); - assert!(!is_functional(version, version.width(), 25, 24)); - assert!(is_functional(version, version.width(), 24, 24)); - assert!(!is_functional(version, version.width(), 9, 25)); - assert!(!is_functional(version, version.width(), 20, 0)); - assert!(is_functional(version, version.width(), 21, 0)); - } - - #[test] - fn test_is_functional_qr_7() { - let version = Version::Normal(7); - assert!(is_functional(version, version.width(), 21, 4)); - assert!(is_functional(version, version.width(), 7, 21)); - assert!(is_functional(version, version.width(), 22, 22)); - assert!(is_functional(version, version.width(), 8, 8)); - assert!(!is_functional(version, version.width(), 19, 5)); - assert!(!is_functional(version, version.width(), 36, 3)); - assert!(!is_functional(version, version.width(), 4, 36)); - assert!(is_functional(version, version.width(), 38, 38)); - } - - #[test] - fn test_is_functional_micro() { - let version = Version::Micro(1); - assert!(is_functional(version, version.width(), 8, 0)); - assert!(is_functional(version, version.width(), 10, 0)); - assert!(!is_functional(version, version.width(), 10, 1)); - assert!(is_functional(version, version.width(), 8, 8)); - assert!(is_functional(version, version.width(), 0, 9)); - assert!(!is_functional(version, version.width(), 1, 9)); - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Data placement iterator - -struct DataModuleIter { - x: i16, - y: i16, - width: i16, - timing_pattern_column: i16, -} - -impl DataModuleIter { - fn new(version: Version) -> Self { - let width = version.width(); - Self { - x: width - 1, - y: width - 1, - width, - timing_pattern_column: match version { - Version::Micro(_) => 0, - Version::Normal(_) => 6, - }, - } - } -} - -impl Iterator for DataModuleIter { - type Item = (i16, i16); - - fn next(&mut self) -> Option<(i16, i16)> { - let adjusted_ref_col = if self.x <= self.timing_pattern_column { self.x + 1 } else { self.x }; - if adjusted_ref_col <= 0 { - return None; - } - - let res = (self.x, self.y); - let column_type = (self.width - adjusted_ref_col) % 4; - - match column_type { - 2 if self.y > 0 => { - self.y -= 1; - self.x += 1; - } - 0 if self.y < self.width - 1 => { - self.y += 1; - self.x += 1; - } - 0 | 2 if self.x == self.timing_pattern_column + 1 => { - self.x -= 2; - } - _ => { - self.x -= 1; - } - } - - Some(res) - } -} - -#[cfg(test)] -#[rustfmt::skip] // skip to prevent file becoming too long. -mod data_iter_tests { - use alloc::vec::{Vec}; - - use crate::canvas::DataModuleIter; - use crate::types::Version; - - #[test] - fn test_qr() { - let res = DataModuleIter::new(Version::Normal(1)).collect::<Vec<(i16, i16)>>(); - assert_eq!(res, vec![ - (20, 20), (19, 20), (20, 19), (19, 19), (20, 18), (19, 18), - (20, 17), (19, 17), (20, 16), (19, 16), (20, 15), (19, 15), - (20, 14), (19, 14), (20, 13), (19, 13), (20, 12), (19, 12), - (20, 11), (19, 11), (20, 10), (19, 10), (20, 9), (19, 9), - (20, 8), (19, 8), (20, 7), (19, 7), (20, 6), (19, 6), - (20, 5), (19, 5), (20, 4), (19, 4), (20, 3), (19, 3), - (20, 2), (19, 2), (20, 1), (19, 1), (20, 0), (19, 0), - - (18, 0), (17, 0), (18, 1), (17, 1), (18, 2), (17, 2), - (18, 3), (17, 3), (18, 4), (17, 4), (18, 5), (17, 5), - (18, 6), (17, 6), (18, 7), (17, 7), (18, 8), (17, 8), - (18, 9), (17, 9), (18, 10), (17, 10), (18, 11), (17, 11), - (18, 12), (17, 12), (18, 13), (17, 13), (18, 14), (17, 14), - (18, 15), (17, 15), (18, 16), (17, 16), (18, 17), (17, 17), - (18, 18), (17, 18), (18, 19), (17, 19), (18, 20), (17, 20), - - (16, 20), (15, 20), (16, 19), (15, 19), (16, 18), (15, 18), - (16, 17), (15, 17), (16, 16), (15, 16), (16, 15), (15, 15), - (16, 14), (15, 14), (16, 13), (15, 13), (16, 12), (15, 12), - (16, 11), (15, 11), (16, 10), (15, 10), (16, 9), (15, 9), - (16, 8), (15, 8), (16, 7), (15, 7), (16, 6), (15, 6), - (16, 5), (15, 5), (16, 4), (15, 4), (16, 3), (15, 3), - (16, 2), (15, 2), (16, 1), (15, 1), (16, 0), (15, 0), - - (14, 0), (13, 0), (14, 1), (13, 1), (14, 2), (13, 2), - (14, 3), (13, 3), (14, 4), (13, 4), (14, 5), (13, 5), - (14, 6), (13, 6), (14, 7), (13, 7), (14, 8), (13, 8), - (14, 9), (13, 9), (14, 10), (13, 10), (14, 11), (13, 11), - (14, 12), (13, 12), (14, 13), (13, 13), (14, 14), (13, 14), - (14, 15), (13, 15), (14, 16), (13, 16), (14, 17), (13, 17), - (14, 18), (13, 18), (14, 19), (13, 19), (14, 20), (13, 20), - - (12, 20), (11, 20), (12, 19), (11, 19), (12, 18), (11, 18), - (12, 17), (11, 17), (12, 16), (11, 16), (12, 15), (11, 15), - (12, 14), (11, 14), (12, 13), (11, 13), (12, 12), (11, 12), - (12, 11), (11, 11), (12, 10), (11, 10), (12, 9), (11, 9), - (12, 8), (11, 8), (12, 7), (11, 7), (12, 6), (11, 6), - (12, 5), (11, 5), (12, 4), (11, 4), (12, 3), (11, 3), - (12, 2), (11, 2), (12, 1), (11, 1), (12, 0), (11, 0), - - (10, 0), (9, 0), (10, 1), (9, 1), (10, 2), (9, 2), - (10, 3), (9, 3), (10, 4), (9, 4), (10, 5), (9, 5), - (10, 6), (9, 6), (10, 7), (9, 7), (10, 8), (9, 8), - (10, 9), (9, 9), (10, 10), (9, 10), (10, 11), (9, 11), - (10, 12), (9, 12), (10, 13), (9, 13), (10, 14), (9, 14), - (10, 15), (9, 15), (10, 16), (9, 16), (10, 17), (9, 17), - (10, 18), (9, 18), (10, 19), (9, 19), (10, 20), (9, 20), - - (8, 20), (7, 20), (8, 19), (7, 19), (8, 18), (7, 18), - (8, 17), (7, 17), (8, 16), (7, 16), (8, 15), (7, 15), - (8, 14), (7, 14), (8, 13), (7, 13), (8, 12), (7, 12), - (8, 11), (7, 11), (8, 10), (7, 10), (8, 9), (7, 9), - (8, 8), (7, 8), (8, 7), (7, 7), (8, 6), (7, 6), - (8, 5), (7, 5), (8, 4), (7, 4), (8, 3), (7, 3), - (8, 2), (7, 2), (8, 1), (7, 1), (8, 0), (7, 0), - - (5, 0), (4, 0), (5, 1), (4, 1), (5, 2), (4, 2), - (5, 3), (4, 3), (5, 4), (4, 4), (5, 5), (4, 5), - (5, 6), (4, 6), (5, 7), (4, 7), (5, 8), (4, 8), - (5, 9), (4, 9), (5, 10), (4, 10), (5, 11), (4, 11), - (5, 12), (4, 12), (5, 13), (4, 13), (5, 14), (4, 14), - (5, 15), (4, 15), (5, 16), (4, 16), (5, 17), (4, 17), - (5, 18), (4, 18), (5, 19), (4, 19), (5, 20), (4, 20), - - (3, 20), (2, 20), (3, 19), (2, 19), (3, 18), (2, 18), - (3, 17), (2, 17), (3, 16), (2, 16), (3, 15), (2, 15), - (3, 14), (2, 14), (3, 13), (2, 13), (3, 12), (2, 12), - (3, 11), (2, 11), (3, 10), (2, 10), (3, 9), (2, 9), - (3, 8), (2, 8), (3, 7), (2, 7), (3, 6), (2, 6), - (3, 5), (2, 5), (3, 4), (2, 4), (3, 3), (2, 3), - (3, 2), (2, 2), (3, 1), (2, 1), (3, 0), (2, 0), - - (1, 0), (0, 0), (1, 1), (0, 1), (1, 2), (0, 2), - (1, 3), (0, 3), (1, 4), (0, 4), (1, 5), (0, 5), - (1, 6), (0, 6), (1, 7), (0, 7), (1, 8), (0, 8), - (1, 9), (0, 9), (1, 10), (0, 10), (1, 11), (0, 11), - (1, 12), (0, 12), (1, 13), (0, 13), (1, 14), (0, 14), - (1, 15), (0, 15), (1, 16), (0, 16), (1, 17), (0, 17), - (1, 18), (0, 18), (1, 19), (0, 19), (1, 20), (0, 20), - ]); - } - - #[test] - fn test_micro_qr() { - let res = DataModuleIter::new(Version::Micro(1)).collect::<Vec<(i16, i16)>>(); - assert_eq!(res, vec![ - (10, 10), (9, 10), (10, 9), (9, 9), (10, 8), (9, 8), - (10, 7), (9, 7), (10, 6), (9, 6), (10, 5), (9, 5), - (10, 4), (9, 4), (10, 3), (9, 3), (10, 2), (9, 2), - (10, 1), (9, 1), (10, 0), (9, 0), - - (8, 0), (7, 0), (8, 1), (7, 1), (8, 2), (7, 2), - (8, 3), (7, 3), (8, 4), (7, 4), (8, 5), (7, 5), - (8, 6), (7, 6), (8, 7), (7, 7), (8, 8), (7, 8), - (8, 9), (7, 9), (8, 10), (7, 10), - - (6, 10), (5, 10), (6, 9), (5, 9), (6, 8), (5, 8), - (6, 7), (5, 7), (6, 6), (5, 6), (6, 5), (5, 5), - (6, 4), (5, 4), (6, 3), (5, 3), (6, 2), (5, 2), - (6, 1), (5, 1), (6, 0), (5, 0), - - (4, 0), (3, 0), (4, 1), (3, 1), (4, 2), (3, 2), - (4, 3), (3, 3), (4, 4), (3, 4), (4, 5), (3, 5), - (4, 6), (3, 6), (4, 7), (3, 7), (4, 8), (3, 8), - (4, 9), (3, 9), (4, 10), (3, 10), - - (2, 10), (1, 10), (2, 9), (1, 9), (2, 8), (1, 8), - (2, 7), (1, 7), (2, 6), (1, 6), (2, 5), (1, 5), - (2, 4), (1, 4), (2, 3), (1, 3), (2, 2), (1, 2), - (2, 1), (1, 1), (2, 0), (1, 0), - ]); - } - - #[test] - fn test_micro_qr_2() { - let res = DataModuleIter::new(Version::Micro(2)).collect::<Vec<(i16, i16)>>(); - assert_eq!(res, vec![ - (12, 12), (11, 12), (12, 11), (11, 11), (12, 10), (11, 10), - (12, 9), (11, 9), (12, 8), (11, 8), (12, 7), (11, 7), - (12, 6), (11, 6), (12, 5), (11, 5), (12, 4), (11, 4), - (12, 3), (11, 3), (12, 2), (11, 2), (12, 1), (11, 1), - (12, 0), (11, 0), - - (10, 0), (9, 0), (10, 1), (9, 1), (10, 2), (9, 2), - (10, 3), (9, 3), (10, 4), (9, 4), (10, 5), (9, 5), - (10, 6), (9, 6), (10, 7), (9, 7), (10, 8), (9, 8), - (10, 9), (9, 9), (10, 10), (9, 10), (10, 11), (9, 11), - (10, 12), (9, 12), - - (8, 12), (7, 12), (8, 11), (7, 11), (8, 10), (7, 10), - (8, 9), (7, 9), (8, 8), (7, 8), (8, 7), (7, 7), - (8, 6), (7, 6), (8, 5), (7, 5), (8, 4), (7, 4), - (8, 3), (7, 3), (8, 2), (7, 2), (8, 1), (7, 1), - (8, 0), (7, 0), - - (6, 0), (5, 0), (6, 1), (5, 1), (6, 2), (5, 2), - (6, 3), (5, 3), (6, 4), (5, 4), (6, 5), (5, 5), - (6, 6), (5, 6), (6, 7), (5, 7), (6, 8), (5, 8), - (6, 9), (5, 9), (6, 10), (5, 10), (6, 11), (5, 11), - (6, 12), (5, 12), - - (4, 12), (3, 12), (4, 11), (3, 11), (4, 10), (3, 10), - (4, 9), (3, 9), (4, 8), (3, 8), (4, 7), (3, 7), - (4, 6), (3, 6), (4, 5), (3, 5), (4, 4), (3, 4), - (4, 3), (3, 3), (4, 2), (3, 2), (4, 1), (3, 1), - (4, 0), (3, 0), - - (2, 0), (1, 0), (2, 1), (1, 1), (2, 2), (1, 2), - (2, 3), (1, 3), (2, 4), (1, 4), (2, 5), (1, 5), - (2, 6), (1, 6), (2, 7), (1, 7), (2, 8), (1, 8), - (2, 9), (1, 9), (2, 10), (1, 10), (2, 11), (1, 11), - (2, 12), (1, 12), - ]); - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Data placement - -impl Canvas { - fn draw_codewords<I>(&mut self, codewords: &[u8], is_half_codeword_at_end: bool, coords: &mut I) - where - I: Iterator<Item = (i16, i16)>, - { - let length = codewords.len(); - let last_word = if is_half_codeword_at_end { length - 1 } else { length }; - for (i, b) in codewords.iter().enumerate() { - let bits_end = if i == last_word { 4 } else { 0 }; - 'outside: for j in (bits_end..=7).rev() { - let color = if (*b & (1 << j)) == 0 { Color::Light } else { Color::Dark }; - for (x, y) in coords.by_ref() { - let r = self.get_mut(x, y); - if *r == Module::Empty { - *r = Module::Unmasked(color); - continue 'outside; - } - } - return; - } - } - } - - /// Draws the encoded data and error correction codes to the empty modules. - pub fn draw_data(&mut self, data: &[u8], ec: &[u8]) { - let is_half_codeword_at_end = match (self.version, self.ec_level) { - (Version::Micro(1), EcLevel::L) | (Version::Micro(3), EcLevel::M) => true, - _ => false, - }; - - let mut coords = DataModuleIter::new(self.version); - self.draw_codewords(data, is_half_codeword_at_end, &mut coords); - self.draw_codewords(ec, false, &mut coords); - } -} - -#[cfg(test)] -mod draw_codewords_test { - use crate::canvas::Canvas; - use crate::types::{EcLevel, Version}; - - #[test] - fn test_micro_qr_1() { - let mut c = Canvas::new(Version::Micro(1), EcLevel::L); - c.draw_all_functional_patterns(); - c.draw_data(b"\x6e\x5d\xe2", b"\x2b\x63"); - assert_eq!( - &*c.to_debug_str(), - "\n\ - #######.#.#\n\ - #.....#..-*\n\ - #.###.#..**\n\ - #.###.#..*-\n\ - #.###.#..**\n\ - #.....#..*-\n\ - #######..*-\n\ - .........-*\n\ - #........**\n\ - .***-**---*\n\ - #---*-*-**-" - ); - } - - #[test] - fn test_qr_2() { - let mut c = Canvas::new(Version::Normal(2), EcLevel::L); - c.draw_all_functional_patterns(); - c.draw_data( - b"\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\ - \x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$", - b"", - ); - assert_eq!( - &*c.to_debug_str(), - "\n\ - #######..--*---*-.#######\n\ - #.....#..-*-*-*-*.#.....#\n\ - #.###.#..*---*---.#.###.#\n\ - #.###.#..--*---*-.#.###.#\n\ - #.###.#..-*-*-*-*.#.###.#\n\ - #.....#..*---*---.#.....#\n\ - #######.#.#.#.#.#.#######\n\ - .........--*---*-........\n\ - ......#..-*-*-*-*........\n\ - --*-*-.-**---*---*--**--*\n\ - -*-*--#----*---*---------\n\ - *----*.*--*-*-*-*-**--**-\n\ - --*-*-#-**---*---*--**--*\n\ - -*-*--.----*---*---------\n\ - *----*#*--*-*-*-*-**--**-\n\ - --*-*-.-**---*---*--**--*\n\ - -*-*--#----*---*#####----\n\ - ........#-*-*-*-#...#-**-\n\ - #######..*---*--#.#.#*--*\n\ - #.....#..--*---*#...#----\n\ - #.###.#..-*-*-*-#####-**-\n\ - #.###.#..*---*--*----*--*\n\ - #.###.#..--*------**-----\n\ - #.....#..-*-*-**-*--*-**-\n\ - #######..*---*--*----*--*" - ); - } -} -//}}} -//------------------------------------------------------------------------------ -//{{{ Masking - -/// The mask patterns. Since QR code and Micro QR code do not use the same -/// pattern number, we name them according to their shape instead of the number. -#[derive(Debug, Copy, Clone)] -pub enum MaskPattern { - /// QR code pattern 000: `(x + y) % 2 == 0`. - Checkerboard = 0b000, - - /// QR code pattern 001: `y % 2 == 0`. - HorizontalLines = 0b001, - - /// QR code pattern 010: `x % 3 == 0`. - VerticalLines = 0b010, - - /// QR code pattern 011: `(x + y) % 3 == 0`. - DiagonalLines = 0b011, - - /// QR code pattern 100: `((x/3) + (y/2)) % 2 == 0`. - LargeCheckerboard = 0b100, - - /// QR code pattern 101: `(x*y)%2 + (x*y)%3 == 0`. - Fields = 0b101, - - /// QR code pattern 110: `((x*y)%2 + (x*y)%3) % 2 == 0`. - Diamonds = 0b110, - - /// QR code pattern 111: `((x+y)%2 + (x*y)%3) % 2 == 0`. - Meadow = 0b111, -} - -mod mask_functions { - pub fn checkerboard(x: i16, y: i16) -> bool { - (x + y) % 2 == 0 - } - pub fn horizontal_lines(_: i16, y: i16) -> bool { - y % 2 == 0 - } - pub fn vertical_lines(x: i16, _: i16) -> bool { - x % 3 == 0 - } - pub fn diagonal_lines(x: i16, y: i16) -> bool { - (x + y) % 3 == 0 - } - pub fn large_checkerboard(x: i16, y: i16) -> bool { - ((y / 2) + (x / 3)) % 2 == 0 - } - pub fn fields(x: i16, y: i16) -> bool { - (x * y) % 2 + (x * y) % 3 == 0 - } - pub fn diamonds(x: i16, y: i16) -> bool { - ((x * y) % 2 + (x * y) % 3) % 2 == 0 - } - pub fn meadow(x: i16, y: i16) -> bool { - ((x + y) % 2 + (x * y) % 3) % 2 == 0 - } -} - -fn get_mask_function(pattern: MaskPattern) -> fn(i16, i16) -> bool { - match pattern { - MaskPattern::Checkerboard => mask_functions::checkerboard, - MaskPattern::HorizontalLines => mask_functions::horizontal_lines, - MaskPattern::VerticalLines => mask_functions::vertical_lines, - MaskPattern::DiagonalLines => mask_functions::diagonal_lines, - MaskPattern::LargeCheckerboard => mask_functions::large_checkerboard, - MaskPattern::Fields => mask_functions::fields, - MaskPattern::Diamonds => mask_functions::diamonds, - MaskPattern::Meadow => mask_functions::meadow, - } -} - -impl Canvas { - /// Applies a mask to the canvas. This method will also draw the format info - /// patterns. - pub fn apply_mask(&mut self, pattern: MaskPattern) { - let mask_fn = get_mask_function(pattern); - for x in 0..self.width { - for y in 0..self.width { - let module = self.get_mut(x, y); - *module = module.mask(mask_fn(x, y)); - } - } - - self.draw_format_info_patterns(pattern); - } - - /// Draws the format information to encode the error correction level and - /// mask pattern. - /// - /// If the error correction level or mask pattern is not supported in the - /// current QR code version, this method will fail. - fn draw_format_info_patterns(&mut self, pattern: MaskPattern) { - let format_number = match self.version { - Version::Normal(_) => { - let simple_format_number = ((self.ec_level as usize) ^ 1) << 3 | (pattern as usize); - FORMAT_INFOS_QR[simple_format_number] - } - Version::Micro(a) => { - let micro_pattern_number = match pattern { - MaskPattern::HorizontalLines => 0b00, - MaskPattern::LargeCheckerboard => 0b01, - MaskPattern::Diamonds => 0b10, - MaskPattern::Meadow => 0b11, - _ => panic!("Unsupported mask pattern in Micro QR code"), - }; - let symbol_number = match (a, self.ec_level) { - (1, EcLevel::L) => 0b000, - (2, EcLevel::L) => 0b001, - (2, EcLevel::M) => 0b010, - (3, EcLevel::L) => 0b011, - (3, EcLevel::M) => 0b100, - (4, EcLevel::L) => 0b101, - (4, EcLevel::M) => 0b110, - (4, EcLevel::Q) => 0b111, - _ => panic!("Unsupported version/ec_level combination in Micro QR code"), - }; - let simple_format_number = symbol_number << 2 | micro_pattern_number; - FORMAT_INFOS_MICRO_QR[simple_format_number] - } - }; - self.draw_format_info_patterns_with_number(format_number); - } -} - -#[cfg(test)] -mod mask_tests { - use crate::canvas::{Canvas, MaskPattern}; - use crate::types::{EcLevel, Version}; - - #[test] - fn test_apply_mask_qr() { - let mut c = Canvas::new(Version::Normal(1), EcLevel::L); - c.draw_all_functional_patterns(); - c.apply_mask(MaskPattern::Checkerboard); - - assert_eq!( - &*c.to_debug_str(), - "\n\ - #######...#.#.#######\n\ - #.....#..#.#..#.....#\n\ - #.###.#.#.#.#.#.###.#\n\ - #.###.#..#.#..#.###.#\n\ - #.###.#...#.#.#.###.#\n\ - #.....#..#.#..#.....#\n\ - #######.#.#.#.#######\n\ - ........##.#.........\n\ - ###.#####.#.###...#..\n\ - .#.#.#.#.#.#.#.#.#.#.\n\ - #.#.#.#.#.#.#.#.#.#.#\n\ - .#.#.#.#.#.#.#.#.#.#.\n\ - #.#.#.#.#.#.#.#.#.#.#\n\ - ........##.#.#.#.#.#.\n\ - #######.#.#.#.#.#.#.#\n\ - #.....#.##.#.#.#.#.#.\n\ - #.###.#.#.#.#.#.#.#.#\n\ - #.###.#..#.#.#.#.#.#.\n\ - #.###.#.#.#.#.#.#.#.#\n\ - #.....#.##.#.#.#.#.#.\n\ - #######.#.#.#.#.#.#.#" - ); - } - - #[test] - fn test_draw_format_info_patterns_qr() { - let mut c = Canvas::new(Version::Normal(1), EcLevel::L); - c.draw_format_info_patterns(MaskPattern::LargeCheckerboard); - assert_eq!( - &*c.to_debug_str(), - "\n\ - ????????#????????????\n\ - ????????#????????????\n\ - ????????#????????????\n\ - ????????#????????????\n\ - ????????.????????????\n\ - ????????#????????????\n\ - ?????????????????????\n\ - ????????.????????????\n\ - ##..##?..????..#.####\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ????????#????????????\n\ - ????????.????????????\n\ - ????????#????????????\n\ - ????????#????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????#????????????\n\ - ????????#????????????" - ); - } - - #[test] - fn test_draw_format_info_patterns_micro_qr() { - let mut c = Canvas::new(Version::Micro(2), EcLevel::L); - c.draw_format_info_patterns(MaskPattern::LargeCheckerboard); - assert_eq!( - &*c.to_debug_str(), - "\n\ - ?????????????\n\ - ????????#????\n\ - ????????.????\n\ - ????????.????\n\ - ????????#????\n\ - ????????#????\n\ - ????????.????\n\ - ????????.????\n\ - ?#.#....#????\n\ - ?????????????\n\ - ?????????????\n\ - ?????????????\n\ - ?????????????" - ); - } -} - -static FORMAT_INFOS_QR: [u16; 32] = [ - 0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, 0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, - 0x6c41, 0x6976, 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b, 0x355f, 0x3068, 0x3f31, 0x3a06, - 0x24b4, 0x2183, 0x2eda, 0x2bed, -]; - -static FORMAT_INFOS_MICRO_QR: [u16; 32] = [ - 0x4445, 0x4172, 0x4e2b, 0x4b1c, 0x55ae, 0x5099, 0x5fc0, 0x5af7, 0x6793, 0x62a4, 0x6dfd, 0x68ca, 0x7678, 0x734f, - 0x7c16, 0x7921, 0x06de, 0x03e9, 0x0cb0, 0x0987, 0x1735, 0x1202, 0x1d5b, 0x186c, 0x2508, 0x203f, 0x2f66, 0x2a51, - 0x34e3, 0x31d4, 0x3e8d, 0x3bba, -]; - -//}}} -//------------------------------------------------------------------------------ -//{{{ Penalty score - -impl Canvas { - /// Compute the penalty score for having too many adjacent modules with the - /// same color. - /// - /// Every 5+N adjacent modules in the same column/row having the same color - /// will contribute 3+N points. - fn compute_adjacent_penalty_score(&self, is_horizontal: bool) -> u16 { - let mut total_score = 0; - - for i in 0..self.width { - let map_fn = |j| if is_horizontal { self.get(j, i) } else { self.get(i, j) }; - - let colors = (0..self.width).map(map_fn).chain(Some(Module::Empty).into_iter()); - let mut last_color = Module::Empty; - let mut consecutive_len = 1_u16; - - for color in colors { - if color == last_color { - consecutive_len += 1; - } else { - last_color = color; - if consecutive_len >= 5 { - total_score += consecutive_len - 2; - } - consecutive_len = 1; - } - } - } - - total_score - } - - /// Compute the penalty score for having too many rectangles with the same - /// color. - /// - /// Every 2×2 blocks (with overlapping counted) having the same color will - /// contribute 3 points. - fn compute_block_penalty_score(&self) -> u16 { - let mut total_score = 0; - - for i in 0..self.width - 1 { - for j in 0..self.width - 1 { - let this = self.get(i, j); - let right = self.get(i + 1, j); - let bottom = self.get(i, j + 1); - let bottom_right = self.get(i + 1, j + 1); - if this == right && right == bottom && bottom == bottom_right { - total_score += 3; - } - } - } - - total_score - } - - /// Compute the penalty score for having a pattern similar to the finder - /// pattern in the wrong place. - /// - /// Every pattern that looks like `#.###.#....` in any orientation will add - /// 40 points. - fn compute_finder_penalty_score(&self, is_horizontal: bool) -> u16 { - static PATTERN: [Color; 7] = - [Color::Dark, Color::Light, Color::Dark, Color::Dark, Color::Dark, Color::Light, Color::Dark]; - - let mut total_score = 0; - - for i in 0..self.width { - for j in 0..self.width - 6 { - // TODO a ref to a closure should be enough? - let get: Box<dyn Fn(i16) -> Color> = if is_horizontal { - Box::new(|k| self.get(k, i).into()) - } else { - Box::new(|k| self.get(i, k).into()) - }; - - if (j..(j + 7)).map(&*get).ne(PATTERN.iter().cloned()) { - continue; - } - - let check = |k| 0 <= k && k < self.width && get(k) != Color::Light; - if !((j - 4)..j).any(&check) || !((j + 7)..(j + 11)).any(&check) { - total_score += 40; - } - } - } - - total_score - 360 - } - - /// Compute the penalty score for having an unbalanced dark/light ratio. - /// - /// The score is given linearly by the deviation from a 50% ratio of dark - /// modules. The highest possible score is 100. - /// - /// Note that this algorithm differs slightly from the standard we do not - /// round the result every 5%, but the difference should be negligible and - /// should not affect which mask is chosen. - fn compute_balance_penalty_score(&self) -> u16 { - let dark_modules = self.modules.iter().filter(|m| m.is_dark()).count(); - let total_modules = self.modules.len(); - let ratio = dark_modules * 200 / total_modules; - if ratio >= 100 { ratio - 100 } else { 100 - ratio }.as_u16() - } - - /// Compute the penalty score for having too many light modules on the sides. - /// - /// This penalty score is exclusive to Micro QR code. - /// - /// Note that the standard gives the formula for *efficiency* score, which - /// has the inverse meaning of this method, but it is very easy to convert - /// between the two (this score is (16×width − standard-score)). - fn compute_light_side_penalty_score(&self) -> u16 { - let h = (1..self.width).filter(|j| !self.get(*j, -1).is_dark()).count(); - let v = (1..self.width).filter(|j| !self.get(-1, *j).is_dark()).count(); - - (h + v + 15 * max(h, v)).as_u16() - } - - /// Compute the total penalty scores. A QR code having higher points is less - /// desirable. - fn compute_total_penalty_scores(&self) -> u16 { - match self.version { - Version::Normal(_) => { - let s1_a = self.compute_adjacent_penalty_score(true); - let s1_b = self.compute_adjacent_penalty_score(false); - let s2 = self.compute_block_penalty_score(); - let s3_a = self.compute_finder_penalty_score(true); - let s3_b = self.compute_finder_penalty_score(false); - let s4 = self.compute_balance_penalty_score(); - s1_a + s1_b + s2 + s3_a + s3_b + s4 - } - Version::Micro(_) => self.compute_light_side_penalty_score(), - } - } -} - -#[cfg(test)] -mod penalty_tests { - use crate::canvas::{Canvas, MaskPattern}; - use crate::types::{Color, EcLevel, Version}; - - fn create_test_canvas() -> Canvas { - let mut c = Canvas::new(Version::Normal(1), EcLevel::Q); - c.draw_all_functional_patterns(); - c.draw_data( - b"\x20\x5b\x0b\x78\xd1\x72\xdc\x4d\x43\x40\xec\x11\x00", - b"\xa8\x48\x16\x52\xd9\x36\x9c\x00\x2e\x0f\xb4\x7a\x10", - ); - c.apply_mask(MaskPattern::Checkerboard); - c - } - - #[test] - fn check_penalty_canvas() { - let c = create_test_canvas(); - assert_eq!( - &*c.to_debug_str(), - "\n\ - #######.##....#######\n\ - #.....#.#..#..#.....#\n\ - #.###.#.#..##.#.###.#\n\ - #.###.#.#.....#.###.#\n\ - #.###.#.#.#...#.###.#\n\ - #.....#...#...#.....#\n\ - #######.#.#.#.#######\n\ - ........#............\n\ - .##.#.##....#.#.#####\n\ - .#......####....#...#\n\ - ..##.###.##...#.##...\n\ - .##.##.#..##.#.#.###.\n\ - #...#.#.#.###.###.#.#\n\ - ........##.#..#...#.#\n\ - #######.#.#....#.##..\n\ - #.....#..#.##.##.#...\n\ - #.###.#.#.#...#######\n\ - #.###.#..#.#.#.#...#.\n\ - #.###.#.#...####.#..#\n\ - #.....#.#.##.#...#.##\n\ - #######.....####....#" - ); - } - - #[test] - fn test_penalty_score_adjacent() { - let c = create_test_canvas(); - assert_eq!(c.compute_adjacent_penalty_score(true), 88); - assert_eq!(c.compute_adjacent_penalty_score(false), 92); - } - - #[test] - fn test_penalty_score_block() { - let c = create_test_canvas(); - assert_eq!(c.compute_block_penalty_score(), 90); - } - - #[test] - fn test_penalty_score_finder() { - let c = create_test_canvas(); - assert_eq!(c.compute_finder_penalty_score(true), 0); - assert_eq!(c.compute_finder_penalty_score(false), 40); - } - - #[test] - fn test_penalty_score_balance() { - let c = create_test_canvas(); - assert_eq!(c.compute_balance_penalty_score(), 2); - } - - #[test] - fn test_penalty_score_light_sides() { - static HORIZONTAL_SIDE: [Color; 17] = [ - Color::Dark, - Color::Light, - Color::Light, - Color::Dark, - Color::Dark, - Color::Dark, - Color::Light, - Color::Light, - Color::Dark, - Color::Light, - Color::Dark, - Color::Light, - Color::Light, - Color::Dark, - Color::Light, - Color::Light, - Color::Light, - ]; - static VERTICAL_SIDE: [Color; 17] = [ - Color::Dark, - Color::Dark, - Color::Dark, - Color::Light, - Color::Light, - Color::Dark, - Color::Dark, - Color::Light, - Color::Dark, - Color::Light, - Color::Dark, - Color::Light, - Color::Dark, - Color::Light, - Color::Light, - Color::Dark, - Color::Light, - ]; - - let mut c = Canvas::new(Version::Micro(4), EcLevel::Q); - for i in 0_i16..17 { - c.put(i, -1, HORIZONTAL_SIDE[i as usize]); - c.put(-1, i, VERTICAL_SIDE[i as usize]); - } - - assert_eq!(c.compute_light_side_penalty_score(), 168); - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Select mask with lowest penalty score - -static ALL_PATTERNS_QR: [MaskPattern; 8] = [ - MaskPattern::Checkerboard, - MaskPattern::HorizontalLines, - MaskPattern::VerticalLines, - MaskPattern::DiagonalLines, - MaskPattern::LargeCheckerboard, - MaskPattern::Fields, - MaskPattern::Diamonds, - MaskPattern::Meadow, -]; - -static ALL_PATTERNS_MICRO_QR: [MaskPattern; 4] = - [MaskPattern::HorizontalLines, MaskPattern::LargeCheckerboard, MaskPattern::Diamonds, MaskPattern::Meadow]; - -impl Canvas { - /// Construct a new canvas and apply the best masking that gives the lowest - /// penalty score. - pub fn apply_best_mask(&self) -> Self { - match self.version { - Version::Normal(_) => ALL_PATTERNS_QR.iter(), - Version::Micro(_) => ALL_PATTERNS_MICRO_QR.iter(), - } - .map(|ptn| { - let mut c = self.clone(); - c.apply_mask(*ptn); - c - }) - .min_by_key(Self::compute_total_penalty_scores) - .expect("at least one pattern") - } - - /// Convert the modules into a vector of booleans. - #[deprecated(since = "0.4.0", note = "use `into_colors()` instead")] - pub fn to_bools(&self) -> Vec<bool> { - self.modules.iter().map(|m| m.is_dark()).collect() - } - - /// Convert the modules into a vector of colors. - pub fn into_colors(self) -> Vec<Color> { - self.modules.into_iter().map(Color::from).collect() - } -} - -//}}} -//------------------------------------------------------------------------------ diff --git a/qrcode-rust/src/cast.rs b/qrcode-rust/src/cast.rs deleted file mode 100644 index a4b1954..0000000 --- a/qrcode-rust/src/cast.rs +++ /dev/null @@ -1,87 +0,0 @@ -use core::fmt::Display; - -pub trait Truncate { - fn truncate_as_u8(self) -> u8; -} - -impl Truncate for u16 { - #[allow(clippy::cast_possible_truncation)] - fn truncate_as_u8(self) -> u8 { - (self & 0xff) as u8 - } -} - -pub trait As { - fn as_u16(self) -> u16; - fn as_i16(self) -> i16; - fn as_u32(self) -> u32; - fn as_usize(self) -> usize; - fn as_isize(self) -> isize; -} - -trait ExpectOrOverflow { - type Output; - fn expect_or_overflow<D: Display>(self, value: D, ty: &str) -> Self::Output; -} - -impl<T> ExpectOrOverflow for Option<T> { - type Output = T; - fn expect_or_overflow<D: Display>(self, value: D, ty: &str) -> Self::Output { - match self { - Some(v) => v, - None => panic!("{} overflows {}", value, ty), - } - } -} - -macro_rules! impl_as { - ($ty:ty) => { - #[allow(unconditional_recursion)] // idk why - #[cfg(debug_assertions)] - impl As for $ty { - fn as_u16(self) -> u16 { - self.as_u16() - } - - fn as_i16(self) -> i16 { - self.as_i16() - } - - fn as_u32(self) -> u32 { - self.as_u32() - } - - fn as_usize(self) -> usize { - self.as_usize() - } - - fn as_isize(self) -> isize { - self.as_isize() - } - } - - #[cfg(not(debug_assertions))] - impl As for $ty { - fn as_u16(self) -> u16 { - self as u16 - } - fn as_i16(self) -> i16 { - self as i16 - } - fn as_u32(self) -> u32 { - self as u32 - } - fn as_usize(self) -> usize { - self as usize - } - fn as_isize(self) -> isize { - self as isize - } - } - }; -} - -impl_as!(i16); -impl_as!(u32); -impl_as!(usize); -impl_as!(isize); diff --git a/qrcode-rust/src/ec.rs b/qrcode-rust/src/ec.rs deleted file mode 100644 index 7903abb..0000000 --- a/qrcode-rust/src/ec.rs +++ /dev/null @@ -1,488 +0,0 @@ -//! The `ec` module applies the Reed-Solomon error correction codes. - -use core::ops::Deref; - -use alloc::vec::Vec; - -use crate::types::{EcLevel, QrResult, Version}; - -//------------------------------------------------------------------------------ -//{{{ Error correction primitive - -/// Creates the error correction code in N bytes. -/// -/// This method only supports computing the error-correction code up to -/// 69 bytes. Longer blocks will result in task panic. -/// -/// This method treats the data as a polynomial of the form -/// (a\[0\] x<sup>m+n</sup> + a\[1\] x<sup>m+n-1</sup> + … + a\[m\] x<sup>n</sup>) -/// in GF(2<sup>8</sup>), and then computes the polynomial modulus with a -/// generator polynomial of degree N. -pub fn create_error_correction_code(data: &[u8], ec_code_size: usize) -> Vec<u8> { - let data_len = data.len(); - let log_den = GENERATOR_POLYNOMIALS[ec_code_size]; - - let mut res = data.to_vec(); - res.resize(ec_code_size + data_len, 0); - - // rust-lang-nursery/rust-clippy#2213 - for i in 0..data_len { - let lead_coeff = res[i] as usize; - if lead_coeff == 0 { - continue; - } - - let log_lead_coeff = usize::from(LOG_TABLE[lead_coeff]); - for (u, v) in res[i + 1..].iter_mut().zip(log_den.iter()) { - *u ^= EXP_TABLE[(usize::from(*v) + log_lead_coeff) % 255]; - } - } - - res.split_off(data_len) -} - -#[cfg(test)] -mod ec_tests { - use crate::ec::create_error_correction_code; - - #[test] - fn test_poly_mod_1() { - let res = create_error_correction_code(b" [\x0bx\xd1r\xdcMC@\xec\x11\xec\x11\xec\x11", 10); - assert_eq!(&*res, b"\xc4#'w\xeb\xd7\xe7\xe2]\x17"); - } - - #[test] - fn test_poly_mod_2() { - let res = create_error_correction_code(b" [\x0bx\xd1r\xdcMC@\xec\x11\xec", 13); - assert_eq!(&*res, b"\xa8H\x16R\xd96\x9c\x00.\x0f\xb4z\x10"); - } - - #[test] - fn test_poly_mod_3() { - let res = create_error_correction_code(b"CUF\x86W&U\xc2w2\x06\x12\x06g&", 18); - assert_eq!(&*res, b"\xd5\xc7\x0b-s\xf7\xf1\xdf\xe5\xf8\x9au\x9aoV\xa1o'"); - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Interleave support - -/// This method interleaves a vector of slices into a single vector. -/// -/// It will first insert all the first elements of the slices in `blocks`, then -/// all the second elements, then all the third elements, and so on. -/// -/// The longest slice must be at the last of `blocks`, and `blocks` must not be -/// empty. -fn interleave<T: Copy, V: Deref<Target = [T]>>(blocks: &[V]) -> Vec<T> { - let last_block_len = blocks.last().expect("non-empty blocks").len(); - let mut res = Vec::with_capacity(last_block_len * blocks.len()); - for i in 0..last_block_len { - for t in blocks { - if i < t.len() { - res.push(t[i]); - } - } - } - res -} - -#[test] -fn test_interleave() { - let res = interleave(&[&b"1234"[..], b"5678", b"abcdef", b"ghijkl"]); - assert_eq!(&*res, b"15ag26bh37ci48djekfl"); -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ QR code error correction - -/// Constructs data and error correction codewords ready to be put in the QR -/// code matrix. -/// -/// # Errors -/// -/// Returns `Err(QrError::InvalidVersion)` if it is not valid to use the -/// `ec_level` for the given version (e.g. `Version::Micro(1)` with -/// `EcLevel::H`). -pub fn construct_codewords(rawbits: &[u8], version: Version, ec_level: EcLevel) -> QrResult<(Vec<u8>, Vec<u8>)> { - let (block_1_size, block_1_count, block_2_size, block_2_count) = version.fetch(ec_level, &DATA_BYTES_PER_BLOCK)?; - - let blocks_count = block_1_count + block_2_count; - let block_1_end = block_1_size * block_1_count; - let total_size = block_1_end + block_2_size * block_2_count; - - debug_assert_eq!(rawbits.len(), total_size); - - // Divide the data into blocks. - let mut blocks = Vec::with_capacity(blocks_count); - blocks.extend(rawbits[..block_1_end].chunks(block_1_size)); - if block_2_size > 0 { - blocks.extend(rawbits[block_1_end..].chunks(block_2_size)); - } - - // Generate EC codes. - let ec_bytes = version.fetch(ec_level, &EC_BYTES_PER_BLOCK)?; - let ec_codes = blocks.iter().map(|block| create_error_correction_code(block, ec_bytes)).collect::<Vec<Vec<u8>>>(); - - let blocks_vec = interleave(&blocks); - let ec_vec = interleave(&ec_codes); - - Ok((blocks_vec, ec_vec)) -} - -#[cfg(test)] -mod construct_codewords_test { - use crate::ec::construct_codewords; - use crate::types::{EcLevel, Version}; - - #[test] - fn test_add_ec_simple() { - let msg = b" [\x0bx\xd1r\xdcMC@\xec\x11\xec\x11\xec\x11"; - let (blocks_vec, ec_vec) = construct_codewords(msg, Version::Normal(1), EcLevel::M).unwrap(); - assert_eq!(&*blocks_vec, msg); - assert_eq!(&*ec_vec, b"\xc4#'w\xeb\xd7\xe7\xe2]\x17"); - } - - #[test] - fn test_add_ec_complex() { - let msg = b"CUF\x86W&U\xc2w2\x06\x12\x06g&\xf6\xf6B\x07v\x86\xf2\x07&V\x16\xc6\xc7\x92\x06\ - \xb6\xe6\xf7w2\x07v\x86W&R\x06\x86\x972\x07F\xf7vV\xc2\x06\x972\x10\xec\x11\xec\ - \x11\xec\x11\xec"; - let expected_blocks = b"C\xf6\xb6FU\xf6\xe6\xf7FB\xf7v\x86\x07wVWv2\xc2&\x86\x07\x06U\xf2v\ - \x97\xc2\x07\x862w&W\x102V&\xec\x06\x16R\x11\x12\xc6\x06\xec\x06\ - \xc7\x86\x11g\x92\x97\xec&\x062\x11\x07\xec"; - let expected_ec = b"\xd5W\x94\xeb\xc7\xcct\x9f\x0b`\xb1\x05-<\xd4\xads\xcaL\x18\xf7\xb6\x85\ - \x93\xf1|K;\xdf\x9d\xf2!\xe5\xc8\xeej\xf8\x86L(\x9a\x1b\xc3\xffu\x81\ - \xe6\xac\x9a\xd1\xbdRo\x11\n\x02V\xa3l\x83\xa1\xa3\xf0 ox\xc0\xb2'\x85\ - \x8d\xec"; - - let (blocks_vec, ec_vec) = construct_codewords(msg, Version::Normal(5), EcLevel::Q).unwrap(); - assert_eq!(&*blocks_vec, &expected_blocks[..]); - assert_eq!(&*ec_vec, &expected_ec[..]); - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Number of allowed errors - -/// Computes the maximum allowed number of erratic modules can be introduced to -/// the QR code, before the data becomes truly corrupted. -/// -/// # Errors -/// -/// Returns `Err(QrError::InvalidVersion)` if it is not valid to use the -/// `ec_level` for the given version (e.g. `Version::Micro(1)` with -/// `EcLevel::H`). -pub fn max_allowed_errors(version: Version, ec_level: EcLevel) -> QrResult<usize> { - use crate::EcLevel::{L, M}; - use crate::Version::{Micro, Normal}; - - let p = match (version, ec_level) { - (Micro(2), L) | (Normal(1), L) => 3, - (Micro(_), L) | (Normal(2), L) | (Micro(2), M) | (Normal(1), M) => 2, - (Normal(1), _) | (Normal(3), L) => 1, - _ => 0, - }; - - let ec_bytes_per_block = version.fetch(ec_level, &EC_BYTES_PER_BLOCK)?; - let (_, count1, _, count2) = version.fetch(ec_level, &DATA_BYTES_PER_BLOCK)?; - let ec_bytes = (count1 + count2) * ec_bytes_per_block; - - Ok((ec_bytes - p) / 2) -} - -#[cfg(test)] -mod max_allowed_errors_test { - use crate::ec::max_allowed_errors; - use crate::types::{EcLevel, Version}; - - #[test] - fn test_low_versions() { - assert_eq!(Ok(0), max_allowed_errors(Version::Micro(1), EcLevel::L)); - - assert_eq!(Ok(1), max_allowed_errors(Version::Micro(2), EcLevel::L)); - assert_eq!(Ok(2), max_allowed_errors(Version::Micro(2), EcLevel::M)); - - assert_eq!(Ok(2), max_allowed_errors(Version::Micro(3), EcLevel::L)); - assert_eq!(Ok(4), max_allowed_errors(Version::Micro(3), EcLevel::M)); - - assert_eq!(Ok(3), max_allowed_errors(Version::Micro(4), EcLevel::L)); - assert_eq!(Ok(5), max_allowed_errors(Version::Micro(4), EcLevel::M)); - assert_eq!(Ok(7), max_allowed_errors(Version::Micro(4), EcLevel::Q)); - - assert_eq!(Ok(2), max_allowed_errors(Version::Normal(1), EcLevel::L)); - assert_eq!(Ok(4), max_allowed_errors(Version::Normal(1), EcLevel::M)); - assert_eq!(Ok(6), max_allowed_errors(Version::Normal(1), EcLevel::Q)); - assert_eq!(Ok(8), max_allowed_errors(Version::Normal(1), EcLevel::H)); - - assert_eq!(Ok(4), max_allowed_errors(Version::Normal(2), EcLevel::L)); - assert_eq!(Ok(8), max_allowed_errors(Version::Normal(2), EcLevel::M)); - assert_eq!(Ok(11), max_allowed_errors(Version::Normal(2), EcLevel::Q)); - assert_eq!(Ok(14), max_allowed_errors(Version::Normal(2), EcLevel::H)); - - assert_eq!(Ok(7), max_allowed_errors(Version::Normal(3), EcLevel::L)); - assert_eq!(Ok(13), max_allowed_errors(Version::Normal(3), EcLevel::M)); - assert_eq!(Ok(18), max_allowed_errors(Version::Normal(3), EcLevel::Q)); - assert_eq!(Ok(22), max_allowed_errors(Version::Normal(3), EcLevel::H)); - - assert_eq!(Ok(10), max_allowed_errors(Version::Normal(4), EcLevel::L)); - assert_eq!(Ok(18), max_allowed_errors(Version::Normal(4), EcLevel::M)); - assert_eq!(Ok(26), max_allowed_errors(Version::Normal(4), EcLevel::Q)); - assert_eq!(Ok(32), max_allowed_errors(Version::Normal(4), EcLevel::H)); - } - - #[test] - fn test_high_versions() { - assert_eq!(Ok(375), max_allowed_errors(Version::Normal(40), EcLevel::L)); - assert_eq!(Ok(686), max_allowed_errors(Version::Normal(40), EcLevel::M)); - assert_eq!(Ok(1020), max_allowed_errors(Version::Normal(40), EcLevel::Q)); - assert_eq!(Ok(1215), max_allowed_errors(Version::Normal(40), EcLevel::H)); - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Precomputed tables for GF(256). - -/// `EXP_TABLE` encodes the value of 2<sup>n</sup> in the Galois Field GF(256). -static EXP_TABLE: &[u8] = b"\ -\x01\x02\x04\x08\x10\x20\x40\x80\x1d\x3a\x74\xe8\xcd\x87\x13\x26\ -\x4c\x98\x2d\x5a\xb4\x75\xea\xc9\x8f\x03\x06\x0c\x18\x30\x60\xc0\ -\x9d\x27\x4e\x9c\x25\x4a\x94\x35\x6a\xd4\xb5\x77\xee\xc1\x9f\x23\ -\x46\x8c\x05\x0a\x14\x28\x50\xa0\x5d\xba\x69\xd2\xb9\x6f\xde\xa1\ -\x5f\xbe\x61\xc2\x99\x2f\x5e\xbc\x65\xca\x89\x0f\x1e\x3c\x78\xf0\ -\xfd\xe7\xd3\xbb\x6b\xd6\xb1\x7f\xfe\xe1\xdf\xa3\x5b\xb6\x71\xe2\ -\xd9\xaf\x43\x86\x11\x22\x44\x88\x0d\x1a\x34\x68\xd0\xbd\x67\xce\ -\x81\x1f\x3e\x7c\xf8\xed\xc7\x93\x3b\x76\xec\xc5\x97\x33\x66\xcc\ -\x85\x17\x2e\x5c\xb8\x6d\xda\xa9\x4f\x9e\x21\x42\x84\x15\x2a\x54\ -\xa8\x4d\x9a\x29\x52\xa4\x55\xaa\x49\x92\x39\x72\xe4\xd5\xb7\x73\ -\xe6\xd1\xbf\x63\xc6\x91\x3f\x7e\xfc\xe5\xd7\xb3\x7b\xf6\xf1\xff\ -\xe3\xdb\xab\x4b\x96\x31\x62\xc4\x95\x37\x6e\xdc\xa5\x57\xae\x41\ -\x82\x19\x32\x64\xc8\x8d\x07\x0e\x1c\x38\x70\xe0\xdd\xa7\x53\xa6\ -\x51\xa2\x59\xb2\x79\xf2\xf9\xef\xc3\x9b\x2b\x56\xac\x45\x8a\x09\ -\x12\x24\x48\x90\x3d\x7a\xf4\xf5\xf7\xf3\xfb\xeb\xcb\x8b\x0b\x16\ -\x2c\x58\xb0\x7d\xfa\xe9\xcf\x83\x1b\x36\x6c\xd8\xad\x47\x8e\x01"; - -/// `LOG_TABLE` is the inverse function of `EXP_TABLE`. -static LOG_TABLE: &[u8] = b"\ -\xff\x00\x01\x19\x02\x32\x1a\xc6\x03\xdf\x33\xee\x1b\x68\xc7\x4b\ -\x04\x64\xe0\x0e\x34\x8d\xef\x81\x1c\xc1\x69\xf8\xc8\x08\x4c\x71\ -\x05\x8a\x65\x2f\xe1\x24\x0f\x21\x35\x93\x8e\xda\xf0\x12\x82\x45\ -\x1d\xb5\xc2\x7d\x6a\x27\xf9\xb9\xc9\x9a\x09\x78\x4d\xe4\x72\xa6\ -\x06\xbf\x8b\x62\x66\xdd\x30\xfd\xe2\x98\x25\xb3\x10\x91\x22\x88\ -\x36\xd0\x94\xce\x8f\x96\xdb\xbd\xf1\xd2\x13\x5c\x83\x38\x46\x40\ -\x1e\x42\xb6\xa3\xc3\x48\x7e\x6e\x6b\x3a\x28\x54\xfa\x85\xba\x3d\ -\xca\x5e\x9b\x9f\x0a\x15\x79\x2b\x4e\xd4\xe5\xac\x73\xf3\xa7\x57\ -\x07\x70\xc0\xf7\x8c\x80\x63\x0d\x67\x4a\xde\xed\x31\xc5\xfe\x18\ -\xe3\xa5\x99\x77\x26\xb8\xb4\x7c\x11\x44\x92\xd9\x23\x20\x89\x2e\ -\x37\x3f\xd1\x5b\x95\xbc\xcf\xcd\x90\x87\x97\xb2\xdc\xfc\xbe\x61\ -\xf2\x56\xd3\xab\x14\x2a\x5d\x9e\x84\x3c\x39\x53\x47\x6d\x41\xa2\ -\x1f\x2d\x43\xd8\xb7\x7b\xa4\x76\xc4\x17\x49\xec\x7f\x0c\x6f\xf6\ -\x6c\xa1\x3b\x52\x29\x9d\x55\xaa\xfb\x60\x86\xb1\xbb\xcc\x3e\x5a\ -\xcb\x59\x5f\xb0\x9c\xa9\xa0\x51\x0b\xf5\x16\xeb\x7a\x75\x2c\xd7\ -\x4f\xae\xd5\xe9\xe6\xe7\xad\xe8\x74\xd6\xf4\xea\xa8\x50\x58\xaf"; - -/// The generator polynomial list. -/// -/// `GENERATOR_POLYNOMIALS[i]` is the polynomial for `i` error correction code -/// words. Each entry encodes the log coefficients of the expanded polynomial -/// (x − 2<sup>0</sup>)(x − 2<sup>1</sup>)…(x − 2<sup>i-1</sup>). Each entry is -/// used as the denominator for polynomial division to obtain the modulus which -/// is the Reed-Solomon error correction code. -/// -/// A partial list can be found from ISO/IEC 18004:2006 Annex A. -#[rustfmt::skip] -// ^ this attribute is currently useless, see rust-lang-nursery/rustfmt#1080 and 1298 -static GENERATOR_POLYNOMIALS: [&[u8]; 70] = [ - b"", - b"\x00", - b"\x19\x01", - b"\xc6\xc7\x03", - b"\x4b\xf9\x4e\x06", - b"\x71\xa4\xa6\x77\x0a", - b"\xa6\x00\x86\x05\xb0\x0f", - b"\x57\xe5\x92\x95\xee\x66\x15", - b"\xaf\xee\xd0\xf9\xd7\xfc\xc4\x1c", - b"\x5f\xf6\x89\xe7\xeb\x95\x0b\x7b\x24", - b"\xfb\x43\x2e\x3d\x76\x46\x40\x5e\x20\x2d", - b"\xdc\xc0\x5b\xc2\xac\xb1\xd1\x74\xe3\x0a\x37", - b"\x66\x2b\x62\x79\xbb\x71\xc6\x8f\x83\x57\x9d\x42", - b"\x4a\x98\xb0\x64\x56\x64\x6a\x68\x82\xda\xce\x8c\x4e", - b"\xc7\xf9\x9b\x30\xbe\x7c\xda\x89\xd8\x57\xcf\x3b\x16\x5b", - b"\x08\xb7\x3d\x5b\xca\x25\x33\x3a\x3a\xed\x8c\x7c\x05\x63\x69", - b"\x78\x68\x6b\x6d\x66\xa1\x4c\x03\x5b\xbf\x93\xa9\xb6\xc2\xe1\x78", - b"\x2b\x8b\xce\x4e\x2b\xef\x7b\xce\xd6\x93\x18\x63\x96\x27\xf3\xa3\x88", - b"\xd7\xea\x9e\x5e\xb8\x61\x76\xaa\x4f\xbb\x98\x94\xfc\xb3\x05\x62\x60\x99", - b"\x43\x03\x69\x99\x34\x5a\x53\x11\x96\x9f\x2c\x80\x99\x85\xfc\xde\x8a\xdc\xab", - b"\x11\x3c\x4f\x32\x3d\xa3\x1a\xbb\xca\xb4\xdd\xe1\x53\xef\x9c\xa4\xd4\xd4\xbc\xbe", - b"\xf0\xe9\x68\xf7\xb5\x8c\x43\x62\x55\xc8\xd2\x73\x94\x89\xe6\x24\x7a\xfe\x94\xaf\xd2", - b"\xd2\xab\xf7\xf2\x5d\xe6\x0e\x6d\xdd\x35\xc8\x4a\x08\xac\x62\x50\xdb\x86\xa0\x69\xa5\xe7", - b"\xab\x66\x92\x5b\x31\x67\x41\x11\xc1\x96\x0e\x19\xb7\xf8\x5e\xa4\xe0\xc0\x01\x4e\x38\x93\xfd", - b"\xe5\x79\x87\x30\xd3\x75\xfb\x7e\x9f\xb4\xa9\x98\xc0\xe2\xe4\xda\x6f\x00\x75\xe8\x57\x60\xe3\x15", - b"\xe7\xb5\x9c\x27\xaa\x1a\x0c\x3b\x0f\x94\xc9\x36\x42\xed\xd0\x63\xa7\x90\xb6\x5f\xf3\x81\xb2\xfc\x2d", - b"\xad\x7d\x9e\x02\x67\xb6\x76\x11\x91\xc9\x6f\x1c\xa5\x35\xa1\x15\xf5\x8e\x0d\x66\x30\xe3\x99\x91\xda\x46", - b"\x4f\xe4\x08\xa5\xe3\x15\xb4\x1d\x09\xed\x46\x63\x2d\x3a\x8a\x87\x49\x7e\xac\x5e\xd8\xc1\x9d\x1a\x11\x95\x60", - b"\xa8\xdf\xc8\x68\xe0\xea\x6c\xb4\x6e\xbe\xc3\x93\xcd\x1b\xe8\xc9\x15\x2b\xf5\x57\x2a\xc3\xd4\x77\xf2\x25\x09\x7b", - b"\x9c\x2d\xb7\x1d\x97\xdb\x36\x60\xf9\x18\x88\x05\xf1\xaf\xbd\x1c\x4b\xea\x96\x94\x17\x09\xca\xa2\x44\xfa\x8c\x18\x97", - b"\x29\xad\x91\x98\xd8\x1f\xb3\xb6\x32\x30\x6e\x56\xef\x60\xde\x7d\x2a\xad\xe2\xc1\xe0\x82\x9c\x25\xfb\xd8\xee\x28\xc0\xb4", - b"\x14\x25\xfc\x5d\x3f\x4b\xe1\x1f\x73\x53\x71\x27\x2c\x49\x7a\x89\x76\x77\x90\xf8\xf8\x37\x01\xe1\x69\x7b\xb7\x75\xbb\xc8\xd2", - b"\x0a\x06\x6a\xbe\xf9\xa7\x04\x43\xd1\x8a\x8a\x20\xf2\x7b\x59\x1b\x78\xb9\x50\x9c\x26\x45\xab\x3c\x1c\xde\x50\x34\xfe\xb9\xdc\xf1", - b"\xf5\xe7\x37\x18\x47\x4e\x4c\x51\xe1\xd4\xad\x25\xd7\x2e\x77\xe5\xf5\xa7\x7e\x48\xb5\x5e\xa5\xd2\x62\x7d\x9f\xb8\xa9\xe8\xb9\xe7\x12", - b"\x6f\x4d\x92\x5e\x1a\x15\x6c\x13\x69\x5e\x71\xc1\x56\x8c\xa3\x7d\x3a\x9e\xe5\xef\xda\x67\x38\x46\x72\x3d\xb7\x81\xa7\x0d\x62\x3e\x81\x33", - b"\x07\x5e\x8f\x51\xf7\x7f\xca\xca\xc2\x7d\x92\x1d\x8a\xa2\x99\x41\x69\x7a\x74\xee\x1a\x24\xd8\x70\x7d\xe4\x0f\x31\x08\xa2\x1e\x7e\x6f\x3a\x55", - b"\xc8\xb7\x62\x10\xac\x1f\xf6\xea\x3c\x98\x73\x00\xa7\x98\x71\xf8\xee\x6b\x12\x3f\xda\x25\x57\xd2\x69\xb1\x78\x4a\x79\xc4\x75\xfb\x71\xe9\x1e\x78", - b"\x9a\x4b\x8d\xb4\x3d\xa5\x68\xe8\x2e\xe3\x60\xb2\x5c\x87\x39\xa2\x78\xc2\xd4\xae\xfc\xb7\x2a\x23\x9d\x6f\x17\x85\x64\x08\x69\x25\xc0\xbd\x9f\x13\x9c", - b"\x9f\x22\x26\xe4\xe6\x3b\xf3\x5f\x31\xda\xb0\xa4\x14\x41\x2d\x6f\x27\x51\x31\x76\x71\xde\xc1\xfa\xf2\xa8\xd9\x29\xa4\xf7\xb1\x1e\xee\x12\x78\x99\x3c\xc1", - b"\x51\xd8\xae\x2f\xc8\x96\x3b\x9c\x59\x8f\x59\xa6\xb7\xaa\x98\x15\xa5\xb1\x71\x84\xea\x05\x9a\x44\x7c\xaf\xc4\x9d\xf9\xe9\x53\x18\x99\xf1\x7e\x24\x74\x13\xe7", - b"\x3b\x74\x4f\xa1\xfc\x62\x80\xcd\x80\xa1\xf7\x39\xa3\x38\xeb\x6a\x35\x1a\xbb\xae\xe2\x68\xaa\x07\xaf\x23\xb5\x72\x58\x29\x2f\xa3\x7d\x86\x48\x14\xe8\x35\x23\x0f", - b"\x84\xa7\x34\x8b\xb8\xdf\x95\x5c\xfa\x12\x53\x21\x7f\x6d\xc2\x07\xd3\xf2\x6d\x42\x56\xa9\x57\x60\xbb\x9f\x72\xac\x76\xd0\xb7\xc8\x52\xb3\x26\x27\x22\xf2\x8e\x93\x37", - b"\xfa\x67\xdd\xe6\x19\x12\x89\xe7\x00\x03\x3a\xf2\xdd\xbf\x6e\x54\xe6\x08\xbc\x6a\x60\x93\x0f\x83\x8b\x22\x65\xdf\x27\x65\xd5\xc7\xed\xfe\xc9\x7b\xab\xa2\xc2\x75\x32\x60", - b"\x60\x43\x03\xf5\xd9\xd7\x21\x41\xf0\x6d\x90\x3f\x15\x83\x26\x65\x99\x80\x37\x1f\xed\x03\x5e\xa0\x14\x57\x4d\x38\xbf\x7b\xcf\x4b\x52\x00\x7a\x84\x65\x91\xd7\x0f\x79\xc0\x8a", - b"\xbe\x07\x3d\x79\x47\xf6\x45\x37\xa8\xbc\x59\xf3\xbf\x19\x48\x7b\x09\x91\x0e\xf7\x01\xee\x2c\x4e\x8f\x3e\xe0\x7e\x76\x72\x44\xa3\x34\xc2\xd9\x93\xcc\xa9\x25\x82\x71\x66\x49\xb5", - b"\x06\xac\x48\xfa\x12\xab\xab\xa2\xe5\xbb\xef\x04\xbb\x0b\x25\xe4\x66\x48\x66\x16\x21\x49\x5f\x63\x84\x01\x0f\x59\x04\x70\x82\x5f\xd3\xeb\xe3\x3a\x23\x58\x84\x17\x2c\xa5\x36\xbb\xe1", - b"\x70\x5e\x58\x70\xfd\xe0\xca\x73\xbb\x63\x59\x05\x36\x71\x81\x2c\x3a\x10\x87\xd8\xa9\xd3\x24\x01\x04\x60\x3c\xf1\x49\x68\xea\x08\xf9\xf5\x77\xae\x34\x19\x9d\xe0\x2b\xca\xdf\x13\x52\x0f", - b"\x4c\xa4\xe5\x5c\x4f\xa8\xdb\x6e\x68\x15\xdc\x4a\x13\xc7\xc3\x64\x5d\xbf\x2b\xd5\x48\x38\x8a\xa1\x7d\xbb\x77\xfa\xbd\x89\xbe\x4c\x7e\xf7\x5d\x1e\x84\x06\x3a\xd5\xd0\xa5\xe0\x98\x85\x5b\x3d", - b"\xe4\x19\xc4\x82\xd3\x92\x3c\x18\xfb\x5a\x27\x66\xf0\x3d\xb2\x3f\x2e\x7b\x73\x12\xdd\x6f\x87\xa0\xb6\xcd\x6b\xce\x5f\x96\x78\xb8\x5b\x15\xf7\x9c\x8c\xee\xbf\x0b\x5e\xe3\x54\x32\xa3\x27\x22\x6c", - b"\xac\x79\x01\x29\xc1\xde\xed\x40\x6d\xb5\x34\x78\xd4\xe2\xef\xf5\xd0\x14\xf6\x22\xe1\xcc\x86\x65\x7d\xce\x45\x8a\xfa\x00\x4d\x3a\x8f\xb9\xdc\xfe\xd2\xbe\x70\x58\x5b\x39\x5a\x6d\x05\x0d\xb5\x19\x9c", - b"\xe8\x7d\x9d\xa1\xa4\x09\x76\x2e\xd1\x63\xcb\xc1\x23\x03\xd1\x6f\xc3\xf2\xcb\xe1\x2e\x0d\x20\xa0\x7e\xd1\x82\xa0\xf2\xd7\xf2\x4b\x4d\x2a\xbd\x20\x71\x41\x7c\x45\xe4\x72\xeb\xaf\x7c\xaa\xd7\xe8\x85\xcd", - b"\xd5\xa6\x8e\x2b\x0a\xd8\x8d\xa3\xac\xb4\x66\x46\x59\x3e\xde\x3e\x2a\xd2\x97\xa3\xda\x46\x4d\x27\xa6\xbf\x72\xca\xf5\xbc\xb7\xdd\x4b\xd4\x1b\xed\x7f\xcc\xeb\x3e\xbe\xe8\x12\x2e\xab\x0f\x62\xf7\x42\xa3\x00", - b"\x74\x32\x56\xba\x32\xdc\xfb\x59\xc0\x2e\x56\x7f\x7c\x13\xb8\xe9\x97\xd7\x16\x0e\x3b\x91\x25\xf2\xcb\x86\xfe\x59\xbe\x5e\x3b\x41\x7c\x71\x64\xe9\xeb\x79\x16\x4c\x56\x61\x27\xf2\xc8\xdc\x65\x21\xef\xfe\x74\x33", - b"\x7a\xd6\xe7\x88\xc7\x0b\x06\xcd\x7c\x48\xd5\x75\xbb\x3c\x93\xc9\x49\x4b\x21\x92\xab\xf7\x76\xd0\x9d\xb1\xcb\xeb\x53\x2d\xe2\xca\xe5\xa8\x07\x39\xed\xeb\xc8\x7c\x6a\xfe\xa5\x0e\x93\x00\x39\x2a\x1f\xb2\xd5\xad\x67", - b"\xb7\x1a\xc9\x57\xd2\xdd\x71\x15\x2e\x41\x2d\x32\xee\xb8\xf9\xe1\x66\x3a\xd1\xda\x6d\xa5\x1a\x5f\xb8\xc0\x34\xf5\x23\xfe\xee\xaf\xac\x4f\x7b\x19\x7a\x2b\x78\x6c\xd7\x50\x80\xc9\xeb\x08\x99\x3b\x65\x1f\xc6\x4c\x1f\x9c", - b"\x26\xc5\x7b\xa7\x10\x57\xb2\xee\xe3\x61\x94\xf7\x1a\x5a\xe4\xb6\xec\xc5\x2f\xf9\x24\xd5\x36\x71\xb5\x4a\xb1\xcc\x9b\x3d\x2f\x2a\x00\x84\x90\xfb\xc8\x26\x26\x8a\x36\x2c\x40\x13\x16\xce\x10\x0a\xe4\xd3\xa1\xab\x2c\xc2\xd2", - b"\x6a\x78\x6b\x9d\xa4\xd8\x70\x74\x02\x5b\xf8\xa3\x24\xc9\xca\xe5\x06\x90\xfe\x9b\x87\xd0\xaa\xd1\x0c\x8b\x7f\x8e\xb6\xf9\xb1\xae\xbe\x1c\x0a\x55\xef\xb8\x65\x7c\x98\xce\x60\x17\xa3\x3d\x1b\xc4\xf7\x97\x9a\xca\xcf\x14\x3d\x0a", - b"\x3a\x8c\xed\x5d\x6a\x3d\xc1\x02\x57\x49\xc2\xd7\x9f\xa3\x0a\x9b\x05\x79\x99\x3b\xf8\x04\x75\x16\x3c\xb1\x90\x2c\x48\xe4\x3e\x01\x13\xaa\x71\x9e\x19\xaf\xc7\x8b\x5a\x01\xd2\x07\x77\x9a\x59\x9f\x82\x7a\x2e\x93\xbe\x87\x5e\x44\x42", - b"\x52\x74\x1a\xf7\x42\x1b\x3e\x6b\xfc\xb6\xc8\xb9\xeb\x37\xfb\xf2\xd2\x90\x9a\xed\xb0\x8d\xc0\xf8\x98\xf9\xce\x55\xfd\x8e\x41\xa5\x7d\x17\x18\x1e\x7a\xf0\xd6\x06\x81\xda\x1d\x91\x7f\x86\xce\xf5\x75\x1d\x29\x3f\x9f\x8e\xe9\x7d\x94\x7b", - b"\x39\x73\xe8\x0b\xc3\xd9\x03\xce\x4d\x43\x1d\xa6\xb4\x6a\x76\xcb\x11\x45\x98\xd5\x4a\x2c\x31\x2b\x62\x3d\xfd\x7a\x0e\x2b\xd1\x8f\x09\x68\x6b\xab\xe0\x39\xfe\xfb\xe2\xe8\xdd\xc2\xf0\x75\xa1\x52\xb2\xf6\xb2\x21\x32\x56\xd7\xef\xb4\xb4\xb5", - b"\x6b\x8c\x1a\x0c\x09\x8d\xf3\xc5\xe2\xc5\xdb\x2d\xd3\x65\xdb\x78\x1c\xb5\x7f\x06\x64\xf7\x02\xcd\xc6\x39\x73\xdb\x65\x6d\xa0\x52\x25\x26\xee\x31\xa0\xd1\x79\x56\x0b\x7c\x1e\xb5\x54\x19\xc2\x57\x41\x66\xbe\xdc\x46\x1b\xd1\x10\x59\x07\x21\xf0", - b"\xa1\xf4\x69\x73\x40\x09\xdd\xec\x10\x91\x94\x22\x90\xba\x0d\x14\xfe\xf6\x26\x23\xca\x48\x04\xd4\x9f\xd3\xa5\x87\xfc\xfa\x19\x57\x1e\x78\xe2\xea\x5c\xc7\x48\x07\x9b\xda\xe7\x2c\x7d\xb2\x9c\xae\x7c\x2b\x64\x1f\x38\x65\xcc\x40\xaf\xe1\xa9\x92\x2d", - b"\x41\xca\x71\x62\x47\xdf\xf8\x76\xd6\x5e\x00\x7a\x25\x17\x02\xe4\x3a\x79\x07\x69\x87\x4e\xf3\x76\x46\x4c\xdf\x59\x48\x32\x46\x6f\xc2\x11\xd4\x7e\xb5\x23\xdd\x75\xeb\x0b\xe5\x95\x93\x7b\xd5\x28\x73\x06\xc8\x64\x1a\xf6\xb6\xda\x7f\xd7\x24\xba\x6e\x6a", - b"\x1e\x47\x24\x47\x13\xc3\xac\x6e\x3d\x02\xa9\xc2\x5a\x88\x3b\xb6\xe7\x91\x66\x27\xaa\xe7\xd6\x43\xc4\xcf\x35\x70\xf6\x5a\x5a\x79\xb7\x92\x4a\x4d\x26\x59\x16\xe7\x37\x38\xf2\x70\xd9\x6e\x7b\x3e\xc9\xd9\x80\xa5\x3c\xb5\x25\xa1\xf6\x84\xf6\x12\x73\x88\xa8", - b"\x2d\x33\xaf\x09\x07\x9e\x9f\x31\x44\x77\x5c\x7b\xb1\xcc\xbb\xfe\xc8\x4e\x8d\x95\x77\x1a\x7f\x35\xa0\x5d\xc7\xd4\x1d\x18\x91\x9c\xd0\x96\xda\xd1\x04\xd8\x5b\x2f\xb8\x92\x2f\x8c\xc3\xc3\x7d\xf2\xee\x3f\x63\x6c\x8c\xe6\xf2\x1f\xcc\x0b\xb2\xf3\xd9\x9c\xd5\xe7", - b"\x89\x9e\xf7\xf0\x25\xee\xd6\x80\x63\xda\x2e\x8a\xc6\x80\x5c\xdb\x6d\x8b\xa6\x19\x42\x43\x0e\x3a\xee\x95\xb1\xc3\xdd\x9a\xab\x30\x50\x0c\x3b\xbe\xe4\x13\x37\xd0\x5c\x70\xe5\x25\x3c\x0a\x2f\x51\x00\xc0\x25\xab\xaf\x93\x80\x49\xa6\x3d\x95\x0c\x18\x5f\x46\x71\x28", - b"\x05\x76\xde\xb4\x88\x88\xa2\x33\x2e\x75\x0d\xd7\x51\x11\x8b\xf7\xc5\xab\x5f\xad\x41\x89\xb2\x44\x6f\x5f\x65\x29\x48\xd6\xa9\xc5\x5f\x07\x2c\x9a\x4d\x6f\xec\x28\x79\x8f\x3f\x57\x50\xfd\xf0\x7e\xd9\x4d\x22\xe8\x6a\x32\xa8\x52\x4c\x92\x43\x6a\xab\x19\x84\x5d\x2d\x69", - b"\xbf\xac\x71\x56\x07\xa6\xf6\xb9\x9b\xfa\x62\x71\x59\x56\xd6\xe1\x9c\xbe\x3a\x21\x90\x43\xb3\xa3\x34\x9a\xe9\x97\x68\xfb\xa0\x7e\xaf\xd0\xe1\x46\xe3\x92\x04\x98\x8b\x67\x19\x6b\x3d\xcc\x9f\xfa\xc1\xe1\x69\xa0\x62\xa7\x02\x35\x10\xf2\x53\xd2\xc4\x67\xf8\x56\xd3\x29\xab", - b"\xf7\x9f\xdf\x21\xe0\x5d\x4d\x46\x5a\xa0\x20\xfe\x2b\x96\x54\x65\xbe\xcd\x85\x34\x3c\xca\xa5\xdc\xcb\x97\x5d\x54\x0f\x54\xfd\xad\xa0\x59\xe3\x34\xc7\x61\x5f\xe7\x34\xb1\x29\x7d\x89\xf1\xa6\xe1\x76\x02\x36\x20\x52\xd7\xaf\xc6\x2b\xee\xeb\x1b\x65\xb8\x7f\x03\x05\x08\xa3\xee", - b"\x69\x49\x44\x01\x1d\xa8\x75\x0e\x58\xd0\x37\x2e\x2a\xd9\x06\x54\xb3\x61\x06\xf0\xc0\xe7\x9e\x40\x76\xa0\xcb\x39\x3d\x6c\xc7\x7c\x41\xbb\xdd\xa7\x27\xb6\x9f\xb4\xf4\xcb\xe4\xfe\x0d\xaf\x3d\x5a\xce\x28\xc7\x5e\x43\x39\x51\xe5\x2e\x7b\x59\x25\x1f\xca\x42\xfa\x23\xaa\xf3\x58\x33", -]; - -//}}} -//------------------------------------------------------------------------------ -//{{{ Tables for error correction sizes - -/// `EC_BYTES_PER_BLOCK` provides the number of codewords (bytes) used for error -/// correction per block in each version. -/// -/// This is a copy of ISO/IEC 18004:2006, §6.5.1, Table 9 (The 4th column divide -/// by the sum of the 6th column). -static EC_BYTES_PER_BLOCK: [[usize; 4]; 44] = [ - // Normal versions. - [7, 10, 13, 17], // 1 - [10, 16, 22, 28], // 2 - [15, 26, 18, 22], // 3 - [20, 18, 26, 16], // 4 - [26, 24, 18, 22], // 5 - [18, 16, 24, 28], // 6 - [20, 18, 18, 26], // 7 - [24, 22, 22, 26], // 8 - [30, 22, 20, 24], // 9 - [18, 26, 24, 28], // 10 - [20, 30, 28, 24], // 11 - [24, 22, 26, 28], // 12 - [26, 22, 24, 22], // 13 - [30, 24, 20, 24], // 14 - [22, 24, 30, 24], // 15 - [24, 28, 24, 30], // 16 - [28, 28, 28, 28], // 17 - [30, 26, 28, 28], // 18 - [28, 26, 26, 26], // 19 - [28, 26, 30, 28], // 20 - [28, 26, 28, 30], // 21 - [28, 28, 30, 24], // 22 - [30, 28, 30, 30], // 23 - [30, 28, 30, 30], // 24 - [26, 28, 30, 30], // 25 - [28, 28, 28, 30], // 26 - [30, 28, 30, 30], // 27 - [30, 28, 30, 30], // 28 - [30, 28, 30, 30], // 29 - [30, 28, 30, 30], // 30 - [30, 28, 30, 30], // 31 - [30, 28, 30, 30], // 32 - [30, 28, 30, 30], // 33 - [30, 28, 30, 30], // 34 - [30, 28, 30, 30], // 35 - [30, 28, 30, 30], // 36 - [30, 28, 30, 30], // 37 - [30, 28, 30, 30], // 38 - [30, 28, 30, 30], // 39 - [30, 28, 30, 30], // 40 - // Micro versions. - [2, 0, 0, 0], // M1 - [5, 6, 0, 0], // M2 - [6, 8, 0, 0], // M3 - [8, 10, 14, 0], // M4 -]; - -/// `DATA_BYTES_PER_BLOCK` provides the number of codewords (bytes) used for -/// real data per block in each version. -/// -/// This is a copy of ISO/IEC 18004:2006, §6.5.1, Table 9 (The value "k" of the -/// 7th column, followed by the 6th column). -/// -/// Every entry is a 4-tuple. Take `DATA_BYTES_PER_BLOCK[39][3] == (15, 20, 16, 61)` -/// as an example, this means in version 40 with correction level H, there are -/// 20 blocks with 15 bytes in size, and 61 blocks with 16 bytes in size. -static DATA_BYTES_PER_BLOCK: [[(usize, usize, usize, usize); 4]; 44] = [ - // Normal versions. - [(19, 1, 0, 0), (16, 1, 0, 0), (13, 1, 0, 0), (9, 1, 0, 0)], // 1 - [(34, 1, 0, 0), (28, 1, 0, 0), (22, 1, 0, 0), (16, 1, 0, 0)], // 2 - [(55, 1, 0, 0), (44, 1, 0, 0), (17, 2, 0, 0), (13, 2, 0, 0)], // 3 - [(80, 1, 0, 0), (32, 2, 0, 0), (24, 2, 0, 0), (9, 4, 0, 0)], // 4 - [(108, 1, 0, 0), (43, 2, 0, 0), (15, 2, 16, 2), (11, 2, 12, 2)], // 5 - [(68, 2, 0, 0), (27, 4, 0, 0), (19, 4, 0, 0), (15, 4, 0, 0)], // 6 - [(78, 2, 0, 0), (31, 4, 0, 0), (14, 2, 15, 4), (13, 4, 14, 1)], // 7 - [(97, 2, 0, 0), (38, 2, 39, 2), (18, 4, 19, 2), (14, 4, 15, 2)], // 8 - [(116, 2, 0, 0), (36, 3, 37, 2), (16, 4, 17, 4), (12, 4, 13, 4)], // 9 - [(68, 2, 69, 2), (43, 4, 44, 1), (19, 6, 20, 2), (15, 6, 16, 2)], // 10 - [(81, 4, 0, 0), (50, 1, 51, 4), (22, 4, 23, 4), (12, 3, 13, 8)], // 11 - [(92, 2, 93, 2), (36, 6, 37, 2), (20, 4, 21, 6), (14, 7, 15, 4)], // 12 - [(107, 4, 0, 0), (37, 8, 38, 1), (20, 8, 21, 4), (11, 12, 12, 4)], // 13 - [(115, 3, 116, 1), (40, 4, 41, 5), (16, 11, 17, 5), (12, 11, 13, 5)], // 14 - [(87, 5, 88, 1), (41, 5, 42, 5), (24, 5, 25, 7), (12, 11, 13, 7)], // 15 - [(98, 5, 99, 1), (45, 7, 46, 3), (19, 15, 20, 2), (15, 3, 16, 13)], // 16 - [(107, 1, 108, 5), (46, 10, 47, 1), (22, 1, 23, 15), (14, 2, 15, 17)], // 17 - [(120, 5, 121, 1), (43, 9, 44, 4), (22, 17, 23, 1), (14, 2, 15, 19)], // 18 - [(113, 3, 114, 4), (44, 3, 45, 11), (21, 17, 22, 4), (13, 9, 14, 16)], // 19 - [(107, 3, 108, 5), (41, 3, 42, 13), (24, 15, 25, 5), (15, 15, 16, 10)], // 20 - [(116, 4, 117, 4), (42, 17, 0, 0), (22, 17, 23, 6), (16, 19, 17, 6)], // 21 - [(111, 2, 112, 7), (46, 17, 0, 0), (24, 7, 25, 16), (13, 34, 0, 0)], // 22 - [(121, 4, 122, 5), (47, 4, 48, 14), (24, 11, 25, 14), (15, 16, 16, 14)], // 23 - [(117, 6, 118, 4), (45, 6, 46, 14), (24, 11, 25, 16), (16, 30, 17, 2)], // 24 - [(106, 8, 107, 4), (47, 8, 48, 13), (24, 7, 25, 22), (15, 22, 16, 13)], // 25 - [(114, 10, 115, 2), (46, 19, 47, 4), (22, 28, 23, 6), (16, 33, 17, 4)], // 26 - [(122, 8, 123, 4), (45, 22, 46, 3), (23, 8, 24, 26), (15, 12, 16, 28)], // 27 - [(117, 3, 118, 10), (45, 3, 46, 23), (24, 4, 25, 31), (15, 11, 16, 31)], // 28 - [(116, 7, 117, 7), (45, 21, 46, 7), (23, 1, 24, 37), (15, 19, 16, 26)], // 29 - [(115, 5, 116, 10), (47, 19, 48, 10), (24, 15, 25, 25), (15, 23, 16, 25)], // 30 - [(115, 13, 116, 3), (46, 2, 47, 29), (24, 42, 25, 1), (15, 23, 16, 28)], // 31 - [(115, 17, 0, 0), (46, 10, 47, 23), (24, 10, 25, 35), (15, 19, 16, 35)], // 32 - [(115, 17, 116, 1), (46, 14, 47, 21), (24, 29, 25, 19), (15, 11, 16, 46)], // 33 - [(115, 13, 116, 6), (46, 14, 47, 23), (24, 44, 25, 7), (16, 59, 17, 1)], // 34 - [(121, 12, 122, 7), (47, 12, 48, 26), (24, 39, 25, 14), (15, 22, 16, 41)], // 35 - [(121, 6, 122, 14), (47, 6, 48, 34), (24, 46, 25, 10), (15, 2, 16, 64)], // 36 - [(122, 17, 123, 4), (46, 29, 47, 14), (24, 49, 25, 10), (15, 24, 16, 46)], // 37 - [(122, 4, 123, 18), (46, 13, 47, 32), (24, 48, 25, 14), (15, 42, 16, 32)], // 38 - [(117, 20, 118, 4), (47, 40, 48, 7), (24, 43, 25, 22), (15, 10, 16, 67)], // 39 - [(118, 19, 119, 6), (47, 18, 48, 31), (24, 34, 25, 34), (15, 20, 16, 61)], // 40 - // Micro versions. - [(3, 1, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0)], // M1 - [(5, 1, 0, 0), (4, 1, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0)], // M2 - [(11, 1, 0, 0), (9, 1, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0)], // M3 - [(16, 1, 0, 0), (14, 1, 0, 0), (10, 1, 0, 0), (0, 0, 0, 0)], // M4 -]; - -//}}} diff --git a/qrcode-rust/src/lib.rs b/qrcode-rust/src/lib.rs deleted file mode 100644 index f7346d9..0000000 --- a/qrcode-rust/src/lib.rs +++ /dev/null @@ -1,382 +0,0 @@ -//! QRCode encoder -//! -//! This crate provides a QR code and Micro QR code encoder for binary data. -//! -//! -//! - -#![no_std] -#![cfg_attr(feature = "image", doc = "```rust")] -#![cfg_attr(not(feature = "image"), doc = "```ignore")] -//! use qrcode::QrCode; -//! use image::Luma; -//! -//! // Encode some data into bits. -//! let code = QrCode::new(b"01234567").unwrap(); -//! -//! // Render the bits into an image. -//! let image = code.render::<Luma<u8>>().build(); -//! -//! // Save the image. -//! # if cfg!(unix) { -//! image.save("/tmp/qrcode.png").unwrap(); -//! # } -//! -//! // You can also render it into a string. -//! let string = code.render() -//! .light_color(' ') -//! .dark_color('#') -//! .build(); -//! println!("{}", string); -//! ``` - -#![cfg_attr(feature = "bench", feature(test, external_doc))] // Unstable libraries -// #![deny(warnings, clippy::pedantic)] -#![allow( - clippy::must_use_candidate, // This is just annoying. - clippy::use_self, // Rust 1.33 doesn't support Self::EnumVariant, let's try again in 1.37. -)] -#![cfg_attr(feature = "bench", doc(include = "../README.md"))] -// ^ make sure we can test our README.md. - -#[macro_use] -extern crate alloc; - -use core::ops::Index; - -pub mod bits; -pub mod canvas; -mod cast; -pub mod ec; -pub mod optimize; -pub mod render; -pub mod types; - -pub use crate::types::{Color, EcLevel, QrResult, Version}; - -use crate::cast::As; -use crate::render::{Pixel, Renderer}; -use alloc::string::String; -use alloc::vec::Vec; -// use checked_int_cast::CheckedIntCast; - -/// The encoded QR code symbol. -#[derive(Clone)] -pub struct QrCode { - content: Vec<Color>, - version: Version, - ec_level: EcLevel, - width: usize, -} - -impl QrCode { - /// Constructs a new QR code which automatically encodes the given data. - /// - /// This method uses the "medium" error correction level and automatically - /// chooses the smallest QR code. - /// - /// use qrcode::QrCode; - /// - /// let code = QrCode::new(b"Some data").unwrap(); - /// - /// # Errors - /// - /// Returns error if the QR code cannot be constructed, e.g. when the data - /// is too long. - pub fn new<D: AsRef<[u8]>>(data: D) -> QrResult<Self> { - Self::with_error_correction_level(data, EcLevel::M) - } - - /// Constructs a new QR code which automatically encodes the given data at a - /// specific error correction level. - /// - /// This method automatically chooses the smallest QR code. - /// - /// use qrcode::{QrCode, EcLevel}; - /// - /// let code = QrCode::with_error_correction_level(b"Some data", EcLevel::H).unwrap(); - /// - /// # Errors - /// - /// Returns error if the QR code cannot be constructed, e.g. when the data - /// is too long. - pub fn with_error_correction_level<D: AsRef<[u8]>>(data: D, ec_level: EcLevel) -> QrResult<Self> { - let bits = bits::encode_auto(data.as_ref(), ec_level)?; - Self::with_bits(bits, ec_level) - } - - /// Constructs a new QR code for the given version and error correction - /// level. - /// - /// use qrcode::{QrCode, Version, EcLevel}; - /// - /// let code = QrCode::with_version(b"Some data", Version::Normal(5), EcLevel::M).unwrap(); - /// - /// This method can also be used to generate Micro QR code. - /// - /// use qrcode::{QrCode, Version, EcLevel}; - /// - /// let micro_code = QrCode::with_version(b"123", Version::Micro(1), EcLevel::L).unwrap(); - /// - /// # Errors - /// - /// Returns error if the QR code cannot be constructed, e.g. when the data - /// is too long, or when the version and error correction level are - /// incompatible. - pub fn with_version<D: AsRef<[u8]>>(data: D, version: Version, ec_level: EcLevel) -> QrResult<Self> { - let mut bits = bits::Bits::new(version); - bits.push_optimal_data(data.as_ref())?; - bits.push_terminator(ec_level)?; - Self::with_bits(bits, ec_level) - } - - /// Constructs a new QR code with encoded bits. - /// - /// Use this method only if there are very special need to manipulate the - /// raw bits before encoding. Some examples are: - /// - /// * Encode data using specific character set with ECI - /// * Use the FNC1 modes - /// * Avoid the optimal segmentation algorithm - /// - /// See the `Bits` structure for detail. - /// - /// #![allow(unused_must_use)] - /// - /// use qrcode::{QrCode, Version, EcLevel}; - /// use qrcode::bits::Bits; - /// - /// let mut bits = Bits::new(Version::Normal(1)); - /// bits.push_eci_designator(9); - /// bits.push_byte_data(b"\xca\xfe\xe4\xe9\xea\xe1\xf2 QR"); - /// bits.push_terminator(EcLevel::L); - /// let qrcode = QrCode::with_bits(bits, EcLevel::L); - /// - /// # Errors - /// - /// Returns error if the QR code cannot be constructed, e.g. when the bits - /// are too long, or when the version and error correction level are - /// incompatible. - pub fn with_bits(bits: bits::Bits, ec_level: EcLevel) -> QrResult<Self> { - let version = bits.version(); - let data = bits.into_bytes(); - let (encoded_data, ec_data) = ec::construct_codewords(&data, version, ec_level)?; - let mut canvas = canvas::Canvas::new(version, ec_level); - canvas.draw_all_functional_patterns(); - canvas.draw_data(&encoded_data, &ec_data); - let canvas = canvas.apply_best_mask(); - Ok(Self { content: canvas.into_colors(), version, ec_level, width: version.width().as_usize() }) - } - - /// Gets the version of this QR code. - pub fn version(&self) -> Version { - self.version - } - - /// Gets the error correction level of this QR code. - pub fn error_correction_level(&self) -> EcLevel { - self.ec_level - } - - /// Gets the number of modules per side, i.e. the width of this QR code. - /// - /// The width here does not contain the quiet zone paddings. - pub fn width(&self) -> usize { - self.width - } - - /// Gets the maximum number of allowed erratic modules can be introduced - /// before the data becomes corrupted. Note that errors should not be - /// introduced to functional modules. - pub fn max_allowed_errors(&self) -> usize { - ec::max_allowed_errors(self.version, self.ec_level).expect("invalid version or ec_level") - } - - /// Checks whether a module at coordinate (x, y) is a functional module or - /// not. - pub fn is_functional(&self, x: usize, y: usize) -> bool { - let x: i16 = x.as_i16(); - let y: i16 = y.as_i16(); - canvas::is_functional(self.version, self.version.width(), x, y) - } - - /// Converts the QR code into a human-readable string. This is mainly for - /// debugging only. - pub fn to_debug_str(&self, on_char: char, off_char: char) -> String { - self.render().quiet_zone(false).dark_color(on_char).light_color(off_char).build() - } - - /// Converts the QR code to a vector of booleans. Each entry represents the - /// color of the module, with "true" means dark and "false" means light. - #[deprecated(since = "0.4.0", note = "use `to_colors()` instead")] - pub fn to_vec(&self) -> Vec<bool> { - self.content.iter().map(|c| *c != Color::Light).collect() - } - - /// Converts the QR code to a vector of booleans. Each entry represents the - /// color of the module, with "true" means dark and "false" means light. - #[deprecated(since = "0.4.0", note = "use `into_colors()` instead")] - pub fn into_vec(self) -> Vec<bool> { - self.content.into_iter().map(|c| c != Color::Light).collect() - } - - /// Converts the QR code to a vector of colors. - pub fn to_colors(&self) -> Vec<Color> { - self.content.clone() - } - - /// Converts the QR code to a vector of colors. - pub fn into_colors(self) -> Vec<Color> { - self.content - } - - /// Renders the QR code into an image. The result is an image builder, which - /// you may do some additional configuration before copying it into a - /// concrete image. - /// - /// # Examples - /// - #[cfg_attr(feature = "image", doc = " ```rust")] - #[cfg_attr(not(feature = "image"), doc = " ```ignore")] - /// # use qrcode::QrCode; - /// # use image::Rgb; - /// - /// let image = QrCode::new(b"hello").unwrap() - /// .render() - /// .dark_color(Rgb([0, 0, 128])) - /// .light_color(Rgb([224, 224, 224])) // adjust colors - /// .quiet_zone(false) // disable quiet zone (white border) - /// .min_dimensions(300, 300) // sets minimum image size - /// .build(); - /// ``` - /// - /// Note: the `image` crate itself also provides method to rotate the image, - /// or overlay a logo on top of the QR code. - pub fn render<P: Pixel>(&self) -> Renderer<P> { - let quiet_zone = if self.version.is_micro() { 2 } else { 4 }; - Renderer::new(&self.content, self.width, quiet_zone) - } -} - -impl Index<(usize, usize)> for QrCode { - type Output = Color; - - fn index(&self, (x, y): (usize, usize)) -> &Color { - let index = y * self.width + x; - &self.content[index] - } -} - -#[cfg(test)] -mod tests { - use crate::{EcLevel, QrCode, Version}; - - #[test] - fn test_annex_i_qr() { - // This uses the ISO Annex I as test vector. - let code = QrCode::with_version(b"01234567", Version::Normal(1), EcLevel::M).unwrap(); - assert_eq!( - &*code.to_debug_str('#', '.'), - "\ - #######..#.##.#######\n\ - #.....#..####.#.....#\n\ - #.###.#.#.....#.###.#\n\ - #.###.#.##....#.###.#\n\ - #.###.#.#.###.#.###.#\n\ - #.....#.#...#.#.....#\n\ - #######.#.#.#.#######\n\ - ........#..##........\n\ - #.#####..#..#.#####..\n\ - ...#.#.##.#.#..#.##..\n\ - ..#...##.#.#.#..#####\n\ - ....#....#.....####..\n\ - ...######..#.#..#....\n\ - ........#.#####..##..\n\ - #######..##.#.##.....\n\ - #.....#.#.#####...#.#\n\ - #.###.#.#...#..#.##..\n\ - #.###.#.##..#..#.....\n\ - #.###.#.#.##.#..#.#..\n\ - #.....#........##.##.\n\ - #######.####.#..#.#.." - ); - } - - #[test] - fn test_annex_i_micro_qr() { - let code = QrCode::with_version(b"01234567", Version::Micro(2), EcLevel::L).unwrap(); - assert_eq!( - &*code.to_debug_str('#', '.'), - "\ - #######.#.#.#\n\ - #.....#.###.#\n\ - #.###.#..##.#\n\ - #.###.#..####\n\ - #.###.#.###..\n\ - #.....#.#...#\n\ - #######..####\n\ - .........##..\n\ - ##.#....#...#\n\ - .##.#.#.#.#.#\n\ - ###..#######.\n\ - ...#.#....##.\n\ - ###.#..##.###" - ); - } -} - -#[cfg(all(test, feature = "image"))] -mod image_tests { - use crate::{EcLevel, QrCode, Version}; - use image::{load_from_memory, Luma, Rgb}; - - #[test] - fn test_annex_i_qr_as_image() { - let code = QrCode::new(b"01234567").unwrap(); - let image = code.render::<Luma<u8>>().build(); - let expected = load_from_memory(include_bytes!("test_annex_i_qr_as_image.png")).unwrap().to_luma(); - assert_eq!(image.dimensions(), expected.dimensions()); - assert_eq!(image.into_raw(), expected.into_raw()); - } - - #[test] - fn test_annex_i_micro_qr_as_image() { - let code = QrCode::with_version(b"01234567", Version::Micro(2), EcLevel::L).unwrap(); - let image = code - .render() - .min_dimensions(200, 200) - .dark_color(Rgb([128, 0, 0])) - .light_color(Rgb([255, 255, 128])) - .build(); - let expected = load_from_memory(include_bytes!("test_annex_i_micro_qr_as_image.png")).unwrap().to_rgb(); - assert_eq!(image.dimensions(), expected.dimensions()); - assert_eq!(image.into_raw(), expected.into_raw()); - } -} - -#[cfg(all(test, feature = "svg"))] -mod svg_tests { - use crate::render::svg::Color as SvgColor; - use crate::{EcLevel, QrCode, Version}; - - #[test] - fn test_annex_i_qr_as_svg() { - let code = QrCode::new(b"01234567").unwrap(); - let image = code.render::<SvgColor>().build(); - let expected = include_str!("test_annex_i_qr_as_svg.svg"); - assert_eq!(&image, expected); - } - - #[test] - fn test_annex_i_micro_qr_as_svg() { - let code = QrCode::with_version(b"01234567", Version::Micro(2), EcLevel::L).unwrap(); - let image = code - .render() - .min_dimensions(200, 200) - .dark_color(SvgColor("#800000")) - .light_color(SvgColor("#ffff80")) - .build(); - let expected = include_str!("test_annex_i_micro_qr_as_svg.svg"); - assert_eq!(&image, expected); - } -} diff --git a/qrcode-rust/src/main.rs b/qrcode-rust/src/main.rs deleted file mode 100644 index 67946c8..0000000 --- a/qrcode-rust/src/main.rs +++ /dev/null @@ -1,11 +0,0 @@ -use qrcode::{render::unicode, QrCode}; - -fn main() { - let code = QrCode::new("https://www.youtube.com/watch?v=p7YXXieghto").unwrap(); - let image = code - .render::<unicode::Dense1x2>() - .dark_color(unicode::Dense1x2::Light) - .light_color(unicode::Dense1x2::Dark) - .build(); - println!("{}", image); -} diff --git a/qrcode-rust/src/optimize.rs b/qrcode-rust/src/optimize.rs deleted file mode 100644 index 1d3af2c..0000000 --- a/qrcode-rust/src/optimize.rs +++ /dev/null @@ -1,684 +0,0 @@ -//! Find the optimal data mode sequence to encode a piece of data. -use crate::types::{Mode, Version}; - -use core::slice::Iter; - -#[cfg(feature = "bench")] -extern crate test; - -//------------------------------------------------------------------------------ -//{{{ Segment - -/// A segment of data committed to an encoding mode. -#[derive(PartialEq, Eq, Debug, Copy, Clone)] -pub struct Segment { - /// The encoding mode of the segment of data. - pub mode: Mode, - - /// The start index of the segment. - pub begin: usize, - - /// The end index (exclusive) of the segment. - pub end: usize, -} - -impl Segment { - /// Compute the number of bits (including the size of the mode indicator and - /// length bits) when this segment is encoded. - pub fn encoded_len(&self, version: Version) -> usize { - let byte_size = self.end - self.begin; - let chars_count = if self.mode == Mode::Kanji { byte_size / 2 } else { byte_size }; - - let mode_bits_count = version.mode_bits_count(); - let length_bits_count = self.mode.length_bits_count(version); - let data_bits_count = self.mode.data_bits_count(chars_count); - - mode_bits_count + length_bits_count + data_bits_count - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Parser - -/// This iterator is basically equivalent to -/// -/// ```ignore -/// data.map(|c| ExclCharSet::from_u8(*c)) -/// .chain(Some(ExclCharSet::End).move_iter()) -/// .enumerate() -/// ``` -/// -/// But the type is too hard to write, thus the new type. -/// -struct EcsIter<I> { - base: I, - index: usize, - ended: bool, -} - -impl<'a, I: Iterator<Item = &'a u8>> Iterator for EcsIter<I> { - type Item = (usize, ExclCharSet); - - fn next(&mut self) -> Option<(usize, ExclCharSet)> { - if self.ended { - return None; - } - - match self.base.next() { - None => { - self.ended = true; - Some((self.index, ExclCharSet::End)) - } - Some(c) => { - let old_index = self.index; - self.index += 1; - Some((old_index, ExclCharSet::from_u8(*c))) - } - } - } -} - -/// QR code data parser to classify the input into distinct segments. -pub struct Parser<'a> { - ecs_iter: EcsIter<Iter<'a, u8>>, - state: State, - begin: usize, - pending_single_byte: bool, -} - -impl<'a> Parser<'a> { - /// Creates a new iterator which parse the data into segments that only - /// contains their exclusive subsets. No optimization is done at this point. - /// - /// use qrcode::optimize::{Parser, Segment}; - /// use qrcode::types::Mode::{Alphanumeric, Numeric, Byte}; - /// - /// let parse_res = Parser::new(b"ABC123abcd").collect::<Vec<Segment>>(); - /// assert_eq!(parse_res, vec![Segment { mode: Alphanumeric, begin: 0, end: 3 }, - /// Segment { mode: Numeric, begin: 3, end: 6 }, - /// Segment { mode: Byte, begin: 6, end: 10 }]); - /// - pub fn new(data: &[u8]) -> Parser { - Parser { - ecs_iter: EcsIter { base: data.iter(), index: 0, ended: false }, - state: State::Init, - begin: 0, - pending_single_byte: false, - } - } -} - -impl<'a> Iterator for Parser<'a> { - type Item = Segment; - - fn next(&mut self) -> Option<Segment> { - if self.pending_single_byte { - self.pending_single_byte = false; - self.begin += 1; - return Some(Segment { mode: Mode::Byte, begin: self.begin - 1, end: self.begin }); - } - - loop { - let (i, ecs) = match self.ecs_iter.next() { - None => return None, - Some(a) => a, - }; - let (next_state, action) = STATE_TRANSITION[self.state as usize + ecs as usize]; - self.state = next_state; - - let old_begin = self.begin; - let push_mode = match action { - Action::Idle => continue, - Action::Numeric => Mode::Numeric, - Action::Alpha => Mode::Alphanumeric, - Action::Byte => Mode::Byte, - Action::Kanji => Mode::Kanji, - Action::KanjiAndSingleByte => { - let next_begin = i - 1; - if self.begin == next_begin { - Mode::Byte - } else { - self.pending_single_byte = true; - self.begin = next_begin; - return Some(Segment { mode: Mode::Kanji, begin: old_begin, end: next_begin }); - } - } - }; - - self.begin = i; - return Some(Segment { mode: push_mode, begin: old_begin, end: i }); - } - } -} - -#[cfg(test)] -mod parse_tests { - use alloc::vec::Vec; - - use crate::optimize::{Parser, Segment}; - use crate::types::Mode; - - fn parse(data: &[u8]) -> Vec<Segment> { - Parser::new(data).collect() - } - - #[test] - fn test_parse_1() { - let segs = parse(b"01049123451234591597033130128%10ABC123"); - assert_eq!( - segs, - vec![ - Segment { mode: Mode::Numeric, begin: 0, end: 29 }, - Segment { mode: Mode::Alphanumeric, begin: 29, end: 30 }, - Segment { mode: Mode::Numeric, begin: 30, end: 32 }, - Segment { mode: Mode::Alphanumeric, begin: 32, end: 35 }, - Segment { mode: Mode::Numeric, begin: 35, end: 38 }, - ] - ); - } - - #[test] - fn test_parse_shift_jis_example_1() { - let segs = parse(b"\x82\xa0\x81\x41\x41\xb1\x81\xf0"); // "あ、AアÅ" - assert_eq!( - segs, - vec![ - Segment { mode: Mode::Kanji, begin: 0, end: 4 }, - Segment { mode: Mode::Alphanumeric, begin: 4, end: 5 }, - Segment { mode: Mode::Byte, begin: 5, end: 6 }, - Segment { mode: Mode::Kanji, begin: 6, end: 8 }, - ] - ); - } - - #[test] - fn test_parse_utf_8() { - // Mojibake? - let segs = parse(b"\xe3\x81\x82\xe3\x80\x81A\xef\xbd\xb1\xe2\x84\xab"); - assert_eq!( - segs, - vec![ - Segment { mode: Mode::Kanji, begin: 0, end: 4 }, - Segment { mode: Mode::Byte, begin: 4, end: 5 }, - Segment { mode: Mode::Kanji, begin: 5, end: 7 }, - Segment { mode: Mode::Byte, begin: 7, end: 10 }, - Segment { mode: Mode::Kanji, begin: 10, end: 12 }, - Segment { mode: Mode::Byte, begin: 12, end: 13 }, - ] - ); - } - - #[test] - fn test_not_kanji_1() { - let segs = parse(b"\x81\x30"); - assert_eq!( - segs, - vec![Segment { mode: Mode::Byte, begin: 0, end: 1 }, Segment { mode: Mode::Numeric, begin: 1, end: 2 },] - ); - } - - #[test] - fn test_not_kanji_2() { - // Note that it's implementation detail that the byte seq is split into - // two. Perhaps adjust the test to check for this. - let segs = parse(b"\xeb\xc0"); - assert_eq!( - segs, - vec![Segment { mode: Mode::Byte, begin: 0, end: 1 }, Segment { mode: Mode::Byte, begin: 1, end: 2 },] - ); - } - - #[test] - fn test_not_kanji_3() { - let segs = parse(b"\x81\x7f"); - assert_eq!( - segs, - vec![Segment { mode: Mode::Byte, begin: 0, end: 1 }, Segment { mode: Mode::Byte, begin: 1, end: 2 },] - ); - } - - #[test] - fn test_not_kanji_4() { - let segs = parse(b"\x81\x40\x81"); - assert_eq!( - segs, - vec![Segment { mode: Mode::Kanji, begin: 0, end: 2 }, Segment { mode: Mode::Byte, begin: 2, end: 3 },] - ); - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Optimizer - -pub struct Optimizer<I> { - parser: I, - last_segment: Segment, - last_segment_size: usize, - version: Version, - ended: bool, -} - -impl<I: Iterator<Item = Segment>> Optimizer<I> { - /// Optimize the segments by combining adjacent segments when possible. - /// - /// Currently this method uses a greedy algorithm by combining segments from - /// left to right until the new segment is longer than before. This method - /// does *not* use Annex J from the ISO standard. - /// - pub fn new(mut segments: I, version: Version) -> Self { - match segments.next() { - None => Self { - parser: segments, - last_segment: Segment { mode: Mode::Numeric, begin: 0, end: 0 }, - last_segment_size: 0, - version, - ended: true, - }, - Some(segment) => Self { - parser: segments, - last_segment: segment, - last_segment_size: segment.encoded_len(version), - version, - ended: false, - }, - } - } -} - -impl<'a> Parser<'a> { - pub fn optimize(self, version: Version) -> Optimizer<Parser<'a>> { - Optimizer::new(self, version) - } -} - -impl<I: Iterator<Item = Segment>> Iterator for Optimizer<I> { - type Item = Segment; - - fn next(&mut self) -> Option<Segment> { - if self.ended { - return None; - } - - loop { - match self.parser.next() { - None => { - self.ended = true; - return Some(self.last_segment); - } - Some(segment) => { - let seg_size = segment.encoded_len(self.version); - - let new_segment = Segment { - mode: self.last_segment.mode.max(segment.mode), - begin: self.last_segment.begin, - end: segment.end, - }; - let new_size = new_segment.encoded_len(self.version); - - if self.last_segment_size + seg_size >= new_size { - self.last_segment = new_segment; - self.last_segment_size = new_size; - } else { - let old_segment = self.last_segment; - self.last_segment = segment; - self.last_segment_size = seg_size; - return Some(old_segment); - } - } - } - } - } -} - -/// Computes the total encoded length of all segments. -pub fn total_encoded_len(segments: &[Segment], version: Version) -> usize { - segments.iter().map(|seg| seg.encoded_len(version)).sum() -} - -#[cfg(test)] -mod optimize_tests { - use alloc::vec::Vec; - - use crate::optimize::{total_encoded_len, Optimizer, Segment}; - use crate::types::{Mode, Version}; - - fn test_optimization_result(given: Vec<Segment>, expected: Vec<Segment>, version: Version) { - let prev_len = total_encoded_len(&given, version); - let opt_segs = Optimizer::new(given.iter().copied(), version).collect::<Vec<_>>(); - let new_len = total_encoded_len(&opt_segs, version); - if given != opt_segs { - assert!(prev_len > new_len, "{} > {}", prev_len, new_len); - } - assert!( - opt_segs == expected, - "Optimization gave something better: {} < {} ({:?})", - new_len, - total_encoded_len(&expected, version), - opt_segs - ); - } - - #[test] - fn test_example_1() { - test_optimization_result( - vec![ - Segment { mode: Mode::Alphanumeric, begin: 0, end: 3 }, - Segment { mode: Mode::Numeric, begin: 3, end: 6 }, - Segment { mode: Mode::Byte, begin: 6, end: 10 }, - ], - vec![ - Segment { mode: Mode::Alphanumeric, begin: 0, end: 6 }, - Segment { mode: Mode::Byte, begin: 6, end: 10 }, - ], - Version::Normal(1), - ); - } - - #[test] - fn test_example_2() { - test_optimization_result( - vec![ - Segment { mode: Mode::Numeric, begin: 0, end: 29 }, - Segment { mode: Mode::Alphanumeric, begin: 29, end: 30 }, - Segment { mode: Mode::Numeric, begin: 30, end: 32 }, - Segment { mode: Mode::Alphanumeric, begin: 32, end: 35 }, - Segment { mode: Mode::Numeric, begin: 35, end: 38 }, - ], - vec![ - Segment { mode: Mode::Numeric, begin: 0, end: 29 }, - Segment { mode: Mode::Alphanumeric, begin: 29, end: 38 }, - ], - Version::Normal(9), - ); - } - - #[test] - fn test_example_3() { - test_optimization_result( - vec![ - Segment { mode: Mode::Kanji, begin: 0, end: 4 }, - Segment { mode: Mode::Alphanumeric, begin: 4, end: 5 }, - Segment { mode: Mode::Byte, begin: 5, end: 6 }, - Segment { mode: Mode::Kanji, begin: 6, end: 8 }, - ], - vec![Segment { mode: Mode::Byte, begin: 0, end: 8 }], - Version::Normal(1), - ); - } - - #[test] - fn test_example_4() { - test_optimization_result( - vec![Segment { mode: Mode::Kanji, begin: 0, end: 10 }, Segment { mode: Mode::Byte, begin: 10, end: 11 }], - vec![Segment { mode: Mode::Kanji, begin: 0, end: 10 }, Segment { mode: Mode::Byte, begin: 10, end: 11 }], - Version::Normal(1), - ); - } - - #[test] - fn test_annex_j_guideline_1a() { - test_optimization_result( - vec![ - Segment { mode: Mode::Numeric, begin: 0, end: 3 }, - Segment { mode: Mode::Alphanumeric, begin: 3, end: 4 }, - ], - vec![ - Segment { mode: Mode::Numeric, begin: 0, end: 3 }, - Segment { mode: Mode::Alphanumeric, begin: 3, end: 4 }, - ], - Version::Micro(2), - ); - } - - #[test] - fn test_annex_j_guideline_1b() { - test_optimization_result( - vec![ - Segment { mode: Mode::Numeric, begin: 0, end: 2 }, - Segment { mode: Mode::Alphanumeric, begin: 2, end: 4 }, - ], - vec![Segment { mode: Mode::Alphanumeric, begin: 0, end: 4 }], - Version::Micro(2), - ); - } - - #[test] - fn test_annex_j_guideline_1c() { - test_optimization_result( - vec![ - Segment { mode: Mode::Numeric, begin: 0, end: 3 }, - Segment { mode: Mode::Alphanumeric, begin: 3, end: 4 }, - ], - vec![Segment { mode: Mode::Alphanumeric, begin: 0, end: 4 }], - Version::Micro(3), - ); - } -} - -#[cfg(feature = "bench")] -#[bench] -fn bench_optimize(bencher: &mut test::Bencher) { - use crate::types::Version; - - let data = b"QR\x83R\x81[\x83h\x81i\x83L\x83\x85\x81[\x83A\x81[\x83\x8b\x83R\x81[\x83h\x81j\ - \x82\xc6\x82\xcd\x81A1994\x94N\x82\xc9\x83f\x83\x93\x83\\\x81[\x82\xcc\x8aJ\ - \x94\xad\x95\x94\x96\xe5\x81i\x8c\xbb\x8d\xdd\x82\xcd\x95\xaa\x97\xa3\x82\xb5\x83f\ - \x83\x93\x83\\\x81[\x83E\x83F\x81[\x83u\x81j\x82\xaa\x8aJ\x94\xad\x82\xb5\x82\xbd\ - \x83}\x83g\x83\x8a\x83b\x83N\x83X\x8c^\x93\xf1\x8e\x9f\x8c\xb3\x83R\x81[\x83h\ - \x82\xc5\x82\xa0\x82\xe9\x81B\x82\xc8\x82\xa8\x81AQR\x83R\x81[\x83h\x82\xc6\ - \x82\xa2\x82\xa4\x96\xbc\x8f\xcc\x81i\x82\xa8\x82\xe6\x82\xd1\x92P\x8c\xea\x81j\ - \x82\xcd\x83f\x83\x93\x83\\\x81[\x83E\x83F\x81[\x83u\x82\xcc\x93o\x98^\x8f\xa4\ - \x95W\x81i\x91\xe64075066\x8d\x86\x81j\x82\xc5\x82\xa0\x82\xe9\x81BQR\x82\xcd\ - Quick Response\x82\xc9\x97R\x97\x88\x82\xb5\x81A\x8d\x82\x91\xac\x93\xc7\x82\xdd\ - \x8e\xe6\x82\xe8\x82\xaa\x82\xc5\x82\xab\x82\xe9\x82\xe6\x82\xa4\x82\xc9\x8aJ\ - \x94\xad\x82\xb3\x82\xea\x82\xbd\x81B\x93\x96\x8f\x89\x82\xcd\x8e\xa9\x93\xae\ - \x8e\xd4\x95\x94\x95i\x8dH\x8f\xea\x82\xe2\x94z\x91\x97\x83Z\x83\x93\x83^\x81[\ - \x82\xc8\x82\xc7\x82\xc5\x82\xcc\x8eg\x97p\x82\xf0\x94O\x93\xaa\x82\xc9\x8aJ\ - \x94\xad\x82\xb3\x82\xea\x82\xbd\x82\xaa\x81A\x8c\xbb\x8d\xdd\x82\xc5\x82\xcd\x83X\ - \x83}\x81[\x83g\x83t\x83H\x83\x93\x82\xcc\x95\x81\x8by\x82\xc8\x82\xc7\x82\xc9\ - \x82\xe6\x82\xe8\x93\xfa\x96{\x82\xc9\x8c\xc0\x82\xe7\x82\xb8\x90\xa2\x8aE\x93I\ - \x82\xc9\x95\x81\x8by\x82\xb5\x82\xc4\x82\xa2\x82\xe9\x81B"; - bencher.iter(|| Parser::new(data).optimize(Version::Normal(15))); -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Internal types and data for parsing - -/// All values of `u8` can be split into 9 different character sets when -/// determining which encoding to use. This enum represents these groupings for -/// parsing purpose. -#[derive(Copy, Clone)] -enum ExclCharSet { - /// The end of string. - End = 0, - - /// All symbols supported by the Alphanumeric encoding, i.e. space, `$`, `%`, - /// `*`, `+`, `-`, `.`, `/` and `:`. - Symbol = 1, - - /// All numbers (0–9). - Numeric = 2, - - /// All uppercase letters (A–Z). These characters may also appear in the - /// second byte of a Shift JIS 2-byte encoding. - Alpha = 3, - - /// The first byte of a Shift JIS 2-byte encoding, in the range 0x81–0x9f. - KanjiHi1 = 4, - - /// The first byte of a Shift JIS 2-byte encoding, in the range 0xe0–0xea. - KanjiHi2 = 5, - - /// The first byte of a Shift JIS 2-byte encoding, of value 0xeb. This is - /// different from the other two range that the second byte has a smaller - /// range. - KanjiHi3 = 6, - - /// The second byte of a Shift JIS 2-byte encoding, in the range 0x40–0xbf, - /// excluding letters (covered by `Alpha`), 0x81–0x9f (covered by `KanjiHi1`), - /// and the invalid byte 0x7f. - KanjiLo1 = 7, - - /// The second byte of a Shift JIS 2-byte encoding, in the range 0xc0–0xfc, - /// excluding the range 0xe0–0xeb (covered by `KanjiHi2` and `KanjiHi3`). - /// This half of byte-pair cannot appear as the second byte leaded by - /// `KanjiHi3`. - KanjiLo2 = 8, - - /// Any other values not covered by the above character sets. - Byte = 9, -} - -impl ExclCharSet { - /// Determines which character set a byte is in. - fn from_u8(c: u8) -> Self { - match c { - 0x20 | 0x24 | 0x25 | 0x2a | 0x2b | 0x2d..=0x2f | 0x3a => ExclCharSet::Symbol, - 0x30..=0x39 => ExclCharSet::Numeric, - 0x41..=0x5a => ExclCharSet::Alpha, - 0x81..=0x9f => ExclCharSet::KanjiHi1, - 0xe0..=0xea => ExclCharSet::KanjiHi2, - 0xeb => ExclCharSet::KanjiHi3, - 0x40 | 0x5b..=0x7e | 0x80 | 0xa0..=0xbf => ExclCharSet::KanjiLo1, - 0xc0..=0xdf | 0xec..=0xfc => ExclCharSet::KanjiLo2, - _ => ExclCharSet::Byte, - } - } -} - -/// The current parsing state. -#[derive(Copy, Clone)] -enum State { - /// Just initialized. - Init = 0, - - /// Inside a string that can be exclusively encoded as Numeric. - Numeric = 10, - - /// Inside a string that can be exclusively encoded as Alphanumeric. - Alpha = 20, - - /// Inside a string that can be exclusively encoded as 8-Bit Byte. - Byte = 30, - - /// Just encountered the first byte of a Shift JIS 2-byte sequence of the - /// set `KanjiHi1` or `KanjiHi2`. - KanjiHi12 = 40, - - /// Just encountered the first byte of a Shift JIS 2-byte sequence of the - /// set `KanjiHi3`. - KanjiHi3 = 50, - - /// Inside a string that can be exclusively encoded as Kanji. - Kanji = 60, -} - -/// What should the parser do after a state transition. -#[derive(Copy, Clone)] -enum Action { - /// The parser should do nothing. - Idle, - - /// Push the current segment as a Numeric string, and reset the marks. - Numeric, - - /// Push the current segment as an Alphanumeric string, and reset the marks. - Alpha, - - /// Push the current segment as a 8-Bit Byte string, and reset the marks. - Byte, - - /// Push the current segment as a Kanji string, and reset the marks. - Kanji, - - /// Push the current segment excluding the last byte as a Kanji string, then - /// push the remaining single byte as a Byte string, and reset the marks. - KanjiAndSingleByte, -} - -static STATE_TRANSITION: [(State, Action); 70] = [ - // STATE_TRANSITION[current_state + next_character] == (next_state, what_to_do) - - // Init state: - (State::Init, Action::Idle), // End - (State::Alpha, Action::Idle), // Symbol - (State::Numeric, Action::Idle), // Numeric - (State::Alpha, Action::Idle), // Alpha - (State::KanjiHi12, Action::Idle), // KanjiHi1 - (State::KanjiHi12, Action::Idle), // KanjiHi2 - (State::KanjiHi3, Action::Idle), // KanjiHi3 - (State::Byte, Action::Idle), // KanjiLo1 - (State::Byte, Action::Idle), // KanjiLo2 - (State::Byte, Action::Idle), // Byte - // Numeric state: - (State::Init, Action::Numeric), // End - (State::Alpha, Action::Numeric), // Symbol - (State::Numeric, Action::Idle), // Numeric - (State::Alpha, Action::Numeric), // Alpha - (State::KanjiHi12, Action::Numeric), // KanjiHi1 - (State::KanjiHi12, Action::Numeric), // KanjiHi2 - (State::KanjiHi3, Action::Numeric), // KanjiHi3 - (State::Byte, Action::Numeric), // KanjiLo1 - (State::Byte, Action::Numeric), // KanjiLo2 - (State::Byte, Action::Numeric), // Byte - // Alpha state: - (State::Init, Action::Alpha), // End - (State::Alpha, Action::Idle), // Symbol - (State::Numeric, Action::Alpha), // Numeric - (State::Alpha, Action::Idle), // Alpha - (State::KanjiHi12, Action::Alpha), // KanjiHi1 - (State::KanjiHi12, Action::Alpha), // KanjiHi2 - (State::KanjiHi3, Action::Alpha), // KanjiHi3 - (State::Byte, Action::Alpha), // KanjiLo1 - (State::Byte, Action::Alpha), // KanjiLo2 - (State::Byte, Action::Alpha), // Byte - // Byte state: - (State::Init, Action::Byte), // End - (State::Alpha, Action::Byte), // Symbol - (State::Numeric, Action::Byte), // Numeric - (State::Alpha, Action::Byte), // Alpha - (State::KanjiHi12, Action::Byte), // KanjiHi1 - (State::KanjiHi12, Action::Byte), // KanjiHi2 - (State::KanjiHi3, Action::Byte), // KanjiHi3 - (State::Byte, Action::Idle), // KanjiLo1 - (State::Byte, Action::Idle), // KanjiLo2 - (State::Byte, Action::Idle), // Byte - // KanjiHi12 state: - (State::Init, Action::KanjiAndSingleByte), // End - (State::Alpha, Action::KanjiAndSingleByte), // Symbol - (State::Numeric, Action::KanjiAndSingleByte), // Numeric - (State::Kanji, Action::Idle), // Alpha - (State::Kanji, Action::Idle), // KanjiHi1 - (State::Kanji, Action::Idle), // KanjiHi2 - (State::Kanji, Action::Idle), // KanjiHi3 - (State::Kanji, Action::Idle), // KanjiLo1 - (State::Kanji, Action::Idle), // KanjiLo2 - (State::Byte, Action::KanjiAndSingleByte), // Byte - // KanjiHi3 state: - (State::Init, Action::KanjiAndSingleByte), // End - (State::Alpha, Action::KanjiAndSingleByte), // Symbol - (State::Numeric, Action::KanjiAndSingleByte), // Numeric - (State::Kanji, Action::Idle), // Alpha - (State::Kanji, Action::Idle), // KanjiHi1 - (State::KanjiHi12, Action::KanjiAndSingleByte), // KanjiHi2 - (State::KanjiHi3, Action::KanjiAndSingleByte), // KanjiHi3 - (State::Kanji, Action::Idle), // KanjiLo1 - (State::Byte, Action::KanjiAndSingleByte), // KanjiLo2 - (State::Byte, Action::KanjiAndSingleByte), // Byte - // Kanji state: - (State::Init, Action::Kanji), // End - (State::Alpha, Action::Kanji), // Symbol - (State::Numeric, Action::Kanji), // Numeric - (State::Alpha, Action::Kanji), // Alpha - (State::KanjiHi12, Action::Idle), // KanjiHi1 - (State::KanjiHi12, Action::Idle), // KanjiHi2 - (State::KanjiHi3, Action::Idle), // KanjiHi3 - (State::Byte, Action::Kanji), // KanjiLo1 - (State::Byte, Action::Kanji), // KanjiLo2 - (State::Byte, Action::Kanji), // Byte -]; - -//}}} diff --git a/qrcode-rust/src/render/image.rs b/qrcode-rust/src/render/image.rs deleted file mode 100644 index 5a3974c..0000000 --- a/qrcode-rust/src/render/image.rs +++ /dev/null @@ -1,150 +0,0 @@ -#![cfg(feature = "image")] - -use crate::render::{Canvas, Pixel}; -use crate::types::Color; - -use image::{ImageBuffer, Luma, LumaA, Pixel as ImagePixel, Primitive, Rgb, Rgba}; - -macro_rules! impl_pixel_for_image_pixel { - ($p:ident<$s:ident>: $c:pat => $d:expr) => { - impl<$s: Primitive + 'static> Pixel for $p<$s> { - type Image = ImageBuffer<Self, Vec<S>>; - type Canvas = (Self, Self::Image); - - fn default_color(color: Color) -> Self { - match color.select($s::zero(), $s::max_value()) { - $c => $p($d), - } - } - } - }; -} - -impl_pixel_for_image_pixel! { Luma<S>: p => [p] } -impl_pixel_for_image_pixel! { LumaA<S>: p => [p, S::max_value()] } -impl_pixel_for_image_pixel! { Rgb<S>: p => [p, p, p] } -impl_pixel_for_image_pixel! { Rgba<S>: p => [p, p, p, S::max_value()] } - -impl<P: ImagePixel + 'static> Canvas for (P, ImageBuffer<P, Vec<P::Subpixel>>) { - type Pixel = P; - type Image = ImageBuffer<P, Vec<P::Subpixel>>; - - fn new(width: u32, height: u32, dark_pixel: P, light_pixel: P) -> Self { - (dark_pixel, ImageBuffer::from_pixel(width, height, light_pixel)) - } - - fn draw_dark_pixel(&mut self, x: u32, y: u32) { - self.1.put_pixel(x, y, self.0); - } - - fn into_image(self) -> ImageBuffer<P, Vec<P::Subpixel>> { - self.1 - } -} - -#[cfg(test)] -mod render_tests { - use crate::render::Renderer; - use crate::types::Color; - use image::{Luma, Rgba}; - - #[test] - fn test_render_luma8_unsized() { - let image = Renderer::<Luma<u8>>::new( - &[ - Color::Light, - Color::Dark, - Color::Dark, - // - Color::Dark, - Color::Light, - Color::Light, - // - Color::Light, - Color::Dark, - Color::Light, - ], - 3, - 1, - ) - .module_dimensions(1, 1) - .build(); - - #[rustfmt::skip] - let expected = [ - 255, 255, 255, 255, 255, - 255, 255, 0, 0, 255, - 255, 0, 255, 255, 255, - 255, 255, 0, 255, 255, - 255, 255, 255, 255, 255, - ]; - assert_eq!(image.into_raw(), expected); - } - - #[test] - fn test_render_rgba_unsized() { - let image = Renderer::<Rgba<u8>>::new(&[Color::Light, Color::Dark, Color::Dark, Color::Dark], 2, 1) - .module_dimensions(1, 1) - .build(); - - #[rustfmt::skip] - let expected: &[u8] = &[ - 255,255,255,255, 255,255,255,255, 255,255,255,255, 255,255,255,255, - 255,255,255,255, 255,255,255,255, 0, 0, 0,255, 255,255,255,255, - 255,255,255,255, 0, 0, 0,255, 0, 0, 0,255, 255,255,255,255, - 255,255,255,255, 255,255,255,255, 255,255,255,255, 255,255,255,255, - ]; - - assert_eq!(image.into_raw(), expected); - } - - #[test] - fn test_render_resized_min() { - let image = Renderer::<Luma<u8>>::new(&[Color::Dark, Color::Light, Color::Light, Color::Dark], 2, 1) - .min_dimensions(10, 10) - .build(); - - #[rustfmt::skip] - let expected: &[u8] = &[ - 255,255,255, 255,255,255, 255,255,255, 255,255,255, - 255,255,255, 255,255,255, 255,255,255, 255,255,255, - 255,255,255, 255,255,255, 255,255,255, 255,255,255, - - 255,255,255, 0, 0, 0, 255,255,255, 255,255,255, - 255,255,255, 0, 0, 0, 255,255,255, 255,255,255, - 255,255,255, 0, 0, 0, 255,255,255, 255,255,255, - - 255,255,255, 255,255,255, 0, 0, 0, 255,255,255, - 255,255,255, 255,255,255, 0, 0, 0, 255,255,255, - 255,255,255, 255,255,255, 0, 0, 0, 255,255,255, - - 255,255,255, 255,255,255, 255,255,255, 255,255,255, - 255,255,255, 255,255,255, 255,255,255, 255,255,255, - 255,255,255, 255,255,255, 255,255,255, 255,255,255, - ]; - - assert_eq!(image.dimensions(), (12, 12)); - assert_eq!(image.into_raw(), expected); - } - - #[test] - fn test_render_resized_max() { - let image = Renderer::<Luma<u8>>::new(&[Color::Dark, Color::Light, Color::Light, Color::Dark], 2, 1) - .max_dimensions(10, 5) - .build(); - - #[rustfmt::skip] - let expected: &[u8] = &[ - 255,255, 255,255, 255,255, 255,255, - - 255,255, 0, 0, 255,255, 255,255, - - 255,255, 255,255, 0, 0, 255,255, - - 255,255, 255,255, 255,255, 255,255, - ]; - - assert_eq!(image.dimensions(), (8, 4)); - assert_eq!(image.into_raw(), expected); - } -} diff --git a/qrcode-rust/src/render/mod.rs b/qrcode-rust/src/render/mod.rs deleted file mode 100644 index 71f4306..0000000 --- a/qrcode-rust/src/render/mod.rs +++ /dev/null @@ -1,191 +0,0 @@ -//! Render a QR code into image. - -use crate::cast::As; -use crate::types::Color; -use core::cmp::max; - -pub mod image; -pub mod string; -pub mod svg; -pub mod unicode; - -//------------------------------------------------------------------------------ -//{{{ Pixel trait - -/// Abstraction of an image pixel. -pub trait Pixel: Copy + Sized { - /// Type of the finalized image. - type Image: Sized + 'static; - - /// The type that stores an intermediate buffer before finalizing to a - /// concrete image - type Canvas: Canvas<Pixel = Self, Image = Self::Image>; - - /// Obtains the default module size. The result must be at least 1×1. - fn default_unit_size() -> (u32, u32) { - (8, 8) - } - - /// Obtains the default pixel color when a module is dark or light. - fn default_color(color: Color) -> Self; -} - -/// Rendering canvas of a QR code image. -pub trait Canvas: Sized { - type Pixel: Sized; - type Image: Sized; - - /// Constructs a new canvas of the given dimensions. - fn new(width: u32, height: u32, dark_pixel: Self::Pixel, light_pixel: Self::Pixel) -> Self; - - /// Draws a single dark pixel at the (x, y) coordinate. - fn draw_dark_pixel(&mut self, x: u32, y: u32); - - fn draw_dark_rect(&mut self, left: u32, top: u32, width: u32, height: u32) { - for y in top..(top + height) { - for x in left..(left + width) { - self.draw_dark_pixel(x, y); - } - } - } - - /// Finalize the canvas to a real image. - fn into_image(self) -> Self::Image; -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Renderer - -/// A QR code renderer. This is a builder type which converts a bool-vector into -/// an image. -pub struct Renderer<'a, P: Pixel> { - content: &'a [Color], - modules_count: u32, // <- we call it `modules_count` here to avoid ambiguity of `width`. - quiet_zone: u32, - module_size: (u32, u32), - - dark_color: P, - light_color: P, - has_quiet_zone: bool, -} - -impl<'a, P: Pixel> Renderer<'a, P> { - /// Creates a new renderer. - pub fn new(content: &'a [Color], modules_count: usize, quiet_zone: u32) -> Renderer<'a, P> { - assert!(modules_count * modules_count == content.len()); - Renderer { - content, - modules_count: modules_count.as_u32(), - quiet_zone, - module_size: P::default_unit_size(), - dark_color: P::default_color(Color::Dark), - light_color: P::default_color(Color::Light), - has_quiet_zone: true, - } - } - - /// Sets color of a dark module. Default is opaque black. - pub fn dark_color(&mut self, color: P) -> &mut Self { - self.dark_color = color; - self - } - - /// Sets color of a light module. Default is opaque white. - pub fn light_color(&mut self, color: P) -> &mut Self { - self.light_color = color; - self - } - - /// Whether to include the quiet zone in the generated image. - pub fn quiet_zone(&mut self, has_quiet_zone: bool) -> &mut Self { - self.has_quiet_zone = has_quiet_zone; - self - } - - /// Sets the size of each module in pixels. Default is 8px. - #[deprecated(since = "0.4.0", note = "use `.module_dimensions(width, width)` instead")] - pub fn module_size(&mut self, width: u32) -> &mut Self { - self.module_dimensions(width, width) - } - - /// Sets the size of each module in pixels. Default is 8×8. - pub fn module_dimensions(&mut self, width: u32, height: u32) -> &mut Self { - self.module_size = (max(width, 1), max(height, 1)); - self - } - - #[deprecated(since = "0.4.0", note = "use `.min_dimensions(width, width)` instead")] - pub fn min_width(&mut self, width: u32) -> &mut Self { - self.min_dimensions(width, width) - } - - /// Sets the minimum total image size in pixels, including the quiet zone if - /// applicable. The renderer will try to find the dimension as small as - /// possible, such that each module in the QR code has uniform size (no - /// distortion). - /// - /// For instance, a version 1 QR code has 19 modules across including the - /// quiet zone. If we request an image of size ≥200×200, we get that each - /// module's size should be 11×11, so the actual image size will be 209×209. - pub fn min_dimensions(&mut self, width: u32, height: u32) -> &mut Self { - let quiet_zone = if self.has_quiet_zone { 2 } else { 0 } * self.quiet_zone; - let width_in_modules = self.modules_count + quiet_zone; - let unit_width = (width + width_in_modules - 1) / width_in_modules; - let unit_height = (height + width_in_modules - 1) / width_in_modules; - self.module_dimensions(unit_width, unit_height) - } - - /// Sets the maximum total image size in pixels, including the quiet zone if - /// applicable. The renderer will try to find the dimension as large as - /// possible, such that each module in the QR code has uniform size (no - /// distortion). - /// - /// For instance, a version 1 QR code has 19 modules across including the - /// quiet zone. If we request an image of size ≤200×200, we get that each - /// module's size should be 10×10, so the actual image size will be 190×190. - /// - /// The module size is at least 1×1, so if the restriction is too small, the - /// final image *can* be larger than the input. - pub fn max_dimensions(&mut self, width: u32, height: u32) -> &mut Self { - let quiet_zone = if self.has_quiet_zone { 2 } else { 0 } * self.quiet_zone; - let width_in_modules = self.modules_count + quiet_zone; - let unit_width = width / width_in_modules; - let unit_height = height / width_in_modules; - self.module_dimensions(unit_width, unit_height) - } - - /// Renders the QR code into an image. - #[deprecated(since = "0.4.0", note = "renamed to `.build()` to de-emphasize the image connection")] - pub fn to_image(&self) -> P::Image { - self.build() - } - - /// Renders the QR code into an image. - pub fn build(&self) -> P::Image { - let w = self.modules_count; - let qz = if self.has_quiet_zone { self.quiet_zone } else { 0 }; - let width = w + 2 * qz; - - let (mw, mh) = self.module_size; - let real_width = width * mw; - let real_height = width * mh; - - let mut canvas = P::Canvas::new(real_width, real_height, self.dark_color, self.light_color); - let mut i = 0; - for y in 0..width { - for x in 0..width { - if qz <= x && x < w + qz && qz <= y && y < w + qz { - if self.content[i] != Color::Light { - canvas.draw_dark_rect(x * mw, y * mh, mw, mh); - } - i += 1; - } - } - } - - canvas.into_image() - } -} - -//}}} diff --git a/qrcode-rust/src/render/string.rs b/qrcode-rust/src/render/string.rs deleted file mode 100644 index a7ae42c..0000000 --- a/qrcode-rust/src/render/string.rs +++ /dev/null @@ -1,125 +0,0 @@ -//! String rendering support. - -use alloc::string::String; -use alloc::vec::Vec; - -use crate::cast::As; -use crate::render::{Canvas as RenderCanvas, Pixel}; -use crate::types::Color; - -pub trait Element: Copy { - fn default_color(color: Color) -> Self; - fn strlen(self) -> usize; - fn append_to_string(self, string: &mut String); -} - -impl Element for char { - fn default_color(color: Color) -> Self { - color.select('█', ' ') - } - - fn strlen(self) -> usize { - self.len_utf8() - } - - fn append_to_string(self, string: &mut String) { - string.push(self) - } -} - -impl<'a> Element for &'a str { - fn default_color(color: Color) -> Self { - color.select("\u{2588}", " ") - } - - fn strlen(self) -> usize { - self.len() - } - - fn append_to_string(self, string: &mut String) { - string.push_str(self) - } -} - -#[doc(hidden)] -pub struct Canvas<P: Element> { - buffer: Vec<P>, - width: usize, - dark_pixel: P, - dark_cap_inc: isize, - capacity: isize, -} - -impl<P: Element> Pixel for P { - type Canvas = Canvas<Self>; - type Image = String; - - fn default_unit_size() -> (u32, u32) { - (1, 1) - } - - fn default_color(color: Color) -> Self { - <Self as Element>::default_color(color) - } -} - -impl<P: Element> RenderCanvas for Canvas<P> { - type Pixel = P; - type Image = String; - - fn new(width: u32, height: u32, dark_pixel: P, light_pixel: P) -> Self { - let width = width.as_usize(); - let height = height.as_isize(); - let dark_cap = dark_pixel.strlen().as_isize(); - let light_cap = light_pixel.strlen().as_isize(); - - Self { - buffer: vec![light_pixel; width * height.as_usize()], - width, - dark_pixel, - dark_cap_inc: dark_cap - light_cap, - capacity: light_cap * width.as_isize() * height + (height - 1), - } - } - - fn draw_dark_pixel(&mut self, x: u32, y: u32) { - let x = x.as_usize(); - let y = y.as_usize(); - self.capacity += self.dark_cap_inc; - self.buffer[x + y * self.width] = self.dark_pixel; - } - - fn into_image(self) -> String { - let mut result = String::with_capacity(self.capacity.as_usize()); - for (i, pixel) in self.buffer.into_iter().enumerate() { - if i != 0 && i % self.width == 0 { - result.push('\n'); - } - pixel.append_to_string(&mut result); - } - result - } -} - -#[test] -fn test_render_to_string() { - use crate::render::Renderer; - - let colors = &[Color::Dark, Color::Light, Color::Light, Color::Dark]; - let image: String = Renderer::<char>::new(colors, 2, 1).build(); - assert_eq!(&image, " \n \u{2588} \n \u{2588} \n "); - - let image2 = Renderer::new(colors, 2, 1).light_color("A").dark_color("!B!").module_dimensions(2, 2).build(); - - assert_eq!( - &image2, - "AAAAAAAA\n\ - AAAAAAAA\n\ - AA!B!!B!AAAA\n\ - AA!B!!B!AAAA\n\ - AAAA!B!!B!AA\n\ - AAAA!B!!B!AA\n\ - AAAAAAAA\n\ - AAAAAAAA" - ); -} diff --git a/qrcode-rust/src/render/svg.rs b/qrcode-rust/src/render/svg.rs deleted file mode 100644 index ba85fbd..0000000 --- a/qrcode-rust/src/render/svg.rs +++ /dev/null @@ -1,76 +0,0 @@ -//! SVG rendering support. -//! -//! # Example -//! -//! ``` -//! use qrcode::QrCode; -//! use qrcode::render::svg; -//! -//! let code = QrCode::new(b"Hello").unwrap(); -//! let svg_xml = code.render::<svg::Color>().build(); -//! println!("{}", svg_xml); - -#![cfg(feature = "svg")] - -use std::fmt::Write; -use std::marker::PhantomData; - -use crate::render::{Canvas as RenderCanvas, Pixel}; -use crate::types::Color as ModuleColor; - -/// An SVG color. -#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Color<'a>(pub &'a str); - -impl<'a> Pixel for Color<'a> { - type Canvas = Canvas<'a>; - type Image = String; - - fn default_color(color: ModuleColor) -> Self { - Color(color.select("#000", "#fff")) - } -} - -#[doc(hidden)] -pub struct Canvas<'a> { - svg: String, - marker: PhantomData<Color<'a>>, -} - -impl<'a> RenderCanvas for Canvas<'a> { - type Pixel = Color<'a>; - type Image = String; - - fn new(width: u32, height: u32, dark_pixel: Color<'a>, light_pixel: Color<'a>) -> Self { - Canvas { - svg: format!( - concat!( - r#"<?xml version="1.0" standalone="yes"?>"#, - r#"<svg xmlns="http://www.w3.org/2000/svg""#, - r#" version="1.1" width="{w}" height="{h}""#, - r#" viewBox="0 0 {w} {h}" shape-rendering="crispEdges">"#, - r#"<rect x="0" y="0" width="{w}" height="{h}" fill="{bg}"/>"#, - r#"<path fill="{fg}" d=""#, - ), - w = width, - h = height, - fg = dark_pixel.0, - bg = light_pixel.0 - ), - marker: PhantomData, - } - } - - fn draw_dark_pixel(&mut self, x: u32, y: u32) { - self.draw_dark_rect(x, y, 1, 1) - } - - fn draw_dark_rect(&mut self, left: u32, top: u32, width: u32, height: u32) { - write!(self.svg, "M{l} {t}h{w}v{h}H{l}V{t}", l = left, t = top, w = width, h = height).unwrap(); - } - - fn into_image(mut self) -> String { - self.svg.push_str(r#""/></svg>"#); - self.svg - } -} diff --git a/qrcode-rust/src/render/unicode.rs b/qrcode-rust/src/render/unicode.rs deleted file mode 100644 index 11e7a2c..0000000 --- a/qrcode-rust/src/render/unicode.rs +++ /dev/null @@ -1,142 +0,0 @@ -//! UTF-8 rendering, with 2 pixels per symbol. - -use crate::render::{Canvas as RenderCanvas, Color, Pixel}; -use alloc::{string::String, vec::Vec}; - -const CODEPAGE: [&str; 4] = [" ", "\u{2584}", "\u{2580}", "\u{2588}"]; - -#[derive(Copy, Clone, PartialEq, Eq)] -pub enum Dense1x2 { - Dark, - Light, -} - -impl Pixel for Dense1x2 { - type Image = String; - type Canvas = Canvas1x2; - fn default_color(color: Color) -> Dense1x2 { - color.select(Dense1x2::Dark, Dense1x2::Light) - } - fn default_unit_size() -> (u32, u32) { - (1, 1) - } -} - -impl Dense1x2 { - fn value(self) -> u8 { - match self { - Dense1x2::Dark => 1, - Dense1x2::Light => 0, - } - } - fn parse_2_bits(sym: u8) -> &'static str { - CODEPAGE[usize::from(sym)] - } -} - -pub struct Canvas1x2 { - canvas: Vec<u8>, - width: u32, - dark_pixel: u8, -} - -impl RenderCanvas for Canvas1x2 { - type Pixel = Dense1x2; - type Image = String; - - fn new(width: u32, height: u32, dark_pixel: Dense1x2, light_pixel: Dense1x2) -> Self { - let a = vec![light_pixel.value(); (width * height) as usize]; - Canvas1x2 { width, canvas: a, dark_pixel: dark_pixel.value() } - } - - fn draw_dark_pixel(&mut self, x: u32, y: u32) { - self.canvas[(x + y * self.width) as usize] = self.dark_pixel; - } - - fn into_image(self) -> String { - self.canvas - // Chopping array into 1-line sized fragments - .chunks_exact(self.width as usize) - .collect::<Vec<&[u8]>>() - // And then glueing every 2 lines. - .chunks(2) - .map(|rows| { - { - // Then zipping those 2 lines together into a single 2-bit number list. - if rows.len() == 2 { - rows[0].iter().zip(rows[1]).map(|(top, bot)| (top * 2 + bot)).collect::<Vec<u8>>() - } else { - rows[0].iter().map(|top| (top * 2)).collect::<Vec<u8>>() - } - } - .into_iter() - // Mapping those 2-bit numbers to corresponding pixels. - .map(Dense1x2::parse_2_bits) - .collect::<Vec<&str>>() - .concat() - }) - .collect::<Vec<String>>() - .join("\n") - } -} - -#[test] -fn test_render_to_utf8_string() { - use crate::render::Renderer; - let colors = &[Color::Dark, Color::Light, Color::Light, Color::Dark]; - let image: String = Renderer::<Dense1x2>::new(colors, 2, 1).build(); - - assert_eq!(&image, " ▄ \n ▀ "); - - let image2 = Renderer::<Dense1x2>::new(colors, 2, 1).module_dimensions(2, 2).build(); - - assert_eq!(&image2, " \n ██ \n ██ \n "); -} - -#[test] -fn integration_render_utf8_1x2() { - use crate::render::unicode::Dense1x2; - use crate::{EcLevel, QrCode, Version}; - - let code = QrCode::with_version(b"09876542", Version::Micro(2), EcLevel::L).unwrap(); - let image = code.render::<Dense1x2>().module_dimensions(1, 1).build(); - assert_eq!( - image, - String::new() - + " \n" - + " █▀▀▀▀▀█ ▀ █ ▀ \n" - + " █ ███ █ ▀ █ \n" - + " █ ▀▀▀ █ ▀█ █ \n" - + " ▀▀▀▀▀▀▀ ▄▀▀ █ \n" - + " ▀█ ▀▀▀▀▀██▀▀▄ \n" - + " ▀███▄ ▀▀ █ ██ \n" - + " ▀▀▀ ▀ ▀▀ ▀ ▀ \n" - + " " - ) -} - -#[test] -fn integration_render_utf8_1x2_inverted() { - use crate::render::unicode::Dense1x2; - use crate::{EcLevel, QrCode, Version}; - - let code = QrCode::with_version(b"12345678", Version::Micro(2), EcLevel::L).unwrap(); - let image = code - .render::<Dense1x2>() - .dark_color(Dense1x2::Light) - .light_color(Dense1x2::Dark) - .module_dimensions(1, 1) - .build(); - assert_eq!( - image, - "█████████████████\n\ - ██ ▄▄▄▄▄ █▄▀▄█▄██\n\ - ██ █ █ █ █ ██\n\ - ██ █▄▄▄█ █▄▄██▀██\n\ - ██▄▄▄▄▄▄▄█▄▄▄▀ ██\n\ - ██▄ ▀ ▀ ▀▄▄ ████\n\ - ██▄▄▀▄█ ▀▀▀ ▀▄▄██\n\ - ██▄▄▄█▄▄█▄██▄█▄██\n\ - ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀" - ); -} diff --git a/qrcode-rust/src/test_annex_i_micro_qr_as_image.png b/qrcode-rust/src/test_annex_i_micro_qr_as_image.png deleted file mode 100644 index 43cb1f7..0000000 Binary files a/qrcode-rust/src/test_annex_i_micro_qr_as_image.png and /dev/null differ diff --git a/qrcode-rust/src/test_annex_i_micro_qr_as_svg.svg b/qrcode-rust/src/test_annex_i_micro_qr_as_svg.svg deleted file mode 100644 index efac918..0000000 --- a/qrcode-rust/src/test_annex_i_micro_qr_as_svg.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" standalone="yes"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="204" height="204" viewBox="0 0 204 204" shape-rendering="crispEdges"><rect x="0" y="0" width="204" height="204" fill="#ffff80"/><path fill="#800000" d="M24 24h12v12H24V24M36 24h12v12H36V24M48 24h12v12H48V24M60 24h12v12H60V24M72 24h12v12H72V24M84 24h12v12H84V24M96 24h12v12H96V24M120 24h12v12H120V24M144 24h12v12H144V24M168 24h12v12H168V24M24 36h12v12H24V36M96 36h12v12H96V36M120 36h12v12H120V36M132 36h12v12H132V36M144 36h12v12H144V36M168 36h12v12H168V36M24 48h12v12H24V48M48 48h12v12H48V48M60 48h12v12H60V48M72 48h12v12H72V48M96 48h12v12H96V48M132 48h12v12H132V48M144 48h12v12H144V48M168 48h12v12H168V48M24 60h12v12H24V60M48 60h12v12H48V60M60 60h12v12H60V60M72 60h12v12H72V60M96 60h12v12H96V60M132 60h12v12H132V60M144 60h12v12H144V60M156 60h12v12H156V60M168 60h12v12H168V60M24 72h12v12H24V72M48 72h12v12H48V72M60 72h12v12H60V72M72 72h12v12H72V72M96 72h12v12H96V72M120 72h12v12H120V72M132 72h12v12H132V72M144 72h12v12H144V72M24 84h12v12H24V84M96 84h12v12H96V84M120 84h12v12H120V84M168 84h12v12H168V84M24 96h12v12H24V96M36 96h12v12H36V96M48 96h12v12H48V96M60 96h12v12H60V96M72 96h12v12H72V96M84 96h12v12H84V96M96 96h12v12H96V96M132 96h12v12H132V96M144 96h12v12H144V96M156 96h12v12H156V96M168 96h12v12H168V96M132 108h12v12H132V108M144 108h12v12H144V108M24 120h12v12H24V120M36 120h12v12H36V120M60 120h12v12H60V120M120 120h12v12H120V120M168 120h12v12H168V120M36 132h12v12H36V132M48 132h12v12H48V132M72 132h12v12H72V132M96 132h12v12H96V132M120 132h12v12H120V132M144 132h12v12H144V132M168 132h12v12H168V132M24 144h12v12H24V144M36 144h12v12H36V144M48 144h12v12H48V144M84 144h12v12H84V144M96 144h12v12H96V144M108 144h12v12H108V144M120 144h12v12H120V144M132 144h12v12H132V144M144 144h12v12H144V144M156 144h12v12H156V144M60 156h12v12H60V156M84 156h12v12H84V156M144 156h12v12H144V156M156 156h12v12H156V156M24 168h12v12H24V168M36 168h12v12H36V168M48 168h12v12H48V168M72 168h12v12H72V168M108 168h12v12H108V168M120 168h12v12H120V168M144 168h12v12H144V168M156 168h12v12H156V168M168 168h12v12H168V168"/></svg> \ No newline at end of file diff --git a/qrcode-rust/src/test_annex_i_qr_as_image.png b/qrcode-rust/src/test_annex_i_qr_as_image.png deleted file mode 100644 index 4d5e5d6..0000000 Binary files a/qrcode-rust/src/test_annex_i_qr_as_image.png and /dev/null differ diff --git a/qrcode-rust/src/test_annex_i_qr_as_svg.svg b/qrcode-rust/src/test_annex_i_qr_as_svg.svg deleted file mode 100644 index 6f37446..0000000 --- a/qrcode-rust/src/test_annex_i_qr_as_svg.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" standalone="yes"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="232" height="232" viewBox="0 0 232 232" shape-rendering="crispEdges"><rect x="0" y="0" width="232" height="232" fill="#fff"/><path fill="#000" d="M32 32h8v8H32V32M40 32h8v8H40V32M48 32h8v8H48V32M56 32h8v8H56V32M64 32h8v8H64V32M72 32h8v8H72V32M80 32h8v8H80V32M104 32h8v8H104V32M120 32h8v8H120V32M128 32h8v8H128V32M144 32h8v8H144V32M152 32h8v8H152V32M160 32h8v8H160V32M168 32h8v8H168V32M176 32h8v8H176V32M184 32h8v8H184V32M192 32h8v8H192V32M32 40h8v8H32V40M80 40h8v8H80V40M104 40h8v8H104V40M112 40h8v8H112V40M120 40h8v8H120V40M128 40h8v8H128V40M144 40h8v8H144V40M192 40h8v8H192V40M32 48h8v8H32V48M48 48h8v8H48V48M56 48h8v8H56V48M64 48h8v8H64V48M80 48h8v8H80V48M96 48h8v8H96V48M144 48h8v8H144V48M160 48h8v8H160V48M168 48h8v8H168V48M176 48h8v8H176V48M192 48h8v8H192V48M32 56h8v8H32V56M48 56h8v8H48V56M56 56h8v8H56V56M64 56h8v8H64V56M80 56h8v8H80V56M96 56h8v8H96V56M104 56h8v8H104V56M144 56h8v8H144V56M160 56h8v8H160V56M168 56h8v8H168V56M176 56h8v8H176V56M192 56h8v8H192V56M32 64h8v8H32V64M48 64h8v8H48V64M56 64h8v8H56V64M64 64h8v8H64V64M80 64h8v8H80V64M96 64h8v8H96V64M112 64h8v8H112V64M120 64h8v8H120V64M128 64h8v8H128V64M144 64h8v8H144V64M160 64h8v8H160V64M168 64h8v8H168V64M176 64h8v8H176V64M192 64h8v8H192V64M32 72h8v8H32V72M80 72h8v8H80V72M96 72h8v8H96V72M128 72h8v8H128V72M144 72h8v8H144V72M192 72h8v8H192V72M32 80h8v8H32V80M40 80h8v8H40V80M48 80h8v8H48V80M56 80h8v8H56V80M64 80h8v8H64V80M72 80h8v8H72V80M80 80h8v8H80V80M96 80h8v8H96V80M112 80h8v8H112V80M128 80h8v8H128V80M144 80h8v8H144V80M152 80h8v8H152V80M160 80h8v8H160V80M168 80h8v8H168V80M176 80h8v8H176V80M184 80h8v8H184V80M192 80h8v8H192V80M96 88h8v8H96V88M120 88h8v8H120V88M128 88h8v8H128V88M32 96h8v8H32V96M48 96h8v8H48V96M56 96h8v8H56V96M64 96h8v8H64V96M72 96h8v8H72V96M80 96h8v8H80V96M104 96h8v8H104V96M128 96h8v8H128V96M144 96h8v8H144V96M152 96h8v8H152V96M160 96h8v8H160V96M168 96h8v8H168V96M176 96h8v8H176V96M56 104h8v8H56V104M72 104h8v8H72V104M88 104h8v8H88V104M96 104h8v8H96V104M112 104h8v8H112V104M128 104h8v8H128V104M152 104h8v8H152V104M168 104h8v8H168V104M176 104h8v8H176V104M48 112h8v8H48V112M80 112h8v8H80V112M88 112h8v8H88V112M104 112h8v8H104V112M120 112h8v8H120V112M136 112h8v8H136V112M160 112h8v8H160V112M168 112h8v8H168V112M176 112h8v8H176V112M184 112h8v8H184V112M192 112h8v8H192V112M64 120h8v8H64V120M104 120h8v8H104V120M152 120h8v8H152V120M160 120h8v8H160V120M168 120h8v8H168V120M176 120h8v8H176V120M56 128h8v8H56V128M64 128h8v8H64V128M72 128h8v8H72V128M80 128h8v8H80V128M88 128h8v8H88V128M96 128h8v8H96V128M120 128h8v8H120V128M136 128h8v8H136V128M160 128h8v8H160V128M96 136h8v8H96V136M112 136h8v8H112V136M120 136h8v8H120V136M128 136h8v8H128V136M136 136h8v8H136V136M144 136h8v8H144V136M168 136h8v8H168V136M176 136h8v8H176V136M32 144h8v8H32V144M40 144h8v8H40V144M48 144h8v8H48V144M56 144h8v8H56V144M64 144h8v8H64V144M72 144h8v8H72V144M80 144h8v8H80V144M104 144h8v8H104V144M112 144h8v8H112V144M128 144h8v8H128V144M144 144h8v8H144V144M152 144h8v8H152V144M32 152h8v8H32V152M80 152h8v8H80V152M96 152h8v8H96V152M112 152h8v8H112V152M120 152h8v8H120V152M128 152h8v8H128V152M136 152h8v8H136V152M144 152h8v8H144V152M176 152h8v8H176V152M192 152h8v8H192V152M32 160h8v8H32V160M48 160h8v8H48V160M56 160h8v8H56V160M64 160h8v8H64V160M80 160h8v8H80V160M96 160h8v8H96V160M128 160h8v8H128V160M152 160h8v8H152V160M168 160h8v8H168V160M176 160h8v8H176V160M32 168h8v8H32V168M48 168h8v8H48V168M56 168h8v8H56V168M64 168h8v8H64V168M80 168h8v8H80V168M96 168h8v8H96V168M104 168h8v8H104V168M128 168h8v8H128V168M152 168h8v8H152V168M32 176h8v8H32V176M48 176h8v8H48V176M56 176h8v8H56V176M64 176h8v8H64V176M80 176h8v8H80V176M96 176h8v8H96V176M112 176h8v8H112V176M120 176h8v8H120V176M136 176h8v8H136V176M160 176h8v8H160V176M176 176h8v8H176V176M32 184h8v8H32V184M80 184h8v8H80V184M152 184h8v8H152V184M160 184h8v8H160V184M176 184h8v8H176V184M184 184h8v8H184V184M32 192h8v8H32V192M40 192h8v8H40V192M48 192h8v8H48V192M56 192h8v8H56V192M64 192h8v8H64V192M72 192h8v8H72V192M80 192h8v8H80V192M96 192h8v8H96V192M104 192h8v8H104V192M112 192h8v8H112V192M120 192h8v8H120V192M136 192h8v8H136V192M160 192h8v8H160V192M176 192h8v8H176V192"/></svg> \ No newline at end of file diff --git a/qrcode-rust/src/types.rs b/qrcode-rust/src/types.rs deleted file mode 100644 index 0bca045..0000000 --- a/qrcode-rust/src/types.rs +++ /dev/null @@ -1,326 +0,0 @@ -use crate::cast::As; -use core::cmp::{Ordering, PartialOrd}; -use core::default::Default; -use core::fmt::{Display, Error, Formatter}; -use core::ops::Not; - -//------------------------------------------------------------------------------ -//{{{ QrResult - -/// `QrError` encodes the error encountered when generating a QR code. -#[derive(Debug, PartialEq, Eq, Copy, Clone)] -pub enum QrError { - /// The data is too long to encode into a QR code for the given version. - DataTooLong, - - /// The provided version / error correction level combination is invalid. - InvalidVersion, - - /// Some characters in the data cannot be supported by the provided QR code - /// version. - UnsupportedCharacterSet, - - /// The provided ECI designator is invalid. A valid designator should be - /// between 0 and 999999. - InvalidEciDesignator, - - /// A character not belonging to the character set is found. - InvalidCharacter, -} - -impl Display for QrError { - fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { - let msg = match *self { - QrError::DataTooLong => "data too long", - QrError::InvalidVersion => "invalid version", - QrError::UnsupportedCharacterSet => "unsupported character set", - QrError::InvalidEciDesignator => "invalid ECI designator", - QrError::InvalidCharacter => "invalid character", - }; - fmt.write_str(msg) - } -} - -/// `QrResult` is a convenient alias for a QR code generation result. -pub type QrResult<T> = Result<T, QrError>; - -//}}} -//------------------------------------------------------------------------------ -//{{{ Color - -/// The color of a module. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -pub enum Color { - /// The module is light colored. - Light, - /// The module is dark colored. - Dark, -} - -impl Color { - /// Selects a value according to color of the module. Equivalent to - /// `if self != Color::Light { dark } else { light }`. - /// - /// # Examples - /// - /// ```rust - /// # use qrcode::types::Color; - /// assert_eq!(Color::Light.select(1, 0), 0); - /// assert_eq!(Color::Dark.select("black", "white"), "black"); - /// ``` - pub fn select<T>(self, dark: T, light: T) -> T { - match self { - Color::Light => light, - Color::Dark => dark, - } - } -} - -impl Not for Color { - type Output = Self; - fn not(self) -> Self { - match self { - Color::Light => Color::Dark, - Color::Dark => Color::Light, - } - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Error correction level - -/// The error correction level. It allows the original information be recovered -/// even if parts of the code is damaged. -#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)] -pub enum EcLevel { - /// Low error correction. Allows up to 7% of wrong blocks. - L = 0, - - /// Medium error correction (default). Allows up to 15% of wrong blocks. - M = 1, - - /// "Quartile" error correction. Allows up to 25% of wrong blocks. - Q = 2, - - /// High error correction. Allows up to 30% of wrong blocks. - H = 3, -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Version - -/// In QR code terminology, `Version` means the size of the generated image. -/// Larger version means the size of code is larger, and therefore can carry -/// more information. -/// -/// The smallest version is `Version::Normal(1)` of size 21×21, and the largest -/// is `Version::Normal(40)` of size 177×177. -#[derive(Debug, PartialEq, Eq, Copy, Clone)] -pub enum Version { - /// A normal QR code version. The parameter should be between 1 and 40. - Normal(i16), - - /// A Micro QR code version. The parameter should be between 1 and 4. - Micro(i16), -} - -impl Version { - /// Get the number of "modules" on each size of the QR code, i.e. the width - /// and height of the code. - pub fn width(self) -> i16 { - match self { - Version::Normal(v) => v * 4 + 17, - Version::Micro(v) => v * 2 + 9, - } - } - - /// Obtains an object from a hard-coded table. - /// - /// The table must be a 44×4 array. The outer array represents the content - /// for each version. The first 40 entry corresponds to QR code versions 1 - /// to 40, and the last 4 corresponds to Micro QR code version 1 to 4. The - /// inner array represents the content in each error correction level, in - /// the order [L, M, Q, H]. - /// - /// # Errors - /// - /// If the entry compares equal to the default value of `T`, this method - /// returns `Err(QrError::InvalidVersion)`. - pub fn fetch<T>(self, ec_level: EcLevel, table: &[[T; 4]]) -> QrResult<T> - where - T: PartialEq + Default + Copy, - { - match self { - Version::Normal(v @ 1..=40) => { - return Ok(table[(v - 1).as_usize()][ec_level as usize]); - } - Version::Micro(v @ 1..=4) => { - let obj = table[(v + 39).as_usize()][ec_level as usize]; - if obj != T::default() { - return Ok(obj); - } - } - _ => {} - } - Err(QrError::InvalidVersion) - } - - /// The number of bits needed to encode the mode indicator. - pub fn mode_bits_count(self) -> usize { - match self { - Version::Micro(a) => (a - 1).as_usize(), - _ => 4, - } - } - - /// Checks whether is version refers to a Micro QR code. - pub fn is_micro(self) -> bool { - match self { - Version::Normal(_) => false, - Version::Micro(_) => true, - } - } -} - -//}}} -//------------------------------------------------------------------------------ -//{{{ Mode indicator - -/// The mode indicator, which specifies the character set of the encoded data. -#[derive(Debug, PartialEq, Eq, Copy, Clone)] -pub enum Mode { - /// The data contains only characters 0 to 9. - Numeric, - - /// The data contains only uppercase letters (A–Z), numbers (0–9) and a few - /// punctuations marks (space, `$`, `%`, `*`, `+`, `-`, `.`, `/`, `:`). - Alphanumeric, - - /// The data contains arbitrary binary data. - Byte, - - /// The data contains Shift-JIS-encoded double-byte text. - Kanji, -} - -impl Mode { - /// Computes the number of bits needed to encode the data length. - /// - /// use qrcode::types::{Version, Mode}; - /// - /// assert_eq!(Mode::Numeric.length_bits_count(Version::Normal(1)), 10); - /// - /// This method will return `Err(QrError::UnsupportedCharacterSet)` if the - /// mode is not supported in the given version. - pub fn length_bits_count(self, version: Version) -> usize { - match version { - Version::Micro(a) => { - let a = a.as_usize(); - match self { - Mode::Numeric => 2 + a, - Mode::Alphanumeric | Mode::Byte => 1 + a, - Mode::Kanji => a, - } - } - Version::Normal(1..=9) => match self { - Mode::Numeric => 10, - Mode::Alphanumeric => 9, - Mode::Byte | Mode::Kanji => 8, - }, - Version::Normal(10..=26) => match self { - Mode::Numeric => 12, - Mode::Alphanumeric => 11, - Mode::Byte => 16, - Mode::Kanji => 10, - }, - Version::Normal(_) => match self { - Mode::Numeric => 14, - Mode::Alphanumeric => 13, - Mode::Byte => 16, - Mode::Kanji => 12, - }, - } - } - - /// Computes the number of bits needed to some data of a given raw length. - /// - /// use qrcode::types::Mode; - /// - /// assert_eq!(Mode::Numeric.data_bits_count(7), 24); - /// - /// Note that in Kanji mode, the `raw_data_len` is the number of Kanjis, - /// i.e. half the total size of bytes. - pub fn data_bits_count(self, raw_data_len: usize) -> usize { - match self { - Mode::Numeric => (raw_data_len * 10 + 2) / 3, - Mode::Alphanumeric => (raw_data_len * 11 + 1) / 2, - Mode::Byte => raw_data_len * 8, - Mode::Kanji => raw_data_len * 13, - } - } - - /// Find the lowest common mode which both modes are compatible with. - /// - /// use qrcode::types::Mode; - /// - /// let a = Mode::Numeric; - /// let b = Mode::Kanji; - /// let c = a.max(b); - /// assert!(a <= c); - /// assert!(b <= c); - /// - pub fn max(self, other: Self) -> Self { - match self.partial_cmp(&other) { - Some(Ordering::Less) | Some(Ordering::Equal) => other, - Some(Ordering::Greater) => self, - None => Mode::Byte, - } - } -} - -impl PartialOrd for Mode { - /// Defines a partial ordering between modes. If `a <= b`, then `b` contains - /// a superset of all characters supported by `a`. - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - match (*self, *other) { - (Mode::Numeric, Mode::Alphanumeric) - | (Mode::Numeric, Mode::Byte) - | (Mode::Alphanumeric, Mode::Byte) - | (Mode::Kanji, Mode::Byte) => Some(Ordering::Less), - (Mode::Alphanumeric, Mode::Numeric) - | (Mode::Byte, Mode::Numeric) - | (Mode::Byte, Mode::Alphanumeric) - | (Mode::Byte, Mode::Kanji) => Some(Ordering::Greater), - (a, b) if a == b => Some(Ordering::Equal), - _ => None, - } - } -} - -#[cfg(test)] -mod mode_tests { - use crate::types::Mode::{Alphanumeric, Byte, Kanji, Numeric}; - - #[test] - fn test_mode_order() { - assert!(Numeric < Alphanumeric); - assert!(Byte > Kanji); - assert!(!(Numeric < Kanji)); - assert!(!(Numeric >= Kanji)); - } - - #[test] - fn test_max() { - assert_eq!(Byte.max(Kanji), Byte); - assert_eq!(Numeric.max(Alphanumeric), Alphanumeric); - assert_eq!(Alphanumeric.max(Alphanumeric), Alphanumeric); - assert_eq!(Numeric.max(Kanji), Byte); - assert_eq!(Kanji.max(Numeric), Byte); - assert_eq!(Alphanumeric.max(Numeric), Alphanumeric); - assert_eq!(Kanji.max(Kanji), Kanji); - } -} - -//}}} diff --git a/repbuild/Cargo.toml b/repbuild/Cargo.toml index 400f6b7..5e185b8 100644 --- a/repbuild/Cargo.toml +++ b/repbuild/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "repbuild" -version = "0.1.0" +version = "0.2.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] -colored = "2.0" +env_logger = "0.10" +error-stack = "0.2" +fatfs = "0.3" +log = "0.4" diff --git a/repbuild/background.bmp b/repbuild/background.bmp new file mode 100644 index 0000000..2e112cf Binary files /dev/null and b/repbuild/background.bmp differ diff --git a/repbuild/limine.cfg b/repbuild/limine.cfg new file mode 100644 index 0000000..bfbe0b4 --- /dev/null +++ b/repbuild/limine.cfg @@ -0,0 +1,21 @@ +${ABLEOS_KERNEL}=boot:///kernel +# TODO: Make a boot background image for ableOS + +DEFAULT_ENTRY=1 +TIMEOUT=3 +VERBOSE=yes +INTERFACE_RESOLUTION=1024x768 +# Terminal related settings +TERM_WALLPAPER=boot:///background.bmp +TERM_BACKDROP=008080 + +:AbleOS + COMMENT=Default AbleOS boot entry. + PROTOCOL=limine + KERNEL_PATH=${ABLEOS_KERNEL} + KERNEL_CMDLINE= + # Setting a default resolution for the framebuffer + RESOLUTION=1024x768x24 + + # MODULE_PATH=boot:///boot/initrd.tar + # MODULE_CMDLINE=This is the first module. diff --git a/repbuild/src/main.rs b/repbuild/src/main.rs index bc4d571..04599ff 100644 --- a/repbuild/src/main.rs +++ b/repbuild/src/main.rs @@ -1,222 +1,226 @@ -/* - * Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me> - * Copyright (c) 2022, able <abl3theabove@gmail.com> - * - * SPDX-License-Identifier: MPL-2.0 - */ +use error_stack::{bail, report, Context, IntoReport, Result, ResultExt}; +use fatfs::{FileSystem, FormatVolumeOptions, FsOptions, ReadWriteSeek}; +use std::{fmt::Display, fs::File, io, path::Path, process::Command}; -use std::{fs, process::Command}; +fn main() -> Result<(), Error> { + env_logger::init(); + let mut args = std::env::args(); + args.next(); -use colored::*; + match args.next().as_deref() { + Some("build" | "b") => { + let mut release = false; + let mut target = Target::X86_64; + for arg in args { + if arg == "-r" || arg == "--release" { + release = true; + } + if arg == "rv64" || arg == "riscv64" || arg == "riscv64-virt" { + target = Target::Riscv64Virt; + } + } -struct Options { - pub subcommand: Subcommand, - pub arguments: Vec<String>, -} - -enum Subcommand { - Doc, - Help, - Run, - Empty, - /// Run all tests for all architectures - Test, - Unknown(String), -} - -impl Subcommand { - fn from_str<S: AsRef<str>>(str: S) -> Subcommand { - match str.as_ref() { - "doc" => Subcommand::Doc, - "help" => Subcommand::Help, - "run" | "r" => Subcommand::Run, - "test" | "t" => Subcommand::Test, - "" => Subcommand::Empty, - unknown => Subcommand::Unknown(unknown.to_string()), + build(release, target).change_context(Error::Build) } + Some("run" | "r") => { + let mut release = false; + let mut target = Target::X86_64; + for arg in args { + if arg == "-r" || arg == "--release" { + release = true; + } + if arg == "rv64" || arg == "riscv64" || arg == "riscv64-virt" { + target = Target::Riscv64Virt; + } + } + + build(release, target)?; + run(release, target) + } + Some("help" | "h") => { + println!(concat!( + "AbleOS RepBuild\n", + "Subcommands:\n", + " build (b): Build a bootable disk image\n", + " help (h): Print this message\n", + " run (r): Build and run AbleOS in QEMU\n\n", + "Options for build and run:\n", + " -r: build in release mode", + " [target]: sets target" + ),); + Ok(()) + } + _ => Err(report!(Error::InvalidSubCom)), } } -enum MachineType { +fn get_fs() -> Result<FileSystem<impl ReadWriteSeek>, io::Error> { + let path = Path::new("target/disk.img"); + + match std::fs::metadata(path) { + Err(e) if e.kind() == io::ErrorKind::NotFound => (), + Err(e) => bail!(e), + Ok(_) => { + return FileSystem::new( + File::options().read(true).write(true).open(path)?, + FsOptions::new(), + ) + .into_report() + } + } + + let mut img = File::options() + .read(true) + .write(true) + .create(true) + .open(path)?; + + img.set_len(1024 * 1024 * 64)?; + + fatfs::format_volume(&mut img, FormatVolumeOptions::new())?; + + let fs = FileSystem::new(img, FsOptions::new())?; + let bootdir = fs.root_dir().create_dir("efi")?.create_dir("boot")?; + + io::copy( + &mut File::open("limine/BOOTX64.EFI") + .into_report() + .attach_printable("copying Limine bootloader (have you pulled the submodule?)")?, + &mut bootdir.create_file("bootx64.efi")?, + )?; + + io::copy( + &mut File::open("repbuild/limine.cfg")?, + &mut fs.root_dir().create_file("limine.cfg")?, + )?; + + io::copy( + &mut File::open("repbuild/background.bmp")?, + &mut fs.root_dir().create_file("background.bmp")?, + )?; + + drop(bootdir); + Ok(fs) +} + +fn build(release: bool, target: Target) -> Result<(), Error> { + let fs = get_fs().change_context(Error::Io)?; + let mut com = Command::new("cargo"); + com.current_dir("kernel"); + com.args(["b"]); + if release { + com.arg("-r"); + } + + match target { + Target::Riscv64Virt => { + com.args(["--target", "targets/riscv64-virt-ableos.json"]); + } + _ => {} + } + + match com.status() { + Ok(s) if s.code() != Some(0) => bail!(Error::Build), + Err(e) => bail!(report!(e).change_context(Error::Build)), + _ => (), + } + + if target != Target::X86_64 { + return Ok(()); + } + + (|| -> std::io::Result<_> { + io::copy( + &mut File::open( + Path::new("target/x86_64-ableos") + .join(if release { "release" } else { "debug" }) + .join("kernel"), + )?, + &mut fs.root_dir().create_file("kernel")?, + ) + .map(|_| ()) + })() + .into_report() + .change_context(Error::Io) +} + +fn run(release: bool, target: Target) -> Result<(), Error> { + let mut com = match target { + Target::X86_64 => Command::new("qemu-system-x86_64"), + Target::Riscv64Virt => Command::new("qemu-system-riscv64"), + }; + + if target == Target::X86_64 { + #[rustfmt::skip] + com.args([ + "-bios", + std::env::var("REPBUILD_QEMU_FIRMWARE_PATH") + .as_deref() + .unwrap_or("/usr/share/OVMF/OVMF_CODE.fd"), + "-drive", "file=target/disk.img,format=raw", + "-m", "4G", + "-serial", "stdio", + "-smp", "cores=2", + ]); + + #[cfg(target_os = "linux")] + { + com.args(["-enable-kvm", "-cpu", "host"]); + } + } + + if target == Target::Riscv64Virt { + #[rustfmt::skip] + com.args([ + "-M", "virt", + "-m", "128M", + "-serial", "stdio", + "-kernel", + if release { + "target/riscv64-virt-ableos/release/kernel" + } else { + "target/riscv64-virt-ableos/debug/kernel" + } + ]); + } + + match com + .status() + .into_report() + .change_context(Error::ProcessSpawn)? + { + s if s.success() => Ok(()), + s => Err(report!(Error::Qemu(s.code()))), + } +} + +#[derive(Clone, Copy, PartialEq, Eq)] +enum Target { X86_64, - RiscV64, - AArch64, - Unknown(String), + Riscv64Virt, } -fn main() { - let options = options(); +#[derive(Debug)] +enum Error { + Build, + InvalidSubCom, + Io, + ProcessSpawn, + Qemu(Option<i32>), +} - match options.subcommand { - Subcommand::Test => { - Command::new("cargo") - .args(["test", "--target=json_targets/x86_64-ableos.json"]) - .current_dir(fs::canonicalize("./ableos").unwrap()) - .status() - .unwrap(); - - // panic!("Test Infrastructure missing"); - } - Subcommand::Doc => { - let machine_text = options.arguments.get(0).cloned().unwrap_or_default(); - - match machine(machine_text) { - MachineType::X86_64 => { - Command::new("cargo") - .args(["doc", "--open"]) - .current_dir(fs::canonicalize("./ableos").unwrap()) - .status() - .unwrap(); - } - MachineType::RiscV64 => { - Command::new("cargo") - .args(["doc", "--open", "--target=riscv64gc-unknown-none-elf"]) - .current_dir(fs::canonicalize("./ableos").unwrap()) - .status() - .unwrap(); - } - MachineType::AArch64 => { - Command::new("cargo") - .args(["doc", "--open", "--target=json_targets/aarch64-ableos.json"]) - .current_dir(fs::canonicalize("./ableos").unwrap()) - .status() - .unwrap(); - } - MachineType::Unknown(unknown) => { - eprintln!( - "{}: unknown machine type `{}`", - "error".red().bold(), - unknown.bold(), - ); - eprintln!("expected one of x86_64, riscv64 or aarch64"); - } +impl Context for Error {} +impl Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Build => f.write_str("failed to build the kernel"), + Self::InvalidSubCom => { + f.write_str("missing or invalid subcommand (available: build, run)") } - } - Subcommand::Help => help(), - Subcommand::Run => { - let machine_text = options.arguments.get(0).cloned().unwrap_or_default(); - let debug = options.arguments.get(1).cloned().unwrap_or_default(); - let debug = matches!(debug.as_str(), "--debug" | "--dbg" | "-d"); - - match machine(machine_text) { - MachineType::X86_64 if debug => { - Command::new("cargo") - .args(["run", "--", "-S", "-gdb", "tcp:9000"]) - .current_dir(fs::canonicalize("./ableos").unwrap()) - .status() - .unwrap(); - } - MachineType::X86_64 => { - Command::new("cargo") - .args(["run", "--release"]) - .current_dir(fs::canonicalize("./ableos").unwrap()) - .status() - .unwrap(); - } - MachineType::RiscV64 if debug => { - eprintln!( - "{}: debug is not implemented for riscv64", - "error".red().bold() - ); - } - MachineType::RiscV64 => { - Command::new("cargo") - .args(["build", "--release", "--target=riscv64gc-unknown-none-elf"]) - .current_dir(fs::canonicalize("./ableos").unwrap()) - .status() - .unwrap(); - - Command::new("qemu-system-riscv64") - .args(["-machine", "virt"]) - .args(["-cpu", "rv64"]) - .args(["-smp", "8"]) - .args(["-m", "128M"]) - .arg("-bios") - .arg("src/arch/riscv/firmwear/opensbi-riscv64-generic-fw_jump.bin") - .arg("-kernel") - .arg("target/riscv64gc-unknown-none-elf/release/ableos") - .current_dir(fs::canonicalize("./ableos").unwrap()) - .status() - .unwrap(); - } - MachineType::AArch64 if debug => { - eprintln!( - "{}: debug is not implemented for aarch64", - "error".red().bold() - ); - } - MachineType::AArch64 => { - Command::new("cargo") - .args([ - "build", - "--release", - "--target=json_targets/aarch64-ableos.json", - ]) - .current_dir(fs::canonicalize("./ableos").unwrap()) - .status() - .unwrap(); - - Command::new("qemu-system-aarch64") - .args(["-machine", "virt"]) - .args(["-m", "1024M"]) - .args(["-cpu", "cortex-a53"]) - .args(["-kernel", "target/aarch64-ableos/release/ableos"]) - .args(["-device", "virtio-keyboard"]) - .current_dir(fs::canonicalize("./ableos").unwrap()) - .status() - .unwrap(); - } - MachineType::Unknown(unknown) => { - eprintln!( - "{}: unknown machine type `{}`", - "error".red().bold(), - unknown.bold(), - ); - eprintln!("expected one of x86_64, riscv64 or aarch64"); - } - } - } - Subcommand::Empty => { - eprintln!("{}: no subcommand passed", "error".red().bold()); - help(); - } - Subcommand::Unknown(unknown) => { - eprintln!( - "{}: unknown subcommand `{}`", - "error".red().bold(), - unknown.bold() - ); - help(); + Self::Io => f.write_str("IO error"), + Self::ProcessSpawn => f.write_str("failed to spawn a process"), + Self::Qemu(Some(c)) => write!(f, "QEMU Error: {c}"), + Self::Qemu(None) => write!(f, "QEMU Error: interrupted by signal"), } } } - -fn options() -> Options { - let subcommand = std::env::args().nth(1).unwrap_or_default(); - let arguments = std::env::args().skip(2).collect(); - - Options { - subcommand: Subcommand::from_str(subcommand), - arguments, - } -} - -fn machine<S: AsRef<str>>(text: S) -> MachineType { - match text.as_ref() { - "x86" | "x86_64" => MachineType::X86_64, - "riscv" | "riscv64" => MachineType::RiscV64, - "arm" | "arm64" | "aarch64" => MachineType::AArch64, - "" => { - eprintln!( - "{}: no machine type passed, defaulting to x86_64", - "warning".yellow().bold() - ); - MachineType::X86_64 - } - unknown => MachineType::Unknown(unknown.to_string()), - } -} - -fn help() { - todo!("`help`") -} diff --git a/rust-toolchain.toml b/rust-toolchain.toml index d32c413..ecc21cc 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] channel = "nightly" -components = ["rust-src", "llvm-tools-preview"] +components = ["rust-src", "llvm-tools"] diff --git a/userland/README.md b/userland/README.md deleted file mode 100644 index d8df701..0000000 --- a/userland/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# ableOS userland - diff --git a/userland/bogomips.c b/userland/bogomips.c deleted file mode 100644 index 7e601c8..0000000 --- a/userland/bogomips.c +++ /dev/null @@ -1,77 +0,0 @@ -// Utterly stolen from stack overflow - - - - - -/* - * Standalone BogoMips program - * - * Based on code Linux kernel code in init/main.c and - * include/linux/delay.h - * - * For more information on interpreting the results, see the BogoMIPS - * Mini-HOWTO document. - * - * version: 1.3 - * author: Jeff Tranter (Jeff_Tranter@Mitel.COM) - */ - -#include <stdio.h> -#include <time.h> - -#ifdef CLASSIC_BOGOMIPS -/* the original code from the Linux kernel */ -static __inline__ void delay(int loops) -{ - __asm__(".align 2,0x90\n1:\tdecl %0\n\tjns 1b": :"a" (loops):"ax"); -} -#endif - -#ifdef QNX_BOGOMIPS -/* version for QNX C compiler */ -void delay(int loops); -#pragma aux delay = \ - "l1:" \ - "dec eax" \ - "jns l1" \ - parm nomemory [eax] modify exact nomemory [eax]; -#endif - -#ifdef PORTABLE_BOGOMIPS -/* portable version */ -static void delay(int loops) -{ - long i; - for (i = loops; i >= 0 ; i--) - ; -} -#endif - -int -main(void) -{ - unsigned long loops_per_sec = 1; - unsigned long ticks; - - printf("Calibrating delay loop.. "); - fflush(stdout); - - while ((loops_per_sec <<= 1)) { - ticks = clock(); - delay(loops_per_sec); - ticks = clock() - ticks; - if (ticks >= CLOCKS_PER_SEC) { - loops_per_sec = (loops_per_sec / ticks) * CLOCKS_PER_SEC; - printf("ok - %lu.%02lu BogoMips\n", - loops_per_sec/500000, - (loops_per_sec/5000) % 100 - ); - return 0; - } - } - printf("failed\n"); - return -1; -} - - diff --git a/userland/lib_syscalls/C/file_calls.c b/userland/lib_syscalls/C/file_calls.c deleted file mode 100644 index 4a8b050..0000000 --- a/userland/lib_syscalls/C/file_calls.c +++ /dev/null @@ -1,30 +0,0 @@ -enum FSReturns { - /// The system call was successful - Ok, - - /// The directory can not be created - DirectoryCouldNotBeCreated, - - /// The directory could not be removed - DirectoryCouldNotBeRemoved, - - /// - FileCouldNotBeCreated, - - /// - FileCouldNotBeRemoved, - /// The file could not be opened - - FileCouldNotBeOpened, - /// - FileCouldNotBeClosed, -}; - -int create_directory(path) { - return DirectoryCouldNotBeCreated; -} - -/// -int remove_directory(path) { - return DirectoryCouldNotBeRemoved; -} diff --git a/userland/lib_syscalls/README.md b/userland/lib_syscalls/README.md deleted file mode 100644 index 72dff5f..0000000 --- a/userland/lib_syscalls/README.md +++ /dev/null @@ -1 +0,0 @@ -# The libraries here are simplified examples of syscall APi \ No newline at end of file diff --git a/userland/rname/Cargo.lock b/userland/rname/Cargo.lock deleted file mode 100644 index c4f7097..0000000 --- a/userland/rname/Cargo.lock +++ /dev/null @@ -1,7 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "rname" -version = "0.1.0" diff --git a/userland/rname/Cargo.toml b/userland/rname/Cargo.toml deleted file mode 100644 index 8f2e8e2..0000000 --- a/userland/rname/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "rname" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] diff --git a/userland/rname/src/main.rs b/userland/rname/src/main.rs deleted file mode 100644 index 87fb20f..0000000 --- a/userland/rname/src/main.rs +++ /dev/null @@ -1,44 +0,0 @@ -//! An implementation of the uname command. - -use crate::Arch::*; -use core::fmt; - -// an example string "Darwin Roadrunner.local 10.3.0 Darwin Kernel Version 10.3.0: Fri Feb 26 11:58:09 PST 2010; root:xnu-1504.3.12~1/RELEASE_I386 i386" -pub struct RName { - pub arch: Arch, -} - -#[derive(Debug, Clone, Copy)] -pub enum Arch { - X86, - X86_64, - ARM, - ARM64, - PPC, - PPC64, - MIPS, - MIPS64, - SPARC, - SPARC64, - Unknown, -} - -impl fmt::Display for Arch { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self) - } -} - -fn main() { - let mut rname_string = "".to_string(); - - rname_string.push_str("ableOS"); - - let arch = Some(X86_64); - if let Some(arch) = arch { - let fmt_str = format!(" {:?}", arch); - rname_string.push_str(&fmt_str); - } - - println!("{}", rname_string); -} diff --git a/userland/root_fs/ext2.img b/userland/root_fs/ext2.img deleted file mode 100644 index 762bece..0000000 Binary files a/userland/root_fs/ext2.img and /dev/null differ diff --git a/userland/wasm_pk_data/src/lib.rs b/userland/wasm_pk_data/src/lib.rs deleted file mode 100644 index fc5a014..0000000 --- a/userland/wasm_pk_data/src/lib.rs +++ /dev/null @@ -1,22 +0,0 @@ -#![no_std] - -extern crate alloc; - -use { - alloc::{string::String, vec::Vec}, - serde::Deserialize, -}; - -#[derive(Debug, Deserialize)] -pub struct Version { - pub major: u16, - pub minor: u8, - pub patch: u8, -} - -#[derive(Debug, Deserialize)] -pub struct Metadata { - pub name: String, - pub version: Version, - pub authors: Vec<String>, -}