Index: kdevplatform/language/CMakeLists.txt =================================================================== --- kdevplatform/language/CMakeLists.txt +++ kdevplatform/language/CMakeLists.txt @@ -6,6 +6,23 @@ check_include_file("malloc.h" HAVE_MALLOC_H) check_symbol_exists(malloc_trim "malloc.h" HAVE_MALLOC_TRIM) +include(FindPkgConfig) +# find LMDB and lmdbxx +find_path(LMDBXX_INCLUDE_DIRS NAMES "lmdb++.h" HINTS "$ENV{LMDB_DIR}/include") +find_path(LMDB_INCLUDE_DIRS NAMES "lmdb.h" HINTS "$ENV{LMDB_DIR}/include") +find_library(LMDB_LIBRARIES NAMES lmdb HINTS $ENV{LMDB_DIR}/lib) +find_package_handle_standard_args(LMDB DEFAULT_MSG LMDB_INCLUDE_DIRS LMDB_LIBRARIES) +find_package_handle_standard_args(LMDBXX DEFAULT_MSG LMDBXX_INCLUDE_DIRS) +pkg_check_modules(PKG_LZ4 liblz4 REQUIRED) +find_package_handle_standard_args(LZ4 DEFAULT_MSG PKG_LZ4_INCLUDEDIR PKG_LZ4_LIBRARIES) +# # find LevelDB stuff +# find_path(LEVELDB_INCLUDE_DIRS NAMES "leveldb" HINTS "$ENV{LEVELDB_DIR}/include") +# find_library(LEVELDB_LIBRARIES NAMES leveldb HINTS $ENV{LEVELDB_DIR}/lib ) +# find_package_handle_standard_args(LEVELDB DEFAULT_MSG LEVELDB_INCLUDE_DIRS LEVELDB_LIBRARIES) +# find KyotoCabinet stuff +# pkg_check_modules(PKG_KYOTOCABINET kyotocabinet REQUIRED) +# find_package_handle_standard_args(KYOTOCABINET DEFAULT_MSG PKG_KYOTOCABINET_INCLUDEDIR PKG_KYOTOCABINET_LIBRARIES) + if(BUILD_TESTING) add_subdirectory(highlighting/tests) add_subdirectory(duchain/tests) @@ -48,6 +65,7 @@ duchain/localindexeddeclaration.cpp duchain/topducontext.cpp duchain/topducontextdynamicdata.cpp + duchain/topducontextdynamicdata_p.cpp duchain/topducontextutils.cpp duchain/functiondefinition.cpp duchain/declaration.cpp @@ -177,6 +195,10 @@ kdevplatform_add_library(KDevPlatformLanguage SOURCES ${KDevPlatformLanguage_LIB_SRCS}) target_include_directories(KDevPlatformLanguage PRIVATE ${Boost_INCLUDE_DIRS}) +target_include_directories(KDevPlatformLanguage PRIVATE ${LMDB_INCLUDE_DIRS} ${LMDBXX_INCLUDE_DIRS} ${PKG_LZ4_INCLUDEDIR}) +# target_include_directories(KDevPlatformLanguage PRIVATE ${LEVELDB_INCLUDE_DIRS}) +# target_include_directories(KDevPlatformLanguage PRIVATE ${PKG_KYOTOCABINET_INCLUDEDIR}) +kde_source_files_enable_exceptions(duchain/topducontextdynamicdata_p.cpp) target_link_libraries(KDevPlatformLanguage LINK_PUBLIC KF5::ThreadWeaver KDev::Interfaces @@ -191,6 +213,9 @@ KDev::Util KDev::Project ) +target_link_libraries(KDevPlatformLanguage LINK_PRIVATE ${LMDB_LIBRARIES} ${PKG_LZ4_LIBRARIES}) +# target_link_libraries(KDevPlatformLanguage LINK_PRIVATE ${LEVELDB_LIBRARIES}) +# target_link_libraries(KDevPlatformLanguage LINK_PRIVATE ${PKG_KYOTOCABINET_LIBRARIES}) install(FILES assistant/renameaction.h Index: kdevplatform/language/duchain/tests/CMakeLists.txt =================================================================== --- kdevplatform/language/duchain/tests/CMakeLists.txt +++ kdevplatform/language/duchain/tests/CMakeLists.txt @@ -10,6 +10,9 @@ ecm_add_test(test_stringhelpers.cpp LINK_LIBRARIES Qt5::Test KDev::Tests KDev::Language) +ecm_add_test(test_topcontextstore.cpp + LINK_LIBRARIES Qt5::Test KDev::Tests KDev::Language) + if(NOT COMPILER_OPTIMIZATIONS_DISABLED) ecm_add_test(bench_hashes.cpp LINK_LIBRARIES Qt5::Test KDev::Tests KDev::Language) Index: kdevplatform/language/duchain/tests/test_topcontextstore.h =================================================================== --- /dev/null +++ kdevplatform/language/duchain/tests/test_topcontextstore.h @@ -0,0 +1,49 @@ +/* + * This file is part of KDevelop + * + * Copyright 2016 Milian Wolff + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KDEVPLATFORM_TEST_TOPCONTEXTSTORE_H +#define KDEVPLATFORM_TEST_TOPCONTEXTSTORE_H + +#include +#include +#include + +class TestTopDUContextStore : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + void testTopContextStore_data(); + void testTopContextStore(); + + void benchTopContextStore_data(); + void benchTopContextStore(); + void benchTopContextStoreRead(); + void benchTopContextStoreRemove(); + +private: + static uint testKeys; + static uint benchKeys; + QVector benchValues; +}; + +#endif // KDEVPLATFORM_TEST_TOPCONTEXTSTORE_H Index: kdevplatform/language/duchain/tests/test_topcontextstore.cpp =================================================================== --- /dev/null +++ kdevplatform/language/duchain/tests/test_topcontextstore.cpp @@ -0,0 +1,1926 @@ +/* + * This file is part of KDevelop + * + * Copyright 2018 R.J.V. Bertin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// with LMDB, the store is about 1.1x larger than the length of the stored values (but +// our LZ4 compression can reach as much as a 2x reduction in average value size). +// with KyotoCabinet-lzo, the store is about 1.76x smaller than the length of the stored values + +// timing results on Linux 4.14 running on an 1.6Ghz Intel N3150 and ZFSonLinux 0.7.6 + +// KDEV_TOPCONTEXTS_USE_FILES: +// QINFO : TestTopDUContextStore::benchTopContextStore() 6000 items, max length= 38494 from sample of length 38497 +// QINFO : TestTopDUContextStore::benchTopContextStore() total value bytes: 115232709 total key bytes: 24000 +// QINFO : TestTopDUContextStore::benchTopContextStore() Writing 6000 keys (last flushed): 1.583 seconds +// PASS : TestTopDUContextStore::benchTopContextStore() +// QINFO : TestTopDUContextStore::benchTopContextStoreRead() Reading 6000 keys: 0.445 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRead() +// QINFO : TestTopDUContextStore::benchTopContextStoreRemove() Removing 6000 keys: 0.736 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRemove() +// PASS : TestTopDUContextStore::cleanupTestCase() +// Totals: 21 passed, 0 failed, 0 skipped, 0 blacklisted, 3426ms +// ## Idem, with only 1500 keys +// QINFO : TestTopDUContextStore::benchTopContextStore() 1500 items, max length= 38484 from sample of length 38497 +// QINFO : TestTopDUContextStore::benchTopContextStore() total value bytes: 28350833 total key bytes: 6000 +// QINFO : TestTopDUContextStore::benchTopContextStore() Writing 1500 keys (last flushed): 0.351 seconds +// PASS : TestTopDUContextStore::benchTopContextStore() +// QINFO : TestTopDUContextStore::benchTopContextStoreRead() Reading 1500 keys: 0.092 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRead() +// QINFO : TestTopDUContextStore::benchTopContextStoreRemove() Removing 1500 keys: 0.232 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRemove() +// PASS : TestTopDUContextStore::cleanupTestCase() +// Totals: 21 passed, 0 failed, 0 skipped, 0 blacklisted, 1171ms +// ## idem, on NFS: +// QINFO : TestTopDUContextStore::benchTopContextStore() 6000 items, max length= 38488 from sample of length 38497 +// QINFO : TestTopDUContextStore::benchTopContextStore() total value bytes: 115800253 total key bytes: 24000 +// QINFO : TestTopDUContextStore::benchTopContextStore() Writing 6000 keys (last flushed): 108.579 seconds +// PASS : TestTopDUContextStore::benchTopContextStore() +// QINFO : TestTopDUContextStore::benchTopContextStoreRead() Reading 6000 keys: 50.502 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRead() +// QINFO : TestTopDUContextStore::benchTopContextStoreRemove() Removing 6000 keys: 27.651 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRemove() +// PASS : TestTopDUContextStore::cleanupTestCase() +// Totals: 21 passed, 0 failed, 0 skipped, 0 blacklisted, 194162ms +// QINFO : TestTopDUContextStore::benchTopContextStore() 1500 items, max length= 38462 from sample of length 38497 +// QINFO : TestTopDUContextStore::benchTopContextStore() total value bytes: 29375929 total key bytes: 6000 +// QINFO : TestTopDUContextStore::benchTopContextStore() Writing 1500 keys (last flushed): 26.459 seconds +// PASS : TestTopDUContextStore::benchTopContextStore() +// QINFO : TestTopDUContextStore::benchTopContextStoreRead() Reading 1500 keys: 11.778 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRead() +// QINFO : TestTopDUContextStore::benchTopContextStoreRemove() Removing 1500 keys: 6.494 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRemove() +// PASS : TestTopDUContextStore::cleanupTestCase() +// Totals: 21 passed, 0 failed, 0 skipped, 0 blacklisted, 51921ms +// KDEV_TOPCONTEXTS_USE_LMDB: +// QINFO : TestTopDUContextStore::benchTopContextStore() 1500 items, max length= 38436 from sample of length 38497 +// QINFO : TestTopDUContextStore::benchTopContextStore() total value bytes: 29003787 total key bytes: 6000 +// QINFO : TestTopDUContextStore::benchTopContextStore() Writing 1500 keys (last flushed): 7.496 seconds +// PASS : TestTopDUContextStore::benchTopContextStore() +// QINFO : TestTopDUContextStore::benchTopContextStoreRead() Reading 1500 keys: 0.13 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRead() +// QINFO : TestTopDUContextStore::benchTopContextStoreRemove() Removing 1500 keys: 5.556 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRemove() +// PASS : TestTopDUContextStore::cleanupTestCase() +// Totals: 21 passed, 0 failed, 0 skipped, 0 blacklisted, 39789ms +// ## idem, on NFS: +// QINFO : TestTopDUContextStore::benchTopContextStore() 1500 items, max length= 38489 from sample of length 38497 +// QINFO : TestTopDUContextStore::benchTopContextStore() total value bytes: 29405755 total key bytes: 6000 +// QINFO : TestTopDUContextStore::benchTopContextStore() Writing 1500 keys (last flushed): 25.161 seconds +// PASS : TestTopDUContextStore::benchTopContextStore() +// QINFO : TestTopDUContextStore::benchTopContextStoreRead() Reading 1500 keys: 0.102 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRead() +// QINFO : TestTopDUContextStore::benchTopContextStoreRemove() Removing 1500 keys: 21.618 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRemove() +// PASS : TestTopDUContextStore::cleanupTestCase() +// Totals: 21 passed, 0 failed, 0 skipped, 0 blacklisted, 116657ms +// KDEV_TOPCONTEXTS_USE_KYOTO: +// QINFO : TestTopDUContextStore::benchTopContextStore() 1500 items, max length= 38467 from sample of length 38497 +// QINFO : TestTopDUContextStore::benchTopContextStore() total value bytes: 29759286 total key bytes: 6000 +// QINFO : TestTopDUContextStore::benchTopContextStore() Writing 1500 keys (last flushed): 7.891 seconds +// PASS : TestTopDUContextStore::benchTopContextStore() +// QINFO : TestTopDUContextStore::benchTopContextStoreRead() Reading 1500 keys: 6.139 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRead() +// QINFO : TestTopDUContextStore::benchTopContextStoreRemove() Removing 1500 keys: 0.212 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRemove() +// PASS : TestTopDUContextStore::cleanupTestCase() +// Totals: 21 passed, 0 failed, 0 skipped, 0 blacklisted, 37116ms +// ## idem, on NFS: +// QINFO : TestTopDUContextStore::benchTopContextStore() 1500 items, max length= 38468 from sample of length 38497 +// QINFO : TestTopDUContextStore::benchTopContextStore() total value bytes: 28638008 total key bytes: 6000 +// QINFO : TestTopDUContextStore::benchTopContextStore() Writing 1500 keys (last flushed): 27.135 seconds +// PASS : TestTopDUContextStore::benchTopContextStore() +// QINFO : TestTopDUContextStore::benchTopContextStoreRead() Reading 1500 keys: 17.317 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRead() +// QINFO : TestTopDUContextStore::benchTopContextStoreRemove() Removing 1500 keys: 0.218 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRemove() +// PASS : TestTopDUContextStore::cleanupTestCase() +// Totals: 21 passed, 0 failed, 0 skipped, 0 blacklisted, 180553ms + +// ## on a 2.7Ghz i7 running Mac OS X 10.9.5 +// KDEV_TOPCONTEXTS_USE_FILES: +// QINFO : TestTopDUContextStore::benchTopContextStore() 6000 items, max length= 38495 from sample of length 38497 +// QINFO : TestTopDUContextStore::benchTopContextStore() total value bytes: 115547442 total key bytes: 24000 +// QINFO : TestTopDUContextStore::benchTopContextStore() Writing 6000 keys (last flushed): 1.622 seconds +// PASS : TestTopDUContextStore::benchTopContextStore() +// QINFO : TestTopDUContextStore::benchTopContextStoreRead() Reading 6000 keys: 0.13 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRead() +// QINFO : TestTopDUContextStore::benchTopContextStoreRemove() Removing 6000 keys: 0.924 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRemove() +// PASS : TestTopDUContextStore::cleanupTestCase() +// Totals: 21 passed, 0 failed, 0 skipped, 0 blacklisted, 8829ms +// QINFO : TestTopDUContextStore::benchTopContextStore() 1500 items, max length= 38463 from sample of length 38497 +// QINFO : TestTopDUContextStore::benchTopContextStore() total value bytes: 28304777 total key bytes: 6000 +// QINFO : TestTopDUContextStore::benchTopContextStore() Writing 1500 keys (last flushed): 0.299 seconds +// PASS : TestTopDUContextStore::benchTopContextStore() +// QINFO : TestTopDUContextStore::benchTopContextStoreRead() Reading 1500 keys: 0.032 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRead() +// QINFO : TestTopDUContextStore::benchTopContextStoreRemove() Removing 1500 keys: 0.208 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRemove() +// PASS : TestTopDUContextStore::cleanupTestCase() +// Totals: 21 passed, 0 failed, 0 skipped, 0 blacklisted, 3508ms +// KDEV_TOPCONTEXTS_USE_LMDB: +// QINFO : TestTopDUContextStore::benchTopContextStore() 1500 items, max length= 38478 from sample of length 38497 +// QINFO : TestTopDUContextStore::benchTopContextStore() total value bytes: 29783345 total key bytes: 6000 +// QINFO : TestTopDUContextStore::benchTopContextStore() Writing 1500 keys (last flushed): 4.653 seconds +// PASS : TestTopDUContextStore::benchTopContextStore() +// QINFO : TestTopDUContextStore::benchTopContextStoreRead() Reading 1500 keys: 0.025 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRead() +// QINFO : TestTopDUContextStore::benchTopContextStoreRemove() Removing 1500 keys: 7.234 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRemove() +// PASS : TestTopDUContextStore::cleanupTestCase() +// Totals: 21 passed, 0 failed, 0 skipped, 0 blacklisted, 18791ms +// KDEV_TOPCONTEXTS_USE_KYOTO: +// QINFO : TestTopDUContextStore::benchTopContextStore() 1500 items, max length= 38492 from sample of length 38497 +// QINFO : TestTopDUContextStore::benchTopContextStore() total value bytes: 28963844 total key bytes: 6000 +// QINFO : TestTopDUContextStore::benchTopContextStore() Writing 1500 keys (last flushed): 22.364 seconds +// PASS : TestTopDUContextStore::benchTopContextStore() +// QINFO : TestTopDUContextStore::benchTopContextStoreRead() Reading 1500 keys: 3.267 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRead() +// QINFO : TestTopDUContextStore::benchTopContextStoreRemove() Removing 1500 keys: 0.052 seconds +// PASS : TestTopDUContextStore::benchTopContextStoreRemove() +// PASS : TestTopDUContextStore::cleanupTestCase() +// Totals: 21 passed, 0 failed, 0 skipped, 0 blacklisted, 38792ms + + +#include "test_topcontextstore.h" + +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +QTEST_MAIN(TestTopDUContextStore) + +using namespace KDevelop; + +uint TestTopDUContextStore::testKeys = 16; +uint TestTopDUContextStore::benchKeys = 1500; + +static QString basePath() +{ + return globalItemRepositoryRegistry().path() + "/topcontexts/"; +} + +void TestTopDUContextStore::initTestCase() +{ + AutoTestShell::init(); + TestCore::initialize(Core::NoUi); + + DUChain::self()->disablePersistentStorage(); + CodeRepresentation::setDiskChangesForbidden(true); + QDir().mkpath(basePath()); +} + +void TestTopDUContextStore::cleanupTestCase() +{ + TestCore::shutdown(); +} + +extern unsigned char realDUData[]; +extern double realDUDataSize; + +void TestTopDUContextStore::testTopContextStore_data() +{ + QTest::addColumn("key"); + QTest::addColumn("value"); + QTest::addColumn("size"); + + for (uint i = 0 ; i < benchKeys ; ++i) { + TopDUContextStore writer(i); + QByteArray data; + uint size; + if (i == 0) { + // 1st key/value pair will use the stored real data so that we can + // test our own LZ4 compression scheme in the LMDB backend (random + // values won't compress). + size = realDUDataSize; + data.setRawData(reinterpret_cast(realDUData), size); + } else { + size = qrand() * 32767.0 / RAND_MAX; + data.resize(size); + char *d = data.data(); + for (uint j = 0 ; j < size ; ++j) { + d[j] = qrand() * 256.0 / RAND_MAX; + } + } + if (i < testKeys) { + // we store all keys that will be used in the benchmark so the store will be primed + // but only do write/read/exists/remove verifications for the requested number of items. + QTest::newRow("keyval") << i << data << data.size(); + } + if (writer.open(QIODevice::WriteOnly)) { + writer.write(data.constData(), data.size()); + writer.commit(); + const auto errString = writer.errorString(); + if (!errString.isEmpty() && errString != "Unknown error") { + qCritical() << "Failed to write entry for key" << i << "to" << writer.fileName() << ":" << writer.errorString(); + } else { + QVERIFY(writer.flush()); + } + } else { + qCritical() << "Failed to open" << writer.fileName(); + } + } + sync(); +} + +void TestTopDUContextStore::testTopContextStore() +{ + QFETCH(uint, key); + QFETCH(QByteArray, value); + QFETCH(int, size); + + TopDUContextStore reader(key); + QByteArray testval; + if (reader.open(QIODevice::ReadOnly)) { + testval = reader.readAll(); + if (testval.isEmpty() && !reader.errorString().isEmpty()) { + qCritical() << "Failed to read entry for key" << key << "from" << reader.fileName() << ":" << reader.errorString(); + } + } else { + qCritical() << "Failed to open" << reader.fileName(); + } + QCOMPARE(testval.size(), size); + QCOMPARE(testval, value); + QVERIFY(TopDUContextStore::exists(key)); + QVERIFY(TopDUContextStore::remove(key)); + QVERIFY(!TopDUContextStore::exists(key)); +} + +void TestTopDUContextStore::benchTopContextStore_data() +{ + uint maxSize = 0, totalSize = 0; + benchValues.reserve(benchKeys); + // subsample random strings from the real topcontext data + // (always from the left, there should be no interest to + // randomising the offset). + for (uint i = 0 ; i < benchKeys ; ++i) { + uint size = qrand() * realDUDataSize / RAND_MAX; + if (size > maxSize) { + maxSize = size; + } + QByteArray data(reinterpret_cast(realDUData), size); + benchValues.append(data); + totalSize += size; + if (i >= testKeys) { + // remove keys that weren't removed in testTopContextStore() + // so we will time writing, not overwriting + TopDUContextStore::remove(i); + } + } + sync(); + sleep(1); + qInfo() << benchValues.size() << "items, max length=" << maxSize << "from sample of length" << realDUDataSize; + qInfo() << "\ttotal value bytes:" << totalSize << "total key bytes:" << benchKeys * sizeof(uint); +} + +// benchmarks don't use QBENCHMARK because they're not suitable for being +// called multiple times. +void TestTopDUContextStore::benchTopContextStore() +{ + QElapsedTimer timer; + timer.start(); + for (uint i = 0 ; i < benchKeys ; ++i) { + TopDUContextStore writer(i); + if (writer.open(QIODevice::WriteOnly)) { + QByteArray data = benchValues.at(i); + writer.write(data.constData(), data.size()); + writer.commit(); + if (i == benchKeys - 1) { + writer.flush(); + } + } + } + qInfo() << "Writing" << benchKeys << "keys (last flushed):" << timer.elapsed() / 1000.0 << "seconds"; +} + +#include +void TestTopDUContextStore::benchTopContextStoreRead() +{ + QElapsedTimer timer; + timer.start(); + for (uint i = 0 ; i < benchKeys ; ++i) + { + TopDUContextStore reader(i); + if (reader.open(QIODevice::ReadOnly)) { +#if defined(KDEV_TOPCONTEXTS_USE_FILES) && !defined(KDEV_TOPCONTEXTS_DONT_MMAP) + uchar* data = reader.map(0, reader.size()); + reader.commit(); +#else + QByteArray data = reader.readAll(); +#endif + } + } + qInfo() << "Reading" << benchKeys << "keys:" << timer.elapsed() / 1000.0 << "seconds"; +} + +void TestTopDUContextStore::benchTopContextStoreRemove() +{ + QElapsedTimer timer; + timer.start(); + for (uint i = 0 ; i < benchKeys ; ++i) + { + TopDUContextStore::remove(i); + } + qInfo() << "Removing" << benchKeys << "keys:" << timer.elapsed() / 1000.0 << "seconds"; +} + +// this is actual TopDUContext data from KDevelop itself +unsigned char realDUData[] = {64, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 127, 255, 255, 255, 127, +64, 64, 140, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 127, 0, 0, 0, 1, +0, 0, 0, 148, 0, 0, 0, 7, 0, 0, 0, 0, 65, 30, 0, 46, 186, 10, 0, 59, 23, 0, 0, +128, 129, 19, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 167, 0, 0, 0, 0, 0, 0, 0, +2, 0, 1, 0, 0, 0, 0, 0, 0, 64, 64, 64, 0, 0, 0, 0, 200, 21, 0, 0, 0, 0, 0, 0, 1, +0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, +8, 0, 0, 0, 9, 0, 0, 0, 10, 0, 0, 0, 61, 0, 0, 0, 62, 0, 0, 0, 63, 0, 0, 0, 64, +0, 0, 0, 65, 0, 0, 0, 11, 0, 0, 0, 12, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 15, 0, +0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, 19, 0, 0, 0, 20, 0, 0, 0, 21, 0, 0, +0, 22, 0, 0, 0, 23, 0, 0, 0, 24, 0, 0, 0, 25, 0, 0, 0, 26, 0, 0, 0, 27, 0, 0, 0, +28, 0, 0, 0, 29, 0, 0, 0, 30, 0, 0, 0, 31, 0, 0, 0, 32, 0, 0, 0, 33, 0, 0, 0, +34, 0, 0, 0, 35, 0, 0, 0, 36, 0, 0, 0, 66, 0, 0, 0, 67, 0, 0, 0, 37, 0, 0, 0, +38, 0, 0, 0, 39, 0, 0, 0, 40, 0, 0, 0, 41, 0, 0, 0, 42, 0, 0, 0, 43, 0, 0, 0, +44, 0, 0, 0, 45, 0, 0, 0, 46, 0, 0, 0, 47, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, +50, 0, 0, 0, 51, 0, 0, 0, 52, 0, 0, 0, 53, 0, 0, 0, 54, 0, 0, 0, 55, 0, 0, 0, +56, 0, 0, 0, 57, 0, 0, 0, 58, 0, 0, 0, 68, 0, 0, 0, 69, 0, 0, 0, 70, 0, 0, 0, +71, 0, 0, 0, 72, 0, 0, 0, 73, 0, 0, 0, 74, 0, 0, 0, 75, 0, 0, 0, 76, 0, 0, 0, +77, 0, 0, 0, 78, 0, 0, 0, 79, 0, 0, 0, 80, 0, 0, 0, 81, 0, 0, 0, 82, 0, 0, 0, +83, 0, 0, 0, 84, 0, 0, 0, 85, 0, 0, 0, 86, 0, 0, 0, 87, 0, 0, 0, 88, 0, 0, 0, +89, 0, 0, 0, 90, 0, 0, 0, 91, 0, 0, 0, 92, 0, 0, 0, 93, 0, 0, 0, 94, 0, 0, 0, +95, 0, 0, 0, 96, 0, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99, 0, 0, 0, 100, 0, 0, 0, +101, 0, 0, 0, 102, 0, 0, 0, 59, 0, 0, 0, 60, 0, 0, 0, 103, 0, 0, 0, 104, 0, 0, +0, 105, 0, 0, 0, 106, 0, 0, 0, 107, 0, 0, 0, 108, 0, 0, 0, 109, 0, 0, 0, 110, 0, +0, 0, 111, 0, 0, 0, 112, 0, 0, 0, 113, 0, 0, 0, 114, 0, 0, 0, 115, 0, 0, 0, 116, +0, 0, 0, 117, 0, 0, 0, 118, 0, 0, 0, 119, 0, 0, 0, 120, 0, 0, 0, 121, 0, 0, 0, +122, 0, 0, 0, 123, 0, 0, 0, 124, 0, 0, 0, 125, 0, 0, 0, 126, 0, 0, 0, 127, 0, 0, +0, 64, 23, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 61, 0, 0, 0, 62, 0, 0, 0, 2, 0, 0, 0, +3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 8, 0, 0, 0, 9, 0, 0, +0, 10, 0, 0, 0, 64, 0, 0, 0, 66, 0, 0, 0, 67, 0, 0, 0, 69, 0, 0, 0, 70, 0, 0, 0, +74, 0, 0, 0, 73, 0, 0, 0, 77, 0, 0, 0, 78, 0, 0, 0, 79, 0, 0, 0, 80, 0, 0, 0, +81, 0, 0, 0, 82, 0, 0, 0, 83, 0, 0, 0, 84, 0, 0, 0, 11, 0, 0, 0, 12, 0, 0, 0, +13, 0, 0, 0, 14, 0, 0, 0, 15, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, +19, 0, 0, 0, 20, 0, 0, 0, 21, 0, 0, 0, 22, 0, 0, 0, 23, 0, 0, 0, 24, 0, 0, 0, +25, 0, 0, 0, 26, 0, 0, 0, 27, 0, 0, 0, 28, 0, 0, 0, 29, 0, 0, 0, 30, 0, 0, 0, +31, 0, 0, 0, 32, 0, 0, 0, 33, 0, 0, 0, 34, 0, 0, 0, 35, 0, 0, 0, 36, 0, 0, 0, +85, 0, 0, 0, 106, 0, 0, 0, 105, 0, 0, 0, 37, 0, 0, 0, 38, 0, 0, 0, 39, 0, 0, 0, +40, 0, 0, 0, 41, 0, 0, 0, 42, 0, 0, 0, 43, 0, 0, 0, 44, 0, 0, 0, 45, 0, 0, 0, +46, 0, 0, 0, 47, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, 50, 0, 0, 0, 51, 0, 0, 0, +52, 0, 0, 0, 53, 0, 0, 0, 54, 0, 0, 0, 55, 0, 0, 0, 56, 0, 0, 0, 57, 0, 0, 0, +58, 0, 0, 0, 126, 0, 0, 0, 134, 0, 0, 0, 133, 0, 0, 0, 141, 0, 0, 0, 149, 0, 0, +0, 148, 0, 0, 0, 156, 0, 0, 0, 160, 0, 0, 0, 162, 0, 0, 0, 164, 0, 0, 0, 169, 0, +0, 0, 172, 0, 0, 0, 175, 0, 0, 0, 179, 0, 0, 0, 183, 0, 0, 0, 186, 0, 0, 0, 189, +0, 0, 0, 192, 0, 0, 0, 194, 0, 0, 0, 198, 0, 0, 0, 201, 0, 0, 0, 204, 0, 0, 0, +207, 0, 0, 0, 210, 0, 0, 0, 213, 0, 0, 0, 216, 0, 0, 0, 219, 0, 0, 0, 221, 0, 0, +0, 224, 0, 0, 0, 226, 0, 0, 0, 227, 0, 0, 0, 228, 0, 0, 0, 229, 0, 0, 0, 232, 0, +0, 0, 237, 0, 0, 0, 239, 0, 0, 0, 241, 0, 0, 0, 243, 0, 0, 0, 245, 0, 0, 0, 247, +0, 0, 0, 59, 0, 0, 0, 60, 0, 0, 0, 249, 0, 0, 0, 254, 0, 0, 0, 2, 1, 0, 0, 6, 1, +0, 0, 9, 1, 0, 0, 13, 1, 0, 0, 17, 1, 0, 0, 21, 1, 0, 0, 25, 1, 0, 0, 29, 1, 0, +0, 34, 1, 0, 0, 40, 1, 0, 0, 45, 1, 0, 0, 49, 1, 0, 0, 51, 1, 0, 0, 54, 1, 0, 0, +56, 1, 0, 0, 58, 1, 0, 0, 63, 1, 0, 0, 68, 1, 0, 0, 71, 1, 0, 0, 74, 1, 0, 0, +79, 1, 0, 0, 84, 1, 0, 0, 85, 1, 0, 0, 86, 1, 0, 0, 87, 1, 0, 0, 91, 1, 0, 0, +230, 0, 0, 0, 15, 0, 0, 0, 230, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, +15, 0, 0, 0, 237, 0, 0, 0, 22, 0, 0, 0, 1, 0, 0, 0, 243, 0, 0, 0, 15, 0, 0, 0, +243, 0, 0, 0, 25, 0, 0, 0, 4, 0, 0, 0, 6, 1, 0, 0, 34, 0, 0, 0, 6, 1, 0, 0, 41, +0, 0, 0, 3, 0, 0, 0, 6, 1, 0, 0, 52, 0, 0, 0, 6, 1, 0, 0, 59, 0, 0, 0, 3, 0, 0, +0, 22, 1, 0, 0, 28, 0, 0, 0, 22, 1, 0, 0, 35, 0, 0, 0, 3, 0, 0, 0, 159, 3, 0, 0, +29, 0, 0, 0, 159, 3, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 6, 167, 13, 0, 0, 0, 0, 0, +0, 64, 64, 64, 0, 0, 0, 0, 28, 167, 13, 0, 0, 0, 0, 0, 0, 64, 64, 64, 0, 0, 0, +0, 150, 167, 13, 0, 0, 0, 0, 0, 0, 64, 64, 64, 0, 0, 0, 0, 64, 168, 13, 0, 0, 0, +0, 0, 0, 64, 64, 64, 0, 0, 0, 0, 172, 167, 13, 0, 0, 0, 0, 0, 0, 64, 64, 64, 0, +0, 0, 0, 36, 169, 13, 0, 0, 0, 0, 0, 0, 64, 64, 64, 0, 0, 0, 0, 136, 94, 1, 0, +0, 0, 0, 0, 0, 64, 64, 64, 0, 0, 0, 0, 182, 168, 13, 0, 0, 0, 0, 0, 0, 64, 64, +64, 0, 0, 0, 0, 40, 171, 13, 0, 0, 0, 0, 0, 0, 64, 64, 64, 0, 0, 0, 0, 240, 166, +13, 0, 0, 0, 0, 0, 0, 64, 64, 64, 0, 0, 0, 0, 218, 166, 13, 0, 0, 0, 0, 0, 0, +64, 64, 64, 0, 0, 0, 0, 138, 168, 13, 0, 0, 0, 0, 0, 0, 64, 64, 64, 0, 0, 0, 0, +246, 177, 13, 0, 0, 0, 0, 0, 0, 64, 64, 64, 0, 0, 0, 0, 218, 171, 13, 0, 0, 0, +0, 0, 0, 64, 64, 64, 0, 0, 0, 0, 134, 174, 13, 0, 0, 0, 0, 0, 0, 64, 64, 64, 0, +0, 0, 0, 127, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 113, 0, +0, 0, 0, 0, 0, 0, 169, 0, 0, 0, 0, 0, 0, 0, 225, 0, 0, 0, 0, 0, 0, 0, 25, 1, 0, +0, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 0, 0, 137, 1, 0, 0, 0, 0, 0, 0, 193, 1, 0, 0, +0, 0, 0, 0, 249, 1, 0, 0, 0, 0, 0, 0, 49, 2, 0, 0, 0, 0, 0, 0, 105, 2, 0, 0, 0, +0, 0, 0, 161, 2, 0, 0, 0, 0, 0, 0, 217, 2, 0, 0, 0, 0, 0, 0, 17, 3, 0, 0, 0, 0, +0, 0, 73, 3, 0, 0, 0, 0, 0, 0, 129, 3, 0, 0, 0, 0, 0, 0, 185, 3, 0, 0, 0, 0, 0, +0, 241, 3, 0, 0, 0, 0, 0, 0, 41, 4, 0, 0, 0, 0, 0, 0, 97, 4, 0, 0, 0, 0, 0, 0, +153, 4, 0, 0, 0, 0, 0, 0, 209, 4, 0, 0, 0, 0, 0, 0, 9, 5, 0, 0, 0, 0, 0, 0, 65, +5, 0, 0, 0, 0, 0, 0, 121, 5, 0, 0, 0, 0, 0, 0, 177, 5, 0, 0, 0, 0, 0, 0, 233, 5, +0, 0, 0, 0, 0, 0, 33, 6, 0, 0, 0, 0, 0, 0, 89, 6, 0, 0, 0, 0, 0, 0, 145, 6, 0, +0, 0, 0, 0, 0, 201, 6, 0, 0, 0, 0, 0, 0, 1, 7, 0, 0, 0, 0, 0, 0, 57, 7, 0, 0, 0, +0, 0, 0, 113, 7, 0, 0, 0, 0, 0, 0, 169, 7, 0, 0, 0, 0, 0, 0, 225, 7, 0, 0, 0, 0, +0, 0, 25, 8, 0, 0, 0, 0, 0, 0, 81, 8, 0, 0, 0, 0, 0, 0, 137, 8, 0, 0, 0, 0, 0, +0, 193, 8, 0, 0, 0, 0, 0, 0, 249, 8, 0, 0, 0, 0, 0, 0, 49, 9, 0, 0, 0, 0, 0, 0, +105, 9, 0, 0, 0, 0, 0, 0, 161, 9, 0, 0, 0, 0, 0, 0, 217, 9, 0, 0, 0, 0, 0, 0, +17, 10, 0, 0, 0, 0, 0, 0, 73, 10, 0, 0, 0, 0, 0, 0, 129, 10, 0, 0, 0, 0, 0, 0, +185, 10, 0, 0, 0, 0, 0, 0, 241, 10, 0, 0, 0, 0, 0, 0, 41, 11, 0, 0, 0, 0, 0, 0, +97, 11, 0, 0, 0, 0, 0, 0, 153, 11, 0, 0, 0, 0, 0, 0, 209, 11, 0, 0, 0, 0, 0, 0, +9, 12, 0, 0, 0, 0, 0, 0, 65, 12, 0, 0, 0, 0, 0, 0, 121, 12, 0, 0, 0, 0, 0, 0, +177, 12, 0, 0, 0, 0, 0, 0, 233, 12, 0, 0, 0, 0, 0, 0, 33, 13, 0, 0, 0, 0, 0, 0, +93, 13, 0, 0, 0, 0, 0, 0, 153, 13, 0, 0, 0, 0, 0, 0, 213, 13, 0, 0, 0, 0, 0, 0, +41, 14, 0, 0, 0, 0, 0, 0, 125, 14, 0, 0, 0, 0, 0, 0, 1, 15, 0, 0, 0, 0, 0, 0, +133, 15, 0, 0, 0, 0, 0, 0, 37, 16, 0, 0, 0, 0, 0, 0, 197, 16, 0, 0, 0, 0, 0, 0, +81, 17, 0, 0, 0, 0, 0, 0, 221, 17, 0, 0, 0, 0, 0, 0, 33, 18, 0, 0, 0, 0, 0, 0, +93, 18, 0, 0, 0, 0, 0, 0, 173, 18, 0, 0, 0, 0, 0, 0, 29, 19, 0, 0, 0, 0, 0, 0, +113, 19, 0, 0, 0, 0, 0, 0, 217, 19, 0, 0, 0, 0, 0, 0, 49, 20, 0, 0, 0, 0, 0, 0, +157, 20, 0, 0, 0, 0, 0, 0, 5, 21, 0, 0, 0, 0, 0, 0, 109, 21, 0, 0, 0, 0, 0, 0, +193, 21, 0, 0, 0, 0, 0, 0, 17, 22, 0, 0, 0, 0, 0, 0, 105, 22, 0, 0, 0, 0, 0, 0, +189, 22, 0, 0, 0, 0, 0, 0, 17, 23, 0, 0, 0, 0, 0, 0, 121, 23, 0, 0, 0, 0, 0, 0, +225, 23, 0, 0, 0, 0, 0, 0, 53, 24, 0, 0, 0, 0, 0, 0, 137, 24, 0, 0, 0, 0, 0, 0, +241, 24, 0, 0, 0, 0, 0, 0, 65, 25, 0, 0, 0, 0, 0, 0, 149, 25, 0, 0, 0, 0, 0, 0, +229, 25, 0, 0, 0, 0, 0, 0, 77, 26, 0, 0, 0, 0, 0, 0, 209, 26, 0, 0, 0, 0, 0, 0, +53, 27, 0, 0, 0, 0, 0, 0, 153, 27, 0, 0, 0, 0, 0, 0, 233, 27, 0, 0, 0, 0, 0, 0, +57, 28, 0, 0, 0, 0, 0, 0, 137, 28, 0, 0, 0, 0, 0, 0, 217, 28, 0, 0, 0, 0, 0, 0, +73, 29, 0, 0, 0, 0, 0, 0, 201, 29, 0, 0, 0, 0, 0, 0, 53, 30, 0, 0, 0, 0, 0, 0, +157, 30, 0, 0, 0, 0, 0, 0, 9, 31, 0, 0, 0, 0, 0, 0, 137, 31, 0, 0, 0, 0, 0, 0, +9, 32, 0, 0, 0, 0, 0, 0, 137, 32, 0, 0, 0, 0, 0, 0, 245, 32, 0, 0, 0, 0, 0, 0, +141, 33, 0, 0, 0, 0, 0, 0, 41, 34, 0, 0, 0, 0, 0, 0, 193, 34, 0, 0, 0, 0, 0, 0, +65, 35, 0, 0, 0, 0, 0, 0, 145, 35, 0, 0, 0, 0, 0, 0, 249, 35, 0, 0, 0, 0, 0, 0, +93, 36, 0, 0, 0, 0, 0, 0, 193, 36, 0, 0, 0, 0, 0, 0, 89, 37, 0, 0, 0, 0, 0, 0, +221, 37, 0, 0, 0, 0, 0, 0, 49, 38, 0, 0, 0, 0, 0, 0, 153, 38, 0, 0, 0, 0, 0, 0, +49, 39, 0, 0, 0, 0, 0, 0, 201, 39, 0, 0, 0, 0, 0, 0, 53, 40, 0, 0, 0, 0, 0, 0, +93, 1, 0, 0, 137, 40, 0, 0, 0, 0, 0, 0, 209, 40, 0, 0, 0, 0, 0, 0, 25, 41, 0, 0, +0, 0, 0, 0, 97, 41, 0, 0, 0, 0, 0, 0, 169, 41, 0, 0, 0, 0, 0, 0, 253, 41, 0, 0, +0, 0, 0, 0, 69, 42, 0, 0, 0, 0, 0, 0, 141, 42, 0, 0, 0, 0, 0, 0, 229, 42, 0, 0, +0, 0, 0, 0, 61, 43, 0, 0, 0, 0, 0, 0, 133, 43, 0, 0, 0, 0, 0, 0, 205, 43, 0, 0, +0, 0, 0, 0, 21, 44, 0, 0, 0, 0, 0, 0, 93, 44, 0, 0, 0, 0, 0, 0, 165, 44, 0, 0, +0, 0, 0, 0, 237, 44, 0, 0, 0, 0, 0, 0, 53, 45, 0, 0, 0, 0, 0, 0, 125, 45, 0, 0, +0, 0, 0, 0, 197, 45, 0, 0, 0, 0, 0, 0, 13, 46, 0, 0, 0, 0, 0, 0, 85, 46, 0, 0, +0, 0, 0, 0, 157, 46, 0, 0, 0, 0, 0, 0, 229, 46, 0, 0, 0, 0, 0, 0, 45, 47, 0, 0, +0, 0, 0, 0, 117, 47, 0, 0, 0, 0, 0, 0, 189, 47, 0, 0, 0, 0, 0, 0, 5, 48, 0, 0, +0, 0, 0, 0, 77, 48, 0, 0, 0, 0, 0, 0, 149, 48, 0, 0, 0, 0, 0, 0, 221, 48, 0, 0, +0, 0, 0, 0, 37, 49, 0, 0, 0, 0, 0, 0, 109, 49, 0, 0, 0, 0, 0, 0, 181, 49, 0, 0, +0, 0, 0, 0, 253, 49, 0, 0, 0, 0, 0, 0, 69, 50, 0, 0, 0, 0, 0, 0, 141, 50, 0, 0, +0, 0, 0, 0, 213, 50, 0, 0, 0, 0, 0, 0, 29, 51, 0, 0, 0, 0, 0, 0, 101, 51, 0, 0, +0, 0, 0, 0, 173, 51, 0, 0, 0, 0, 0, 0, 245, 51, 0, 0, 0, 0, 0, 0, 61, 52, 0, 0, +0, 0, 0, 0, 133, 52, 0, 0, 0, 0, 0, 0, 205, 52, 0, 0, 0, 0, 0, 0, 21, 53, 0, 0, +0, 0, 0, 0, 93, 53, 0, 0, 0, 0, 0, 0, 165, 53, 0, 0, 0, 0, 0, 0, 237, 53, 0, 0, +0, 0, 0, 0, 53, 54, 0, 0, 0, 0, 0, 0, 125, 54, 0, 0, 0, 0, 0, 0, 197, 54, 0, 0, +0, 0, 0, 0, 13, 55, 0, 0, 0, 0, 0, 0, 85, 55, 0, 0, 0, 0, 0, 0, 157, 55, 0, 0, +0, 0, 0, 0, 229, 55, 0, 0, 0, 0, 0, 0, 45, 56, 0, 0, 0, 0, 0, 0, 117, 56, 0, 0, +0, 0, 0, 0, 189, 56, 0, 0, 0, 0, 0, 0, 5, 57, 0, 0, 0, 0, 0, 0, 93, 57, 0, 0, 0, +0, 0, 0, 173, 57, 0, 0, 0, 0, 0, 0, 233, 57, 0, 0, 0, 0, 0, 0, 37, 58, 0, 0, 61, +0, 0, 0, 97, 58, 0, 0, 0, 0, 0, 0, 157, 58, 0, 0, 62, 0, 0, 0, 217, 58, 0, 0, 0, +0, 0, 0, 21, 59, 0, 0, 0, 0, 0, 0, 81, 59, 0, 0, 63, 0, 0, 0, 141, 59, 0, 0, 0, +0, 0, 0, 201, 59, 0, 0, 0, 0, 0, 0, 17, 60, 0, 0, 64, 0, 0, 0, 77, 60, 0, 0, 64, +0, 0, 0, 137, 60, 0, 0, 0, 0, 0, 0, 197, 60, 0, 0, 0, 0, 0, 0, 13, 61, 0, 0, 65, +0, 0, 0, 73, 61, 0, 0, 65, 0, 0, 0, 133, 61, 0, 0, 0, 0, 0, 0, 193, 61, 0, 0, 0, +0, 0, 0, 253, 61, 0, 0, 0, 0, 0, 0, 57, 62, 0, 0, 0, 0, 0, 0, 117, 62, 0, 0, 0, +0, 0, 0, 177, 62, 0, 0, 0, 0, 0, 0, 237, 62, 0, 0, 0, 0, 0, 0, 41, 63, 0, 0, 0, +0, 0, 0, 101, 63, 0, 0, 0, 0, 0, 0, 161, 63, 0, 0, 66, 0, 0, 0, 221, 63, 0, 0, +66, 0, 0, 0, 25, 64, 0, 0, 66, 0, 0, 0, 85, 64, 0, 0, 66, 0, 0, 0, 145, 64, 0, +0, 66, 0, 0, 0, 205, 64, 0, 0, 66, 0, 0, 0, 9, 65, 0, 0, 66, 0, 0, 0, 69, 65, 0, +0, 66, 0, 0, 0, 129, 65, 0, 0, 66, 0, 0, 0, 189, 65, 0, 0, 66, 0, 0, 0, 249, 65, +0, 0, 66, 0, 0, 0, 53, 66, 0, 0, 66, 0, 0, 0, 113, 66, 0, 0, 66, 0, 0, 0, 173, +66, 0, 0, 66, 0, 0, 0, 233, 66, 0, 0, 66, 0, 0, 0, 37, 67, 0, 0, 66, 0, 0, 0, +97, 67, 0, 0, 66, 0, 0, 0, 157, 67, 0, 0, 66, 0, 0, 0, 217, 67, 0, 0, 66, 0, 0, +0, 21, 68, 0, 0, 0, 0, 0, 0, 81, 68, 0, 0, 0, 0, 0, 0, 141, 68, 0, 0, 67, 0, 0, +0, 201, 68, 0, 0, 67, 0, 0, 0, 5, 69, 0, 0, 67, 0, 0, 0, 65, 69, 0, 0, 67, 0, 0, +0, 125, 69, 0, 0, 67, 0, 0, 0, 185, 69, 0, 0, 67, 0, 0, 0, 245, 69, 0, 0, 67, 0, +0, 0, 49, 70, 0, 0, 67, 0, 0, 0, 109, 70, 0, 0, 67, 0, 0, 0, 169, 70, 0, 0, 67, +0, 0, 0, 229, 70, 0, 0, 67, 0, 0, 0, 33, 71, 0, 0, 67, 0, 0, 0, 93, 71, 0, 0, +67, 0, 0, 0, 153, 71, 0, 0, 67, 0, 0, 0, 213, 71, 0, 0, 67, 0, 0, 0, 17, 72, 0, +0, 67, 0, 0, 0, 77, 72, 0, 0, 67, 0, 0, 0, 137, 72, 0, 0, 67, 0, 0, 0, 197, 72, +0, 0, 67, 0, 0, 0, 1, 73, 0, 0, 0, 0, 0, 0, 73, 73, 0, 0, 68, 0, 0, 0, 133, 73, +0, 0, 68, 0, 0, 0, 193, 73, 0, 0, 68, 0, 0, 0, 253, 73, 0, 0, 68, 0, 0, 0, 57, +74, 0, 0, 68, 0, 0, 0, 117, 74, 0, 0, 68, 0, 0, 0, 177, 74, 0, 0, 0, 0, 0, 0, +237, 74, 0, 0, 0, 0, 0, 0, 53, 75, 0, 0, 69, 0, 0, 0, 113, 75, 0, 0, 69, 0, 0, +0, 173, 75, 0, 0, 69, 0, 0, 0, 233, 75, 0, 0, 69, 0, 0, 0, 37, 76, 0, 0, 69, 0, +0, 0, 97, 76, 0, 0, 69, 0, 0, 0, 157, 76, 0, 0, 0, 0, 0, 0, 229, 76, 0, 0, 70, +0, 0, 0, 33, 77, 0, 0, 70, 0, 0, 0, 93, 77, 0, 0, 70, 0, 0, 0, 153, 77, 0, 0, +70, 0, 0, 0, 213, 77, 0, 0, 70, 0, 0, 0, 17, 78, 0, 0, 70, 0, 0, 0, 77, 78, 0, +0, 0, 0, 0, 0, 137, 78, 0, 0, 0, 0, 0, 0, 209, 78, 0, 0, 71, 0, 0, 0, 13, 79, 0, +0, 71, 0, 0, 0, 73, 79, 0, 0, 71, 0, 0, 0, 133, 79, 0, 0, 71, 0, 0, 0, 193, 79, +0, 0, 71, 0, 0, 0, 253, 79, 0, 0, 71, 0, 0, 0, 57, 80, 0, 0, 0, 0, 0, 0, 133, +80, 0, 0, 72, 0, 0, 0, 193, 80, 0, 0, 72, 0, 0, 0, 253, 80, 0, 0, 72, 0, 0, 0, +57, 81, 0, 0, 0, 0, 0, 0, 133, 81, 0, 0, 73, 0, 0, 0, 193, 81, 0, 0, 0, 0, 0, 0, +13, 82, 0, 0, 74, 0, 0, 0, 73, 82, 0, 0, 0, 0, 0, 0, 149, 82, 0, 0, 75, 0, 0, 0, +209, 82, 0, 0, 75, 0, 0, 0, 13, 83, 0, 0, 75, 0, 0, 0, 73, 83, 0, 0, 75, 0, 0, +0, 133, 83, 0, 0, 0, 0, 0, 0, 209, 83, 0, 0, 76, 0, 0, 0, 13, 84, 0, 0, 76, 0, +0, 0, 73, 84, 0, 0, 0, 0, 0, 0, 149, 84, 0, 0, 77, 0, 0, 0, 209, 84, 0, 0, 77, +0, 0, 0, 13, 85, 0, 0, 0, 0, 0, 0, 89, 85, 0, 0, 78, 0, 0, 0, 149, 85, 0, 0, 78, +0, 0, 0, 209, 85, 0, 0, 78, 0, 0, 0, 13, 86, 0, 0, 0, 0, 0, 0, 89, 86, 0, 0, 79, +0, 0, 0, 149, 86, 0, 0, 79, 0, 0, 0, 209, 86, 0, 0, 79, 0, 0, 0, 13, 87, 0, 0, +0, 0, 0, 0, 89, 87, 0, 0, 80, 0, 0, 0, 149, 87, 0, 0, 80, 0, 0, 0, 209, 87, 0, +0, 0, 0, 0, 0, 29, 88, 0, 0, 81, 0, 0, 0, 89, 88, 0, 0, 81, 0, 0, 0, 149, 88, 0, +0, 0, 0, 0, 0, 225, 88, 0, 0, 82, 0, 0, 0, 29, 89, 0, 0, 82, 0, 0, 0, 89, 89, 0, +0, 0, 0, 0, 0, 165, 89, 0, 0, 83, 0, 0, 0, 225, 89, 0, 0, 0, 0, 0, 0, 45, 90, 0, +0, 84, 0, 0, 0, 105, 90, 0, 0, 84, 0, 0, 0, 165, 90, 0, 0, 84, 0, 0, 0, 225, 90, +0, 0, 0, 0, 0, 0, 45, 91, 0, 0, 85, 0, 0, 0, 105, 91, 0, 0, 85, 0, 0, 0, 165, +91, 0, 0, 0, 0, 0, 0, 241, 91, 0, 0, 86, 0, 0, 0, 45, 92, 0, 0, 86, 0, 0, 0, +105, 92, 0, 0, 0, 0, 0, 0, 181, 92, 0, 0, 87, 0, 0, 0, 241, 92, 0, 0, 87, 0, 0, +0, 45, 93, 0, 0, 0, 0, 0, 0, 121, 93, 0, 0, 88, 0, 0, 0, 181, 93, 0, 0, 88, 0, +0, 0, 241, 93, 0, 0, 0, 0, 0, 0, 61, 94, 0, 0, 89, 0, 0, 0, 121, 94, 0, 0, 89, +0, 0, 0, 181, 94, 0, 0, 0, 0, 0, 0, 1, 95, 0, 0, 90, 0, 0, 0, 61, 95, 0, 0, 90, +0, 0, 0, 121, 95, 0, 0, 0, 0, 0, 0, 197, 95, 0, 0, 91, 0, 0, 0, 1, 96, 0, 0, 91, +0, 0, 0, 61, 96, 0, 0, 0, 0, 0, 0, 137, 96, 0, 0, 92, 0, 0, 0, 197, 96, 0, 0, 0, +0, 0, 0, 17, 97, 0, 0, 93, 0, 0, 0, 77, 97, 0, 0, 93, 0, 0, 0, 137, 97, 0, 0, 0, +0, 0, 0, 213, 97, 0, 0, 94, 0, 0, 0, 17, 98, 0, 0, 0, 0, 0, 0, 77, 98, 0, 0, 0, +0, 0, 0, 137, 98, 0, 0, 0, 0, 0, 0, 197, 98, 0, 0, 0, 0, 0, 0, 17, 99, 0, 0, 95, +0, 0, 0, 77, 99, 0, 0, 95, 0, 0, 0, 137, 99, 0, 0, 0, 0, 0, 0, 213, 99, 0, 0, +96, 0, 0, 0, 17, 100, 0, 0, 96, 0, 0, 0, 77, 100, 0, 0, 96, 0, 0, 0, 137, 100, +0, 0, 96, 0, 0, 0, 197, 100, 0, 0, 0, 0, 0, 0, 17, 101, 0, 0, 97, 0, 0, 0, 77, +101, 0, 0, 0, 0, 0, 0, 153, 101, 0, 0, 98, 0, 0, 0, 213, 101, 0, 0, 0, 0, 0, 0, +33, 102, 0, 0, 99, 0, 0, 0, 93, 102, 0, 0, 0, 0, 0, 0, 169, 102, 0, 0, 100, 0, +0, 0, 229, 102, 0, 0, 0, 0, 0, 0, 49, 103, 0, 0, 101, 0, 0, 0, 109, 103, 0, 0, +0, 0, 0, 0, 185, 103, 0, 0, 102, 0, 0, 0, 245, 103, 0, 0, 0, 0, 0, 0, 65, 104, +0, 0, 103, 0, 0, 0, 125, 104, 0, 0, 103, 0, 0, 0, 185, 104, 0, 0, 103, 0, 0, 0, +245, 104, 0, 0, 103, 0, 0, 0, 49, 105, 0, 0, 0, 0, 0, 0, 125, 105, 0, 0, 104, 0, +0, 0, 185, 105, 0, 0, 104, 0, 0, 0, 245, 105, 0, 0, 104, 0, 0, 0, 49, 106, 0, 0, +0, 0, 0, 0, 125, 106, 0, 0, 105, 0, 0, 0, 185, 106, 0, 0, 105, 0, 0, 0, 245, +106, 0, 0, 105, 0, 0, 0, 49, 107, 0, 0, 0, 0, 0, 0, 125, 107, 0, 0, 106, 0, 0, +0, 185, 107, 0, 0, 106, 0, 0, 0, 245, 107, 0, 0, 0, 0, 0, 0, 65, 108, 0, 0, 107, +0, 0, 0, 125, 108, 0, 0, 107, 0, 0, 0, 185, 108, 0, 0, 107, 0, 0, 0, 245, 108, +0, 0, 0, 0, 0, 0, 65, 109, 0, 0, 108, 0, 0, 0, 125, 109, 0, 0, 108, 0, 0, 0, +185, 109, 0, 0, 108, 0, 0, 0, 245, 109, 0, 0, 0, 0, 0, 0, 65, 110, 0, 0, 109, 0, +0, 0, 125, 110, 0, 0, 109, 0, 0, 0, 185, 110, 0, 0, 109, 0, 0, 0, 245, 110, 0, +0, 0, 0, 0, 0, 65, 111, 0, 0, 110, 0, 0, 0, 125, 111, 0, 0, 110, 0, 0, 0, 185, +111, 0, 0, 110, 0, 0, 0, 245, 111, 0, 0, 0, 0, 0, 0, 65, 112, 0, 0, 111, 0, 0, +0, 125, 112, 0, 0, 111, 0, 0, 0, 185, 112, 0, 0, 111, 0, 0, 0, 245, 112, 0, 0, +0, 0, 0, 0, 65, 113, 0, 0, 112, 0, 0, 0, 125, 113, 0, 0, 112, 0, 0, 0, 185, 113, +0, 0, 112, 0, 0, 0, 245, 113, 0, 0, 112, 0, 0, 0, 49, 114, 0, 0, 0, 0, 0, 0, +125, 114, 0, 0, 113, 0, 0, 0, 185, 114, 0, 0, 113, 0, 0, 0, 245, 114, 0, 0, 113, +0, 0, 0, 49, 115, 0, 0, 113, 0, 0, 0, 109, 115, 0, 0, 113, 0, 0, 0, 169, 115, 0, +0, 0, 0, 0, 0, 245, 115, 0, 0, 114, 0, 0, 0, 49, 116, 0, 0, 114, 0, 0, 0, 109, +116, 0, 0, 114, 0, 0, 0, 169, 116, 0, 0, 114, 0, 0, 0, 229, 116, 0, 0, 0, 0, 0, +0, 49, 117, 0, 0, 115, 0, 0, 0, 109, 117, 0, 0, 115, 0, 0, 0, 169, 117, 0, 0, +115, 0, 0, 0, 229, 117, 0, 0, 0, 0, 0, 0, 49, 118, 0, 0, 116, 0, 0, 0, 109, 118, +0, 0, 0, 0, 0, 0, 185, 118, 0, 0, 117, 0, 0, 0, 245, 118, 0, 0, 117, 0, 0, 0, +49, 119, 0, 0, 0, 0, 0, 0, 125, 119, 0, 0, 118, 0, 0, 0, 185, 119, 0, 0, 0, 0, +0, 0, 5, 120, 0, 0, 119, 0, 0, 0, 65, 120, 0, 0, 0, 0, 0, 0, 141, 120, 0, 0, +120, 0, 0, 0, 201, 120, 0, 0, 120, 0, 0, 0, 5, 121, 0, 0, 120, 0, 0, 0, 65, 121, +0, 0, 120, 0, 0, 0, 125, 121, 0, 0, 0, 0, 0, 0, 201, 121, 0, 0, 121, 0, 0, 0, 5, +122, 0, 0, 121, 0, 0, 0, 65, 122, 0, 0, 121, 0, 0, 0, 125, 122, 0, 0, 121, 0, 0, +0, 185, 122, 0, 0, 0, 0, 0, 0, 5, 123, 0, 0, 122, 0, 0, 0, 65, 123, 0, 0, 122, +0, 0, 0, 125, 123, 0, 0, 0, 0, 0, 0, 201, 123, 0, 0, 123, 0, 0, 0, 5, 124, 0, 0, +123, 0, 0, 0, 65, 124, 0, 0, 0, 0, 0, 0, 141, 124, 0, 0, 124, 0, 0, 0, 201, 124, +0, 0, 124, 0, 0, 0, 5, 125, 0, 0, 124, 0, 0, 0, 65, 125, 0, 0, 124, 0, 0, 0, +125, 125, 0, 0, 0, 0, 0, 0, 201, 125, 0, 0, 125, 0, 0, 0, 5, 126, 0, 0, 125, 0, +0, 0, 65, 126, 0, 0, 125, 0, 0, 0, 125, 126, 0, 0, 125, 0, 0, 0, 185, 126, 0, 0, +0, 0, 0, 0, 245, 126, 0, 0, 0, 0, 0, 0, 49, 127, 0, 0, 0, 0, 0, 0, 109, 127, 0, +0, 0, 0, 0, 0, 185, 127, 0, 0, 126, 0, 0, 0, 245, 127, 0, 0, 126, 0, 0, 0, 49, +128, 0, 0, 126, 0, 0, 0, 109, 128, 0, 0, 0, 0, 0, 0, 185, 128, 0, 0, 127, 0, 0, +0, 245, 128, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 165, 0, 0, 0, 8, 0, 0, 0, 165, +0, 0, 0, 16, 0, 0, 0, 0, 0, 141, 0, 146, 172, 4, 0, 59, 23, 0, 0, 1, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 198, 0, 0, +0, 8, 0, 0, 0, 198, 0, 0, 0, 27, 0, 0, 0, 0, 0, 141, 0, 168, 172, 4, 0, 59, 23, +0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, +0, 0, 0, 200, 0, 0, 0, 8, 0, 0, 0, 200, 0, 0, 0, 27, 0, 0, 0, 0, 0, 141, 0, 190, +172, 4, 0, 59, 23, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 202, 0, 0, 0, 8, 0, 0, 0, 202, 0, 0, 0, 28, 0, 0, +0, 0, 0, 141, 0, 212, 172, 4, 0, 59, 23, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 205, 0, 0, 0, 8, 0, 0, 0, +205, 0, 0, 0, 59, 0, 0, 0, 0, 0, 141, 0, 234, 172, 4, 0, 59, 23, 0, 0, 5, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 208, +0, 0, 0, 8, 0, 0, 0, 209, 0, 0, 0, 66, 0, 0, 0, 0, 0, 141, 0, 0, 173, 4, 0, 59, +23, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 7, 0, 0, 0, 212, 0, 0, 0, 8, 0, 0, 0, 212, 0, 0, 0, 41, 0, 0, 0, 0, 0, 141, +0, 22, 173, 4, 0, 59, 23, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 215, 0, 0, 0, 8, 0, 0, 0, 215, 0, 0, 0, 64, +0, 0, 0, 0, 0, 141, 0, 44, 173, 4, 0, 59, 23, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 218, 0, 0, 0, 8, 0, 0, +0, 218, 0, 0, 0, 47, 0, 0, 0, 0, 0, 141, 0, 66, 173, 4, 0, 59, 23, 0, 0, 9, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, +221, 0, 0, 0, 8, 0, 0, 0, 222, 0, 0, 0, 83, 0, 0, 0, 0, 0, 141, 0, 88, 173, 4, +0, 59, 23, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 7, 0, 0, 0, 28, 1, 0, 0, 8, 0, 0, 0, 28, 1, 0, 0, 25, 0, 0, 0, 0, 0, +141, 0, 110, 173, 4, 0, 59, 23, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 30, 1, 0, 0, 8, 0, 0, 0, 30, 1, 0, 0, +27, 0, 0, 0, 0, 0, 141, 0, 132, 173, 4, 0, 59, 23, 0, 0, 12, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 32, 1, 0, 0, 8, +0, 0, 0, 32, 1, 0, 0, 27, 0, 0, 0, 0, 0, 141, 0, 154, 173, 4, 0, 59, 23, 0, 0, +13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, +0, 0, 34, 1, 0, 0, 8, 0, 0, 0, 34, 1, 0, 0, 27, 0, 0, 0, 0, 0, 141, 0, 176, 173, +4, 0, 59, 23, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 7, 0, 0, 0, 36, 1, 0, 0, 8, 0, 0, 0, 36, 1, 0, 0, 31, 0, 0, 0, 0, 0, +141, 0, 198, 173, 4, 0, 59, 23, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 38, 1, 0, 0, 8, 0, 0, 0, 38, 1, 0, 0, +29, 0, 0, 0, 0, 0, 141, 0, 220, 173, 4, 0, 59, 23, 0, 0, 16, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 40, 1, 0, 0, 8, +0, 0, 0, 40, 1, 0, 0, 30, 0, 0, 0, 0, 0, 141, 0, 242, 173, 4, 0, 59, 23, 0, 0, +17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, +0, 0, 42, 1, 0, 0, 8, 0, 0, 0, 42, 1, 0, 0, 27, 0, 0, 0, 0, 0, 141, 0, 8, 174, +4, 0, 59, 23, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 7, 0, 0, 0, 44, 1, 0, 0, 8, 0, 0, 0, 44, 1, 0, 0, 28, 0, 0, 0, 0, 0, +141, 0, 30, 174, 4, 0, 59, 23, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 46, 1, 0, 0, 8, 0, 0, 0, 46, 1, 0, 0, +30, 0, 0, 0, 0, 0, 141, 0, 52, 174, 4, 0, 59, 23, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 48, 1, 0, 0, 8, 0, +0, 0, 48, 1, 0, 0, 31, 0, 0, 0, 0, 0, 141, 0, 74, 174, 4, 0, 59, 23, 0, 0, 21, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, +55, 1, 0, 0, 8, 0, 0, 0, 55, 1, 0, 0, 27, 0, 0, 0, 0, 0, 141, 0, 96, 174, 4, 0, +59, 23, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 7, 0, 0, 0, 57, 1, 0, 0, 8, 0, 0, 0, 57, 1, 0, 0, 25, 0, 0, 0, 0, 0, 141, +0, 118, 174, 4, 0, 59, 23, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 60, 1, 0, 0, 8, 0, 0, 0, 60, 1, 0, 0, 27, +0, 0, 0, 0, 0, 141, 0, 140, 174, 4, 0, 59, 23, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 62, 1, 0, 0, 8, 0, 0, +0, 62, 1, 0, 0, 25, 0, 0, 0, 0, 0, 141, 0, 162, 174, 4, 0, 59, 23, 0, 0, 25, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, +64, 1, 0, 0, 8, 0, 0, 0, 64, 1, 0, 0, 27, 0, 0, 0, 0, 0, 141, 0, 184, 174, 4, 0, +59, 23, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 7, 0, 0, 0, 66, 1, 0, 0, 8, 0, 0, 0, 66, 1, 0, 0, 27, 0, 0, 0, 0, 0, 141, +0, 206, 174, 4, 0, 59, 23, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 68, 1, 0, 0, 8, 0, 0, 0, 68, 1, 0, 0, 27, +0, 0, 0, 0, 0, 141, 0, 228, 174, 4, 0, 59, 23, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 75, 1, 0, 0, 8, 0, 0, +0, 75, 1, 0, 0, 28, 0, 0, 0, 0, 0, 141, 0, 250, 174, 4, 0, 59, 23, 0, 0, 29, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, +80, 1, 0, 0, 8, 0, 0, 0, 80, 1, 0, 0, 26, 0, 0, 0, 0, 0, 141, 0, 16, 175, 4, 0, +59, 23, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 7, 0, 0, 0, 82, 1, 0, 0, 8, 0, 0, 0, 82, 1, 0, 0, 24, 0, 0, 0, 0, 0, 141, +0, 38, 175, 4, 0, 59, 23, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 86, 1, 0, 0, 8, 0, 0, 0, 86, 1, 0, 0, 27, 0, +0, 0, 0, 0, 141, 0, 60, 175, 4, 0, 59, 23, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 88, 1, 0, 0, 8, 0, 0, 0, +88, 1, 0, 0, 26, 0, 0, 0, 0, 0, 141, 0, 82, 175, 4, 0, 59, 23, 0, 0, 33, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 90, +1, 0, 0, 8, 0, 0, 0, 90, 1, 0, 0, 29, 0, 0, 0, 0, 0, 141, 0, 104, 175, 4, 0, 59, +23, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 7, 0, 0, 0, 92, 1, 0, 0, 8, 0, 0, 0, 92, 1, 0, 0, 28, 0, 0, 0, 0, 0, 141, 0, +126, 175, 4, 0, 59, 23, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 101, 1, 0, 0, 8, 0, 0, 0, 101, 1, 0, 0, 27, +0, 0, 0, 0, 0, 141, 0, 148, 175, 4, 0, 59, 23, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 146, 1, 0, 0, 8, 0, 0, +0, 146, 1, 0, 0, 22, 0, 0, 0, 0, 0, 141, 0, 170, 175, 4, 0, 59, 23, 0, 0, 37, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, +148, 1, 0, 0, 8, 0, 0, 0, 148, 1, 0, 0, 29, 0, 0, 0, 0, 0, 141, 0, 192, 175, 4, +0, 59, 23, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 7, 0, 0, 0, 150, 1, 0, 0, 8, 0, 0, 0, 150, 1, 0, 0, 29, 0, 0, 0, 0, 0, +141, 0, 214, 175, 4, 0, 59, 23, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 152, 1, 0, 0, 8, 0, 0, 0, 152, 1, 0, +0, 34, 0, 0, 0, 0, 0, 141, 0, 236, 175, 4, 0, 59, 23, 0, 0, 40, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 154, 1, 0, 0, +8, 0, 0, 0, 154, 1, 0, 0, 30, 0, 0, 0, 0, 0, 141, 0, 2, 176, 4, 0, 59, 23, 0, 0, +41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, +0, 0, 156, 1, 0, 0, 8, 0, 0, 0, 156, 1, 0, 0, 27, 0, 0, 0, 0, 0, 141, 0, 24, +176, 4, 0, 59, 23, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 158, 1, 0, 0, 8, 0, 0, 0, 158, 1, 0, 0, 37, 0, 0, +0, 0, 0, 141, 0, 46, 176, 4, 0, 59, 23, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 160, 1, 0, 0, 8, 0, 0, 0, +160, 1, 0, 0, 28, 0, 0, 0, 0, 0, 141, 0, 68, 176, 4, 0, 59, 23, 0, 0, 44, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 162, +1, 0, 0, 8, 0, 0, 0, 162, 1, 0, 0, 29, 0, 0, 0, 0, 0, 141, 0, 90, 176, 4, 0, 59, +23, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 7, 0, 0, 0, 164, 1, 0, 0, 8, 0, 0, 0, 164, 1, 0, 0, 29, 0, 0, 0, 0, 0, 141, +0, 112, 176, 4, 0, 59, 23, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 166, 1, 0, 0, 8, 0, 0, 0, 166, 1, 0, 0, +33, 0, 0, 0, 0, 0, 141, 0, 134, 176, 4, 0, 59, 23, 0, 0, 47, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 168, 1, 0, 0, 8, +0, 0, 0, 168, 1, 0, 0, 29, 0, 0, 0, 0, 0, 141, 0, 156, 176, 4, 0, 59, 23, 0, 0, +48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, +0, 0, 170, 1, 0, 0, 8, 0, 0, 0, 170, 1, 0, 0, 29, 0, 0, 0, 0, 0, 141, 0, 178, +176, 4, 0, 59, 23, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 172, 1, 0, 0, 8, 0, 0, 0, 172, 1, 0, 0, 32, 0, 0, +0, 0, 0, 141, 0, 200, 176, 4, 0, 59, 23, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 174, 1, 0, 0, 8, 0, 0, 0, +174, 1, 0, 0, 30, 0, 0, 0, 0, 0, 141, 0, 222, 176, 4, 0, 59, 23, 0, 0, 51, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 176, +1, 0, 0, 8, 0, 0, 0, 176, 1, 0, 0, 32, 0, 0, 0, 0, 0, 141, 0, 244, 176, 4, 0, +59, 23, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 7, 0, 0, 0, 185, 1, 0, 0, 8, 0, 0, 0, 185, 1, 0, 0, 33, 0, 0, 0, 0, 0, +141, 0, 10, 177, 4, 0, 59, 23, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 187, 1, 0, 0, 8, 0, 0, 0, 187, 1, 0, +0, 31, 0, 0, 0, 0, 0, 141, 0, 32, 177, 4, 0, 59, 23, 0, 0, 54, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 189, 1, 0, 0, 8, +0, 0, 0, 189, 1, 0, 0, 30, 0, 0, 0, 0, 0, 141, 0, 54, 177, 4, 0, 59, 23, 0, 0, +55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, +0, 0, 191, 1, 0, 0, 8, 0, 0, 0, 191, 1, 0, 0, 33, 0, 0, 0, 0, 0, 141, 0, 76, +177, 4, 0, 59, 23, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 193, 1, 0, 0, 8, 0, 0, 0, 193, 1, 0, 0, 29, 0, 0, +0, 0, 0, 141, 0, 98, 177, 4, 0, 59, 23, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 195, 1, 0, 0, 8, 0, 0, 0, +195, 1, 0, 0, 36, 0, 0, 0, 0, 0, 141, 0, 120, 177, 4, 0, 59, 23, 0, 0, 58, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 31, +4, 0, 0, 8, 0, 0, 0, 31, 4, 0, 0, 69, 0, 0, 0, 0, 0, 141, 0, 142, 177, 4, 0, 59, +23, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 7, 0, 0, 0, 33, 4, 0, 0, 8, 0, 0, 0, 33, 4, 0, 0, 52, 0, 0, 0, 0, 0, 141, 0, +164, 177, 4, 0, 59, 23, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 230, 0, 0, 0, 8, 0, 0, 0, 230, 0, 0, 0, 22, +0, 0, 0, 0, 0, 141, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 6, 1, 0, 0, 63, 0, 0, 0, 237, 0, 0, 0, 8, +0, 0, 0, 237, 0, 0, 0, 22, 0, 0, 0, 0, 0, 141, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 6, 1, 0, 0, +65, 0, 0, 0, 243, 0, 0, 0, 8, 0, 0, 0, 243, 0, 0, 0, 25, 0, 0, 0, 0, 0, 141, 0, +2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, +0, 0, 0, 0, 0, 6, 1, 0, 0, 68, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 3, 1, 0, 0, 1, +0, 0, 0, 0, 0, 141, 0, 64, 168, 13, 0, 59, 23, 0, 0, 70, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 2, 1, 0, 0, 71, 0, 0, 0, 72, 0, 0, +0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 0, 1, 0, 0, 8, 0, +0, 0, 3, 1, 0, 0, 1, 0, 0, 0, 0, 0, 141, 0, 64, 168, 13, 0, 59, 23, 0, 0, 74, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 2, 1, 0, 0, +75, 0, 0, 0, 76, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 7, 0, 0, 0, 6, 0, +0, 0, 109, 1, 0, 0, 8, 0, 0, 0, 138, 1, 0, 0, 1, 0, 0, 0, 0, 0, 141, 0, 36, 169, +13, 0, 59, 23, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, +0, 0, 0, 0, 0, 5, 1, 0, 0, 86, 0, 0, 0, 87, 0, 0, 0, 88, 0, 0, 0, 89, 0, 0, 0, +90, 0, 0, 0, 91, 0, 0, 0, 92, 0, 0, 0, 93, 0, 0, 0, 94, 0, 0, 0, 95, 0, 0, 0, +96, 0, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99, 0, 0, 0, 100, 0, 0, 0, 101, 0, 0, 0, +102, 0, 0, 0, 103, 0, 0, 0, 104, 0, 0, 0, 109, 1, 0, 0, 8, 0, 0, 0, 138, 1, 0, +0, 1, 0, 0, 0, 0, 0, 141, 0, 36, 169, 13, 0, 59, 23, 0, 0, 106, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 5, 1, 0, 0, 107, 0, 0, 0, +108, 0, 0, 0, 109, 0, 0, 0, 110, 0, 0, 0, 111, 0, 0, 0, 112, 0, 0, 0, 113, 0, 0, +0, 114, 0, 0, 0, 115, 0, 0, 0, 116, 0, 0, 0, 117, 0, 0, 0, 118, 0, 0, 0, 119, 0, +0, 0, 120, 0, 0, 0, 121, 0, 0, 0, 122, 0, 0, 0, 123, 0, 0, 0, 124, 0, 0, 0, 125, +0, 0, 0, 199, 1, 0, 0, 8, 0, 0, 0, 207, 1, 0, 0, 1, 0, 0, 0, 0, 0, 141, 0, 40, +171, 13, 0, 59, 23, 0, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, +0, 0, 0, 4, 0, 0, 0, 2, 1, 0, 0, 127, 0, 0, 0, 128, 0, 0, 0, 129, 0, 0, 0, 130, +0, 0, 0, 131, 0, 0, 0, 132, 0, 0, 0, 203, 1, 0, 0, 1, 0, 0, 0, 203, 1, 0, 0, 7, +0, 0, 0, 6, 0, 0, 0, 204, 1, 0, 0, 1, 0, 0, 0, 204, 1, 0, 0, 7, 0, 0, 0, 6, 0, +0, 0, 205, 1, 0, 0, 1, 0, 0, 0, 205, 1, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 206, 1, 0, +0, 1, 0, 0, 0, 206, 1, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 199, 1, 0, 0, 8, 0, 0, 0, +207, 1, 0, 0, 1, 0, 0, 0, 0, 0, 141, 0, 40, 171, 13, 0, 59, 23, 0, 0, 134, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0, 2, 1, 0, 0, 135, +0, 0, 0, 136, 0, 0, 0, 137, 0, 0, 0, 138, 0, 0, 0, 139, 0, 0, 0, 140, 0, 0, 0, +203, 1, 0, 0, 1, 0, 0, 0, 203, 1, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 204, 1, 0, 0, 1, +0, 0, 0, 204, 1, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 205, 1, 0, 0, 1, 0, 0, 0, 205, 1, +0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 206, 1, 0, 0, 1, 0, 0, 0, 206, 1, 0, 0, 7, 0, 0, +0, 6, 0, 0, 0, 210, 1, 0, 0, 8, 0, 0, 0, 217, 1, 0, 0, 1, 0, 0, 0, 0, 0, 141, 0, +218, 171, 13, 0, 59, 23, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +6, 0, 0, 0, 3, 0, 0, 0, 2, 1, 0, 0, 142, 0, 0, 0, 143, 0, 0, 0, 144, 0, 0, 0, +145, 0, 0, 0, 146, 0, 0, 0, 147, 0, 0, 0, 212, 1, 0, 0, 1, 0, 0, 0, 212, 1, 0, +0, 7, 0, 0, 0, 6, 0, 0, 0, 213, 1, 0, 0, 1, 0, 0, 0, 213, 1, 0, 0, 7, 0, 0, 0, +6, 0, 0, 0, 214, 1, 0, 0, 1, 0, 0, 0, 214, 1, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 210, +1, 0, 0, 8, 0, 0, 0, 217, 1, 0, 0, 1, 0, 0, 0, 0, 0, 141, 0, 218, 171, 13, 0, +59, 23, 0, 0, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 3, +0, 0, 0, 2, 1, 0, 0, 150, 0, 0, 0, 151, 0, 0, 0, 152, 0, 0, 0, 153, 0, 0, 0, +154, 0, 0, 0, 155, 0, 0, 0, 212, 1, 0, 0, 1, 0, 0, 0, 212, 1, 0, 0, 7, 0, 0, 0, +6, 0, 0, 0, 213, 1, 0, 0, 1, 0, 0, 0, 213, 1, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 214, +1, 0, 0, 1, 0, 0, 0, 214, 1, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 226, 1, 0, 0, 0, 0, +0, 0, 226, 1, 0, 0, 53, 0, 0, 0, 0, 0, 141, 0, 140, 172, 13, 0, 59, 23, 0, 0, +156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, +0, 0, 157, 0, 0, 0, 158, 0, 0, 0, 159, 0, 0, 0, 238, 1, 0, 0, 0, 0, 0, 0, 238, +1, 0, 0, 27, 0, 0, 0, 0, 0, 141, 0, 162, 172, 13, 0, 59, 23, 0, 0, 160, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 161, 0, +0, 0, 251, 1, 0, 0, 0, 0, 0, 0, 251, 1, 0, 0, 34, 0, 0, 0, 0, 0, 141, 0, 184, +172, 13, 0, 59, 23, 0, 0, 162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, +0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 163, 0, 0, 0, 251, 1, 0, 0, 20, 0, 0, 0, 251, +1, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 118, 2, 0, 0, 0, 0, 0, 0, 118, 2, 0, 0, 86, 0, +0, 0, 0, 0, 141, 0, 206, 172, 13, 0, 59, 23, 0, 0, 164, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 165, 0, 0, 0, 166, 0, +0, 0, 167, 0, 0, 0, 168, 0, 0, 0, 118, 2, 0, 0, 18, 0, 0, 0, 118, 2, 0, 0, 25, +0, 0, 0, 0, 0, 0, 0, 118, 2, 0, 0, 70, 0, 0, 0, 118, 2, 0, 0, 80, 0, 0, 0, 10, +0, 0, 0, 134, 2, 0, 0, 0, 0, 0, 0, 134, 2, 0, 0, 49, 0, 0, 0, 0, 0, 141, 0, 228, +172, 13, 0, 59, 23, 0, 0, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, +0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 170, 0, 0, 0, 171, 0, 0, 0, 134, 2, 0, 0, 18, +0, 0, 0, 134, 2, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 149, 2, 0, 0, 0, 0, 0, 0, 149, +2, 0, 0, 54, 0, 0, 0, 0, 0, 141, 0, 250, 172, 13, 0, 59, 23, 0, 0, 172, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 173, 0, +0, 0, 174, 0, 0, 0, 149, 2, 0, 0, 20, 0, 0, 0, 149, 2, 0, 0, 27, 0, 0, 0, 0, 0, +0, 0, 149, 2, 0, 0, 34, 0, 0, 0, 149, 2, 0, 0, 50, 0, 0, 0, 9, 0, 0, 0, 174, 2, +0, 0, 0, 0, 0, 0, 174, 2, 0, 0, 70, 0, 0, 0, 0, 0, 141, 0, 16, 173, 13, 0, 59, +23, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, +0, 3, 0, 0, 0, 176, 0, 0, 0, 177, 0, 0, 0, 178, 0, 0, 0, 174, 2, 0, 0, 19, 0, 0, +0, 174, 2, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 193, 2, 0, 0, 0, 0, 0, 0, 193, 2, 0, +0, 75, 0, 0, 0, 0, 0, 141, 0, 38, 173, 13, 0, 59, 23, 0, 0, 179, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 180, 0, 0, 0, +181, 0, 0, 0, 182, 0, 0, 0, 193, 2, 0, 0, 21, 0, 0, 0, 193, 2, 0, 0, 28, 0, 0, +0, 0, 0, 0, 0, 193, 2, 0, 0, 35, 0, 0, 0, 193, 2, 0, 0, 51, 0, 0, 0, 9, 0, 0, 0, +201, 2, 0, 0, 0, 0, 0, 0, 201, 2, 0, 0, 47, 0, 0, 0, 0, 0, 141, 0, 60, 173, 13, +0, 59, 23, 0, 0, 183, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, +2, 0, 0, 0, 3, 0, 0, 0, 184, 0, 0, 0, 185, 0, 0, 0, 201, 2, 0, 0, 18, 0, 0, 0, +201, 2, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 201, 2, 0, 0, 32, 0, 0, 0, 201, 2, 0, 0, +40, 0, 0, 0, 8, 0, 0, 0, 209, 2, 0, 0, 0, 0, 0, 0, 209, 2, 0, 0, 50, 0, 0, 0, 0, +0, 141, 0, 82, 173, 13, 0, 59, 23, 0, 0, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 187, 0, 0, 0, 188, 0, 0, 0, 209, +2, 0, 0, 18, 0, 0, 0, 209, 2, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 209, 2, 0, 0, 32, +0, 0, 0, 209, 2, 0, 0, 43, 0, 0, 0, 13, 0, 0, 0, 230, 2, 0, 0, 0, 0, 0, 0, 230, +2, 0, 0, 42, 0, 0, 0, 0, 0, 141, 0, 104, 173, 13, 0, 59, 23, 0, 0, 189, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 190, 0, +0, 0, 191, 0, 0, 0, 230, 2, 0, 0, 18, 0, 0, 0, 230, 2, 0, 0, 25, 0, 0, 0, 0, 0, +0, 0, 240, 2, 0, 0, 0, 0, 0, 0, 240, 2, 0, 0, 32, 0, 0, 0, 0, 0, 141, 0, 126, +173, 13, 0, 59, 23, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, +0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 193, 0, 0, 0, 240, 2, 0, 0, 19, 0, 0, 0, 240, +2, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 67, 0, 0, +0, 0, 0, 141, 0, 148, 173, 13, 0, 59, 23, 0, 0, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 195, 0, 0, 0, 196, 0, 0, +0, 197, 0, 0, 0, 0, 3, 0, 0, 23, 0, 0, 0, 0, 3, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, +12, 3, 0, 0, 0, 0, 0, 0, 12, 3, 0, 0, 57, 0, 0, 0, 0, 0, 141, 0, 170, 173, 13, +0, 59, 23, 0, 0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, +1, 0, 0, 0, 3, 0, 0, 0, 199, 0, 0, 0, 200, 0, 0, 0, 12, 3, 0, 0, 23, 0, 0, 0, +12, 3, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 26, 3, 0, 0, 0, 0, 0, 0, 26, 3, 0, 0, 54, +0, 0, 0, 0, 0, 141, 0, 192, 173, 13, 0, 59, 23, 0, 0, 201, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 202, 0, 0, 0, 203, +0, 0, 0, 26, 3, 0, 0, 22, 0, 0, 0, 26, 3, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 42, 3, +0, 0, 0, 0, 0, 0, 42, 3, 0, 0, 55, 0, 0, 0, 0, 0, 141, 0, 214, 173, 13, 0, 59, +23, 0, 0, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, +0, 3, 0, 0, 0, 205, 0, 0, 0, 206, 0, 0, 0, 42, 3, 0, 0, 20, 0, 0, 0, 42, 3, 0, +0, 27, 0, 0, 0, 0, 0, 0, 0, 42, 3, 0, 0, 34, 0, 0, 0, 42, 3, 0, 0, 50, 0, 0, 0, +9, 0, 0, 0, 76, 3, 0, 0, 0, 0, 0, 0, 76, 3, 0, 0, 51, 0, 0, 0, 0, 0, 141, 0, +236, 173, 13, 0, 59, 23, 0, 0, 207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +2, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 208, 0, 0, 0, 209, 0, 0, 0, 76, 3, 0, 0, 25, +0, 0, 0, 76, 3, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 76, 3, 0, 0, 39, 0, 0, 0, 76, 3, +0, 0, 45, 0, 0, 0, 6, 0, 0, 0, 95, 3, 0, 0, 0, 0, 0, 0, 95, 3, 0, 0, 63, 0, 0, +0, 0, 0, 141, 0, 2, 174, 13, 0, 59, 23, 0, 0, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 211, 0, 0, 0, 212, 0, 0, 0, +95, 3, 0, 0, 28, 0, 0, 0, 95, 3, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 107, 3, 0, 0, 0, +0, 0, 0, 107, 3, 0, 0, 64, 0, 0, 0, 0, 0, 141, 0, 24, 174, 13, 0, 59, 23, 0, 0, +213, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 3, 0, +0, 0, 214, 0, 0, 0, 215, 0, 0, 0, 107, 3, 0, 0, 28, 0, 0, 0, 107, 3, 0, 0, 35, +0, 0, 0, 0, 0, 0, 0, 127, 3, 0, 0, 0, 0, 0, 0, 127, 3, 0, 0, 50, 0, 0, 0, 0, 0, +141, 0, 46, 174, 13, 0, 59, 23, 0, 0, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 217, 0, 0, 0, 218, 0, 0, 0, 127, 3, +0, 0, 24, 0, 0, 0, 127, 3, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 127, 3, 0, 0, 38, 0, +0, 0, 127, 3, 0, 0, 45, 0, 0, 0, 2, 0, 0, 0, 136, 3, 0, 0, 0, 0, 0, 0, 136, 3, +0, 0, 41, 0, 0, 0, 0, 0, 141, 0, 68, 174, 13, 0, 59, 23, 0, 0, 219, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 220, 0, 0, +0, 136, 3, 0, 0, 28, 0, 0, 0, 136, 3, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 144, 3, 0, +0, 0, 0, 0, 0, 144, 3, 0, 0, 49, 0, 0, 0, 0, 0, 141, 0, 90, 174, 13, 0, 59, 23, +0, 0, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, +3, 0, 0, 0, 222, 0, 0, 0, 223, 0, 0, 0, 144, 3, 0, 0, 25, 0, 0, 0, 144, 3, 0, 0, +32, 0, 0, 0, 0, 0, 0, 0, 151, 3, 0, 0, 0, 0, 0, 0, 151, 3, 0, 0, 39, 0, 0, 0, 0, +0, 141, 0, 112, 174, 13, 0, 59, 23, 0, 0, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 225, 0, 0, 0, 151, 3, 0, 0, 26, +0, 0, 0, 151, 3, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 168, 3, 0, 0, 0, 0, 0, 0, 168, +3, 0, 0, 60, 0, 0, 0, 0, 0, 141, 0, 200, 174, 13, 0, 59, 23, 0, 0, 229, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 230, 0, +0, 0, 231, 0, 0, 0, 168, 3, 0, 0, 24, 0, 0, 0, 168, 3, 0, 0, 31, 0, 0, 0, 0, 0, +0, 0, 168, 3, 0, 0, 38, 0, 0, 0, 168, 3, 0, 0, 53, 0, 0, 0, 14, 0, 0, 0, 204, 3, +0, 0, 0, 0, 0, 0, 204, 3, 0, 0, 84, 0, 0, 0, 0, 0, 141, 0, 222, 174, 13, 0, 59, +23, 0, 0, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 3, 0, 0, +0, 3, 0, 0, 0, 233, 0, 0, 0, 234, 0, 0, 0, 235, 0, 0, 0, 236, 0, 0, 0, 204, 3, +0, 0, 19, 0, 0, 0, 204, 3, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 204, 3, 0, 0, 33, 0, +0, 0, 204, 3, 0, 0, 40, 0, 0, 0, 1, 0, 0, 0, 204, 3, 0, 0, 70, 0, 0, 0, 204, 3, +0, 0, 77, 0, 0, 0, 1, 0, 0, 0, 210, 3, 0, 0, 0, 0, 0, 0, 210, 3, 0, 0, 34, 0, 0, +0, 0, 0, 141, 0, 244, 174, 13, 0, 59, 23, 0, 0, 237, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 238, 0, 0, 0, 210, 3, 0, +0, 0, 0, 0, 0, 210, 3, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 210, 3, 0, 0, 21, 0, 0, 0, +210, 3, 0, 0, 28, 0, 0, 0, 1, 0, 0, 0, 221, 3, 0, 0, 0, 0, 0, 0, 221, 3, 0, 0, +31, 0, 0, 0, 0, 0, 141, 0, 10, 175, 13, 0, 59, 23, 0, 0, 239, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 240, 0, 0, 0, +221, 3, 0, 0, 0, 0, 0, 0, 221, 3, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 221, 3, 0, 0, +18, 0, 0, 0, 221, 3, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 239, 3, 0, 0, 0, 0, 0, 0, +239, 3, 0, 0, 33, 0, 0, 0, 0, 0, 141, 0, 32, 175, 13, 0, 59, 23, 0, 0, 241, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, +242, 0, 0, 0, 239, 3, 0, 0, 20, 0, 0, 0, 239, 3, 0, 0, 27, 0, 0, 0, 1, 0, 0, 0, +249, 3, 0, 0, 0, 0, 0, 0, 249, 3, 0, 0, 32, 0, 0, 0, 0, 0, 141, 0, 54, 175, 13, +0, 59, 23, 0, 0, 243, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, +1, 0, 0, 0, 3, 0, 0, 0, 244, 0, 0, 0, 249, 3, 0, 0, 19, 0, 0, 0, 249, 3, 0, 0, +26, 0, 0, 0, 1, 0, 0, 0, 12, 4, 0, 0, 0, 0, 0, 0, 12, 4, 0, 0, 32, 0, 0, 0, 0, +0, 141, 0, 76, 175, 13, 0, 59, 23, 0, 0, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 246, 0, 0, 0, 12, 4, 0, 0, 19, +0, 0, 0, 12, 4, 0, 0, 26, 0, 0, 0, 1, 0, 0, 0, 28, 4, 0, 0, 0, 0, 0, 0, 28, 4, +0, 0, 32, 0, 0, 0, 0, 0, 141, 0, 98, 175, 13, 0, 59, 23, 0, 0, 247, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 248, 0, 0, +0, 28, 4, 0, 0, 19, 0, 0, 0, 28, 4, 0, 0, 26, 0, 0, 0, 1, 0, 0, 0, 103, 4, 0, 0, +0, 0, 0, 0, 103, 4, 0, 0, 83, 0, 0, 0, 0, 0, 141, 0, 120, 175, 13, 0, 59, 23, 0, +0, 249, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 3, +0, 0, 0, 250, 0, 0, 0, 251, 0, 0, 0, 252, 0, 0, 0, 253, 0, 0, 0, 103, 4, 0, 0, +18, 0, 0, 0, 103, 4, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 103, 4, 0, 0, 70, 0, 0, 0, +103, 4, 0, 0, 77, 0, 0, 0, 2, 0, 0, 0, 117, 4, 0, 0, 0, 0, 0, 0, 117, 4, 0, 0, +56, 0, 0, 0, 0, 0, 141, 0, 142, 175, 13, 0, 59, 23, 0, 0, 254, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 255, 0, 0, 0, 0, +1, 0, 0, 1, 1, 0, 0, 117, 4, 0, 0, 14, 0, 0, 0, 117, 4, 0, 0, 21, 0, 0, 0, 1, 0, +0, 0, 117, 4, 0, 0, 28, 0, 0, 0, 117, 4, 0, 0, 35, 0, 0, 0, 2, 0, 0, 0, 117, 4, +0, 0, 41, 0, 0, 0, 117, 4, 0, 0, 49, 0, 0, 0, 8, 0, 0, 0, 126, 4, 0, 0, 0, 0, 0, +0, 126, 4, 0, 0, 65, 0, 0, 0, 0, 0, 141, 0, 164, 175, 13, 0, 59, 23, 0, 0, 2, 1, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 3, +1, 0, 0, 4, 1, 0, 0, 5, 1, 0, 0, 126, 4, 0, 0, 18, 0, 0, 0, 126, 4, 0, 0, 25, 0, +0, 0, 1, 0, 0, 0, 126, 4, 0, 0, 32, 0, 0, 0, 126, 4, 0, 0, 39, 0, 0, 0, 2, 0, 0, +0, 144, 4, 0, 0, 0, 0, 0, 0, 144, 4, 0, 0, 45, 0, 0, 0, 0, 0, 141, 0, 208, 175, +13, 0, 59, 23, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, +2, 0, 0, 0, 3, 0, 0, 0, 7, 1, 0, 0, 8, 1, 0, 0, 144, 4, 0, 0, 19, 0, 0, 0, 144, +4, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 144, 4, 0, 0, 33, 0, 0, 0, 144, 4, 0, 0, 40, +0, 0, 0, 2, 0, 0, 0, 155, 4, 0, 0, 0, 0, 0, 0, 155, 4, 0, 0, 49, 0, 0, 0, 0, 0, +141, 0, 230, 175, 13, 0, 59, 23, 0, 0, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 10, 1, 0, 0, 11, 1, 0, 0, 12, 1, 0, 0, +155, 4, 0, 0, 14, 0, 0, 0, 155, 4, 0, 0, 21, 0, 0, 0, 1, 0, 0, 0, 155, 4, 0, 0, +28, 0, 0, 0, 155, 4, 0, 0, 35, 0, 0, 0, 2, 0, 0, 0, 176, 4, 0, 0, 0, 0, 0, 0, +176, 4, 0, 0, 66, 0, 0, 0, 0, 0, 141, 0, 106, 176, 13, 0, 59, 23, 0, 0, 13, 1, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, +14, 1, 0, 0, 15, 1, 0, 0, 16, 1, 0, 0, 176, 4, 0, 0, 21, 0, 0, 0, 176, 4, 0, 0, +28, 0, 0, 0, 1, 0, 0, 0, 176, 4, 0, 0, 35, 0, 0, 0, 176, 4, 0, 0, 42, 0, 0, 0, +2, 0, 0, 0, 176, 4, 0, 0, 48, 0, 0, 0, 176, 4, 0, 0, 60, 0, 0, 0, 11, 0, 0, 0, +199, 4, 0, 0, 0, 0, 0, 0, 199, 4, 0, 0, 66, 0, 0, 0, 0, 0, 141, 0, 128, 176, 13, +0, 59, 23, 0, 0, 17, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, +0, 0, 0, 3, 0, 0, 0, 18, 1, 0, 0, 19, 1, 0, 0, 20, 1, 0, 0, 199, 4, 0, 0, 21, 0, +0, 0, 199, 4, 0, 0, 28, 0, 0, 0, 1, 0, 0, 0, 199, 4, 0, 0, 35, 0, 0, 0, 199, 4, +0, 0, 42, 0, 0, 0, 2, 0, 0, 0, 199, 4, 0, 0, 48, 0, 0, 0, 199, 4, 0, 0, 60, 0, +0, 0, 11, 0, 0, 0, 219, 4, 0, 0, 0, 0, 0, 0, 219, 4, 0, 0, 66, 0, 0, 0, 0, 0, +141, 0, 150, 176, 13, 0, 59, 23, 0, 0, 21, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 22, 1, 0, 0, 23, 1, 0, 0, 24, 1, 0, +0, 219, 4, 0, 0, 21, 0, 0, 0, 219, 4, 0, 0, 28, 0, 0, 0, 1, 0, 0, 0, 219, 4, 0, +0, 35, 0, 0, 0, 219, 4, 0, 0, 42, 0, 0, 0, 2, 0, 0, 0, 219, 4, 0, 0, 48, 0, 0, +0, 219, 4, 0, 0, 60, 0, 0, 0, 7, 0, 0, 0, 235, 4, 0, 0, 0, 0, 0, 0, 235, 4, 0, +0, 57, 0, 0, 0, 0, 0, 141, 0, 172, 176, 13, 0, 59, 23, 0, 0, 25, 1, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 26, 1, 0, 0, +27, 1, 0, 0, 28, 1, 0, 0, 235, 4, 0, 0, 20, 0, 0, 0, 235, 4, 0, 0, 27, 0, 0, 0, +1, 0, 0, 0, 235, 4, 0, 0, 34, 0, 0, 0, 235, 4, 0, 0, 41, 0, 0, 0, 2, 0, 0, 0, 7, +5, 0, 0, 0, 0, 0, 0, 7, 5, 0, 0, 68, 0, 0, 0, 0, 0, 141, 0, 194, 176, 13, 0, 59, +23, 0, 0, 29, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, +0, 3, 0, 0, 0, 30, 1, 0, 0, 31, 1, 0, 0, 32, 1, 0, 0, 33, 1, 0, 0, 7, 5, 0, 0, +13, 0, 0, 0, 7, 5, 0, 0, 20, 0, 0, 0, 1, 0, 0, 0, 7, 5, 0, 0, 27, 0, 0, 0, 7, 5, +0, 0, 34, 0, 0, 0, 2, 0, 0, 0, 7, 5, 0, 0, 40, 0, 0, 0, 7, 5, 0, 0, 47, 0, 0, 0, +3, 0, 0, 0, 7, 5, 0, 0, 54, 0, 0, 0, 7, 5, 0, 0, 61, 0, 0, 0, 3, 0, 0, 0, 56, 5, +0, 0, 0, 0, 0, 0, 57, 5, 0, 0, 26, 0, 0, 0, 0, 0, 141, 0, 216, 176, 13, 0, 59, +23, 0, 0, 34, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 4, 0, 0, +0, 3, 0, 0, 0, 35, 1, 0, 0, 36, 1, 0, 0, 37, 1, 0, 0, 38, 1, 0, 0, 39, 1, 0, 0, +56, 5, 0, 0, 13, 0, 0, 0, 56, 5, 0, 0, 20, 0, 0, 0, 1, 0, 0, 0, 56, 5, 0, 0, 27, +0, 0, 0, 56, 5, 0, 0, 34, 0, 0, 0, 2, 0, 0, 0, 56, 5, 0, 0, 40, 0, 0, 0, 56, 5, +0, 0, 47, 0, 0, 0, 3, 0, 0, 0, 56, 5, 0, 0, 54, 0, 0, 0, 56, 5, 0, 0, 61, 0, 0, +0, 3, 0, 0, 0, 81, 5, 0, 0, 0, 0, 0, 0, 81, 5, 0, 0, 68, 0, 0, 0, 0, 0, 141, 0, +238, 176, 13, 0, 59, 23, 0, 0, 40, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +4, 0, 0, 0, 4, 0, 0, 0, 3, 0, 0, 0, 41, 1, 0, 0, 42, 1, 0, 0, 43, 1, 0, 0, 44, +1, 0, 0, 81, 5, 0, 0, 13, 0, 0, 0, 81, 5, 0, 0, 20, 0, 0, 0, 1, 0, 0, 0, 81, 5, +0, 0, 27, 0, 0, 0, 81, 5, 0, 0, 34, 0, 0, 0, 2, 0, 0, 0, 81, 5, 0, 0, 40, 0, 0, +0, 81, 5, 0, 0, 47, 0, 0, 0, 3, 0, 0, 0, 81, 5, 0, 0, 54, 0, 0, 0, 81, 5, 0, 0, +61, 0, 0, 0, 3, 0, 0, 0, 105, 5, 0, 0, 0, 0, 0, 0, 105, 5, 0, 0, 68, 0, 0, 0, 0, +0, 141, 0, 4, 177, 13, 0, 59, 23, 0, 0, 45, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 46, 1, 0, 0, 47, 1, 0, 0, 48, 1, 0, +0, 105, 5, 0, 0, 21, 0, 0, 0, 105, 5, 0, 0, 28, 0, 0, 0, 1, 0, 0, 0, 105, 5, 0, +0, 35, 0, 0, 0, 105, 5, 0, 0, 42, 0, 0, 0, 2, 0, 0, 0, 105, 5, 0, 0, 48, 0, 0, +0, 105, 5, 0, 0, 58, 0, 0, 0, 4, 0, 0, 0, 113, 5, 0, 0, 0, 0, 0, 0, 113, 5, 0, +0, 41, 0, 0, 0, 0, 0, 141, 0, 26, 177, 13, 0, 59, 23, 0, 0, 49, 1, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 50, 1, 0, 0, +113, 5, 0, 0, 22, 0, 0, 0, 113, 5, 0, 0, 32, 0, 0, 0, 4, 0, 0, 0, 131, 5, 0, 0, +0, 0, 0, 0, 131, 5, 0, 0, 55, 0, 0, 0, 0, 0, 141, 0, 48, 177, 13, 0, 59, 23, 0, +0, 51, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 3, +0, 0, 0, 52, 1, 0, 0, 53, 1, 0, 0, 131, 5, 0, 0, 22, 0, 0, 0, 131, 5, 0, 0, 29, +0, 0, 0, 1, 0, 0, 0, 131, 5, 0, 0, 36, 0, 0, 0, 131, 5, 0, 0, 46, 0, 0, 0, 4, 0, +0, 0, 137, 5, 0, 0, 0, 0, 0, 0, 137, 5, 0, 0, 43, 0, 0, 0, 0, 0, 141, 0, 70, +177, 13, 0, 59, 23, 0, 0, 54, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, +0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 55, 1, 0, 0, 137, 5, 0, 0, 0, 0, 0, 0, 137, 5, 0, +0, 7, 0, 0, 0, 1, 0, 0, 0, 137, 5, 0, 0, 24, 0, 0, 0, 137, 5, 0, 0, 34, 0, 0, 0, +4, 0, 0, 0, 143, 5, 0, 0, 0, 0, 0, 0, 143, 5, 0, 0, 42, 0, 0, 0, 0, 0, 141, 0, +92, 177, 13, 0, 59, 23, 0, 0, 56, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 57, 1, 0, 0, 143, 5, 0, 0, 0, 0, 0, 0, 143, +5, 0, 0, 7, 0, 0, 0, 2, 0, 0, 0, 143, 5, 0, 0, 23, 0, 0, 0, 143, 5, 0, 0, 33, 0, +0, 0, 4, 0, 0, 0, 164, 5, 0, 0, 0, 0, 0, 0, 165, 5, 0, 0, 24, 0, 0, 0, 0, 0, +141, 0, 114, 177, 13, 0, 59, 23, 0, 0, 58, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 3, 0, 0, 0, 59, 1, 0, 0, 60, 1, 0, 0, 61, 1, 0, +0, 62, 1, 0, 0, 164, 5, 0, 0, 20, 0, 0, 0, 164, 5, 0, 0, 30, 0, 0, 0, 4, 0, 0, +0, 164, 5, 0, 0, 40, 0, 0, 0, 164, 5, 0, 0, 47, 0, 0, 0, 3, 0, 0, 0, 164, 5, 0, +0, 54, 0, 0, 0, 164, 5, 0, 0, 61, 0, 0, 0, 3, 0, 0, 0, 165, 5, 0, 0, 7, 0, 0, 0, +165, 5, 0, 0, 20, 0, 0, 0, 5, 0, 0, 0, 226, 5, 0, 0, 0, 0, 0, 0, 227, 5, 0, 0, +23, 0, 0, 0, 0, 0, 141, 0, 136, 177, 13, 0, 59, 23, 0, 0, 63, 1, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 64, 1, 0, 0, 65, +1, 0, 0, 66, 1, 0, 0, 67, 1, 0, 0, 226, 5, 0, 0, 20, 0, 0, 0, 226, 5, 0, 0, 30, +0, 0, 0, 4, 0, 0, 0, 226, 5, 0, 0, 40, 0, 0, 0, 226, 5, 0, 0, 47, 0, 0, 0, 3, 0, +0, 0, 226, 5, 0, 0, 54, 0, 0, 0, 226, 5, 0, 0, 61, 0, 0, 0, 3, 0, 0, 0, 246, 5, +0, 0, 0, 0, 0, 0, 246, 5, 0, 0, 59, 0, 0, 0, 0, 0, 141, 0, 158, 177, 13, 0, 59, +23, 0, 0, 68, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, +0, 3, 0, 0, 0, 69, 1, 0, 0, 70, 1, 0, 0, 246, 5, 0, 0, 20, 0, 0, 0, 246, 5, 0, +0, 30, 0, 0, 0, 4, 0, 0, 0, 4, 6, 0, 0, 0, 0, 0, 0, 4, 6, 0, 0, 57, 0, 0, 0, 0, +0, 141, 0, 180, 177, 13, 0, 59, 23, 0, 0, 71, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 72, 1, 0, 0, 73, 1, 0, 0, 4, 6, +0, 0, 22, 0, 0, 0, 4, 6, 0, 0, 32, 0, 0, 0, 4, 0, 0, 0, 4, 6, 0, 0, 42, 0, 0, 0, +4, 6, 0, 0, 48, 0, 0, 0, 6, 0, 0, 0, 16, 6, 0, 0, 0, 0, 0, 0, 16, 6, 0, 0, 75, +0, 0, 0, 0, 0, 141, 0, 202, 177, 13, 0, 59, 23, 0, 0, 74, 1, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 3, 0, 0, 0, 75, 1, 0, 0, 76, 1, +0, 0, 77, 1, 0, 0, 78, 1, 0, 0, 16, 6, 0, 0, 13, 0, 0, 0, 16, 6, 0, 0, 20, 0, 0, +0, 1, 0, 0, 0, 16, 6, 0, 0, 27, 0, 0, 0, 16, 6, 0, 0, 34, 0, 0, 0, 2, 0, 0, 0, +16, 6, 0, 0, 46, 0, 0, 0, 16, 6, 0, 0, 53, 0, 0, 0, 3, 0, 0, 0, 16, 6, 0, 0, 64, +0, 0, 0, 16, 6, 0, 0, 71, 0, 0, 0, 3, 0, 0, 0, 28, 6, 0, 0, 0, 0, 0, 0, 28, 6, +0, 0, 76, 0, 0, 0, 0, 0, 141, 0, 224, 177, 13, 0, 59, 23, 0, 0, 79, 1, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 3, 0, 0, 0, 80, 1, 0, +0, 81, 1, 0, 0, 82, 1, 0, 0, 83, 1, 0, 0, 28, 6, 0, 0, 14, 0, 0, 0, 28, 6, 0, 0, +21, 0, 0, 0, 1, 0, 0, 0, 28, 6, 0, 0, 28, 0, 0, 0, 28, 6, 0, 0, 35, 0, 0, 0, 2, +0, 0, 0, 28, 6, 0, 0, 47, 0, 0, 0, 28, 6, 0, 0, 54, 0, 0, 0, 3, 0, 0, 0, 28, 6, +0, 0, 65, 0, 0, 0, 28, 6, 0, 0, 72, 0, 0, 0, 3, 0, 0, 0, 45, 6, 0, 0, 0, 0, 0, +0, 45, 6, 0, 0, 64, 0, 0, 0, 0, 0, 141, 0, 56, 178, 13, 0, 59, 23, 0, 0, 87, 1, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, +88, 1, 0, 0, 89, 1, 0, 0, 90, 1, 0, 0, 45, 6, 0, 0, 20, 0, 0, 0, 45, 6, 0, 0, +27, 0, 0, 0, 0, 0, 0, 0, 45, 6, 0, 0, 34, 0, 0, 0, 45, 6, 0, 0, 46, 0, 0, 0, 12, +0, 0, 0, 53, 6, 0, 0, 0, 0, 0, 0, 53, 6, 0, 0, 45, 0, 0, 0, 0, 0, 141, 0, 78, +178, 13, 0, 59, 23, 0, 0, 91, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, +0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 92, 1, 0, 0, 93, 1, 0, 0, 53, 6, 0, 0, 21, 0, 0, +0, 53, 6, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 165, 0, 0, 0, 8, 0, 0, 0, 165, 0, 0, 0, +16, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 138, 61, 3, 0, +2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 81, 186, +10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 0, 0, 0, 8, 0, 0, 0, 198, 0, 0, 0, 25, 0, 0, +0, 0, 0, 143, 0, 59, 23, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 160, 61, 3, 0, 2, 0, 1, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 48, 0, 255, 255, +0, 0, 0, 0, 0, 0, 0, 0, 200, 0, 0, 0, 8, 0, 0, 0, 200, 0, 0, 0, 25, 0, 0, 0, 0, +0, 143, 0, 59, 23, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 182, 61, 3, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 57, 0, 255, 255, 0, 0, +0, 0, 0, 0, 0, 0, 202, 0, 0, 0, 8, 0, 0, 0, 202, 0, 0, 0, 25, 0, 0, 0, 0, 0, +143, 0, 59, 23, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 204, 61, 3, 0, 2, 0, 1, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 251, 120, 10, 0, 0, 0, 0, +0, 0, 0, 0, 0, 205, 0, 0, 0, 8, 0, 0, 0, 205, 0, 0, 0, 18, 0, 0, 0, 0, 0, 143, +0, 59, 23, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 226, 61, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 200, 186, 10, 0, 1, 0, 0, 0, 3, +0, 0, 0, 97, 0, 255, 255, 98, 0, 255, 255, 99, 0, 255, 255, 208, 0, 0, 0, 8, 0, +0, 0, 208, 0, 0, 0, 24, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 6, 0, 0, 0, 0, 0, +0, 0, 248, 61, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +6, 2, 0, 0, 13, 187, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 0, 0, 0, 8, 0, 0, 0, +212, 0, 0, 0, 24, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, +14, 62, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, +0, 0, 117, 187, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 0, 0, 0, 8, 0, 0, 0, 215, 0, +0, 0, 18, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 36, 62, +3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, +163, 187, 10, 0, 1, 0, 0, 0, 4, 0, 0, 0, 97, 0, 255, 255, 98, 0, 255, 255, 99, +0, 255, 255, 100, 0, 255, 255, 218, 0, 0, 0, 8, 0, 0, 0, 218, 0, 0, 0, 18, 0, 0, +0, 0, 0, 143, 0, 59, 23, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 58, 62, 3, 0, 2, 0, 1, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 229, 187, 10, 0, 1, +0, 0, 0, 4, 0, 0, 0, 97, 0, 255, 255, 98, 0, 255, 255, 99, 0, 255, 255, 100, 0, +255, 255, 221, 0, 0, 0, 8, 0, 0, 0, 221, 0, 0, 0, 26, 0, 0, 0, 0, 0, 143, 0, 59, +23, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 80, 62, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 30, 188, 10, 0, 0, 0, 0, 0, 0, 0, 0, +0, 28, 1, 0, 0, 8, 0, 0, 0, 28, 1, 0, 0, 20, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, +0, 11, 0, 0, 0, 0, 0, 0, 0, 102, 62, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 147, 188, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, +1, 0, 0, 8, 0, 0, 0, 30, 1, 0, 0, 20, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 12, +0, 0, 0, 0, 0, 0, 0, 124, 62, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 6, 2, 0, 0, 39, 243, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 1, 0, 0, +8, 0, 0, 0, 32, 1, 0, 0, 18, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 13, 0, 0, 0, +0, 0, 0, 0, 146, 62, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 6, 2, 0, 0, 203, 188, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 1, 0, 0, 8, 0, 0, +0, 34, 1, 0, 0, 18, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 14, 0, 0, 0, 0, 0, 0, +0, 168, 62, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, +2, 0, 0, 241, 188, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 1, 0, 0, 8, 0, 0, 0, 36, +1, 0, 0, 22, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 190, +62, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, +0, 27, 189, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 1, 0, 0, 8, 0, 0, 0, 38, 1, 0, 0, +20, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 212, 62, 3, 0, +2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 67, 189, +10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 1, 0, 0, 8, 0, 0, 0, 40, 1, 0, 0, 20, 0, 0, +0, 0, 0, 143, 0, 59, 23, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 234, 62, 3, 0, 2, 0, 1, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 107, 189, 10, 0, +0, 0, 0, 0, 0, 0, 0, 0, 42, 1, 0, 0, 8, 0, 0, 0, 42, 1, 0, 0, 17, 0, 0, 0, 0, 0, +143, 0, 59, 23, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 63, 3, 0, 2, 0, 1, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 145, 189, 10, 0, 0, 0, 0, 0, +0, 0, 0, 0, 44, 1, 0, 0, 8, 0, 0, 0, 44, 1, 0, 0, 18, 0, 0, 0, 0, 0, 143, 0, 59, +23, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 22, 63, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 184, 189, 10, 0, 0, 0, 0, 0, 0, 0, 0, +0, 46, 1, 0, 0, 8, 0, 0, 0, 46, 1, 0, 0, 21, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, +0, 20, 0, 0, 0, 0, 0, 0, 0, 44, 63, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 226, 189, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 1, +0, 0, 8, 0, 0, 0, 48, 1, 0, 0, 21, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 21, 0, +0, 0, 0, 0, 0, 0, 66, 63, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 6, 2, 0, 0, 11, 190, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 1, 0, 0, 8, +0, 0, 0, 55, 1, 0, 0, 22, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 22, 0, 0, 0, 0, +0, 0, 0, 88, 63, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 6, 2, 0, 0, 54, 190, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 1, 0, 0, 8, 0, 0, 0, +57, 1, 0, 0, 19, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, +110, 63, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, +0, 0, 89, 190, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 1, 0, 0, 8, 0, 0, 0, 60, 1, 0, +0, 22, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 132, 63, 3, +0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 128, +190, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 1, 0, 0, 8, 0, 0, 0, 62, 1, 0, 0, 20, 0, +0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 154, 63, 3, 0, 2, 0, +1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 156, 241, 8, +0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 1, 0, 0, 8, 0, 0, 0, 64, 1, 0, 0, 22, 0, 0, 0, 0, +0, 143, 0, 59, 23, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 176, 63, 3, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 192, 241, 8, 0, 0, 0, +0, 0, 0, 0, 0, 0, 66, 1, 0, 0, 8, 0, 0, 0, 66, 1, 0, 0, 22, 0, 0, 0, 0, 0, 143, +0, 59, 23, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 198, 63, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 237, 241, 8, 0, 0, 0, 0, 0, 0, +0, 0, 0, 68, 1, 0, 0, 8, 0, 0, 0, 68, 1, 0, 0, 18, 0, 0, 0, 0, 0, 143, 0, 59, +23, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 220, 63, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 27, 189, 10, 0, 0, 0, 0, 0, 0, 0, 0, +0, 75, 1, 0, 0, 8, 0, 0, 0, 75, 1, 0, 0, 23, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, +0, 29, 0, 0, 0, 0, 0, 0, 0, 242, 63, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 156, 241, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, +1, 0, 0, 8, 0, 0, 0, 80, 1, 0, 0, 21, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 30, +0, 0, 0, 0, 0, 0, 0, 8, 64, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 6, 2, 0, 0, 192, 241, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 1, 0, 0, +8, 0, 0, 0, 82, 1, 0, 0, 19, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 31, 0, 0, 0, +0, 0, 0, 0, 30, 64, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 6, 2, 0, 0, 237, 241, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 1, 0, 0, 8, 0, 0, +0, 86, 1, 0, 0, 19, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 32, 0, 0, 0, 0, 0, 0, +0, 52, 64, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, +2, 0, 0, 66, 191, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 1, 0, 0, 8, 0, 0, 0, 88, 1, +0, 0, 18, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 74, 64, +3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, +103, 191, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 1, 0, 0, 8, 0, 0, 0, 90, 1, 0, 0, +21, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 96, 64, 3, 0, +2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 143, +191, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 1, 0, 0, 8, 0, 0, 0, 92, 1, 0, 0, 20, 0, +0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 118, 64, 3, 0, 2, 0, +1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 182, 191, 10, +0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 1, 0, 0, 8, 0, 0, 0, 101, 1, 0, 0, 22, 0, 0, 0, +0, 0, 143, 0, 59, 23, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 140, 64, 3, 0, 2, 0, 1, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 147, 188, 10, 0, 0, +0, 0, 0, 0, 0, 0, 0, 146, 1, 0, 0, 8, 0, 0, 0, 146, 1, 0, 0, 19, 0, 0, 0, 0, 0, +143, 0, 59, 23, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 162, 64, 3, 0, 2, 0, 1, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 134, 85, 9, 0, 0, 0, 0, 0, +0, 0, 0, 0, 148, 1, 0, 0, 8, 0, 0, 0, 148, 1, 0, 0, 20, 0, 0, 0, 0, 0, 143, 0, +59, 23, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 184, 64, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 10, 192, 10, 0, 0, 0, 0, 0, 0, 0, +0, 0, 150, 1, 0, 0, 8, 0, 0, 0, 150, 1, 0, 0, 20, 0, 0, 0, 0, 0, 143, 0, 59, 23, +0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 206, 64, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 50, 192, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, +152, 1, 0, 0, 8, 0, 0, 0, 152, 1, 0, 0, 25, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, +40, 0, 0, 0, 0, 0, 0, 0, 228, 64, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 95, 192, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 1, +0, 0, 8, 0, 0, 0, 154, 1, 0, 0, 21, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 41, 0, +0, 0, 0, 0, 0, 0, 250, 64, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 6, 2, 0, 0, 136, 192, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 1, 0, 0, +8, 0, 0, 0, 156, 1, 0, 0, 17, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 42, 0, 0, 0, +0, 0, 0, 0, 16, 65, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 6, 2, 0, 0, 173, 192, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 1, 0, 0, 8, 0, +0, 0, 158, 1, 0, 0, 28, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 43, 0, 0, 0, 0, 0, +0, 0, 38, 65, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +6, 2, 0, 0, 222, 192, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 1, 0, 0, 8, 0, 0, 0, +160, 1, 0, 0, 19, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, +60, 65, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, +0, 0, 5, 193, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 1, 0, 0, 8, 0, 0, 0, 162, 1, +0, 0, 20, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 82, 65, +3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, +45, 193, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 1, 0, 0, 8, 0, 0, 0, 164, 1, 0, 0, +20, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 104, 65, 3, 0, +2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 85, 193, +10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 1, 0, 0, 8, 0, 0, 0, 166, 1, 0, 0, 24, 0, 0, +0, 0, 0, 143, 0, 59, 23, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 126, 65, 3, 0, 2, 0, 1, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 129, 193, 10, 0, +0, 0, 0, 0, 0, 0, 0, 0, 168, 1, 0, 0, 8, 0, 0, 0, 168, 1, 0, 0, 20, 0, 0, 0, 0, +0, 143, 0, 59, 23, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 148, 65, 3, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 169, 193, 10, 0, 0, 0, +0, 0, 0, 0, 0, 0, 170, 1, 0, 0, 8, 0, 0, 0, 170, 1, 0, 0, 20, 0, 0, 0, 0, 0, +143, 0, 59, 23, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 170, 65, 3, 0, 2, 0, 1, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 209, 193, 10, 0, 0, 0, 0, +0, 0, 0, 0, 0, 172, 1, 0, 0, 8, 0, 0, 0, 172, 1, 0, 0, 23, 0, 0, 0, 0, 0, 143, +0, 59, 23, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 192, 65, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 252, 193, 10, 0, 0, 0, 0, 0, 0, +0, 0, 0, 174, 1, 0, 0, 8, 0, 0, 0, 174, 1, 0, 0, 21, 0, 0, 0, 0, 0, 143, 0, 59, +23, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 214, 65, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 37, 194, 10, 0, 0, 0, 0, 0, 0, 0, 0, +0, 176, 1, 0, 0, 8, 0, 0, 0, 176, 1, 0, 0, 23, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, +0, 52, 0, 0, 0, 0, 0, 0, 0, 236, 65, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 80, 194, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, +1, 0, 0, 8, 0, 0, 0, 185, 1, 0, 0, 24, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 53, +0, 0, 0, 0, 0, 0, 0, 2, 66, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 6, 2, 0, 0, 124, 194, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 1, 0, +0, 8, 0, 0, 0, 187, 1, 0, 0, 21, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 54, 0, 0, +0, 0, 0, 0, 0, 24, 66, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 6, 2, 0, 0, 165, 194, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 1, 0, 0, 8, +0, 0, 0, 189, 1, 0, 0, 19, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 55, 0, 0, 0, 0, +0, 0, 0, 46, 66, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 6, 2, 0, 0, 205, 194, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 1, 0, 0, 8, 0, 0, +0, 191, 1, 0, 0, 23, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 56, 0, 0, 0, 0, 0, 0, +0, 68, 66, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, +2, 0, 0, 250, 194, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 1, 0, 0, 8, 0, 0, 0, 193, +1, 0, 0, 19, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 90, +66, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, +0, 34, 195, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 1, 0, 0, 8, 0, 0, 0, 195, 1, 0, +0, 24, 0, 0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 112, 66, 3, +0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 13, +195, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 4, 0, 0, 8, 0, 0, 0, 31, 4, 0, 0, 16, 0, +0, 0, 0, 0, 143, 0, 59, 23, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 134, 66, 3, 0, 2, 0, +1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 123, 195, 10, +0, 1, 0, 0, 0, 4, 0, 0, 0, 97, 195, 10, 0, 25, 67, 1, 0, 66, 73, 10, 0, 110, +195, 10, 0, 33, 4, 0, 0, 8, 0, 0, 0, 33, 4, 0, 0, 17, 0, 0, 0, 0, 0, 143, 0, 59, +23, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 156, 66, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 197, 195, 10, 0, 1, 0, 0, 0, 2, 0, 0, +0, 184, 195, 10, 0, 110, 195, 10, 0, 177, 0, 0, 0, 15, 0, 0, 0, 177, 0, 0, 0, +25, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 178, 11, 0, 238, 186, 7, +0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 187, +0, 0, 0, 12, 0, 0, 0, 187, 0, 0, 0, 28, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, +0, 0, 212, 178, 11, 0, 12, 188, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 230, 0, 0, 0, 15, 0, 0, 0, 230, 0, 0, 0, 22, 0, 0, +0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 178, 11, 0, 34, 188, 7, 0, 2, 0, 1, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 230, 0, 0, 0, 23, +0, 0, 0, 230, 0, 0, 0, 30, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 179, +11, 0, 34, 188, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 6, 0, 0, 237, 0, 0, 0, 15, 0, 0, 0, 237, 0, 0, 0, 22, 0, 0, 0, 0, 0, 10, +0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 179, 11, 0, 56, 188, 7, 0, 2, 0, 1, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 237, 0, 0, 0, 23, 0, 0, 0, +237, 0, 0, 0, 30, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 179, 11, 0, +56, 188, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, +0, 0, 240, 0, 0, 0, 21, 0, 0, 0, 240, 0, 0, 0, 28, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, +0, 0, 0, 0, 0, 118, 179, 11, 0, 78, 188, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 243, 0, 0, 0, 15, 0, 0, 0, 243, 0, 0, 0, +25, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 179, 11, 0, 122, 188, 7, +0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 243, +0, 0, 0, 26, 0, 0, 0, 243, 0, 0, 0, 36, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, +0, 0, 28, 180, 11, 0, 122, 188, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 15, 0, 0, 0, 0, 1, 0, 0, 22, 0, 0, 0, +0, 0, 17, 0, 59, 23, 0, 0, 64, 0, 0, 0, 62, 180, 11, 0, 188, 188, 7, 0, 2, 0, 1, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 22, 1, 0, 0, 3, 3, 0, 1, 0, 0, 0, 2, +0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 10, 0, 0, 0, 1, 1, 0, 0, 17, 0, 0, 0, 0, 0, 9, +0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 36, 1, 0, 210, 188, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 169, 21, 1, 0, 1, 2, 0, 0, 2, 1, 0, 0, 8, 0, 0, 0, 2, 1, +0, 0, 15, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 36, 1, 0, 232, 188, +7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 22, 1, 0, 1, 2, 0, 0, +3, 1, 0, 0, 2, 0, 0, 0, 3, 1, 0, 0, 9, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, +0, 92, 180, 11, 0, 188, 188, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 15, 0, 0, 0, 0, 1, 0, 0, 22, 0, 0, 0, 0, +0, 17, 0, 59, 23, 0, 0, 65, 0, 0, 0, 62, 180, 11, 0, 188, 188, 7, 0, 2, 0, 1, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 22, 1, 0, 0, 3, 3, 0, 1, 0, 0, 0, 2, 0, +0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 10, 0, 0, 0, 1, 1, 0, 0, 17, 0, 0, 0, 0, 0, 9, 0, +0, 0, 0, 0, 0, 0, 0, 0, 30, 36, 1, 0, 210, 188, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 169, 21, 1, 0, 1, 2, 0, 64, 2, 1, 0, 0, 8, 0, 0, 0, 2, 1, +0, 0, 15, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 36, 1, 0, 232, 188, +7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 22, 1, 0, 1, 2, 0, 0, +6, 1, 0, 0, 14, 0, 0, 0, 6, 1, 0, 0, 26, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, +0, 0, 152, 180, 11, 0, 254, 188, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 6, 1, 0, 0, 43, 0, 0, 0, 6, 1, 0, 0, 44, 0, 0, 0, +0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 180, 11, 0, 114, 80, 3, 0, 2, 0, 1, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 6, 1, 0, 0, 61, 0, +0, 0, 6, 1, 0, 0, 62, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 180, 11, +0, 136, 80, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, +2, 0, 0, 22, 1, 0, 0, 14, 0, 0, 0, 22, 1, 0, 0, 26, 0, 0, 0, 0, 0, 7, 0, 0, 0, +0, 0, 0, 0, 0, 0, 8, 181, 11, 0, 42, 189, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 22, 1, 0, 0, 37, 0, 0, 0, 22, 1, 0, 0, +41, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 181, 11, 0, 150, 2, 1, 0, +2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 22, 1, +0, 0, 49, 0, 0, 0, 22, 1, 0, 0, 55, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, +176, 36, 1, 0, 86, 189, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 1, 2, 0, 0, 22, 1, 0, 0, 63, 0, 0, 0, 22, 1, 0, 0, 69, 0, 0, 0, 0, 0, +7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 36, 1, 0, 108, 189, 7, 0, 2, 0, 1, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 22, 1, 0, 0, 77, 0, 0, 0, +22, 1, 0, 0, 83, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 36, 1, 0, +130, 189, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, +2, 0, 0, 109, 1, 0, 0, 13, 0, 0, 0, 109, 1, 0, 0, 26, 0, 0, 0, 0, 0, 7, 0, 59, +23, 0, 0, 66, 0, 0, 0, 60, 181, 11, 0, 152, 189, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 110, 1, 0, 0, 1, 0, 0, 0, 110, +1, 0, 0, 10, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 181, 11, 0, 174, +189, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, +0, 111, 1, 0, 0, 1, 0, 0, 0, 111, 1, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, +0, 0, 0, 0, 136, 181, 11, 0, 196, 189, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 113, 1, 0, 0, 1, 0, 0, 0, 113, 1, 0, 0, 13, +0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 181, 11, 0, 218, 189, 7, 0, 2, +0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 114, 1, 0, +0, 1, 0, 0, 0, 114, 1, 0, 0, 19, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, +220, 181, 11, 0, 240, 189, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 2, 0, 0, 115, 1, 0, 0, 1, 0, 0, 0, 115, 1, 0, 0, 16, 0, 0, 0, 0, +0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 182, 11, 0, 6, 190, 7, 0, 2, 0, 1, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 116, 1, 0, 0, 1, 0, 0, 0, +116, 1, 0, 0, 17, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 182, 11, 0, +28, 190, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, +0, 0, 119, 1, 0, 0, 1, 0, 0, 0, 119, 1, 0, 0, 9, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, +0, 0, 0, 0, 0, 90, 182, 11, 0, 50, 190, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 120, 1, 0, 0, 1, 0, 0, 0, 120, 1, 0, 0, +13, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 182, 11, 0, 72, 190, 7, 0, +2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 122, 1, +0, 0, 1, 0, 0, 0, 122, 1, 0, 0, 9, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, +174, 182, 11, 0, 94, 190, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 2, 0, 0, 123, 1, 0, 0, 1, 0, 0, 0, 123, 1, 0, 0, 13, 0, 0, 0, 0, +0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 182, 11, 0, 116, 190, 7, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 125, 1, 0, 0, 1, 0, 0, +0, 125, 1, 0, 0, 18, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 183, 11, 0, +138, 190, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +2, 0, 0, 128, 1, 0, 0, 1, 0, 0, 0, 128, 1, 0, 0, 15, 0, 0, 0, 0, 0, 7, 0, 0, 0, +0, 0, 0, 0, 0, 0, 44, 183, 11, 0, 160, 190, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 129, 1, 0, 0, 1, 0, 0, 0, 129, 1, 0, +0, 9, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 183, 11, 0, 182, 190, 7, +0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 130, +1, 0, 0, 1, 0, 0, 0, 130, 1, 0, 0, 13, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, +0, 128, 183, 11, 0, 204, 190, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 2, 0, 0, 132, 1, 0, 0, 1, 0, 0, 0, 132, 1, 0, 0, 15, 0, 0, 0, +0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 183, 11, 0, 226, 190, 7, 0, 2, 0, 1, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 133, 1, 0, 0, 1, 0, +0, 0, 133, 1, 0, 0, 8, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 183, +11, 0, 248, 190, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 2, 0, 0, 134, 1, 0, 0, 1, 0, 0, 0, 134, 1, 0, 0, 12, 0, 0, 0, 0, 0, 7, 0, +0, 0, 0, 0, 0, 0, 0, 0, 254, 183, 11, 0, 14, 191, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 135, 1, 0, 0, 1, 0, 0, 0, 135, +1, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 184, 11, 0, 36, +191, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, +0, 136, 1, 0, 0, 1, 0, 0, 0, 136, 1, 0, 0, 18, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, +0, 0, 0, 0, 82, 184, 11, 0, 58, 191, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 138, 1, 0, 0, 2, 0, 0, 0, 138, 1, 0, 0, 15, +0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 184, 11, 0, 152, 189, 7, 0, 2, +0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 109, 1, 0, +0, 13, 0, 0, 0, 109, 1, 0, 0, 26, 0, 0, 0, 0, 0, 7, 0, 59, 23, 0, 0, 67, 0, 0, +0, 60, 181, 11, 0, 152, 189, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 2, 0, 0, 110, 1, 0, 0, 1, 0, 0, 0, 110, 1, 0, 0, 10, 0, 0, 0, +0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 181, 11, 0, 174, 189, 7, 0, 2, 0, 1, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 111, 1, 0, 0, 1, 0, +0, 0, 111, 1, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 181, +11, 0, 196, 189, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 2, 0, 0, 113, 1, 0, 0, 1, 0, 0, 0, 113, 1, 0, 0, 13, 0, 0, 0, 0, 0, 7, 0, +0, 0, 0, 0, 0, 0, 0, 0, 178, 181, 11, 0, 218, 189, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 114, 1, 0, 0, 1, 0, 0, 0, 114, +1, 0, 0, 19, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 181, 11, 0, 240, +189, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, +0, 115, 1, 0, 0, 1, 0, 0, 0, 115, 1, 0, 0, 16, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, +0, 0, 0, 0, 6, 182, 11, 0, 6, 190, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 116, 1, 0, 0, 1, 0, 0, 0, 116, 1, 0, 0, 17, 0, +0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 182, 11, 0, 28, 190, 7, 0, 2, 0, +1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 119, 1, 0, 0, +1, 0, 0, 0, 119, 1, 0, 0, 9, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, +182, 11, 0, 50, 190, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 2, 0, 0, 120, 1, 0, 0, 1, 0, 0, 0, 120, 1, 0, 0, 13, 0, 0, 0, 0, 0, 7, +0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 182, 11, 0, 72, 190, 7, 0, 2, 0, 1, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 122, 1, 0, 0, 1, 0, 0, 0, +122, 1, 0, 0, 9, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 182, 11, 0, +94, 190, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, +0, 0, 123, 1, 0, 0, 1, 0, 0, 0, 123, 1, 0, 0, 13, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, +0, 0, 0, 0, 0, 216, 182, 11, 0, 116, 190, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 125, 1, 0, 0, 1, 0, 0, 0, 125, 1, 0, 0, +18, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 183, 11, 0, 138, 190, 7, 0, +2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 128, 1, +0, 0, 1, 0, 0, 0, 128, 1, 0, 0, 15, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, +44, 183, 11, 0, 160, 190, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 2, 0, 0, 129, 1, 0, 0, 1, 0, 0, 0, 129, 1, 0, 0, 9, 0, 0, 0, 0, +0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 183, 11, 0, 182, 190, 7, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 130, 1, 0, 0, 1, 0, 0, +0, 130, 1, 0, 0, 13, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 183, 11, +0, 204, 190, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 2, 0, 0, 132, 1, 0, 0, 1, 0, 0, 0, 132, 1, 0, 0, 15, 0, 0, 0, 0, 0, 7, 0, 0, +0, 0, 0, 0, 0, 0, 0, 170, 183, 11, 0, 226, 190, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 133, 1, 0, 0, 1, 0, 0, 0, 133, 1, +0, 0, 8, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 183, 11, 0, 248, 190, +7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, +134, 1, 0, 0, 1, 0, 0, 0, 134, 1, 0, 0, 12, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, +0, 0, 0, 254, 183, 11, 0, 14, 191, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 135, 1, 0, 0, 1, 0, 0, 0, 135, 1, 0, 0, 14, 0, +0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 184, 11, 0, 36, 191, 7, 0, 2, 0, +1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 136, 1, 0, 0, +1, 0, 0, 0, 136, 1, 0, 0, 18, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, +184, 11, 0, 58, 191, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 2, 0, 0, 199, 1, 0, 0, 15, 0, 0, 0, 199, 1, 0, 0, 23, 0, 0, 0, 0, 0, +17, 0, 59, 23, 0, 0, 68, 0, 0, 0, 158, 184, 11, 0, 80, 191, 7, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 34, 1, 0, 0, 3, 3, 0, 1, 0, 0, 0, 2, 0, 0, +0, 0, 0, 0, 0, 200, 1, 0, 0, 14, 0, 0, 0, 200, 1, 0, 0, 22, 0, 0, 0, 0, 0, 9, 0, +0, 0, 0, 0, 0, 0, 0, 0, 64, 36, 1, 0, 102, 191, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 84, 23, 1, 0, 1, 2, 0, 0, 202, 1, 0, 0, 14, 0, 0, 0, 202, +1, 0, 0, 22, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 36, 1, 0, 124, +191, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 23, 1, 0, 1, 2, +0, 64, 203, 1, 0, 0, 9, 0, 0, 0, 203, 1, 0, 0, 24, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, +0, 0, 0, 0, 0, 30, 36, 1, 0, 146, 191, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 106, 22, 1, 0, 1, 2, 0, 0, 204, 1, 0, 0, 9, 0, 0, 0, 204, 1, 0, 0, +22, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 36, 1, 0, 168, 191, 7, 0, +2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 24, 1, 0, 1, 2, 0, 0, 205, +1, 0, 0, 9, 0, 0, 0, 205, 1, 0, 0, 26, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, +0, 30, 36, 1, 0, 190, 191, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +163, 24, 1, 0, 1, 2, 0, 64, 206, 1, 0, 0, 9, 0, 0, 0, 206, 1, 0, 0, 19, 0, 0, 0, +0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 36, 1, 0, 212, 191, 7, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 24, 1, 0, 1, 2, 0, 64, 207, 1, 0, 0, 2, 0, +0, 0, 207, 1, 0, 0, 10, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 184, +11, 0, 80, 191, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 6, 0, 0, 199, 1, 0, 0, 15, 0, 0, 0, 199, 1, 0, 0, 23, 0, 0, 0, 0, 0, 17, +0, 59, 23, 0, 0, 69, 0, 0, 0, 158, 184, 11, 0, 80, 191, 7, 0, 2, 0, 1, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 34, 1, 0, 0, 3, 3, 64, 1, 0, 0, 0, 2, 0, 0, 0, +0, 0, 0, 0, 200, 1, 0, 0, 14, 0, 0, 0, 200, 1, 0, 0, 22, 0, 0, 0, 0, 0, 9, 0, 0, +0, 0, 0, 0, 0, 0, 0, 64, 36, 1, 0, 102, 191, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 84, 23, 1, 0, 1, 2, 0, 64, 202, 1, 0, 0, 14, 0, 0, 0, 202, 1, +0, 0, 22, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 36, 1, 0, 124, 191, +7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 23, 1, 0, 1, 2, 0, 0, +203, 1, 0, 0, 9, 0, 0, 0, 203, 1, 0, 0, 24, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, +0, 0, 0, 30, 36, 1, 0, 146, 191, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 106, 22, 1, 0, 1, 2, 0, 0, 204, 1, 0, 0, 9, 0, 0, 0, 204, 1, 0, 0, 22, 0, +0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 36, 1, 0, 168, 191, 7, 0, 2, 0, 1, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 24, 1, 0, 1, 2, 0, 0, 205, 1, 0, 0, +9, 0, 0, 0, 205, 1, 0, 0, 26, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, +36, 1, 0, 190, 191, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, +24, 1, 0, 1, 2, 0, 0, 206, 1, 0, 0, 9, 0, 0, 0, 206, 1, 0, 0, 19, 0, 0, 0, 0, 0, +9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 36, 1, 0, 212, 191, 7, 0, 2, 0, 1, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 24, 1, 0, 1, 2, 0, 64, 210, 1, 0, 0, 15, 0, 0, +0, 210, 1, 0, 0, 26, 0, 0, 0, 0, 0, 17, 0, 59, 23, 0, 0, 70, 0, 0, 0, 222, 184, +11, 0, 234, 191, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 34, +1, 0, 0, 3, 3, 64, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 211, 1, 0, 0, 7, 0, 0, 0, +211, 1, 0, 0, 17, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 36, 1, 0, 0, +192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 21, 1, 0, 1, 2, +0, 64, 212, 1, 0, 0, 8, 0, 0, 0, 212, 1, 0, 0, 18, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, +0, 0, 0, 0, 0, 30, 36, 1, 0, 22, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 106, 22, 1, 0, 1, 2, 0, 0, 213, 1, 0, 0, 8, 0, 0, 0, 213, 1, 0, 0, +20, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 36, 1, 0, 44, 192, 7, 0, 2, +0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 24, 1, 0, 1, 2, 0, 0, 214, 1, +0, 0, 8, 0, 0, 0, 214, 1, 0, 0, 21, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, +30, 36, 1, 0, 66, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +163, 24, 1, 0, 1, 2, 0, 64, 215, 1, 0, 0, 14, 0, 0, 0, 215, 1, 0, 0, 27, 0, 0, +0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 36, 1, 0, 88, 192, 7, 0, 2, 0, 1, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 32, 1, 0, 1, 2, 0, 64, 216, 1, 0, 0, +14, 0, 0, 0, 216, 1, 0, 0, 27, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, +36, 1, 0, 110, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, +78, 1, 0, 1, 2, 0, 0, 217, 1, 0, 0, 2, 0, 0, 0, 217, 1, 0, 0, 13, 0, 0, 0, 0, 0, +7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 184, 11, 0, 234, 191, 7, 0, 2, 0, 1, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 210, 1, 0, 0, 15, 0, 0, 0, +210, 1, 0, 0, 26, 0, 0, 0, 0, 0, 17, 0, 59, 23, 0, 0, 71, 0, 0, 0, 222, 184, 11, +0, 234, 191, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 34, 1, 0, +0, 3, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 211, 1, 0, 0, 7, 0, 0, 0, 211, +1, 0, 0, 17, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 36, 1, 0, 0, 192, +7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 21, 1, 0, 1, 2, 0, +64, 212, 1, 0, 0, 8, 0, 0, 0, 212, 1, 0, 0, 18, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, +0, 0, 0, 0, 30, 36, 1, 0, 22, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 106, 22, 1, 0, 1, 2, 0, 0, 213, 1, 0, 0, 8, 0, 0, 0, 213, 1, 0, 0, 20, +0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 36, 1, 0, 44, 192, 7, 0, 2, 0, +1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 24, 1, 0, 1, 2, 0, 0, 214, 1, 0, +0, 8, 0, 0, 0, 214, 1, 0, 0, 21, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, +30, 36, 1, 0, 66, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +163, 24, 1, 0, 1, 2, 0, 0, 215, 1, 0, 0, 14, 0, 0, 0, 215, 1, 0, 0, 27, 0, 0, 0, +0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 36, 1, 0, 88, 192, 7, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 32, 1, 0, 1, 2, 0, 64, 216, 1, 0, 0, 14, +0, 0, 0, 216, 1, 0, 0, 27, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 36, +1, 0, 110, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 78, +1, 0, 1, 2, 0, 0, 226, 1, 0, 0, 6, 0, 0, 0, 226, 1, 0, 0, 17, 0, 0, 0, 0, 0, 12, +0, 59, 23, 0, 0, 72, 0, 0, 0, 30, 185, 11, 0, 132, 192, 7, 0, 2, 0, 1, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +48, 0, 0, 0, 0, 0, 0, 0, 226, 1, 0, 0, 23, 0, 0, 0, 226, 1, 0, 0, 28, 0, 0, 0, +0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 6, 1, 0, 224, 118, 2, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 226, 1, 0, 0, 35, 0, 0, +0, 226, 1, 0, 0, 40, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 6, 1, 0, +246, 118, 2, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, +0, 0, 0, 226, 1, 0, 0, 47, 0, 0, 0, 226, 1, 0, 0, 52, 0, 0, 0, 0, 0, 7, 0, 0, 0, +0, 0, 0, 0, 0, 0, 214, 6, 1, 0, 154, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 238, 1, 0, 0, 6, 0, 0, 0, 238, 1, 0, 0, +18, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 73, 0, 0, 0, 108, 101, 2, 0, 176, 192, +7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 238, 1, 0, 0, 23, 0, 0, 0, 238, +1, 0, 0, 26, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 1, 1, 0, 198, +192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, +0, 251, 1, 0, 0, 5, 0, 0, 0, 251, 1, 0, 0, 19, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, +0, 74, 0, 0, 0, 100, 185, 11, 0, 220, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, +0, 0, 0, 0, 251, 1, 0, 0, 30, 0, 0, 0, 251, 1, 0, 0, 33, 0, 0, 0, 0, 0, 7, 0, 0, +0, 0, 0, 0, 0, 0, 0, 82, 185, 11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 118, 2, 0, 0, 5, 0, 0, 0, 118, 2, +0, 0, 17, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 75, 0, 0, 0, 126, 185, 11, 0, 8, +193, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 118, 2, 0, 0, 27, 0, 0, 0, +118, 2, 0, 0, 30, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 185, 11, 0, +242, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, +0, 0, 0, 118, 2, 0, 0, 44, 0, 0, 0, 118, 2, 0, 0, 48, 0, 0, 0, 0, 0, 7, 0, 0, 0, +0, 0, 0, 0, 0, 0, 90, 35, 1, 0, 114, 3, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 118, 2, 0, 0, 63, 0, 0, 0, 118, 2, 0, 0, +68, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 36, 1, 0, 124, 218, 2, 0, +2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 118, 2, +0, 0, 81, 0, 0, 0, 118, 2, 0, 0, 85, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, +0, 178, 178, 11, 0, 66, 162, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 1, 0, 0, 0, 134, 2, 0, 0, 5, 0, 0, 0, 134, 2, 0, 0, 17, 0, 0, 0, +0, 0, 12, 0, 59, 23, 0, 0, 76, 0, 0, 0, 164, 185, 11, 0, 30, 193, 7, 0, 2, 0, 1, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 104, 0, 114, 0, 0, 0, 0, 0, 134, 2, 0, 0, 27, 0, 0, 0, 134, 2, 0, 0, 30, +0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 185, 11, 0, 242, 192, 7, 0, 2, +0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 134, 2, 0, +0, 44, 0, 0, 0, 134, 2, 0, 0, 48, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, +90, 35, 1, 0, 114, 3, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 1, 0, 0, 0, 149, 2, 0, 0, 5, 0, 0, 0, 149, 2, 0, 0, 19, 0, 0, 0, 0, 0, +12, 0, 59, 23, 0, 0, 77, 0, 0, 0, 194, 185, 11, 0, 52, 193, 7, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +96, 0, 46, 0, 0, 0, 0, 0, 149, 2, 0, 0, 29, 0, 0, 0, 149, 2, 0, 0, 32, 0, 0, 0, +0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 185, 11, 0, 242, 192, 7, 0, 2, 0, 1, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 149, 2, 0, 0, 51, 0, +0, 0, 149, 2, 0, 0, 53, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 178, +11, 0, 50, 195, 5, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 1, 0, 0, 0, 174, 2, 0, 0, 5, 0, 0, 0, 174, 2, 0, 0, 18, 0, 0, 0, 0, 0, 12, 0, +59, 23, 0, 0, 78, 0, 0, 0, 224, 185, 11, 0, 74, 193, 7, 0, 2, 0, 1, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, +0, 111, 0, 0, 0, 0, 0, 174, 2, 0, 0, 28, 0, 0, 0, 174, 2, 0, 0, 31, 0, 0, 0, 0, +0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 185, 11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 174, 2, 0, 0, 45, 0, 0, +0, 174, 2, 0, 0, 49, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 35, 1, 0, +114, 3, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, +0, 0, 174, 2, 0, 0, 64, 0, 0, 0, 174, 2, 0, 0, 69, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, +0, 0, 0, 0, 0, 64, 36, 1, 0, 124, 218, 2, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 193, 2, 0, 0, 5, 0, 0, 0, 193, 2, 0, 0, 20, +0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 79, 0, 0, 0, 2, 186, 11, 0, 96, 193, 7, 0, +2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 193, 2, 0, 0, 30, 0, 0, 0, 193, 2, 0, +0, 33, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 185, 11, 0, 242, 192, 7, +0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 193, +2, 0, 0, 52, 0, 0, 0, 193, 2, 0, 0, 54, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, +0, 0, 212, 178, 11, 0, 50, 195, 5, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 193, 2, 0, 0, 69, 0, 0, 0, 193, 2, 0, 0, 74, 0, 0, +0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 36, 1, 0, 124, 218, 2, 0, 2, 0, 1, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 201, 2, 0, 0, 5, 0, +0, 0, 201, 2, 0, 0, 17, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 80, 0, 0, 0, 54, +186, 11, 0, 118, 193, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 201, 2, +0, 0, 27, 0, 0, 0, 201, 2, 0, 0, 30, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, +0, 64, 185, 11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 1, 0, 0, 0, 201, 2, 0, 0, 42, 0, 0, 0, 201, 2, 0, 0, 46, 0, 0, 0, +0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 186, 11, 0, 140, 193, 7, 0, 2, 0, 1, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 209, 2, 0, 0, 5, 0, +0, 0, 209, 2, 0, 0, 17, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 81, 0, 0, 0, 102, +186, 11, 0, 162, 193, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 209, 2, +0, 0, 27, 0, 0, 0, 209, 2, 0, 0, 30, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, +0, 64, 185, 11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 1, 0, 0, 0, 209, 2, 0, 0, 45, 0, 0, 0, 209, 2, 0, 0, 49, 0, 0, 0, +0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 186, 11, 0, 140, 193, 7, 0, 2, 0, 1, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 230, 2, 0, 0, 5, 0, +0, 0, 230, 2, 0, 0, 17, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 82, 0, 0, 0, 132, +186, 11, 0, 184, 193, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 230, 2, +0, 0, 27, 0, 0, 0, 230, 2, 0, 0, 30, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, +0, 64, 185, 11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 1, 0, 0, 0, 230, 2, 0, 0, 36, 0, 0, 0, 230, 2, 0, 0, 41, 0, 0, 0, +0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 1, 1, 0, 206, 193, 7, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 240, 2, 0, 0, 5, 0, 0, +0, 240, 2, 0, 0, 18, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 83, 0, 0, 0, 162, 186, +11, 0, 228, 193, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 240, 2, 0, 0, +28, 0, 0, 0, 240, 2, 0, 0, 31, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, +185, 11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 1, 0, 0, 0, 0, 3, 0, 0, 5, 0, 0, 0, 0, 3, 0, 0, 22, 0, 0, 0, 0, 0, 12, +0, 59, 23, 0, 0, 84, 0, 0, 0, 188, 186, 11, 0, 250, 193, 7, 0, 2, 0, 1, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +96, 0, 46, 0, 0, 0, 0, 0, 0, 3, 0, 0, 32, 0, 0, 0, 0, 3, 0, 0, 35, 0, 0, 0, 0, +0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 185, 11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, 0, 0, 50, 0, 0, +0, 0, 3, 0, 0, 55, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 36, 1, 0, +124, 218, 2, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, +0, 0, 0, 0, 3, 0, 0, 61, 0, 0, 0, 0, 3, 0, 0, 66, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, +0, 0, 0, 0, 0, 148, 1, 1, 0, 16, 194, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 12, 3, 0, 0, 5, 0, 0, 0, 12, 3, 0, 0, 22, 0, +0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 85, 0, 0, 0, 222, 186, 11, 0, 38, 194, 7, 0, 2, +0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 12, 3, 0, 0, 32, 0, 0, 0, 12, 3, 0, 0, 35, +0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 185, 11, 0, 242, 192, 7, 0, 2, +0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 12, 3, 0, +0, 51, 0, 0, 0, 12, 3, 0, 0, 56, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, +126, 94, 2, 0, 124, 218, 2, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 1, 0, 0, 0, 26, 3, 0, 0, 5, 0, 0, 0, 26, 3, 0, 0, 21, 0, 0, 0, 0, 0, +12, 0, 59, 23, 0, 0, 86, 0, 0, 0, 252, 186, 11, 0, 60, 194, 7, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +96, 0, 46, 0, 0, 0, 0, 0, 26, 3, 0, 0, 31, 0, 0, 0, 26, 3, 0, 0, 34, 0, 0, 0, 0, +0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 185, 11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 26, 3, 0, 0, 49, 0, 0, +0, 26, 3, 0, 0, 53, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 240, 1, 0, +114, 3, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, +0, 0, 42, 3, 0, 0, 5, 0, 0, 0, 42, 3, 0, 0, 19, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, +0, 87, 0, 0, 0, 44, 187, 11, 0, 82, 194, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, +0, 0, 0, 42, 3, 0, 0, 29, 0, 0, 0, 42, 3, 0, 0, 32, 0, 0, 0, 0, 0, 7, 0, 0, 0, +0, 0, 0, 0, 0, 0, 64, 185, 11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 42, 3, 0, 0, 52, 0, 0, 0, 42, 3, 0, 0, +54, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 187, 11, 0, 50, 195, 5, 0, +2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 76, 3, +0, 0, 5, 0, 0, 0, 76, 3, 0, 0, 24, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 88, 0, 0, +0, 74, 187, 11, 0, 104, 194, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 76, +3, 0, 0, 34, 0, 0, 0, 76, 3, 0, 0, 37, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, +0, 64, 185, 11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 1, 0, 0, 0, 76, 3, 0, 0, 46, 0, 0, 0, 76, 3, 0, 0, 50, 0, 0, 0, +0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 36, 1, 0, 120, 170, 1, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 95, 3, 0, 0, 5, 0, 0, +0, 95, 3, 0, 0, 27, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 89, 0, 0, 0, 104, 187, +11, 0, 126, 194, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 95, 3, 0, 0, +37, 0, 0, 0, 95, 3, 0, 0, 40, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, +185, 11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 1, 0, 0, 0, 95, 3, 0, 0, 55, 0, 0, 0, 95, 3, 0, 0, 62, 0, 0, 0, 0, 0, +7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 36, 1, 0, 148, 194, 7, 0, 2, 0, 1, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 107, 3, 0, 0, 5, 0, 0, 0, +107, 3, 0, 0, 27, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 90, 0, 0, 0, 222, 186, 11, +0, 170, 194, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 107, 3, 0, 0, 37, +0, 0, 0, 107, 3, 0, 0, 40, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 185, +11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 1, 0, 0, 0, 107, 3, 0, 0, 56, 0, 0, 0, 107, 3, 0, 0, 63, 0, 0, 0, 0, 0, 7, 0, +0, 0, 0, 0, 0, 0, 0, 0, 126, 94, 2, 0, 148, 194, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 127, 3, 0, 0, 5, 0, 0, 0, 127, +3, 0, 0, 23, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 91, 0, 0, 0, 134, 187, 11, 0, +192, 194, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, +2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 127, 3, 0, 0, 33, 0, +0, 0, 127, 3, 0, 0, 36, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 185, +11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 1, 0, 0, 0, 127, 3, 0, 0, 46, 0, 0, 0, 127, 3, 0, 0, 49, 0, 0, 0, 0, 0, 7, 0, +0, 0, 0, 0, 0, 0, 0, 0, 118, 179, 11, 0, 214, 194, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 136, 3, 0, 0, 5, 0, 0, 0, 136, +3, 0, 0, 27, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 92, 0, 0, 0, 164, 187, 11, 0, +236, 194, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, +2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 136, 3, 0, 0, 37, 0, +0, 0, 136, 3, 0, 0, 40, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 185, +11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 1, 0, 0, 0, 144, 3, 0, 0, 5, 0, 0, 0, 144, 3, 0, 0, 24, 0, 0, 0, 0, 0, 12, 0, +59, 23, 0, 0, 93, 0, 0, 0, 190, 187, 11, 0, 2, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, +0, 46, 0, 0, 0, 0, 0, 144, 3, 0, 0, 34, 0, 0, 0, 144, 3, 0, 0, 37, 0, 0, 0, 0, +0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 185, 11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 144, 3, 0, 0, 45, 0, 0, +0, 144, 3, 0, 0, 48, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 36, 1, 0, +244, 141, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, +0, 0, 0, 151, 3, 0, 0, 6, 0, 0, 0, 151, 3, 0, 0, 25, 0, 0, 0, 0, 0, 12, 0, 59, +23, 0, 0, 94, 0, 0, 0, 220, 187, 11, 0, 24, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, +0, 0, 0, 0, 0, 0, 151, 3, 0, 0, 35, 0, 0, 0, 151, 3, 0, 0, 38, 0, 0, 0, 0, 0, 7, +0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 185, 11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 159, 3, 0, 0, 13, 0, 0, 0, +159, 3, 0, 0, 28, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 188, 11, 0, +46, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, +0, 0, 159, 3, 0, 0, 38, 0, 0, 0, 159, 3, 0, 0, 41, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, +0, 0, 0, 0, 0, 64, 185, 11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 159, 3, 0, 0, 55, 0, 0, 0, 159, 3, 0, 0, +58, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 35, 1, 0, 140, 163, 3, 0, +2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 168, 3, +0, 0, 5, 0, 0, 0, 168, 3, 0, 0, 23, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 95, 0, +0, 0, 72, 188, 11, 0, 68, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, +168, 3, 0, 0, 33, 0, 0, 0, 168, 3, 0, 0, 36, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, +0, 0, 0, 64, 185, 11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 168, 3, 0, 0, 55, 0, 0, 0, 168, 3, 0, 0, 59, 0, +0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 188, 11, 0, 50, 28, 7, 0, 2, 0, 1, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 204, 3, 0, 0, 5, +0, 0, 0, 204, 3, 0, 0, 18, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 96, 0, 0, 0, 138, +188, 11, 0, 90, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 112, 45, 103, 0, 0, 0, 0, 204, 3, +0, 0, 28, 0, 0, 0, 204, 3, 0, 0, 31, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, +0, 64, 185, 11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 1, 0, 0, 0, 204, 3, 0, 0, 42, 0, 0, 0, 204, 3, 0, 0, 48, 0, 0, 0, +0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 188, 11, 0, 226, 14, 1, 0, 2, 0, 1, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 204, 3, 0, 0, 63, 0, +0, 0, 204, 3, 0, 0, 68, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 36, 1, +0, 124, 218, 2, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +1, 0, 0, 0, 204, 3, 0, 0, 80, 0, 0, 0, 204, 3, 0, 0, 83, 0, 0, 0, 0, 0, 7, 0, 0, +0, 0, 0, 0, 0, 0, 0, 120, 188, 11, 0, 112, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 210, 3, 0, 0, 9, 0, 0, 0, 210, 3, +0, 0, 20, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 97, 0, 0, 0, 176, 188, 11, 0, 134, +195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 210, 3, 0, 0, 30, 0, 0, 0, +210, 3, 0, 0, 33, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 188, 11, 0, +112, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, +0, 0, 0, 221, 3, 0, 0, 7, 0, 0, 0, 221, 3, 0, 0, 17, 0, 0, 0, 0, 0, 12, 0, 59, +23, 0, 0, 98, 0, 0, 0, 202, 188, 11, 0, 156, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, +0, 0, 0, 0, 0, 0, 221, 3, 0, 0, 27, 0, 0, 0, 221, 3, 0, 0, 30, 0, 0, 0, 0, 0, 7, +0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 188, 11, 0, 112, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 239, 3, 0, 0, 5, 0, 0, 0, +239, 3, 0, 0, 19, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 99, 0, 0, 0, 228, 188, 11, +0, 178, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 239, 3, 0, 0, 29, +0, 0, 0, 239, 3, 0, 0, 32, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, +188, 11, 0, 112, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 1, 0, 0, 0, 249, 3, 0, 0, 5, 0, 0, 0, 249, 3, 0, 0, 18, 0, 0, 0, 0, 0, +12, 0, 59, 23, 0, 0, 100, 0, 0, 0, 254, 188, 11, 0, 200, 195, 7, 0, 2, 0, 1, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 96, 0, 46, 0, 0, 0, 0, 0, 249, 3, 0, 0, 28, 0, 0, 0, 249, 3, 0, 0, 31, 0, 0, +0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 188, 11, 0, 112, 195, 7, 0, 2, 0, 1, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 12, 4, 0, 0, 5, +0, 0, 0, 12, 4, 0, 0, 18, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 101, 0, 0, 0, 254, +188, 11, 0, 222, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 12, 4, 0, +0, 28, 0, 0, 0, 12, 4, 0, 0, 31, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, +102, 188, 11, 0, 112, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 1, 0, 0, 0, 28, 4, 0, 0, 5, 0, 0, 0, 28, 4, 0, 0, 18, 0, 0, 0, 0, 0, +12, 0, 59, 23, 0, 0, 102, 0, 0, 0, 228, 188, 11, 0, 244, 195, 7, 0, 2, 0, 1, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 96, 0, 46, 0, 0, 0, 0, 0, 28, 4, 0, 0, 28, 0, 0, 0, 28, 4, 0, 0, 31, 0, 0, 0, +0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 188, 11, 0, 112, 195, 7, 0, 2, 0, 1, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 103, 4, 0, 0, 5, 0, +0, 0, 103, 4, 0, 0, 17, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 103, 0, 0, 0, 42, +189, 11, 0, 10, 196, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 103, 4, 0, +0, 27, 0, 0, 0, 103, 4, 0, 0, 30, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, +102, 188, 11, 0, 112, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 1, 0, 0, 0, 103, 4, 0, 0, 44, 0, 0, 0, 103, 4, 0, 0, 48, 0, 0, 0, 0, +0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 35, 1, 0, 114, 11, 1, 0, 2, 0, 1, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 103, 4, 0, 0, 63, 0, 0, 0, +103, 4, 0, 0, 68, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 36, 1, 0, +124, 218, 2, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, +0, 0, 0, 103, 4, 0, 0, 79, 0, 0, 0, 103, 4, 0, 0, 82, 0, 0, 0, 0, 0, 7, 0, 0, 0, +0, 0, 0, 0, 0, 0, 24, 189, 11, 0, 32, 196, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 117, 4, 0, 0, 5, 0, 0, 0, 117, 4, 0, +0, 13, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 104, 0, 0, 0, 80, 189, 11, 0, 54, +196, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 117, 4, 0, 0, 23, 0, 0, 0, +117, 4, 0, 0, 26, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 188, 11, 0, +112, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, +0, 0, 0, 117, 4, 0, 0, 36, 0, 0, 0, 117, 4, 0, 0, 39, 0, 0, 0, 0, 0, 7, 0, 0, 0, +0, 0, 0, 0, 0, 0, 118, 179, 11, 0, 32, 196, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 117, 4, 0, 0, 51, 0, 0, 0, 117, 4, 0, +0, 55, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 186, 11, 0, 140, 193, 7, +0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 126, +4, 0, 0, 4, 0, 0, 0, 126, 4, 0, 0, 17, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 105, +0, 0, 0, 114, 189, 11, 0, 76, 196, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 255, 255, 255, 0, +0, 0, 0, 126, 4, 0, 0, 27, 0, 0, 0, 126, 4, 0, 0, 30, 0, 0, 0, 0, 0, 7, 0, 0, 0, +0, 0, 0, 0, 0, 0, 102, 188, 11, 0, 112, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 126, 4, 0, 0, 40, 0, 0, 0, 126, 4, 0, +0, 43, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 179, 11, 0, 32, 196, 7, +0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 126, +4, 0, 0, 59, 0, 0, 0, 126, 4, 0, 0, 64, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, +0, 0, 126, 94, 2, 0, 124, 218, 2, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 144, 4, 0, 0, 5, 0, 0, 0, 144, 4, 0, 0, 18, 0, 0, +0, 0, 0, 12, 0, 59, 23, 0, 0, 106, 0, 0, 0, 148, 189, 11, 0, 142, 196, 7, 0, 2, +0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 144, 4, 0, 0, 28, 0, 0, 0, 144, 4, 0, 0, +31, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 185, 11, 0, 242, 192, 7, 0, +2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 144, 4, +0, 0, 41, 0, 0, 0, 144, 4, 0, 0, 44, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, +0, 118, 179, 11, 0, 32, 196, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 1, 0, 0, 0, 155, 4, 0, 0, 5, 0, 0, 0, 155, 4, 0, 0, 13, 0, 0, 0, +0, 0, 12, 0, 59, 23, 0, 0, 107, 0, 0, 0, 178, 189, 11, 0, 164, 196, 7, 0, 2, 0, +1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 155, 4, 0, 0, 23, 0, 0, 0, 155, 4, 0, 0, 26, +0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 188, 11, 0, 112, 195, 7, 0, 2, +0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 155, 4, 0, +0, 36, 0, 0, 0, 155, 4, 0, 0, 39, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, +118, 179, 11, 0, 32, 196, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 1, 0, 0, 0, 155, 4, 0, 0, 45, 0, 0, 0, 155, 4, 0, 0, 48, 0, 0, 0, 0, +0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 1, 1, 0, 18, 197, 7, 0, 2, 0, 1, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 176, 4, 0, 0, 5, 0, 0, 0, +176, 4, 0, 0, 20, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 108, 0, 0, 0, 230, 189, +11, 0, 40, 197, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 176, 4, 0, 0, +30, 0, 0, 0, 176, 4, 0, 0, 33, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, +188, 11, 0, 112, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 1, 0, 0, 0, 176, 4, 0, 0, 43, 0, 0, 0, 176, 4, 0, 0, 46, 0, 0, 0, 0, 0, +7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 179, 11, 0, 32, 196, 7, 0, 2, 0, 1, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 176, 4, 0, 0, 62, 0, 0, 0, +176, 4, 0, 0, 65, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 189, 11, 0, +234, 100, 6, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, +0, 0, 0, 199, 4, 0, 0, 5, 0, 0, 0, 199, 4, 0, 0, 20, 0, 0, 0, 0, 0, 12, 0, 59, +23, 0, 0, 109, 0, 0, 0, 230, 189, 11, 0, 62, 197, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, +0, 0, 0, 0, 0, 0, 199, 4, 0, 0, 30, 0, 0, 0, 199, 4, 0, 0, 33, 0, 0, 0, 0, 0, 7, +0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 188, 11, 0, 112, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 199, 4, 0, 0, 43, 0, 0, 0, +199, 4, 0, 0, 46, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 179, 11, 0, +32, 196, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, +0, 0, 199, 4, 0, 0, 62, 0, 0, 0, 199, 4, 0, 0, 65, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, +0, 0, 0, 0, 0, 212, 189, 11, 0, 234, 100, 6, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 219, 4, 0, 0, 5, 0, 0, 0, 219, 4, 0, 0, +20, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 110, 0, 0, 0, 26, 190, 11, 0, 84, 197, +7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 219, 4, 0, 0, 30, 0, 0, 0, 219, +4, 0, 0, 33, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 188, 11, 0, 112, +195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, +0, 219, 4, 0, 0, 43, 0, 0, 0, 219, 4, 0, 0, 46, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, +0, 0, 0, 0, 118, 179, 11, 0, 32, 196, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 219, 4, 0, 0, 62, 0, 0, 0, 219, 4, 0, 0, 65, +0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 190, 11, 0, 106, 197, 7, 0, 2, +0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 235, 4, 0, +0, 5, 0, 0, 0, 235, 4, 0, 0, 19, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 111, 0, 0, +0, 60, 190, 11, 0, 128, 197, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, +235, 4, 0, 0, 29, 0, 0, 0, 235, 4, 0, 0, 32, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, +0, 0, 0, 102, 188, 11, 0, 112, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 235, 4, 0, 0, 42, 0, 0, 0, 235, 4, 0, 0, 45, 0, +0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 179, 11, 0, 32, 196, 7, 0, 2, 0, +1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 235, 4, 0, 0, +53, 0, 0, 0, 235, 4, 0, 0, 56, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, +36, 1, 0, 244, 141, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 1, 0, 0, 0, 7, 5, 0, 0, 5, 0, 0, 0, 7, 5, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, +59, 23, 0, 0, 112, 0, 0, 0, 94, 190, 11, 0, 150, 197, 7, 0, 2, 0, 1, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, +0, 46, 0, 0, 0, 0, 0, 7, 5, 0, 0, 22, 0, 0, 0, 7, 5, 0, 0, 25, 0, 0, 0, 0, 0, 7, +0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 188, 11, 0, 112, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 7, 5, 0, 0, 35, 0, 0, 0, 7, +5, 0, 0, 38, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 179, 11, 0, 32, +196, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, +0, 7, 5, 0, 0, 49, 0, 0, 0, 7, 5, 0, 0, 52, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, +0, 0, 0, 42, 181, 11, 0, 158, 11, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 7, 5, 0, 0, 63, 0, 0, 0, 7, 5, 0, 0, 67, 0, 0, +0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 181, 11, 0, 138, 14, 1, 0, 2, 0, 1, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 56, 5, 0, 0, 5, +0, 0, 0, 56, 5, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 113, 0, 0, 0, 132, +190, 11, 0, 172, 197, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 56, 5, 0, +0, 22, 0, 0, 0, 56, 5, 0, 0, 25, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, +102, 188, 11, 0, 112, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 1, 0, 0, 0, 56, 5, 0, 0, 35, 0, 0, 0, 56, 5, 0, 0, 38, 0, 0, 0, 0, +0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 179, 11, 0, 32, 196, 7, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 56, 5, 0, 0, 49, 0, 0, +0, 56, 5, 0, 0, 52, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 181, 11, 0, +158, 11, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, +0, 0, 56, 5, 0, 0, 63, 0, 0, 0, 56, 5, 0, 0, 67, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, +0, 0, 0, 0, 0, 42, 181, 11, 0, 138, 14, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 57, 5, 0, 0, 20, 0, 0, 0, 57, 5, 0, 0, +25, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 36, 1, 0, 124, 218, 2, 0, +2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 81, 5, +0, 0, 5, 0, 0, 0, 81, 5, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 114, 0, +0, 0, 94, 190, 11, 0, 194, 197, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 41, 0, 0, 0, 0, 0, +81, 5, 0, 0, 22, 0, 0, 0, 81, 5, 0, 0, 25, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, +0, 0, 0, 102, 188, 11, 0, 112, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 81, 5, 0, 0, 35, 0, 0, 0, 81, 5, 0, 0, 38, 0, +0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 179, 11, 0, 32, 196, 7, 0, 2, 0, +1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 81, 5, 0, 0, +49, 0, 0, 0, 81, 5, 0, 0, 52, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, +181, 11, 0, 158, 11, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 1, 0, 0, 0, 81, 5, 0, 0, 63, 0, 0, 0, 81, 5, 0, 0, 67, 0, 0, 0, 0, 0, 7, +0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 181, 11, 0, 138, 14, 1, 0, 2, 0, 1, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 105, 5, 0, 0, 5, 0, 0, 0, +105, 5, 0, 0, 20, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 115, 0, 0, 0, 210, 190, +11, 0, 216, 197, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 105, 5, 0, 0, +30, 0, 0, 0, 105, 5, 0, 0, 33, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, +188, 11, 0, 112, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 1, 0, 0, 0, 105, 5, 0, 0, 43, 0, 0, 0, 105, 5, 0, 0, 46, 0, 0, 0, 0, 0, +7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 179, 11, 0, 32, 196, 7, 0, 2, 0, 1, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 105, 5, 0, 0, 61, 0, 0, 0, +105, 5, 0, 0, 67, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 190, 11, 0, +200, 47, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, +0, 0, 113, 5, 0, 0, 5, 0, 0, 0, 113, 5, 0, 0, 21, 0, 0, 0, 0, 0, 12, 0, 59, 23, +0, 0, 116, 0, 0, 0, 244, 190, 11, 0, 4, 198, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, +0, 0, 0, 0, 113, 5, 0, 0, 34, 0, 0, 0, 113, 5, 0, 0, 40, 0, 0, 0, 0, 0, 7, 0, 0, +0, 0, 0, 0, 0, 0, 0, 174, 190, 11, 0, 200, 47, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 131, 5, 0, 0, 5, 0, 0, 0, 131, 5, +0, 0, 21, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 117, 0, 0, 0, 14, 191, 11, 0, 26, +198, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 131, 5, 0, 0, 31, 0, 0, 0, +131, 5, 0, 0, 34, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 188, 11, 0, +112, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, +0, 0, 0, 131, 5, 0, 0, 48, 0, 0, 0, 131, 5, 0, 0, 54, 0, 0, 0, 0, 0, 7, 0, 0, 0, +0, 0, 0, 0, 0, 0, 174, 190, 11, 0, 200, 47, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 137, 5, 0, 0, 9, 0, 0, 0, 137, 5, 0, +0, 23, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 118, 0, 0, 0, 44, 191, 11, 0, 48, +198, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 5, 0, 0, 36, 0, 0, 0, +137, 5, 0, 0, 42, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 190, 11, 0, +200, 47, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, +0, 0, 143, 5, 0, 0, 8, 0, 0, 0, 143, 5, 0, 0, 22, 0, 0, 0, 0, 0, 12, 0, 59, 23, +0, 0, 119, 0, 0, 0, 70, 191, 11, 0, 70, 198, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, +0, 0, 0, 0, 143, 5, 0, 0, 35, 0, 0, 0, 143, 5, 0, 0, 41, 0, 0, 0, 0, 0, 7, 0, 0, +0, 0, 0, 0, 0, 0, 0, 174, 190, 11, 0, 200, 47, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 164, 5, 0, 0, 5, 0, 0, 0, 164, 5, +0, 0, 19, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 120, 0, 0, 0, 96, 191, 11, 0, 92, +198, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 164, 5, 0, 0, 32, 0, 0, 0, +164, 5, 0, 0, 38, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 190, 11, 0, +200, 47, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, +0, 0, 164, 5, 0, 0, 49, 0, 0, 0, 164, 5, 0, 0, 52, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, +0, 0, 0, 0, 0, 42, 181, 11, 0, 158, 11, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 164, 5, 0, 0, 63, 0, 0, 0, 164, 5, 0, 0, +67, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 181, 11, 0, 138, 14, 1, 0, +2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 165, 5, +0, 0, 21, 0, 0, 0, 165, 5, 0, 0, 23, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, +0, 124, 184, 11, 0, 222, 62, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 1, 0, 0, 0, 226, 5, 0, 0, 5, 0, 0, 0, 226, 5, 0, 0, 19, 0, 0, 0, +0, 0, 12, 0, 59, 23, 0, 0, 121, 0, 0, 0, 134, 191, 11, 0, 114, 198, 7, 0, 2, 0, +1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 226, 5, 0, 0, 32, 0, 0, 0, 226, 5, 0, 0, 38, +0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 190, 11, 0, 200, 47, 3, 0, 2, +0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 226, 5, 0, +0, 49, 0, 0, 0, 226, 5, 0, 0, 52, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, +42, 181, 11, 0, 158, 11, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 1, 0, 0, 0, 226, 5, 0, 0, 63, 0, 0, 0, 226, 5, 0, 0, 67, 0, 0, 0, 0, +0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 181, 11, 0, 138, 14, 1, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 227, 5, 0, 0, 17, 0, 0, +0, 227, 5, 0, 0, 22, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 36, 1, 0, +124, 218, 2, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, +0, 0, 0, 246, 5, 0, 0, 5, 0, 0, 0, 246, 5, 0, 0, 19, 0, 0, 0, 0, 0, 12, 0, 59, +23, 0, 0, 122, 0, 0, 0, 172, 191, 11, 0, 136, 198, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, +46, 0, 0, 0, 0, 0, 246, 5, 0, 0, 32, 0, 0, 0, 246, 5, 0, 0, 38, 0, 0, 0, 0, 0, +7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 190, 11, 0, 200, 47, 3, 0, 2, 0, 1, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 246, 5, 0, 0, 53, 0, 0, 0, +246, 5, 0, 0, 58, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 36, 1, 0, +124, 218, 2, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, +0, 0, 0, 4, 6, 0, 0, 5, 0, 0, 0, 4, 6, 0, 0, 21, 0, 0, 0, 0, 0, 12, 0, 59, 23, +0, 0, 123, 0, 0, 0, 202, 191, 11, 0, 158, 198, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, +0, 0, 0, 0, 0, 4, 6, 0, 0, 34, 0, 0, 0, 4, 6, 0, 0, 40, 0, 0, 0, 0, 0, 7, 0, 0, +0, 0, 0, 0, 0, 0, 0, 174, 190, 11, 0, 200, 47, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 4, 6, 0, 0, 50, 0, 0, 0, 4, 6, 0, +0, 56, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 230, 1, 0, 180, 198, 7, +0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 16, +6, 0, 0, 5, 0, 0, 0, 16, 6, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 124, +0, 0, 0, 232, 191, 11, 0, 202, 198, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, +0, 16, 6, 0, 0, 22, 0, 0, 0, 16, 6, 0, 0, 25, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, +0, 0, 0, 0, 102, 188, 11, 0, 112, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 16, 6, 0, 0, 35, 0, 0, 0, 16, 6, 0, 0, 38, +0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 179, 11, 0, 32, 196, 7, 0, 2, +0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 16, 6, 0, +0, 55, 0, 0, 0, 16, 6, 0, 0, 56, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, +220, 180, 11, 0, 114, 80, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 1, 0, 0, 0, 16, 6, 0, 0, 73, 0, 0, 0, 16, 6, 0, 0, 74, 0, 0, 0, 0, +0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 180, 11, 0, 136, 80, 3, 0, 2, 0, 1, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 6, 0, 0, 5, 0, 0, +0, 28, 6, 0, 0, 13, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 125, 0, 0, 0, 232, 191, +11, 0, 224, 198, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 46, 0, 0, 0, 0, 0, 28, 6, 0, 0, +23, 0, 0, 0, 28, 6, 0, 0, 26, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, +188, 11, 0, 112, 195, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 1, 0, 0, 0, 28, 6, 0, 0, 36, 0, 0, 0, 28, 6, 0, 0, 39, 0, 0, 0, 0, 0, +7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 179, 11, 0, 32, 196, 7, 0, 2, 0, 1, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 6, 0, 0, 56, 0, 0, 0, +28, 6, 0, 0, 57, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 180, 11, 0, +114, 80, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, +0, 0, 28, 6, 0, 0, 74, 0, 0, 0, 28, 6, 0, 0, 75, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, +0, 0, 0, 0, 0, 220, 180, 11, 0, 136, 80, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 36, 6, 0, 0, 13, 0, 0, 0, 36, 6, 0, 0, +25, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 192, 11, 0, 246, 198, 7, 0, +2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 36, 6, +0, 0, 39, 0, 0, 0, 36, 6, 0, 0, 42, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, +90, 35, 1, 0, 140, 163, 3, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 1, 2, 0, 0, 36, 6, 0, 0, 50, 0, 0, 0, 36, 6, 0, 0, 53, 0, 0, 0, 0, 0, +7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 36, 1, 0, 244, 141, 7, 0, 2, 0, 1, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 45, 6, 0, 0, 4, 0, 0, 0, +45, 6, 0, 0, 19, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 126, 0, 0, 0, 92, 192, 11, +0, 34, 199, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, +2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 32, 0, 0, 0, 0, 0, 45, 6, 0, 0, 29, 0, +0, 0, 45, 6, 0, 0, 32, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 185, 11, +0, 242, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +1, 0, 0, 0, 45, 6, 0, 0, 48, 0, 0, 0, 45, 6, 0, 0, 52, 0, 0, 0, 0, 0, 7, 0, 0, +0, 0, 0, 0, 0, 0, 0, 74, 192, 11, 0, 50, 28, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 45, 6, 0, 0, 60, 0, 0, 0, 45, 6, 0, 0, +63, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 36, 1, 0, 244, 141, 7, 0, +2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 53, 6, +0, 0, 4, 0, 0, 0, 53, 6, 0, 0, 20, 0, 0, 0, 0, 0, 12, 0, 59, 23, 0, 0, 127, 0, +0, 0, 126, 192, 11, 0, 56, 199, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 32, 0, 0, 0, 0, 0, +53, 6, 0, 0, 30, 0, 0, 0, 53, 6, 0, 0, 33, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, +0, 0, 0, 64, 185, 11, 0, 242, 192, 7, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 53, 6, 0, 0, 40, 0, 0, 0, 53, 6, 0, 0, 44, 0, +0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 6, 1, 0, 78, 199, 7, 0, 2, 0, 1, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}; +double realDUDataSize = sizeof(realDUData) / sizeof(unsigned char); Index: kdevplatform/language/duchain/topducontextdynamicdata.h =================================================================== --- kdevplatform/language/duchain/topducontextdynamicdata.h +++ kdevplatform/language/duchain/topducontextdynamicdata.h @@ -1,5 +1,5 @@ /* This is part of KDevelop - Copyright 2008 David Nolden + Copyright 2018 R.J.V. Bertin This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -21,10 +21,9 @@ #include #include +#include #include "problem.h" -class QFile; - namespace KDevelop { class TopDUContext; @@ -34,6 +33,18 @@ class IndexedDUContext; class DUChainBaseData; +#ifdef KDEV_TOPCONTEXTS_USE_FILES +using TopDUContextStore = TopDUContextFile; +#elif defined(KDEV_TOPCONTEXTS_USE_LMDB) +using TopDUContextStore = TopDUContextLMDB; +#elif defined(KDEV_TOPCONTEXTS_USE_LEVELDB) +using TopDUContextStore = TopDUContextLevelDB; +#elif defined(KDEV_TOPCONTEXTS_USE_KYOTO) +using TopDUContextStore = TopDUContextKyotoCabinet; +#else +class TopDUContextStore; +#endif + ///This class contains dynamic data of a top-context, and also the repository that contains all the data within this top-context. class TopDUContextDynamicData { public: @@ -118,6 +129,9 @@ uint position; }; + static QString basePath(); + static QString pathForTopContext(const uint topContextIndex); + private: bool hasChanged() const; @@ -153,8 +167,8 @@ void deleteOnDisk(); bool isItemForIndexLoaded(uint index) const; - void loadData(QFile* file) const; - void writeData(QFile* file); + void loadData(TopDUContextStore* file) const; + void writeData(TopDUContextStore* file); //May contain zero items if they were deleted mutable QVector items; @@ -174,7 +188,7 @@ bool m_onDisk; mutable bool m_dataLoaded; - mutable QFile* m_mappedFile; + mutable TopDUContextStore* m_mappedFile; mutable uchar* m_mappedData; mutable size_t m_mappedDataSize; mutable bool m_itemRetrievalForbidden; Index: kdevplatform/language/duchain/topducontextdynamicdata.cpp =================================================================== --- kdevplatform/language/duchain/topducontextdynamicdata.cpp +++ kdevplatform/language/duchain/topducontextdynamicdata.cpp @@ -18,6 +18,7 @@ Boston, MA 02110-1301, USA. */ +#include "topducontextdynamicdata_p.h" #include "topducontextdynamicdata.h" #include @@ -37,9 +38,13 @@ #include //#define DEBUG_DATA_INFO +#include //This might be problematic on some systems, because really many mmaps are created +#if defined(KDEV_TOPCONTEXTS_USE_FILES) && !defined(KDEV_TOPCONTEXTS_DONT_MMAP) #define USE_MMAP +#endif + using namespace KDevelop; namespace { @@ -149,33 +154,23 @@ #endif } -QString basePath() -{ - return globalItemRepositoryRegistry().path() + "/topcontexts/"; -} - -QString pathForTopContext(const uint topContextIndex) -{ - return basePath() + QString::number(topContextIndex); -} - enum LoadType { PartialLoad, ///< Only load the direct member data FullLoad ///< Load everything, including appended lists }; template void loadTopDUContextData(const uint topContextIndex, LoadType loadType, F callback) { - QFile file(pathForTopContext(topContextIndex)); - if (!file.open(QIODevice::ReadOnly)) { + TopDUContextStore store(topContextIndex); + if (!store.open(QIODevice::ReadOnly)) { return; } uint readValue; - file.read((char*)&readValue, sizeof(uint)); + store.read((char*)&readValue, sizeof(uint)); // now readValue is filled with the top-context data size Q_ASSERT(readValue >= sizeof(TopDUContextData)); - const QByteArray data = file.read(loadType == FullLoad ? readValue : sizeof(TopDUContextData)); + const QByteArray data = store.read(loadType == FullLoad ? readValue : sizeof(TopDUContextData)); const TopDUContextData* topData = reinterpret_cast(data.constData()); callback(topData); } @@ -386,13 +381,18 @@ reinterpret_cast(data->pointerInData(offsets[realIndex].dataOffset)) ); - auto& item = items[realIndex]; - item = dynamic_cast::value>(DUChainItemSystem::self().create(itemData)); - if (!item) { - //When this happens, the item has not been registered correctly. - //We can stop here, because else we will get crashes later. - qCritical() << "Failed to load item with identity" << itemData->classId; - return {}; + if (itemData) { + auto& item = items[realIndex]; + item = dynamic_cast::value>(DUChainItemSystem::self().create(itemData)); + if (!item) { + //When this happens, the item has not been registered correctly. + //We can stop here, because else we will get crashes later. + qCritical() << "Failed to load item with identity" << itemData->classId; + return {}; + } + } else { + qCritical() << "Failed to load item at realIndex" << realIndex << "itemData=" << itemData; + return {}; } if (isSharedDataItem()) { @@ -424,27 +424,27 @@ } template -void TopDUContextDynamicData::DUChainItemStorage::loadData(QFile* file) const +void TopDUContextDynamicData::DUChainItemStorage::loadData(TopDUContextStore* store) const { Q_ASSERT(offsets.isEmpty()); Q_ASSERT(items.isEmpty()); uint readValue; - file->read((char*)&readValue, sizeof(uint)); + store->read((char*)&readValue, sizeof(uint)); offsets.resize(readValue); - file->read((char*)offsets.data(), sizeof(ItemDataInfo) * offsets.size()); + store->read((char*)offsets.data(), sizeof(ItemDataInfo) * offsets.size()); //Fill with zeroes for now, will be initialized on-demand items.resize(offsets.size()); } template -void TopDUContextDynamicData::DUChainItemStorage::writeData(QFile* file) +void TopDUContextDynamicData::DUChainItemStorage::writeData(TopDUContextStore* store) { uint writeValue = offsets.size(); - file->write((char*)&writeValue, sizeof(uint)); - file->write((char*)offsets.data(), sizeof(ItemDataInfo) * offsets.size()); + store->write((char*)&writeValue, sizeof(uint)); + store->write((char*)offsets.data(), sizeof(ItemDataInfo) * offsets.size()); } //END DUChainItemStorage @@ -495,7 +495,7 @@ bool TopDUContextDynamicData::fileExists(uint topContextIndex) { - return QFile::exists(pathForTopContext(topContextIndex)); + return TopDUContextStore::exists(topContextIndex); } QList TopDUContextDynamicData::loadImporters(uint topContextIndex) { @@ -537,63 +537,63 @@ Q_ASSERT(!m_dataLoaded); Q_ASSERT(m_data.isEmpty()); - QFile* file = new QFile(pathForTopContext(m_topContext->ownIndex())); - bool open = file->open(QIODevice::ReadOnly); + TopDUContextStore* store = new TopDUContextStore(m_topContext->ownIndex()); + bool open = store->open(QIODevice::ReadOnly); Q_UNUSED(open); Q_ASSERT(open); - Q_ASSERT(file->size()); + Q_ASSERT(store->size()); //Skip the offsets, we're already read them //Skip top-context data uint readValue; - file->read((char*)&readValue, sizeof(uint)); - file->seek(readValue + file->pos()); + store->read((char*)&readValue, sizeof(uint)); + store->seek(readValue + store->pos()); - m_contexts.loadData(file); - m_declarations.loadData(file); - m_problems.loadData(file); + m_contexts.loadData(store); + m_declarations.loadData(store); + m_problems.loadData(store); #ifdef USE_MMAP - m_mappedData = file->map(file->pos(), file->size() - file->pos()); + m_mappedData = store->map(store->pos(), store->size() - store->pos()); if(m_mappedData) { - m_mappedFile = file; - m_mappedDataSize = file->size() - file->pos(); - file->close(); //Close the file, so there is less open file descriptors(May be problematic) + m_mappedFile = store; + m_mappedDataSize = store->size() - store->pos(); + store->commit(); //Close the store, so there are less open file descriptors (May be problematic) }else{ - qCDebug(LANGUAGE) << "Failed to map" << file->fileName(); + qCDebug(LANGUAGE) << "Failed to map" << store->fileName(); } #endif if(!m_mappedFile) { - QByteArray data = file->readAll(); + QByteArray data = store->readAll(); m_data.append({data, (uint)data.size()}); - delete file; + delete store; } m_dataLoaded = true; } TopDUContext* TopDUContextDynamicData::load(uint topContextIndex) { - QFile file(pathForTopContext(topContextIndex)); - if(file.open(QIODevice::ReadOnly)) { - if(file.size() == 0) { - qCWarning(LANGUAGE) << "Top-context file is empty" << file.fileName(); + TopDUContextStore store(topContextIndex); + if(store.open(QIODevice::ReadOnly)) { + if(store.size() == 0) { + qCWarning(LANGUAGE) << "Top-context store is empty" << store.fileName(); return nullptr; } QVector contextDataOffsets; QVector declarationDataOffsets; uint readValue; - file.read((char*)&readValue, sizeof(uint)); + store.read((char*)&readValue, sizeof(uint)); //now readValue is filled with the top-context data size - QByteArray topContextData = file.read(readValue); + QByteArray topContextData = store.read(readValue); DUChainBaseData* topData = reinterpret_cast(topContextData.data()); TopDUContext* ret = dynamic_cast(DUChainItemSystem::self().create(topData)); if(!ret) { - qCWarning(LANGUAGE) << "Cannot load a top-context from file" << file.fileName() << "- the required language-support for handling ID" << topData->classId << "is probably not loaded"; + qCWarning(LANGUAGE) << "Cannot load a top-context from store" << store.fileName() << "- the required language-support for handling ID" << topData->classId << "is probably not loaded"; return nullptr; } @@ -630,12 +630,22 @@ m_onDisk = false; - bool successfullyRemoved = QFile::remove(filePath()); + bool successfullyRemoved = TopDUContextStore::remove(m_topContext->ownIndex()); Q_UNUSED(successfullyRemoved); Q_ASSERT(successfullyRemoved); qCDebug(LANGUAGE) << "deletion ready"; } +QString TopDUContextDynamicData::basePath() +{ + return globalItemRepositoryRegistry().path() + "/topcontexts/"; +} + +QString TopDUContextDynamicData::pathForTopContext(const uint topContextIndex) +{ + return basePath() + QString::number(topContextIndex); +} + QString KDevelop::TopDUContextDynamicData::filePath() const { return pathForTopContext(m_topContext->ownIndex()); } @@ -713,32 +723,55 @@ QDir().mkpath(basePath()); - QFile file(filePath()); - if(file.open(QIODevice::WriteOnly)) { + QElapsedTimer timer; + qint64 nBytes = 0; + if (Q_LIKELY(QFileInfo(basePath()).isWritable())) { + timer.start(); + TopDUContextStore store(m_topContext->ownIndex()); + if(store.open(QIODevice::WriteOnly)) { - file.resize(0); + store.resize(0); - file.write((char*)&topContextDataSize, sizeof(uint)); - foreach(const ArrayWithPosition& pos, m_topContextData) - file.write(pos.array.constData(), pos.position); + store.write((char*)&topContextDataSize, sizeof(uint)); + foreach(const ArrayWithPosition& pos, m_topContextData) + store.write(pos.array.constData(), pos.position); - m_contexts.writeData(&file); - m_declarations.writeData(&file); - m_problems.writeData(&file); + m_contexts.writeData(&store); + m_declarations.writeData(&store); + m_problems.writeData(&store); - foreach(const ArrayWithPosition& pos, m_data) - file.write(pos.array.constData(), pos.position); + foreach(const ArrayWithPosition& pos, m_data) + store.write(pos.array.constData(), pos.position); - m_onDisk = true; + m_onDisk = true; - if (file.size() == 0) { - qCWarning(LANGUAGE) << "Saving zero size top ducontext data"; + nBytes = store.size(); + if (store.size() == 0) { + qCWarning(LANGUAGE) << "Saving zero size top ducontext data"; + } + store.commit(); + } else { + qCWarning(LANGUAGE) << "Cannot open topcontext" << store.fileName() << "for writing:" << store.errorString(); } - file.close(); +// qCDebug(LANGUAGE) << "stored" << m_topContext->url().str() << m_topContext->ownIndex() << "import-count:" << m_topContext->importedParentContexts().size(); } else { - qCWarning(LANGUAGE) << "Cannot open top-context for writing"; + static bool warned = false; + if (!warned) { + qCWarning(LANGUAGE) << "Topcontexts directory" << basePath() << "is not writable, topcontext files won't be stored."; + warned = true; + } + } + if (timer.isValid()) { + auto elapsed = timer.elapsed(); + static quint64 totalBytes = 0; + static double totalElapsed = 0.0; + totalBytes += nBytes; + totalElapsed += elapsed / 1000.0; + if (totalBytes && totalElapsed >= 0.5) { + qCInfo(LANGUAGE) << "Stored" << totalBytes << "topcontext bytes at" << totalBytes / totalElapsed << "bytes/second"; + totalBytes = 0, totalElapsed = 0.0; + } } -// qCDebug(LANGUAGE) << "stored" << m_topContext->url().str() << m_topContext->ownIndex() << "import-count:" << m_topContext->importedParentContexts().size(); } TopDUContextDynamicData::ItemDataInfo TopDUContextDynamicData::writeDataInfo(const ItemDataInfo& info, const DUChainBaseData* data, uint& totalDataOffset) { Index: kdevplatform/language/duchain/topducontextdynamicdata_p.h =================================================================== --- /dev/null +++ kdevplatform/language/duchain/topducontextdynamicdata_p.h @@ -0,0 +1,156 @@ +/* This is part of KDevelop + Copyright 2018 R.J.V. Bertin + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KDEVPLATFORM_TOPDUCONTEXTDYNAMICDATA_P_H +#define KDEVPLATFORM_TOPDUCONTEXTDYNAMICDATA_P_H + +#include +#include + +#include + +namespace KDevelop { + +// #define KDEV_TOPCONTEXTS_DB_TESTING +// #define KDEV_TOPCONTEXTS_USE_FILES +#define KDEV_TOPCONTEXTS_USE_LMDB +// #define KDEV_TOPCONTEXTS_USE_LEVELDB +// #define KDEV_TOPCONTEXTS_USE_KYOTO + +// thin wrapper around QFile, implementing the default TopDUContext +// storage mechanism but also used for migration purposes in the +// database stores. +class KDEVPLATFORMLANGUAGE_EXPORT TopDUContextFile : public QFile +{ +public: + TopDUContextFile(uint topContextIndex); + void commit(); + static bool exists(uint topContextIndex); + static bool remove(uint topContextIndex); +}; + +#if defined(KDEV_TOPCONTEXTS_USE_LMDB) || defined(KDEV_TOPCONTEXTS_USE_LEVELDB) || defined(KDEV_TOPCONTEXTS_USE_KYOTO) +class KDEVPLATFORMLANGUAGE_EXPORT TopDUContextDB +{ +public: + virtual ~TopDUContextDB() {}; + virtual bool open(QIODevice::OpenMode mode) = 0; + virtual void commit() = 0; + virtual bool flush() = 0; + bool resize(qint64); + qint64 write(const char* data, qint64 len); + qint64 read(char* data, qint64 maxSize); + QByteArray read(qint64 maxSize); + QByteArray readAll(); + qint64 pos() const; + bool seek(qint64 pos); + qint64 size(); + QString errorString() const; + QString fileName() const; + static bool exists(uint) { return false; }; + static bool remove(uint) { return false; }; + +protected: + bool open(QIODevice::OpenMode mode, const QString &backendName); + virtual bool getCurrentKeyValue() = 0; + virtual bool isValid() = 0; + virtual bool currentKeyExists() = 0; + static bool exists(const QByteArray&) { return false; }; + static QByteArray indexKey(uint idx); + static QByteArray indexKey(uint* idx); + bool migrateFromFile(); + QByteArray m_currentKey; + uint m_currentIndex; + QByteArray m_currentValue; + qint64 m_currentLen, m_readCursor; + int m_mode; + QString m_errorString; +}; +#endif + +#ifdef KDEV_TOPCONTEXTS_USE_LMDB +class KDEVPLATFORMLANGUAGE_EXPORT TopDUContextLMDB : public TopDUContextDB +{ +public: + typedef union { char *bytes; qint64 *qint64Ptr; } LZ4Frame; + TopDUContextLMDB(uint topContextIndex); + virtual ~TopDUContextLMDB(); + bool open(QIODevice::OpenMode mode) override; + void commit() override; + bool flush() override; + QString fileName() const; + static bool exists(uint topContextIndex); + static bool remove(uint topContextIndex); + +protected: + virtual bool getCurrentKeyValue() override; + virtual bool isValid() override; + virtual bool currentKeyExists() override; + static bool exists(const QByteArray& key); + static void *s_lz4State; + static size_t s_mapSize; + static bool s_envExists; + static uint s_DbRefCount; +}; +#endif + +#ifdef KDEV_TOPCONTEXTS_USE_LEVELDB +class KDEVPLATFORMLANGUAGE_EXPORT TopDUContextLevelDB : public TopDUContextDB +{ +public: + TopDUContextLevelDB(uint topContextIndex); + virtual ~TopDUContextLevelDB(); + bool open(QIODevice::OpenMode mode) override; + void commit() override; + bool flush() override; + static bool exists(uint topContextIndex); + static bool remove(uint topContextIndex); + +protected: + virtual bool getCurrentKeyValue() override; + virtual bool isValid() override; + virtual bool currentKeyExists() override; + static bool exists(const QByteArray& key); + static uint s_DbRefCount; +}; +#endif + +#ifdef KDEV_TOPCONTEXTS_USE_KYOTO +class KDEVPLATFORMLANGUAGE_EXPORT TopDUContextKyotoCabinet : public TopDUContextDB +{ +public: + TopDUContextKyotoCabinet(uint topContextIndex); + virtual ~TopDUContextKyotoCabinet(); + bool open(QIODevice::OpenMode mode) override; + void commit() override; + bool flush() override; + QString fileName() const; + static bool exists(uint topContextIndex); + static bool remove(uint topContextIndex); + +protected: + virtual bool getCurrentKeyValue() override; + virtual bool isValid() override; + virtual bool currentKeyExists() override; + static bool exists(const QByteArray& key); + static uint s_DbRefCount; +}; +#endif + +} +#endif Index: kdevplatform/language/duchain/topducontextdynamicdata_p.cpp =================================================================== --- /dev/null +++ kdevplatform/language/duchain/topducontextdynamicdata_p.cpp @@ -0,0 +1,1029 @@ +/* This is part of KDevelop + + Copyright 2018 R.J.V. Bertin + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "topducontextdynamicdata_p.h" +#include "topducontextdynamicdata.h" + +#include + +#ifndef KDEV_TOPCONTEXTS_USE_FILES +#ifdef KDEV_TOPCONTEXTS_USE_LMDB +#include +// we roll our own compression +#include +#else +#define MDB_RDONLY 0x20000 +#endif +#ifdef KDEV_TOPCONTEXTS_USE_LEVELDB +#include +#include +#endif +#ifdef KDEV_TOPCONTEXTS_USE_KYOTO +#include +#endif +#endif + +#include + +//#define DEBUG_DATA_INFO + +using namespace KDevelop; + +#ifndef KDEV_TOPCONTEXTS_USE_FILES + +bool TopDUContextDB::open(QIODevice::OpenMode mode, const QString &backendName) +{ + if (isValid() && !m_currentKey.isEmpty()) { + int lmMode = mode == QIODevice::ReadOnly ? MDB_RDONLY : 0; + if (lmMode == MDB_RDONLY && !currentKeyExists()) { + // migration: see if the index file exists + if (migrateFromFile()) { + return true; + } + m_errorString = QStringLiteral("No item #") + QByteArray::number(m_currentIndex) + QStringLiteral(" in database"); + return false; + } + m_mode = lmMode; + m_currentValue.clear(); + m_currentLen = 0; + m_readCursor = -1; + m_errorString.clear(); + return true; + } + m_errorString = QStringLiteral("%1 database backend not initialised properly").arg(backendName); + return false; +} + +QString TopDUContextDB::fileName() const +{ + return TopDUContextDynamicData::basePath() + "...#" + QByteArray::number(m_currentIndex); +} + +QString TopDUContextDB::errorString() const +{ + return m_errorString; +} + +bool TopDUContextDB::resize(qint64) +{ + return m_mode != MDB_RDONLY; +} + +qint64 TopDUContextDB::write(const char *data, qint64 len) +{ + if (m_mode != MDB_RDONLY) { + m_currentValue.append(QByteArray::fromRawData(data, len)); + m_currentLen += len; + return len; + } + return 0; +} + +// read the current key value into m_currentValue if necessary, and return the +// requested @p maxSize bytes from the current read position in @p data. Update +// the read position afterwards, and reset m_currentValue when all data has +// been returned. +// Special case: data==NULL and maxSize==-1; return the number of remaining bytes +// and do NOT reset m_currentValue +qint64 TopDUContextDB::read(char *data, qint64 maxSize) +{ + if (isValid() && !m_currentKey.isEmpty() && m_mode == MDB_RDONLY) { + if (!getCurrentKeyValue()) { + return -1; + } + if (m_readCursor >= 0 && m_readCursor < m_currentLen) { + qint64 rlen = m_currentLen - m_readCursor; + if (Q_LIKELY(maxSize >= 0)) { + if (maxSize < rlen) { + rlen = maxSize; + } + const char *val = m_currentValue.constData(); + memcpy(data, &val[m_readCursor], rlen); + m_readCursor += rlen; + if (m_readCursor >= m_currentLen) { + // all read, clear the cache + m_currentValue.clear(); + m_currentLen = 0; + m_readCursor = -1; + } + } else { + // special case: don't update m_readCursor; + } + return rlen; + } + } + return -1; +} + +QByteArray TopDUContextDB::read(qint64 maxSize) +{ + QByteArray data; + data.resize(maxSize); + auto len = read(data.data(), maxSize); + data.resize(len >= 0 ? len : 0); + return data; +} + +// Reads all the remaining data, returned as a QByteArray +QByteArray TopDUContextDB::readAll() +{ + QByteArray data; + auto readLen = read(nullptr, -1); + if (readLen > 0) { + // should always be true: + if (Q_LIKELY(m_readCursor >= 0 && m_readCursor + readLen <= m_currentValue.size())) { + if (m_readCursor == 0) { + data = m_currentValue; + } else { + data.resize(readLen); + const char *val = m_currentValue.constData(); + memcpy(data.data(), &val[m_readCursor], readLen); + } + } else { + qCWarning(LANGUAGE) << Q_FUNC_INFO << "m_readCursor=" << m_readCursor << "readLen=" << readLen + << "m_currentValue.size=" << m_currentValue.size(); + if (readLen == m_currentValue.size()) { + // m_readCursor should have been 0!!! + qCWarning(LANGUAGE) << "\tm_readCursor should have been 0!!"; + data = m_currentValue; + } + } + // all read, clear the cache + m_currentValue.clear(); + m_currentLen = 0; + m_readCursor = -1; + } + return data; +} + +qint64 TopDUContextDB::pos() const +{ + return m_readCursor < 0 ? 0 : m_readCursor; +} + +bool TopDUContextDB::seek(qint64 pos) +{ + if (pos <= m_currentLen) { + m_readCursor = pos; + return true; + } + return false; +} + +qint64 TopDUContextDB::size() +{ + if (!m_currentLen && m_mode == MDB_RDONLY) { + // cache the key value + read(nullptr, -1); + } + return m_currentLen; +} + +QByteArray TopDUContextDB::indexKey(uint idx) +{ + return QByteArray::number(idx); +} + +// NB: @p idx must point to a variable that will not be outlived by the returned QByteArray! +QByteArray TopDUContextDB::indexKey(uint *idx) +{ + return QByteArray::fromRawData(reinterpret_cast(idx), sizeof(uint)); +} + +bool TopDUContextDB::migrateFromFile() +{ + TopDUContextFile migrateFile(m_currentIndex); + if (migrateFile.open(QIODevice::ReadOnly)) { + // should we care about empty files here? + qCDebug(LANGUAGE) << "Migrating" << migrateFile.fileName(); + const QByteArray content = migrateFile.readAll(); + migrateFile.close(); + m_mode = 0; + m_currentValue = content; + m_currentLen = content.size(); + // commit() will reset the key so we need to cache it + const QByteArray key = m_currentKey; + m_errorString.clear(); + commit(); + if (m_errorString.isEmpty()) { + // migration was successful, remove the file + QFile::remove(migrateFile.fileName()); + } + m_errorString.clear(); + // take care that we don't have to read the data back in + m_currentKey = key; + m_currentValue = content; + m_currentLen = content.size(); + m_readCursor = 0; + m_mode = MDB_RDONLY; + return true; + } + return false; +} + +#ifdef KDEV_TOPCONTEXTS_USE_LMDB +// TopDUContextLMDB : wraps the QFile API needed for TopDUContexts around LMDB + +static QString lmdbxx_exception_handler(const lmdb::error &e, const QString &operation) +{ + const QString msg = QStringLiteral("LMDB exception in \"%1\": %2").arg(operation).arg(e.what()); + qCWarning(LANGUAGE) << msg; + if (qEnvironmentVariableIsSet("KDEV_TOPCONTEXTS_STORE_FAILURE_ABORT")) { + qFatal(msg.toLatin1()); + } + return msg; +} + +// there is exactly 1 topcontexts directory per session, so we can make do with a single +// global static LMDB env instance which is not exported at all (= no need to include +// lmdb.h and/or lmdbxx.h in our own headerfile). +static lmdb::env lmdbEnv {nullptr}; +void *TopDUContextLMDB::s_lz4State = nullptr; +bool TopDUContextLMDB::s_envExists = false; +uint TopDUContextLMDB::s_DbRefCount = 0; +// set the initial map size to 64Mb +size_t TopDUContextLMDB::s_mapSize = 1024UL * 1024UL * 64UL; +static double compRatioSum = 0; +static size_t compRatioN = 0; + +static void printCompRatio() +{ + if (compRatioN) { + fprintf(stderr, "average LZ4 compression ratio: %g\n", compRatioSum / compRatioN); + } +} + +TopDUContextLMDB::TopDUContextLMDB(uint topContextIndex) +{ + if (!s_envExists && Q_LIKELY(QFileInfo(TopDUContextDynamicData::basePath()).isWritable())) { + try { + lmdbEnv = lmdb::env::create(); + lmdbEnv.open(TopDUContextDynamicData::basePath().toLatin1().constData()); + MDB_envinfo stat; + lmdb::env_info(lmdbEnv.handle(), &stat); + if (stat.me_mapsize > s_mapSize) { + s_mapSize = stat.me_mapsize; + } + lmdbEnv.set_mapsize(s_mapSize); + s_lz4State = new char[LZ4_sizeofState()]; + s_envExists = true; + qCDebug(LANGUAGE) << "lmdbEnv=" << lmdbEnv << "mapsize=" << stat.me_mapsize << "LZ4 state buffer:" << LZ4_sizeofState(); + atexit(printCompRatio); + } catch (const lmdb::error &e) { + m_errorString = lmdbxx_exception_handler(e, QStringLiteral("database creation")); + } + } + if (s_envExists) { + m_currentIndex = topContextIndex; + m_currentKey = indexKey(m_currentIndex); + s_DbRefCount += 1; + } + m_currentLen = -1; + // the remaining member vars are initialised elsewhere intentionally. +} + +TopDUContextLMDB::~TopDUContextLMDB() +{ + if (s_envExists) { + s_DbRefCount -= 1; + if (s_DbRefCount <= 0) { + s_DbRefCount = 0; + flush(); + } + } else { + s_DbRefCount = 0; + } +} + +bool TopDUContextLMDB::open(QIODevice::OpenMode mode) +{ + return TopDUContextDB::open(mode, QStringLiteral("LMDB")); +} + +void TopDUContextLMDB::commit() +{ + if (s_envExists && m_mode != MDB_RDONLY) { + if (m_currentValue.size() != m_currentLen) { + // m_currentLen is the true size + qCDebug(LANGUAGE) << "TopDUContextLMDB index" << QByteArray::number(m_currentIndex) << "internal size mismatch:" + << m_currentValue.size() << "vs" << m_currentLen; + } + char *data; + size_t dataLen = 0; + int lz4BufLen = m_currentLen > sizeof(qint64) ? LZ4_compressBound(m_currentLen) : 0; + lmdb::val value; + if (lz4BufLen) { + data = new char[lz4BufLen + sizeof(m_currentLen)]; + // compress to an qint64-sized offset into the dest buffer; the original size will be stored in + // those first 64 bits. + dataLen = LZ4_compress_fast_extState(s_lz4State, m_currentValue.constData(), &data[sizeof(m_currentLen)], + m_currentLen, lz4BufLen, 1); + if (dataLen && dataLen + sizeof(qint64) < m_currentLen) { + LZ4Frame frame; + frame.bytes = data; + frame.qint64Ptr[0] = m_currentLen; + value = lmdb::val(data, dataLen + sizeof(m_currentLen)); + compRatioSum += double(m_currentLen) / value.size(); + compRatioN += 1; + } else { + qCDebug(LANGUAGE) << "Index" << m_currentIndex << "compression failed or useless: m_currentLen=" << m_currentLen + << "compressedLen=" << dataLen << "LZ4_compressBound=" << lz4BufLen; + delete data; + dataLen = 0; + lz4BufLen = 0; + } + } + if (!dataLen) { + value = lmdb::val(m_currentValue.constData(), m_currentLen); + } +// // ensure that there's a NUL byte at the end (after the range we'll commit to the store) +// if (!m_currentValue.endsWith('\0')) { +// m_currentValue.append('\0'); +// } + lmdb::val key(m_currentKey.constData(), m_currentKey.size()); + try { + auto txn = lmdb::txn::begin(lmdbEnv); + auto dbi = lmdb::dbi::open(txn, nullptr); + try { + lmdb::dbi_put(txn, dbi, key, value); + txn.commit(); + } catch (const lmdb::error &e) { + if (e.code() == MDB_MAP_FULL) { + try { + qCDebug(LANGUAGE) << "aborting LMDB write to grow mapsize"; + txn.abort(); + lmdb::dbi_close(lmdbEnv, dbi); + s_mapSize *= 2; + qCDebug(LANGUAGE) << "\tgrowing mapsize to" << s_mapSize; + lmdbEnv.set_mapsize(s_mapSize); + commit(); + } catch (const lmdb::error &e) { + m_errorString = lmdbxx_exception_handler(e, QStringLiteral("growing mapsize to ") + QString::number(s_mapSize)); + } + } else { + m_errorString = lmdbxx_exception_handler(e, QStringLiteral("committing index ") + + QByteArray::number(m_currentIndex) + " size " + QString::number(m_currentLen)); + } + } + } catch (const lmdb::error &e) { + m_errorString = lmdbxx_exception_handler(e, QStringLiteral("committing index ") + + QByteArray::number(m_currentIndex) + " size " + QString::number(m_currentLen)); + } + m_currentKey.clear(); + m_currentValue.clear(); + m_currentLen = 0; + if (lz4BufLen && data) { + delete data; + } + } +} + +bool TopDUContextLMDB::flush() +{ + if (s_envExists && m_mode != MDB_RDONLY) { + try { + return mdb_env_sync(lmdbEnv, true) == MDB_SUCCESS; + } catch (const lmdb::error &e) { + m_errorString = lmdbxx_exception_handler(e, QStringLiteral("database flush")); + } + } + return false; +} + +bool TopDUContextLMDB::getCurrentKeyValue() +{ + // we only return false if a read error occurred; if a key doesn't exist + // m_currentValue will remain empty. + bool ret = true; + if (m_currentValue.isEmpty()) { + // read the key value from storage into cache + try { + auto rtxn = lmdb::txn::begin(lmdbEnv, nullptr, MDB_RDONLY); + auto dbi = lmdb::dbi::open(rtxn, nullptr); + auto cursor = lmdb::cursor::open(rtxn, dbi); + lmdb::val key(m_currentKey.constData(), m_currentKey.size()); + lmdb::val val {}; + bool found = cursor.get(key, val, MDB_SET); + if (found) { + bool isRaw = true; + if (val.size() > sizeof(qint64)) { + LZ4Frame frame; + frame.bytes = val.data(); + qint64 orgSize = frame.qint64Ptr[0]; + if (orgSize > 0) { + int compressedSize = val.size() - sizeof(qint64); + // size m_currentValue so decompression can go into the final destination directly + m_currentValue.resize(orgSize); + if (LZ4_decompress_safe(&frame.bytes[sizeof(qint64)], m_currentValue.data(), compressedSize, orgSize) == orgSize) { + isRaw = false; + m_currentLen = m_currentValue.size(); + } else { +// qCDebug(LANGUAGE) << "Index" << m_currentIndex << "failed LZ4 decompression from size" << compressedSize << "to size" << orgSize; + } + } + } + if (isRaw) { +// qCDebug(LANGUAGE) << "Index" << m_currentIndex << "is uncompressed, size=" << val.size(); + m_currentValue = QByteArray(val.data(), val.size()); + m_currentLen = m_currentValue.size(); + } + m_readCursor = 0; + } + cursor.close(); + rtxn.abort(); + } catch (const lmdb::error &e) { + m_errorString = lmdbxx_exception_handler(e, QStringLiteral("reading index ") + QByteArray::number(m_currentIndex)); + ret = false; + } + } + return ret; +} + +bool TopDUContextLMDB::isValid() +{ + return s_envExists; +} + +bool TopDUContextLMDB::currentKeyExists() +{ + return exists(m_currentKey); +} + +bool TopDUContextLMDB::exists(const QByteArray &key) +{ + if (lmdbEnv.handle() != nullptr) { + try { + auto rtxn = lmdb::txn::begin(lmdbEnv, nullptr, MDB_RDONLY); + auto dbi = lmdb::dbi::open(rtxn, nullptr); + auto cursor = lmdb::cursor::open(rtxn, dbi); + lmdb::val k(key.constData(), key.size()); + bool ret = cursor.get(k, nullptr, MDB_SET); + cursor.close(); + rtxn.abort(); + return ret; + } catch (const lmdb::error &e) { + lmdbxx_exception_handler(e, QStringLiteral("checking for index") + key); + } + } + return false; +} + +QString TopDUContextLMDB::fileName() const +{ + return TopDUContextDynamicData::basePath() + "data.mdb" + ":#" + QByteArray::number(m_currentIndex); +} + +bool TopDUContextLMDB::exists(uint topContextIndex) +{ + return exists(indexKey(topContextIndex)); +} + +bool TopDUContextLMDB::remove(uint topContextIndex) +{ + if (s_envExists) { + const auto key = indexKey(topContextIndex); + lmdb::val k {key.constData(), static_cast(key.size())}; + try { + auto txn = lmdb::txn::begin(lmdbEnv); + auto dbi = lmdb::dbi::open(txn, nullptr); + bool ret = lmdb::dbi_del(txn, dbi, k, nullptr); + txn.commit(); + lmdbEnv.sync(); + // also remove the file if it (still) exists + QFile::remove(TopDUContextDynamicData::pathForTopContext(topContextIndex)); + return ret; + } catch (const lmdb::error &e) { + lmdbxx_exception_handler(e, QStringLiteral("removing index %1").arg(topContextIndex)); + } + } + return false; +} +#endif + +#ifdef KDEV_TOPCONTEXTS_USE_LEVELDB +// LevelDB storage backend +static QString leveldb_exception_handler(const std::exception &e, const QString &operation) +{ + const QString msg = QStringLiteral("LevelDB exception in \"%1\": %2").arg(operation).arg(e.what()); + qCWarning(LANGUAGE) << msg; + if (qEnvironmentVariableIsSet("KDEV_TOPCONTEXTS_STORE_FAILURE_ABORT")) { + qFatal(msg.toLatin1()); + } + return msg; +} + +// our keys are uint values and stored as uint* in the original QByteArray m_currentKey +// use that knowledge to avoid sorting lexographically. +class QuickSortingComparator : public leveldb::Comparator +{ +public: + // Comparison function that doesn't result in any sorting + int Compare(const leveldb::Slice &a, const leveldb::Slice &b) const + { + const uint *ia = reinterpret_cast(a.data()); + const uint *ib = reinterpret_cast(b.data()); + return *ia - *ib; + } + + const char *Name() const + { + return "QuickSortingComparator"; + } + void FindShortestSeparator(std::string *, const leveldb::Slice &) const {} + void FindShortSuccessor(std::string *) const {} +}; +static QuickSortingComparator leveldbComparator; + +// there is exactly 1 topcontexts directory per session, so we can make do with a single +// global static LevelDB instance which is not exported at all (= no need to include +// db.h in our own headerfile). + +class LevelDBHook +{ +public: + ~LevelDBHook() + { + if (s_levelDB) { + delete s_levelDB; + } + } + + static const leveldb::Status init() + { + leveldb::Options options; + options.create_if_missing = true; + options.comparator = &leveldbComparator; + int attempts = 0; + leveldb::Status status; + do { + attempts += 1; + leveldb::Status status = leveldb::DB::Open(options, TopDUContextDynamicData::basePath().toStdString(), &s_levelDB); + if (!status.ok()) { + s_levelDB = nullptr; + if (status.IsInvalidArgument()) { + // retry opening a fresh store + leveldb::DestroyDB(TopDUContextDynamicData::basePath().toStdString(), options); + } + } + } while (!s_levelDB && attempts < 2); + return status; + } + + inline leveldb::DB *instance() + { + return s_levelDB; + } + + static leveldb::DB *s_levelDB; +}; +static LevelDBHook levelDB; + +leveldb::DB *LevelDBHook::s_levelDB = nullptr; +uint TopDUContextLevelDB::s_DbRefCount = 0; + +TopDUContextLevelDB::TopDUContextLevelDB(uint topContextIndex) +{ + if (!levelDB.instance() && Q_LIKELY(QFileInfo(TopDUContextDynamicData::basePath()).isWritable())) { + leveldb::Status status = LevelDBHook::init(); + if (!status.ok()) { + m_errorString = QStringLiteral("Error opening LevelDB database:") + QString::fromStdString(status.ToString()); + qCWarning(LANGUAGE) << m_errorString; + } + } + if (levelDB.instance()) { + m_currentIndex = topContextIndex; + m_currentKey = indexKey(&m_currentIndex); + s_DbRefCount += 1; + } + m_currentLen = -1; + // the remaining member vars are initialised elsewhere intentionally. +} + +TopDUContextLevelDB::~TopDUContextLevelDB() +{ + if (levelDB.instance()) { + s_DbRefCount -= 1; + if (s_DbRefCount <= 0) { + // optimisation: don't delete the global DB handle; too many TopDUContextLevelDB + // instances are created too frequently that are deleted immediately after a + // single use. + s_DbRefCount = 0; + } + } else { + s_DbRefCount = 0; + } +} + +bool TopDUContextLevelDB::open(QIODevice::OpenMode mode) +{ + return TopDUContextDB::open(mode, QStringLiteral("LevelDB")); +} + +void TopDUContextLevelDB::commit() +{ + if (isValid() && m_mode != MDB_RDONLY) { + if (m_currentValue.size() != m_currentLen) { + // m_currentLen is the true size + qCDebug(LANGUAGE) << "TopDUContextLevelDB index" << QByteArray::number(m_currentIndex) << "internal size mismatch:" + << m_currentValue.size() << "vs" << m_currentLen; + } + leveldb::Status status; + leveldb::Slice key(m_currentKey.constData(), m_currentKey.size()); + leveldb::Slice value(m_currentValue.constData(), m_currentLen); + try { + status = levelDB.instance()->Put(leveldb::WriteOptions(), key, value); + } catch (const std::exception &e) { + m_errorString = leveldb_exception_handler(e, QStringLiteral("committing value for ") + QByteArray::number(m_currentIndex)); + qCWarning(LANGUAGE) << m_errorString; + } + if (!status.ok()) { + m_errorString = QStringLiteral("Error committing index ") + + QByteArray::number(m_currentIndex) + " size " + QString::number(m_currentLen) + + QStringLiteral(": ") + QString::fromStdString(status.ToString()); + qCWarning(LANGUAGE) << m_errorString; + } + m_currentKey.clear(); + m_currentValue.clear(); + m_currentLen = 0; + } +} + +bool TopDUContextLevelDB::flush() +{ + if (isValid() && m_mode != MDB_RDONLY) { + try { + levelDB.instance()->CompactRange(nullptr, nullptr); + return true; + } catch (const std::exception &e) { + m_errorString = leveldb_exception_handler(e, QStringLiteral("database flush (CompactRange)")); + qCWarning(LANGUAGE) << m_errorString; + } + } + return false; +} + +bool TopDUContextLevelDB::getCurrentKeyValue() +{ + // we only return false if a read error occurred; if a key doesn't exist + // m_currentValue will remain empty. + bool ret = true; + if (m_currentValue.isEmpty()) { + // read the key value from storage into cache + leveldb::Slice key(m_currentKey.constData(), m_currentKey.size()); + std::string value; + leveldb::Status status = levelDB.instance()->Get(leveldb::ReadOptions(), key, &value); + if (status.ok()) { + m_currentValue = QByteArray(value.data(), value.size()); + m_currentLen = value.size(); + m_readCursor = 0; + } else if (status.IsCorruption() || status.IsIOError() || status.IsNotSupportedError() || status.IsInvalidArgument()) { + ret = false; + } + } + return ret; +} + +bool TopDUContextLevelDB::isValid() +{ + return levelDB.instance(); +} + +bool TopDUContextLevelDB::currentKeyExists() +{ + return exists(m_currentKey); +} + +bool TopDUContextLevelDB::exists(const QByteArray &key) +{ + if (levelDB.instance()) { + std::string value; + leveldb::Slice k(key.constData(), key.size()); + leveldb::Status status = levelDB.instance()->Get(leveldb::ReadOptions(), k, &value); + if (!status.ok() && !status.IsNotFound()) { + qCWarning(LANGUAGE) << QStringLiteral("Error checking for index") + key + + QStringLiteral(": ") + QString::fromStdString(status.ToString()); + return false; + } + return status.ok(); + } + return false; +} + +bool TopDUContextLevelDB::exists(uint topContextIndex) +{ + return exists(indexKey(&topContextIndex)); +} + +bool TopDUContextLevelDB::remove(uint topContextIndex) +{ + if (levelDB.instance()) { + const auto key = indexKey(&topContextIndex); + leveldb::Slice k(key.constData(), key.size()); + leveldb::Status status = levelDB.instance()->Delete(leveldb::WriteOptions(), k); + if (!status.ok()) { + qCWarning(LANGUAGE) << QStringLiteral("Error removing index %1").arg(topContextIndex) + + QStringLiteral(": ") + QString::fromStdString(status.ToString()); + return false; + } + // also remove the file if it (still) exists + QFile::remove(TopDUContextDynamicData::pathForTopContext(topContextIndex)); + return true; + } + return false; +} + +#endif // KDEV_TOPCONTEXTS_USE_LEVELDB + +#ifdef KDEV_TOPCONTEXTS_USE_KYOTO +using namespace kyotocabinet; + +static QString kyotocabinet_exception_handler(const std::exception &e, const QString &operation) +{ + const QString msg = QStringLiteral("KyotoCabinet exception in \"%1\": %2").arg(operation).arg(e.what()); + qCWarning(LANGUAGE) << msg; + if (qEnvironmentVariableIsSet("KDEV_TOPCONTEXTS_STORE_FAILURE_ABORT")) { + qFatal(msg.toLatin1()); + } + return msg; +} + +// there is exactly 1 topcontexts directory per session, which is fine because we can only use a single +// global static KyotoCabinet instance anyway. Wrap it in a local class which is not exported at all +// (= no need to include kcpolydb.h in our own headerfile). + +class KyotoCabinetHook +{ +public: + ~KyotoCabinetHook() + { + if (s_kyotoCab) { + try { + if (!s_kyotoCab->close()) { + qCWarning(LANGUAGE) << "Error closing KyotoCabinet database:" << errorString(); + } + delete s_kyotoCab; + } catch (const std::exception &e) { + qCWarning(LANGUAGE) << kyotocabinet_exception_handler(e, QStringLiteral("closing cabinet.kch")); + // don't delete s_kyotoCab if something went wrong closing the DB + } + } + } + + static bool init() + { + s_kyotoCab = new PolyDB; + bool ok = false; + s_errorString.clear(); + try { + int attempts = 0; + uint32_t flags = PolyDB::OWRITER | PolyDB::OCREATE; + do { + attempts += 1; + // for logging, append + // #log=+#logkinds=debug + // for compression (ZLIB deflate), append + // #opts=sc#zcomp=def + ok = s_kyotoCab->open(TopDUContextDynamicData::basePath().toStdString() + "cabinet.kch#opts=sc#zcomp=lzo", flags); + if (!ok && s_kyotoCab->error().code() == BasicDB::Error::INVALID) { + // try by recreating the database + flags = PolyDB::OWRITER | PolyDB::OTRUNCATE; + } + } while (!ok && attempts < 2); + } catch (const std::exception &e) { + s_errorString = kyotocabinet_exception_handler(e, QStringLiteral("opening cabinet.kch")); + ok = false; + } + if (!ok) { + if (s_errorString.isEmpty()) { + s_errorString = QStringLiteral("Error opening KyotoCabinet database:") + + errorString(); + } + delete s_kyotoCab; + s_kyotoCab = nullptr; + } + return s_kyotoCab; + } + + inline PolyDB *instance() + { + return s_kyotoCab; + } + + static inline QString errorString() + { + return QString::fromStdString(s_kyotoCab->error().name()); + } + + static PolyDB *s_kyotoCab; + static QString s_errorString; +}; +static KyotoCabinetHook kyotoCabinet; + +PolyDB *KyotoCabinetHook::s_kyotoCab = nullptr; +QString KyotoCabinetHook::s_errorString; + +uint TopDUContextKyotoCabinet::s_DbRefCount = 0; + +TopDUContextKyotoCabinet::TopDUContextKyotoCabinet(uint topContextIndex) +{ + if (!kyotoCabinet.instance() && Q_LIKELY(QFileInfo(TopDUContextDynamicData::basePath()).isWritable())) { + if (!kyotoCabinet.init()) { + m_errorString = kyotoCabinet.s_errorString; + qCWarning(LANGUAGE) << m_errorString; + } + } + if (kyotoCabinet.instance()) { + m_currentIndex = topContextIndex; + m_currentKey = indexKey(&m_currentIndex); + s_DbRefCount += 1; + } + m_currentLen = -1; + // the remaining member vars are initialised elsewhere intentionally. +} + +TopDUContextKyotoCabinet::~TopDUContextKyotoCabinet() +{ + if (kyotoCabinet.instance()) { + s_DbRefCount -= 1; + if (s_DbRefCount <= 0) { + // optimisation: don't delete the global DB handle; too many TopDUContextKyotoCabinet + // instances are created too frequently that are deleted immediately after a + // single use. + s_DbRefCount = 0; + } + kyotoCabinet.instance()->synchronize(s_DbRefCount == 0); + } else { + s_DbRefCount = 0; + } +} + +QString TopDUContextKyotoCabinet::fileName() const +{ + return TopDUContextDynamicData::basePath() + "cabinet.kch:#" + QByteArray::number(m_currentIndex); +} + +bool TopDUContextKyotoCabinet::open(QIODevice::OpenMode mode) +{ + return TopDUContextDB::open(mode, QStringLiteral("KyotoCabinet")); +} + +void TopDUContextKyotoCabinet::commit() +{ + if (isValid() && m_mode != MDB_RDONLY) { + if (m_currentValue.size() != m_currentLen) { + // m_currentLen is the true size + qCDebug(LANGUAGE) << "TopDUContextKyotoCabinet index" << QByteArray::number(m_currentIndex) << "internal size mismatch:" + << m_currentValue.size() << "vs" << m_currentLen; + } + try { + if (!kyotoCabinet.instance()->set(m_currentKey.constData(), m_currentKey.size(), + m_currentValue.constData(), m_currentLen)) { + m_errorString = QStringLiteral("Error committing index ") + + QByteArray::number(m_currentIndex) + " size " + QString::number(m_currentLen) + + QStringLiteral(": ") + kyotoCabinet.errorString(); + qCWarning(LANGUAGE) << m_errorString; + } + } catch (const std::exception &e) { + m_errorString = kyotocabinet_exception_handler(e, QStringLiteral("committing value for ") + QByteArray::number(m_currentIndex)); + qCWarning(LANGUAGE) << m_errorString; + } + m_currentKey.clear(); + m_currentValue.clear(); + m_currentLen = 0; + } +} + +bool TopDUContextKyotoCabinet::flush() +{ + if (isValid() && m_mode != MDB_RDONLY) { + try { + return kyotoCabinet.instance()->synchronize(true); + } catch (const std::exception &e) { + m_errorString = kyotocabinet_exception_handler(e, QStringLiteral("database flush")); + qCWarning(LANGUAGE) << m_errorString; + } + } + return false; +} + +bool TopDUContextKyotoCabinet::getCurrentKeyValue() +{ + // we only return false if a read error occurred; if a key doesn't exist + // m_currentValue will remain empty. + bool ret = true; + if (m_currentValue.isEmpty()) { + // read the key value from storage into cache + size_t size; + try { + const char *value = kyotoCabinet.instance()->get(m_currentKey.constData(), m_currentKey.size(), &size); + if (value) { + m_currentValue = QByteArray(value, size); + m_currentLen = m_currentValue.size(); + m_readCursor = 0; + delete[] value; + } else { + qCWarning(LANGUAGE) << "read NULL for index" << m_currentIndex << "; exists=" << currentKeyExists(); + } + } catch (const std::exception &e) { + m_errorString = kyotocabinet_exception_handler(e, QStringLiteral("reading value for ") + QByteArray::number(m_currentIndex)); + qCWarning(LANGUAGE) << m_errorString; + ret = false; + } + } + return ret; +} + +bool TopDUContextKyotoCabinet::isValid() +{ + return kyotoCabinet.instance(); +} + +bool TopDUContextKyotoCabinet::currentKeyExists() +{ + return exists(m_currentKey); +} + +bool TopDUContextKyotoCabinet::exists(const QByteArray &key) +{ + if (kyotoCabinet.instance()) { + try { + bool found = kyotoCabinet.instance()->check(key.constData(), key.size()) >= 0; + if (!found && kyotoCabinet.instance()->error().code() != BasicDB::Error::NOREC) { + qCWarning(LANGUAGE) << QStringLiteral("Error checking for index") + key + + QStringLiteral(": ") + kyotoCabinet.errorString(); + } + return found; + } catch (const std::exception &e) { + qCWarning(LANGUAGE) << kyotocabinet_exception_handler(e, QStringLiteral("checking presence of ") + key); + } + } + return false; +} + +bool TopDUContextKyotoCabinet::exists(uint topContextIndex) +{ + return exists(indexKey(&topContextIndex)); +} + +bool TopDUContextKyotoCabinet::remove(uint topContextIndex) +{ + if (kyotoCabinet.instance()) { + const auto key = indexKey(&topContextIndex); + try { + bool ret = kyotoCabinet.instance()->remove(key.constData(), key.size()); + if (!ret) { + qCWarning(LANGUAGE) << QStringLiteral("Error removing index %1").arg(topContextIndex) + + QStringLiteral(": ") + kyotoCabinet.errorString(); + } + // also remove the file if it (still) exists + QFile::remove(TopDUContextDynamicData::pathForTopContext(topContextIndex)); + return ret; + } catch (const std::exception &e) { + qCWarning(LANGUAGE) << kyotocabinet_exception_handler(e, QStringLiteral("removing ") + QByteArray::number(topContextIndex)); + } + } + return false; +} +#endif // KDEV_TOPCONTEXTS_USE_KYOTO + +#endif // KDEV_TOPCONTEXTS_USE_FILES + +// TopDUContextFile : thin wrapper around the QFile API needed for TopDUContexts +// so TopDUContextLMDB can be used as a drop-in replacement instead of this class. +TopDUContextFile::TopDUContextFile(uint topContextIndex) + : QFile(TopDUContextDynamicData::pathForTopContext(topContextIndex)) +{ +} + +bool TopDUContextFile::exists(uint topContextIndex) +{ + return QFile::exists(TopDUContextDynamicData::pathForTopContext(topContextIndex)); +} + +bool TopDUContextFile::remove(uint topContextIndex) +{ + return QFile::remove(TopDUContextDynamicData::pathForTopContext(topContextIndex)); +} + +void TopDUContextFile::commit() +{ + QFile::close(); +} + +// kate: indent-width 2; tab-width 2;