From 4bb8979d6a38f5e4b7e15dd0d39a4f06a2620a3c Mon Sep 17 00:00:00 2001 From: houndthe Date: Sat, 20 Mar 2021 01:22:24 +0100 Subject: [PATCH 01/21] Implement telfhash for import table and add TLSH to the project --- .../fileformat/file_format/elf/elf_format.h | 1 + .../types/import_table/elf_import_table.h | 18 + .../types/import_table/import_table.h | 9 +- include/retdec/fileformat/utils/tlsh/tlsh.h | 183 + .../retdec/fileformat/utils/tlsh/tlsh_impl.h | 164 + .../retdec/fileformat/utils/tlsh/tlsh_util.h | 70 + .../retdec/fileformat/utils/tlsh/version.h | 19 + .../fileformat/utils/tlsh/win_version.h | 21 + src/fileformat/CMakeLists.txt | 4 + src/fileformat/file_format/elf/elf_format.cpp | 2 +- .../types/import_table/elf_import_table.cpp | 89 + .../types/import_table/import_table.cpp | 8 + src/fileformat/utils/tlsh/tlsh.cpp | 241 + src/fileformat/utils/tlsh/tlsh_impl.cpp | 811 +++ src/fileformat/utils/tlsh/tlsh_util.cpp | 5051 +++++++++++++++++ .../file_information/file_information.cpp | 8 + .../file_information/file_information.h | 1 + .../file_information_types/import_table.cpp | 5 + .../file_information_types/import_table.h | 1 + .../import_table_plain_getter.cpp | 2 + .../import_table_json_getter.cpp | 2 + 21 files changed, 6706 insertions(+), 4 deletions(-) create mode 100644 include/retdec/fileformat/types/import_table/elf_import_table.h create mode 100644 include/retdec/fileformat/utils/tlsh/tlsh.h create mode 100644 include/retdec/fileformat/utils/tlsh/tlsh_impl.h create mode 100644 include/retdec/fileformat/utils/tlsh/tlsh_util.h create mode 100644 include/retdec/fileformat/utils/tlsh/version.h create mode 100644 include/retdec/fileformat/utils/tlsh/win_version.h create mode 100644 src/fileformat/types/import_table/elf_import_table.cpp create mode 100644 src/fileformat/utils/tlsh/tlsh.cpp create mode 100644 src/fileformat/utils/tlsh/tlsh_impl.cpp create mode 100644 src/fileformat/utils/tlsh/tlsh_util.cpp diff --git a/include/retdec/fileformat/file_format/elf/elf_format.h b/include/retdec/fileformat/file_format/elf/elf_format.h index 39210c580..35d95bea5 100644 --- a/include/retdec/fileformat/file_format/elf/elf_format.h +++ b/include/retdec/fileformat/file_format/elf/elf_format.h @@ -13,6 +13,7 @@ #include "retdec/fileformat/file_format/file_format.h" #include "retdec/fileformat/types/note_section/elf_notes.h" +#include "retdec/fileformat/types/import_table/elf_import_table.h" namespace retdec { namespace fileformat { diff --git a/include/retdec/fileformat/types/import_table/elf_import_table.h b/include/retdec/fileformat/types/import_table/elf_import_table.h new file mode 100644 index 000000000..b1ffddb21 --- /dev/null +++ b/include/retdec/fileformat/types/import_table/elf_import_table.h @@ -0,0 +1,18 @@ +/** + * @file include/retdec/fileformat/types/import_table/elf_import_table.h + * @brief Class for ELF import table. + * @copyright (c) 2021 Avast Software, licensed under the MIT license + */ + +#include "import_table.h" + +namespace retdec { +namespace fileformat { + +class ElfImportTable : public ImportTable +{ +public: + void computeHashes() override; +}; +} // namespace fileformat +} // namespace retdec \ No newline at end of file diff --git a/include/retdec/fileformat/types/import_table/import_table.h b/include/retdec/fileformat/types/import_table/import_table.h index a3b1b4041..b7c3a79b8 100644 --- a/include/retdec/fileformat/types/import_table/import_table.h +++ b/include/retdec/fileformat/types/import_table/import_table.h @@ -11,7 +11,6 @@ #include #include "retdec/fileformat/types/import_table/import.h" - namespace retdec { namespace fileformat { @@ -20,7 +19,7 @@ namespace fileformat { */ class ImportTable { - private: + protected: using importsIterator = std::vector>::const_iterator; std::vector libraries; ///< name of libraries std::vector missingDeps; ///< missing dependencies @@ -28,6 +27,7 @@ class ImportTable std::string impHashCrc32; ///< imphash CRC32 std::string impHashMd5; ///< imphash MD5 std::string impHashSha256; ///< imphash SHA256 + std::string impHashTlsh; public: /// @name Getters /// @{ @@ -39,6 +39,7 @@ class ImportTable const std::string& getImphashCrc32() const; const std::string& getImphashMd5() const; const std::string& getImphashSha256() const; + const std::string& getImpHashTlsh() const; const std::vector & getMissingDependencies() const; std::string getLibrary(std::size_t libraryIndex) const; @@ -55,7 +56,7 @@ class ImportTable /// @name Other methods /// @{ - void computeHashes(); + virtual void computeHashes(); void clear(); void addLibrary(std::string name, bool missingDependency = false); void addImport(std::unique_ptr&& import); @@ -70,6 +71,8 @@ class ImportTable void dump(std::string &dumpTable) const; void dumpLibrary(std::size_t libraryIndex, std::string &libraryDump) const; /// @} + + virtual ~ImportTable() = default; }; } // namespace fileformat diff --git a/include/retdec/fileformat/utils/tlsh/tlsh.h b/include/retdec/fileformat/utils/tlsh/tlsh.h new file mode 100644 index 000000000..c373cc336 --- /dev/null +++ b/include/retdec/fileformat/utils/tlsh/tlsh.h @@ -0,0 +1,183 @@ +// tlsh.h - TrendLSH Hash Algorithm + +/* + * TLSH is provided for use under two licenses: Apache OR BSD. + * Users may opt to use either license depending on the license + * restictions of the systems with which they plan to integrate + * the TLSH code. + */ + +/* ============== + * Apache License + * ============== + * Copyright 2013 Trend Micro Incorporated + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* =========== + * BSD License + * =========== + * Copyright (c) 2013, Trend Micro Incorporated + * 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. + + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + */ + +#ifndef HEADER_TLSH_H +#define HEADER_TLSH_H + +#if defined WINDOWS || defined MINGW +#include "win_version.h" +#else +#include "version.h" +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#ifdef __cplusplus + +class TlshImpl; + +// Define TLSH_STRING_LEN_REQ, which is the string length of "T1" + the hex value of the Tlsh hash. +// BUCKETS_256 & CHECKSUM_3B are compiler switches defined in CMakeLists.txt +#if defined BUCKETS_256 + #define TLSH_STRING_LEN_REQ 136 + // changed the minimum data length to 256 for version 3.3 + #define MIN_DATA_LENGTH 50 + // added the -force option for version 3.5 + // added the -conservatibe option for version 3.17 + #define MIN_CONSERVATIVE_DATA_LENGTH 256 +#endif + +#if defined BUCKETS_128 + #define TLSH_STRING_LEN_REQ 72 + // changed the minimum data length to 256 for version 3.3 + #define MIN_DATA_LENGTH 50 + // added the -force option for version 3.5 + // added the -conservatibe option for version 3.17 + #define MIN_CONSERVATIVE_DATA_LENGTH 256 +#endif + +#if defined BUCKETS_48 + // No 3 Byte checksum option for 48 Bucket min hash + #define TLSH_STRING_LEN 30 + // changed the minimum data length to 256 for version 3.3 + #define MIN_DATA_LENGTH 10 + // added the -force option for version 3.5 + #define MIN_CONSERVATIVE_DATA_LENGTH 10 +#endif + +#define TLSH_STRING_BUFFER_LEN (TLSH_STRING_LEN_REQ+1) + +#ifdef WINDOWS +#include +#else + #if defined(__SPARC) || defined(_AS_MK_OS_RH73) + #define TLSH_API + #else + #define TLSH_API __attribute__ ((visibility("default"))) + #endif +#endif + +class TLSH_API Tlsh{ + +public: + Tlsh(); + Tlsh(const Tlsh& other); + + /* allow the user to add data in multiple iterations */ + void update(const unsigned char* data, unsigned int len); + + /* to signal the class there is no more data to be added */ + void final(const unsigned char* data = NULL, unsigned int len = 0, int fc_cons_option = 0); + + /* to get the hex-encoded hash code */ + const char* getHash(int showvers=0) const ; + + /* to get the hex-encoded hash code without allocating buffer in TlshImpl - bufSize should be TLSH_STRING_BUFFER_LEN */ + const char* getHash(char *buffer, unsigned int bufSize, int showvers=0) const; + + /* to bring to object back to the initial state */ + void reset(); + + // access functions + int Lvalue(); + int Q1ratio(); + int Q2ratio(); + int Checksum(int k); + int BucketValue(int bucket); + + /* calculate difference */ + /* The len_diff parameter specifies if the file length is to be included in the difference calculation (len_diff=true) or if it */ + /* is to be excluded (len_diff=false). In general, the length should be considered in the difference calculation, but there */ + /* could be applications where a part of the adversarial activity might be to add a lot of content. For example to add 1 million */ + /* zero bytes at the end of a file. In that case, the caller would want to exclude the length from the calculation. */ + int totalDiff(const Tlsh *, bool len_diff=true) const; + + /* validate TrendLSH string and reset the hash according to it */ + int fromTlshStr(const char* str); + + /* check if Tlsh object is valid to operate */ + bool isValid() const; + + /* display the contents of NOTICE.txt */ + static void display_notice(); + + /* Return the version information used to build this library */ + static const char *version(); + + // operators + Tlsh& operator=(const Tlsh& other); + bool operator==(const Tlsh& other) const; + bool operator!=(const Tlsh& other) const; + + ~Tlsh(); + +private: + TlshImpl* impl; +}; + +#ifdef TLSH_DISTANCE_PARAMETERS +void set_tlsh_distance_parameters(int length_mult_value, int qratio_mult_value, int hist_diff1_add_value, int hist_diff2_add_value, int hist_diff3_add_value); +#endif + +#endif + +#endif + diff --git a/include/retdec/fileformat/utils/tlsh/tlsh_impl.h b/include/retdec/fileformat/utils/tlsh/tlsh_impl.h new file mode 100644 index 000000000..c5a006872 --- /dev/null +++ b/include/retdec/fileformat/utils/tlsh/tlsh_impl.h @@ -0,0 +1,164 @@ +/* + * TLSH is provided for use under two licenses: Apache OR BSD. + * Users may opt to use either license depending on the license + * restictions of the systems with which they plan to integrate + * the TLSH code. + */ + +/* ============== + * Apache License + * ============== + * Copyright 2013 Trend Micro Incorporated + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* =========== + * BSD License + * =========== + * Copyright (c) 2013, Trend Micro Incorporated + * 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. + + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + */ + +#if defined WINDOWS || defined MINGW +#include "win_version.h" +#else +#include "version.h" +#endif + +#ifndef HEADER_TLSH_IMPL_H +#define HEADER_TLSH_IMPL_H + +#define SLIDING_WND_SIZE 5 + +#define BUCKETS 256 +#define Q_BITS 2 // 2 bits; quartile value 0, 1, 2, 3 + +// BUCKETS_256 & CHECKSUM_3B are compiler switches defined in CMakeLists.txt + +#if defined BUCKETS_256 + #define EFF_BUCKETS 256 + #define CODE_SIZE 64 // 256 * 2 bits = 64 bytes + #if defined CHECKSUM_3B + #define INTERNAL_TLSH_STRING_LEN 138 + #define TLSH_CHECKSUM_LEN 3 + // defined in tlsh.h #define TLSH_STRING_LEN 138 // 2 + 3 + 64 bytes = 138 hexidecimal chars + #else + #define INTERNAL_TLSH_STRING_LEN 134 + #define TLSH_CHECKSUM_LEN 1 + // defined in tlsh.h #define TLSH_STRING_LEN 134 // 2 + 1 + 64 bytes = 134 hexidecimal chars + #endif +#endif + +#if defined BUCKETS_128 + #define EFF_BUCKETS 128 + #define CODE_SIZE 32 // 128 * 2 bits = 32 bytes + #if defined CHECKSUM_3B + #define INTERNAL_TLSH_STRING_LEN 74 + #define TLSH_CHECKSUM_LEN 3 + // defined in tlsh.h #define TLSH_STRING_LEN 74 // 2 + 3 + 32 bytes = 74 hexidecimal chars + #else + #define INTERNAL_TLSH_STRING_LEN 70 + #define TLSH_CHECKSUM_LEN 1 + // defined in tlsh.h #define TLSH_STRING_LEN 70 // 2 + 1 + 32 bytes = 70 hexidecimal chars + #endif +#endif + +#if defined BUCKETS_48 + #define INTERNAL_TLSH_STRING_LEN 33 + #define EFF_BUCKETS 48 + #define CODE_SIZE 12 // 48 * 2 bits = 12 bytes + #define TLSH_CHECKSUM_LEN 1 + // defined in tlsh.h #define TLSH_STRING_LEN 30 // 2 + 1 + 12 bytes = 30 hexidecimal chars +#endif + +class TlshImpl +{ +public: + TlshImpl(); + ~TlshImpl(); +public: + void update(const unsigned char* data, unsigned int len); + void fast_update(const unsigned char* data, unsigned int len); + void final(int fc_cons_option = 0); + void reset(); + const char* hash(int showvers) const; + const char* hash(char *buffer, unsigned int bufSize, int showvers) const; // saves allocating hash string in TLSH instance - bufSize should be TLSH_STRING_LEN + 1 + int compare(const TlshImpl& other) const; + int totalDiff(const TlshImpl& other, bool len_diff=true) const; + int Lvalue(); + int Q1ratio(); + int Q2ratio(); + int Checksum(int k); + int BucketValue(int bucket); + int fromTlshStr(const char* str); + bool isValid() const { return lsh_code_valid; } + +private: + unsigned int *a_bucket; + unsigned char slide_window[SLIDING_WND_SIZE]; + unsigned int data_len; + + struct lsh_bin_struct { + unsigned char checksum[TLSH_CHECKSUM_LEN]; // 1 to 3 bytes + unsigned char Lvalue; // 1 byte + union { +#if defined(__SPARC) || defined(_AIX) + #pragma pack(1) +#endif + unsigned char QB; + struct{ +#if defined(__SPARC) || defined(_AIX) + unsigned char Q2ratio : 4; + unsigned char Q1ratio : 4; +#else + unsigned char Q1ratio : 4; + unsigned char Q2ratio : 4; +#endif + } QR; + } Q; // 1 bytes + unsigned char tmp_code[CODE_SIZE]; // 32/64 bytes + } lsh_bin; + + mutable char *lsh_code; // allocated when hash() function without buffer is called - 70/134 bytes or 74/138 bytes + bool lsh_code_valid; // true iff final() or fromTlshStr complete successfully +}; + + +#endif + diff --git a/include/retdec/fileformat/utils/tlsh/tlsh_util.h b/include/retdec/fileformat/utils/tlsh/tlsh_util.h new file mode 100644 index 000000000..fa66e9dd2 --- /dev/null +++ b/include/retdec/fileformat/utils/tlsh/tlsh_util.h @@ -0,0 +1,70 @@ +/* + * TLSH is provided for use under two licenses: Apache OR BSD. + * Users may opt to use either license depending on the license + * restictions of the systems with which they plan to integrate + * the TLSH code. + */ + +/* ============== + * Apache License + * ============== + * Copyright 2013 Trend Micro Incorporated + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* =========== + * BSD License + * =========== + * Copyright (c) 2013, Trend Micro Incorporated + * 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. + + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + */ + +#ifndef HEADER_TLSH_UTIL_H +#define HEADER_TLSH_UTIL_H + +unsigned char b_mapping(unsigned char salt, unsigned char i, unsigned char j, unsigned char k); +unsigned char l_capturing(unsigned int len); +int mod_diff(unsigned int x, unsigned int y, unsigned int R); +int h_distance( int len, const unsigned char x[], const unsigned char y[]); +void to_hex( unsigned char * psrc, int len, char* pdest); +void from_hex( const char* psrc, int len, unsigned char* pdest); +unsigned char swap_byte( const unsigned char in ); + +#endif + diff --git a/include/retdec/fileformat/utils/tlsh/version.h b/include/retdec/fileformat/utils/tlsh/version.h new file mode 100644 index 000000000..e4689eba8 --- /dev/null +++ b/include/retdec/fileformat/utils/tlsh/version.h @@ -0,0 +1,19 @@ +/**************************************************** + * This file is generated by cmake. Modify the top + * level CMakeLists.txt to change the VERSION numbers + ****************************************************/ + +#define VERSION_MAJOR 4 +#define VERSION_MINOR 5 +#define VERSION_PATCH 0 +#define TLSH_HASH "compact hash" +#define TLSH_CHECKSUM "1 byte checksum" + +#define buckets 128 +#define TLSH_CHECKSUM_LEN 1 +#define EFF_BUCKETS 128 +#define CODE_SIZE 32 +#define MIN_DATA_LENGTH 50 +#define MIN_CONSERVATIVE_DATA_LENGTH 256 +#define TLSH_STRING_LEN_REQ 72 +#define INTERNAL_TLSH_STRING_LEN 70 diff --git a/include/retdec/fileformat/utils/tlsh/win_version.h b/include/retdec/fileformat/utils/tlsh/win_version.h new file mode 100644 index 000000000..6c2e40483 --- /dev/null +++ b/include/retdec/fileformat/utils/tlsh/win_version.h @@ -0,0 +1,21 @@ +/**************************************************** + * The file "version.h" is generated by cmake. + * But there was trouble creating this file on Windows + * so this is the default calues required + * Beware - do not change these values unless you really understand the software. + ****************************************************/ + +#define VERSION_MAJOR 4 +#define VERSION_MINOR 5 +#define VERSION_PATCH 0 +#define TLSH_HASH "compact hash" +#define TLSH_CHECKSUM "1 byte checksum" + +#define buckets 128 +#define TLSH_CHECKSUM_LEN 1 +#define EFF_BUCKETS 128 +#define CODE_SIZE 32 +#define MIN_DATA_LENGTH 50 +#define MIN_CONSERVATIVE_DATA_LENGTH 256 +#define TLSH_STRING_LEN_REQ 72 +#define INTERNAL_TLSH_STRING_LEN 70 diff --git a/src/fileformat/CMakeLists.txt b/src/fileformat/CMakeLists.txt index b69b5252b..1e7ef4134 100644 --- a/src/fileformat/CMakeLists.txt +++ b/src/fileformat/CMakeLists.txt @@ -13,6 +13,9 @@ add_library(fileformat STATIC utils/other.cpp utils/asn1.cpp utils/file_io.cpp + utils/tlsh/tlsh_impl.cpp + utils/tlsh/tlsh_util.cpp + utils/tlsh/tlsh.cpp format_factory.cpp types/dotnet_headers/blob_stream.cpp types/dotnet_headers/user_string_stream.cpp @@ -34,6 +37,7 @@ add_library(fileformat STATIC types/visual_basic/visual_basic_extern.cpp types/import_table/import.cpp types/import_table/import_table.cpp + types/import_table/elf_import_table.cpp types/import_table/pe_import.cpp types/export_table/export.cpp types/export_table/export_table.cpp diff --git a/src/fileformat/file_format/elf/elf_format.cpp b/src/fileformat/file_format/elf/elf_format.cpp index 1f28fbc21..05d2183ac 100644 --- a/src/fileformat/file_format/elf/elf_format.cpp +++ b/src/fileformat/file_format/elf/elf_format.cpp @@ -1758,7 +1758,7 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio { if(!importTable) { - importTable = new ImportTable(); + importTable = new ElfImportTable(); } auto keyIter = importNameAddressMap.equal_range(name); // we create std::set from std::multimap values in order to ensure determinism diff --git a/src/fileformat/types/import_table/elf_import_table.cpp b/src/fileformat/types/import_table/elf_import_table.cpp new file mode 100644 index 000000000..ef749b0fd --- /dev/null +++ b/src/fileformat/types/import_table/elf_import_table.cpp @@ -0,0 +1,89 @@ +/** + * @file include/retdec/fileformat/types/import_table/elf_import_table.h + * @brief Class for ELF import table. + * @copyright (c) 2021 Avast Software, licensed under the MIT license + */ + +#include "retdec/fileformat/utils/crypto.h" +#include "retdec/utils/string.h" +#include "retdec/fileformat/utils/tlsh/tlsh.h" +#include "retdec/fileformat/types/import_table/elf_import_table.h" +#include +#include + +using namespace retdec::utils; + +namespace retdec { +namespace fileformat { + +static const std::vector exclusion_strings = { + "__libc_start_main", // main function + "main", // main function + "abort", // ARM default + "cachectl", // MIPS default + "cacheflush", // MIPS default + "puts", // Compiler optimization (function replacement) + "atol", // Compiler optimization (function replacement) + "malloc_trim" // GNU extensions +}; + +bool isSymbolExcluded(std::string symbol) +{ + if (symbol.empty()) { + return true; + } + std::regex exclusion_regex("(^[_\.].*$)|(^.*64$)|(^str.*$)|(^mem.*$)"); + if (std::regex_match(symbol, exclusion_regex)) { + return true; + } + + if (std::find(exclusion_strings.begin(), exclusion_strings.end(), symbol) != exclusion_strings.end()) { + return true; + } + + return false; +} + +/** + * Compute import telfhash + */ +void ElfImportTable::computeHashes() +{ + std::vector imported_symbols; + + for (const auto& import : imports) { + auto funcName = toLower(import->getName()); + + // filter the symbols just as telfhash does for the same result + if (isSymbolExcluded(funcName)) { + continue; + } + + imported_symbols.push_back(funcName); + } + + std::sort(imported_symbols.begin(), imported_symbols.end()); + + std::string impHashString; + for (const auto& symbol : imported_symbols) { + if (!impHashString.empty()) + impHashString.append(1, ','); + + impHashString.append(symbol); + } + + if (impHashString.size()) { + Tlsh tlsh; + tlsh.update(reinterpret_cast(impHashString.data()), impHashString.size()); + tlsh.final(); + const int show_version = 1; /* this prepends the hash with 'T' + number of the version */ + impHashTlsh = toLower(tlsh.getHash(show_version)); + + impHashCrc32 = getCrc32(reinterpret_cast(impHashString.data()), impHashString.size()); + impHashMd5 = getMd5(reinterpret_cast(impHashString.data()), impHashString.size()); + impHashSha256 = getSha256(reinterpret_cast(impHashString.data()), impHashString.size()); + } +} + +} // namespace fileformat +} // namespace retdec \ No newline at end of file diff --git a/src/fileformat/types/import_table/import_table.cpp b/src/fileformat/types/import_table/import_table.cpp index c7edb0ced..c2fc06675 100644 --- a/src/fileformat/types/import_table/import_table.cpp +++ b/src/fileformat/types/import_table/import_table.cpp @@ -675,6 +675,14 @@ const std::string& ImportTable::getImphashSha256() const return impHashSha256; } +/** + * Get imphash as tlsh + * @return Imphash as tlsh + */ +const std::string& ImportTable::getImpHashTlsh() const { + return impHashTlsh; +} + /** * Get list of missing dependencies * @return Vector of missing dependencies diff --git a/src/fileformat/utils/tlsh/tlsh.cpp b/src/fileformat/utils/tlsh/tlsh.cpp new file mode 100644 index 000000000..e39b942a0 --- /dev/null +++ b/src/fileformat/utils/tlsh/tlsh.cpp @@ -0,0 +1,241 @@ +/* + * TLSH is provided for use under two licenses: Apache OR BSD. + * Users may opt to use either license depending on the license + * restictions of the systems with which they plan to integrate + * the TLSH code. + */ + +/* ============== + * Apache License + * ============== + * Copyright 2013 Trend Micro Incorporated + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* =========== + * BSD License + * =========== + * Copyright (c) 2013, Trend Micro Incorporated + * 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. + + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + */ + +#include "retdec/fileformat/utils/tlsh/tlsh.h" +#include "retdec/fileformat/utils/tlsh/tlsh_impl.h" +#include "stdio.h" +#include +#include + +///////////////////////////////////////////////////// +// C++ Implementation + +Tlsh::Tlsh():impl(NULL) +{ + impl = new TlshImpl(); +} + +Tlsh::Tlsh(const Tlsh& other):impl(NULL) +{ + impl = new TlshImpl(); + *impl = *other.impl; +} + +Tlsh::~Tlsh() +{ + delete impl; +} + +void Tlsh::display_notice() +{ + printf(" =========================================================================\n"); + printf(" == NOTICE file for use with the Apache License, Version 2.0, ==\n"); + printf(" == in this case for the Trend Locality Sensitive Hash distribution. ==\n"); + printf(" =========================================================================\n"); + printf("\n"); + printf(" Trend Locality Sensitive Hash (TLSH)\n"); + printf(" Copyright 2010-2014 Trend Micro\n"); + printf("\n"); + printf(" This product includes software developed at\n"); + printf(" Trend Micro (http://www.trendmicro.com/)\n"); + printf("\n"); + printf(" Refer to the following publications for more information:\n"); + printf(" \n"); + printf(" Jonathan Oliver, Chun Cheng and Yanggui Chen,\n"); + printf(" \"TLSH - A Locality Sensitive Hash\"\n"); + printf(" 4th Cybercrime and Trustworthy Computing Workshop, Sydney, November 2013\n"); + printf(" https://github.com/trendmicro/tlsh/blob/master/TLSH_CTC_final.pdf\n"); + printf(" \n"); + printf(" Jonathan Oliver, Scott Forman and Chun Cheng,\n"); + printf(" \"Using Randomization to Attack Similarity Digests\"\n"); + printf(" Applications and Techniques in Information Security. Springer Berlin Heidelberg, 2014. 199-210.\n"); + printf(" https://github.com/trendmicro/tlsh/blob/master/Attacking_LSH_and_Sim_Dig.pdf\n"); + printf("\n"); + printf(" Jonathan Oliver and Jayson Pryde\n"); + printf(" http://blog.trendmicro.com/trendlabs-security-intelligence/smart-whitelisting-using-locality-sensitive-hashing/\n"); + printf("\n"); + printf("\n"); + printf("\n"); + printf("\n"); + printf("\n"); + printf("\n"); + printf("\n"); + printf("\n"); + printf(" \n"); + printf(" SHA1 of first 242 lines of LICENSE - so that we can append NOTICE.txt to LICENSE\n"); + printf(" $ head -n 242 LICENSE | openssl dgst -sha1\n"); + printf(" (stdin)= 11e8757af16132dd60979eacd73a525a40ff31f0\n"); + printf("\n"); +} + +const char *Tlsh::version() +{ + static char versionBuf[256]; + if (versionBuf[0] == '\0') + snprintf(versionBuf, sizeof(versionBuf), "%d.%d.%d %s %s sliding_window=%d", + VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, TLSH_HASH, TLSH_CHECKSUM, SLIDING_WND_SIZE); + return versionBuf; +} + +void Tlsh::update(const unsigned char* data, unsigned int len) +{ + if ( NULL != impl ) + impl->update(data, len); +} + +void Tlsh::final(const unsigned char* data, unsigned int len, int fc_cons_option) +{ + if ( NULL != impl ){ + if ( NULL != data && len > 0 ) + impl->update(data, len); + impl->final(fc_cons_option); + } +} + +const char* Tlsh::getHash(int showvers) const +{ + if ( NULL != impl ) + return impl->hash(showvers); + else + return ""; +} + +const char* Tlsh::getHash (char *buffer, unsigned int bufSize, int showvers) const +{ + if ( NULL != impl ) + return impl->hash(buffer, bufSize, showvers); + else { + buffer[0] = '\0'; + return buffer; + } +} + +void Tlsh::reset() +{ + if ( NULL != impl ) + impl->reset(); +} + +Tlsh& Tlsh::operator=(const Tlsh& other) +{ + if (this == &other) + return *this; + + *impl = *other.impl; + return *this; +} + +bool Tlsh::operator==(const Tlsh& other) const +{ + if( this == &other ) + return true; + else if( NULL == impl || NULL == other.impl ) + return false; + else + return ( 0 == impl->compare(*other.impl) ); +} + +bool Tlsh::operator!=(const Tlsh& other) const +{ + return !(*this==other); +} + +int Tlsh::Lvalue() +{ + return( impl->Lvalue() ); +} +int Tlsh::Q1ratio() +{ + return( impl->Q1ratio() ); +} +int Tlsh::Q2ratio() +{ + return( impl->Q2ratio() ); +} +int Tlsh::Checksum(int k) +{ + return( impl->Checksum(k) ); +} +int Tlsh::BucketValue(int bucket) +{ + return( impl->BucketValue(bucket) ); +} + +int Tlsh::totalDiff(const Tlsh *other, bool len_diff) const +{ + if( NULL==impl || NULL == other || NULL == other->impl ) + return -(EINVAL); + else if ( this == other ) + return 0; + else + return (impl->totalDiff(*other->impl, len_diff)); +} + +int Tlsh::fromTlshStr(const char* str) +{ + if ( NULL == impl ) + return -(ENOMEM); + else if ( NULL == str ) + return -(EINVAL); + else + return impl->fromTlshStr(str); +} + +bool Tlsh::isValid() const +{ + return (impl ? impl->isValid() : false); +} diff --git a/src/fileformat/utils/tlsh/tlsh_impl.cpp b/src/fileformat/utils/tlsh/tlsh_impl.cpp new file mode 100644 index 000000000..c95c3c108 --- /dev/null +++ b/src/fileformat/utils/tlsh/tlsh_impl.cpp @@ -0,0 +1,811 @@ +/* + * TLSH is provided for use under two licenses: Apache OR BSD. + * Users may opt to use either license depending on the license + * restictions of the systems with which they plan to integrate + * the TLSH code. + */ + +/* ============== + * Apache License + * ============== + * Copyright 2013 Trend Micro Incorporated + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* =========== + * BSD License + * =========== + * Copyright (c) 2013, Trend Micro Incorporated + * 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. + + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + */ + +#include "retdec/fileformat/utils/tlsh/tlsh.h" +#include "retdec/fileformat/utils/tlsh/tlsh_impl.h" +#include "retdec/fileformat/utils/tlsh/tlsh_util.h" + +#include +#include +#include +#include +#include +#include +#include + +#define RANGE_LVALUE 256 +#define RANGE_QRATIO 16 + +static void find_quartile(unsigned int *q1, unsigned int *q2, unsigned int *q3, const unsigned int * a_bucket); +static unsigned int partition(unsigned int * buf, unsigned int left, unsigned int right); + +//////////////////////////////////////////////////////////////////////////////////////////////// + +TlshImpl::TlshImpl() : a_bucket(NULL), data_len(0), lsh_code(NULL), lsh_code_valid(false) +{ + memset(this->slide_window, 0, sizeof this->slide_window); + memset(&this->lsh_bin, 0, sizeof this->lsh_bin); + + assert (sizeof (this->lsh_bin.Q.QR) == sizeof (this->lsh_bin.Q.QB)); +} + +TlshImpl::~TlshImpl() +{ + delete [] this->a_bucket; + delete [] this->lsh_code; +} + +void TlshImpl::reset() +{ + delete [] this->a_bucket; this->a_bucket = NULL; + memset(this->slide_window, 0, sizeof this->slide_window); + delete [] this->lsh_code; this->lsh_code = NULL; + memset(&this->lsh_bin, 0, sizeof this->lsh_bin); + this->data_len = 0; + this->lsh_code_valid = false; +} + +//////////////////////////////////////////////////////////////////////////////////////////// + +// Pearson's sample random table +static unsigned char v_table[256] = { + 1, 87, 49, 12, 176, 178, 102, 166, 121, 193, 6, 84, 249, 230, 44, 163, + 14, 197, 213, 181, 161, 85, 218, 80, 64, 239, 24, 226, 236, 142, 38, 200, + 110, 177, 104, 103, 141, 253, 255, 50, 77, 101, 81, 18, 45, 96, 31, 222, + 25, 107, 190, 70, 86, 237, 240, 34, 72, 242, 20, 214, 244, 227, 149, 235, + 97, 234, 57, 22, 60, 250, 82, 175, 208, 5, 127, 199, 111, 62, 135, 248, + 174, 169, 211, 58, 66, 154, 106, 195, 245, 171, 17, 187, 182, 179, 0, 243, + 132, 56, 148, 75, 128, 133, 158, 100, 130, 126, 91, 13, 153, 246, 216, 219, + 119, 68, 223, 78, 83, 88, 201, 99, 122, 11, 92, 32, 136, 114, 52, 10, + 138, 30, 48, 183, 156, 35, 61, 26, 143, 74, 251, 94, 129, 162, 63, 152, + 170, 7, 115, 167, 241, 206, 3, 150, 55, 59, 151, 220, 90, 53, 23, 131, + 125, 173, 15, 238, 79, 95, 89, 16, 105, 137, 225, 224, 217, 160, 37, 123, + 118, 73, 2, 157, 46, 116, 9, 145, 134, 228, 207, 212, 202, 215, 69, 229, + 27, 188, 67, 124, 168, 252, 42, 4, 29, 108, 21, 247, 19, 205, 39, 203, + 233, 40, 186, 147, 198, 192, 155, 33, 164, 191, 98, 204, 165, 180, 117, 76, + 140, 36, 210, 172, 41, 54, 159, 8, 185, 232, 113, 196, 231, 47, 146, 120, + 51, 65, 28, 144, 254, 221, 93, 189, 194, 139, 112, 43, 71, 109, 184, 209 +}; + +// Pearson's algorithm +unsigned char b_mapping(unsigned char salt, unsigned char i, unsigned char j, unsigned char k) { + unsigned char h = 0; + + h = v_table[h ^ salt]; + h = v_table[h ^ i]; + h = v_table[h ^ j]; + h = v_table[h ^ k]; + return h; +} + +/* +NEVER USED - showing a step in the optimization sequence +unsigned char faster_b_mapping(unsigned char mod_salt, unsigned char i, unsigned char j, unsigned char k) { + unsigned char h; + + h = v_table[mod_salt ^ i]; + h = v_table[h ^ j]; + h = v_table[h ^ k]; + return h; +} +*/ + +#define fast_b_mapping(ms,i,j,k) (v_table[ v_table[ v_table[ms^i] ^ j] ^ k ]) + +//////////////////////////////////////////////////////////////////////////////////////////// + +#if SLIDING_WND_SIZE==5 + #define SLIDING_WND_SIZE_M1 4 +#elif SLIDING_WND_SIZE==4 + #define SLIDING_WND_SIZE_M1 3 +#elif SLIDING_WND_SIZE==6 + #define SLIDING_WND_SIZE_M1 5 +#elif SLIDING_WND_SIZE==7 + #define SLIDING_WND_SIZE_M1 6 +#elif SLIDING_WND_SIZE==8 + #define SLIDING_WND_SIZE_M1 7 +#endif + +void TlshImpl::update(const unsigned char* data, unsigned int len) +{ + if (this->lsh_code_valid) { + fprintf(stderr, "call to update() on a tlsh that is already valid\n"); + return; + } + + #define RNG_SIZE SLIDING_WND_SIZE + #define RNG_IDX(i) ((i+RNG_SIZE)%RNG_SIZE) + + unsigned int fed_len = this->data_len; + + if (this->a_bucket == NULL) { + this->a_bucket = new unsigned int [BUCKETS]; + memset(this->a_bucket, 0, sizeof(int)*BUCKETS); + } + +#if SLIDING_WND_SIZE==5 + if (TLSH_CHECKSUM_LEN == 1) { + fast_update(data, len); + return; + } +#endif + int j = (int)(this->data_len % RNG_SIZE); + + for( unsigned int i=0; islide_window[j] = data[i]; + + if ( fed_len >= SLIDING_WND_SIZE_M1 ) { + //only calculate when input >= 5 bytes + int j_1 = RNG_IDX(j-1); + int j_2 = RNG_IDX(j-2); + int j_3 = RNG_IDX(j-3); +#if SLIDING_WND_SIZE>=5 + int j_4 = RNG_IDX(j-4); +#endif +#if SLIDING_WND_SIZE>=6 + int j_5 = RNG_IDX(j-5); +#endif +#if SLIDING_WND_SIZE>=7 + int j_6 = RNG_IDX(j-6); +#endif +#if SLIDING_WND_SIZE>=8 + int j_7 = RNG_IDX(j-7); +#endif + +#ifndef CHECKSUM_0B + for (int k = 0; k < TLSH_CHECKSUM_LEN; k++) { + if (k == 0) { + // b_mapping(0, ... ) + this->lsh_bin.checksum[k] = fast_b_mapping(1, this->slide_window[j], this->slide_window[j_1], this->lsh_bin.checksum[k]); + } else { + // use calculated 1 byte checksums to expand the total checksum to 3 bytes + this->lsh_bin.checksum[k] = b_mapping(this->lsh_bin.checksum[k-1], this->slide_window[j], this->slide_window[j_1], this->lsh_bin.checksum[k]); + } + } +#endif + + unsigned char r; + // b_mapping(2, ... ) + r = fast_b_mapping(49, this->slide_window[j], this->slide_window[j_1], this->slide_window[j_2]); + this->a_bucket[r]++; + // b_mapping(3, ... ) + r = fast_b_mapping(12, this->slide_window[j], this->slide_window[j_1], this->slide_window[j_3]); + this->a_bucket[r]++; + // b_mapping(5, ... ) + r = fast_b_mapping(178, this->slide_window[j], this->slide_window[j_2], this->slide_window[j_3]); + this->a_bucket[r]++; +#if SLIDING_WND_SIZE>=5 + // b_mapping(7, ... ) + r = fast_b_mapping(166, this->slide_window[j], this->slide_window[j_2], this->slide_window[j_4]); + this->a_bucket[r]++; + // b_mapping(11, ... ) + r = fast_b_mapping(84, this->slide_window[j], this->slide_window[j_1], this->slide_window[j_4]); + this->a_bucket[r]++; + // b_mapping(13, ... ) + r = fast_b_mapping(230, this->slide_window[j], this->slide_window[j_3], this->slide_window[j_4]); + this->a_bucket[r]++; +#endif +#if SLIDING_WND_SIZE>=6 + // b_mapping(17, ... ) + r = fast_b_mapping(197, this->slide_window[j], this->slide_window[j_1], this->slide_window[j_5]); + this->a_bucket[r]++; + // b_mapping(19, ... ) + r = fast_b_mapping(181, this->slide_window[j], this->slide_window[j_2], this->slide_window[j_5]); + this->a_bucket[r]++; + // b_mapping(23, ... ) + r = fast_b_mapping(80, this->slide_window[j], this->slide_window[j_3], this->slide_window[j_5]); + this->a_bucket[r]++; + // b_mapping(29, ... ) + r = fast_b_mapping(142, this->slide_window[j], this->slide_window[j_4], this->slide_window[j_5]); + this->a_bucket[r]++; +#endif +#if SLIDING_WND_SIZE>=7 + // b_mapping(31, ... ) + r = fast_b_mapping(200, this->slide_window[j], this->slide_window[j_1], this->slide_window[j_6]); + this->a_bucket[r]++; + // b_mapping(37, ... ) + r = fast_b_mapping(253, this->slide_window[j], this->slide_window[j_2], this->slide_window[j_6]); + this->a_bucket[r]++; + // b_mapping(41, ... ) + r = fast_b_mapping(101, this->slide_window[j], this->slide_window[j_3], this->slide_window[j_6]); + this->a_bucket[r]++; + // b_mapping(43, ... ) + r = fast_b_mapping(18, this->slide_window[j], this->slide_window[j_4], this->slide_window[j_6]); + this->a_bucket[r]++; + // b_mapping(47, ... ) + r = fast_b_mapping(222, this->slide_window[j], this->slide_window[j_5], this->slide_window[j_6]); + this->a_bucket[r]++; +#endif +#if SLIDING_WND_SIZE>=8 + // b_mapping(53, ... ) + r = fast_b_mapping(237, this->slide_window[j], this->slide_window[j_1], this->slide_window[j_7]); + this->a_bucket[r]++; + // b_mapping(59, ... ) + r = fast_b_mapping(214, this->slide_window[j], this->slide_window[j_2], this->slide_window[j_7]); + this->a_bucket[r]++; + // b_mapping(61, ... ) + r = fast_b_mapping(227, this->slide_window[j], this->slide_window[j_3], this->slide_window[j_7]); + this->a_bucket[r]++; + // b_mapping(67, ... ) + r = fast_b_mapping(22, this->slide_window[j], this->slide_window[j_4], this->slide_window[j_7]); + this->a_bucket[r]++; + // b_mapping(71, ... ) + r = fast_b_mapping(175, this->slide_window[j], this->slide_window[j_5], this->slide_window[j_7]); + this->a_bucket[r]++; + // b_mapping(73, ... ) + r = fast_b_mapping(5, this->slide_window[j], this->slide_window[j_6], this->slide_window[j_7]); + this->a_bucket[r]++; +#endif + } + } + this->data_len += len; +} + +///////////////////////////////////////////////////////////////////////////// +// update for the case when SLIDING_WND_SIZE==5 && (TLSH_CHECKSUM_LEN == 1) +///////////////////////////////////////////////////////////////////////////// + +void TlshImpl::fast_update(const unsigned char* data, unsigned int len) +{ + unsigned int fed_len = this->data_len; + int j = (int)(this->data_len % RNG_SIZE); + unsigned char checksum = this->lsh_bin.checksum[0]; + + for( unsigned int i=0; i= SLIDING_WND_SIZE_M1 ) { + //only calculate when input >= 5 bytes + if ((i >= 4) && (i+5 < len)) { + unsigned a0 = data[i-4]; + unsigned a1 = data[i-3]; + unsigned a2 = data[i-2]; + unsigned a3 = data[i-1]; + unsigned a4 = data[i]; + unsigned a5 = data[i+1]; + unsigned a6 = data[i+2]; + unsigned a7 = data[i+3]; + unsigned a8 = data[i+4]; + + checksum = fast_b_mapping(1, a4, a3, checksum ); + this->a_bucket[ fast_b_mapping(49, a4, a3, a2 ) ]++; + this->a_bucket[ fast_b_mapping(12, a4, a3, a1 ) ]++; + this->a_bucket[ fast_b_mapping(178, a4, a2, a1 ) ]++; + this->a_bucket[ fast_b_mapping(166, a4, a2, a0 ) ]++; + this->a_bucket[ fast_b_mapping(84, a4, a3, a0 ) ]++; + this->a_bucket[ fast_b_mapping(230, a4, a1, a0 ) ]++; + + checksum = fast_b_mapping(1, a5, a4, checksum ); + this->a_bucket[ fast_b_mapping(49, a5, a4, a3 ) ]++; + this->a_bucket[ fast_b_mapping(12, a5, a4, a2 ) ]++; + this->a_bucket[ fast_b_mapping(178, a5, a3, a2 ) ]++; + this->a_bucket[ fast_b_mapping(166, a5, a3, a1 ) ]++; + this->a_bucket[ fast_b_mapping(84, a5, a4, a1 ) ]++; + this->a_bucket[ fast_b_mapping(230, a5, a2, a1 ) ]++; + + checksum = fast_b_mapping(1, a6, a5, checksum ); + this->a_bucket[ fast_b_mapping(49, a6, a5, a4 ) ]++; + this->a_bucket[ fast_b_mapping(12, a6, a5, a3 ) ]++; + this->a_bucket[ fast_b_mapping(178, a6, a4, a3 ) ]++; + this->a_bucket[ fast_b_mapping(166, a6, a4, a2 ) ]++; + this->a_bucket[ fast_b_mapping(84, a6, a5, a2 ) ]++; + this->a_bucket[ fast_b_mapping(230, a6, a3, a2 ) ]++; + + checksum = fast_b_mapping(1, a7, a6, checksum ); + this->a_bucket[ fast_b_mapping(49, a7, a6, a5 ) ]++; + this->a_bucket[ fast_b_mapping(12, a7, a6, a4 ) ]++; + this->a_bucket[ fast_b_mapping(178, a7, a5, a4 ) ]++; + this->a_bucket[ fast_b_mapping(166, a7, a5, a3 ) ]++; + this->a_bucket[ fast_b_mapping(84, a7, a6, a3 ) ]++; + this->a_bucket[ fast_b_mapping(230, a7, a4, a3 ) ]++; + + checksum = fast_b_mapping(1, a8, a7, checksum ); + this->a_bucket[ fast_b_mapping(49, a8, a7, a6 ) ]++; + this->a_bucket[ fast_b_mapping(12, a8, a7, a5 ) ]++; + this->a_bucket[ fast_b_mapping(178, a8, a6, a5 ) ]++; + this->a_bucket[ fast_b_mapping(166, a8, a6, a4 ) ]++; + this->a_bucket[ fast_b_mapping(84, a8, a7, a4 ) ]++; + this->a_bucket[ fast_b_mapping(230, a8, a5, a4 ) ]++; + + i=i+5; + fed_len=fed_len+5; + j=RNG_IDX(j+5); + } else { + this->slide_window[j] = data[i]; + int j_1 = RNG_IDX(j-1); if (i >= 1) { this->slide_window[j_1] = data[i-1]; } + int j_2 = RNG_IDX(j-2); if (i >= 2) { this->slide_window[j_2] = data[i-2]; } + int j_3 = RNG_IDX(j-3); if (i >= 3) { this->slide_window[j_3] = data[i-3]; } + int j_4 = RNG_IDX(j-4); if (i >= 4) { this->slide_window[j_4] = data[i-4]; } + + checksum = fast_b_mapping(1, this->slide_window[j], this->slide_window[j_1], checksum ); + this->a_bucket[ fast_b_mapping(49, this->slide_window[j], this->slide_window[j_1], this->slide_window[j_2] ) ]++; + this->a_bucket[ fast_b_mapping(12, this->slide_window[j], this->slide_window[j_1], this->slide_window[j_3] ) ]++; + this->a_bucket[ fast_b_mapping(178, this->slide_window[j], this->slide_window[j_2], this->slide_window[j_3] ) ]++; + this->a_bucket[ fast_b_mapping(166, this->slide_window[j], this->slide_window[j_2], this->slide_window[j_4] ) ]++; + this->a_bucket[ fast_b_mapping(84, this->slide_window[j], this->slide_window[j_1], this->slide_window[j_4] ) ]++; + this->a_bucket[ fast_b_mapping(230, this->slide_window[j], this->slide_window[j_3], this->slide_window[j_4] ) ]++; + i++; + fed_len++; + j=RNG_IDX(j+1); + } + } else { + i++; + fed_len++; + j=RNG_IDX(j+1); + } + } + this->lsh_bin.checksum[0] = checksum; + this->data_len += len; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +/* to signal the class there is no more data to be added */ +void TlshImpl::final(int fc_cons_option) +{ + if (this->lsh_code_valid) { + fprintf(stderr, "call to final() on a tlsh that is already valid\n"); + return; + } + // incoming data must more than or equal to MIN_DATA_LENGTH bytes + if ((fc_cons_option <= 1) && (this->data_len < MIN_DATA_LENGTH)) { + // this->lsh_code be empty + delete [] this->a_bucket; this->a_bucket = NULL; + return; + } + if ((fc_cons_option == 2) && (this->data_len < MIN_CONSERVATIVE_DATA_LENGTH)) { + // this->lsh_code be empty + delete [] this->a_bucket; this->a_bucket = NULL; + return; + } + + unsigned int q1, q2, q3; + find_quartile(&q1, &q2, &q3, this->a_bucket); + + // issue #79 - divide by 0 if q3 == 0 + if (q3 == 0) { + delete [] this->a_bucket; this->a_bucket = NULL; + return; + } + + // buckets must be more than 50% non-zero + int nonzero = 0; + for(unsigned int i=0; ia_bucket[4*i + j] > 0) { + nonzero++; + } + } + } +#if defined BUCKETS_48 + if (nonzero < 18) { + // printf("nonzero=%d\n", nonzero); + delete [] this->a_bucket; this->a_bucket = NULL; + return; + } +#else + if (nonzero <= 4*CODE_SIZE/2) { + delete [] this->a_bucket; this->a_bucket = NULL; + return; + } +#endif + + for(unsigned int i=0; ia_bucket[4*i + j]; + if( q3 < k ) { + h += 3 << (j*2); // leave the optimization j*2 = j<<1 or j*2 = j+j for compiler + } else if( q2 < k ) { + h += 2 << (j*2); + } else if( q1 < k ) { + h += 1 << (j*2); + } + } + this->lsh_bin.tmp_code[i] = h; + } + + //Done with a_bucket so deallocate + delete [] this->a_bucket; this->a_bucket = NULL; + + this->lsh_bin.Lvalue = l_capturing(this->data_len); + this->lsh_bin.Q.QR.Q1ratio = (unsigned int) ((float)(q1*100)/(float) q3) % 16; + this->lsh_bin.Q.QR.Q2ratio = (unsigned int) ((float)(q2*100)/(float) q3) % 16; + this->lsh_code_valid = true; +} + +int TlshImpl::fromTlshStr(const char* str) +{ + // Assume that we have 128 Buckets + int start = 0; + if (strncmp(str, "T1", 2) == 0) { + start = 2; + } else { + start = 0; + } + // Validate input string + for( int ii=0; ii < INTERNAL_TLSH_STRING_LEN; ii++ ) { + int i = ii + start; + if (!( (str[i] >= '0' && str[i] <= '9') || + (str[i] >= 'A' && str[i] <= 'F') || + (str[i] >= 'a' && str[i] <= 'f') )) + { + // printf("warning ii=%d str[%d]='%c'\n", ii, i, str[i]); + return 1; + } + } + int xi = INTERNAL_TLSH_STRING_LEN + start; + if (( (str[xi] >= '0' && str[xi] <= '9') || + (str[xi] >= 'A' && str[xi] <= 'F') || + (str[xi] >= 'a' && str[xi] <= 'f') )) + { + // printf("warning xi=%d\n", xi); + return 1; + } + + this->reset(); + + lsh_bin_struct tmp; + from_hex( &str[start], INTERNAL_TLSH_STRING_LEN, (unsigned char*)&tmp ); + + // Reconstruct checksum, Qrations & lvalue + for (int k = 0; k < TLSH_CHECKSUM_LEN; k++) { + this->lsh_bin.checksum[k] = swap_byte(tmp.checksum[k]); + } + this->lsh_bin.Lvalue = swap_byte( tmp.Lvalue ); + this->lsh_bin.Q.QB = swap_byte(tmp.Q.QB); + for( int i=0; i < CODE_SIZE; i++ ){ + this->lsh_bin.tmp_code[i] = (tmp.tmp_code[CODE_SIZE-1-i]); + } + this->lsh_code_valid = true; + + return 0; +} + +const char* TlshImpl::hash(char *buffer, unsigned int bufSize, int showvers) const +{ + if (bufSize < TLSH_STRING_LEN_REQ + 1) { + strncpy(buffer, "", bufSize); + return buffer; + } + if (this->lsh_code_valid == false) { + strncpy(buffer, "", bufSize); + return buffer; + } + + lsh_bin_struct tmp; + for (int k = 0; k < TLSH_CHECKSUM_LEN; k++) { + tmp.checksum[k] = swap_byte( this->lsh_bin.checksum[k] ); + } + tmp.Lvalue = swap_byte( this->lsh_bin.Lvalue ); + tmp.Q.QB = swap_byte( this->lsh_bin.Q.QB ); + for( int i=0; i < CODE_SIZE; i++ ){ + tmp.tmp_code[i] = (this->lsh_bin.tmp_code[CODE_SIZE-1-i]); + } + + if (showvers) { + buffer[0] = 'T'; + buffer[1] = '0' + showvers; + to_hex( (unsigned char*)&tmp, sizeof(tmp), &buffer[2]); + } else { + to_hex( (unsigned char*)&tmp, sizeof(tmp), buffer); + } + return buffer; +} + +/* to get the hex-encoded hash code */ +const char* TlshImpl::hash(int showvers) const +{ + if (this->lsh_code != NULL) { + // lsh_code has been previously calculated, so just return it + return this->lsh_code; + } + + this->lsh_code = new char [TLSH_STRING_LEN_REQ+1]; + memset(this->lsh_code, 0, TLSH_STRING_LEN_REQ+1); + + return hash(this->lsh_code, TLSH_STRING_LEN_REQ+1, showvers); +} + + +// compare +int TlshImpl::compare(const TlshImpl& other) const +{ + return (memcmp( &(this->lsh_bin), &(other.lsh_bin), sizeof(this->lsh_bin))); +} + +//////////////////////////////////////////// +// the default for these parameters is 12 +//////////////////////////////////////////// + +static int length_mult = 12; +static int qratio_mult = 12; + +#ifdef TLSH_DISTANCE_PARAMETERS + + int hist_diff1_add = 1; + int hist_diff2_add = 2; + int hist_diff3_add = 6; + +void set_tlsh_distance_parameters(int length_mult_value, int qratio_mult_value, int hist_diff1_add_value, int hist_diff2_add_value, int hist_diff3_add_value) +{ + if (length_mult_value != -1) { + length_mult = length_mult_value; + } + if (qratio_mult_value != -1) { + qratio_mult = qratio_mult_value; + } + if (hist_diff1_add_value != -1) { + hist_diff1_add = hist_diff1_add_value; + } + if (hist_diff2_add_value != -1) { + hist_diff2_add = hist_diff2_add_value; + } + if (hist_diff3_add_value != -1) { + hist_diff3_add = hist_diff3_add_value; + } +} +#endif + +int TlshImpl::Lvalue() +{ + return(this->lsh_bin.Lvalue); +} +int TlshImpl::Q1ratio() +{ + return(this->lsh_bin.Q.QR.Q1ratio); +} +int TlshImpl::Q2ratio() +{ + return(this->lsh_bin.Q.QR.Q2ratio); +} +int TlshImpl::Checksum(int k) +{ + if ((k >= TLSH_CHECKSUM_LEN) || (k < 0)) { + return(0); + } + return(this->lsh_bin.checksum[k]); +} +int TlshImpl::BucketValue(int bucket) +{ +int idx; +int elem; +unsigned char bv; +// default TLSH +// #define EFF_BUCKETS 128 +// #define CODE_SIZE 32 // 128 * 2 bits = 32 bytes + + idx = (CODE_SIZE - (bucket / 4)) - 1; +// if ((idx < 0) || (idx >= CODE_SIZE)) { +// printf("error in BucketValue: idx=%d\n", idx); +// exit(1); +// } + elem = bucket % 4; + bv = this->lsh_bin.tmp_code[idx]; + int h1 = bv / 16; + int h2 = bv % 16; + int p1 = h1 / 4; + int p2 = h1 % 4; + int p3 = h2 / 4; + int p4 = h2 % 4; + if (elem == 0) { + return(p1); + } + if (elem == 1) { + return(p2); + } + if (elem == 2) { + return(p3); + } + return(p4); +} + +int TlshImpl::totalDiff(const TlshImpl& other, bool len_diff) const +{ + int diff = 0; + + if (len_diff) { + int ldiff = mod_diff( this->lsh_bin.Lvalue, other.lsh_bin.Lvalue, RANGE_LVALUE); + if ( ldiff == 0 ) + diff = 0; + else if ( ldiff == 1 ) + diff = 1; + else + diff += ldiff*length_mult; + } + + int q1diff = mod_diff( this->lsh_bin.Q.QR.Q1ratio, other.lsh_bin.Q.QR.Q1ratio, RANGE_QRATIO); + if ( q1diff <= 1 ) + diff += q1diff; + else + diff += (q1diff-1)*qratio_mult; + + int q2diff = mod_diff( this->lsh_bin.Q.QR.Q2ratio, other.lsh_bin.Q.QR.Q2ratio, RANGE_QRATIO); + if ( q2diff <= 1) + diff += q2diff; + else + diff += (q2diff-1)*qratio_mult; + + for (int k = 0; k < TLSH_CHECKSUM_LEN; k++) { + if (this->lsh_bin.checksum[k] != other.lsh_bin.checksum[k] ) { + diff ++; + break; + } + } + + diff += h_distance( CODE_SIZE, this->lsh_bin.tmp_code, other.lsh_bin.tmp_code ); + + return (diff); +} + + + +#define SWAP_UINT(x,y) do {\ + unsigned int int_tmp = (x); \ + (x) = (y); \ + (y) = int_tmp; } while(0) + +void find_quartile(unsigned int *q1, unsigned int *q2, unsigned int *q3, const unsigned int * a_bucket) +{ + unsigned int bucket_copy[EFF_BUCKETS], short_cut_left[EFF_BUCKETS], short_cut_right[EFF_BUCKETS], spl=0, spr=0; + unsigned int p1 = EFF_BUCKETS/4-1; + unsigned int p2 = EFF_BUCKETS/2-1; + unsigned int p3 = EFF_BUCKETS-EFF_BUCKETS/4-1; + unsigned int end = EFF_BUCKETS-1; + + for(unsigned int i=0; i<=end; i++) { + bucket_copy[i] = a_bucket[i]; + } + + for( unsigned int l=0, r=end; ; ) { + unsigned int ret = partition( bucket_copy, l, r ); + if( ret > p2 ) { + r = ret - 1; + short_cut_right[spr] = ret; + spr++; + } else if( ret < p2 ){ + l = ret + 1; + short_cut_left[spl] = ret; + spl++; + } else { + *q2 = bucket_copy[p2]; + break; + } + } + + short_cut_left[spl] = p2-1; + short_cut_right[spr] = p2+1; + + for( unsigned int i=0, l=0; i<=spl; i++ ) { + unsigned int r = short_cut_left[i]; + if( r > p1 ) { + for( ; ; ) { + unsigned int ret = partition( bucket_copy, l, r ); + if( ret > p1 ) { + r = ret-1; + } else if( ret < p1 ) { + l = ret+1; + } else { + *q1 = bucket_copy[p1]; + break; + } + } + break; + } else if( r < p1 ) { + l = r; + } else { + *q1 = bucket_copy[p1]; + break; + } + } + + for( unsigned int i=0, r=end; i<=spr; i++ ) { + unsigned int l = short_cut_right[i]; + if( l < p3 ) { + for( ; ; ) { + unsigned int ret = partition( bucket_copy, l, r ); + if( ret > p3 ) { + r = ret-1; + } else if( ret < p3 ) { + l = ret+1; + } else { + *q3 = bucket_copy[p3]; + break; + } + } + break; + } else if( l > p3 ) { + r = l; + } else { + *q3 = bucket_copy[p3]; + break; + } + } + +} + +unsigned int partition(unsigned int * buf, unsigned int left, unsigned int right) +{ + if( left == right ) { + return left; + } + if( left+1 == right ) { + if( buf[left] > buf[right] ) { + SWAP_UINT( buf[left], buf[right] ); + } + return left; + } + + unsigned int ret = left, pivot = (left + right)>>1; + + unsigned int val = buf[pivot]; + + buf[pivot] = buf[right]; + buf[right] = val; + + for( unsigned int i = left; i < right; i++ ) { + if( buf[i] < val ) { + SWAP_UINT( buf[ret], buf[i] ); + ret++; + } + } + buf[right] = buf[ret]; + buf[ret] = val; + + return ret; +} + + diff --git a/src/fileformat/utils/tlsh/tlsh_util.cpp b/src/fileformat/utils/tlsh/tlsh_util.cpp new file mode 100644 index 000000000..a5435a84d --- /dev/null +++ b/src/fileformat/utils/tlsh/tlsh_util.cpp @@ -0,0 +1,5051 @@ +/* + * TLSH is provided for use under two licenses: Apache OR BSD. + * Users may opt to use either license depending on the license + * restictions of the systems with which they plan to integrate + * the TLSH code. + */ + +/* ============== + * Apache License + * ============== + * Copyright 2013 Trend Micro Incorporated + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* =========== + * BSD License + * =========== + * Copyright (c) 2013, Trend Micro Incorporated + * 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. + + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + */ + +/* + * Util definition and functions + */ + +#include + +// Compile and run gen_arr2.cpp to generate bit_pairs_diff_table +static unsigned char bit_pairs_diff_table[][256] = { +{ +0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, 6, 7, 8, 12, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, 12, 13, 14, 18, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, 10, 11, 12, 16, +8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, 14, 15, 16, 20, +6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, 12, 13, 14, 18, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, 14, 15, 16, 20, +12, 13, 14, 18, 13, 14, 15, 19, 14, 15, 16, 20, 18, 19, 20, 24 +}, +{ +1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, 7, 6, 7, 8, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, 13, 12, 13, 14, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, 11, 10, 11, 12, +9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, 15, 14, 15, 16, +7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, 13, 12, 13, 14, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, 15, 14, 15, 16, +13, 12, 13, 14, 14, 13, 14, 15, 15, 14, 15, 16, 19, 18, 19, 20 +}, +{ +2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, 8, 7, 6, 7, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, 14, 13, 12, 13, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, 12, 11, 10, 11, +10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, 16, 15, 14, 15, +8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, 14, 13, 12, 13, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, 16, 15, 14, 15, +14, 13, 12, 13, 15, 14, 13, 14, 16, 15, 14, 15, 20, 19, 18, 19 +}, +{ +6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, 12, 8, 7, 6, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, 18, 14, 13, 12, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, 16, 12, 11, 10, +14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, 20, 16, 15, 14, +12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, 18, 14, 13, 12, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, 20, 16, 15, 14, +18, 14, 13, 12, 19, 15, 14, 13, 20, 16, 15, 14, 24, 20, 19, 18 +}, +{ +1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, +9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, +7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, +13, 14, 15, 19, 12, 13, 14, 18, 13, 14, 15, 19, 14, 15, 16, 20 +}, +{ +2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, +10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, +8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, +14, 13, 14, 15, 13, 12, 13, 14, 14, 13, 14, 15, 15, 14, 15, 16 +}, +{ +3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, +11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, +9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, +15, 14, 13, 14, 14, 13, 12, 13, 15, 14, 13, 14, 16, 15, 14, 15 +}, +{ +7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, +15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, +13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, +19, 15, 14, 13, 18, 14, 13, 12, 19, 15, 14, 13, 20, 16, 15, 14 +}, +{ +2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, +10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, +8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, +14, 15, 16, 20, 13, 14, 15, 19, 12, 13, 14, 18, 13, 14, 15, 19 +}, +{ +3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, +11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, +9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, +15, 14, 15, 16, 14, 13, 14, 15, 13, 12, 13, 14, 14, 13, 14, 15 +}, +{ +4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, +12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, +10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, +16, 15, 14, 15, 15, 14, 13, 14, 14, 13, 12, 13, 15, 14, 13, 14 +}, +{ +8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, +16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, +14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, +20, 16, 15, 14, 19, 15, 14, 13, 18, 14, 13, 12, 19, 15, 14, 13 +}, +{ +6, 7, 8, 12, 2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +12, 13, 14, 18, 8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +10, 11, 12, 16, 6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, +14, 15, 16, 20, 10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, +12, 13, 14, 18, 8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +14, 15, 16, 20, 10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, +18, 19, 20, 24, 14, 15, 16, 20, 13, 14, 15, 19, 12, 13, 14, 18 +}, +{ +7, 6, 7, 8, 3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +13, 12, 13, 14, 9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +11, 10, 11, 12, 7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, +15, 14, 15, 16, 11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, +13, 12, 13, 14, 9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +15, 14, 15, 16, 11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, +19, 18, 19, 20, 15, 14, 15, 16, 14, 13, 14, 15, 13, 12, 13, 14 +}, +{ +8, 7, 6, 7, 4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +14, 13, 12, 13, 10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +12, 11, 10, 11, 8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, +16, 15, 14, 15, 12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, +14, 13, 12, 13, 10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +16, 15, 14, 15, 12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, +20, 19, 18, 19, 16, 15, 14, 15, 15, 14, 13, 14, 14, 13, 12, 13 +}, +{ +12, 8, 7, 6, 8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +18, 14, 13, 12, 14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +16, 12, 11, 10, 12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, +20, 16, 15, 14, 16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, +18, 14, 13, 12, 14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +20, 16, 15, 14, 16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, +24, 20, 19, 18, 20, 16, 15, 14, 19, 15, 14, 13, 18, 14, 13, 12 +}, +{ +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, 6, 7, 8, 12, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, 10, 11, 12, 16, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, 12, 13, 14, 18, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, 14, 15, 16, 20 +}, +{ +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, 7, 6, 7, 8, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, 11, 10, 11, 12, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, 13, 12, 13, 14, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, 15, 14, 15, 16 +}, +{ +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, 8, 7, 6, 7, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, 12, 11, 10, 11, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, 14, 13, 12, 13, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, 16, 15, 14, 15 +}, +{ +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, 12, 8, 7, 6, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, 16, 12, 11, 10, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, 18, 14, 13, 12, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, 20, 16, 15, 14 +}, +{ +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16 +}, +{ +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12 +}, +{ +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11 +}, +{ +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10 +}, +{ +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15 +}, +{ +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11 +}, +{ +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10 +}, +{ +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9 +}, +{ +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +6, 7, 8, 12, 2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +10, 11, 12, 16, 6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +12, 13, 14, 18, 8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +14, 15, 16, 20, 10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14 +}, +{ +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +7, 6, 7, 8, 3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +11, 10, 11, 12, 7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +13, 12, 13, 14, 9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +15, 14, 15, 16, 11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10 +}, +{ +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +8, 7, 6, 7, 4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +12, 11, 10, 11, 8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +14, 13, 12, 13, 10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +16, 15, 14, 15, 12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9 +}, +{ +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +12, 8, 7, 6, 8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +16, 12, 11, 10, 12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +18, 14, 13, 12, 14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +20, 16, 15, 14, 16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8 +}, +{ +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, 6, 7, 8, 12, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, 10, 11, 12, 16, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, 14, 15, 16, 20, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, 12, 13, 14, 18, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19 +}, +{ +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, 7, 6, 7, 8, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, 11, 10, 11, 12, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, 15, 14, 15, 16, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, 13, 12, 13, 14, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15 +}, +{ +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, 8, 7, 6, 7, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, 12, 11, 10, 11, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, 16, 15, 14, 15, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, 14, 13, 12, 13, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14 +}, +{ +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, 12, 8, 7, 6, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, 16, 12, 11, 10, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, 20, 16, 15, 14, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, 18, 14, 13, 12, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13 +}, +{ +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15 +}, +{ +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11 +}, +{ +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10 +}, +{ +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9 +}, +{ +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14 +}, +{ +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10 +}, +{ +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9 +}, +{ +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8 +}, +{ +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +6, 7, 8, 12, 2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +10, 11, 12, 16, 6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +14, 15, 16, 20, 10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +12, 13, 14, 18, 8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13 +}, +{ +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +7, 6, 7, 8, 3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +11, 10, 11, 12, 7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +15, 14, 15, 16, 11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +13, 12, 13, 14, 9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9 +}, +{ +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +8, 7, 6, 7, 4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +12, 11, 10, 11, 8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +16, 15, 14, 15, 12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +14, 13, 12, 13, 10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8 +}, +{ +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +12, 8, 7, 6, 8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +16, 12, 11, 10, 12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +20, 16, 15, 14, 16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +18, 14, 13, 12, 14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7 +}, +{ +6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, 12, 13, 14, 18, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, 6, 7, 8, 12, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, 14, 15, 16, 20, +4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, 10, 11, 12, 16, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +12, 13, 14, 18, 13, 14, 15, 19, 14, 15, 16, 20, 18, 19, 20, 24, +8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, 14, 15, 16, 20, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, 12, 13, 14, 18 +}, +{ +7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, 13, 12, 13, 14, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, 7, 6, 7, 8, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, 15, 14, 15, 16, +5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, 11, 10, 11, 12, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +13, 12, 13, 14, 14, 13, 14, 15, 15, 14, 15, 16, 19, 18, 19, 20, +9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, 15, 14, 15, 16, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, 13, 12, 13, 14 +}, +{ +8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, 14, 13, 12, 13, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, 8, 7, 6, 7, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, 16, 15, 14, 15, +6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, 12, 11, 10, 11, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +14, 13, 12, 13, 15, 14, 13, 14, 16, 15, 14, 15, 20, 19, 18, 19, +10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, 16, 15, 14, 15, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, 14, 13, 12, 13 +}, +{ +12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, 18, 14, 13, 12, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, 12, 8, 7, 6, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, 20, 16, 15, 14, +10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, 16, 12, 11, 10, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +18, 14, 13, 12, 19, 15, 14, 13, 20, 16, 15, 14, 24, 20, 19, 18, +14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, 20, 16, 15, 14, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, 18, 14, 13, 12 +}, +{ +7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, +5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +13, 14, 15, 19, 12, 13, 14, 18, 13, 14, 15, 19, 14, 15, 16, 20, +9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14 +}, +{ +8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, +6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +14, 13, 14, 15, 13, 12, 13, 14, 14, 13, 14, 15, 15, 14, 15, 16, +10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10 +}, +{ +9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, +7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +15, 14, 13, 14, 14, 13, 12, 13, 15, 14, 13, 14, 16, 15, 14, 15, +11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9 +}, +{ +13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, +11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +19, 15, 14, 13, 18, 14, 13, 12, 19, 15, 14, 13, 20, 16, 15, 14, +15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8 +}, +{ +8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, +6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +14, 15, 16, 20, 13, 14, 15, 19, 12, 13, 14, 18, 13, 14, 15, 19, +10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13 +}, +{ +9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, +7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +15, 14, 15, 16, 14, 13, 14, 15, 13, 12, 13, 14, 14, 13, 14, 15, +11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9 +}, +{ +10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, +8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +16, 15, 14, 15, 15, 14, 13, 14, 14, 13, 12, 13, 15, 14, 13, 14, +12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8 +}, +{ +14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, +12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +20, 16, 15, 14, 19, 15, 14, 13, 18, 14, 13, 12, 19, 15, 14, 13, +16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7 +}, +{ +12, 13, 14, 18, 8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +6, 7, 8, 12, 2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +14, 15, 16, 20, 10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, +10, 11, 12, 16, 6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +18, 19, 20, 24, 14, 15, 16, 20, 13, 14, 15, 19, 12, 13, 14, 18, +14, 15, 16, 20, 10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +12, 13, 14, 18, 8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12 +}, +{ +13, 12, 13, 14, 9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +7, 6, 7, 8, 3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +15, 14, 15, 16, 11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, +11, 10, 11, 12, 7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +19, 18, 19, 20, 15, 14, 15, 16, 14, 13, 14, 15, 13, 12, 13, 14, +15, 14, 15, 16, 11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +13, 12, 13, 14, 9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8 +}, +{ +14, 13, 12, 13, 10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +8, 7, 6, 7, 4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +16, 15, 14, 15, 12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, +12, 11, 10, 11, 8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +20, 19, 18, 19, 16, 15, 14, 15, 15, 14, 13, 14, 14, 13, 12, 13, +16, 15, 14, 15, 12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +14, 13, 12, 13, 10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7 +}, +{ +18, 14, 13, 12, 14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +12, 8, 7, 6, 8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +20, 16, 15, 14, 16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, +16, 12, 11, 10, 12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +24, 20, 19, 18, 20, 16, 15, 14, 19, 15, 14, 13, 18, 14, 13, 12, +20, 16, 15, 14, 16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +18, 14, 13, 12, 14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6 +}, +{ +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, 6, 7, 8, 12, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, 12, 13, 14, 18, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, 10, 11, 12, 16, +8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, 14, 15, 16, 20 +}, +{ +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, 7, 6, 7, 8, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, 13, 12, 13, 14, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, 11, 10, 11, 12, +9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, 15, 14, 15, 16 +}, +{ +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, 8, 7, 6, 7, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, 14, 13, 12, 13, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, 12, 11, 10, 11, +10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, 16, 15, 14, 15 +}, +{ +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, 12, 8, 7, 6, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, 18, 14, 13, 12, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, 16, 12, 11, 10, +14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, 20, 16, 15, 14 +}, +{ +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, +9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16 +}, +{ +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, +10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12 +}, +{ +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, +11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11 +}, +{ +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, +15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10 +}, +{ +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, +10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15 +}, +{ +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, +11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11 +}, +{ +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, +12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10 +}, +{ +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, +16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9 +}, +{ +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +6, 7, 8, 12, 2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +12, 13, 14, 18, 8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +10, 11, 12, 16, 6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, +14, 15, 16, 20, 10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14 +}, +{ +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +7, 6, 7, 8, 3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +13, 12, 13, 14, 9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +11, 10, 11, 12, 7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, +15, 14, 15, 16, 11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10 +}, +{ +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +8, 7, 6, 7, 4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +14, 13, 12, 13, 10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +12, 11, 10, 11, 8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, +16, 15, 14, 15, 12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9 +}, +{ +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +12, 8, 7, 6, 8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +18, 14, 13, 12, 14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +16, 12, 11, 10, 12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, +20, 16, 15, 14, 16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8 +}, +{ +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, 6, 7, 8, 12, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, 10, 11, 12, 16 +}, +{ +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, 7, 6, 7, 8, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, 11, 10, 11, 12 +}, +{ +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, 8, 7, 6, 7, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, 12, 11, 10, 11 +}, +{ +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, 12, 8, 7, 6, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, 16, 12, 11, 10 +}, +{ +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12 +}, +{ +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8 +}, +{ +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7 +}, +{ +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6 +}, +{ +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11 +}, +{ +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7 +}, +{ +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6 +}, +{ +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5 +}, +{ +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +6, 7, 8, 12, 2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +10, 11, 12, 16, 6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10 +}, +{ +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +7, 6, 7, 8, 3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +11, 10, 11, 12, 7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6 +}, +{ +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +8, 7, 6, 7, 4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +12, 11, 10, 11, 8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5 +}, +{ +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +12, 8, 7, 6, 8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +16, 12, 11, 10, 12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4 +}, +{ +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, 6, 7, 8, 12, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, 10, 11, 12, 16, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15 +}, +{ +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, 7, 6, 7, 8, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, 11, 10, 11, 12, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11 +}, +{ +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, 8, 7, 6, 7, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, 12, 11, 10, 11, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10 +}, +{ +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, 12, 8, 7, 6, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, 16, 12, 11, 10, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9 +}, +{ +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11 +}, +{ +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7 +}, +{ +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6 +}, +{ +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5 +}, +{ +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10 +}, +{ +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6 +}, +{ +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5 +}, +{ +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4 +}, +{ +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +6, 7, 8, 12, 2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +10, 11, 12, 16, 6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9 +}, +{ +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +7, 6, 7, 8, 3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +11, 10, 11, 12, 7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5 +}, +{ +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +8, 7, 6, 7, 4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +12, 11, 10, 11, 8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4 +}, +{ +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +12, 8, 7, 6, 8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +16, 12, 11, 10, 12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3 +}, +{ +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, 12, 13, 14, 18, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, 6, 7, 8, 12, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, 14, 15, 16, 20, +4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, 10, 11, 12, 16, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14 +}, +{ +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, 13, 12, 13, 14, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, 7, 6, 7, 8, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, 15, 14, 15, 16, +5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, 11, 10, 11, 12, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10 +}, +{ +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, 14, 13, 12, 13, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, 8, 7, 6, 7, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, 16, 15, 14, 15, +6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, 12, 11, 10, 11, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9 +}, +{ +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, 18, 14, 13, 12, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, 12, 8, 7, 6, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, 20, 16, 15, 14, +10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, 16, 12, 11, 10, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8 +}, +{ +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, +5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10 +}, +{ +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, +6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6 +}, +{ +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, +7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5 +}, +{ +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, +11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4 +}, +{ +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, +6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9 +}, +{ +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, +7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5 +}, +{ +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, +8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4 +}, +{ +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, +12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3 +}, +{ +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +12, 13, 14, 18, 8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +6, 7, 8, 12, 2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +14, 15, 16, 20, 10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, +10, 11, 12, 16, 6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8 +}, +{ +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +13, 12, 13, 14, 9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +7, 6, 7, 8, 3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +15, 14, 15, 16, 11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, +11, 10, 11, 12, 7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4 +}, +{ +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +14, 13, 12, 13, 10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +8, 7, 6, 7, 4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +16, 15, 14, 15, 12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, +12, 11, 10, 11, 8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3 +}, +{ +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +18, 14, 13, 12, 14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +12, 8, 7, 6, 8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +20, 16, 15, 14, 16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, +16, 12, 11, 10, 12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2 +}, +{ +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, 10, 11, 12, 16, +8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, 14, 15, 16, 20, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, 6, 7, 8, 12, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, 12, 13, 14, 18, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19 +}, +{ +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, 11, 10, 11, 12, +9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, 15, 14, 15, 16, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, 7, 6, 7, 8, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, 13, 12, 13, 14, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15 +}, +{ +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, 12, 11, 10, 11, +10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, 16, 15, 14, 15, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, 8, 7, 6, 7, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, 14, 13, 12, 13, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14 +}, +{ +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, 16, 12, 11, 10, +14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, 20, 16, 15, 14, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, 12, 8, 7, 6, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, 18, 14, 13, 12, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13 +}, +{ +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, +9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15 +}, +{ +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, +10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11 +}, +{ +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, +11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10 +}, +{ +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, +15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9 +}, +{ +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, +10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14 +}, +{ +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, +11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10 +}, +{ +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, +12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9 +}, +{ +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, +16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8 +}, +{ +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +10, 11, 12, 16, 6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, +14, 15, 16, 20, 10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +6, 7, 8, 12, 2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +12, 13, 14, 18, 8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13 +}, +{ +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +11, 10, 11, 12, 7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, +15, 14, 15, 16, 11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +7, 6, 7, 8, 3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +13, 12, 13, 14, 9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9 +}, +{ +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +12, 11, 10, 11, 8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, +16, 15, 14, 15, 12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +8, 7, 6, 7, 4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +14, 13, 12, 13, 10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8 +}, +{ +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +16, 12, 11, 10, 12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, +20, 16, 15, 14, 16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +12, 8, 7, 6, 8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +18, 14, 13, 12, 14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7 +}, +{ +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, 10, 11, 12, 16, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, 6, 7, 8, 12, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15 +}, +{ +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, 11, 10, 11, 12, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, 7, 6, 7, 8, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11 +}, +{ +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, 12, 11, 10, 11, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, 8, 7, 6, 7, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10 +}, +{ +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, 16, 12, 11, 10, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, 12, 8, 7, 6, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9 +}, +{ +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11 +}, +{ +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7 +}, +{ +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6 +}, +{ +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5 +}, +{ +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10 +}, +{ +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6 +}, +{ +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5 +}, +{ +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4 +}, +{ +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +10, 11, 12, 16, 6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +6, 7, 8, 12, 2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9 +}, +{ +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +11, 10, 11, 12, 7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +7, 6, 7, 8, 3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5 +}, +{ +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +12, 11, 10, 11, 8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +8, 7, 6, 7, 4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4 +}, +{ +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +16, 12, 11, 10, 12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +12, 8, 7, 6, 8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3 +}, +{ +4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, 10, 11, 12, 16, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, 6, 7, 8, 12, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14 +}, +{ +5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, 11, 10, 11, 12, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, 7, 6, 7, 8, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10 +}, +{ +6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, 12, 11, 10, 11, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, 8, 7, 6, 7, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9 +}, +{ +10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, 16, 12, 11, 10, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, 12, 8, 7, 6, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8 +}, +{ +5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10 +}, +{ +6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6 +}, +{ +7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5 +}, +{ +11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4 +}, +{ +6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9 +}, +{ +7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5 +}, +{ +8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4 +}, +{ +12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3 +}, +{ +10, 11, 12, 16, 6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +6, 7, 8, 12, 2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8 +}, +{ +11, 10, 11, 12, 7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +7, 6, 7, 8, 3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4 +}, +{ +12, 11, 10, 11, 8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +8, 7, 6, 7, 4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3 +}, +{ +16, 12, 11, 10, 12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +12, 8, 7, 6, 8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2 +}, +{ +8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, 14, 15, 16, 20, +4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, 10, 11, 12, 16, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, 12, 13, 14, 18, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, 6, 7, 8, 12, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13 +}, +{ +9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, 15, 14, 15, 16, +5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, 11, 10, 11, 12, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, 13, 12, 13, 14, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, 7, 6, 7, 8, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9 +}, +{ +10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, 16, 15, 14, 15, +6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, 12, 11, 10, 11, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, 14, 13, 12, 13, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, 8, 7, 6, 7, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8 +}, +{ +14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, 20, 16, 15, 14, +10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, 16, 12, 11, 10, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, 18, 14, 13, 12, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, 12, 8, 7, 6, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7 +}, +{ +9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, +5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9 +}, +{ +10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, +6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5 +}, +{ +11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, +7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4 +}, +{ +15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, +11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3 +}, +{ +10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, +6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8 +}, +{ +11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, +7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4 +}, +{ +12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, +8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3 +}, +{ +16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, +12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2 +}, +{ +14, 15, 16, 20, 10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, +10, 11, 12, 16, 6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +12, 13, 14, 18, 8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +6, 7, 8, 12, 2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7 +}, +{ +15, 14, 15, 16, 11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, +11, 10, 11, 12, 7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +13, 12, 13, 14, 9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +7, 6, 7, 8, 3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3 +}, +{ +16, 15, 14, 15, 12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, +12, 11, 10, 11, 8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +14, 13, 12, 13, 10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +8, 7, 6, 7, 4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2 +}, +{ +20, 16, 15, 14, 16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, +16, 12, 11, 10, 12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +18, 14, 13, 12, 14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +12, 8, 7, 6, 8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1 +}, +{ +6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, 12, 13, 14, 18, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, 14, 15, 16, 20, +12, 13, 14, 18, 13, 14, 15, 19, 14, 15, 16, 20, 18, 19, 20, 24, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, 10, 11, 12, 16, +8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, 14, 15, 16, 20, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, 6, 7, 8, 12, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, 12, 13, 14, 18 +}, +{ +7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, 13, 12, 13, 14, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, 15, 14, 15, 16, +13, 12, 13, 14, 14, 13, 14, 15, 15, 14, 15, 16, 19, 18, 19, 20, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, 11, 10, 11, 12, +9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, 15, 14, 15, 16, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, 7, 6, 7, 8, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, 13, 12, 13, 14 +}, +{ +8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, 14, 13, 12, 13, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, 16, 15, 14, 15, +14, 13, 12, 13, 15, 14, 13, 14, 16, 15, 14, 15, 20, 19, 18, 19, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, 12, 11, 10, 11, +10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, 16, 15, 14, 15, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, 8, 7, 6, 7, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, 14, 13, 12, 13 +}, +{ +12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, 18, 14, 13, 12, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, 20, 16, 15, 14, +18, 14, 13, 12, 19, 15, 14, 13, 20, 16, 15, 14, 24, 20, 19, 18, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, 16, 12, 11, 10, +14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, 20, 16, 15, 14, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, 12, 8, 7, 6, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, 18, 14, 13, 12 +}, +{ +7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, +13, 14, 15, 19, 12, 13, 14, 18, 13, 14, 15, 19, 14, 15, 16, 20, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, +9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14 +}, +{ +8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, +14, 13, 14, 15, 13, 12, 13, 14, 14, 13, 14, 15, 15, 14, 15, 16, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, +10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10 +}, +{ +9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, +15, 14, 13, 14, 14, 13, 12, 13, 15, 14, 13, 14, 16, 15, 14, 15, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, +11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9 +}, +{ +13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, +19, 15, 14, 13, 18, 14, 13, 12, 19, 15, 14, 13, 20, 16, 15, 14, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, +15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8 +}, +{ +8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, +14, 15, 16, 20, 13, 14, 15, 19, 12, 13, 14, 18, 13, 14, 15, 19, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, +10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13 +}, +{ +9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, +15, 14, 15, 16, 14, 13, 14, 15, 13, 12, 13, 14, 14, 13, 14, 15, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, +11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9 +}, +{ +10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, +16, 15, 14, 15, 15, 14, 13, 14, 14, 13, 12, 13, 15, 14, 13, 14, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, +12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8 +}, +{ +14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, +20, 16, 15, 14, 19, 15, 14, 13, 18, 14, 13, 12, 19, 15, 14, 13, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, +16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7 +}, +{ +12, 13, 14, 18, 8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +14, 15, 16, 20, 10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, +18, 19, 20, 24, 14, 15, 16, 20, 13, 14, 15, 19, 12, 13, 14, 18, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +10, 11, 12, 16, 6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, +14, 15, 16, 20, 10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +6, 7, 8, 12, 2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +12, 13, 14, 18, 8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12 +}, +{ +13, 12, 13, 14, 9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +15, 14, 15, 16, 11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, +19, 18, 19, 20, 15, 14, 15, 16, 14, 13, 14, 15, 13, 12, 13, 14, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +11, 10, 11, 12, 7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, +15, 14, 15, 16, 11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +7, 6, 7, 8, 3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +13, 12, 13, 14, 9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8 +}, +{ +14, 13, 12, 13, 10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +16, 15, 14, 15, 12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, +20, 19, 18, 19, 16, 15, 14, 15, 15, 14, 13, 14, 14, 13, 12, 13, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +12, 11, 10, 11, 8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, +16, 15, 14, 15, 12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +8, 7, 6, 7, 4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +14, 13, 12, 13, 10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7 +}, +{ +18, 14, 13, 12, 14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +20, 16, 15, 14, 16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, +24, 20, 19, 18, 20, 16, 15, 14, 19, 15, 14, 13, 18, 14, 13, 12, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +16, 12, 11, 10, 12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, +20, 16, 15, 14, 16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +12, 8, 7, 6, 8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +18, 14, 13, 12, 14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6 +}, +{ +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, 12, 13, 14, 18, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, 14, 15, 16, 20, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, 10, 11, 12, 16, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, 6, 7, 8, 12, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14 +}, +{ +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, 13, 12, 13, 14, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, 15, 14, 15, 16, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, 11, 10, 11, 12, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, 7, 6, 7, 8, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10 +}, +{ +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, 14, 13, 12, 13, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, 16, 15, 14, 15, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, 12, 11, 10, 11, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, 8, 7, 6, 7, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9 +}, +{ +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, 18, 14, 13, 12, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, 20, 16, 15, 14, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, 16, 12, 11, 10, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, 12, 8, 7, 6, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8 +}, +{ +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10 +}, +{ +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6 +}, +{ +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5 +}, +{ +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4 +}, +{ +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9 +}, +{ +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5 +}, +{ +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4 +}, +{ +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3 +}, +{ +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +12, 13, 14, 18, 8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +14, 15, 16, 20, 10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +10, 11, 12, 16, 6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +6, 7, 8, 12, 2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8 +}, +{ +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +13, 12, 13, 14, 9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +15, 14, 15, 16, 11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +11, 10, 11, 12, 7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +7, 6, 7, 8, 3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4 +}, +{ +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +14, 13, 12, 13, 10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +16, 15, 14, 15, 12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +12, 11, 10, 11, 8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +8, 7, 6, 7, 4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3 +}, +{ +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +18, 14, 13, 12, 14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +20, 16, 15, 14, 16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +16, 12, 11, 10, 12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +12, 8, 7, 6, 8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2 +}, +{ +8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, 14, 15, 16, 20, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, 12, 13, 14, 18, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, 10, 11, 12, 16, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, 6, 7, 8, 12, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13 +}, +{ +9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, 15, 14, 15, 16, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, 13, 12, 13, 14, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, 11, 10, 11, 12, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, 7, 6, 7, 8, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9 +}, +{ +10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, 16, 15, 14, 15, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, 14, 13, 12, 13, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, 12, 11, 10, 11, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, 8, 7, 6, 7, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8 +}, +{ +14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, 20, 16, 15, 14, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, 18, 14, 13, 12, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, 16, 12, 11, 10, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, 12, 8, 7, 6, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7 +}, +{ +9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9 +}, +{ +10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5 +}, +{ +11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4 +}, +{ +15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3 +}, +{ +10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8 +}, +{ +11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4 +}, +{ +12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3 +}, +{ +16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2 +}, +{ +14, 15, 16, 20, 10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +12, 13, 14, 18, 8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +10, 11, 12, 16, 6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +6, 7, 8, 12, 2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7 +}, +{ +15, 14, 15, 16, 11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +13, 12, 13, 14, 9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +11, 10, 11, 12, 7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +7, 6, 7, 8, 3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3 +}, +{ +16, 15, 14, 15, 12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +14, 13, 12, 13, 10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +12, 11, 10, 11, 8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +8, 7, 6, 7, 4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2 +}, +{ +20, 16, 15, 14, 16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +18, 14, 13, 12, 14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +16, 12, 11, 10, 12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +12, 8, 7, 6, 8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1 +}, +{ +12, 13, 14, 18, 13, 14, 15, 19, 14, 15, 16, 20, 18, 19, 20, 24, +8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, 14, 15, 16, 20, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, 12, 13, 14, 18, +8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, 14, 15, 16, 20, +4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, 10, 11, 12, 16, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, 13, 14, 15, 19, +3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, 9, 10, 11, 15, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, 12, 13, 14, 18, +2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, 8, 9, 10, 14, +1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, 7, 8, 9, 13, +0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8, 6, 7, 8, 12 +}, +{ +13, 12, 13, 14, 14, 13, 14, 15, 15, 14, 15, 16, 19, 18, 19, 20, +9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, 15, 14, 15, 16, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, 13, 12, 13, 14, +9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, 15, 14, 15, 16, +5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, 11, 10, 11, 12, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, 14, 13, 14, 15, +4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, 10, 9, 10, 11, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, 13, 12, 13, 14, +3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, 9, 8, 9, 10, +2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, 8, 7, 8, 9, +1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, 7, 6, 7, 8 +}, +{ +14, 13, 12, 13, 15, 14, 13, 14, 16, 15, 14, 15, 20, 19, 18, 19, +10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, 16, 15, 14, 15, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, 14, 13, 12, 13, +10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, 16, 15, 14, 15, +6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, 12, 11, 10, 11, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, 15, 14, 13, 14, +5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, 11, 10, 9, 10, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, 14, 13, 12, 13, +4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, 10, 9, 8, 9, +3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, 9, 8, 7, 8, +2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, 8, 7, 6, 7 +}, +{ +18, 14, 13, 12, 19, 15, 14, 13, 20, 16, 15, 14, 24, 20, 19, 18, +14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, 20, 16, 15, 14, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, 18, 14, 13, 12, +14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, 20, 16, 15, 14, +10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, 16, 12, 11, 10, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, 19, 15, 14, 13, +9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, 15, 11, 10, 9, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, 18, 14, 13, 12, +8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, 14, 10, 9, 8, +7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, 13, 9, 8, 7, +6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2, 12, 8, 7, 6 +}, +{ +13, 14, 15, 19, 12, 13, 14, 18, 13, 14, 15, 19, 14, 15, 16, 20, +9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, +9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, 10, 11, 12, 16, +5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, 6, 7, 8, 12, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, 9, 10, 11, 15, +4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, 5, 6, 7, 11, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, 8, 9, 10, 14, +3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, 4, 5, 6, 10, +2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, 3, 4, 5, 9, +1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7, 2, 3, 4, 8 +}, +{ +14, 13, 14, 15, 13, 12, 13, 14, 14, 13, 14, 15, 15, 14, 15, 16, +10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, +10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, 11, 10, 11, 12, +6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, 7, 6, 7, 8, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, 10, 9, 10, 11, +5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, 6, 5, 6, 7, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, 9, 8, 9, 10, +4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 5, 4, 5, 6, +3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5, +2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4 +}, +{ +15, 14, 13, 14, 14, 13, 12, 13, 15, 14, 13, 14, 16, 15, 14, 15, +11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, +11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, 12, 11, 10, 11, +7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, 8, 7, 6, 7, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, 11, 10, 9, 10, +6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, 7, 6, 5, 6, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, 10, 9, 8, 9, +5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, 6, 5, 4, 5, +4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4, +3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3 +}, +{ +19, 15, 14, 13, 18, 14, 13, 12, 19, 15, 14, 13, 20, 16, 15, 14, +15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, +15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, 16, 12, 11, 10, +11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, 12, 8, 7, 6, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, 15, 11, 10, 9, +10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, 11, 7, 6, 5, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, 14, 10, 9, 8, +9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, 10, 6, 5, 4, +8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, 9, 5, 4, 3, +7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1, 8, 4, 3, 2 +}, +{ +14, 15, 16, 20, 13, 14, 15, 19, 12, 13, 14, 18, 13, 14, 15, 19, +10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, +10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, 9, 10, 11, 15, +6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, 5, 6, 7, 11, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, 8, 9, 10, 14, +5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, 4, 5, 6, 10, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, 7, 8, 9, 13, +4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, 3, 4, 5, 9, +3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, 2, 3, 4, 8, +2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6, 1, 2, 3, 7 +}, +{ +15, 14, 15, 16, 14, 13, 14, 15, 13, 12, 13, 14, 14, 13, 14, 15, +11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, +11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, 10, 9, 10, 11, +7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, 6, 5, 6, 7, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, 9, 8, 9, 10, +6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, 5, 4, 5, 6, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, 8, 7, 8, 9, +5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, +4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, +3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3 +}, +{ +16, 15, 14, 15, 15, 14, 13, 14, 14, 13, 12, 13, 15, 14, 13, 14, +12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, +12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, 11, 10, 9, 10, +8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, 7, 6, 5, 6, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, 10, 9, 8, 9, +7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, 6, 5, 4, 5, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, 9, 8, 7, 8, +6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 4, +5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 4, 3, 2, 3, +4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2 +}, +{ +20, 16, 15, 14, 19, 15, 14, 13, 18, 14, 13, 12, 19, 15, 14, 13, +16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, +16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, 15, 11, 10, 9, +12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, 11, 7, 6, 5, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, 14, 10, 9, 8, +11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, 10, 6, 5, 4, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, 13, 9, 8, 7, +10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, 9, 5, 4, 3, +9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, 8, 4, 3, 2, +8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0, 7, 3, 2, 1 +}, +{ +18, 19, 20, 24, 14, 15, 16, 20, 13, 14, 15, 19, 12, 13, 14, 18, +14, 15, 16, 20, 10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +12, 13, 14, 18, 8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, +14, 15, 16, 20, 10, 11, 12, 16, 9, 10, 11, 15, 8, 9, 10, 14, +10, 11, 12, 16, 6, 7, 8, 12, 5, 6, 7, 11, 4, 5, 6, 10, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +13, 14, 15, 19, 9, 10, 11, 15, 8, 9, 10, 14, 7, 8, 9, 13, +9, 10, 11, 15, 5, 6, 7, 11, 4, 5, 6, 10, 3, 4, 5, 9, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +12, 13, 14, 18, 8, 9, 10, 14, 7, 8, 9, 13, 6, 7, 8, 12, +8, 9, 10, 14, 4, 5, 6, 10, 3, 4, 5, 9, 2, 3, 4, 8, +7, 8, 9, 13, 3, 4, 5, 9, 2, 3, 4, 8, 1, 2, 3, 7, +6, 7, 8, 12, 2, 3, 4, 8, 1, 2, 3, 7, 0, 1, 2, 6 +}, +{ +19, 18, 19, 20, 15, 14, 15, 16, 14, 13, 14, 15, 13, 12, 13, 14, +15, 14, 15, 16, 11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +13, 12, 13, 14, 9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, +15, 14, 15, 16, 11, 10, 11, 12, 10, 9, 10, 11, 9, 8, 9, 10, +11, 10, 11, 12, 7, 6, 7, 8, 6, 5, 6, 7, 5, 4, 5, 6, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +14, 13, 14, 15, 10, 9, 10, 11, 9, 8, 9, 10, 8, 7, 8, 9, +10, 9, 10, 11, 6, 5, 6, 7, 5, 4, 5, 6, 4, 3, 4, 5, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +13, 12, 13, 14, 9, 8, 9, 10, 8, 7, 8, 9, 7, 6, 7, 8, +9, 8, 9, 10, 5, 4, 5, 6, 4, 3, 4, 5, 3, 2, 3, 4, +8, 7, 8, 9, 4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, +7, 6, 7, 8, 3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2 +}, +{ +20, 19, 18, 19, 16, 15, 14, 15, 15, 14, 13, 14, 14, 13, 12, 13, +16, 15, 14, 15, 12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +14, 13, 12, 13, 10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, +16, 15, 14, 15, 12, 11, 10, 11, 11, 10, 9, 10, 10, 9, 8, 9, +12, 11, 10, 11, 8, 7, 6, 7, 7, 6, 5, 6, 6, 5, 4, 5, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +15, 14, 13, 14, 11, 10, 9, 10, 10, 9, 8, 9, 9, 8, 7, 8, +11, 10, 9, 10, 7, 6, 5, 6, 6, 5, 4, 5, 5, 4, 3, 4, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +14, 13, 12, 13, 10, 9, 8, 9, 9, 8, 7, 8, 8, 7, 6, 7, +10, 9, 8, 9, 6, 5, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, +9, 8, 7, 8, 5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, +8, 7, 6, 7, 4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1 +}, +{ +24, 20, 19, 18, 20, 16, 15, 14, 19, 15, 14, 13, 18, 14, 13, 12, +20, 16, 15, 14, 16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +18, 14, 13, 12, 14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, +20, 16, 15, 14, 16, 12, 11, 10, 15, 11, 10, 9, 14, 10, 9, 8, +16, 12, 11, 10, 12, 8, 7, 6, 11, 7, 6, 5, 10, 6, 5, 4, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +19, 15, 14, 13, 15, 11, 10, 9, 14, 10, 9, 8, 13, 9, 8, 7, +15, 11, 10, 9, 11, 7, 6, 5, 10, 6, 5, 4, 9, 5, 4, 3, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +18, 14, 13, 12, 14, 10, 9, 8, 13, 9, 8, 7, 12, 8, 7, 6, +14, 10, 9, 8, 10, 6, 5, 4, 9, 5, 4, 3, 8, 4, 3, 2, +13, 9, 8, 7, 9, 5, 4, 3, 8, 4, 3, 2, 7, 3, 2, 1, +12, 8, 7, 6, 8, 4, 3, 2, 7, 3, 2, 1, 6, 2, 1, 0 +} +}; + + +////////////////////////////////////////////// +// replace the log() and real valued calculations in l_capturing +////////////////////////////////////////////// + +// #define LOG_1_5 0.4054651 +// #define LOG_1_3 0.26236426 +// #define LOG_1_1 0.095310180 +// +// unsigned char l_capturing(unsigned int len) { +// int i; +// if( len <= 656 ) { +// i = (int) floor( std::log((float) len) / LOG_1_5 ); +// } else if( len <= 3199 ) { +// i = (int) floor( std::log((float) len) / LOG_1_3 - 8.72777 ); +// } else { +// i = (int) floor( std::log((float) len) / LOG_1_1 - 62.5472 ); +// } +// +// return (unsigned char) (i & 0xFF); +// } + +////////////////////////////////////////////// +// topval is the topval of an array of values of len in l_capturing() +////////////////////////////////////////////// + +unsigned int topval[170] = { +1, +2, +3, +5, +7, +11, +17, +25, +38, +57, +86, +129, +194, +291, +437, +656, +854, +1110, +1443, +1876, +2439, +3171, +3475, +3823, +4205, +4626, +5088, +5597, +6157, +6772, +7450, +8195, +9014, +9916, +10907, +11998, +13198, +14518, +15970, +17567, +19323, +21256, +23382, +25720, +28292, +31121, +34233, +37656, +41422, +45564, +50121, +55133, +60646, +66711, +73382, +80721, +88793, +97672, +107439, +118183, +130002, +143002, +157302, +173032, +190335, +209369, +230306, +253337, +278670, +306538, +337191, +370911, +408002, +448802, +493682, +543050, +597356, +657091, +722800, +795081, +874589, +962048, +1058252, +1164078, +1280486, +1408534, +1549388, +1704327, +1874759, +2062236, +2268459, +2495305, +2744836, +3019320, +3321252, +3653374, +4018711, +4420582, +4862641, +5348905, +5883796, +6472176, +7119394, +7831333, +8614467, +9475909, +10423501, +11465851, +12612437, +13873681, +15261050, +16787154, +18465870, +20312458, +22343706, +24578077, +27035886, +29739474, +32713425, +35984770, +39583245, +43541573, +47895730, +52685306, +57953837, +63749221, +70124148, +77136564, +84850228, +93335252, +102668779, +112935659, +124229227, +136652151, +150317384, +165349128, +181884040, +200072456, +220079703, +242087671, +266296456, +292926096, +322218735, +354440623, +389884688, +428873168, +471760495, +518936559, +570830240, +627913311, +690704607, +759775136, +835752671, +919327967, +1011260767, +1112386880, +1223623232, +1345985727, +1480584256, +1628642751, +1791507135, +1970657856, +2167723648, +2384496256, +2622945920, +2885240448, +3173764736, +3491141248, +3840255616, +4224281216 +}; + +#include + +unsigned char l_capturing(unsigned int len) +{ + int bottom = 0; + int top = 170; + unsigned char idx = 85; + + while (1) { + if (idx == 0) { + return(idx); + } + if ((len <= topval[idx]) && (len > topval[idx-1])) { +// printf("len=%u idx=%u\n", len, idx); + return(idx); + } + if (len < topval[idx]) { + top = idx - 1; + } else { + bottom = idx + 1; + } + idx = (bottom + top) / 2; + } +} + +int mod_diff(unsigned int x, unsigned int y, unsigned int R) +{ + int dl = 0; + int dr = 0; + if ( y > x ){ + dl = (int)(y - x); + dr = (int)(x + R - y); + }else{ + dl = (int)(x - y); + dr = (int)(y + R - x); + } + return (dl > dr ? dr : dl); +} + +/////////////////////////////////////////////////////////////// + +#include "retdec/fileformat/utils/tlsh/tlsh.h" + +#ifdef TLSH_DISTANCE_PARAMETERS +#include // for abs() +extern int hist_diff1_add; // default value 1 +extern int hist_diff2_add; // default value 2 +extern int hist_diff3_add; // default value 6 + +static int pairbit_diff(int pairb, int opairb) +{ + int diff = abs(pairb - opairb); + if (diff == 0) { + // printf("PBD: %d\n", diff); + return(0); + } else if (diff == 1) { + // printf("PBD: diff=%d %d\n", diff, hist_diff1_add); + return(hist_diff1_add); + } else if (diff == 2) { + // printf("PBD: diff=%d %d\n", diff, hist_diff2_add); + return(hist_diff2_add); + } + // printf("PBD: diff=%d %d\n", diff, hist_diff3_add); + return(hist_diff3_add); +} + +static int byte_diff(unsigned char bv, unsigned char obv) +{ + int h1 = (unsigned char) bv / 16; + int oh1 = (unsigned char) obv / 16; + int h2 = (unsigned char) bv % 16; + int oh2 = (unsigned char) obv % 16; + int p1 = h1 / 4; + int op1 = oh1 / 4; + int p2 = h1 % 4; + int op2 = oh1 % 4; + int p3 = h2 / 4; + int op3 = oh2 / 4; + int p4 = h2 % 4; + int op4 = oh2 % 4; + int diff = 0; + diff = diff + pairbit_diff(p1, op1); + diff = diff + pairbit_diff(p2, op2); + diff = diff + pairbit_diff(p3, op3); + diff = diff + pairbit_diff(p4, op4); + return(diff); +} +/////////////////////////////////////////////////////////////// + +static int test_distance = 1; +#endif + +int h_distance( int len, const unsigned char x[], const unsigned char y[]) +{ + int diff = 0; + +#ifdef TLSH_DISTANCE_PARAMETERS + if (test_distance) { + for (int i=0; i> 4) & 0x0F; + byte |= ((in & 0x0F) << 4) & 0xF0; + return byte; +} + +void to_hex( unsigned char * psrc, int len, char* pdest ) +{ + static unsigned char HexLookup[513]= { + "000102030405060708090A0B0C0D0E0F" + "101112131415161718191A1B1C1D1E1F" + "202122232425262728292A2B2C2D2E2F" + "303132333435363738393A3B3C3D3E3F" + "404142434445464748494A4B4C4D4E4F" + "505152535455565758595A5B5C5D5E5F" + "606162636465666768696A6B6C6D6E6F" + "707172737475767778797A7B7C7D7E7F" + "808182838485868788898A8B8C8D8E8F" + "909192939495969798999A9B9C9D9E9F" + "A0A1A2A3A4A5A6A7A8A9AAABACADAEAF" + "B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF" + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF" + "D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF" + "E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF" + "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF" + }; + unsigned short* pwHex = (unsigned short*)HexLookup; + unsigned short* pwDest= (unsigned short*)pdest; + + for (int i=0; i?@ (gap) + 10,11,12,13,14,15, // ABCDEF + 0,0,0,0,0,0,0,0,0,0,0,0,0, // GHIJKLMNOPQRS (gap) + 0,0,0,0,0,0,0,0,0,0,0,0,0, // TUVWXYZ[/]^_` (gap) + 10,11,12,13,14,15 // abcdef + }; + + for (int i=0; igetImphashSha256() : ""; } +std::string ImportTable::getImphashTlsh() const +{ + return table ? table->getImpHashTlsh() : ""; +} + /** * Get import * @param position Index of selected import from table (indexed from 0) diff --git a/src/fileinfo/file_information/file_information_types/import_table.h b/src/fileinfo/file_information/file_information_types/import_table.h index 954721c23..91eec9eab 100644 --- a/src/fileinfo/file_information/file_information_types/import_table.h +++ b/src/fileinfo/file_information/file_information_types/import_table.h @@ -27,6 +27,7 @@ class ImportTable std::string getImphashCrc32() const; std::string getImphashMd5() const; std::string getImphashSha256() const; + std::string getImphashTlsh() const; const retdec::fileformat::Import* getImport(std::size_t position) const; std::string getImportName(std::size_t position) const; std::string getImportUsageType(std::size_t position) const; diff --git a/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/import_table_plain_getter.cpp b/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/import_table_plain_getter.cpp index 9899a8e33..fa503b108 100644 --- a/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/import_table_plain_getter.cpp +++ b/src/fileinfo/file_presentation/getters/iterative_getter/iterative_distribution_getter/import_table_plain_getter.cpp @@ -54,10 +54,12 @@ std::size_t ImportTablePlainGetter::getBasicInfo(std::size_t structIndex, std::v desc.push_back("CRC32 : "); desc.push_back("MD5 : "); desc.push_back("SHA256 : "); + desc.push_back("TLSH : "); info.push_back(std::to_string(fileinfo.getNumberOfStoredImports())); info.push_back(fileinfo.getImphashCrc32()); info.push_back(fileinfo.getImphashMd5()); info.push_back(fileinfo.getImphashSha256()); + info.push_back(fileinfo.getImphashTlsh()); return info.size(); } diff --git a/src/fileinfo/file_presentation/getters/iterative_getter/iterative_subtitle_getter/import_table_json_getter.cpp b/src/fileinfo/file_presentation/getters/iterative_getter/iterative_subtitle_getter/import_table_json_getter.cpp index 1a70cc45a..da235b623 100644 --- a/src/fileinfo/file_presentation/getters/iterative_getter/iterative_subtitle_getter/import_table_json_getter.cpp +++ b/src/fileinfo/file_presentation/getters/iterative_getter/iterative_subtitle_getter/import_table_json_getter.cpp @@ -50,10 +50,12 @@ std::size_t ImportTableJsonGetter::getBasicInfo(std::size_t structIndex, std::ve desc.push_back("crc32"); desc.push_back("md5"); desc.push_back("sha256"); + desc.push_back("tlsh"); info.push_back(std::to_string(fileinfo.getNumberOfStoredImports())); info.push_back(fileinfo.getImphashCrc32()); info.push_back(fileinfo.getImphashMd5()); info.push_back(fileinfo.getImphashSha256()); + info.push_back(fileinfo.getImphashTlsh()); return info.size(); } From 6505da06d3c6862c4a91d098c4c7692d9b320dbe Mon Sep 17 00:00:00 2001 From: houndthe Date: Tue, 23 Mar 2021 13:11:28 +0100 Subject: [PATCH 02/21] comment the import symbol filter regexes --- src/fileformat/types/import_table/elf_import_table.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/fileformat/types/import_table/elf_import_table.cpp b/src/fileformat/types/import_table/elf_import_table.cpp index ef749b0fd..c044acf2b 100644 --- a/src/fileformat/types/import_table/elf_import_table.cpp +++ b/src/fileformat/types/import_table/elf_import_table.cpp @@ -32,7 +32,14 @@ bool isSymbolExcluded(std::string symbol) if (symbol.empty()) { return true; } + /* ignore: + symbols starting with . or _ + x86-64 specific functions + string functions (str.* and mem.*), gcc changes them depending on architecture + symbols starting with . or _ + */ std::regex exclusion_regex("(^[_\.].*$)|(^.*64$)|(^str.*$)|(^mem.*$)"); + if (std::regex_match(symbol, exclusion_regex)) { return true; } From 2e5d12cf1091a89b777e6a1a56bd069e236136c0 Mon Sep 17 00:00:00 2001 From: houndthe Date: Tue, 23 Mar 2021 17:26:18 +0100 Subject: [PATCH 03/21] Use std::set for faster lookup --- src/fileformat/types/import_table/elf_import_table.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fileformat/types/import_table/elf_import_table.cpp b/src/fileformat/types/import_table/elf_import_table.cpp index c044acf2b..b285e3d43 100644 --- a/src/fileformat/types/import_table/elf_import_table.cpp +++ b/src/fileformat/types/import_table/elf_import_table.cpp @@ -16,7 +16,7 @@ using namespace retdec::utils; namespace retdec { namespace fileformat { -static const std::vector exclusion_strings = { +static const std::set exclusion_set = { "__libc_start_main", // main function "main", // main function "abort", // ARM default @@ -44,7 +44,7 @@ bool isSymbolExcluded(std::string symbol) return true; } - if (std::find(exclusion_strings.begin(), exclusion_strings.end(), symbol) != exclusion_strings.end()) { + if (exclusion_set.count(symbol)) { return true; } From c27d3d7dd33a2a27ef798c8bfcea7bc9b4b8f160 Mon Sep 17 00:00:00 2001 From: houndthe Date: Tue, 30 Mar 2021 14:46:12 +0200 Subject: [PATCH 04/21] Address code review comments --- .../types/import_table/elf_import_table.h | 2 +- .../types/import_table/import_table.h | 1 + .../types/import_table/elf_import_table.cpp | 64 ++++++++++--------- .../types/import_table/import_table.cpp | 4 -- 4 files changed, 35 insertions(+), 36 deletions(-) diff --git a/include/retdec/fileformat/types/import_table/elf_import_table.h b/include/retdec/fileformat/types/import_table/elf_import_table.h index b1ffddb21..ec96b70b6 100644 --- a/include/retdec/fileformat/types/import_table/elf_import_table.h +++ b/include/retdec/fileformat/types/import_table/elf_import_table.h @@ -15,4 +15,4 @@ class ElfImportTable : public ImportTable void computeHashes() override; }; } // namespace fileformat -} // namespace retdec \ No newline at end of file +} // namespace retdec diff --git a/include/retdec/fileformat/types/import_table/import_table.h b/include/retdec/fileformat/types/import_table/import_table.h index b7c3a79b8..46d5c58ab 100644 --- a/include/retdec/fileformat/types/import_table/import_table.h +++ b/include/retdec/fileformat/types/import_table/import_table.h @@ -11,6 +11,7 @@ #include #include "retdec/fileformat/types/import_table/import.h" + namespace retdec { namespace fileformat { diff --git a/src/fileformat/types/import_table/elf_import_table.cpp b/src/fileformat/types/import_table/elf_import_table.cpp index b285e3d43..050ddc286 100644 --- a/src/fileformat/types/import_table/elf_import_table.cpp +++ b/src/fileformat/types/import_table/elf_import_table.cpp @@ -9,6 +9,7 @@ #include "retdec/fileformat/utils/tlsh/tlsh.h" #include "retdec/fileformat/types/import_table/elf_import_table.h" #include +#include > #include using namespace retdec::utils; @@ -16,7 +17,9 @@ using namespace retdec::utils; namespace retdec { namespace fileformat { -static const std::set exclusion_set = { +/* exclusions are based on the original implementation + https://github.com/trendmicro/telfhash/blob/master/telfhash/telfhash.py */ +static const std::unordered_set exclusion_set = { "__libc_start_main", // main function "main", // main function "abort", // ARM default @@ -27,36 +30,25 @@ static const std::set exclusion_set = { "malloc_trim" // GNU extensions }; -bool isSymbolExcluded(std::string symbol) -{ - if (symbol.empty()) { - return true; - } - /* ignore: - symbols starting with . or _ - x86-64 specific functions - string functions (str.* and mem.*), gcc changes them depending on architecture - symbols starting with . or _ - */ - std::regex exclusion_regex("(^[_\.].*$)|(^.*64$)|(^str.*$)|(^mem.*$)"); - - if (std::regex_match(symbol, exclusion_regex)) { - return true; - } - - if (exclusion_set.count(symbol)) { - return true; - } +/* +ignore + symbols starting with . or + x86-64 specific functions + string functions (str.* and mem.*), gcc changes them depending on architecture + symbols starting with . or _ +*/ +static std::regex exclusion_regex("(^[_\.].*$)|(^.*64$)|(^str.*$)|(^mem.*$)"); - return false; +static bool isSymbolExcluded(const std::string& symbol) +{ + return symbol.empty() + || std::regex_match(symbol, exclusion_regex) + || exclusion_set.count(symbol); } -/** - * Compute import telfhash - */ void ElfImportTable::computeHashes() { - std::vector imported_symbols; + std::vector imported_symbols(imports.size()); for (const auto& import : imports) { auto funcName = toLower(import->getName()); @@ -69,6 +61,7 @@ void ElfImportTable::computeHashes() imported_symbols.push_back(funcName); } + /* sort them lexicographically */ std::sort(imported_symbols.begin(), imported_symbols.end()); std::string impHashString; @@ -81,16 +74,25 @@ void ElfImportTable::computeHashes() if (impHashString.size()) { Tlsh tlsh; - tlsh.update(reinterpret_cast(impHashString.data()), impHashString.size()); + tlsh.update( + reinterpret_cast(impHashString.data()), + impHashString.size()); + tlsh.final(); const int show_version = 1; /* this prepends the hash with 'T' + number of the version */ impHashTlsh = toLower(tlsh.getHash(show_version)); - impHashCrc32 = getCrc32(reinterpret_cast(impHashString.data()), impHashString.size()); - impHashMd5 = getMd5(reinterpret_cast(impHashString.data()), impHashString.size()); - impHashSha256 = getSha256(reinterpret_cast(impHashString.data()), impHashString.size()); + impHashCrc32 = getCrc32( + reinterpret_cast(impHashString.data()), + impHashString.size()); + impHashMd5 = getMd5( + reinterpret_cast(impHashString.data()), + impHashString.size()); + impHashSha256 = getSha256( + reinterpret_cast(impHashString.data()), + impHashString.size()); } } } // namespace fileformat -} // namespace retdec \ No newline at end of file +} // namespace retdec diff --git a/src/fileformat/types/import_table/import_table.cpp b/src/fileformat/types/import_table/import_table.cpp index c2fc06675..76dc5a15f 100644 --- a/src/fileformat/types/import_table/import_table.cpp +++ b/src/fileformat/types/import_table/import_table.cpp @@ -675,10 +675,6 @@ const std::string& ImportTable::getImphashSha256() const return impHashSha256; } -/** - * Get imphash as tlsh - * @return Imphash as tlsh - */ const std::string& ImportTable::getImpHashTlsh() const { return impHashTlsh; } From 0ec716c54b152715271e7777e85d5fa954fafaa4 Mon Sep 17 00:00:00 2001 From: houndthe Date: Tue, 30 Mar 2021 14:49:47 +0200 Subject: [PATCH 05/21] better formatting --- .../types/import_table/elf_import_table.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/fileformat/types/import_table/elf_import_table.cpp b/src/fileformat/types/import_table/elf_import_table.cpp index 050ddc286..ccd48e9b6 100644 --- a/src/fileformat/types/import_table/elf_import_table.cpp +++ b/src/fileformat/types/import_table/elf_import_table.cpp @@ -73,24 +73,18 @@ void ElfImportTable::computeHashes() } if (impHashString.size()) { + auto data = reinterpret_cast(impHashString.data()); + Tlsh tlsh; - tlsh.update( - reinterpret_cast(impHashString.data()), - impHashString.size()); + tlsh.update(data, impHashString.size()); tlsh.final(); const int show_version = 1; /* this prepends the hash with 'T' + number of the version */ impHashTlsh = toLower(tlsh.getHash(show_version)); - impHashCrc32 = getCrc32( - reinterpret_cast(impHashString.data()), - impHashString.size()); - impHashMd5 = getMd5( - reinterpret_cast(impHashString.data()), - impHashString.size()); - impHashSha256 = getSha256( - reinterpret_cast(impHashString.data()), - impHashString.size()); + impHashCrc32 = getCrc32(data, impHashString.size()); + impHashMd5 = getMd5(data, impHashString.size()); + impHashSha256 = getSha256(data, impHashString.size()); } } From 71d31cc19e9b2eb1f6ac803d8c9cbafa04ededb4 Mon Sep 17 00:00:00 2001 From: houndthe Date: Thu, 1 Apr 2021 18:55:04 +0200 Subject: [PATCH 06/21] Move TLSH to deps/ using cmake --- LICENSE-THIRD-PARTY | 274 ++++++++++++++++++ cmake/options.cmake | 3 + deps/CMakeLists.txt | 1 + deps/tlsh/CMakeLists.txt | 164 +++++++++++ deps/tlsh/retdec-tlsh-config.cmake | 3 + {src/fileformat/utils => deps}/tlsh/tlsh.cpp | 4 +- .../utils => deps}/tlsh/tlsh_impl.cpp | 26 +- .../utils => deps}/tlsh/tlsh_util.cpp | 20 +- include/retdec/fileformat/utils/tlsh/tlsh.h | 183 ------------ .../retdec/fileformat/utils/tlsh/tlsh_impl.h | 164 ----------- .../retdec/fileformat/utils/tlsh/tlsh_util.h | 70 ----- .../retdec/fileformat/utils/tlsh/version.h | 19 -- .../fileformat/utils/tlsh/win_version.h | 21 -- src/fileformat/CMakeLists.txt | 4 +- .../types/import_table/elf_import_table.cpp | 2 +- 15 files changed, 469 insertions(+), 489 deletions(-) create mode 100644 deps/tlsh/CMakeLists.txt create mode 100644 deps/tlsh/retdec-tlsh-config.cmake rename {src/fileformat/utils => deps}/tlsh/tlsh.cpp (98%) rename {src/fileformat/utils => deps}/tlsh/tlsh_impl.cpp (97%) rename {src/fileformat/utils => deps}/tlsh/tlsh_util.cpp (99%) delete mode 100644 include/retdec/fileformat/utils/tlsh/tlsh.h delete mode 100644 include/retdec/fileformat/utils/tlsh/tlsh_impl.h delete mode 100644 include/retdec/fileformat/utils/tlsh/tlsh_util.h delete mode 100644 include/retdec/fileformat/utils/tlsh/version.h delete mode 100644 include/retdec/fileformat/utils/tlsh/win_version.h diff --git a/LICENSE-THIRD-PARTY b/LICENSE-THIRD-PARTY index 3a51aa14e..63d7ee20a 100644 --- a/LICENSE-THIRD-PARTY +++ b/LICENSE-THIRD-PARTY @@ -18,6 +18,7 @@ RetDec uses the following third-party libraries or other resources: 10) yaramod: https://github.com/avast/yaramod 11) Eigen: http://eigen.tuxfamily.org/index.php?title=Main_Page 12) cmake-modules: https://github.com/rpavlik/cmake-modules +13) tlsh: https://github.com/trendmicro/tlsh These third-party libraries or other resources are licensed under the following licenses: @@ -699,3 +700,276 @@ SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +=============================================================================== +12) tlsh +=============================================================================== + ===================== + LICENSE OPTION NOTICE + ===================== + TLSH is provided for use under two licenses: Apache OR BSD. + Users may opt to use either license depending on the license + restictions of the systems with which they plan to integrate + the TLSH code. + + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + BSD License Version 3 + https://opensource.org/licenses/BSD-3-Clause + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 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. + + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + 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. + + + ========================================================================= + == NOTICE file for use with the Apache License, Version 2.0, == + == in this case for the Trend Locality Sensitive Hash distribution. == + ========================================================================= + + Trend Locality Sensitive Hash (TLSH) + Copyright 2010-2014 Trend Micro + + This product includes software developed at + Trend Micro (http://www.trendmicro.com/) + + Refer to the following publications for more information: + + Jonathan Oliver, Chun Cheng and Yanggui Chen, + "TLSH - A Locality Sensitive Hash" + 4th Cybercrime and Trustworthy Computing Workshop, Sydney, November 2013 + https://github.com/trendmicro/tlsh/blob/master/TLSH_CTC_final.pdf + + Jonathan Oliver, Scott Forman and Chun Cheng, + "Using Randomization to Attack Similarity Digests" + Applications and Techniques in Information Security. Springer Berlin Heidelberg, 2014. 199-210. + https://github.com/trendmicro/tlsh/blob/master/Attacking_LSH_and_Sim_Dig.pdf + + Jonathan Oliver and Jayson Pryde + http://blog.trendmicro.com/trendlabs-security-intelligence/smart-whitelisting-using-locality-sensitive-hashing/ diff --git a/cmake/options.cmake b/cmake/options.cmake index 1e862654f..cc0d4db34 100644 --- a/cmake/options.cmake +++ b/cmake/options.cmake @@ -516,3 +516,6 @@ set_if_at_least_one_set(RETDEC_ENABLE_SUPPORT_YARA_TOOLS set_if_at_least_one_set(RETDEC_ENABLE_SUPPORT_YARA_STATIC_CODE RETDEC_ENABLE_RETDEC) + +set_if_at_least_one_set(RETDEC_ENABLE_TLSH + RETDEC_ENABLE_FILEFORMAT) \ No newline at end of file diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 30068a4c1..e857b3e01 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -14,6 +14,7 @@ endif() set(MSVC_GE $) set(MSVC_CONFIG $<${MSVC_GE}:$/>) +cond_add_subdirectory(tlsh RETDEC_ENABLE_TLSH) cond_add_subdirectory(capstone RETDEC_ENABLE_CAPSTONE) cond_add_subdirectory(elfio RETDEC_ENABLE_ELFIO) cond_add_subdirectory(googletest RETDEC_ENABLE_GOOGLETEST) diff --git a/deps/tlsh/CMakeLists.txt b/deps/tlsh/CMakeLists.txt new file mode 100644 index 000000000..886855360 --- /dev/null +++ b/deps/tlsh/CMakeLists.txt @@ -0,0 +1,164 @@ +# TLSH is provided for use under two licenses: Apache OR BSD. +# Users may opt to use either license depending on the license +# restictions of the systems with which they plan to integrate +# the TLSH code. +# +# ============== +# Apache License +# ============== +# Copyright 2013 Trend Micro Incorporated +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# =========== +# BSD License +# =========== +# Copyright (c) 2013, Trend Micro Incorporated +# 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. + +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# 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. + +set(TLSH_VERSION_MAJOR 4) +set(TLSH_VERSION_MINOR 2) +set(TLSH_VERSION_PATCH 1) + +# TLSH uses only half the counting buckets. +# It can use all the buckets now. +set(TLSH_BUCKETS_128 1) +if(TLSH_BUCKETS_48 EQUAL 1) + set(TLSH_HASH "min hash") + add_definitions(-DBUCKETS_48) +endif() +if(TLSH_BUCKETS_128 EQUAL 1) + set(TLSH_HASH "compact hash") + add_definitions(-DBUCKETS_128) +endif() +if(TLSH_BUCKETS_256 EQUAL 1) + set(TLSH_HASH "full hash") + add_definitions(-DBUCKETS_256) +endif() + +# TLSH uses 1 byte checksum. The collision rate is 1 in 24. +# It can use 3 bytes checksum now. That collision rate in 1 in 5800. +set(TLSH_CHECKSUM_1B 1) + +if(TLSH_CHECKSUM_0B EQUAL 1) + set(TLSH_CHECKSUM "no checksum") + add_definitions(-DCHECKSUM_0B) +endif() +if(TLSH_CHECKSUM_1B EQUAL 1) + set(TLSH_CHECKSUM "1 byte checksum") +endif() +if(TLSH_CHECKSUM_3B EQUAL 1) + set(TLSH_CHECKSUM "3 bytes checksum") + add_definitions(-DCHECKSUM_3B) +endif() + +# setting TLSH_DISTANCE_PARAMETERS to 1 allows you to set command line arguments +# to set - and hence experiment with the distance parameters +# by default this is zero +set(TLSH_DISTANCE_PARAMETERS 0) + +# write a file with the VERSION information +file(REMOVE VERSION) +file(WRITE VERSION + "// This file is generated by cmake. Modify\n" + "// CMakeLists.txt to change the VERSION numbers\n" + "TLSH version: ${TLSH_VERSION_MAJOR}.${TLSH_VERSION_MINOR}.${TLSH_VERSION_PATCH} ${TLSH_HASH}, ${TLSH_CHECKSUM}\n") + +file(REMOVE include/tlsh/version.h) +file(WRITE include/tlsh/version.h + "/****************************************************\n" + " * This file is generated by cmake. Modify the top\n" + " * level CMakeLists.txt to change the VERSION numbers\n" + " ****************************************************/\n\n" + "#define VERSION_MAJOR ${TLSH_VERSION_MAJOR}\n" + "#define VERSION_MINOR ${TLSH_VERSION_MINOR}\n" + "#define VERSION_PATCH ${TLSH_VERSION_PATCH}\n" + "#define TLSH_HASH \"${TLSH_HASH}\"\n" + "#define TLSH_CHECKSUM \"${TLSH_CHECKSUM}\"\n") +if(TLSH_DISTANCE_PARAMETERS EQUAL 1) +file(APPEND include/tlsh/version.h + "#define TLSH_DISTANCE_PARAMETERS ${TLSH_DISTANCE_PARAMETERS}\n") +endif() + +set(TLSH_SRCS tlsh.cpp tlsh_impl.cpp tlsh_util.cpp) + +add_library(tlsh STATIC ${TLSH_SRCS}) +add_library(retdec::deps::tlsh ALIAS tlsh) + +target_include_directories(tlsh + SYSTEM INTERFACE + $ + $ + PRIVATE + $ +) + + +# set_target_properties(tlsh PROPERTIES OUTPUT_NAME "retdec-tlsh") + +if(MSVC) + add_definitions(-DTLSH_EXPORTS -DTLSH_LIB) +endif() + +# Install includes. +install( + DIRECTORY ${RETDEC_DEPS_DIR}/tlsh/include/ + DESTINATION ${RETDEC_INSTALL_DEPS_INCLUDE_DIR} +) + +# Install libs. +install(TARGETS tlsh + EXPORT tlsh-targets + ARCHIVE DESTINATION ${RETDEC_INSTALL_LIB_DIR} + LIBRARY DESTINATION ${RETDEC_INSTALL_LIB_DIR} +) + +# Export targets. +install(EXPORT tlsh-targets + FILE "retdec-tlsh-targets.cmake" + NAMESPACE retdec::deps:: + DESTINATION ${RETDEC_INSTALL_CMAKE_DIR} +) + +# Install CMake files. +install( + FILES + "${CMAKE_CURRENT_LIST_DIR}/retdec-tlsh-config.cmake" + DESTINATION + "${RETDEC_INSTALL_CMAKE_DIR}" +) \ No newline at end of file diff --git a/deps/tlsh/retdec-tlsh-config.cmake b/deps/tlsh/retdec-tlsh-config.cmake new file mode 100644 index 000000000..f28e9bb28 --- /dev/null +++ b/deps/tlsh/retdec-tlsh-config.cmake @@ -0,0 +1,3 @@ +if(NOT TARGET retdec::deps::tlsh) + include(${CMAKE_CURRENT_LIST_DIR}/retdec-tlsh-targets.cmake) +endif() \ No newline at end of file diff --git a/src/fileformat/utils/tlsh/tlsh.cpp b/deps/tlsh/tlsh.cpp similarity index 98% rename from src/fileformat/utils/tlsh/tlsh.cpp rename to deps/tlsh/tlsh.cpp index e39b942a0..876959bc9 100644 --- a/src/fileformat/utils/tlsh/tlsh.cpp +++ b/deps/tlsh/tlsh.cpp @@ -55,8 +55,8 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "retdec/fileformat/utils/tlsh/tlsh.h" -#include "retdec/fileformat/utils/tlsh/tlsh_impl.h" +#include "include/tlsh/tlsh.h" +#include "include/tlsh/tlsh_impl.h" #include "stdio.h" #include #include diff --git a/src/fileformat/utils/tlsh/tlsh_impl.cpp b/deps/tlsh/tlsh_impl.cpp similarity index 97% rename from src/fileformat/utils/tlsh/tlsh_impl.cpp rename to deps/tlsh/tlsh_impl.cpp index c95c3c108..4bd7b317a 100644 --- a/src/fileformat/utils/tlsh/tlsh_impl.cpp +++ b/deps/tlsh/tlsh_impl.cpp @@ -55,9 +55,9 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "retdec/fileformat/utils/tlsh/tlsh.h" -#include "retdec/fileformat/utils/tlsh/tlsh_impl.h" -#include "retdec/fileformat/utils/tlsh/tlsh_util.h" +#include "include/tlsh/tlsh.h" +#include "include/tlsh/tlsh_impl.h" +#include "include/tlsh/tlsh_util.h" #include #include @@ -183,7 +183,7 @@ void TlshImpl::update(const unsigned char* data, unsigned int len) return; } #endif - int j = (int)(this->data_len % RNG_SIZE); + int j = static_cast(this->data_len % RNG_SIZE); for( unsigned int i=0; islide_window[j] = data[i]; @@ -302,7 +302,7 @@ void TlshImpl::update(const unsigned char* data, unsigned int len) void TlshImpl::fast_update(const unsigned char* data, unsigned int len) { unsigned int fed_len = this->data_len; - int j = (int)(this->data_len % RNG_SIZE); + int j = static_cast(this->data_len % RNG_SIZE); unsigned char checksum = this->lsh_bin.checksum[0]; for( unsigned int i=0; ia_bucket); - // issue #79 - divide by 0 if q3 == 0 - if (q3 == 0) { - delete [] this->a_bucket; this->a_bucket = NULL; - return; - } - // buckets must be more than 50% non-zero int nonzero = 0; for(unsigned int i=0; ia_bucket; this->a_bucket = NULL; this->lsh_bin.Lvalue = l_capturing(this->data_len); - this->lsh_bin.Q.QR.Q1ratio = (unsigned int) ((float)(q1*100)/(float) q3) % 16; - this->lsh_bin.Q.QR.Q2ratio = (unsigned int) ((float)(q2*100)/(float) q3) % 16; + this->lsh_bin.Q.QR.Q1ratio = static_cast (static_cast(q1*100)/static_cast (q3)) % 16; + this->lsh_bin.Q.QR.Q2ratio = static_cast (static_cast(q2*100)/static_cast (q3)) % 16; this->lsh_code_valid = true; } @@ -499,7 +493,7 @@ int TlshImpl::fromTlshStr(const char* str) this->reset(); lsh_bin_struct tmp; - from_hex( &str[start], INTERNAL_TLSH_STRING_LEN, (unsigned char*)&tmp ); + from_hex( &str[start], INTERNAL_TLSH_STRING_LEN, reinterpret_cast(&tmp) ); // Reconstruct checksum, Qrations & lvalue for (int k = 0; k < TLSH_CHECKSUM_LEN; k++) { @@ -539,9 +533,9 @@ const char* TlshImpl::hash(char *buffer, unsigned int bufSize, int showvers) con if (showvers) { buffer[0] = 'T'; buffer[1] = '0' + showvers; - to_hex( (unsigned char*)&tmp, sizeof(tmp), &buffer[2]); + to_hex( reinterpret_cast(&tmp), sizeof(tmp), &buffer[2]); } else { - to_hex( (unsigned char*)&tmp, sizeof(tmp), buffer); + to_hex( reinterpret_cast(&tmp), sizeof(tmp), buffer); } return buffer; } diff --git a/src/fileformat/utils/tlsh/tlsh_util.cpp b/deps/tlsh/tlsh_util.cpp similarity index 99% rename from src/fileformat/utils/tlsh/tlsh_util.cpp rename to deps/tlsh/tlsh_util.cpp index a5435a84d..e3e45bc9c 100644 --- a/src/fileformat/utils/tlsh/tlsh_util.cpp +++ b/deps/tlsh/tlsh_util.cpp @@ -4902,18 +4902,18 @@ int mod_diff(unsigned int x, unsigned int y, unsigned int R) int dl = 0; int dr = 0; if ( y > x ){ - dl = (int)(y - x); - dr = (int)(x + R - y); + dl = static_cast(y - x); + dr = static_cast(x + R - y); }else{ - dl = (int)(x - y); - dr = (int)(y + R - x); + dl = static_cast(x - y); + dr = static_cast(y + R - x); } return (dl > dr ? dr : dl); } /////////////////////////////////////////////////////////////// -#include "retdec/fileformat/utils/tlsh/tlsh.h" +#include "include/tlsh/tlsh.h" #ifdef TLSH_DISTANCE_PARAMETERS #include // for abs() @@ -5018,14 +5018,14 @@ void to_hex( unsigned char * psrc, int len, char* pdest ) "E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF" "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF" }; - unsigned short* pwHex = (unsigned short*)HexLookup; - unsigned short* pwDest= (unsigned short*)pdest; + unsigned short* pwHex = reinterpret_cast(HexLookup); + unsigned short* pwDest= reinterpret_cast(pdest); for (int i=0; i(pwDest))= 0; // terminate the string } void from_hex( const char* psrc, int len, unsigned char* pdest ) @@ -5043,8 +5043,8 @@ void from_hex( const char* psrc, int len, unsigned char* pdest ) }; for (int i=0; i(const_cast(psrc + i))] << 4; + d |= DecLookup[*reinterpret_cast(const_cast(psrc + i + 1))]; *pdest++ = d; } } diff --git a/include/retdec/fileformat/utils/tlsh/tlsh.h b/include/retdec/fileformat/utils/tlsh/tlsh.h deleted file mode 100644 index c373cc336..000000000 --- a/include/retdec/fileformat/utils/tlsh/tlsh.h +++ /dev/null @@ -1,183 +0,0 @@ -// tlsh.h - TrendLSH Hash Algorithm - -/* - * TLSH is provided for use under two licenses: Apache OR BSD. - * Users may opt to use either license depending on the license - * restictions of the systems with which they plan to integrate - * the TLSH code. - */ - -/* ============== - * Apache License - * ============== - * Copyright 2013 Trend Micro Incorporated - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* =========== - * BSD License - * =========== - * Copyright (c) 2013, Trend Micro Incorporated - * 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. - - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * 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. - */ - -#ifndef HEADER_TLSH_H -#define HEADER_TLSH_H - -#if defined WINDOWS || defined MINGW -#include "win_version.h" -#else -#include "version.h" -#endif - -#ifndef NULL -#define NULL 0 -#endif - -#ifdef __cplusplus - -class TlshImpl; - -// Define TLSH_STRING_LEN_REQ, which is the string length of "T1" + the hex value of the Tlsh hash. -// BUCKETS_256 & CHECKSUM_3B are compiler switches defined in CMakeLists.txt -#if defined BUCKETS_256 - #define TLSH_STRING_LEN_REQ 136 - // changed the minimum data length to 256 for version 3.3 - #define MIN_DATA_LENGTH 50 - // added the -force option for version 3.5 - // added the -conservatibe option for version 3.17 - #define MIN_CONSERVATIVE_DATA_LENGTH 256 -#endif - -#if defined BUCKETS_128 - #define TLSH_STRING_LEN_REQ 72 - // changed the minimum data length to 256 for version 3.3 - #define MIN_DATA_LENGTH 50 - // added the -force option for version 3.5 - // added the -conservatibe option for version 3.17 - #define MIN_CONSERVATIVE_DATA_LENGTH 256 -#endif - -#if defined BUCKETS_48 - // No 3 Byte checksum option for 48 Bucket min hash - #define TLSH_STRING_LEN 30 - // changed the minimum data length to 256 for version 3.3 - #define MIN_DATA_LENGTH 10 - // added the -force option for version 3.5 - #define MIN_CONSERVATIVE_DATA_LENGTH 10 -#endif - -#define TLSH_STRING_BUFFER_LEN (TLSH_STRING_LEN_REQ+1) - -#ifdef WINDOWS -#include -#else - #if defined(__SPARC) || defined(_AS_MK_OS_RH73) - #define TLSH_API - #else - #define TLSH_API __attribute__ ((visibility("default"))) - #endif -#endif - -class TLSH_API Tlsh{ - -public: - Tlsh(); - Tlsh(const Tlsh& other); - - /* allow the user to add data in multiple iterations */ - void update(const unsigned char* data, unsigned int len); - - /* to signal the class there is no more data to be added */ - void final(const unsigned char* data = NULL, unsigned int len = 0, int fc_cons_option = 0); - - /* to get the hex-encoded hash code */ - const char* getHash(int showvers=0) const ; - - /* to get the hex-encoded hash code without allocating buffer in TlshImpl - bufSize should be TLSH_STRING_BUFFER_LEN */ - const char* getHash(char *buffer, unsigned int bufSize, int showvers=0) const; - - /* to bring to object back to the initial state */ - void reset(); - - // access functions - int Lvalue(); - int Q1ratio(); - int Q2ratio(); - int Checksum(int k); - int BucketValue(int bucket); - - /* calculate difference */ - /* The len_diff parameter specifies if the file length is to be included in the difference calculation (len_diff=true) or if it */ - /* is to be excluded (len_diff=false). In general, the length should be considered in the difference calculation, but there */ - /* could be applications where a part of the adversarial activity might be to add a lot of content. For example to add 1 million */ - /* zero bytes at the end of a file. In that case, the caller would want to exclude the length from the calculation. */ - int totalDiff(const Tlsh *, bool len_diff=true) const; - - /* validate TrendLSH string and reset the hash according to it */ - int fromTlshStr(const char* str); - - /* check if Tlsh object is valid to operate */ - bool isValid() const; - - /* display the contents of NOTICE.txt */ - static void display_notice(); - - /* Return the version information used to build this library */ - static const char *version(); - - // operators - Tlsh& operator=(const Tlsh& other); - bool operator==(const Tlsh& other) const; - bool operator!=(const Tlsh& other) const; - - ~Tlsh(); - -private: - TlshImpl* impl; -}; - -#ifdef TLSH_DISTANCE_PARAMETERS -void set_tlsh_distance_parameters(int length_mult_value, int qratio_mult_value, int hist_diff1_add_value, int hist_diff2_add_value, int hist_diff3_add_value); -#endif - -#endif - -#endif - diff --git a/include/retdec/fileformat/utils/tlsh/tlsh_impl.h b/include/retdec/fileformat/utils/tlsh/tlsh_impl.h deleted file mode 100644 index c5a006872..000000000 --- a/include/retdec/fileformat/utils/tlsh/tlsh_impl.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * TLSH is provided for use under two licenses: Apache OR BSD. - * Users may opt to use either license depending on the license - * restictions of the systems with which they plan to integrate - * the TLSH code. - */ - -/* ============== - * Apache License - * ============== - * Copyright 2013 Trend Micro Incorporated - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* =========== - * BSD License - * =========== - * Copyright (c) 2013, Trend Micro Incorporated - * 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. - - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * 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. - */ - -#if defined WINDOWS || defined MINGW -#include "win_version.h" -#else -#include "version.h" -#endif - -#ifndef HEADER_TLSH_IMPL_H -#define HEADER_TLSH_IMPL_H - -#define SLIDING_WND_SIZE 5 - -#define BUCKETS 256 -#define Q_BITS 2 // 2 bits; quartile value 0, 1, 2, 3 - -// BUCKETS_256 & CHECKSUM_3B are compiler switches defined in CMakeLists.txt - -#if defined BUCKETS_256 - #define EFF_BUCKETS 256 - #define CODE_SIZE 64 // 256 * 2 bits = 64 bytes - #if defined CHECKSUM_3B - #define INTERNAL_TLSH_STRING_LEN 138 - #define TLSH_CHECKSUM_LEN 3 - // defined in tlsh.h #define TLSH_STRING_LEN 138 // 2 + 3 + 64 bytes = 138 hexidecimal chars - #else - #define INTERNAL_TLSH_STRING_LEN 134 - #define TLSH_CHECKSUM_LEN 1 - // defined in tlsh.h #define TLSH_STRING_LEN 134 // 2 + 1 + 64 bytes = 134 hexidecimal chars - #endif -#endif - -#if defined BUCKETS_128 - #define EFF_BUCKETS 128 - #define CODE_SIZE 32 // 128 * 2 bits = 32 bytes - #if defined CHECKSUM_3B - #define INTERNAL_TLSH_STRING_LEN 74 - #define TLSH_CHECKSUM_LEN 3 - // defined in tlsh.h #define TLSH_STRING_LEN 74 // 2 + 3 + 32 bytes = 74 hexidecimal chars - #else - #define INTERNAL_TLSH_STRING_LEN 70 - #define TLSH_CHECKSUM_LEN 1 - // defined in tlsh.h #define TLSH_STRING_LEN 70 // 2 + 1 + 32 bytes = 70 hexidecimal chars - #endif -#endif - -#if defined BUCKETS_48 - #define INTERNAL_TLSH_STRING_LEN 33 - #define EFF_BUCKETS 48 - #define CODE_SIZE 12 // 48 * 2 bits = 12 bytes - #define TLSH_CHECKSUM_LEN 1 - // defined in tlsh.h #define TLSH_STRING_LEN 30 // 2 + 1 + 12 bytes = 30 hexidecimal chars -#endif - -class TlshImpl -{ -public: - TlshImpl(); - ~TlshImpl(); -public: - void update(const unsigned char* data, unsigned int len); - void fast_update(const unsigned char* data, unsigned int len); - void final(int fc_cons_option = 0); - void reset(); - const char* hash(int showvers) const; - const char* hash(char *buffer, unsigned int bufSize, int showvers) const; // saves allocating hash string in TLSH instance - bufSize should be TLSH_STRING_LEN + 1 - int compare(const TlshImpl& other) const; - int totalDiff(const TlshImpl& other, bool len_diff=true) const; - int Lvalue(); - int Q1ratio(); - int Q2ratio(); - int Checksum(int k); - int BucketValue(int bucket); - int fromTlshStr(const char* str); - bool isValid() const { return lsh_code_valid; } - -private: - unsigned int *a_bucket; - unsigned char slide_window[SLIDING_WND_SIZE]; - unsigned int data_len; - - struct lsh_bin_struct { - unsigned char checksum[TLSH_CHECKSUM_LEN]; // 1 to 3 bytes - unsigned char Lvalue; // 1 byte - union { -#if defined(__SPARC) || defined(_AIX) - #pragma pack(1) -#endif - unsigned char QB; - struct{ -#if defined(__SPARC) || defined(_AIX) - unsigned char Q2ratio : 4; - unsigned char Q1ratio : 4; -#else - unsigned char Q1ratio : 4; - unsigned char Q2ratio : 4; -#endif - } QR; - } Q; // 1 bytes - unsigned char tmp_code[CODE_SIZE]; // 32/64 bytes - } lsh_bin; - - mutable char *lsh_code; // allocated when hash() function without buffer is called - 70/134 bytes or 74/138 bytes - bool lsh_code_valid; // true iff final() or fromTlshStr complete successfully -}; - - -#endif - diff --git a/include/retdec/fileformat/utils/tlsh/tlsh_util.h b/include/retdec/fileformat/utils/tlsh/tlsh_util.h deleted file mode 100644 index fa66e9dd2..000000000 --- a/include/retdec/fileformat/utils/tlsh/tlsh_util.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * TLSH is provided for use under two licenses: Apache OR BSD. - * Users may opt to use either license depending on the license - * restictions of the systems with which they plan to integrate - * the TLSH code. - */ - -/* ============== - * Apache License - * ============== - * Copyright 2013 Trend Micro Incorporated - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* =========== - * BSD License - * =========== - * Copyright (c) 2013, Trend Micro Incorporated - * 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. - - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * 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. - */ - -#ifndef HEADER_TLSH_UTIL_H -#define HEADER_TLSH_UTIL_H - -unsigned char b_mapping(unsigned char salt, unsigned char i, unsigned char j, unsigned char k); -unsigned char l_capturing(unsigned int len); -int mod_diff(unsigned int x, unsigned int y, unsigned int R); -int h_distance( int len, const unsigned char x[], const unsigned char y[]); -void to_hex( unsigned char * psrc, int len, char* pdest); -void from_hex( const char* psrc, int len, unsigned char* pdest); -unsigned char swap_byte( const unsigned char in ); - -#endif - diff --git a/include/retdec/fileformat/utils/tlsh/version.h b/include/retdec/fileformat/utils/tlsh/version.h deleted file mode 100644 index e4689eba8..000000000 --- a/include/retdec/fileformat/utils/tlsh/version.h +++ /dev/null @@ -1,19 +0,0 @@ -/**************************************************** - * This file is generated by cmake. Modify the top - * level CMakeLists.txt to change the VERSION numbers - ****************************************************/ - -#define VERSION_MAJOR 4 -#define VERSION_MINOR 5 -#define VERSION_PATCH 0 -#define TLSH_HASH "compact hash" -#define TLSH_CHECKSUM "1 byte checksum" - -#define buckets 128 -#define TLSH_CHECKSUM_LEN 1 -#define EFF_BUCKETS 128 -#define CODE_SIZE 32 -#define MIN_DATA_LENGTH 50 -#define MIN_CONSERVATIVE_DATA_LENGTH 256 -#define TLSH_STRING_LEN_REQ 72 -#define INTERNAL_TLSH_STRING_LEN 70 diff --git a/include/retdec/fileformat/utils/tlsh/win_version.h b/include/retdec/fileformat/utils/tlsh/win_version.h deleted file mode 100644 index 6c2e40483..000000000 --- a/include/retdec/fileformat/utils/tlsh/win_version.h +++ /dev/null @@ -1,21 +0,0 @@ -/**************************************************** - * The file "version.h" is generated by cmake. - * But there was trouble creating this file on Windows - * so this is the default calues required - * Beware - do not change these values unless you really understand the software. - ****************************************************/ - -#define VERSION_MAJOR 4 -#define VERSION_MINOR 5 -#define VERSION_PATCH 0 -#define TLSH_HASH "compact hash" -#define TLSH_CHECKSUM "1 byte checksum" - -#define buckets 128 -#define TLSH_CHECKSUM_LEN 1 -#define EFF_BUCKETS 128 -#define CODE_SIZE 32 -#define MIN_DATA_LENGTH 50 -#define MIN_CONSERVATIVE_DATA_LENGTH 256 -#define TLSH_STRING_LEN_REQ 72 -#define INTERNAL_TLSH_STRING_LEN 70 diff --git a/src/fileformat/CMakeLists.txt b/src/fileformat/CMakeLists.txt index 1e7ef4134..768a5a029 100644 --- a/src/fileformat/CMakeLists.txt +++ b/src/fileformat/CMakeLists.txt @@ -13,9 +13,6 @@ add_library(fileformat STATIC utils/other.cpp utils/asn1.cpp utils/file_io.cpp - utils/tlsh/tlsh_impl.cpp - utils/tlsh/tlsh_util.cpp - utils/tlsh/tlsh.cpp format_factory.cpp types/dotnet_headers/blob_stream.cpp types/dotnet_headers/user_string_stream.cpp @@ -99,6 +96,7 @@ target_link_libraries(fileformat retdec::utils retdec::pelib retdec::deps::elfio + retdec::deps::tlsh retdec::deps::llvm PRIVATE OpenSSL::Crypto diff --git a/src/fileformat/types/import_table/elf_import_table.cpp b/src/fileformat/types/import_table/elf_import_table.cpp index ccd48e9b6..afb60b640 100644 --- a/src/fileformat/types/import_table/elf_import_table.cpp +++ b/src/fileformat/types/import_table/elf_import_table.cpp @@ -6,8 +6,8 @@ #include "retdec/fileformat/utils/crypto.h" #include "retdec/utils/string.h" -#include "retdec/fileformat/utils/tlsh/tlsh.h" #include "retdec/fileformat/types/import_table/elf_import_table.h" +#include #include #include > #include From 6611b0f3efd1311b8fbcf8174223583778ed5309 Mon Sep 17 00:00:00 2001 From: houndthe Date: Thu, 1 Apr 2021 21:31:38 +0200 Subject: [PATCH 07/21] Forgot to commit tlsh headers --- deps/tlsh/include/tlsh/tlsh.h | 183 +++++++++++++++++++++++++++ deps/tlsh/include/tlsh/tlsh_impl.h | 164 ++++++++++++++++++++++++ deps/tlsh/include/tlsh/tlsh_util.h | 70 ++++++++++ deps/tlsh/include/tlsh/win_version.h | 21 +++ 4 files changed, 438 insertions(+) create mode 100644 deps/tlsh/include/tlsh/tlsh.h create mode 100644 deps/tlsh/include/tlsh/tlsh_impl.h create mode 100644 deps/tlsh/include/tlsh/tlsh_util.h create mode 100644 deps/tlsh/include/tlsh/win_version.h diff --git a/deps/tlsh/include/tlsh/tlsh.h b/deps/tlsh/include/tlsh/tlsh.h new file mode 100644 index 000000000..c373cc336 --- /dev/null +++ b/deps/tlsh/include/tlsh/tlsh.h @@ -0,0 +1,183 @@ +// tlsh.h - TrendLSH Hash Algorithm + +/* + * TLSH is provided for use under two licenses: Apache OR BSD. + * Users may opt to use either license depending on the license + * restictions of the systems with which they plan to integrate + * the TLSH code. + */ + +/* ============== + * Apache License + * ============== + * Copyright 2013 Trend Micro Incorporated + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* =========== + * BSD License + * =========== + * Copyright (c) 2013, Trend Micro Incorporated + * 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. + + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + */ + +#ifndef HEADER_TLSH_H +#define HEADER_TLSH_H + +#if defined WINDOWS || defined MINGW +#include "win_version.h" +#else +#include "version.h" +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#ifdef __cplusplus + +class TlshImpl; + +// Define TLSH_STRING_LEN_REQ, which is the string length of "T1" + the hex value of the Tlsh hash. +// BUCKETS_256 & CHECKSUM_3B are compiler switches defined in CMakeLists.txt +#if defined BUCKETS_256 + #define TLSH_STRING_LEN_REQ 136 + // changed the minimum data length to 256 for version 3.3 + #define MIN_DATA_LENGTH 50 + // added the -force option for version 3.5 + // added the -conservatibe option for version 3.17 + #define MIN_CONSERVATIVE_DATA_LENGTH 256 +#endif + +#if defined BUCKETS_128 + #define TLSH_STRING_LEN_REQ 72 + // changed the minimum data length to 256 for version 3.3 + #define MIN_DATA_LENGTH 50 + // added the -force option for version 3.5 + // added the -conservatibe option for version 3.17 + #define MIN_CONSERVATIVE_DATA_LENGTH 256 +#endif + +#if defined BUCKETS_48 + // No 3 Byte checksum option for 48 Bucket min hash + #define TLSH_STRING_LEN 30 + // changed the minimum data length to 256 for version 3.3 + #define MIN_DATA_LENGTH 10 + // added the -force option for version 3.5 + #define MIN_CONSERVATIVE_DATA_LENGTH 10 +#endif + +#define TLSH_STRING_BUFFER_LEN (TLSH_STRING_LEN_REQ+1) + +#ifdef WINDOWS +#include +#else + #if defined(__SPARC) || defined(_AS_MK_OS_RH73) + #define TLSH_API + #else + #define TLSH_API __attribute__ ((visibility("default"))) + #endif +#endif + +class TLSH_API Tlsh{ + +public: + Tlsh(); + Tlsh(const Tlsh& other); + + /* allow the user to add data in multiple iterations */ + void update(const unsigned char* data, unsigned int len); + + /* to signal the class there is no more data to be added */ + void final(const unsigned char* data = NULL, unsigned int len = 0, int fc_cons_option = 0); + + /* to get the hex-encoded hash code */ + const char* getHash(int showvers=0) const ; + + /* to get the hex-encoded hash code without allocating buffer in TlshImpl - bufSize should be TLSH_STRING_BUFFER_LEN */ + const char* getHash(char *buffer, unsigned int bufSize, int showvers=0) const; + + /* to bring to object back to the initial state */ + void reset(); + + // access functions + int Lvalue(); + int Q1ratio(); + int Q2ratio(); + int Checksum(int k); + int BucketValue(int bucket); + + /* calculate difference */ + /* The len_diff parameter specifies if the file length is to be included in the difference calculation (len_diff=true) or if it */ + /* is to be excluded (len_diff=false). In general, the length should be considered in the difference calculation, but there */ + /* could be applications where a part of the adversarial activity might be to add a lot of content. For example to add 1 million */ + /* zero bytes at the end of a file. In that case, the caller would want to exclude the length from the calculation. */ + int totalDiff(const Tlsh *, bool len_diff=true) const; + + /* validate TrendLSH string and reset the hash according to it */ + int fromTlshStr(const char* str); + + /* check if Tlsh object is valid to operate */ + bool isValid() const; + + /* display the contents of NOTICE.txt */ + static void display_notice(); + + /* Return the version information used to build this library */ + static const char *version(); + + // operators + Tlsh& operator=(const Tlsh& other); + bool operator==(const Tlsh& other) const; + bool operator!=(const Tlsh& other) const; + + ~Tlsh(); + +private: + TlshImpl* impl; +}; + +#ifdef TLSH_DISTANCE_PARAMETERS +void set_tlsh_distance_parameters(int length_mult_value, int qratio_mult_value, int hist_diff1_add_value, int hist_diff2_add_value, int hist_diff3_add_value); +#endif + +#endif + +#endif + diff --git a/deps/tlsh/include/tlsh/tlsh_impl.h b/deps/tlsh/include/tlsh/tlsh_impl.h new file mode 100644 index 000000000..c5a006872 --- /dev/null +++ b/deps/tlsh/include/tlsh/tlsh_impl.h @@ -0,0 +1,164 @@ +/* + * TLSH is provided for use under two licenses: Apache OR BSD. + * Users may opt to use either license depending on the license + * restictions of the systems with which they plan to integrate + * the TLSH code. + */ + +/* ============== + * Apache License + * ============== + * Copyright 2013 Trend Micro Incorporated + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* =========== + * BSD License + * =========== + * Copyright (c) 2013, Trend Micro Incorporated + * 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. + + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + */ + +#if defined WINDOWS || defined MINGW +#include "win_version.h" +#else +#include "version.h" +#endif + +#ifndef HEADER_TLSH_IMPL_H +#define HEADER_TLSH_IMPL_H + +#define SLIDING_WND_SIZE 5 + +#define BUCKETS 256 +#define Q_BITS 2 // 2 bits; quartile value 0, 1, 2, 3 + +// BUCKETS_256 & CHECKSUM_3B are compiler switches defined in CMakeLists.txt + +#if defined BUCKETS_256 + #define EFF_BUCKETS 256 + #define CODE_SIZE 64 // 256 * 2 bits = 64 bytes + #if defined CHECKSUM_3B + #define INTERNAL_TLSH_STRING_LEN 138 + #define TLSH_CHECKSUM_LEN 3 + // defined in tlsh.h #define TLSH_STRING_LEN 138 // 2 + 3 + 64 bytes = 138 hexidecimal chars + #else + #define INTERNAL_TLSH_STRING_LEN 134 + #define TLSH_CHECKSUM_LEN 1 + // defined in tlsh.h #define TLSH_STRING_LEN 134 // 2 + 1 + 64 bytes = 134 hexidecimal chars + #endif +#endif + +#if defined BUCKETS_128 + #define EFF_BUCKETS 128 + #define CODE_SIZE 32 // 128 * 2 bits = 32 bytes + #if defined CHECKSUM_3B + #define INTERNAL_TLSH_STRING_LEN 74 + #define TLSH_CHECKSUM_LEN 3 + // defined in tlsh.h #define TLSH_STRING_LEN 74 // 2 + 3 + 32 bytes = 74 hexidecimal chars + #else + #define INTERNAL_TLSH_STRING_LEN 70 + #define TLSH_CHECKSUM_LEN 1 + // defined in tlsh.h #define TLSH_STRING_LEN 70 // 2 + 1 + 32 bytes = 70 hexidecimal chars + #endif +#endif + +#if defined BUCKETS_48 + #define INTERNAL_TLSH_STRING_LEN 33 + #define EFF_BUCKETS 48 + #define CODE_SIZE 12 // 48 * 2 bits = 12 bytes + #define TLSH_CHECKSUM_LEN 1 + // defined in tlsh.h #define TLSH_STRING_LEN 30 // 2 + 1 + 12 bytes = 30 hexidecimal chars +#endif + +class TlshImpl +{ +public: + TlshImpl(); + ~TlshImpl(); +public: + void update(const unsigned char* data, unsigned int len); + void fast_update(const unsigned char* data, unsigned int len); + void final(int fc_cons_option = 0); + void reset(); + const char* hash(int showvers) const; + const char* hash(char *buffer, unsigned int bufSize, int showvers) const; // saves allocating hash string in TLSH instance - bufSize should be TLSH_STRING_LEN + 1 + int compare(const TlshImpl& other) const; + int totalDiff(const TlshImpl& other, bool len_diff=true) const; + int Lvalue(); + int Q1ratio(); + int Q2ratio(); + int Checksum(int k); + int BucketValue(int bucket); + int fromTlshStr(const char* str); + bool isValid() const { return lsh_code_valid; } + +private: + unsigned int *a_bucket; + unsigned char slide_window[SLIDING_WND_SIZE]; + unsigned int data_len; + + struct lsh_bin_struct { + unsigned char checksum[TLSH_CHECKSUM_LEN]; // 1 to 3 bytes + unsigned char Lvalue; // 1 byte + union { +#if defined(__SPARC) || defined(_AIX) + #pragma pack(1) +#endif + unsigned char QB; + struct{ +#if defined(__SPARC) || defined(_AIX) + unsigned char Q2ratio : 4; + unsigned char Q1ratio : 4; +#else + unsigned char Q1ratio : 4; + unsigned char Q2ratio : 4; +#endif + } QR; + } Q; // 1 bytes + unsigned char tmp_code[CODE_SIZE]; // 32/64 bytes + } lsh_bin; + + mutable char *lsh_code; // allocated when hash() function without buffer is called - 70/134 bytes or 74/138 bytes + bool lsh_code_valid; // true iff final() or fromTlshStr complete successfully +}; + + +#endif + diff --git a/deps/tlsh/include/tlsh/tlsh_util.h b/deps/tlsh/include/tlsh/tlsh_util.h new file mode 100644 index 000000000..fa66e9dd2 --- /dev/null +++ b/deps/tlsh/include/tlsh/tlsh_util.h @@ -0,0 +1,70 @@ +/* + * TLSH is provided for use under two licenses: Apache OR BSD. + * Users may opt to use either license depending on the license + * restictions of the systems with which they plan to integrate + * the TLSH code. + */ + +/* ============== + * Apache License + * ============== + * Copyright 2013 Trend Micro Incorporated + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* =========== + * BSD License + * =========== + * Copyright (c) 2013, Trend Micro Incorporated + * 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. + + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + */ + +#ifndef HEADER_TLSH_UTIL_H +#define HEADER_TLSH_UTIL_H + +unsigned char b_mapping(unsigned char salt, unsigned char i, unsigned char j, unsigned char k); +unsigned char l_capturing(unsigned int len); +int mod_diff(unsigned int x, unsigned int y, unsigned int R); +int h_distance( int len, const unsigned char x[], const unsigned char y[]); +void to_hex( unsigned char * psrc, int len, char* pdest); +void from_hex( const char* psrc, int len, unsigned char* pdest); +unsigned char swap_byte( const unsigned char in ); + +#endif + diff --git a/deps/tlsh/include/tlsh/win_version.h b/deps/tlsh/include/tlsh/win_version.h new file mode 100644 index 000000000..b939e4684 --- /dev/null +++ b/deps/tlsh/include/tlsh/win_version.h @@ -0,0 +1,21 @@ +/**************************************************** + * The file "version.h" is generated by cmake. + * But there was trouble creating this file on Windows + * so this is the default calues required + * Beware - do not change these values unless you really understand the software. + ****************************************************/ + +#define VERSION_MAJOR 4 +#define VERSION_MINOR 2 +#define VERSION_PATCH 1 +#define TLSH_HASH "compact hash" +#define TLSH_CHECKSUM "1 byte checksum" + +#define buckets 128 +#define TLSH_CHECKSUM_LEN 1 +#define EFF_BUCKETS 128 +#define CODE_SIZE 32 +#define MIN_DATA_LENGTH 50 +#define MIN_CONSERVATIVE_DATA_LENGTH 256 +#define TLSH_STRING_LEN_REQ 72 +#define INTERNAL_TLSH_STRING_LEN 70 From 7d5382d7fadbb871ab014a521b2d9e796670d19e Mon Sep 17 00:00:00 2001 From: houndthe Date: Fri, 2 Apr 2021 00:22:14 +0200 Subject: [PATCH 08/21] Restructure elf_format to get symbols in the same manner as telfhash --- .../fileformat/file_format/elf/elf_format.h | 2 ++ .../types/import_table/elf_import_table.h | 5 ++++ src/fileformat/file_format/elf/elf_format.cpp | 28 ++++++++++++++++--- .../types/import_table/elf_import_table.cpp | 13 +++++---- 4 files changed, 38 insertions(+), 10 deletions(-) diff --git a/include/retdec/fileformat/file_format/elf/elf_format.h b/include/retdec/fileformat/file_format/elf/elf_format.h index 35d95bea5..cc4999d43 100644 --- a/include/retdec/fileformat/file_format/elf/elf_format.h +++ b/include/retdec/fileformat/file_format/elf/elf_format.h @@ -24,6 +24,8 @@ namespace fileformat { class ElfFormat : public FileFormat { private: + ElfImportTable *elfImportTable = nullptr; + /** * Description of ELF relocation table */ diff --git a/include/retdec/fileformat/types/import_table/elf_import_table.h b/include/retdec/fileformat/types/import_table/elf_import_table.h index ec96b70b6..c927dd760 100644 --- a/include/retdec/fileformat/types/import_table/elf_import_table.h +++ b/include/retdec/fileformat/types/import_table/elf_import_table.h @@ -5,6 +5,7 @@ */ #include "import_table.h" +#include "retdec/fileformat/types/dotnet_headers/metadata_tables.h" namespace retdec { namespace fileformat { @@ -12,6 +13,10 @@ namespace fileformat { class ElfImportTable : public ImportTable { public: + // so we can prefere .dynsym over .symtab + // https://github.com/trendmicro/telfhash/blob/b5e398e59dc25a56a28861751c1fccc74ef71617/telfhash/telfhash.py#L279 + bool isDynsym = false; + std::vector symbolNames; // used for telfhash calculation void computeHashes() override; }; } // namespace fileformat diff --git a/src/fileformat/file_format/elf/elf_format.cpp b/src/fileformat/file_format/elf/elf_format.cpp index 05d2183ac..84494094b 100644 --- a/src/fileformat/file_format/elf/elf_format.cpp +++ b/src/fileformat/file_format/elf/elf_format.cpp @@ -4,6 +4,7 @@ * @copyright (c) 2017 Avast Software, licensed under the MIT license */ +#include #include #include "retdec/utils/conversion.h" @@ -1733,6 +1734,10 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio std::unordered_multimap importNameAddressMap; loadRelocations(file, section, importNameAddressMap); + if (elfImportTable && !elfImportTable->isDynsym) { + elfImportTable->symbolNames = {}; + } + for(std::size_t i = 0, e = elfSymbolTable->get_loaded_symbols_num(); i < e; ++i) { auto symbol = std::make_shared(); @@ -1747,6 +1752,15 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio symbol->setElfBind(bind); symbol->setElfOther(other); link = fixSymbolLink(link, value); + if (type == STT_FUNC && bind == STB_GLOBAL && other == STV_DEFAULT) { + if (!elfImportTable) { + elfImportTable = new ElfImportTable(); + } + if (!elfImportTable->isDynsym) { + elfImportTable->symbolNames.push_back(name); + } + } + if(link >= file->sections.size() || !file->sections[link] || link == SHN_ABS || link == SHN_COMMON || link == SHN_UNDEF || link == SHN_XINDEX) { @@ -1756,9 +1770,9 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio // Ignore first STN_UNDEF STT_NOTYPE symbol when considering imports if(link == SHN_UNDEF && i != 0) { - if(!importTable) + if(!elfImportTable) { - importTable = new ElfImportTable(); + elfImportTable = new ElfImportTable(); } auto keyIter = importNameAddressMap.equal_range(name); // we create std::set from std::multimap values in order to ensure determinism @@ -1769,7 +1783,7 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio import->setName(name); import->setAddress(address.second); import->setUsageType(symbolToImportUsage(symbol->getUsageType())); - importTable->addImport(std::move(import)); + elfImportTable->addImport(std::move(import)); } if(keyIter.first == keyIter.second && getSectionFromAddress(value)) { @@ -1777,7 +1791,7 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio import->setName(name); import->setAddress(value); import->setUsageType(symbolToImportUsage(symbol->getUsageType())); - importTable->addImport(std::move(import)); + elfImportTable->addImport(std::move(import)); } } } @@ -1798,6 +1812,7 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio } symtab->setName(section->get_name()); + if(symtab->hasSymbols()) { symbolTables.push_back(symtab); @@ -1806,6 +1821,11 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio { delete symtab; } + if (elfImportTable && section->get_type() == SHT_DYNSYM) { + elfImportTable->isDynsym = true; + } + + importTable = elfImportTable; loadImpHash(); loadExpHash(); diff --git a/src/fileformat/types/import_table/elf_import_table.cpp b/src/fileformat/types/import_table/elf_import_table.cpp index afb60b640..6cf7fdf10 100644 --- a/src/fileformat/types/import_table/elf_import_table.cpp +++ b/src/fileformat/types/import_table/elf_import_table.cpp @@ -7,6 +7,7 @@ #include "retdec/fileformat/utils/crypto.h" #include "retdec/utils/string.h" #include "retdec/fileformat/types/import_table/elf_import_table.h" +#include #include #include #include > @@ -48,17 +49,17 @@ static bool isSymbolExcluded(const std::string& symbol) void ElfImportTable::computeHashes() { - std::vector imported_symbols(imports.size()); + std::vector imported_symbols; + imported_symbols.reserve(symbolNames.size()); - for (const auto& import : imports) { - auto funcName = toLower(import->getName()); + for (const auto& symbol : symbolNames) { + auto name = toLower(symbol); - // filter the symbols just as telfhash does for the same result - if (isSymbolExcluded(funcName)) { + if (isSymbolExcluded(name)) { continue; } - imported_symbols.push_back(funcName); + imported_symbols.emplace_back(name); } /* sort them lexicographically */ From 53ac63eff9e9280d4789afd61263052a8e09fe2e Mon Sep 17 00:00:00 2001 From: houndthe Date: Fri, 2 Apr 2021 12:40:28 +0200 Subject: [PATCH 09/21] Ignore symbols from dynamic segments --- src/fileformat/file_format/elf/elf_format.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fileformat/file_format/elf/elf_format.cpp b/src/fileformat/file_format/elf/elf_format.cpp index 84494094b..6635deec0 100644 --- a/src/fileformat/file_format/elf/elf_format.cpp +++ b/src/fileformat/file_format/elf/elf_format.cpp @@ -1756,7 +1756,8 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio if (!elfImportTable) { elfImportTable = new ElfImportTable(); } - if (!elfImportTable->isDynsym) { + /* check if we already have prefered dynsym symbols and ignore symbols from segments */ + if (!elfImportTable->isDynsym && section->get_name().find("dynamic_") == std::string::npos) { elfImportTable->symbolNames.push_back(name); } } From 9fca6025ce1de8af76c353ec95250c1f1507b696 Mon Sep 17 00:00:00 2001 From: houndthe Date: Fri, 2 Apr 2021 13:11:10 +0200 Subject: [PATCH 10/21] First exclude then convert to lower_case --- src/fileformat/types/import_table/elf_import_table.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/fileformat/types/import_table/elf_import_table.cpp b/src/fileformat/types/import_table/elf_import_table.cpp index 6cf7fdf10..a45201280 100644 --- a/src/fileformat/types/import_table/elf_import_table.cpp +++ b/src/fileformat/types/import_table/elf_import_table.cpp @@ -53,12 +53,15 @@ void ElfImportTable::computeHashes() imported_symbols.reserve(symbolNames.size()); for (const auto& symbol : symbolNames) { - auto name = toLower(symbol); - - if (isSymbolExcluded(name)) { + /* It is important to first exclude, then lowercase + as "Str_Aprintf" is valid, but would become + filtered when lower case */ + if (isSymbolExcluded(symbol)) { continue; } + auto name = toLower(symbol); + imported_symbols.emplace_back(name); } From 3d1720d213159d530767ff19126bd4907360f1bf Mon Sep 17 00:00:00 2001 From: houndthe Date: Fri, 2 Apr 2021 14:13:27 +0200 Subject: [PATCH 11/21] mask out symbol visibility from others --- src/fileformat/file_format/elf/elf_format.cpp | 3 ++- src/fileformat/types/import_table/elf_import_table.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/fileformat/file_format/elf/elf_format.cpp b/src/fileformat/file_format/elf/elf_format.cpp index 6635deec0..25f333ea3 100644 --- a/src/fileformat/file_format/elf/elf_format.cpp +++ b/src/fileformat/file_format/elf/elf_format.cpp @@ -1752,7 +1752,8 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio symbol->setElfBind(bind); symbol->setElfOther(other); link = fixSymbolLink(link, value); - if (type == STT_FUNC && bind == STB_GLOBAL && other == STV_DEFAULT) { + auto visibility = other & 0x3; + if (type == STT_FUNC && bind == STB_GLOBAL && visibility == STV_DEFAULT) { if (!elfImportTable) { elfImportTable = new ElfImportTable(); } diff --git a/src/fileformat/types/import_table/elf_import_table.cpp b/src/fileformat/types/import_table/elf_import_table.cpp index a45201280..25a7f727e 100644 --- a/src/fileformat/types/import_table/elf_import_table.cpp +++ b/src/fileformat/types/import_table/elf_import_table.cpp @@ -7,12 +7,13 @@ #include "retdec/fileformat/utils/crypto.h" #include "retdec/utils/string.h" #include "retdec/fileformat/types/import_table/elf_import_table.h" -#include #include + #include #include > #include + using namespace retdec::utils; namespace retdec { From 1209eb7b76994bd749a34fc9d41e914039574202 Mon Sep 17 00:00:00 2001 From: houndthe Date: Tue, 6 Apr 2021 16:37:23 +0200 Subject: [PATCH 12/21] Move telfhash outside import table to elf_format, use TLSH for all imphashes, create default imphash for ELF --- deps/CMakeLists.txt | 2 +- .../fileformat/file_format/elf/elf_format.h | 6 +- .../types/import_table/elf_import_table.h | 4 - src/fileformat/file_format/elf/elf_format.cpp | 110 +++++++++++++++--- .../types/import_table/elf_import_table.cpp | 48 +------- .../types/import_table/import_table.cpp | 21 +++- src/fileinfo/file_detector/elf_detector.cpp | 5 + src/fileinfo/file_detector/elf_detector.h | 1 + .../file_information/file_information.cpp | 10 ++ .../file_information/file_information.h | 3 + .../simple_getter/basic_json_getter.cpp | 3 + .../simple_getter/basic_plain_getter.cpp | 2 + 12 files changed, 145 insertions(+), 70 deletions(-) diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index e857b3e01..8e25d58a3 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -14,7 +14,6 @@ endif() set(MSVC_GE $) set(MSVC_CONFIG $<${MSVC_GE}:$/>) -cond_add_subdirectory(tlsh RETDEC_ENABLE_TLSH) cond_add_subdirectory(capstone RETDEC_ENABLE_CAPSTONE) cond_add_subdirectory(elfio RETDEC_ENABLE_ELFIO) cond_add_subdirectory(googletest RETDEC_ENABLE_GOOGLETEST) @@ -24,3 +23,4 @@ cond_add_subdirectory(rapidjson RETDEC_ENABLE_RAPIDJSON) cond_add_subdirectory(tinyxml2 RETDEC_ENABLE_TINYXML2) cond_add_subdirectory(yara RETDEC_ENABLE_YARA) cond_add_subdirectory(yaramod RETDEC_ENABLE_YARAMOD) +cond_add_subdirectory(tlsh RETDEC_ENABLE_TLSH) diff --git a/include/retdec/fileformat/file_format/elf/elf_format.h b/include/retdec/fileformat/file_format/elf/elf_format.h index cc4999d43..112850047 100644 --- a/include/retdec/fileformat/file_format/elf/elf_format.h +++ b/include/retdec/fileformat/file_format/elf/elf_format.h @@ -24,7 +24,9 @@ namespace fileformat { class ElfFormat : public FileFormat { private: - ElfImportTable *elfImportTable = nullptr; + std::vector telfhashSymbols; + bool telfhashDynsym; /* flag if we already loaded preferred dynsym */ + std::string telfhash; /** * Description of ELF relocation table @@ -83,6 +85,7 @@ class ElfFormat : public FileFormat void loadCorePrPsInfo(std::size_t offset, std::size_t size); void loadCoreAuxvInfo(std::size_t offset, std::size_t size); void loadCoreInfo(); + void loadTelfhash(); /// @} protected: int elfClass; ///< class of input ELF file @@ -137,6 +140,7 @@ class ElfFormat : public FileFormat std::size_t getOsOrAbiVersion() const; std::size_t getSectionTableSize() const; std::size_t getSegmentTableSize() const; + const std::string& getTelfhash() const; int getElfClass() const; bool isWiiPowerPc() const; /// @} diff --git a/include/retdec/fileformat/types/import_table/elf_import_table.h b/include/retdec/fileformat/types/import_table/elf_import_table.h index c927dd760..3fd9908e7 100644 --- a/include/retdec/fileformat/types/import_table/elf_import_table.h +++ b/include/retdec/fileformat/types/import_table/elf_import_table.h @@ -13,10 +13,6 @@ namespace fileformat { class ElfImportTable : public ImportTable { public: - // so we can prefere .dynsym over .symtab - // https://github.com/trendmicro/telfhash/blob/b5e398e59dc25a56a28861751c1fccc74ef71617/telfhash/telfhash.py#L279 - bool isDynsym = false; - std::vector symbolNames; // used for telfhash calculation void computeHashes() override; }; } // namespace fileformat diff --git a/src/fileformat/file_format/elf/elf_format.cpp b/src/fileformat/file_format/elf/elf_format.cpp index 25f333ea3..596226d88 100644 --- a/src/fileformat/file_format/elf/elf_format.cpp +++ b/src/fileformat/file_format/elf/elf_format.cpp @@ -6,12 +6,14 @@ #include #include +#include #include "retdec/utils/conversion.h" #include "retdec/utils/string.h" #include "retdec/fileformat/file_format/elf/elf_format.h" #include "retdec/fileformat/types/symbol_table/elf_symbol.h" #include "retdec/fileformat/utils/conversions.h" +#include using namespace retdec::utils; using namespace ELFIO; @@ -1734,8 +1736,12 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio std::unordered_multimap importNameAddressMap; loadRelocations(file, section, importNameAddressMap); - if (elfImportTable && !elfImportTable->isDynsym) { - elfImportTable->symbolNames = {}; + /* check to ignore symbols from segments for telfhash this is pretty + ugly and error prone, find a better way to know symbol source */ + bool isSegmentSymbols = section->get_name().find("dynamic_") != std::string::npos; + + if (!telfhashDynsym && !isSegmentSymbols) { + telfhashSymbols = {}; } for(std::size_t i = 0, e = elfSymbolTable->get_loaded_symbols_num(); i < e; ++i) @@ -1754,12 +1760,10 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio link = fixSymbolLink(link, value); auto visibility = other & 0x3; if (type == STT_FUNC && bind == STB_GLOBAL && visibility == STV_DEFAULT) { - if (!elfImportTable) { - elfImportTable = new ElfImportTable(); - } - /* check if we already have prefered dynsym symbols and ignore symbols from segments */ - if (!elfImportTable->isDynsym && section->get_name().find("dynamic_") == std::string::npos) { - elfImportTable->symbolNames.push_back(name); + /* check if we already have prefered dynsym symbols and ignore symbols from segments + this is pretty ugly and error prone, find a better way to know symbol source */ + if (!telfhashDynsym && !isSegmentSymbols) { + telfhashSymbols.push_back(name); } } @@ -1772,9 +1776,9 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio // Ignore first STN_UNDEF STT_NOTYPE symbol when considering imports if(link == SHN_UNDEF && i != 0) { - if(!elfImportTable) + if(!importTable) { - elfImportTable = new ElfImportTable(); + importTable = new ElfImportTable(); } auto keyIter = importNameAddressMap.equal_range(name); // we create std::set from std::multimap values in order to ensure determinism @@ -1785,7 +1789,7 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio import->setName(name); import->setAddress(address.second); import->setUsageType(symbolToImportUsage(symbol->getUsageType())); - elfImportTable->addImport(std::move(import)); + importTable->addImport(std::move(import)); } if(keyIter.first == keyIter.second && getSectionFromAddress(value)) { @@ -1793,7 +1797,7 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio import->setName(name); import->setAddress(value); import->setUsageType(symbolToImportUsage(symbol->getUsageType())); - elfImportTable->addImport(std::move(import)); + importTable->addImport(std::move(import)); } } } @@ -1823,16 +1827,85 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio { delete symtab; } - if (elfImportTable && section->get_type() == SHT_DYNSYM) { - elfImportTable->isDynsym = true; + if (section->get_type() == SHT_DYNSYM) { + telfhashDynsym = true; } - importTable = elfImportTable; - + loadTelfhash(); loadImpHash(); loadExpHash(); } +/* exclusions are based on the original implementation + https://github.com/trendmicro/telfhash/blob/master/telfhash/telfhash.py */ +static const std::unordered_set exclusion_set = { + "__libc_start_main", // main function + "main", // main function + "abort", // ARM default + "cachectl", // MIPS default + "cacheflush", // MIPS default + "puts", // Compiler optimization (function replacement) + "atol", // Compiler optimization (function replacement) + "malloc_trim" // GNU extensions +}; + +/* +ignore + symbols starting with . or + x86-64 specific functions + string functions (str.* and mem.*), gcc changes them depending on architecture + symbols starting with . or _ +*/ +static std::regex exclusion_regex("(^[_\.].*$)|(^.*64$)|(^str.*$)|(^mem.*$)"); + +static bool isSymbolExcluded(const std::string& symbol) +{ + return symbol.empty() + || std::regex_match(symbol, exclusion_regex) + || exclusion_set.count(symbol); +} + +void ElfFormat::loadTelfhash() +{ + std::vector imported_symbols; + imported_symbols.reserve(telfhashSymbols.size()); + + for (const auto& symbol : telfhashSymbols) { + /* It is important to first exclude, then lowercase + as "Str_Aprintf" is valid, but would become + filtered when lower case */ + if (isSymbolExcluded(symbol)) { + continue; + } + + auto name = toLower(symbol); + + imported_symbols.emplace_back(name); + } + + /* sort them lexicographically */ + std::sort(imported_symbols.begin(), imported_symbols.end()); + + std::string impHashString; + for (const auto& symbol : imported_symbols) { + if (!impHashString.empty()) + impHashString.append(1, ','); + + impHashString.append(symbol); + } + + if (impHashString.size()) { + auto data = reinterpret_cast(impHashString.data()); + + Tlsh tlsh; + tlsh.update(data, impHashString.size()); + + tlsh.final(); + const int show_version = 1; /* this prepends the hash with 'T' + number of the version */ + telfhash = toLower(tlsh.getHash(show_version)); + } +} + /** * Add new symbol table based on existing symbol table and based on global offset table * @param oldTab Existing symbol table @@ -2979,5 +3052,10 @@ unsigned long long ElfFormat::getBaseOffset() const return minOffset == std::numeric_limits::max() ? 0 : minOffset; } + +const std::string& ElfFormat::getTelfhash() const { + return telfhash; +} + } // namespace fileformat } // namespace retdec diff --git a/src/fileformat/types/import_table/elf_import_table.cpp b/src/fileformat/types/import_table/elf_import_table.cpp index 25a7f727e..8a7067e33 100644 --- a/src/fileformat/types/import_table/elf_import_table.cpp +++ b/src/fileformat/types/import_table/elf_import_table.cpp @@ -19,51 +19,14 @@ using namespace retdec::utils; namespace retdec { namespace fileformat { -/* exclusions are based on the original implementation - https://github.com/trendmicro/telfhash/blob/master/telfhash/telfhash.py */ -static const std::unordered_set exclusion_set = { - "__libc_start_main", // main function - "main", // main function - "abort", // ARM default - "cachectl", // MIPS default - "cacheflush", // MIPS default - "puts", // Compiler optimization (function replacement) - "atol", // Compiler optimization (function replacement) - "malloc_trim" // GNU extensions -}; - -/* -ignore - symbols starting with . or - x86-64 specific functions - string functions (str.* and mem.*), gcc changes them depending on architecture - symbols starting with . or _ -*/ -static std::regex exclusion_regex("(^[_\.].*$)|(^.*64$)|(^str.*$)|(^mem.*$)"); - -static bool isSymbolExcluded(const std::string& symbol) -{ - return symbol.empty() - || std::regex_match(symbol, exclusion_regex) - || exclusion_set.count(symbol); -} - void ElfImportTable::computeHashes() { std::vector imported_symbols; - imported_symbols.reserve(symbolNames.size()); - - for (const auto& symbol : symbolNames) { - /* It is important to first exclude, then lowercase - as "Str_Aprintf" is valid, but would become - filtered when lower case */ - if (isSymbolExcluded(symbol)) { - continue; - } - - auto name = toLower(symbol); + imported_symbols.reserve(imports.size()); - imported_symbols.emplace_back(name); + for (const auto& import : imports) { + auto name = import->getName(); + imported_symbols.emplace_back(toLower(name)); } /* sort them lexicographically */ @@ -84,7 +47,8 @@ void ElfImportTable::computeHashes() tlsh.update(data, impHashString.size()); tlsh.final(); - const int show_version = 1; /* this prepends the hash with 'T' + number of the version */ + /* this prepends the hash with 'T' + number of the version */ + const int show_version = 1; impHashTlsh = toLower(tlsh.getHash(show_version)); impHashCrc32 = getCrc32(data, impHashString.size()); diff --git a/src/fileformat/types/import_table/import_table.cpp b/src/fileformat/types/import_table/import_table.cpp index 76dc5a15f..6fd31ed10 100644 --- a/src/fileformat/types/import_table/import_table.cpp +++ b/src/fileformat/types/import_table/import_table.cpp @@ -10,6 +10,7 @@ #include "retdec/fileformat/utils/crypto.h" #include "retdec/pelib/PeLibAux.h" #include "retdec/fileformat/types/import_table/import_table.h" +#include using namespace retdec::utils; @@ -763,7 +764,7 @@ ImportTable::importsIterator ImportTable::end() const } /** - * Compute import hashes - CRC32, MD5, SHA256. + * Compute import hashes - CRC32, MD5, SHA256, TLSH. */ void ImportTable::computeHashes() { @@ -824,11 +825,19 @@ void ImportTable::computeHashes() //} } - if (impHashBytes.size()) - { - impHashCrc32 = getCrc32((const uint8_t *)impHashBytes.data(), impHashBytes.size()); - impHashMd5 = getMd5((const uint8_t *)impHashBytes.data(), impHashBytes.size()); - impHashSha256 = getSha256((const uint8_t *)impHashBytes.data(), impHashBytes.size()); + if (impHashBytes.size()) { + auto data = reinterpret_cast(impHashBytes.data()); + + Tlsh tlsh; + tlsh.update(data, impHashBytes.size()); + tlsh.final(); + /* this prepends the hash with 'T' + number of the version */ + const int show_version = 1; + impHashTlsh = toLower(tlsh.getHash(show_version)); + + impHashCrc32 = getCrc32(data, impHashBytes.size()); + impHashMd5 = getMd5(data, impHashBytes.size()); + impHashSha256 = getSha256(data, impHashBytes.size()); } } diff --git a/src/fileinfo/file_detector/elf_detector.cpp b/src/fileinfo/file_detector/elf_detector.cpp index 315fa50dd..1f3deffd1 100644 --- a/src/fileinfo/file_detector/elf_detector.cpp +++ b/src/fileinfo/file_detector/elf_detector.cpp @@ -1949,6 +1949,10 @@ void ElfDetector::detectFileType() fileInfo.setFileType(fileType); } +void ElfDetector::getTelfhash() { + fileInfo.setTelfhash(elfParser->getTelfhash()); +} + void ElfDetector::getAdditionalInfo() { getFileVersion(); @@ -1962,6 +1966,7 @@ void ElfDetector::getAdditionalInfo() getSymbolTable(); getNotes(); getCoreInfo(); + getTelfhash(); } /** diff --git a/src/fileinfo/file_detector/elf_detector.h b/src/fileinfo/file_detector/elf_detector.h index c22496c39..a7db13dd5 100644 --- a/src/fileinfo/file_detector/elf_detector.h +++ b/src/fileinfo/file_detector/elf_detector.h @@ -35,6 +35,7 @@ class ElfDetector : public FileDetector void getDynamicSectionsSegments(); void getNotes(); void getCoreInfo(); + void getTelfhash(); /// @} protected: /// @name Detection methods diff --git a/src/fileinfo/file_information/file_information.cpp b/src/fileinfo/file_information/file_information.cpp index 2261ad2ec..f34e405ef 100644 --- a/src/fileinfo/file_information/file_information.cpp +++ b/src/fileinfo/file_information/file_information.cpp @@ -105,6 +105,11 @@ std::string FileInformation::getPathToFile() const return filePath; } +std::string FileInformation::getTelfhash() const +{ + return telfhash; +} + /** * Get CRC32 of input file * @return CRC32 of input file @@ -3737,6 +3742,11 @@ void FileInformation::setPathToFile(const std::string &filepath) filePath = filepath; } +void FileInformation::setTelfhash(const std::string &hash) +{ + telfhash = hash; +} + /** * Get CRC32 of input file * @param fileCrc32 CRC32 of input file diff --git a/src/fileinfo/file_information/file_information.h b/src/fileinfo/file_information/file_information.h index 628c9a8c2..b8080355e 100644 --- a/src/fileinfo/file_information/file_information.h +++ b/src/fileinfo/file_information/file_information.h @@ -26,6 +26,7 @@ class FileInformation private: retdec::cpdetect::ReturnCode status = retdec::cpdetect::ReturnCode::OK; std::string filePath; ///< path to input file + std::string telfhash; ///< telfhash of ELF input file std::string crc32; ///< CRC32 of input file std::string md5; ///< MD5 of input file std::string sha256; ///< SHA256 of input file @@ -76,6 +77,7 @@ class FileInformation /// @{ retdec::cpdetect::ReturnCode getStatus() const; std::string getPathToFile() const; + std::string getTelfhash() const; std::string getCrc32() const; std::string getMd5() const; std::string getSha256() const; @@ -547,6 +549,7 @@ class FileInformation /// @{ void setStatus(retdec::cpdetect::ReturnCode state); void setPathToFile(const std::string &filepath); + void setTelfhash(const std::string &telfhash); void setCrc32(const std::string &fileCrc32); void setMd5(const std::string &fileMd5); void setSha256(const std::string &fileSha256); diff --git a/src/fileinfo/file_presentation/getters/simple_getter/basic_json_getter.cpp b/src/fileinfo/file_presentation/getters/simple_getter/basic_json_getter.cpp index c5872eb62..57c9edf29 100644 --- a/src/fileinfo/file_presentation/getters/simple_getter/basic_json_getter.cpp +++ b/src/fileinfo/file_presentation/getters/simple_getter/basic_json_getter.cpp @@ -4,6 +4,7 @@ * @copyright (c) 2017 Avast Software, licensed under the MIT license */ +#include "retdec/fileformat/file_format/file_format.h" #include "retdec/fileformat/utils/conversions.h" #include "fileinfo/file_presentation/getters/simple_getter/basic_json_getter.h" @@ -26,6 +27,7 @@ std::size_t BasicJsonGetter::loadInformation(std::vector &desc, std desc.clear(); info.clear(); + desc.push_back("telfhash"); desc.push_back("crc32"); desc.push_back("md5"); desc.push_back("sha256"); @@ -36,6 +38,7 @@ std::size_t BasicJsonGetter::loadInformation(std::vector &desc, std desc.push_back("endianness"); desc.push_back("imageBaseAddress"); + info.push_back(fileinfo.getTelfhash()); info.push_back(fileinfo.getCrc32()); info.push_back(fileinfo.getMd5()); info.push_back(fileinfo.getSha256()); diff --git a/src/fileinfo/file_presentation/getters/simple_getter/basic_plain_getter.cpp b/src/fileinfo/file_presentation/getters/simple_getter/basic_plain_getter.cpp index f3c5ab12f..5093a824f 100644 --- a/src/fileinfo/file_presentation/getters/simple_getter/basic_plain_getter.cpp +++ b/src/fileinfo/file_presentation/getters/simple_getter/basic_plain_getter.cpp @@ -30,6 +30,7 @@ std::size_t BasicPlainGetter::loadInformation(std::vector &desc, st desc.clear(); info.clear(); + desc.push_back("Telfhash : "); desc.push_back("CRC32 : "); desc.push_back("MD5 : "); desc.push_back("SHA256 : "); @@ -53,6 +54,7 @@ std::size_t BasicPlainGetter::loadInformation(std::vector &desc, st desc.push_back("Entry point section index: "); desc.push_back("Bytes on entry point : "); + info.push_back(fileinfo.getTelfhash()); info.push_back(fileinfo.getCrc32()); info.push_back(fileinfo.getMd5()); info.push_back(fileinfo.getSha256()); From 7321cf05121b4a8bbad89664d57401db04f6df5f Mon Sep 17 00:00:00 2001 From: houndthe Date: Tue, 6 Apr 2021 16:48:34 +0200 Subject: [PATCH 13/21] Fix uninitialized value --- include/retdec/fileformat/file_format/elf/elf_format.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/retdec/fileformat/file_format/elf/elf_format.h b/include/retdec/fileformat/file_format/elf/elf_format.h index 112850047..1b041a006 100644 --- a/include/retdec/fileformat/file_format/elf/elf_format.h +++ b/include/retdec/fileformat/file_format/elf/elf_format.h @@ -25,7 +25,8 @@ class ElfFormat : public FileFormat { private: std::vector telfhashSymbols; - bool telfhashDynsym; /* flag if we already loaded preferred dynsym */ + /* flag if we already loaded symbols from SHT_DYNSYM */ + bool telfhashDynsym = false; std::string telfhash; /** From 052432ae7def93c4665c5d2a6024cc62911d06bd Mon Sep 17 00:00:00 2001 From: houndthe Date: Wed, 7 Apr 2021 00:44:04 +0200 Subject: [PATCH 14/21] Fixed TLSH build on Windows --- deps/tlsh/CMakeLists.txt | 3 +- deps/tlsh/WinFunctions.cpp | 91 +++++++++++++++++++ deps/tlsh/include/tlsh/WinFunctions.h | 46 ++++++++++ deps/tlsh/include/tlsh/tlsh.h | 2 +- src/fileformat/CMakeLists.txt | 5 + src/fileformat/retdec-fileformat-config.cmake | 1 + 6 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 deps/tlsh/WinFunctions.cpp create mode 100644 deps/tlsh/include/tlsh/WinFunctions.h diff --git a/deps/tlsh/CMakeLists.txt b/deps/tlsh/CMakeLists.txt index 886855360..201c9d96d 100644 --- a/deps/tlsh/CMakeLists.txt +++ b/deps/tlsh/CMakeLists.txt @@ -130,9 +130,8 @@ target_include_directories(tlsh # set_target_properties(tlsh PROPERTIES OUTPUT_NAME "retdec-tlsh") - if(MSVC) - add_definitions(-DTLSH_EXPORTS -DTLSH_LIB) + add_compile_definitions(WINDOWS TLSH_EXPORTS TLSH_LIB) endif() # Install includes. diff --git a/deps/tlsh/WinFunctions.cpp b/deps/tlsh/WinFunctions.cpp new file mode 100644 index 000000000..581756184 --- /dev/null +++ b/deps/tlsh/WinFunctions.cpp @@ -0,0 +1,91 @@ +#ifdef WINDOWS + +// implementation of Linux functions for Windows + +#include + +DIR *opendir(const char *dirname) +{ + if (strlen(dirname) >= NAME_LENGTH) { + printf("ERROR: directory name candidate, %s, is too long (%d >= %d)\n", + dirname, strlen(dirname), NAME_LENGTH); + return NULL; + } + + DWORD dw = GetFileAttributes(dirname); + if ((dw & FILE_ATTRIBUTE_DIRECTORY) == 0) + return NULL; + + DIR *dir = new DIR; + dir->hFind = INVALID_HANDLE_VALUE; + _snprintf(dir->dirname, sizeof(dir->dirname), "%s\\*", dirname); + return dir; +} + +struct dirent *readdir(DIR *dir) +{ + if (dir == NULL) { + return NULL; + } + + if (dir->hFind == INVALID_HANDLE_VALUE) { + dir->hFind = FindFirstFile(dir->dirname, &dir->findFileData); + if (dir->hFind == INVALID_HANDLE_VALUE) { + return NULL; + } + } + else { + if (!FindNextFile(dir->hFind, &dir->findFileData)) { + return NULL; + } + } + + _snprintf(dir->findDirEnt.d_name, sizeof(dir->findDirEnt.d_name), "%s", dir->findFileData.cFileName); + + return &dir->findDirEnt; +} + + +int closedir(DIR *dir) +{ + if (dir != NULL) { + if (dir->hFind != INVALID_HANDLE_VALUE) { + FindClose(dir->hFind); + } + delete dir; + } + return 0; +} + +struct tm *localtime_r(const time_t *timep, struct tm *results) +{ + struct tm *tm_s = localtime(timep); + memcpy(results, tm_s, sizeof(struct tm)); + return results; +} + +bool read_file_win(const char *fname, int sizefile, unsigned char* data) +{ + HANDLE hdl = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (hdl == INVALID_HANDLE_VALUE) { + printf("ERROR: CreateFile failed on %s; error:%d\n", fname, GetLastError()); + return false; + } + + bool retVal = true; + DWORD bytesRead; + if (!ReadFile(hdl, data, sizefile, &bytesRead, NULL)) { + printf("ERROR: ReadFile failed on %s; error:%d\n", fname, GetLastError()); + retVal = false; + } + else if (bytesRead != sizefile) { + printf("ERROR: ReadFile read %d bytes, but %d were requested\n", bytesRead, sizefile); + retVal = false; + } + + CloseHandle(hdl); + return retVal; +} + +#endif \ No newline at end of file diff --git a/deps/tlsh/include/tlsh/WinFunctions.h b/deps/tlsh/include/tlsh/WinFunctions.h new file mode 100644 index 000000000..31930d39f --- /dev/null +++ b/deps/tlsh/include/tlsh/WinFunctions.h @@ -0,0 +1,46 @@ +#ifdef WINDOWS +#ifndef WINFUNCTIONS_H +#define WINFUNCTIONS_H + +#include +#include +#include + +#ifndef TLSH_LIB +# ifdef TLSH_EXPORTS +# define TLSH_API __declspec(dllexport) +# else +# define TLSH_API __declspec(dllimport) +# endif +#else +# define TLSH_API +#endif + +#define strdup _strdup +#define NAME_LENGTH MAX_PATH +#define snprintf _snprintf +#define strcasecmp _stricmp +#define random rand +#define srandom srand + +struct dirent { + char d_name[NAME_LENGTH]; +}; + +typedef struct _DIR +{ + char dirname[NAME_LENGTH]; + HANDLE hFind; + WIN32_FIND_DATA findFileData; + struct dirent findDirEnt; +} DIR; + +extern DIR *opendir(const char *dirname); +extern struct dirent *readdir(DIR *dir); +extern int closedir(DIR *dir); +extern struct tm *localtime_r(const time_t *timep, struct tm *results); +extern bool read_file_win(const char *fname, int sizefile, unsigned char* data); + +#endif // #ifndef WINFUNCTIONS_H + +#endif // #ifdef WINDOWS diff --git a/deps/tlsh/include/tlsh/tlsh.h b/deps/tlsh/include/tlsh/tlsh.h index c373cc336..9a921d4e0 100644 --- a/deps/tlsh/include/tlsh/tlsh.h +++ b/deps/tlsh/include/tlsh/tlsh.h @@ -106,7 +106,7 @@ class TlshImpl; #define TLSH_STRING_BUFFER_LEN (TLSH_STRING_LEN_REQ+1) #ifdef WINDOWS -#include +#include "WinFunctions.h" #else #if defined(__SPARC) || defined(_AS_MK_OS_RH73) #define TLSH_API diff --git a/src/fileformat/CMakeLists.txt b/src/fileformat/CMakeLists.txt index 768a5a029..4aa38eef9 100644 --- a/src/fileformat/CMakeLists.txt +++ b/src/fileformat/CMakeLists.txt @@ -111,6 +111,11 @@ if(WIN32) ) endif() +# needed by tlsh lib +if(MSVC) + add_compile_definitions(WINDOWS TLSH_EXPORTS TLSH_LIB) +endif() + set_target_properties(fileformat PROPERTIES OUTPUT_NAME "retdec-fileformat" diff --git a/src/fileformat/retdec-fileformat-config.cmake b/src/fileformat/retdec-fileformat-config.cmake index f96f8b08f..ca2179825 100644 --- a/src/fileformat/retdec-fileformat-config.cmake +++ b/src/fileformat/retdec-fileformat-config.cmake @@ -14,6 +14,7 @@ if(NOT TARGET retdec::fileformat) pelib elfio llvm + tlsh ) include(${CMAKE_CURRENT_LIST_DIR}/retdec-fileformat-targets.cmake) From 536bef165ff55abc78ec5e42667eeb0c0d4396d6 Mon Sep 17 00:00:00 2001 From: Peter Matula Date: Tue, 13 Apr 2021 13:38:27 +0200 Subject: [PATCH 15/21] fileformat/CMakeLists.txt: do not add tlsh-related stuff --- src/fileformat/CMakeLists.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/fileformat/CMakeLists.txt b/src/fileformat/CMakeLists.txt index 4aa38eef9..768a5a029 100644 --- a/src/fileformat/CMakeLists.txt +++ b/src/fileformat/CMakeLists.txt @@ -111,11 +111,6 @@ if(WIN32) ) endif() -# needed by tlsh lib -if(MSVC) - add_compile_definitions(WINDOWS TLSH_EXPORTS TLSH_LIB) -endif() - set_target_properties(fileformat PROPERTIES OUTPUT_NAME "retdec-fileformat" From 711463d13b64ec1bcae221d120a84ab5a74e777c Mon Sep 17 00:00:00 2001 From: Peter Matula Date: Tue, 13 Apr 2021 14:07:18 +0200 Subject: [PATCH 16/21] deps/tlsh: refactor CMake --- deps/tlsh/CMakeLists.txt | 131 +++-------------------------- deps/tlsh/include/tlsh/version.h | 23 +++++ deps/tlsh/retdec-tlsh-config.cmake | 3 +- src/fileformat/CMakeLists.txt | 2 +- 4 files changed, 36 insertions(+), 123 deletions(-) create mode 100644 deps/tlsh/include/tlsh/version.h diff --git a/deps/tlsh/CMakeLists.txt b/deps/tlsh/CMakeLists.txt index 201c9d96d..71a9c3fa1 100644 --- a/deps/tlsh/CMakeLists.txt +++ b/deps/tlsh/CMakeLists.txt @@ -1,123 +1,9 @@ -# TLSH is provided for use under two licenses: Apache OR BSD. -# Users may opt to use either license depending on the license -# restictions of the systems with which they plan to integrate -# the TLSH code. -# -# ============== -# Apache License -# ============== -# Copyright 2013 Trend Micro Incorporated -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# =========== -# BSD License -# =========== -# Copyright (c) 2013, Trend Micro Incorporated -# 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. -# 3. Neither the name of the copyright holder nor the names of its contributors -# may be used to endorse or promote products derived from this software without -# specific prior written permission. -# -# 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. - -set(TLSH_VERSION_MAJOR 4) -set(TLSH_VERSION_MINOR 2) -set(TLSH_VERSION_PATCH 1) - -# TLSH uses only half the counting buckets. -# It can use all the buckets now. -set(TLSH_BUCKETS_128 1) -if(TLSH_BUCKETS_48 EQUAL 1) - set(TLSH_HASH "min hash") - add_definitions(-DBUCKETS_48) -endif() -if(TLSH_BUCKETS_128 EQUAL 1) - set(TLSH_HASH "compact hash") - add_definitions(-DBUCKETS_128) -endif() -if(TLSH_BUCKETS_256 EQUAL 1) - set(TLSH_HASH "full hash") - add_definitions(-DBUCKETS_256) -endif() - -# TLSH uses 1 byte checksum. The collision rate is 1 in 24. -# It can use 3 bytes checksum now. That collision rate in 1 in 5800. -set(TLSH_CHECKSUM_1B 1) - -if(TLSH_CHECKSUM_0B EQUAL 1) - set(TLSH_CHECKSUM "no checksum") - add_definitions(-DCHECKSUM_0B) -endif() -if(TLSH_CHECKSUM_1B EQUAL 1) - set(TLSH_CHECKSUM "1 byte checksum") -endif() -if(TLSH_CHECKSUM_3B EQUAL 1) - set(TLSH_CHECKSUM "3 bytes checksum") - add_definitions(-DCHECKSUM_3B) -endif() - -# setting TLSH_DISTANCE_PARAMETERS to 1 allows you to set command line arguments -# to set - and hence experiment with the distance parameters -# by default this is zero -set(TLSH_DISTANCE_PARAMETERS 0) - -# write a file with the VERSION information -file(REMOVE VERSION) -file(WRITE VERSION - "// This file is generated by cmake. Modify\n" - "// CMakeLists.txt to change the VERSION numbers\n" - "TLSH version: ${TLSH_VERSION_MAJOR}.${TLSH_VERSION_MINOR}.${TLSH_VERSION_PATCH} ${TLSH_HASH}, ${TLSH_CHECKSUM}\n") - -file(REMOVE include/tlsh/version.h) -file(WRITE include/tlsh/version.h - "/****************************************************\n" - " * This file is generated by cmake. Modify the top\n" - " * level CMakeLists.txt to change the VERSION numbers\n" - " ****************************************************/\n\n" - "#define VERSION_MAJOR ${TLSH_VERSION_MAJOR}\n" - "#define VERSION_MINOR ${TLSH_VERSION_MINOR}\n" - "#define VERSION_PATCH ${TLSH_VERSION_PATCH}\n" - "#define TLSH_HASH \"${TLSH_HASH}\"\n" - "#define TLSH_CHECKSUM \"${TLSH_CHECKSUM}\"\n") -if(TLSH_DISTANCE_PARAMETERS EQUAL 1) -file(APPEND include/tlsh/version.h - "#define TLSH_DISTANCE_PARAMETERS ${TLSH_DISTANCE_PARAMETERS}\n") -endif() - -set(TLSH_SRCS tlsh.cpp tlsh_impl.cpp tlsh_util.cpp) - -add_library(tlsh STATIC ${TLSH_SRCS}) +add_library(tlsh STATIC + tlsh.cpp + tlsh_impl.cpp + tlsh_util.cpp +) add_library(retdec::deps::tlsh ALIAS tlsh) target_include_directories(tlsh @@ -128,10 +14,13 @@ target_include_directories(tlsh $ ) +set_target_properties(tlsh + PROPERTIES + OUTPUT_NAME "retdec-tlsh" +) -# set_target_properties(tlsh PROPERTIES OUTPUT_NAME "retdec-tlsh") if(MSVC) - add_compile_definitions(WINDOWS TLSH_EXPORTS TLSH_LIB) + target_compile_definitions(tlsh PUBLIC WINDOWS TLSH_EXPORTS TLSH_LIB) endif() # Install includes. diff --git a/deps/tlsh/include/tlsh/version.h b/deps/tlsh/include/tlsh/version.h new file mode 100644 index 000000000..41cb3bf8c --- /dev/null +++ b/deps/tlsh/include/tlsh/version.h @@ -0,0 +1,23 @@ + +#define VERSION_MAJOR 4 +#define VERSION_MINOR 2 +#define VERSION_PATCH 1 + +// Default. +#define TLSH_HASH "compact hash" +#define BUCKETS_128 +// Possible option. +//#define TLSH_HASH "min hash" +//#define BUCKETS_48 +// Possible option. +//#define TLSH_HASH "full hash" +//#define BUCKETS_256 + +// Default. +#define TLSH_CHECKSUM "1 byte checksum" +// Possible option. +//#define TLSH_CHECKSUM "no checksum" +//#define CHECKSUM_0B +// Possible option. +//#define TLSH_CHECKSUM "3 bytes checksum" +//#define CHECKSUM_3B diff --git a/deps/tlsh/retdec-tlsh-config.cmake b/deps/tlsh/retdec-tlsh-config.cmake index f28e9bb28..6cbefd361 100644 --- a/deps/tlsh/retdec-tlsh-config.cmake +++ b/deps/tlsh/retdec-tlsh-config.cmake @@ -1,3 +1,4 @@ + if(NOT TARGET retdec::deps::tlsh) include(${CMAKE_CURRENT_LIST_DIR}/retdec-tlsh-targets.cmake) -endif() \ No newline at end of file +endif() diff --git a/src/fileformat/CMakeLists.txt b/src/fileformat/CMakeLists.txt index 768a5a029..c9abee6d5 100644 --- a/src/fileformat/CMakeLists.txt +++ b/src/fileformat/CMakeLists.txt @@ -96,9 +96,9 @@ target_link_libraries(fileformat retdec::utils retdec::pelib retdec::deps::elfio - retdec::deps::tlsh retdec::deps::llvm PRIVATE + retdec::deps::tlsh OpenSSL::Crypto ) From 6299548234e2f493b0178050d5ac905276ac84ba Mon Sep 17 00:00:00 2001 From: Peter Matula Date: Wed, 14 Apr 2021 11:24:35 +0200 Subject: [PATCH 17/21] cmake/options.cmake: move TLSH to deps section --- cmake/options.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/options.cmake b/cmake/options.cmake index cc0d4db34..bf1083c0a 100644 --- a/cmake/options.cmake +++ b/cmake/options.cmake @@ -497,6 +497,9 @@ set_if_at_least_one_set(RETDEC_ENABLE_YARAMOD RETDEC_ENABLE_PAT2YARA RETDEC_ENABLE_PATTERNGEN) +set_if_at_least_one_set(RETDEC_ENABLE_TLSH + RETDEC_ENABLE_FILEFORMAT) + # Support set_if_at_least_one_set(RETDEC_ENABLE_SUPPORT_ORDINALS @@ -516,6 +519,3 @@ set_if_at_least_one_set(RETDEC_ENABLE_SUPPORT_YARA_TOOLS set_if_at_least_one_set(RETDEC_ENABLE_SUPPORT_YARA_STATIC_CODE RETDEC_ENABLE_RETDEC) - -set_if_at_least_one_set(RETDEC_ENABLE_TLSH - RETDEC_ENABLE_FILEFORMAT) \ No newline at end of file From 10217f7a45a1d7d65178c68b4081d45b5b8b4ca3 Mon Sep 17 00:00:00 2001 From: Peter Matula Date: Wed, 14 Apr 2021 11:25:19 +0200 Subject: [PATCH 18/21] deps/tlsh/cmake: add new line at the end --- deps/tlsh/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/tlsh/CMakeLists.txt b/deps/tlsh/CMakeLists.txt index 71a9c3fa1..120b32416 100644 --- a/deps/tlsh/CMakeLists.txt +++ b/deps/tlsh/CMakeLists.txt @@ -49,4 +49,4 @@ install( "${CMAKE_CURRENT_LIST_DIR}/retdec-tlsh-config.cmake" DESTINATION "${RETDEC_INSTALL_CMAKE_DIR}" -) \ No newline at end of file +) From 9c175a352dc1b58245953deb7f00638ebd4340e3 Mon Sep 17 00:00:00 2001 From: Peter Matula Date: Wed, 14 Apr 2021 11:26:52 +0200 Subject: [PATCH 19/21] fileformat/elf_format: C comment -> C++ comment --- include/retdec/fileformat/file_format/elf/elf_format.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/retdec/fileformat/file_format/elf/elf_format.h b/include/retdec/fileformat/file_format/elf/elf_format.h index 1b041a006..ae46ec15e 100644 --- a/include/retdec/fileformat/file_format/elf/elf_format.h +++ b/include/retdec/fileformat/file_format/elf/elf_format.h @@ -25,7 +25,7 @@ class ElfFormat : public FileFormat { private: std::vector telfhashSymbols; - /* flag if we already loaded symbols from SHT_DYNSYM */ + /// flag if we already loaded symbols from SHT_DYNSYM bool telfhashDynsym = false; std::string telfhash; From 6ddeb7e63be0b3d88fa192980d0af2b58e8ebb15 Mon Sep 17 00:00:00 2001 From: Peter Matula Date: Wed, 14 Apr 2021 11:28:09 +0200 Subject: [PATCH 20/21] fileformat/elf_import_table.h: add missing new line --- include/retdec/fileformat/types/import_table/elf_import_table.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/retdec/fileformat/types/import_table/elf_import_table.h b/include/retdec/fileformat/types/import_table/elf_import_table.h index 3fd9908e7..a6c33afe2 100644 --- a/include/retdec/fileformat/types/import_table/elf_import_table.h +++ b/include/retdec/fileformat/types/import_table/elf_import_table.h @@ -15,5 +15,6 @@ class ElfImportTable : public ImportTable public: void computeHashes() override; }; + } // namespace fileformat } // namespace retdec From c5c91b04be1b4512defbd73d136a63c873361103 Mon Sep 17 00:00:00 2001 From: Peter Matula Date: Wed, 14 Apr 2021 11:58:50 +0200 Subject: [PATCH 21/21] fileformat: remove trailing spaces --- src/fileformat/file_format/elf/elf_format.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/fileformat/file_format/elf/elf_format.cpp b/src/fileformat/file_format/elf/elf_format.cpp index 596226d88..e1cdcbc93 100644 --- a/src/fileformat/file_format/elf/elf_format.cpp +++ b/src/fileformat/file_format/elf/elf_format.cpp @@ -1760,7 +1760,7 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio link = fixSymbolLink(link, value); auto visibility = other & 0x3; if (type == STT_FUNC && bind == STB_GLOBAL && visibility == STV_DEFAULT) { - /* check if we already have prefered dynsym symbols and ignore symbols from segments + /* check if we already have prefered dynsym symbols and ignore symbols from segments this is pretty ugly and error prone, find a better way to know symbol source */ if (!telfhashDynsym && !isSegmentSymbols) { telfhashSymbols.push_back(name); @@ -1836,7 +1836,7 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio loadExpHash(); } -/* exclusions are based on the original implementation +/* exclusions are based on the original implementation https://github.com/trendmicro/telfhash/blob/master/telfhash/telfhash.py */ static const std::unordered_set exclusion_set = { "__libc_start_main", // main function @@ -1851,7 +1851,7 @@ static const std::unordered_set exclusion_set = { /* ignore - symbols starting with . or + symbols starting with . or x86-64 specific functions string functions (str.* and mem.*), gcc changes them depending on architecture symbols starting with . or _ @@ -1860,8 +1860,8 @@ static std::regex exclusion_regex("(^[_\.].*$)|(^.*64$)|(^str.*$)|(^mem.*$)"); static bool isSymbolExcluded(const std::string& symbol) { - return symbol.empty() - || std::regex_match(symbol, exclusion_regex) + return symbol.empty() + || std::regex_match(symbol, exclusion_regex) || exclusion_set.count(symbol); }