diff --git a/.codespellrc b/.codespellrc new file mode 100644 index 0000000000..a1e8aa7c0f --- /dev/null +++ b/.codespellrc @@ -0,0 +1,8 @@ +[codespell] +# Ref: https://github.com/codespell-project/codespell#using-a-config-file +skip = .git*,.codespellrc,*.pdf,generated +check-hidden = true +# Ignore mixedCase variables, lines with latin, lines with codespell-ignore pragma, etc +ignore-regex = \b([A-Z]*[a-z]+[A-Z][a-zA-Z]*)\b|.*(Lorem ipsum|eleifend|feugait|codespell-ignore).* +# alph - is used frequently in tests, just ignore altogether +ignore-words-list = ser,alph,inbetween,interm diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml new file mode 100644 index 0000000000..b026c855dd --- /dev/null +++ b/.github/workflows/codespell.yml @@ -0,0 +1,25 @@ +# Codespell configuration is within .codespellrc +--- +name: Codespell + +on: + push: + branches: [master] + pull_request: + branches: [master] + +permissions: + contents: read + +jobs: + codespell: + name: Check for spelling errors + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Annotate locations with typos + uses: codespell-project/codespell-problem-matcher@v1 + - name: Codespell + uses: codespell-project/actions-codespell@v2 diff --git a/.pre-commit-config-local.yaml b/.pre-commit-config-local.yaml new file mode 100644 index 0000000000..1b2c1c90f2 --- /dev/null +++ b/.pre-commit-config-local.yaml @@ -0,0 +1,22 @@ +# See .pre-commit-config.yaml for usage instructions. +repos: + # Uses the local clang-format + - repo: local + hooks: + # Inspired by https://github.com/doublify/pre-commit-clang-format and + # https://github.com/pre-commit/mirrors-clang-format + - id: clang-format-16 + name: clang-format + description: Format files with ClangFormat16. + entry: clang-format-16 -i + language: system + 'types_or': [ c++, c ] + args: [ "-style=file" ] + require_serial: false + + + - repo: https://github.com/codespell-project/codespell + # Configuration for codespell is in .codespellrc + rev: v2.2.6 + hooks: + - id: codespell diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000..29ee828fa8 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,22 @@ +# Usage: +# - Install pre-commit: `pip install pre-commit` (once).ci: +# - In the main directory of QLever run +# - `pre-commit install` to use a package version of clang-format +# - `pre-commit install -c .pre-commit-config-local.yaml` to use the local clang-format +# - Each git commit will now automatically be formatted. Note that +# - commits will fail if the hook reformats your files, so you +# - have to run git commit twice in order to first format and then +# - actually commit. +repos: + # Uses a packaged version of clang-format from https://github.com/ssciwr/clang-format-wheel + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: 'v16.0.6' + hooks: + - id: clang-format + 'types_or': [ c++, c ] + + - repo: https://github.com/codespell-project/codespell + # Configuration for codespell is in .codespellrc + rev: v2.2.6 + hooks: + - id: codespell diff --git a/CMakeLists.txt b/CMakeLists.txt index 45f338ade8..b3fad60c81 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,7 @@ else () endif () ## Build targets for address sanitizer -# AddressSanitize + set(CMAKE_C_FLAGS_ASAN "-fsanitize=address -fsanitize=undefined -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1" CACHE STRING "Flags used by the C compiler during AddressSanitizer builds." @@ -70,7 +70,7 @@ include(FetchContent) FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG f8d7d77c06936315286eb55f8de22cd23c188571 # release-1.14.0 + GIT_TAG 33af80a883ddc33d9c0fac0a5b4578301efb18de # main branch on 2024/05/16 ) ################################ @@ -241,7 +241,7 @@ set(ABSL_PROPAGATE_CXX_STD ON) FetchContent_Declare( abseil GIT_REPOSITORY https://github.com/abseil/abseil-cpp.git - GIT_TAG 258e5a15759cc3d122d4a4826bc499af91d40aa9 # 2023-12-21 + GIT_TAG 93ac3a4f9ee7792af399cebd873ee99ce15aed08 # 2024-05-16 ) if (USE_PARALLEL) @@ -348,7 +348,7 @@ message(STATUS ---) include_directories(src) # Run the script `CompilationInfo.cmake` that creates the file `CompilationInfo.cpp` -# with the current git hash and the curent time and date. When specifying +# with the current git hash and the current time and date. When specifying # `-DDONT_UPDATE_COMPILATION_INFO=true` as an argument to `cmake`, the compilation info is # never updated. This is useful during development to avoid a relinking of the binaries for # every compilation. diff --git a/Dockerfile b/Dockerfile index b2d2945de8..46ae129e3e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -41,7 +41,7 @@ ENV MEMORY_FOR_QUERIES 70 ENV CACHE_MAX_SIZE_GB 30 ENV CACHE_MAX_SIZE_GB_SINGLE_ENTRY 5 ENV CACHE_MAX_NUM_ENTRIES 1000 -# Need the shell to get the INDEX_PREFIX envirionment variable +# Need the shell to get the INDEX_PREFIX environment variable ENTRYPOINT ["/bin/sh", "-c", "exec ServerMain -i \"/index/${INDEX_PREFIX}\" -j 8 -m ${MEMORY_FOR_QUERIES} -c ${CACHE_MAX_SIZE_GB} -e ${CACHE_MAX_SIZE_GB_SINGLE_ENTRY} -k ${CACHE_MAX_NUM_ENTRIES} -p 7001 \"$@\"", "--"] # Build image: docker build -t qlever.master . diff --git a/Dockerfiles/Dockerfile.Ubuntu18.04 b/Dockerfiles/Dockerfile.Ubuntu18.04 index 7af32c5a35..1bf75191c5 100644 --- a/Dockerfiles/Dockerfile.Ubuntu18.04 +++ b/Dockerfiles/Dockerfile.Ubuntu18.04 @@ -49,7 +49,7 @@ ENV MEMORY_FOR_QUERIES 70 ENV CACHE_MAX_SIZE_GB 30 ENV CACHE_MAX_SIZE_GB_SINGLE_ENTRY 5 ENV CACHE_MAX_NUM_ENTRIES 1000 -# Need the shell to get the INDEX_PREFIX envirionment variable +# Need the shell to get the INDEX_PREFIX environment variable ENTRYPOINT ["/bin/sh", "-c", "exec ServerMain -i \"/index/${INDEX_PREFIX}\" -j 8 -m ${MEMORY_FOR_QUERIES} -c ${CACHE_MAX_SIZE_GB} -e ${CACHE_MAX_SIZE_GB_SINGLE_ENTRY} -k ${CACHE_MAX_NUM_ENTRIES} -p 7001 \"$@\"", "--"] # Build image: docker build -t qlever.master . diff --git a/Dockerfiles/Dockerfile.Ubuntu20.04 b/Dockerfiles/Dockerfile.Ubuntu20.04 index 11a319a358..3d9da94d24 100644 --- a/Dockerfiles/Dockerfile.Ubuntu20.04 +++ b/Dockerfiles/Dockerfile.Ubuntu20.04 @@ -45,7 +45,7 @@ ENV MEMORY_FOR_QUERIES 70 ENV CACHE_MAX_SIZE_GB 30 ENV CACHE_MAX_SIZE_GB_SINGLE_ENTRY 5 ENV CACHE_MAX_NUM_ENTRIES 1000 -# Need the shell to get the INDEX_PREFIX envirionment variable +# Need the shell to get the INDEX_PREFIX environment variable ENTRYPOINT ["/bin/sh", "-c", "exec ServerMain -i \"/index/${INDEX_PREFIX}\" -j 8 -m ${MEMORY_FOR_QUERIES} -c ${CACHE_MAX_SIZE_GB} -e ${CACHE_MAX_SIZE_GB_SINGLE_ENTRY} -k ${CACHE_MAX_NUM_ENTRIES} -p 7001 \"$@\"", "--"] # Build image: docker build -t qlever.master . diff --git a/README.md b/README.md index 4bb752c50c..24d1234caa 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # QLever -[![Docker build](https://github.com/ad-freiburg/QLever/actions/workflows/docker-publish.yml/badge.svg)](https://github.com/ad-freiburg/QLever/actions/workflows/docker-build.yml) +[![Docker build](https://github.com/ad-freiburg/QLever/actions/workflows/docker-publish.yml/badge.svg)](https://github.com/ad-freiburg/QLever/actions/workflows/docker-publish.yml) [![Native build](https://github.com/ad-freiburg/qlever/actions/workflows/native-build.yml/badge.svg)](https://github.com/ad-freiburg/qlever/actions/workflows/native-build.yml) [![Format check](https://github.com/ad-freiburg/qlever/actions/workflows/format-check.yml/badge.svg)](https://github.com/ad-freiburg/qlever/actions/workflows/format-check.yml) [![Test coverage](https://codecov.io/github/ad-freiburg/qlever/branch/master/graph/badge.svg?token=OHcEh02rW0)](https://codecov.io/github/ad-freiburg/qlever) diff --git a/benchmark/BenchmarkExamples.cpp b/benchmark/BenchmarkExamples.cpp index 9ac38180aa..e419b96feb 100644 --- a/benchmark/BenchmarkExamples.cpp +++ b/benchmark/BenchmarkExamples.cpp @@ -62,7 +62,7 @@ class ConfigOptions : public BenchmarkInterface { "allowed for the configuration option \"num-signs\".", numSigns); - manager.addOption("coin-flip-try", "The number of succesful coin flips.", + manager.addOption("coin-flip-try", "The number of successful coin flips.", &wonOnTryX_, {false, false, false, false, false}); // Sub manager can be used to organize things better. They are basically @@ -94,7 +94,7 @@ class BMSingleMeasurements : public ConfigOptions { exponentiate(number); }); auto& multipleTimes = results.addMeasurement( - "Recursivly exponentiate multiple times", [&number, &exponentiate]() { + "Recursively exponentiate multiple times", [&number, &exponentiate]() { size_t toExponentiate = number; for (size_t i = 0; i < 10'000'000'000; i++) { toExponentiate = exponentiate(toExponentiate); diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt index 9054dd0f49..ed86be5554 100644 --- a/benchmark/CMakeLists.txt +++ b/benchmark/CMakeLists.txt @@ -27,6 +27,8 @@ endfunction() # Add benchmarks after here. addAndLinkBenchmark(BenchmarkExamples) +addAndLinkBenchmark(JoinAlgorithmBenchmark testUtil memorySize) + addAndLinkBenchmark(IdTableCompressedWriterBenchmark engine testUtil) addAndLinkBenchmark(ParallelMergeBenchmark) diff --git a/benchmark/GroupByHashMapBenchmark.cpp b/benchmark/GroupByHashMapBenchmark.cpp index 8b32efa0fd..346c9da931 100644 --- a/benchmark/GroupByHashMapBenchmark.cpp +++ b/benchmark/GroupByHashMapBenchmark.cpp @@ -84,7 +84,9 @@ auto generateRandomLocalVocabAndIndicesVec = [](size_t n, size_t m) { for (size_t j = 0; j < m; j++) { str += alphanum.at(gen()); } - indices.push_back(localVocab.getIndexAndAddIfNotContained(str)); + using namespace ad_utility::triple_component; + indices.push_back(localVocab.getIndexAndAddIfNotContained( + LiteralOrIri::literalWithoutQuotes(str))); } return std::make_pair(std::move(localVocab), indices); diff --git a/benchmark/JoinAlgorithmBenchmark.cpp b/benchmark/JoinAlgorithmBenchmark.cpp new file mode 100644 index 0000000000..18945aa41c --- /dev/null +++ b/benchmark/JoinAlgorithmBenchmark.cpp @@ -0,0 +1,2225 @@ +// Copyright 2023, University of Freiburg, +// Chair of Algorithms and Data Structures. +// Author: Andre Schlegel (January of 2023, schlegea@informatik.uni-freiburg.de) +// Author of the file this file is based on: Björn Buchhold +// (buchhold@informatik.uni-freiburg.de) +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../benchmark/infrastructure/Benchmark.h" +#include "../benchmark/infrastructure/BenchmarkMeasurementContainer.h" +#include "../benchmark/infrastructure/BenchmarkMetadata.h" +#include "../benchmark/util/ResultTableColumnOperations.h" +#include "../test/util/IdTableHelpers.h" +#include "../test/util/JoinHelpers.h" +#include "../test/util/RandomTestHelpers.h" +#include "engine/Engine.h" +#include "engine/Join.h" +#include "engine/QueryExecutionTree.h" +#include "engine/Result.h" +#include "engine/idTable/IdTable.h" +#include "global/ValueId.h" +#include "util/Algorithm.h" +#include "util/ConfigManager/ConfigManager.h" +#include "util/ConfigManager/ConfigOptionProxy.h" +#include "util/ConstexprUtils.h" +#include "util/Exception.h" +#include "util/Forward.h" +#include "util/HashMap.h" +#include "util/HashSet.h" +#include "util/Log.h" +#include "util/MemorySize/MemorySize.h" +#include "util/Random.h" +#include "util/StringUtils.h" +#include "util/TypeTraits.h" + +using namespace std::string_literals; + +namespace ad_benchmark { + +/* +@brief Return true, iff, the given value is unchanged, when casting to type +`Target` +*/ +template +requires std::convertible_to +static constexpr bool isValuePreservingCast(const Source& source) { + return static_cast(static_cast(source)) == source; +} + +/* +@brief Return biggest possible value for the given arithmetic type. +*/ +template +consteval Type getMaxValue() { + return std::numeric_limits::max(); +} + +/* +@brief Helper function for throwing overflow errors. + +@param reason What is the reason for the overflow? +*/ +template +void throwOverflowError(const std::string_view reason) { + std::string typeName; + if constexpr (std::same_as) { + typeName = "double"; + } else { + AD_CORRECTNESS_CHECK((std::same_as)); + typeName = "size_t"; + } + throw std::runtime_error(absl::StrCat( + typeName, " overflow error: The ", reason, " is bigger than the ", + typeName, " type maximum ", getMaxValue(), + ". Try reducing the values for the configuration options.")); +} + +/* +A struct holding a list of all unique elements inside an `IdTable` column and +how often they occur inside this column. +Note: Can not be updated after creation. +*/ +struct SetOfIdTableColumnElements { + /* + The list of all unique elements is also included inside `numOccurrences_`. + However, accessing a hash map entry based on index position takes linear time, + instead of constant. + */ + std::vector> uniqueElements_{}; + ad_utility::HashMap numOccurrences_{}; + + /* + Set the member variables for the given column. + */ + explicit SetOfIdTableColumnElements( + const std::span& idTableColumnRef) { + std::ranges::for_each(idTableColumnRef, [this](const ValueId& id) { + if (auto numOccurrencesIterator = numOccurrences_.find(id); + numOccurrencesIterator != numOccurrences_.end()) { + (numOccurrencesIterator->second)++; + } else { + numOccurrences_.emplace(id, 1UL); + uniqueElements_.emplace_back(id); + } + }); + } +}; + +/* +@brief Create an overlap between the join columns of the IdTables, by randomly +choosing distinct elements from the join column of the smaller table and +overriding all their occurrences in the join column with randomly chosen +distinct elements from the join column of the bigger table. + +@param smallerTable The table, where distinct join column elements will be +overwritten. +@param biggerTable The table, where distinct join column elements will be copied +from. +@param probabilityToCreateOverlap The height of the probability for any distinct +join column element of `smallerTable` to be overwritten by a random distinct +join column element of `biggerTable`. +@param randomSeed Seed for the random generators. + +@returns The number of new overlap matches created. That is, the amount +of rows added to the result of a join operation with the two given tables. +*/ +static size_t createOverlapRandomly(IdTableAndJoinColumn* const smallerTable, + const IdTableAndJoinColumn& biggerTable, + const double probabilityToCreateOverlap, + ad_utility::RandomSeed randomSeed) { + // For easier access. + auto smallerTableJoinColumnRef{ + smallerTable->idTable.getColumn(smallerTable->joinColumn)}; + const auto& biggerTableJoinColumnRef{ + biggerTable.idTable.getColumn(biggerTable.joinColumn)}; + + // The probability for creating an overlap must be in (0,100], any other + // values make no sense. + AD_CONTRACT_CHECK(0 < probabilityToCreateOverlap && + probabilityToCreateOverlap <= 100); + + // Is the bigger table actually bigger? + AD_CONTRACT_CHECK(smallerTableJoinColumnRef.size() <= + biggerTableJoinColumnRef.size()); + + // Collect and count the table elements. + SetOfIdTableColumnElements biggerTableJoinColumnSet(biggerTableJoinColumnRef); + + // Seeds for the random generators, so that things are less similar. + const std::array seeds = + createArrayOfRandomSeeds<2>(std::move(randomSeed)); + + /* + Creating the generator for choosing a random distinct join column element + in the bigger table. + */ + ad_utility::SlowRandomIntGenerator randomBiggerTableElement( + 0, biggerTableJoinColumnSet.uniqueElements_.size() - 1, seeds.at(0)); + + // Generator for checking, if an overlap should be created. + ad_utility::RandomDoubleGenerator randomDouble(0, 100, seeds.at(1)); + + /* + The amount of new overlap matches, that are generated by this + function. + */ + size_t newOverlapMatches{0UL}; + + // Create the overlap. + ad_utility::HashMap> + smallerTableElementToNewElement{}; + std::ranges::for_each( + smallerTableJoinColumnRef, + [&randomDouble, &probabilityToCreateOverlap, + &smallerTableElementToNewElement, &randomBiggerTableElement, + &newOverlapMatches, &biggerTableJoinColumnSet](auto& id) { + /* + If a value has no hash map value, with which it will be overwritten, we + either assign it its own value, or an element from the bigger table. + */ + if (auto newValueIterator = smallerTableElementToNewElement.find(id); + newValueIterator != smallerTableElementToNewElement.end()) { + const ValueId& newValue = newValueIterator->second; + // Values, that are only found in the smaller table, are added to the + // hash map with value 0. + const size_t numOccurrences{ + biggerTableJoinColumnSet.numOccurrences_[newValue]}; + + // Skip, if the addition would cause an overflow. + if (newOverlapMatches > + getMaxValue() - numOccurrences) { + return; + } + id = newValue; + newOverlapMatches += numOccurrences; + } else if (randomDouble() <= probabilityToCreateOverlap) { + /* + Randomly assign one of the distinct elements in the bigger table to be + the new value. This can only happen the first time, an element in the + smaller table is encountered, because afterwards it will always have + an entry in the hash map for the new values. + */ + smallerTableElementToNewElement.emplace( + id, biggerTableJoinColumnSet.uniqueElements_.at( + randomBiggerTableElement())); + } else { + /* + Assign the value to itself. + This is needed, because so we can indirectly track the first + 'encounter' with an distinct element in the smaller table and save + resources. + */ + smallerTableElementToNewElement.emplace(id, id); + } + }); + + return newOverlapMatches; +} + +/* +@brief Create overlaps between the join columns of the `IdTable`s until it is no +longer possible to grow closer to the wanted number of overlap matches. +Note: Because of runtime complexity concerns, not all overlap possibilities can +be tried and the end result can be unoptimal. + +@param smallerTable The table, where distinct join column elements will be +overwritten. +@param biggerTable The table, where distinct join column elements will be copied +from. +@param wantedNumNewOverlapMatches How many new overlap matches should be +created. Note, that it is not always possible to reach the wanted number. +@param randomSeed Seed for the random generators. + +@returns The number of new overlap matches created. That is, the amount +of rows added to the result of a join operation with the two given tables. +*/ +static size_t createOverlapRandomly(IdTableAndJoinColumn* const smallerTable, + const IdTableAndJoinColumn& biggerTable, + const size_t wantedNumNewOverlapMatches, + ad_utility::RandomSeed randomSeed) { + // For easier access. + auto smallerTableJoinColumnRef{ + smallerTable->idTable.getColumn(smallerTable->joinColumn)}; + const auto& biggerTableJoinColumnRef{ + biggerTable.idTable.getColumn(biggerTable.joinColumn)}; + + // Is the bigger table actually bigger? + AD_CONTRACT_CHECK(smallerTableJoinColumnRef.size() <= + biggerTableJoinColumnRef.size()); + + // Collect and count the table elements. + const SetOfIdTableColumnElements biggerTableJoinColumnSet( + biggerTableJoinColumnRef); + SetOfIdTableColumnElements smallerTableJoinColumnSet( + smallerTableJoinColumnRef); + + // Seeds for the random generators, so that things are less similar. + const std::array seeds = + createArrayOfRandomSeeds<2>(std::move(randomSeed)); + + /* + Creating the generator for choosing a random distinct join column element + in the bigger table. + */ + ad_utility::SlowRandomIntGenerator randomBiggerTableElement( + 0, biggerTableJoinColumnSet.uniqueElements_.size() - 1, seeds.at(0)); + + /* + Assign distinct join column elements of the smaller table to be overwritten by + the bigger table, until we created enough new overlap matches. + */ + randomShuffle(smallerTableJoinColumnSet.uniqueElements_.begin(), + smallerTableJoinColumnSet.uniqueElements_.end(), seeds.at(1)); + size_t newOverlapMatches{0}; + ad_utility::HashMap> + smallerTableElementToNewElement{}; + std::ranges::for_each( + smallerTableJoinColumnSet.uniqueElements_, + [&randomBiggerTableElement, &wantedNumNewOverlapMatches, + &newOverlapMatches, &smallerTableElementToNewElement, + &biggerTableJoinColumnSet, + &smallerTableJoinColumnSet](const ValueId& smallerTableId) { + const auto& biggerTableId{biggerTableJoinColumnSet.uniqueElements_.at( + randomBiggerTableElement())}; + + // Skip this possibility, if we have an overflow. + size_t newMatches{ + smallerTableJoinColumnSet.numOccurrences_.at(smallerTableId)}; + if (const size_t numOccurencesBiggerTable{ + biggerTableJoinColumnSet.numOccurrences_.at(biggerTableId)}; + newMatches > getMaxValue() / numOccurencesBiggerTable) { + return; + } else { + newMatches *= numOccurencesBiggerTable; + } + + // Just add as long as the result is smaller/equal to the wanted number + // of overlaps. + if (newMatches <= wantedNumNewOverlapMatches && + newOverlapMatches <= wantedNumNewOverlapMatches - newMatches) { + smallerTableElementToNewElement.emplace(smallerTableId, + biggerTableId); + newOverlapMatches += newMatches; + } + }); + + // Overwrite the designated values in the smaller table. + std::ranges::for_each( + smallerTableJoinColumnRef, [&smallerTableElementToNewElement](auto& id) { + if (auto newValueIterator = smallerTableElementToNewElement.find(id); + newValueIterator != smallerTableElementToNewElement.end()) { + id = newValueIterator->second; + } + }); + + return newOverlapMatches; +} + +/* +The columns of the automatically generated benchmark tables contain the +following information: +- The parameter, that changes with every row. +- Time needed for sorting `IdTable`s. +- Time needed for merge/galloping join. +- Time needed for sorting and merge/galloping added together. +- Time needed for the hash join. +- How many rows the result of joining the tables has. +- How much faster the hash join is. For example: Two times faster. + +The following enum exists, in order to make the information about the order of +columns explicit. +*/ +enum struct GeneratedTableColumn : unsigned long { + ChangingParamter = 0UL, + TimeForSorting, + TimeForMergeGallopingJoin, + TimeForSortingAndMergeGallopingJoin, + TimeForHashJoin, + NumRowsOfJoinResult, + JoinAlgorithmSpeedup +}; + +// TODO Replace usage with `std::to_underlying`. +/* +Convert the given enum value into the underlying type. +*/ +template +requires std::is_enum_v auto toUnderlying(const Enum& e) { + return static_cast>(e); +} + +// `T` must be an invocable object, which can be invoked with `const size_t&` +// and returns an instance of `ReturnType`. +template +concept growthFunction = + ad_utility::RegularInvocableWithExactReturnType; + +// Is `T` of the given type, or a function, that takes `size_t` and return +// the given type? +template +concept isTypeOrGrowthFunction = + std::same_as || growthFunction; + +// There must be exactly one growth function, that either returns a `size_t`, or +// a `float`. +template +concept exactlyOneGrowthFunction = + ((growthFunction || growthFunction)+...) == 1; + +/* +@brief Calculates the smallest whole exponent $n$, so that $base^n$ is equal, or +bigger, than the `startingPoint`. +*/ +template T> +static double calculateNextWholeExponent(const T& base, + const T& startingPoint) { + // This is a rather simple calculation: We calculate + // $log_(base)(startingPoint)$ and round up. + AD_CONTRACT_CHECK(isValuePreservingCast(startingPoint)); + AD_CONTRACT_CHECK(isValuePreservingCast(base)); + return std::ceil(std::log(static_cast(startingPoint)) / + std::log(static_cast(base))); +} + +/* +@brief Generate a sorted, inclusive interval of exponents $base^x$, with $x$ +always a natural number. +*/ +template +requires std::convertible_to +static std::vector generateExponentInterval(T base, T inclusiveLowerBound, + T inclusiveUpperBound) { + std::vector elements{}; + + /* + A short explanation: We calculate $log_(base_)(inclusiveLowerBound_)$ and + round up. This should give us the $x$ of the first $base_^x$ equal, or + bigger, than `inclusiveLowerBound_`. + */ + AD_CONTRACT_CHECK(isValuePreservingCast(base)); + AD_CONTRACT_CHECK(isValuePreservingCast( + std::pow(static_cast(base), + calculateNextWholeExponent(base, inclusiveLowerBound)))); + auto currentExponent = static_cast( + std::pow(static_cast(base), + calculateNextWholeExponent(base, inclusiveLowerBound))); + + // The rest of the elements. + while (currentExponent <= inclusiveUpperBound && + currentExponent <= std::numeric_limits::max() / base) { + elements.push_back(currentExponent); + currentExponent *= base; + } + return elements; +} + +/* +@brief Generate a sorted,inclusive interval of all natural numbers inside +`[inclusiveLowerBound, inclusiveUpperBound]`. +*/ +template +static std::vector generateNaturalNumberSequenceInterval( + T inclusiveLowerBound, T inclusiveUpperBound) { + if constexpr (std::floating_point) { + inclusiveLowerBound = std::ceil(inclusiveLowerBound); + inclusiveUpperBound = std::floor(inclusiveUpperBound); + } + std::vector elements( + inclusiveUpperBound < inclusiveLowerBound + ? 0UL + : static_cast(inclusiveUpperBound - inclusiveLowerBound + 1), + inclusiveLowerBound); + std::iota(elements.begin(), elements.end(), inclusiveLowerBound); + + return elements; +} + +// Merge multiple sorted vectors into one sorted vector, where every element is +// unique. +template +static std::vector mergeSortedVectors( + const std::vector>& intervals) { + std::vector mergedVector{}; + + // Merge. + std::ranges::for_each(intervals, [&mergedVector](std::vector elements) { + if (mergedVector.empty() || elements.empty()) { + std::ranges::copy(elements, std::back_inserter(mergedVector)); + return; + } + const size_t idxOldLastElem = mergedVector.size() - 1; + std::ranges::copy(elements, std::back_inserter(mergedVector)); + if (mergedVector.at(idxOldLastElem) > mergedVector.at(idxOldLastElem + 1)) { + std::ranges::inplace_merge( + mergedVector, + std::ranges::next(mergedVector.begin(), idxOldLastElem + 1)); + } + }); + + // Delete duplicates. + const auto ret = std::ranges::unique(mergedVector); + mergedVector.erase(ret.begin(), ret.end()); + return mergedVector; +} + +/* +@brief Approximate the amount of memory (in bytes), that a `IdTable` needs. + +@param numRows, numColumns How many rows and columns the `IdTable` has. +*/ +ad_utility::MemorySize approximateMemoryNeededByIdTable( + const size_t& numRows, const size_t& numColumns) { + /* + The overhead can be, more or less, ignored. We are just concerned over + the space needed for the entries. + */ + constexpr size_t memoryPerIdTableEntryInByte = sizeof(IdTable::value_type); + + // In case of overflow, throw an error. + if (numRows > getMaxValue() / numColumns || + numRows * numColumns > + getMaxValue() / memoryPerIdTableEntryInByte) { + throwOverflowError(absl::StrCat("memory size of an 'IdTable' with ", + numRows, " and ", numColumns, + " columns")); + } + + return ad_utility::MemorySize::bytes(numRows * numColumns * + memoryPerIdTableEntryInByte); +} + +/* +@brief Approximate the amount of rows (rounded down) in an `IdTable` with the +given number of columns and memory size. +*/ +static size_t approximateNumIdTableRows(const ad_utility::MemorySize& m, + const size_t numColumns) { + AD_CORRECTNESS_CHECK(numColumns > 0); + AD_CORRECTNESS_CHECK(m.getBytes() > 0); + return (m.getBytes() / sizeof(IdTable::value_type)) / numColumns; +} + +// A struct for holding the variables, that the configuration options will write +// to. +struct ConfigVariables { + /* + The benchmark classes always make tables, where one attribute of the + `IdTables` gets bigger with every row, while the other attributes stay the + same. + For the attributes, that don't stay the same, inclusive boundaries are + defined. Sometimes implicitly via other configuration option. (With the + exception of the sample size ratios for the special benchmarking class + `BmSampleSizeRatio`.) + + For an explanation, what a member variables does, see the created + `ConfigOption`s in `GeneralInterfaceImplementation`. + */ + size_t minSmallerTableRows_; + size_t minBiggerTableRows_; + size_t maxBiggerTableRows_; + size_t smallerTableNumColumns_; + size_t biggerTableNumColumns_; + float overlapChance_; + float smallerTableJoinColumnSampleSizeRatio_; + float biggerTableJoinColumnSampleSizeRatio_; + float minRatioRows_; + float maxRatioRows_; + std::vector benchmarkSampleSizeRatios_; + + /* + The max time for a single measurement and the max memory, that a single + `IdTable` is allowed to take up. + Both are set via `ConfigManager` and the user at runtime, but because their + pure form contains coded information, mainly that `0` stands for `infinite`, + there are getter, which transform them into easier to understand forms. + */ + float maxTimeSingleMeasurement_; + std::string configVariableMaxMemory_; + + /* + The random seed, that we use to create random seeds for our random + generators. Transformed into the more fitting type via getter. + */ + size_t randomSeed_; + + /* + Get the value of the corresponding configuration option. Empty optional stands + for `infinite` time. + */ + std::optional maxTimeSingleMeasurement() const { + if (maxTimeSingleMeasurement_ != 0) { + return {maxTimeSingleMeasurement_}; + } else { + return {std::nullopt}; + } + } + + /* + @brief The maximum amount of memory, the bigger table, and by simple logic + also the smaller table, is allowed to take up. Iff returns the same value as + `maxMemory()`, if the `max-memory` configuration option, interpreted as a + `MemorySize`, wasn't set to `0`. (Which stand for infinite memory.) + */ + ad_utility::MemorySize maxMemoryBiggerTable() const { + return maxMemory().value_or(approximateMemoryNeededByIdTable( + maxBiggerTableRows_, biggerTableNumColumns_)); + } + + /* + The maximum amount of memory, any table is allowed to take up. + Returns the value of the `max-memory` configuration option interpreted as a + `MemorySize`, if it wasn't set to `0`. (Which stand for infinite memory.) In + the case of `0`, returns an empty optional. + */ + std::optional maxMemory() const { + ad_utility::MemorySize maxMemory{ + ad_utility::MemorySize::parse(configVariableMaxMemory_)}; + if (maxMemory != 0_B) { + return {std::move(maxMemory)}; + } else { + return {std::nullopt}; + } + } + + /* + Getter for the the random seed, that we use to create random seeds for our + random generators. + */ + ad_utility::RandomSeed randomSeed() const { + /* + Note: The static cast is needed, because a random generator seed is always + `unsigned int`: + */ + return ad_utility::RandomSeed::make(static_cast(randomSeed_)); + } +}; + +/* +Partly implements the interface `BenchmarkInterface`, by: + +- Providing the member variables, that the benchmark classes here need +using the `ConfigManager`. + +- A helper function for adding the general metadata, that every benchmarking +class adds.. + +- A general function for generating a specific `ResultTable`, that measures the +join algorithms for the given configuration options. +*/ +class GeneralInterfaceImplementation : public BenchmarkInterface { + // The variables, that our configuration options will write to. + ConfigVariables configVariables_; + + public: + const ConfigVariables& getConfigVariables() const { return configVariables_; } + + // The default constructor, which sets up the `ConfigManager`. + GeneralInterfaceImplementation() { + ad_utility::ConfigManager& config = getConfigManager(); + + decltype(auto) minSmallerTableRows = config.addOption( + "min-smaller-table-rows", + "The minimum amount of rows for the smaller 'IdTable' in benchmarking " + "tables.", + &configVariables_.minSmallerTableRows_, 10000UL); + + decltype(auto) minBiggerTableRows = config.addOption( + "min-bigger-table-rows", + "The minimum amount of rows for the bigger 'IdTable' in benchmarking " + "tables.", + &configVariables_.minBiggerTableRows_, 100000UL); + decltype(auto) maxBiggerTableRows = config.addOption( + "max-bigger-table-rows", + "The maximum amount of rows for the bigger 'IdTable' in benchmarking " + "tables.", + &configVariables_.maxBiggerTableRows_, 10000000UL); + + decltype(auto) smallerTableNumColumns = + config.addOption("smaller-table-num-columns", + "The amount of columns in the smaller IdTable.", + &configVariables_.smallerTableNumColumns_, 20UL); + decltype(auto) biggerTableNumColumns = + config.addOption("bigger-table-num-columns", + "The amount of columns in the bigger IdTable.", + &configVariables_.biggerTableNumColumns_, 20UL); + + decltype(auto) overlapChance = config.addOption( + "overlap-chance", + "Chance for all occurrences of a distinc element in the join column of " + "the smaller 'IdTable' to be the same value as a distinc element in " + "the join column of the bigger 'IdTable'. Must be in the range " + "$(0,100]$.", + &configVariables_.overlapChance_, 50.f); + + decltype(auto) smallerTableSampleSizeRatio = config.addOption( + "smaller-table-join-column-sample-size-ratio", + "Join column entries of the smaller tables are picked from a sample " + "space with size 'Amount of smaller table rows' via discrete uniform " + "distribution. This option adjusts the sample space size to 'Amount of " + "rows * ratio' (rounded up), which affects the possibility of " + "duplicates.", + &configVariables_.smallerTableJoinColumnSampleSizeRatio_, 1.f); + decltype(auto) biggerTableSampleSizeRatio = config.addOption( + "bigger-table-join-column-sample-size-ratio", + "Join column entries of the bigger tables are picked from a sample " + "space with size 'Amount of bigger table rows' via discrete uniform " + "distribution. This option adjusts the sample space size to 'Amount of " + "rows * ratio' (rounded up), which affects the possibility of " + "duplicates.", + &configVariables_.biggerTableJoinColumnSampleSizeRatio_, 1.f); + + decltype(auto) randomSeed = config.addOption( + "random-seed", + "The seed used for random generators. Note: The default value is a " + "non-deterministic random value, which changes with every execution.", + &configVariables_.randomSeed_, + static_cast(std::random_device{}())); + using randomSeedValueType = decltype(randomSeed)::value_type; + + decltype(auto) minRatioRows = config.addOption( + "min-ratio-rows", + "The minimum row ratio between the smaller and the bigger 'IdTable' " + "for a benchmark table in the benchmark class 'Benchmarktables, where " + "the smaller table grows and the ratio between tables stays the " + "same.' and 'Benchmarktables, where the smaller table stays at the " + "same amount of rows and the bigger tables keeps getting bigger.'. " + "Also used for the calculation of the number of rows in the smaller " + "table in 'Benchmarktables, where only the sample size ratio " + "changes.'.", + &configVariables_.minRatioRows_, 1.f); + decltype(auto) maxRatioRows = config.addOption( + "max-ratio-rows", + "The maximum row ratio between the smaller and the bigger 'IdTable' " + "for a benchmark table in the benchmark class 'Benchmarktables, where " + "the smaller table grows and the ratio between tables stays the " + "same.'.", + &configVariables_.maxRatioRows_, 1000.f); + + decltype(auto) maxMemoryInStringFormat = config.addOption( + "max-memory", + "Max amount of memory that any 'IdTable' is allowed to take up. '0' " + "for unlimited memory. When set to anything else than '0', " + "configuration option 'max-bigger-table-rows' is ignored. Example: " + "4kB, " + "8MB, 24B, etc. ...", + &configVariables_.configVariableMaxMemory_, "0B"s); + + decltype(auto) maxTimeSingleMeasurement = config.addOption( + "max-time-single-measurement", + "The maximal amount of time, in seconds, any function measurement is " + "allowed to take. '0' for unlimited time. Note: This can only be " + "checked, after a measurement was taken.", + &configVariables_.maxTimeSingleMeasurement_, 0.f); + + decltype(auto) benchmarkSampleSizeRatios = config.addOption( + "benchmark-sample-size-ratios", + absl::StrCat( + "The sample size ratios for the benchmark class 'Benchmarktables, " + "where only the sample size ratio changes.', where the sample size " + "ratio for the smaller and bigger table are set to every element " + "combination in the cartesian product of this set with itself. " + "Example for '{1.0, 2.0}':\n", + ad_utility::addIndentation( + "- Both to '1.0'.\n- Both to '2.0'.\n- The smaller table " + "sample size ratio to '1.0' and the bigger table sample size " + "ratio to '2.0'.\n- The smaller table sample size ratio to " + "'2.0' and the bigger table sample size ratio to '1.0'.", + " ")), + &configVariables_.benchmarkSampleSizeRatios_, + std::vector{0.1f, 1.f, 10.f}); + using benchmarkSampleSizeRatiosValueType = + decltype(benchmarkSampleSizeRatios)::value_type; + + // Helper function for generating lambdas for validators. + + /* + @brief The generated lambda returns true, iff if it is called with a value, + that is bigger than the given minimum value + + @param canBeEqual If true, the generated lambda also returns true, if the + values are equal. + */ + auto generateBiggerEqualLambda = [](const T& minimumValue, + bool canBeEqual) { + return [minimumValue, canBeEqual](const T& valueToCheck) { + return valueToCheck > minimumValue || + (canBeEqual && valueToCheck == minimumValue); + }; + }; + auto generateBiggerEqualLambdaDesc = + [](const ad_utility::isInstantiation< + ad_utility::ConstConfigOptionProxy> auto& option, + const auto& minimumValue, bool canBeEqual) { + return absl::StrCat("'", option.getConfigOption().getIdentifier(), + "' must be bigger than", + canBeEqual ? ", or equal to," : "", " ", + minimumValue, "."); + }; + + // Object with a `operator()` for the `<=` operator. + auto lessEqualLambda = std::less_equal{}; + auto generateLessEqualLambdaDesc = + [](const ad_utility::isInstantiation< + ad_utility::ConstConfigOptionProxy> auto& lhs, + const ad_utility::isInstantiation< + ad_utility::ConstConfigOptionProxy> auto& rhs) { + return absl::StrCat("'", lhs.getConfigOption().getIdentifier(), + "' must be smaller than, or equal to, " + "'", + rhs.getConfigOption().getIdentifier(), "'."); + }; + + // Adding the validators. + + /* + Is `max-memory` big enough, to even allow for minimum amount of row of the + smaller table, bigger table, or the table resulting from joining the smaller + and bigger table? + If not, return an error message. + */ + auto checkIfMaxMemoryBigEnoughForMinNumRows = + [&maxMemoryInStringFormat](const ad_utility::MemorySize maxMemory, + const std::string_view tableName, + const size_t numRows, + const size_t numColumns) + -> std::optional { + const ad_utility::MemorySize memoryNeededForMinNumRows = + approximateMemoryNeededByIdTable(numRows, numColumns); + // Remember: `0` is for unlimited memory. + if (maxMemory == 0_B || memoryNeededForMinNumRows <= maxMemory) { + return std::nullopt; + } else { + return std::make_optional(absl::StrCat( + "'", maxMemoryInStringFormat.getConfigOption().getIdentifier(), + "' (", maxMemory.asString(), ") must be big enough, for at least ", + numRows, " rows in the ", tableName, ", which requires at least ", + memoryNeededForMinNumRows.asString(), ".")); + } + }; + config.addValidator( + [checkIfMaxMemoryBigEnoughForMinNumRows](std::string_view maxMemory, + size_t smallerTableNumColumns, + size_t minNumRows) { + return checkIfMaxMemoryBigEnoughForMinNumRows( + ad_utility::MemorySize::parse(maxMemory), "smaller table", + minNumRows, smallerTableNumColumns); + }, + absl::StrCat("'", + maxMemoryInStringFormat.getConfigOption().getIdentifier(), + "' must be big enough, for at least the minimum number of " + "rows in the smaller table."), + maxMemoryInStringFormat, smallerTableNumColumns, minSmallerTableRows); + config.addValidator( + [checkIfMaxMemoryBigEnoughForMinNumRows](std::string_view maxMemory, + size_t biggerTableNumColumns, + size_t minNumRows) { + return checkIfMaxMemoryBigEnoughForMinNumRows( + ad_utility::MemorySize::parse(maxMemory), "bigger table", + minNumRows, biggerTableNumColumns); + }, + absl::StrCat("'", + maxMemoryInStringFormat.getConfigOption().getIdentifier(), + "' must be big enough, for at least the minimum number of " + "rows in the bigger table."), + maxMemoryInStringFormat, biggerTableNumColumns, minBiggerTableRows); + config.addValidator( + [checkIfMaxMemoryBigEnoughForMinNumRows](std::string_view maxMemory, + size_t smallerTableNumColumns, + size_t biggerTableNumColumns) { + return checkIfMaxMemoryBigEnoughForMinNumRows( + ad_utility::MemorySize::parse(maxMemory), + "result of joining the smaller and bigger table", 1, + smallerTableNumColumns + biggerTableNumColumns - 1); + }, + absl::StrCat("'", + maxMemoryInStringFormat.getConfigOption().getIdentifier(), + "' must be big enough, for at least one row in the result " + "of joining the smaller and bigger table."), + maxMemoryInStringFormat, smallerTableNumColumns, biggerTableNumColumns); + + // Are `min-smaller-table-rows` and `min-bigger-table-rows` big enough, to + // deliver interesting measurements? + const auto addValidatorEnoughRowsToBeInteresting = + [&config, &generateBiggerEqualLambda, &generateBiggerEqualLambdaDesc]( + ad_utility::ConstConfigOptionProxy option) { + config.addValidator( + generateBiggerEqualLambda( + option.getConfigOption().getDefaultValue(), true), + absl::StrCat("'", option.getConfigOption().getIdentifier(), + "' is to small. Interesting measurement values " + "start at ", + option.getConfigOption().getDefaultValueAsString(), + " rows, or more."), + absl::StrCat( + generateBiggerEqualLambdaDesc( + option, + option.getConfigOption().getDefaultValueAsString(), true), + " Interesting measurement values only appear from that point " + "onwards."), + option); + }; + addValidatorEnoughRowsToBeInteresting(minSmallerTableRows); + addValidatorEnoughRowsToBeInteresting(minBiggerTableRows); + + // Is `minSmallerTableRows` smaller, or equal, to `minBiggerTableRows`? + config.addValidator( + lessEqualLambda, + generateLessEqualLambdaDesc(minSmallerTableRows, minBiggerTableRows), + generateLessEqualLambdaDesc(minSmallerTableRows, minBiggerTableRows), + minSmallerTableRows, minBiggerTableRows); + + // Is `minBiggerTableRows` smaller, or equal, to `max-bigger-table-rows`? + config.addValidator( + lessEqualLambda, + generateLessEqualLambdaDesc(minBiggerTableRows, maxBiggerTableRows), + generateLessEqualLambdaDesc(minBiggerTableRows, maxBiggerTableRows), + minBiggerTableRows, maxBiggerTableRows); + + // Do we have at least 1 column? + config.addValidator( + generateBiggerEqualLambda(1UL, true), + generateBiggerEqualLambdaDesc(smallerTableNumColumns, 1UL, true), + generateBiggerEqualLambdaDesc(smallerTableNumColumns, 1UL, true), + smallerTableNumColumns); + config.addValidator( + generateBiggerEqualLambda(1UL, true), + generateBiggerEqualLambdaDesc(biggerTableNumColumns, 1UL, true), + generateBiggerEqualLambdaDesc(biggerTableNumColumns, 1UL, true), + biggerTableNumColumns); + + // Is `overlap-chance` bigger than 0? + config.addValidator( + generateBiggerEqualLambda(0.f, false), + generateBiggerEqualLambdaDesc(overlapChance, 0.f, false), + generateBiggerEqualLambdaDesc(overlapChance, 0.f, false), + overlapChance); + + // Are the sample size ratios bigger than 0? + config.addValidator( + generateBiggerEqualLambda(0.f, false), + generateBiggerEqualLambdaDesc(smallerTableSampleSizeRatio, 0.f, false), + generateBiggerEqualLambdaDesc(smallerTableSampleSizeRatio, 0.f, false), + smallerTableSampleSizeRatio); + config.addValidator( + generateBiggerEqualLambda(0.f, false), + generateBiggerEqualLambdaDesc(biggerTableSampleSizeRatio, 0.f, false), + generateBiggerEqualLambdaDesc(biggerTableSampleSizeRatio, 0.f, false), + biggerTableSampleSizeRatio); + const std::string benchmarkSampleSizeRatioBiggerThanZeroValidatorDesc{ + absl::StrCat( + "All entries in '", + benchmarkSampleSizeRatios.getConfigOption().getIdentifier(), + "' must be bigger than, or equal to, 0.")}; + config.addValidator( + [](const benchmarkSampleSizeRatiosValueType& vec) { + return std::ranges::all_of( + vec, + [](const benchmarkSampleSizeRatiosValueType::value_type ratio) { + return ratio >= 0.f; + }); + }, + benchmarkSampleSizeRatioBiggerThanZeroValidatorDesc, + benchmarkSampleSizeRatioBiggerThanZeroValidatorDesc, + benchmarkSampleSizeRatios); + + /* + We later signal, that the row generation for the sample size ration tables + should be stopped, by returning a float, that is the biggest entry in the + vector plus 1. + So, of course, that has to be possible. + */ + const std::string benchmarkSampleSizeRatiosMaxSizeValidatorDesc{ + absl::StrCat( + "All entries in '", + benchmarkSampleSizeRatios.getConfigOption().getIdentifier(), + "' must be smaller than, or equal to, ", + getMaxValue() - + static_cast(1), + ".")}; + config.addValidator( + [](const benchmarkSampleSizeRatiosValueType& vec) { + return std::ranges::max(vec) <= + getMaxValue() - + 1.f; + }, + benchmarkSampleSizeRatiosMaxSizeValidatorDesc, + benchmarkSampleSizeRatiosMaxSizeValidatorDesc, + benchmarkSampleSizeRatios); + + /* + Is `randomSeed_` smaller/equal than the max value for seeds? + Note: The static cast is needed, because a random generator seed is always + `unsigned int`. + */ + const std::string randomSeedMaxSizeValidatorDesc{ + absl::StrCat("'", randomSeed.getConfigOption().getIdentifier(), + "' must be smaller than, or equal to, ", + ad_utility::RandomSeed::max().get(), ".")}; + config.addValidator( + [maxSeed = static_cast( + ad_utility::RandomSeed::max().get())]( + const randomSeedValueType& seed) { return seed <= maxSeed; }, + randomSeedMaxSizeValidatorDesc, randomSeedMaxSizeValidatorDesc, + randomSeed); + + // Is `max-time-single-measurement` a positive number? + config.addValidator( + generateBiggerEqualLambda(0.f, true), + generateBiggerEqualLambdaDesc(maxTimeSingleMeasurement, 0.f, true), + generateBiggerEqualLambdaDesc(maxTimeSingleMeasurement, 0.f, true), + maxTimeSingleMeasurement); + + // Is the min ratio of rows bigger than the default? + config.addValidator( + generateBiggerEqualLambda( + minRatioRows.getConfigOption().getDefaultValue(), true), + generateBiggerEqualLambdaDesc( + minRatioRows, + minRatioRows.getConfigOption().getDefaultValue(), true), + generateBiggerEqualLambdaDesc( + minRatioRows, + minRatioRows.getConfigOption().getDefaultValue(), true), + minRatioRows); + + // Is `min-ratio-rows` smaller than `max-ratio-rows`? + config.addValidator(std::less_equal{}, + generateLessEqualLambdaDesc(minRatioRows, maxRatioRows), + generateLessEqualLambdaDesc(minRatioRows, maxRatioRows), + minRatioRows, maxRatioRows); + + /* + Is the row ratio needed for the combination of `min-smaller-table-rows` and + `min-bigger-table-rows` inside the range set via `min-ratio-rows` and + `max-ratio-rows`? + */ + const std::string minTableRowNumPossibleDesc{absl::StrCat( + "The row ratio needed for a bigger table with ", + minBiggerTableRows.getConfigOption().getValueAsString(), " ('", + minBiggerTableRows.getConfigOption().getIdentifier(), + "') rows, when the smaller table has ", + minSmallerTableRows.getConfigOption().getValueAsString(), " rows ('", + minSmallerTableRows.getConfigOption().getIdentifier(), + "'), must be in the range described via '", + minRatioRows.getConfigOption().getIdentifier(), "' (", + minRatioRows.getConfigOption().getValueAsString(), ") and '", + maxRatioRows.getConfigOption().getIdentifier(), "' (", + maxRatioRows.getConfigOption().getValueAsString(), ").")}; + config.addValidator( + [](const size_t numRowsSmallerTable, const size_t numRowsBiggerTable, + const float minRatio, const float maxRatio) { + const float neededRatio{ + static_cast(static_cast(numRowsBiggerTable) / + static_cast(numRowsSmallerTable))}; + // Checking for equality is more effort. + return !(neededRatio < minRatio || maxRatio < neededRatio); + }, + minTableRowNumPossibleDesc, minTableRowNumPossibleDesc, + minSmallerTableRows, minBiggerTableRows, minRatioRows, maxRatioRows); + + // Can the options be cast to double, while keeping their values? (Needed + // for calculations later.) + const auto addCastableValidator = + [&config](ad_utility::ConstConfigOptionProxy option) { + /* + As far as I know, it's compiler dependent, which type is bigger: + `size_t` or `double`. + */ + const std::string descriptor{absl::StrCat( + "'", option.getConfigOption().getIdentifier(), + "' must preserve its value when being cast to 'double'.")}; + config.addValidator( + [](const auto& val) { + return isValuePreservingCast(val); + }, + descriptor, descriptor, option); + }; + std::ranges::for_each(std::vector{minBiggerTableRows, maxBiggerTableRows, + minSmallerTableRows}, + addCastableValidator); + } + + /* + @brief Add metadata information about the class, that is always interesting + and not dependent on the created `ResultTable`. + */ + void addDefaultMetadata(BenchmarkMetadata* meta) const { + // Information, that is interesting for all the benchmarking classes. + meta->addKeyValuePair("random-seed", + getConfigVariables().randomSeed().get()); + meta->addKeyValuePair("smaller-table-num-columns", + getConfigVariables().smallerTableNumColumns_); + meta->addKeyValuePair("bigger-table-num-columns", + getConfigVariables().biggerTableNumColumns_); + + /* + Add metadata information about: + - "max-time-single-measurement" + - "maxMemory" + */ + auto addInfiniteWhen0 = [&meta](const std::string& name, + const auto& value) { + if (value != 0) { + meta->addKeyValuePair(name, value); + } else { + meta->addKeyValuePair(name, "infinite"); + } + }; + addInfiniteWhen0("max-time-single-measurement", + configVariables_.maxTimeSingleMeasurement_); + addInfiniteWhen0("max-memory", + getConfigVariables().maxMemory().value_or(0_B).getBytes()); + } + + // A default `stopFunction` for `makeGrowingBenchmarkTable`, that takes + // everything and always returns false. + static constexpr auto alwaysFalse = [](const auto&...) { return false; }; + + /* + @brief Create a benchmark table for join algorithm, with the given + parameters for the IdTables, which will keep getting more rows, until the + `max-time-single-measurement` getter value, the `maxMemoryBiggerTable()` + getter value, or the `maxMemory()` getter value of the configuration options + was reached/surpassed. It will additionally stop, iff `stopFunction` returns + true. The columns will be: + - Return values of the parameter, you gave a function for. + - Time needed for sorting `IdTable`s. + - Time needed for merge/galloping join. + - Time needed for sorting and merge/galloping added together. + - Time needed for the hash join. + - How many rows the result of joining the tables has. + - How much faster the hash join is. For example: Two times faster. + + @tparam T1, T2, T6, T7 Must be a float, or a function, that takes the row + number of the next to be generated row as `const size_t&`, and returns a + float. Can only be a function, if all other template `T` parameter are + vectors. + @tparam T3, T4, T5 Must be a size_t, or a function, that takes the row + number of the next to be generated row as `const size_t&`, and returns a + size_t. Can only be a function, if all other template `T` parameter are + vectors. + + @param results The `BenchmarkResults`, in which you want to create a new + benchmark table. + @param tableDescriptor A identifier for the to be created benchmark table, so + that it can be easier identified later. + @param parameterName The names of the parameter, you gave a growth function + for. Will be set as the name of the column, which will show the returned + values of the growth function. + @param stopFunction Before generating the next row, this function will be + called with the values of the function call arguments `overlap`, `ratioRows`, + `smallerTableNumRows`, `smallerTableNumColumns`, `biggerTableNumColumns`, + `smallerTableJoinColumnSampleSizeRatio` and + `biggerTableJoinColumnSampleSizeRatio` for the to be generated row. Iff. this + function returns true, the row will not be generated and the table generation + stopped. + @param overlap The height of the probability for any distinct join column + element of smallerTable to be overwritten by a random disintct join column + element of biggerTable. That is, all the occurrences of this element. + @param resultTableNumRows How many rows the result of joining the two + generated tables should have. The function argument `overlap` will be ignored, + if a value for this parameter was given. Note: The actual result table size + will be as close as possible to the wanted size, but it can not be guaranteed + to be exactly the same. + @param randomSeed Seed for the random generators. + @param smallerTableSorted, biggerTableSorted Should the bigger/smaller table + be sorted by his join column before being joined? More specifically, some + join algorithm require one, or both, of the IdTables to be sorted. If this + argument is false, the time needed for sorting the required table will + added to the time of the join algorithm. + @param ratioRows How many more rows than the smaller table should the + bigger table have? In more mathematical words: Number of rows of the + bigger table divided by the number of rows of the smaller table is equal + to `ratioRows`. + @param smallerTableNumRows How many rows should the smaller table have? + @param smallerTableNumColumns, biggerTableNumColumns How many columns + should the bigger/smaller tables have? + @param smallerTableJoinColumnSampleSizeRatio, + biggerTableJoinColumnSampleSizeRatio The join column of the tables normally + get random entries out of a sample space with the same amount of possible + numbers as there are rows in the table. (With every number having the same + chance to be picked.) This adjusts the number of elements in the sample size + to `Amount of rows * ratio`, which affects the possibility of duplicates. + */ + template + StopFunction, + isTypeOrGrowthFunction T1, isTypeOrGrowthFunction T2, + isTypeOrGrowthFunction T3, + isTypeOrGrowthFunction T4, + isTypeOrGrowthFunction T5, + isTypeOrGrowthFunction T6 = float, + isTypeOrGrowthFunction T7 = float> + requires exactlyOneGrowthFunction + ResultTable& makeGrowingBenchmarkTable( + BenchmarkResults* results, const std::string& tableDescriptor, + std::string parameterName, StopFunction stopFunction, const T1& overlap, + const std::optional& resultTableNumRows, + ad_utility::RandomSeed randomSeed, const bool smallerTableSorted, + const bool biggerTableSorted, const T2& ratioRows, + const T3& smallerTableNumRows, const T4& smallerTableNumColumns, + const T5& biggerTableNumColumns, + const T6& smallerTableJoinColumnSampleSizeRatio, + const T7& biggerTableJoinColumnSampleSizeRatio) const { + // Is something a growth function? + constexpr auto isGrowthFunction = []() { + /* + We have to cheat a bit, because being a function is not something, that + can easily be checked for to my knowledge. Instead, we simply check, if + it's one of the limited variation of growth function, that we allow. + */ + if constexpr (growthFunction || growthFunction) { + return true; + } else { + return false; + } + }; + + // Returns the first argument, that is a growth function. + auto returnFirstGrowthFunction = + [&isGrowthFunction](Ts&... args) -> auto& { + // Put them into a tuple, so that we can easily look them up. + auto tup = std::tuple{AD_FWD(args)...}; + + // Get the index of the first growth function. + constexpr static size_t idx = + ad_utility::getIndexOfFirstTypeToPassCheck(); + + // Do we have a valid index? + static_assert(idx < sizeof...(Ts), + "There was no growth function in this parameter pack."); + + return std::get(tup); + }; + + /* + @brief Call the growth function with the number of the next row to be + created, if it's a function, and return the result. Otherwise return the + given `possibleGrowthFunction`. + */ + auto returnOrCall = [&isGrowthFunction]( + const T& possibleGrowthFunction, + const size_t nextRowIdx) { + if constexpr (isGrowthFunction.template operator()()) { + return possibleGrowthFunction(nextRowIdx); + } else { + return possibleGrowthFunction; + } + }; + + // For creating a new random seed for every new row. + RandomSeedGenerator seedGenerator{std::move(randomSeed)}; + + ResultTable& table = initializeBenchmarkTable(results, tableDescriptor, + std::move(parameterName)); + + /* + Adding measurements to the table, as long as possible. + */ + while (true) { + // What's the row number of the next to be added row? + const size_t rowIdx = table.numRows(); + + // Does the addition to the table work? + if (!addNewRowToBenchmarkTable( + &table, + returnFirstGrowthFunction( + overlap, ratioRows, smallerTableNumRows, + smallerTableNumColumns, biggerTableNumColumns, + smallerTableJoinColumnSampleSizeRatio, + biggerTableJoinColumnSampleSizeRatio)(rowIdx), + stopFunction, returnOrCall(overlap, rowIdx), resultTableNumRows, + std::invoke(seedGenerator), smallerTableSorted, biggerTableSorted, + returnOrCall(ratioRows, rowIdx), + returnOrCall(smallerTableNumRows, rowIdx), + returnOrCall(smallerTableNumColumns, rowIdx), + returnOrCall(biggerTableNumColumns, rowIdx), + returnOrCall(smallerTableJoinColumnSampleSizeRatio, rowIdx), + returnOrCall(biggerTableJoinColumnSampleSizeRatio, rowIdx))) { + break; + } + } + addPostMeasurementInformationsToBenchmarkTable(&table); + return table; + } + + protected: + /* + @brief Initialize a new `ResultTable`, without any rows, in the given + `BenchmarkResults` for use with the `makeGrowingBenchmarkTable` function. + + @param tableDescriptor The descriptor for the initialized table. + @param changingParameterColumnDesc Name/Description for the first column. + */ + static ResultTable& initializeBenchmarkTable( + BenchmarkResults* results, const std::string& tableDescriptor, + std::string changingParameterColumnDesc) { + return results->addTable( + tableDescriptor, {}, + {std::move(changingParameterColumnDesc), "Time for sorting", + "Merge/Galloping join", "Sorting + merge/galloping join", "Hash join", + "Number of rows in resulting IdTable", "Speedup of hash join"}); + }; + + /* + @brief Set the columns + `GeneratedTableColumn::TimeForSortingAndMergeGallopingJoin` and + `GeneratedTableColumn::JoinAlgorithmSpeedup` based on the content of measured + execution time columns. Requires the columns with the measurements to hold no + empty entries. + */ + static void addPostMeasurementInformationsToBenchmarkTable( + ResultTable* table) { + using enum GeneratedTableColumn; + // Adding together the time for sorting the `IdTables` and then joining + // them via merge/galloping join. + sumUpColumns( + table, + ColumnNumWithType{ + toUnderlying(TimeForSortingAndMergeGallopingJoin)}, + ColumnNumWithType{toUnderlying(TimeForSorting)}, + ColumnNumWithType{toUnderlying(TimeForMergeGallopingJoin)}); + + // Calculate, how much of a speedup the hash join algorithm has in + // comparison to the merge/galloping join algrithm. + calculateSpeedupOfColumn( + table, {toUnderlying(JoinAlgorithmSpeedup)}, + {toUnderlying(TimeForHashJoin)}, + {toUnderlying(TimeForSortingAndMergeGallopingJoin)}); + } + + /* + @brief Add a new row to the benchmark table in `makeGrowingBenchmarkTable` and + set the function time measurements (join algorithms and sorting) in that row. + If setting the function time measurements was not successful, then the row + will not be added. For an explanation of the parameters, see + `makeGrowingBenchmarkTable`. + + @param changingParameterValue What value to set the first column in the new + row. + + @return True, if the row and all measurements were added. False, if the + addition of the row and the measurements was stopped, because either a + `IdTable` required more memory than was allowed via configuration options, a + single measurement took longer than was allowed via configuration options, or + the stop function returned `true`. + */ + bool addNewRowToBenchmarkTable( + ResultTable* table, + const ad_utility::SameAsAny auto changingParameterValue, + ad_utility::InvocableWithExactReturnType auto stopFunction, + const float overlap, const std::optional& resultTableNumRows, + ad_utility::RandomSeed randomSeed, const bool smallerTableSorted, + const bool biggerTableSorted, const float& ratioRows, + const size_t& smallerTableNumRows, const size_t& smallerTableNumColumns, + const size_t& biggerTableNumColumns, + const float smallerTableJoinColumnSampleSizeRatio, + const float biggerTableJoinColumnSampleSizeRatio) const { + /* + Checking, if `smallerTableJoinColumnSampleSizeRatio` and + `biggerTableJoinColumnSampleSizeRatio` are floats bigger than 0. + Otherwise , they don't make sense. + */ + AD_CONTRACT_CHECK(smallerTableJoinColumnSampleSizeRatio > 0); + AD_CONTRACT_CHECK(biggerTableJoinColumnSampleSizeRatio > 0); + + // Make sure, that things can be casted (in later calculations) without + // changing values. + AD_CORRECTNESS_CHECK(isValuePreservingCast(smallerTableNumRows)); + + // Nothing to do, if the stop function returns true. + if (std::invoke(stopFunction, overlap, ratioRows, smallerTableNumRows, + smallerTableNumColumns, biggerTableNumColumns, + smallerTableJoinColumnSampleSizeRatio, + biggerTableJoinColumnSampleSizeRatio)) { + return false; + } + + /* + Check if the smaller and bigger `IdTable` are not to big. Size of the + result table is only checked, if the configuration option for it was set. + */ + if (const auto& maxSizeInputTable{ + getConfigVariables().maxMemoryBiggerTable()}; + approximateMemoryNeededByIdTable( + smallerTableNumRows, smallerTableNumColumns) > maxSizeInputTable || + approximateMemoryNeededByIdTable( + static_cast(static_cast(smallerTableNumRows) * + ratioRows), + biggerTableNumColumns) > maxSizeInputTable) { + return false; + } + + // The lambdas for the join algorithms. + auto hashJoinLambda = makeHashJoinLambda(); + auto joinLambda = makeJoinLambda(); + + /* + Create new `IdTable`s. + First we calculate the value boundaries for the join column entries. These + are needed for the creation of randomly filled tables. + Reminder: The $-1$ in the upper bounds is, because a range [a, b] + of natural numbers has $b - a + 1$ elements. + */ + const size_t smallerTableJoinColumnLowerBound = 0; + /* + Check for overflow, before calculating `smallerTableJoinColumnUpperBound`. + + Short math explanation: Because `size_t` is bigger than `float`, + `static_cast(...) - 1` can never be cause for an overflow. Because + `smallerTableJoinColumnSampleSizeRatio` is always bigger than `0`, + `static_cast(std::ceil(...))` is also always `>=1` and can never + cause an underflow. So, `static_cast(...) - 1` can be safely + ignored. + + `std::ceil(...)` however, can have a overflow. + If there is no overflow + `std::ceil(static_cast(smallerTableNumRows) * + smallerTableJoinColumnSampleSizeRatio) <= + std::floor(getMaxValue())` must be true. Which is + true, iff, `static_cast(smallerTableNumRows) * + smallerTableJoinColumnSampleSizeRatio <= + std::floor(getMaxValue())` is true. + We negate the second clause, transform it into an overflow safe expression + and get our if clause. + */ + if (static_cast(smallerTableNumRows) > + std::floor(getMaxValue()) / + smallerTableJoinColumnSampleSizeRatio) { + throwOverflowError( + absl::StrCat("multiplication of the number of smaller table rows (", + smallerTableNumRows, + ") with 'smaller-table-join-column-sample-size-ratio' (", + smallerTableJoinColumnSampleSizeRatio, ")")); + } + const size_t smallerTableJoinColumnUpperBound = + static_cast(std::ceil(static_cast(smallerTableNumRows) * + smallerTableJoinColumnSampleSizeRatio)) - + 1; + + // Check for overflow. + if (smallerTableJoinColumnUpperBound > + getMaxValue() - 1) { + throwOverflowError( + absl::StrCat("multiplication of the number of smaller table rows (", + smallerTableNumRows, + ") with 'smaller-table-join-column-sample-size-ratio' (", + smallerTableJoinColumnSampleSizeRatio, "), plus 1,")); + } + const size_t biggerTableJoinColumnLowerBound = + smallerTableJoinColumnUpperBound + 1; + + /* + Check for overflow, before calculating `biggerTableJoinColumnUpperBound`. + Short math explanation: I check the intermediate results, before using + them, and also use the same trick as with `smallerTableJoinColumnUpperBound` + to check, that `std::ceil(...)` is neither overflow, nor underflow. + */ + if (static_cast(smallerTableNumRows) > + getMaxValue() / ratioRows) { + throwOverflowError(absl::StrCat( + " the number of bigger table rows (", + static_cast(smallerTableNumRows) * ratioRows, ")")); + } else if (static_cast(smallerTableNumRows) * ratioRows > + std::floor(getMaxValue()) / + biggerTableJoinColumnSampleSizeRatio) { + throwOverflowError( + absl::StrCat("multiplication of the number of bigger table rows (", + static_cast(smallerTableNumRows) * ratioRows, + ") with 'bigger-table-join-column-sample-size-ratio' (", + biggerTableJoinColumnSampleSizeRatio, ")")); + } else if (biggerTableJoinColumnLowerBound - 1 > + getMaxValue() - + static_cast(std::ceil( + static_cast(smallerTableNumRows) * ratioRows * + biggerTableJoinColumnSampleSizeRatio))) { + throw std::runtime_error(absl::StrCat( + "size_t overflow error: The multiplication (rounded up) of the " + "number of smaller table rows (", + smallerTableNumRows, + ") with 'smaller-table-join-column-sample-size-ratio' (", + smallerTableJoinColumnSampleSizeRatio, + "), minus 1, added to the multiplication (rounded up) of the " + "number " + "of bigger table rows (", + static_cast(smallerTableNumRows) * ratioRows, + ") with 'bigger-table-join-column-sample-size-ratio' (", + biggerTableJoinColumnSampleSizeRatio, + ") is bigger than the size_t type maximum ", getMaxValue(), + ". Try reducing the values for the configuration options.")); + } + const size_t biggerTableJoinColumnUpperBound = + biggerTableJoinColumnLowerBound + + static_cast( + std::ceil(static_cast(smallerTableNumRows) * ratioRows * + biggerTableJoinColumnSampleSizeRatio)) - + 1; + + // Seeds for the random generators, so that things are less similar + // between the tables. + const std::array seeds = + createArrayOfRandomSeeds<5>(std::move(randomSeed)); + + // Now we create two randomly filled `IdTable`, which have no overlap, and + // save them together with the information, where their join column is. + IdTableAndJoinColumn smallerTable{ + createRandomlyFilledIdTable( + smallerTableNumRows, smallerTableNumColumns, + JoinColumnAndBounds{0, smallerTableJoinColumnLowerBound, + smallerTableJoinColumnUpperBound, seeds.at(0)}, + seeds.at(1)), + 0}; + IdTableAndJoinColumn biggerTable{ + createRandomlyFilledIdTable( + static_cast(static_cast(smallerTableNumRows) * + ratioRows), + biggerTableNumColumns, + JoinColumnAndBounds{0, biggerTableJoinColumnLowerBound, + biggerTableJoinColumnUpperBound, seeds.at(2)}, + seeds.at(3)), + 0}; + + // Index of the row, that is being added. + const size_t rowIdx{table->numRows()}; + table->addRow(); + table->setEntry(rowIdx, + toUnderlying(GeneratedTableColumn::ChangingParamter), + changingParameterValue); + + // The number of rows, that the joined `ItdTable`s end up having. + size_t numRowsOfResult{0}; + + /* + Creating overlap, if wanted. + Note: The value for `numRowsOfResult` is correct, because the content of + the `IdTable`s is disjunct. + */ + if (resultTableNumRows.has_value()) { + numRowsOfResult = createOverlapRandomly( + &smallerTable, biggerTable, resultTableNumRows.value(), seeds.at(4)); + } else if (overlap > 0) { + numRowsOfResult = createOverlapRandomly(&smallerTable, biggerTable, + overlap, seeds.at(4)); + } + + /* + Check, if the size of the result table isn't to big, if the `maxMemory` + configuration option was set. + */ + if (const auto& maxMemory{getConfigVariables().maxMemory()}; + maxMemory.value_or(ad_utility::MemorySize::max()) < + approximateMemoryNeededByIdTable( + numRowsOfResult, + smallerTableNumColumns + biggerTableNumColumns - 1)) { + table->deleteRow(rowIdx); + return false; + } + + // Sort the `IdTables`, if they should be. + if (smallerTableSorted) { + sortIdTableByJoinColumnInPlace(smallerTable); + } + if (biggerTableSorted) { + sortIdTableByJoinColumnInPlace(biggerTable); + } + const auto isOverMaxTime = + [maxTime = getConfigVariables().maxTimeSingleMeasurement(), &table, + &rowIdx](const GeneratedTableColumn& columnIdx) { + /* + Simply make the comparison trivial, if there was no maximum time + set. + */ + return table->getEntry(rowIdx, toUnderlying(columnIdx)) > + maxTime.value_or(getMaxValue()); + }; + + /* + Adding the benchmark measurements to the current row. + + Hash join first, because merge/galloping join sorts all tables, if + needed, before joining them. + */ + table->addMeasurement( + rowIdx, toUnderlying(GeneratedTableColumn::TimeForHashJoin), + [&smallerTable, &biggerTable, &hashJoinLambda]() { + useJoinFunctionOnIdTables(smallerTable, biggerTable, hashJoinLambda); + }); + if (isOverMaxTime(GeneratedTableColumn::TimeForHashJoin)) { + table->deleteRow(rowIdx); + return false; + } + + /* + The sorting of the `IdTables`. That must be done before the + merge/galloping, otherwise their algorithm won't result in a correct + result. + */ + table->addMeasurement(rowIdx, + toUnderlying(GeneratedTableColumn::TimeForSorting), + [&smallerTable, &smallerTableSorted, &biggerTable, + &biggerTableSorted]() { + if (!smallerTableSorted) { + sortIdTableByJoinColumnInPlace(smallerTable); + } + if (!biggerTableSorted) { + sortIdTableByJoinColumnInPlace(biggerTable); + } + }); + if (isOverMaxTime(GeneratedTableColumn::TimeForSorting)) { + table->deleteRow(rowIdx); + return false; + } + + // The merge/galloping join. + table->addMeasurement( + rowIdx, toUnderlying(GeneratedTableColumn::TimeForMergeGallopingJoin), + [&smallerTable, &biggerTable, &joinLambda]() { + useJoinFunctionOnIdTables(smallerTable, biggerTable, joinLambda); + }); + if (isOverMaxTime(GeneratedTableColumn::TimeForMergeGallopingJoin)) { + table->deleteRow(rowIdx); + return false; + } + + // Adding the number of rows of the result. + table->setEntry(rowIdx, + toUnderlying(GeneratedTableColumn::NumRowsOfJoinResult), + numRowsOfResult); + return true; + } +}; + +/* +@brief Return a lambda function, which returns `prefixValues.at(rowIdx)` until +the vector is exhausted. After that, the lambda function calculates and returns +$base^(x+rowIdx-prefixValues.size())$. With $rowIdx$ being the single `size_t` +argument of the function and $x$ being $log_base(startingPoint)$ rounded up. + + +@tparam ReturnType The return type of the created lambda function. +*/ +template +requires std::convertible_to && + std::convertible_to +auto createDefaultGrowthLambda(const ReturnType& base, + const ReturnType& startingPoint, + std::vector prefixValues = {}) { + return [base, prefixValues = std::move(prefixValues), + startingExponent{calculateNextWholeExponent(base, startingPoint)}]( + const size_t& rowIdx) { + if (rowIdx < prefixValues.size()) { + return prefixValues.at(rowIdx); + } else { + AD_CONTRACT_CHECK(isValuePreservingCast(base)); + AD_CONTRACT_CHECK( + isValuePreservingCast(rowIdx - prefixValues.size())); + AD_CONTRACT_CHECK(isValuePreservingCast( + std::pow(static_cast(base), + startingExponent + + static_cast(rowIdx - prefixValues.size())))); + return static_cast( + std::pow(static_cast(base), + startingExponent + + static_cast(rowIdx - prefixValues.size()))); + } + }; +} + +/* +Create benchmark tables, where the smaller table stays at the same amount of +rows and the bigger tables keeps getting bigger. Amount of columns stays the +same. +*/ +class BmOnlyBiggerTableSizeChanges final + : public GeneralInterfaceImplementation { + public: + std::string name() const override { + return "Benchmarktables, where the smaller table stays at the same amount " + "of rows and the bigger tables keeps getting bigger."; + } + + BenchmarkResults runAllBenchmarks() override { + BenchmarkResults results{}; + /* + Making a benchmark table for all combination of IdTables being sorted and + any possible number of rows for the smaller `IdTable`. + */ + for (const bool smallerTableSorted : {false, true}) { + for (const bool biggerTableSorted : {false, true}) { + for (const size_t smallerTableNumRows : generateExponentInterval( + 10UL, getConfigVariables().minSmallerTableRows_, + static_cast( + static_cast( + getConfigVariables().minBiggerTableRows_) / + getConfigVariables().minRatioRows_))) { + const std::string& tableName = + absl::StrCat("Smaller table stays at ", smallerTableNumRows, + " rows, ratio to rows of bigger table grows."); + const float minRatio{static_cast(std::ceil( + static_cast(getConfigVariables().minBiggerTableRows_) / + static_cast(smallerTableNumRows)))}; + auto growthFunction = createDefaultGrowthLambda( + 10.f, std::ranges::max(minRatio, 10.f), + generateNaturalNumberSequenceInterval(minRatio, 9.f)); + ResultTable& table = makeGrowingBenchmarkTable( + &results, tableName, "Row ratio", alwaysFalse, + getConfigVariables().overlapChance_, std::nullopt, + getConfigVariables().randomSeed(), smallerTableSorted, + biggerTableSorted, growthFunction, smallerTableNumRows, + getConfigVariables().smallerTableNumColumns_, + getConfigVariables().biggerTableNumColumns_, + getConfigVariables().smallerTableJoinColumnSampleSizeRatio_, + getConfigVariables().biggerTableJoinColumnSampleSizeRatio_); + + // Add the metadata, that changes with every call and can't be + // generalized. + BenchmarkMetadata& meta = table.metadata(); + meta.addKeyValuePair("smaller-table-num-rows", smallerTableNumRows); + meta.addKeyValuePair("smaller-table-sorted", smallerTableSorted); + meta.addKeyValuePair("bigger-table-sorted", biggerTableSorted); + } + } + } + + // Add the general metadata. + BenchmarkMetadata& meta{getGeneralMetadata()}; + meta.addKeyValuePair("value-changing-with-every-row", "ratio-rows"); + meta.addKeyValuePair( + "smaller-table-join-column-sample-size-ratio", + getConfigVariables().smallerTableJoinColumnSampleSizeRatio_); + meta.addKeyValuePair( + "bigger-table-join-column-sample-size-ratio", + getConfigVariables().biggerTableJoinColumnSampleSizeRatio_); + meta.addKeyValuePair("overlap-chance", getConfigVariables().overlapChance_); + GeneralInterfaceImplementation::addDefaultMetadata(&meta); + + return results; + } +}; + +// Create benchmark tables, where the smaller table grows and the ratio +// between tables stays the same. As does the amount of columns. +class BmOnlySmallerTableSizeChanges final + : public GeneralInterfaceImplementation { + public: + std::string name() const override { + return "Benchmarktables, where the smaller table grows and the ratio " + "between tables stays the same."; + } + + BenchmarkResults runAllBenchmarks() override { + BenchmarkResults results{}; + + // Making a benchmark table for all combination of IdTables being sorted. + for (const bool smallerTableSorted : {false, true}) { + for (const bool biggerTableSorted : {false, true}) { + // We also make multiple tables for different row ratios. + for (const float ratioRows : mergeSortedVectors( + {generateNaturalNumberSequenceInterval( + getConfigVariables().minRatioRows_, + std::ranges::min(getConfigVariables().maxRatioRows_, + 10.f)), + generateExponentInterval( + 10.f, getConfigVariables().minRatioRows_, + getConfigVariables().maxRatioRows_)})) { + const std::string tableName = absl::StrCat( + "The amount of rows in the smaller table grows and the ratio, to " + "the amount of rows in the bigger table, stays at ", + ratioRows, "."); + + // Returns the amount of rows in the smaller `IdTable`, used for the + // measurements in a given row. + auto growthFunction = createDefaultGrowthLambda( + 10UL, std::ranges::max( + static_cast( + static_cast( + getConfigVariables().minBiggerTableRows_) / + ratioRows), + getConfigVariables().minSmallerTableRows_)); + + ResultTable& table = makeGrowingBenchmarkTable( + &results, tableName, "Amount of rows in the smaller table", + alwaysFalse, getConfigVariables().overlapChance_, std::nullopt, + getConfigVariables().randomSeed(), smallerTableSorted, + biggerTableSorted, ratioRows, growthFunction, + getConfigVariables().smallerTableNumColumns_, + getConfigVariables().biggerTableNumColumns_, + getConfigVariables().smallerTableJoinColumnSampleSizeRatio_, + getConfigVariables().biggerTableJoinColumnSampleSizeRatio_); + + // Add the metadata, that changes with every call and can't be + // generalized. + BenchmarkMetadata& meta = table.metadata(); + meta.addKeyValuePair("smaller-table-sorted", smallerTableSorted); + meta.addKeyValuePair("bigger-table-sorted", biggerTableSorted); + meta.addKeyValuePair("ratio-rows", ratioRows); + } + } + } + + // Add the general metadata. + BenchmarkMetadata& meta{getGeneralMetadata()}; + meta.addKeyValuePair("value-changing-with-every-row", + "smaller-table-num-rows"); + meta.addKeyValuePair( + "smaller-table-join-column-sample-size-ratio", + getConfigVariables().smallerTableJoinColumnSampleSizeRatio_); + meta.addKeyValuePair( + "bigger-table-join-column-sample-size-ratio", + getConfigVariables().biggerTableJoinColumnSampleSizeRatio_); + meta.addKeyValuePair("overlap-chance", getConfigVariables().overlapChance_); + GeneralInterfaceImplementation::addDefaultMetadata(&meta); + return results; + } +}; + +// Create benchmark tables, where the tables are the same size and +// both just get more rows. +class BmSameSizeRowGrowth final : public GeneralInterfaceImplementation { + public: + std::string name() const override { + return "Benchmarktables, where the tables are the same size and both just " + "get more rows."; + } + + BenchmarkResults runAllBenchmarks() override { + BenchmarkResults results{}; + const std::string tableName = + "Both tables always have the same amount of rows and that amount " + "grows."; + + // Returns the amount of rows in the smaller `IdTable`, used for the + // measurements in a given row. + auto growthFunction = createDefaultGrowthLambda( + 10UL, getConfigVariables().minBiggerTableRows_); + + // Making a benchmark table for all combination of IdTables being sorted. + for (const bool smallerTableSorted : {false, true}) { + for (const bool biggerTableSorted : {false, true}) { + ResultTable& table = makeGrowingBenchmarkTable( + &results, tableName, "Amount of rows", alwaysFalse, + getConfigVariables().overlapChance_, std::nullopt, + getConfigVariables().randomSeed(), smallerTableSorted, + biggerTableSorted, 1.f, growthFunction, + getConfigVariables().smallerTableNumColumns_, + getConfigVariables().biggerTableNumColumns_, + getConfigVariables().smallerTableJoinColumnSampleSizeRatio_, + getConfigVariables().biggerTableJoinColumnSampleSizeRatio_); + + // Add the metadata, that changes with every call and can't be + // generalized. + BenchmarkMetadata& meta = table.metadata(); + meta.addKeyValuePair("smaller-table-sorted", smallerTableSorted); + meta.addKeyValuePair("bigger-table-sorted", biggerTableSorted); + } + } + + // Add the general metadata. + BenchmarkMetadata& meta{getGeneralMetadata()}; + meta.addKeyValuePair("value-changing-with-every-row", + "smaller-table-num-rows"); + meta.addKeyValuePair("ratio-rows", 1); + meta.addKeyValuePair( + "smaller-table-join-column-sample-size-ratio", + getConfigVariables().smallerTableJoinColumnSampleSizeRatio_); + meta.addKeyValuePair( + "bigger-table-join-column-sample-size-ratio", + getConfigVariables().biggerTableJoinColumnSampleSizeRatio_); + meta.addKeyValuePair("overlap-chance", getConfigVariables().overlapChance_); + GeneralInterfaceImplementation::addDefaultMetadata(&meta); + return results; + } +}; + +// Create benchmark tables, where the tables are the same size and +// only the number of possible elements in their join column change. +class BmSampleSizeRatio final : public GeneralInterfaceImplementation { + public: + std::string name() const override { + return "Benchmarktables, where only the sample size ratio changes."; + } + + BenchmarkResults runAllBenchmarks() override { + BenchmarkResults results{}; + const auto& ratios{getConfigVariables().benchmarkSampleSizeRatios_}; + const float maxSampleSizeRatio{std::ranges::max(ratios)}; + + /* + We work with the biggest possible smaller and bigger table. That should make + any difference in execution time easier to find. + Note: Strings are for the generation of error messages. + */ + const float ratioRows{getConfigVariables().minRatioRows_}; + constexpr std::string_view ratioRowsDescription{"'min-ratio-rows'"}; + const size_t smallerTableNumRows{ + static_cast(static_cast(approximateNumIdTableRows( + getConfigVariables().maxMemoryBiggerTable(), + getConfigVariables().biggerTableNumColumns_)) / + getConfigVariables().minRatioRows_)}; + std::string smallerTableNumRowsDescription{}; + std::string smallerTableNumRowsConfigurationOptions{}; + if (getConfigVariables().maxMemory().has_value()) { + smallerTableNumRowsDescription = + "division of the maximum number of rows, under the given " + "'max-memory' " + "and 'bigger-table-num-columns', with 'min-ratio-rows'"; + smallerTableNumRowsConfigurationOptions = + "'max-memory' and 'bigger-table-num-columns'"; + } else { + smallerTableNumRowsDescription = + "division of 'max-bigger-table-rows' with 'min-ratio-rows'"; + smallerTableNumRowsConfigurationOptions = "'max-bigger-table-rows'"; + } + + /* + Growth function. Simply walks through the sample size ratios, until it runs + out of them. Then it returns the biggest sample size ratio plus 1. + */ + const auto growthFunction = [&ratios, + &maxSampleSizeRatio](const size_t& rowIdx) { + if (rowIdx < ratios.size()) { + return ratios.at(rowIdx); + } else { + return maxSampleSizeRatio + 1.f; + } + }; + + // Stop, if we run out of sample size ratios. + const auto stopFunction = [&maxSampleSizeRatio]( + float, size_t, size_t, size_t, size_t, + float smallerTableJoinColumnSampleSizeRatio, + float biggerTableJoinColumnSampleSizeRatio) { + return !(smallerTableJoinColumnSampleSizeRatio <= maxSampleSizeRatio && + biggerTableJoinColumnSampleSizeRatio <= maxSampleSizeRatio); + }; + + /* + Calculate the expected number of rows in the result for the simplified + creation model of input tables join columns and overlaps, with the biggest + sample size ratio used for both input tables. The simplified creation model + assumes, that: + - The join column elements of the smaller and bigger table are not disjoint + at creation time. In reality, both join columns are created disjoint and any + overlaps are inserted later. + - The join column entries of the smaller table have a uniform distribution, + are made up out of the join column elements of both tables (smaller and + bigger) and the generation of one row entry is independent from the + generation of all other row entries. + - The join column entries of the bigger table have a uniform distribution, + are made up out of only the elements of the bigger tables and the generation + of one row entry is independent from the generation of all other row + entries. + - The generation of join column entries in the smaller table is independent + from the generation in the bigger table. + + Note: In reality, the set of possible join column entries for the smaller + table has size `|Number of rows in the smaller table| * sampleSizeRatio` + (rounded up) possible elements for entries. `|Number of rows in the bigger + table| * sampleSizeRatio` (rounded up) for the bigger table. + + In this simplified creation model the expected number of rows in the result + is: + (|Number of rows in the smaller table|*|Number of rows in the bigger table|) + / (|Number of rows in the smaller table|*sampleSizeRatio(rounded up)+|Number + of rows in the bigger table|*sampleSizeRatio(rounded up)) + */ + if (static_cast(smallerTableNumRows) > + getMaxValue() / static_cast(smallerTableNumRows)) { + throwOverflowError(absl::StrCat(smallerTableNumRowsDescription, + " ,multiplied with itself,")); + } else if (static_cast(smallerTableNumRows * smallerTableNumRows) > + getMaxValue() / static_cast(ratioRows)) { + throwOverflowError( + absl::StrCat(smallerTableNumRowsDescription, + " ,multiplied with itself, and then multiplied with ", + ratioRowsDescription)); + } else if (static_cast(smallerTableNumRows) > + getMaxValue() / maxSampleSizeRatio) { + throwOverflowError( + absl::StrCat(smallerTableNumRowsDescription, + " ,multiplied with the biggest entry in " + "'benchmark-sample-size-ratios'")); + } else if (static_cast(smallerTableNumRows) * + static_cast(ratioRows) > + getMaxValue() / maxSampleSizeRatio) { + throwOverflowError( + absl::StrCat(smallerTableNumRowsDescription, + " ,multiplied with the biggest entry in " + "'benchmark-sample-size-ratios' and ", + ratioRowsDescription)); + } else if (std::ceil(static_cast(smallerTableNumRows) * + maxSampleSizeRatio) > + getMaxValue() - + std::ceil(static_cast(smallerTableNumRows) * + static_cast(ratioRows) * + maxSampleSizeRatio)) { + throwOverflowError(absl::StrCat( + "addition of the ", smallerTableNumRowsDescription, + ",multiplied with the biggest entry in " + "'benchmark-sample-size-ratios', to the ", + smallerTableNumRowsDescription, ", multiplied with ", + ratioRowsDescription, + " and the biggest entry in 'benchmark-sample-size-ratios',")); + } else if (!isValuePreservingCast(std::floor( + static_cast(smallerTableNumRows) * + static_cast(smallerTableNumRows) * ratioRows / + (std::ceil(static_cast(smallerTableNumRows) * + maxSampleSizeRatio) + + std::ceil(static_cast(smallerTableNumRows) * + ratioRows * maxSampleSizeRatio))))) { + throw std::runtime_error(absl::StrCat( + "size_t casting error: The calculated wanted result size in '", + name(), + "' has to be castable to size_t. Try increasing the values for the " + "configuration options 'min-ratio-rows' or the biggest entry in " + "'benchmark-sample-size-ratios'. Or decreasing the value of ", + smallerTableNumRowsConfigurationOptions, ".")); + } + /* + If 'maxMemory' was set and our normal result is to big, we simply calculate + the number of rows, rounded down, that a result with the maximum memory size + would have. + */ + auto resultWantedNumRows{static_cast( + static_cast(smallerTableNumRows) * + static_cast(smallerTableNumRows) * ratioRows / + (std::ceil(static_cast(smallerTableNumRows) * + maxSampleSizeRatio) + + std::ceil(static_cast(smallerTableNumRows) * ratioRows * + maxSampleSizeRatio)))}; + const size_t resultNumColumns{getConfigVariables().smallerTableNumColumns_ + + getConfigVariables().biggerTableNumColumns_ - + 1}; + if (const auto& maxMemory{getConfigVariables().maxMemory()}; + maxMemory.has_value() && + maxMemory.value() < approximateMemoryNeededByIdTable( + resultWantedNumRows, resultNumColumns)) { + resultWantedNumRows = + approximateNumIdTableRows(maxMemory.value(), resultNumColumns); + } + + // Making a benchmark table for all combination of IdTables being sorted. + for (const bool smallerTableSorted : {false, true}) { + for (const bool biggerTableSorted : {false, true}) { + for (const float smallerTableSampleSizeRatio : ratios) { + const std::string tableName = absl::StrCat( + "Tables, where the sample size ratio of the smaller table is ", + smallerTableSampleSizeRatio, + " and the sample size ratio for the bigger table changes."); + ResultTable& table = makeGrowingBenchmarkTable( + &results, tableName, "Bigger table sample size ratio", + stopFunction, getConfigVariables().overlapChance_, + resultWantedNumRows, getConfigVariables().randomSeed(), + smallerTableSorted, biggerTableSorted, ratioRows, + smallerTableNumRows, getConfigVariables().smallerTableNumColumns_, + getConfigVariables().biggerTableNumColumns_, + smallerTableSampleSizeRatio, growthFunction); + + // Add the metadata, that changes with every call and can't be + // generalized. + BenchmarkMetadata& meta = table.metadata(); + meta.addKeyValuePair("smaller-table-sorted", smallerTableSorted); + meta.addKeyValuePair("bigger-table-sorted", biggerTableSorted); + meta.addKeyValuePair("smaller-table-join-column-sample-size-ratio", + smallerTableSampleSizeRatio); + } + } + } + + // Add the general metadata. + BenchmarkMetadata& meta{getGeneralMetadata()}; + meta.addKeyValuePair("value-changing-with-every-row", + "bigger-table-join-column-sample-size-ratio"); + meta.addKeyValuePair("ratio-rows", ratioRows); + meta.addKeyValuePair("smaller-table-num-rows", smallerTableNumRows); + meta.addKeyValuePair("wanted-result-table-size", resultWantedNumRows); + meta.addKeyValuePair("benchmark-sample-size-ratios", + getConfigVariables().benchmarkSampleSizeRatios_); + GeneralInterfaceImplementation::addDefaultMetadata(&meta); + return results; + } +}; + +// Benchmark tables, where the smaller table grows and the bigger table has a +// static number of rows. +class BmSmallerTableGrowsBiggerTableRemainsSameSize final + : public GeneralInterfaceImplementation { + public: + std::string name() const override { + return "Benchmarktables, where the smaller table grows and the size of the " + "bigger table remains the same."; + } + + BenchmarkResults runAllBenchmarks() override { + BenchmarkResults results{}; + // Making a benchmark table for all combination of IdTables being sorted and + // all possibles sizes for the bigger table. + for (const bool smallerTableSorted : {false, true}) { + for (const bool biggerTableSorted : {false, true}) { + for (const size_t biggerTableNumRows : generateExponentInterval( + 10UL, getConfigVariables().minBiggerTableRows_, + approximateNumIdTableRows( + getConfigVariables().maxMemoryBiggerTable(), + getConfigVariables().biggerTableNumColumns_))) { + /* + Calculate the wanted row ratios, transform them into the fitting + number of smaller table rows, and then create a growth function out + of that. The growth function works because, in this special case, the + table generation stops when the smaller table is bigger than the + bigger table. + */ + const float biggestRowRatio{static_cast( + static_cast(biggerTableNumRows) / + static_cast(getConfigVariables().minSmallerTableRows_))}; + std::vector smallerTableRows; + std::ranges::transform( + mergeSortedVectors( + {generateNaturalNumberSequenceInterval( + 1.f, std::ranges::min(10.f, biggestRowRatio)), + generateExponentInterval(10.f, 10.f, biggestRowRatio)}), + std::back_inserter(smallerTableRows), + [&biggerTableNumRows](const float ratio) { + return static_cast( + static_cast(biggerTableNumRows) / ratio); + }); + std::ranges::reverse(smallerTableRows); + const size_t lastSmallerTableRow{smallerTableRows.back()}; + auto growthFunction = createDefaultGrowthLambda( + 10UL, lastSmallerTableRow + 1UL, std::move(smallerTableRows)); + + // Build the table. + const std::string tableName = absl::StrCat( + "Table, where the smaller table grows and the bigger always has ", + biggerTableNumRows, " rows."); + ResultTable& table = + makeSmallerTableGrowsAndBiggerTableSameSizeBenchmarkTable( + &results, tableName, smallerTableSorted, biggerTableSorted, + growthFunction, biggerTableNumRows); + + // Add the metadata, that changes with every call and can't be + // generalized. + BenchmarkMetadata& meta = table.metadata(); + meta.addKeyValuePair("smaller-table-sorted", smallerTableSorted); + meta.addKeyValuePair("bigger-table-sorted", biggerTableSorted); + meta.addKeyValuePair("bigger-table-num-rows", biggerTableNumRows); + } + } + } + + // Add the general metadata. + BenchmarkMetadata& meta{getGeneralMetadata()}; + meta.addKeyValuePair("value-changing-with-every-row", + std::vector{"smaller-table-num-rows", "ratio-rows"}); + meta.addKeyValuePair( + "smaller-table-join-column-sample-size-ratio", + getConfigVariables().smallerTableJoinColumnSampleSizeRatio_); + meta.addKeyValuePair( + "bigger-table-join-column-sample-size-ratio", + getConfigVariables().biggerTableJoinColumnSampleSizeRatio_); + meta.addKeyValuePair("overlap-chance", getConfigVariables().overlapChance_); + GeneralInterfaceImplementation::addDefaultMetadata(&meta); + return results; + } + + private: + /* + @brief Create a benchmark table for join algorithm, with the given + parameters for the IdTables and the remaining IdTable parameters, that were + not given, taken directly from the configuration options, which will keep + getting more rows, until the `max-time-single-measurement` getter value, the + `maxMemoryBiggerTable()` getter value, or the `maxMemory()` getter value of + the configuration options was reached/surpassed.The columns will be: + - Number of rows in the smaller table. + - Time needed for sorting `IdTable`s. + - Time needed for merge/galloping join. + - Time needed for sorting and merge/galloping added together. + - Time needed for the hash join. + - How many rows the result of joining the tables has. + - How much faster the hash join is. For example: Two times faster. + + @param results The `BenchmarkResults`, in which you want to create a new + benchmark table. + @param tableDescriptor A identifier for the to be created benchmark table, so + that it can be easier identified later. + @param smallerTableSorted, biggerTableSorted Should the bigger/smaller table + be sorted by his join column before being joined? More specifically, some + join algorithm require one, or both, of the IdTables to be sorted. If this + argument is false, the time needed for sorting the required table will + added to the time of the join algorithm. + @param smallerTableNumRows How many rows, should the smaller table have in the + given benchmarking table row? + @param biggerTableNumRows Number of rows in the bigger table. + */ + ResultTable& makeSmallerTableGrowsAndBiggerTableSameSizeBenchmarkTable( + BenchmarkResults* results, const std::string& tableDescriptor, + const bool smallerTableSorted, const bool biggerTableSorted, + const growthFunction auto& smallerTableNumRows, + const size_t biggerTableNumRows) const { + // For creating a new random seed for every new row. + RandomSeedGenerator seedGenerator{getConfigVariables().randomSeed()}; + + ResultTable& table = initializeBenchmarkTable( + results, tableDescriptor, "Amount of rows in the smaller table"); + + /* + Stop function, so that the smaller table doesn't becomes bigger than the + bigger table. + */ + auto smallerTableIsSmallerThanBiggerTable = + [](const bool, const float ratioRows, const auto...) { + return ratioRows < 1.f; + }; + + /* + Adding measurements to the table, as long as possible. + */ + while (addNewRowToBenchmarkTable( + &table, smallerTableNumRows(table.numRows()), + smallerTableIsSmallerThanBiggerTable, + getConfigVariables().overlapChance_, std::nullopt, + std::invoke(seedGenerator), smallerTableSorted, biggerTableSorted, + static_cast( + static_cast(biggerTableNumRows) / + static_cast(smallerTableNumRows(table.numRows()))), + smallerTableNumRows(table.numRows()), + getConfigVariables().smallerTableNumColumns_, + getConfigVariables().biggerTableNumColumns_, + getConfigVariables().smallerTableJoinColumnSampleSizeRatio_, + getConfigVariables().biggerTableJoinColumnSampleSizeRatio_)) { + // Nothing to actually do here. + } + addPostMeasurementInformationsToBenchmarkTable(&table); + return table; + } +}; +// Registering the benchmarks +AD_REGISTER_BENCHMARK(BmSameSizeRowGrowth); +AD_REGISTER_BENCHMARK(BmOnlySmallerTableSizeChanges); +AD_REGISTER_BENCHMARK(BmOnlyBiggerTableSizeChanges); +AD_REGISTER_BENCHMARK(BmSampleSizeRatio); +AD_REGISTER_BENCHMARK(BmSmallerTableGrowsBiggerTableRemainsSameSize); +} // namespace ad_benchmark diff --git a/benchmark/Usage.md b/benchmark/Usage.md index 5e621b776c..29c09bcb4f 100644 --- a/benchmark/Usage.md +++ b/benchmark/Usage.md @@ -68,7 +68,7 @@ BenchmarkResults runAllBenchmarks(){ /* Create an empty table with a number of rows and columns. Doesn't measure anything. The number of columns can not be changed after creation, but the number of rows can. - Important: The row names aren't saved in a seperate container, but INSIDE the + Important: The row names aren't saved in a separate container, but INSIDE the first column of the table. */ auto& table = results.addTable(identifier, {"rowName1", "rowName2", "etc."}, diff --git a/benchmark/infrastructure/Benchmark.h b/benchmark/infrastructure/Benchmark.h index ebe32f3a19..ae5b93d410 100644 --- a/benchmark/infrastructure/Benchmark.h +++ b/benchmark/infrastructure/Benchmark.h @@ -98,7 +98,7 @@ class BenchmarkResults { } /* - * @brief Returns a vector of all the singe measurements. + * @brief Returns a vector of all the single measurements. */ std::vector getSingleMeasurements() const; @@ -185,7 +185,7 @@ class BenchmarkInterface { const ad_utility::ConfigManager& getConfigManager() const; /* - @brief Only used for manipulaton via the infrastructure. Is called directly + @brief Only used for manipulation via the infrastructure. Is called directly before `runAllBenchmarks`. Add/update the default metadata of the benchmark class. Currently @@ -205,7 +205,7 @@ class BenchmarkRegister { using BenchmarkPointer = std::unique_ptr; /* - Static vector of all registered benchmark classe instances. + Static vector of all registered benchmark class instances. */ inline static std::vector registeredBenchmarks{}; @@ -216,7 +216,7 @@ class BenchmarkRegister { * implemented the `BenchmarkInterface`. Shouldn't take up much space * and I couldn't find a better way of doing it. * - * @param benchmarkClasseInstance The memory managment of the passed + * @param benchmarkClasseInstance The memory management of the passed * instances will be taken over by `BenchmarkRegister`. */ explicit BenchmarkRegister(BenchmarkPointer&& benchmarkClasseInstance); @@ -230,9 +230,9 @@ class BenchmarkRegister { /* @brief For each registered benchmark: - Update the default class metadata. - - Run the measurments. + - Run the measurements. - @return Every benchmark class get's measured with their own + @return Every benchmark class gets measured with their own `BenchmarkResults`. They should be in the same order as the registrations. */ static std::vector runAllRegisteredBenchmarks(); @@ -247,7 +247,7 @@ class BenchmarkRegister { Macros for easier registering of benchmark classes. `declareRegisterVariable` and `declareRegisterVariableHidden` are needed for the implementation. Only `registerBenchmark` needs to be 'called', when one -want's to register a benchmark class. +wants to register a benchmark class. */ #define AD_DECLARE_REGISTER_VARIABLE_HIDDEN(line, benchmarkClass, ...) \ static BenchmarkRegister gRegisterVariable##benchmarkClass##line{ \ diff --git a/benchmark/infrastructure/BenchmarkMain.cpp b/benchmark/infrastructure/BenchmarkMain.cpp index 6c96503e62..b605ed7ac0 100644 --- a/benchmark/infrastructure/BenchmarkMain.cpp +++ b/benchmark/infrastructure/BenchmarkMain.cpp @@ -33,7 +33,7 @@ using namespace ad_benchmark; @brief Transform the given benchmark classes and corresponding results to json, and write them to the specified json file. -@param benchmarkClassAndResults The benchmark classes togehter with their +@param benchmarkClassAndResults The benchmark classes together with their results of running `runAllBenchmarks`. @param jsonFileName The name of the json file, where the json informationen should be written in. @@ -55,7 +55,7 @@ static void writeBenchmarkClassAndBenchmarkResultsToJsonFile( AD_CORRECTNESS_CHECK(benchmarkClassAndBenchmarkResultsAsJson.is_array()); /* - Add the old json arry entries to the new json array entries, if a non empty + Add the old json array entries to the new json array entries, if a non empty file exists. Otherwise, we create/fill the file. */ if (appendToJsonInFile && std::filesystem::exists(jsonFileName) && @@ -107,7 +107,7 @@ static __attribute__((noreturn)) void printConfigurationOptionsAndExit() { * and prints their measured time in a fitting format. */ int main(int argc, char** argv) { - // The filename, should the write option be choosen. + // The filename, should the write option be chosen. std::string writeFileName = ""; // The short hand, for the benchmark configuration. std::string shortHandConfigurationString = ""; @@ -126,7 +126,7 @@ int main(int argc, char** argv) { "Writes the benchmarks as json to a json file, overriding the previous" " content of the file.")( "append,a", - "Causes the json option to append to the end of the json arry in the " + "Causes the json option to append to the end of the json array in the " "json file, if there is one, instead of overriding the previous content " "of " "the file.")( @@ -158,7 +158,7 @@ int main(int argc, char** argv) { po::store(po::parse_command_line(argc, argv, options), vm); po::notify(vm); - // If write was choosen, then the given file must be a json file. + // If write was chosen, then the given file must be a json file. if (vm.count("write") && !writeFileName.ends_with(".json")) { std::cerr << "The file defined via `--write` must be a `.json` file.\n"; printUsageAndExit(); @@ -202,7 +202,7 @@ int main(int argc, char** argv) { Pairing the measured times up together with the the benchmark classes, that created them. Note: All the classes registered in `BenchmarkRegister` are always ran in the same order. So the benchmark class and benchmark - results are always at the same index position, and are grouped togehter + results are always at the same index position, and are grouped together correctly. */ const auto& benchmarkClassAndResults{ad_utility::zipVectors( diff --git a/benchmark/infrastructure/BenchmarkMeasurementContainer.cpp b/benchmark/infrastructure/BenchmarkMeasurementContainer.cpp index 5d784baa07..c7736e2e59 100644 --- a/benchmark/infrastructure/BenchmarkMeasurementContainer.cpp +++ b/benchmark/infrastructure/BenchmarkMeasurementContainer.cpp @@ -163,11 +163,11 @@ void ResultTable::setEntry(const size_t& row, const size_t& column, // ____________________________________________________________________________ ResultTable::operator std::string() const { - // Used for the formating of floats in the table. They will always be - // formated as having 4 values after the decimal point. + // Used for the formatting of floats in the table. They will always be + // formatted as having 4 values after the decimal point. static constexpr absl::string_view floatFormatSpecifier = "%.4f"; - // What should be printed between columns. Used for nicer formating. + // What should be printed between columns. Used for nicer formatting. const std::string columnSeperator = " | "; // Convert an `EntryType` of `ResultTable` to a screen friendly @@ -175,7 +175,7 @@ ResultTable::operator std::string() const { auto entryToStringVisitor = [](const T& entry) { /* `EntryType` has multiple distinct possible types, that all need different - handeling. Fortunaly, we can decide the handeling at compile time and + handling. Fortunately, we can decide the handling at compile time and throw the others away, using `if constexpr(std::is_same<...,...>::value)`. */ if constexpr (std::is_same_v) { @@ -276,11 +276,11 @@ ResultTable::operator std::string() const { ad_utility::addIndentation(stream.str(), " ")); } - // For formating: What is the maximum string width of a column, if you + // For formatting: What is the maximum string width of a column, if you // compare all it's entries? std::vector columnMaxStringWidth(numColumns(), 0); for (size_t column = 0; column < numColumns(); column++) { - // How long is the string representation of a colum entry in a wanted row? + // How long is the string representation of a column entry in a wanted row? auto stringWidthOfRow = std::views::transform( entries_, [&column, &entryToString](const std::vector& row) { return entryToString(row.at(column)).length(); @@ -317,7 +317,7 @@ ResultTable::operator std::string() const { // ____________________________________________________________________________ void ResultTable::addRow() { - // Create an emptry row of the same size as every other row. + // Create an empty row of the same size as every other row. entries_.emplace_back(numColumns()); } diff --git a/benchmark/infrastructure/BenchmarkMeasurementContainer.h b/benchmark/infrastructure/BenchmarkMeasurementContainer.h index bb4e40490d..6703bb3224 100644 --- a/benchmark/infrastructure/BenchmarkMeasurementContainer.h +++ b/benchmark/infrastructure/BenchmarkMeasurementContainer.h @@ -271,7 +271,7 @@ class ResultTable : public BenchmarkMetadataGetter { private: /* - @brief Sets the member variables for the constructure functions. + @brief Sets the member variables for the constructor functions. @param descriptor A string to identify this instance in json format later. @param descriptorForLog A string to identify this instance in the log. diff --git a/benchmark/infrastructure/BenchmarkMetadata.h b/benchmark/infrastructure/BenchmarkMetadata.h index 4fb6372e0e..ac7fce4750 100644 --- a/benchmark/infrastructure/BenchmarkMetadata.h +++ b/benchmark/infrastructure/BenchmarkMetadata.h @@ -13,7 +13,7 @@ namespace ad_benchmark { */ class BenchmarkMetadata { // No real reason, to really build everything ourselves, when the - // nlohmann::ordered_json object already containes everything, that we could + // nlohmann::ordered_json object already contains everything, that we could // need. nlohmann::ordered_json data_; diff --git a/benchmark/infrastructure/BenchmarkToJson.h b/benchmark/infrastructure/BenchmarkToJson.h index aa0fb79cd7..792ca8ca83 100644 --- a/benchmark/infrastructure/BenchmarkToJson.h +++ b/benchmark/infrastructure/BenchmarkToJson.h @@ -13,14 +13,14 @@ namespace ad_benchmark { /* - * @brief Create a nlohmann::ordered_json array with all relevant informations - * about the measurments taken by all the `BenchmarkResults`. + * @brief Create a nlohmann::ordered_json array with all relevant information + * about the measurements taken by all the `BenchmarkResults`. */ nlohmann::ordered_json benchmarkResultsToJson( const std::vector& results); /* -@brief Create a nlohmann::ordered_json array with all relevant informations +@brief Create a nlohmann::ordered_json array with all relevant information given by the pairs. */ nlohmann::ordered_json zipBenchmarkClassAndBenchmarkResultsToJson( diff --git a/benchmark/infrastructure/BenchmarkToString.cpp b/benchmark/infrastructure/BenchmarkToString.cpp index 4d323fb8a3..6f87024051 100644 --- a/benchmark/infrastructure/BenchmarkToString.cpp +++ b/benchmark/infrastructure/BenchmarkToString.cpp @@ -42,7 +42,7 @@ std::string getMetadataPrettyString(const BenchmarkMetadata& meta, } /* -@brief Return a string containing a titel version of `categoryName` and a string +@brief Return a string containing a title version of `categoryName` and a string list representation of all the given category entries. Note: This function converts `CategoryType` objects by trying to cast them as `std::string`. @@ -97,7 +97,7 @@ std::string benchmarkResultsToString( } }; - // Visualization for single measurments, if there are any. + // Visualization for single measurements, if there are any. addNonEmptyCategoryToStringSteam("Single measurement benchmarks", results.getSingleMeasurements()); diff --git a/benchmark/infrastructure/BenchmarkToString.h b/benchmark/infrastructure/BenchmarkToString.h index f3ea1fbfef..fe85b62c1a 100644 --- a/benchmark/infrastructure/BenchmarkToString.h +++ b/benchmark/infrastructure/BenchmarkToString.h @@ -36,7 +36,7 @@ std::string getMetadataPrettyString(const BenchmarkMetadata& meta, std::string_view suffix); /* - * @brief Returns a formated string containing all the benchmark information. + * @brief Returns a formatted string containing all the benchmark information. */ std::string benchmarkResultsToString( const BenchmarkInterface* const benchmarkClass, diff --git a/benchmark/util/ResultTableColumnOperations.h b/benchmark/util/ResultTableColumnOperations.h index 175812679d..bf0ea96f6d 100644 --- a/benchmark/util/ResultTableColumnOperations.h +++ b/benchmark/util/ResultTableColumnOperations.h @@ -69,12 +69,12 @@ requires(sizeof...(ColumnInputTypes) > 1) void sumUpColumns( } /* -@brief Reads two floating point columns, calculates the relativ speedup between +@brief Reads two floating point columns, calculates the relative speedup between their entries and writes it in a third column. @param columnToCalculateFor, columnToCompareAgainst The columns, with which the question "How much faster than the entries of `columnToCompareAgainst` -are the entires of `columnToCalculateFor`?". +are the entries of `columnToCalculateFor`?". @param columnToPlaceResultIn This is where the speedup calculation results will be placed in. */ diff --git a/docs/quickstart.md.DEPRECATED b/docs/quickstart.md.DEPRECATED index 70aad6e13f..789b5ae4f8 100644 --- a/docs/quickstart.md.DEPRECATED +++ b/docs/quickstart.md.DEPRECATED @@ -37,7 +37,7 @@ for known issues such as problems with Docker on Mac. Then open [http://localhost:7001/](http://localhost:7001/) in your browser. -For example, all female scientists occuring in the text corpus with the regex +For example, all female scientists occurring in the text corpus with the regex "algo.*" can be obtained with the following query SELECT ?x TEXT(?t) SCORE(?t) WHERE { diff --git a/docs/sparql_plus_text.md b/docs/sparql_plus_text.md index 303bc16d7a..b7384cd704 100644 --- a/docs/sparql_plus_text.md +++ b/docs/sparql_plus_text.md @@ -1,7 +1,7 @@ # SPARQL+Text support in QLever QLever allows the combination of SPARQL and full-text search. The text input -consists of text records, where passages of the text are annotated by entitites +consists of text records, where passages of the text are annotated by entities from the RDF data. The format of the required input files is described below. In SPARQL+Text queries you can then specify co-occurrence of words from the text with entities from the RDF data. This is a very powerful concept: it contains diff --git a/e2e/e2e.sh b/e2e/e2e.sh index 665fd9c8e7..15ce50f44c 100755 --- a/e2e/e2e.sh +++ b/e2e/e2e.sh @@ -129,6 +129,6 @@ if [ $i -ge 60 ]; then exit 1 fi -echo "ServerMain was succesfully started, running queries ..." +echo "ServerMain was successfully started, running queries ..." $PYTHON_BINARY "$PROJECT_DIR/e2e/queryit.py" "$PROJECT_DIR/e2e/scientists_queries.yaml" "http://localhost:9099" | tee "$BINARY_DIR/query_log.txt" || bail "Querying Server failed" popd diff --git a/e2e/scientists_queries.yaml b/e2e/scientists_queries.yaml index c8c4378f51..a945eeb574 100644 --- a/e2e/scientists_queries.yaml +++ b/e2e/scientists_queries.yaml @@ -1869,3 +1869,17 @@ queries: - contains_row: [ "", "Z-da_Rubinst-n", "Zelda_ubinstein" ] - contains_row: [ "", "Zhang_P-li", "Zhang_Peili"] - contains_row: [ "", "Zlata_Bartl", "Zlata_Batl"] + + - query: pattern-trick-empty-subquery + type: no-text + sparql: | + PREFIX foo: + SELECT ?p { + ?s foo:bar foo:Baz . + ?s ?p ?o + } + GROUP BY ?p + checks: + - num_cols: 1 + - selected: [ "?p" ] + - num_rows: 0 diff --git a/master.Makefile b/master.Makefile index f374d56f7d..d86950e313 100644 --- a/master.Makefile +++ b/master.Makefile @@ -8,7 +8,7 @@ SHELL = /bin/bash # This Makefile provides the following targets: # # pin: Pin queries to cache, so that all autocompletion queries are fast, even -# when "Clear cache" is clicked in the QLever UI (ther results for pinned +# when "Clear cache" is clicked in the QLever UI (the results for pinned # queries will never be removed, unless ... see target clear). # # clear: Clear the cache completely (including pinned results). Note that this @@ -17,7 +17,7 @@ SHELL = /bin/bash # clear-unpinned: Clear all unpinned results from the cache. This is exactly # what happens when clicking "Clear cache" in the QLever UI. # -# show-all-ac-queries: Show the AC queries for subject, predicat, object for +# show-all-ac-queries: Show the AC queries for subject, predicate, object for # copy&paste in the QLever UI backend settings. # This Makefile should be used as follows: @@ -57,7 +57,7 @@ CACHE_MAX_NUM_ENTRIES = 1000 # The URL of the QLever backend. QLEVER_API = https://qlever.cs.uni-freiburg.de/api/$(SLUG) -# The URL of the QLever UI istance ... TODO: it's confusing that this also has +# The URL of the QLever UI instance ... TODO: it's confusing that this also has # /api/ in the name, it actually has nothing to do with the URLs from the QLever # backends (which are defined in the Apache configuration of QLever). WARMUP_API = $(subst /api/,/api/warmup/,$(QLEVER_API)) @@ -112,7 +112,7 @@ show-config-default: CAT_TTL = cat $(DB).ttl index: - @if ls $(DB).index.* 1> /dev/null 2>&1; then echo -e "\033[31mIndex exists, delete it first with make remove_index, which would exeucte the following:\033[0m"; echo; make -sn remove_index; echo; else \ + @if ls $(DB).index.* 1> /dev/null 2>&1; then echo -e "\033[31mIndex exists, delete it first with make remove_index, which would execute the following:\033[0m"; echo; make -sn remove_index; echo; else \ time ( docker run -it --rm -v $(shell pwd):/index --entrypoint bash --name qlever.$(DB)-index $(DOCKER_IMAGE) -c "cd /index && $(CAT_TTL) | IndexBuilderMain -F ttl -f - -l -i $(DB) -K $(DB) $(TEXT_OPTIONS_INDEX) -s $(DB_BASE).settings.json | tee $(DB).index-log.txt"; rm -f $(DB)*tmp* ) \ fi diff --git a/misc/multiplicity-problem.txt b/misc/multiplicity-problem.txt index 26697a5d49..4473032524 100644 --- a/misc/multiplicity-problem.txt +++ b/misc/multiplicity-problem.txt @@ -38,7 +38,7 @@ this changes multiplicities from the join column is does not change in multiplicity, size and #distinct change equally: 2/2=1 the next column will also have the size lowered to 2, but the #distincts may or may not be lowered -in the last column, the size is lowered ot 2 and the #distincts HAS to be lowered, either to 2 or possibly even to 1 +in the last column, the size is lowered to 2 and the #distincts HAS to be lowered, either to 2 or possibly even to 1 what happen's in B: We keep every 500th row. diff --git a/misc/query_planning_and_text.txt b/misc/query_planning_and_text.txt index 39a03edd90..c4bb031534 100644 --- a/misc/query_planning_and_text.txt +++ b/misc/query_planning_and_text.txt @@ -4,7 +4,7 @@ IN-CONTEXT: The query planner creates a node for each triple and a scan for each node. This is not necessary for each in-context relation because several triples are worded in one operation. -The only pyhsical scan for a relation is the scan of the wordlists. +The only physical scan for a relation is the scan of the wordlists. Thus, only triples of the form in-context need a SCAN. Where WORDS can be literals, prefixes and also concrete entities. TODO: This will change when there is support for text without words. diff --git a/misc/reduce_ram_and_startup_time.txt b/misc/reduce_ram_and_startup_time.txt index 84c21dab7b..dc94b32936 100644 --- a/misc/reduce_ram_and_startup_time.txt +++ b/misc/reduce_ram_and_startup_time.txt @@ -1,21 +1,21 @@ 1. We can reduce RAM and startup time by not keeping all meta data in RAM. In general, but especially for OXX and also SXX permutation. Downside: -noticeable overhead for queries that are otherwise very fast (e.g. 1-5ms). We might end up with abotu as much overhead as well. +noticeable overhead for queries that are otherwise very fast (e.g. 1-5ms). We might end up with about as much overhead as well. higher overhead for joins with ?s ?p ?o triples, because there a larger number metadata objects many have to be read. HOWTO: The meta-data structure has to change: BlockMetaData has to be moved to its own area on disk to make RelationMetaData objects fixed-size. This should not have much downsides but requires significant rewriting effort. -From there, it should be rather striaghtforward and IndexMetaData->getRmd(...) -will now do the reading and construction of meta data objects too. Since we use them throughout hte query planning a LRU cache may be useful once again. +From there, it should be rather straightforward and IndexMetaData->getRmd(...) +will now do the reading and construction of meta data objects too. Since we use them throughout the query planning a LRU cache may be useful once again. IS THERE AN EASIER WAY TO SAVE RAM?: What happens if i just skip all literals in OXX permutations? --> not possible because I still want to do ?x ?p "Albert Einstein" -I could reduce usage of blocks even more, but there are already very few blocks in OXX permutations, the #obejct is simply so high. +I could reduce usage of blocks even more, but there are already very few blocks in OXX permutations, the #object is simply so high. --> not useful I could try to decrease the ID size diff --git a/src/engine/Bind.cpp b/src/engine/Bind.cpp index 4dac643245..3f7af15c71 100644 --- a/src/engine/Bind.cpp +++ b/src/engine/Bind.cpp @@ -81,10 +81,10 @@ std::vector Bind::getChildren() { } // _____________________________________________________________________________ -ResultTable Bind::computeResult() { +Result Bind::computeResult([[maybe_unused]] bool requestLaziness) { using std::endl; LOG(DEBUG) << "Get input to BIND operation..." << endl; - shared_ptr subRes = _subtree->getResult(); + std::shared_ptr subRes = _subtree->getResult(); LOG(DEBUG) << "Got input to Bind operation." << endl; IdTable idTable{getExecutionContext()->getAllocator()}; @@ -114,7 +114,7 @@ ResultTable Bind::computeResult() { template void Bind::computeExpressionBind( IdTable* outputIdTable, LocalVocab* outputLocalVocab, - const ResultTable& inputResultTable, + const Result& inputResultTable, sparqlExpression::SparqlExpression* expression) const { sparqlExpression::EvaluationContext evaluationContext( *getExecutionContext(), _subtree->getVariableColumns(), diff --git a/src/engine/Bind.h b/src/engine/Bind.h index 82ffc85688..f4a298c214 100644 --- a/src/engine/Bind.h +++ b/src/engine/Bind.h @@ -46,13 +46,13 @@ class Bind : public Operation { [[nodiscard]] vector resultSortedOn() const override; private: - ResultTable computeResult() override; + Result computeResult([[maybe_unused]] bool requestLaziness) override; // Implementation for the binding of arbitrary expressions. template void computeExpressionBind( IdTable* outputIdTable, LocalVocab* outputLocalVocab, - const ResultTable& inputResultTable, + const Result& inputResultTable, sparqlExpression::SparqlExpression* expression) const; [[nodiscard]] VariableToColumnMap computeVariableToColumnMap() const override; diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt index 069687ff26..8c628add78 100644 --- a/src/engine/CMakeLists.txt +++ b/src/engine/CMakeLists.txt @@ -2,7 +2,7 @@ add_subdirectory(sparqlExpressions) add_library(SortPerformanceEstimator SortPerformanceEstimator.cpp) qlever_target_link_libraries(SortPerformanceEstimator) add_library(engine - Engine.cpp QueryExecutionTree.cpp Operation.cpp ResultTable.cpp LocalVocab.cpp + Engine.cpp QueryExecutionTree.cpp Operation.cpp Result.cpp LocalVocab.cpp IndexScan.cpp Join.cpp Sort.cpp Distinct.cpp OrderBy.cpp Filter.cpp Server.cpp QueryPlanner.cpp QueryPlanningCostFactors.cpp diff --git a/src/engine/CartesianProductJoin.cpp b/src/engine/CartesianProductJoin.cpp index c1c631f5b7..02710ef86f 100644 --- a/src/engine/CartesianProductJoin.cpp +++ b/src/engine/CartesianProductJoin.cpp @@ -132,10 +132,11 @@ void CartesianProductJoin::writeResultColumn(std::span targetColumn, } } // ____________________________________________________________________________ -ResultTable CartesianProductJoin::computeResult() { +Result CartesianProductJoin::computeResult( + [[maybe_unused]] bool requestLaziness) { IdTable result{getExecutionContext()->getAllocator()}; result.setNumColumns(getResultWidth()); - std::vector> subResults; + std::vector> subResults; // We don't need to fully materialize the child results if we have a LIMIT // specified and an OFFSET of 0. @@ -154,7 +155,7 @@ ResultTable CartesianProductJoin::computeResult() { } subResults.push_back(child.getResult()); // Early stopping: If one of the results is empty, we can stop early. - if (subResults.back()->size() == 0) { + if (subResults.back()->idTable().size() == 0) { break; } // Example for the following calculation: If we have a LIMIT of 1000 and @@ -162,20 +163,29 @@ ResultTable CartesianProductJoin::computeResult() { // needs to evaluate only its first 10 results. The +1 is because integer // divisions are rounded down by default. if (limitIfPresent.has_value()) { - limitIfPresent.value()._limit = - limitIfPresent.value()._limit.value() / subResults.back()->size() + 1; + limitIfPresent.value()._limit = limitIfPresent.value()._limit.value() / + subResults.back()->idTable().size() + + 1; } } auto sizesView = std::views::transform( - subResults, [](const auto& child) { return child->size(); }); + subResults, [](const auto& child) { return child->idTable().size(); }); auto totalResultSize = std::accumulate(sizesView.begin(), sizesView.end(), 1UL, std::multiplies{}); size_t totalSizeIncludingLimit = getLimit().actualSize(totalResultSize); size_t offset = getLimit().actualOffset(totalResultSize); - result.resize(totalSizeIncludingLimit); + try { + result.resize(totalSizeIncludingLimit); + } catch ( + const ad_utility::detail::AllocationExceedsLimitException& exception) { + throw std::runtime_error{ + "The memory limit was exceeded during the computation of a " + "cross-product. Check if this cross-product is intentional or if you " + "have mistyped a variable name."}; + } if (totalSizeIncludingLimit != 0) { // A `groupSize` of N means that each row of the current result is copied N @@ -202,7 +212,7 @@ ResultTable CartesianProductJoin::computeResult() { auto subResultsDeref = std::views::transform( subResults, [](auto& x) -> decltype(auto) { return *x; }); return {std::move(result), resultSortedOn(), - ResultTable::getMergedLocalVocab(subResultsDeref)}; + Result::getMergedLocalVocab(subResultsDeref)}; } // ____________________________________________________________________________ diff --git a/src/engine/CartesianProductJoin.h b/src/engine/CartesianProductJoin.h index 3b94760c39..45338e1a6f 100644 --- a/src/engine/CartesianProductJoin.h +++ b/src/engine/CartesianProductJoin.h @@ -72,17 +72,17 @@ class CartesianProductJoin : public Operation { protected: // Don't promise any sorting of the result. // TODO Depending on the implementation we could propagate sorted - // columsn from either the first or the last input, but it is questionable if + // columns from either the first or the last input, but it is questionable if // there would be any real benefit from this and it would only increase the // complexity of the query planning and required testing. vector resultSortedOn() const override { return {}; } private: //! Compute the result of the query-subtree rooted at this element.. - ResultTable computeResult() override; + Result computeResult([[maybe_unused]] bool requestLaziness) override; // Copy each element from the `inputColumn` `groupSize` times to the - // `targetColumn`. Repeat until the `targetColumn` is copletely filled. Skip + // `targetColumn`. Repeat until the `targetColumn` is completely filled. Skip // the first `offset` write operations to the `targetColumn`. Call // `checkCancellation` after each write. If `StaticGroupSize != 0`, then the // group size is known at compile time which allows for more efficient loop diff --git a/src/engine/CountAvailablePredicates.cpp b/src/engine/CountAvailablePredicates.cpp index 026ff3e416..eaa4ffcbac 100644 --- a/src/engine/CountAvailablePredicates.cpp +++ b/src/engine/CountAvailablePredicates.cpp @@ -90,7 +90,7 @@ uint64_t CountAvailablePredicates::getSizeEstimateBeforeLimit() { size_t CountAvailablePredicates::getCostEstimate() { if (subtree_.get() != nullptr) { // Without knowing the ratio of elements that will have a pattern assuming - // constant cost per entry should be reasonable (altough non distinct + // constant cost per entry should be reasonable (although non distinct // entries are of course actually cheaper). return subtree_->getCostEstimate() + subtree_->getSizeEstimate(); } else { @@ -100,7 +100,8 @@ size_t CountAvailablePredicates::getCostEstimate() { } // _____________________________________________________________________________ -ResultTable CountAvailablePredicates::computeResult() { +Result CountAvailablePredicates::computeResult( + [[maybe_unused]] bool requestLaziness) { LOG(DEBUG) << "CountAvailablePredicates result computation..." << std::endl; IdTable idTable{getExecutionContext()->getAllocator()}; idTable.setNumColumns(2); @@ -137,7 +138,7 @@ ResultTable CountAvailablePredicates::computeResult() { patterns); return {std::move(idTable), resultSortedOn(), LocalVocab{}}; } else { - std::shared_ptr subresult = subtree_->getResult(); + std::shared_ptr subresult = subtree_->getResult(); LOG(DEBUG) << "CountAvailablePredicates subresult computation done." << std::endl; diff --git a/src/engine/CountAvailablePredicates.h b/src/engine/CountAvailablePredicates.h index 600458f950..4565e031eb 100644 --- a/src/engine/CountAvailablePredicates.h +++ b/src/engine/CountAvailablePredicates.h @@ -16,8 +16,8 @@ using std::string; using std::vector; -// This Operation takes a ResultTable with at least one column containing ids, -// and a column index referring to such a column. It then creates a ResultTable +// This Operation takes a Result with at least one column containing ids, +// and a column index referring to such a column. It then creates a Result // containing two columns, the first one filled with the ids of all predicates // for which there is an entry in the index with one of the entities in the // specified input column as its subject. The second output column contains a @@ -103,6 +103,6 @@ class CountAvailablePredicates : public Operation { void computePatternTrickAllEntities( IdTable* result, const CompactVectorOfStrings& patterns) const; - ResultTable computeResult() override; + Result computeResult([[maybe_unused]] bool requestLaziness) override; [[nodiscard]] VariableToColumnMap computeVariableToColumnMap() const override; }; diff --git a/src/engine/Distinct.cpp b/src/engine/Distinct.cpp index 8f3b1c0fb4..8393ef04f9 100644 --- a/src/engine/Distinct.cpp +++ b/src/engine/Distinct.cpp @@ -7,6 +7,7 @@ #include #include "engine/CallFixedSize.h" +#include "engine/Engine.h" #include "engine/QueryExecutionTree.h" using std::endl; @@ -37,10 +38,10 @@ VariableToColumnMap Distinct::computeVariableToColumnMap() const { } // _____________________________________________________________________________ -ResultTable Distinct::computeResult() { +Result Distinct::computeResult([[maybe_unused]] bool requestLaziness) { IdTable idTable{getExecutionContext()->getAllocator()}; LOG(DEBUG) << "Getting sub-result for distinct result computation..." << endl; - shared_ptr subRes = _subtree->getResult(); + std::shared_ptr subRes = _subtree->getResult(); LOG(DEBUG) << "Distinct result computation..." << endl; idTable.setNumColumns(subRes->idTable().numColumns()); diff --git a/src/engine/Distinct.h b/src/engine/Distinct.h index 068ebaaa96..620fea4f4b 100644 --- a/src/engine/Distinct.h +++ b/src/engine/Distinct.h @@ -55,7 +55,7 @@ class Distinct : public Operation { [[nodiscard]] string getCacheKeyImpl() const override; private: - virtual ResultTable computeResult() override; + virtual Result computeResult([[maybe_unused]] bool requestLaziness) override; VariableToColumnMap computeVariableToColumnMap() const override; }; diff --git a/src/engine/ExportQueryExecutionTrees.cpp b/src/engine/ExportQueryExecutionTrees.cpp index 178c4ee8df..532a97967d 100644 --- a/src/engine/ExportQueryExecutionTrees.cpp +++ b/src/engine/ExportQueryExecutionTrees.cpp @@ -17,8 +17,8 @@ namespace { // Return a range that contains the indices of the rows that have to be exported // from the `idTable` given the `LimitOffsetClause`. It takes into account the // LIMIT, the OFFSET, and the actual size of the `idTable` -auto getRowIndices(const LimitOffsetClause& limitOffset, - const IdTable& idTable) { +auto getRowIndices(const LimitOffsetClause& limitOffset, const Result& result) { + const IdTable& idTable = result.idTable(); return std::views::iota(limitOffset.actualOffset(idTable.size()), limitOffset.upperBound(idTable.size())); } @@ -29,9 +29,9 @@ cppcoro::generator ExportQueryExecutionTrees::constructQueryResultToTriples( const QueryExecutionTree& qet, const ad_utility::sparql_types::Triples& constructTriples, - LimitOffsetClause limitAndOffset, std::shared_ptr res, + LimitOffsetClause limitAndOffset, std::shared_ptr res, CancellationHandle cancellationHandle) { - for (size_t i : getRowIndices(limitAndOffset, res->idTable())) { + for (size_t i : getRowIndices(limitAndOffset, *res)) { ConstructQueryExportContext context{i, *res, qet.getVariableColumns(), qet.getQec()->getIndex()}; using enum PositionInTriple; @@ -56,13 +56,12 @@ ad_utility::streams::stream_generator ExportQueryExecutionTrees:: constructQueryResultToStream( const QueryExecutionTree& qet, const ad_utility::sparql_types::Triples& constructTriples, - LimitOffsetClause limitAndOffset, - std::shared_ptr resultTable, + LimitOffsetClause limitAndOffset, std::shared_ptr result, CancellationHandle cancellationHandle) { - resultTable->logResultSize(); - auto generator = ExportQueryExecutionTrees::constructQueryResultToTriples( - qet, constructTriples, limitAndOffset, resultTable, - std::move(cancellationHandle)); + result->logResultSize(); + auto generator = + constructQueryResultToTriples(qet, constructTriples, limitAndOffset, + result, std::move(cancellationHandle)); for (const auto& triple : generator) { co_yield triple.subject_; co_yield ' '; @@ -91,8 +90,7 @@ nlohmann::json ExportQueryExecutionTrees::constructQueryResultBindingsToQLeverJSON( const QueryExecutionTree& qet, const ad_utility::sparql_types::Triples& constructTriples, - const LimitOffsetClause& limitAndOffset, - std::shared_ptr res, + const LimitOffsetClause& limitAndOffset, std::shared_ptr res, CancellationHandle cancellationHandle) { auto generator = constructQueryResultToTriples(qet, constructTriples, limitAndOffset, std::move(res), @@ -110,13 +108,13 @@ ExportQueryExecutionTrees::constructQueryResultBindingsToQLeverJSON( nlohmann::json ExportQueryExecutionTrees::idTableToQLeverJSONArray( const QueryExecutionTree& qet, const LimitOffsetClause& limitAndOffset, const QueryExecutionTree::ColumnIndicesAndTypes& columns, - std::shared_ptr resultTable, + std::shared_ptr result, CancellationHandle cancellationHandle) { - AD_CORRECTNESS_CHECK(resultTable != nullptr); - const IdTable& data = resultTable->idTable(); + AD_CORRECTNESS_CHECK(result != nullptr); + const IdTable& data = result->idTable(); nlohmann::json json = nlohmann::json::array(); - for (size_t rowIndex : getRowIndices(limitAndOffset, data)) { + for (size_t rowIndex : getRowIndices(limitAndOffset, *result)) { // We need the explicit `array` constructor for the special case of zero // variables. json.push_back(nlohmann::json::array()); @@ -128,7 +126,7 @@ nlohmann::json ExportQueryExecutionTrees::idTableToQLeverJSONArray( } const auto& currentId = data(rowIndex, opt->columnIndex_); const auto& optionalStringAndXsdType = idToStringAndType( - qet.getQec()->getIndex(), currentId, resultTable->localVocab()); + qet.getQec()->getIndex(), currentId, result->localVocab()); if (!optionalStringAndXsdType.has_value()) { row.emplace_back(nullptr); continue; @@ -183,7 +181,25 @@ ExportQueryExecutionTrees::idToStringAndTypeForEncodedValue(Id id) { } } -// ___________________________________________________________________________ +// _____________________________________________________________________________ +ad_utility::triple_component::LiteralOrIri +ExportQueryExecutionTrees::getLiteralOrIriFromVocabIndex( + const Index& index, Id id, const LocalVocab& localVocab) { + using LiteralOrIri = ad_utility::triple_component::LiteralOrIri; + switch (id.getDatatype()) { + case Datatype::LocalVocabIndex: + return localVocab.getWord(id.getLocalVocabIndex()); + case Datatype::VocabIndex: { + auto entity = index.idToOptionalString(id.getVocabIndex()); + AD_CONTRACT_CHECK(entity.has_value()); + return LiteralOrIri::fromStringRepresentation(entity.value()); + } + default: + AD_FAIL(); + } +}; + +// _____________________________________________________________________________ template std::optional> @@ -197,6 +213,23 @@ ExportQueryExecutionTrees::idToStringAndType(const Index& index, Id id, return std::nullopt; } } + + using LiteralOrIri = ad_utility::triple_component::LiteralOrIri; + auto handleIriOrLiteral = [&escapeFunction](const LiteralOrIri& word) + -> std::optional> { + if constexpr (onlyReturnLiterals) { + if (!word.isLiteral()) { + return std::nullopt; + } + } + if constexpr (removeQuotesAndAngleBrackets) { + // TODO Can we get rid of the string copying here? + return std::pair{ + escapeFunction(std::string{asStringViewUnsafe(word.getContent())}), + nullptr}; + } + return std::pair{escapeFunction(word.toStringRepresentation()), nullptr}; + }; switch (id.getDatatype()) { case Datatype::WordVocabIndex: { std::optional entity = @@ -204,37 +237,10 @@ ExportQueryExecutionTrees::idToStringAndType(const Index& index, Id id, AD_CONTRACT_CHECK(entity.has_value()); return std::pair{escapeFunction(std::move(entity.value())), nullptr}; } - case VocabIndex: { - std::optional entity = - index.idToOptionalString(id.getVocabIndex()); - AD_CONTRACT_CHECK(entity.has_value()); - // TODO make this more efficient AND more correct - auto litOrIri = - ad_utility::triple_component::LiteralOrIri::fromStringRepresentation( - entity.value()); - if constexpr (onlyReturnLiterals) { - if (!litOrIri.isLiteral()) { - return std::nullopt; - } - } - if constexpr (removeQuotesAndAngleBrackets) { - entity = asStringViewUnsafe(litOrIri.getContent()); - } - // TODO handle the exporting of literals more correctly. - return std::pair{escapeFunction(std::move(entity.value())), nullptr}; - } - case LocalVocabIndex: { - std::string word = localVocab.getWord(id.getLocalVocabIndex()); - if constexpr (onlyReturnLiterals) { - if (!word.starts_with('"')) { - return std::nullopt; - } - } - if constexpr (removeQuotesAndAngleBrackets) { - word = RdfEscaping::normalizedContentFromLiteralOrIri(std::move(word)); - } - return std::pair{escapeFunction(std::move(word)), nullptr}; - } + case VocabIndex: + case LocalVocabIndex: + return handleIriOrLiteral( + getLiteralOrIriFromVocabIndex(index, id, localVocab)); case TextRecordIndex: return std::pair{ escapeFunction(index.getTextExcerpt(id.getTextRecordIndex())), @@ -269,11 +275,11 @@ nlohmann::json ExportQueryExecutionTrees::selectQueryResultToSparqlJSON( const QueryExecutionTree& qet, const parsedQuery::SelectClause& selectClause, const LimitOffsetClause& limitAndOffset, - shared_ptr resultTable, + std::shared_ptr result, CancellationHandle cancellationHandle) { using nlohmann::json; - AD_CORRECTNESS_CHECK(resultTable != nullptr); + AD_CORRECTNESS_CHECK(result != nullptr); LOG(DEBUG) << "Finished computing the query result in the ID space. " "Resolving strings in result...\n"; @@ -284,9 +290,9 @@ nlohmann::json ExportQueryExecutionTrees::selectQueryResultToSparqlJSON( std::erase(columns, std::nullopt); - const IdTable& idTable = resultTable->idTable(); + const IdTable& idTable = result->idTable(); - json result; + json resultJson; std::vector selectedVars = selectClause.getSelectedVariablesAsStrings(); // Strip the leading '?' from the variables, it is not part of the SPARQL JSON @@ -296,7 +302,7 @@ nlohmann::json ExportQueryExecutionTrees::selectQueryResultToSparqlJSON( var = var.substr(1); } } - result["head"]["vars"] = selectedVars; + resultJson["head"]["vars"] = selectedVars; json bindings = json::array(); @@ -305,8 +311,8 @@ nlohmann::json ExportQueryExecutionTrees::selectQueryResultToSparqlJSON( LOG(WARN) << "Exporting a SPARQL query where none of the selected " "variables is bound in the query" << std::endl; - result["results"]["bindings"] = json::array(); - return result; + resultJson["results"]["bindings"] = json::array(); + return resultJson; } // Take a string from the vocabulary, deduce the type and @@ -353,14 +359,14 @@ nlohmann::json ExportQueryExecutionTrees::selectQueryResultToSparqlJSON( return b; }; - for (size_t rowIndex : getRowIndices(limitAndOffset, idTable)) { + for (size_t rowIndex : getRowIndices(limitAndOffset, *result)) { // TODO: ordered_json` entries are ordered alphabetically, but insertion // order would be preferable. nlohmann::ordered_json binding; for (const auto& column : columns) { const auto& currentId = idTable(rowIndex, column->columnIndex_); const auto& optionalValue = idToStringAndType( - qet.getQec()->getIndex(), currentId, resultTable->localVocab()); + qet.getQec()->getIndex(), currentId, result->localVocab()); if (!optionalValue.has_value()) { continue; } @@ -380,8 +386,8 @@ nlohmann::json ExportQueryExecutionTrees::selectQueryResultToSparqlJSON( bindings.emplace_back(std::move(binding)); cancellationHandle->throwIfCancelled(); } - result["results"]["bindings"] = std::move(bindings); - return result; + resultJson["results"]["bindings"] = std::move(bindings); + return resultJson; } // _____________________________________________________________________________ @@ -389,16 +395,16 @@ nlohmann::json ExportQueryExecutionTrees::selectQueryResultBindingsToQLeverJSON( const QueryExecutionTree& qet, const parsedQuery::SelectClause& selectClause, const LimitOffsetClause& limitAndOffset, - shared_ptr resultTable, + std::shared_ptr result, CancellationHandle cancellationHandle) { - AD_CORRECTNESS_CHECK(resultTable != nullptr); + AD_CORRECTNESS_CHECK(result != nullptr); LOG(DEBUG) << "Resolving strings for finished binary result...\n"; QueryExecutionTree::ColumnIndicesAndTypes selectedColumnIndices = qet.selectedVariablesToColumnIndices(selectClause, true); - return ExportQueryExecutionTrees::idTableToQLeverJSONArray( - qet, limitAndOffset, selectedColumnIndices, std::move(resultTable), - std::move(cancellationHandle)); + return idTableToQLeverJSONArray(qet, limitAndOffset, selectedColumnIndices, + std::move(result), + std::move(cancellationHandle)); } using parsedQuery::SelectClause; @@ -419,17 +425,17 @@ ExportQueryExecutionTrees::selectQueryResultToStream( // This call triggers the possibly expensive computation of the query result // unless the result is already cached. - shared_ptr resultTable = qet.getResult(); - resultTable->logResultSize(); + std::shared_ptr result = qet.getResult(); + result->logResultSize(); LOG(DEBUG) << "Converting result IDs to their corresponding strings ..." << std::endl; auto selectedColumnIndices = qet.selectedVariablesToColumnIndices(selectClause, true); - const auto& idTable = resultTable->idTable(); + const auto& idTable = result->idTable(); // special case : binary export of IdTable if constexpr (format == MediaType::octetStream) { - for (size_t i : getRowIndices(limitAndOffset, idTable)) { + for (size_t i : getRowIndices(limitAndOffset, *result)) { for (const auto& columnIndex : selectedColumnIndices) { if (columnIndex.has_value()) { co_yield std::string_view{reinterpret_cast(&idTable( @@ -457,14 +463,14 @@ ExportQueryExecutionTrees::selectQueryResultToStream( constexpr auto& escapeFunction = format == MediaType::tsv ? RdfEscaping::escapeForTsv : RdfEscaping::escapeForCsv; - for (size_t i : getRowIndices(limitAndOffset, idTable)) { + for (size_t i : getRowIndices(limitAndOffset, *result)) { for (size_t j = 0; j < selectedColumnIndices.size(); ++j) { if (selectedColumnIndices[j].has_value()) { const auto& val = selectedColumnIndices[j].value(); Id id = idTable(i, val.columnIndex_); auto optionalStringAndType = idToStringAndType( - qet.getQec()->getIndex(), id, resultTable->localVocab(), + qet.getQec()->getIndex(), id, result->localVocab(), escapeFunction); if (optionalStringAndType.has_value()) [[likely]] { co_yield optionalStringAndType.value().first; @@ -564,7 +570,7 @@ ad_utility::streams::stream_generator ExportQueryExecutionTrees:: selectClause.getSelectedVariablesAsStrings(); // This call triggers the possibly expensive computation of the query result // unless the result is already cached. - shared_ptr resultTable = qet.getResult(); + std::shared_ptr result = qet.getResult(); // In the XML format, the variables don't include the question mark. auto varsWithoutQuestionMark = std::views::transform( @@ -576,19 +582,19 @@ ad_utility::streams::stream_generator ExportQueryExecutionTrees:: co_yield "\n"; - resultTable->logResultSize(); - const auto& idTable = resultTable->idTable(); + result->logResultSize(); + const auto& idTable = result->idTable(); auto selectedColumnIndices = qet.selectedVariablesToColumnIndices(selectClause, false); // TODO we could prefilter for the nonexisting variables. - for (size_t i : getRowIndices(limitAndOffset, idTable)) { + for (size_t i : getRowIndices(limitAndOffset, *result)) { co_yield "\n "; for (size_t j = 0; j < selectedColumnIndices.size(); ++j) { if (selectedColumnIndices[j].has_value()) { const auto& val = selectedColumnIndices[j].value(); Id id = idTable(i, val.columnIndex_); co_yield idToXMLBinding(val.variable_, id, qet.getQec()->getIndex(), - resultTable->localVocab()); + result->localVocab()); } } co_yield "\n "; @@ -606,8 +612,7 @@ ad_utility::streams::stream_generator ExportQueryExecutionTrees::constructQueryResultToStream( const QueryExecutionTree& qet, const ad_utility::sparql_types::Triples& constructTriples, - LimitOffsetClause limitAndOffset, - std::shared_ptr resultTable, + LimitOffsetClause limitAndOffset, std::shared_ptr result, CancellationHandle cancellationHandle) { static_assert(format == MediaType::octetStream || format == MediaType::csv || format == MediaType::tsv || format == MediaType::sparqlXml); @@ -616,14 +621,14 @@ ExportQueryExecutionTrees::constructQueryResultToStream( } else if constexpr (format == MediaType::sparqlXml) { AD_THROW("XML export is currently not supported for CONSTRUCT queries"); } - resultTable->logResultSize(); + result->logResultSize(); constexpr auto& escapeFunction = format == MediaType::tsv ? RdfEscaping::escapeForTsv : RdfEscaping::escapeForCsv; constexpr char sep = format == MediaType::tsv ? '\t' : ','; - auto generator = ExportQueryExecutionTrees::constructQueryResultToTriples( - qet, constructTriples, limitAndOffset, resultTable, - std::move(cancellationHandle)); + auto generator = + constructQueryResultToTriples(qet, constructTriples, limitAndOffset, + result, std::move(cancellationHandle)); for (auto& triple : generator) { co_yield escapeFunction(std::move(triple.subject_)); co_yield sep; @@ -637,13 +642,13 @@ ExportQueryExecutionTrees::constructQueryResultToStream( // _____________________________________________________________________________ nlohmann::json ExportQueryExecutionTrees::computeQueryResultAsQLeverJSON( const ParsedQuery& query, const QueryExecutionTree& qet, - const ad_utility::Timer& requestTimer, uint64_t maxSend, + const ad_utility::Timer& requestTimer, CancellationHandle cancellationHandle) { - shared_ptr resultTable = qet.getResult(); - resultTable->logResultSize(); + std::shared_ptr result = qet.getResult(); + result->logResultSize(); auto timeResultComputation = requestTimer.msecs(); - size_t resultSize = resultTable->size(); + size_t resultSize = result->idTable().size(); nlohmann::json j; @@ -662,22 +667,18 @@ nlohmann::json ExportQueryExecutionTrees::computeQueryResultAsQLeverJSON( RuntimeInformation runtimeInformation = qet.getRootOperation()->runtimeInfo(); runtimeInformation.addLimitOffsetRow( query._limitOffset, std::chrono::milliseconds::zero(), false); - runtimeInformation.addDetail("executed-implicitly-during-query-export", true); j["runtimeInformation"]["query_execution_tree"] = nlohmann::ordered_json(runtimeInformation); { - auto limitAndOffset = query._limitOffset; - limitAndOffset._limit = std::min(limitAndOffset.limitOrDefault(), maxSend); j["res"] = query.hasSelectClause() - ? ExportQueryExecutionTrees::selectQueryResultBindingsToQLeverJSON( - qet, query.selectClause(), limitAndOffset, - std::move(resultTable), std::move(cancellationHandle)) - : ExportQueryExecutionTrees:: - constructQueryResultBindingsToQLeverJSON( - qet, query.constructClause().triples_, limitAndOffset, - std::move(resultTable), std::move(cancellationHandle)); + ? selectQueryResultBindingsToQLeverJSON( + qet, query.selectClause(), query._limitOffset, + std::move(result), std::move(cancellationHandle)) + : constructQueryResultBindingsToQLeverJSON( + qet, query.constructClause().triples_, query._limitOffset, + std::move(result), std::move(cancellationHandle)); } j["resultsize"] = query.hasSelectClause() ? resultSize : j["res"].size(); j["time"]["total"] = std::to_string(requestTimer.msecs().count()) + "ms"; @@ -720,37 +721,32 @@ ExportQueryExecutionTrees::computeResultAsStream( // _____________________________________________________________________________ nlohmann::json ExportQueryExecutionTrees::computeSelectQueryResultAsSparqlJSON( - const ParsedQuery& query, const QueryExecutionTree& qet, uint64_t maxSend, + const ParsedQuery& query, const QueryExecutionTree& qet, CancellationHandle cancellationHandle) { if (!query.hasSelectClause()) { AD_THROW( "SPARQL-compliant JSON format is only supported for SELECT queries"); } - shared_ptr resultTable = qet.getResult(); - resultTable->logResultSize(); - nlohmann::json j; - auto limitAndOffset = query._limitOffset; - limitAndOffset._limit = std::min(limitAndOffset.limitOrDefault(), maxSend); - j = ExportQueryExecutionTrees::selectQueryResultToSparqlJSON( - qet, query.selectClause(), limitAndOffset, std::move(resultTable), - std::move(cancellationHandle)); - return j; + std::shared_ptr result = qet.getResult(); + result->logResultSize(); + return selectQueryResultToSparqlJSON(qet, query.selectClause(), + query._limitOffset, std::move(result), + std::move(cancellationHandle)); } // _____________________________________________________________________________ nlohmann::json ExportQueryExecutionTrees::computeResultAsJSON( const ParsedQuery& parsedQuery, const QueryExecutionTree& qet, - const ad_utility::Timer& requestTimer, uint64_t maxSend, - ad_utility::MediaType mediaType, CancellationHandle cancellationHandle) { + const ad_utility::Timer& requestTimer, ad_utility::MediaType mediaType, + CancellationHandle cancellationHandle) { try { switch (mediaType) { case ad_utility::MediaType::qleverJson: return computeQueryResultAsQLeverJSON(parsedQuery, qet, requestTimer, - maxSend, std::move(cancellationHandle)); case ad_utility::MediaType::sparqlJson: return computeSelectQueryResultAsSparqlJSON( - parsedQuery, qet, maxSend, std::move(cancellationHandle)); + parsedQuery, qet, std::move(cancellationHandle)); default: AD_FAIL(); } diff --git a/src/engine/ExportQueryExecutionTrees.h b/src/engine/ExportQueryExecutionTrees.h index acb4c6a328..4e8db28e0e 100644 --- a/src/engine/ExportQueryExecutionTrees.h +++ b/src/engine/ExportQueryExecutionTrees.h @@ -2,7 +2,7 @@ // Chair of Algorithms and Data Structures. // Author: Johannes Kalmbach -#include +#pragma once #include "engine/QueryExecutionTree.h" #include "parser/data/LimitOffsetClause.h" @@ -10,8 +10,6 @@ #include "util/http/MediaTypes.h" #include "util/json.h" -#pragma once - // This class contains all the functionality to convert a query that has already // been parsed (by the SPARQL parser) and planned (by the query planner) into // a serialized result. In particular, it creates TSV, CSV, Turtle, JSON (SPARQL @@ -51,12 +49,11 @@ class ExportQueryExecutionTrees { // single JSON object that is fully materialized before the function returns. // The `requestTimer` is used to report timing statistics on the query. It // must have already run during the query planning to produce the expected - // results. If `maxSend` is smaller than the size of the query result, then - // only the first `maxSend` rows are returned. + // results. static nlohmann::json computeResultAsJSON( const ParsedQuery& parsedQuery, const QueryExecutionTree& qet, - const ad_utility::Timer& requestTimer, uint64_t maxSend, - MediaType mediaType, CancellationHandle cancellationHandle); + const ad_utility::Timer& requestTimer, MediaType mediaType, + CancellationHandle cancellationHandle); // Convert the `id` to a human-readable string. The `index` is used to resolve // `Id`s with datatype `VocabIndex` or `TextRecordIndex`. The `localVocab` is @@ -89,6 +86,14 @@ class ExportQueryExecutionTrees { static std::optional> idToStringAndTypeForEncodedValue(Id id); + // Acts as a helper to retrieve an LiteralOrIri object + // from an Id, where the Id is of type `VocabIndex` or `LocalVocabIndex`. + // This function should only be called with suitable `Datatype` Id's, + // otherwise `AD_FAIL()` is called. + static ad_utility::triple_component::LiteralOrIri + getLiteralOrIriFromVocabIndex(const Index& index, Id id, + const LocalVocab& localVocab); + private: // TODO The following functions are all internally called by the // two public functions above. All the code has been inside QLever for a long @@ -99,11 +104,11 @@ class ExportQueryExecutionTrees { // Similar to `queryToJSON`, but always returns the `QLeverJSON` format. static nlohmann::json computeQueryResultAsQLeverJSON( const ParsedQuery& query, const QueryExecutionTree& qet, - const ad_utility::Timer& requestTimer, uint64_t maxSend, + const ad_utility::Timer& requestTimer, CancellationHandle cancellationHandle); // Similar to `queryToJSON`, but always returns the `SparqlJSON` format. static nlohmann::json computeSelectQueryResultAsSparqlJSON( - const ParsedQuery& query, const QueryExecutionTree& qet, uint64_t maxSend, + const ParsedQuery& query, const QueryExecutionTree& qet, CancellationHandle cancellationHandle); // ___________________________________________________________________________ @@ -111,7 +116,7 @@ class ExportQueryExecutionTrees { const QueryExecutionTree& qet, const parsedQuery::SelectClause& selectClause, const LimitOffsetClause& limitAndOffset, - shared_ptr resultTable, + std::shared_ptr resultTable, CancellationHandle cancellationHandle); /** @@ -120,7 +125,6 @@ class ExportQueryExecutionTrees { * `computeQueryResultAsQLeverJSON` to obtain the "actual" query results * (without the meta data) * @param qet The `QueryExecutionTree` of the query. - * @param from the first entries of the idTable are skipped * @param limitAndOffset at most entries are written, starting at * * @param columns each pair of tells @@ -132,7 +136,7 @@ class ExportQueryExecutionTrees { static nlohmann::json idTableToQLeverJSONArray( const QueryExecutionTree& qet, const LimitOffsetClause& limitAndOffset, const QueryExecutionTree::ColumnIndicesAndTypes& columns, - std::shared_ptr resultTable, + std::shared_ptr resultTable, CancellationHandle cancellationHandle); // ___________________________________________________________________________ @@ -140,15 +144,14 @@ class ExportQueryExecutionTrees { const QueryExecutionTree& qet, const ad_utility::sparql_types::Triples& constructTriples, const LimitOffsetClause& limitAndOffset, - std::shared_ptr res, - CancellationHandle cancellationHandle); + std::shared_ptr res, CancellationHandle cancellationHandle); // Generate an RDF graph for a CONSTRUCT query. static cppcoro::generator constructQueryResultToTriples( const QueryExecutionTree& qet, const ad_utility::sparql_types::Triples& constructTriples, - LimitOffsetClause limitAndOffset, std::shared_ptr res, + LimitOffsetClause limitAndOffset, std::shared_ptr res, CancellationHandle cancellationHandle); // ___________________________________________________________________________ @@ -156,7 +159,7 @@ class ExportQueryExecutionTrees { const QueryExecutionTree& qet, const parsedQuery::SelectClause& selectClause, const LimitOffsetClause& limitAndOffset, - shared_ptr resultTable, + std::shared_ptr resultTable, CancellationHandle cancellationHandle); // ___________________________________________________________________________ @@ -165,7 +168,7 @@ class ExportQueryExecutionTrees { const QueryExecutionTree& qet, const ad_utility::sparql_types::Triples& constructTriples, LimitOffsetClause limitAndOffset, - std::shared_ptr resultTable, + std::shared_ptr resultTable, CancellationHandle cancellationHandle); // _____________________________________________________________________________ diff --git a/src/engine/Filter.cpp b/src/engine/Filter.cpp index b6b96fc363..d69aef51c0 100644 --- a/src/engine/Filter.cpp +++ b/src/engine/Filter.cpp @@ -43,9 +43,9 @@ string Filter::getDescriptor() const { } // _____________________________________________________________________________ -ResultTable Filter::computeResult() { +Result Filter::computeResult([[maybe_unused]] bool requestLaziness) { LOG(DEBUG) << "Getting sub-result for Filter result computation..." << endl; - shared_ptr subRes = _subtree->getResult(); + std::shared_ptr subRes = _subtree->getResult(); LOG(DEBUG) << "Filter result computation..." << endl; checkCancellation(); @@ -63,7 +63,7 @@ ResultTable Filter::computeResult() { // _____________________________________________________________________________ template void Filter::computeFilterImpl(IdTable* outputIdTable, - const ResultTable& inputResultTable) { + const Result& inputResultTable) { sparqlExpression::EvaluationContext evaluationContext( *getExecutionContext(), _subtree->getVariableColumns(), inputResultTable.idTable(), getExecutionContext()->getAllocator(), diff --git a/src/engine/Filter.h b/src/engine/Filter.h index 621f29342f..1b1119491a 100644 --- a/src/engine/Filter.h +++ b/src/engine/Filter.h @@ -58,9 +58,9 @@ class Filter : public Operation { return _subtree->getVariableColumns(); } - ResultTable computeResult() override; + Result computeResult([[maybe_unused]] bool requestLaziness) override; template void computeFilterImpl(IdTable* outputIdTable, - const ResultTable& inputResultTable); + const Result& inputResultTable); }; diff --git a/src/engine/GroupBy.cpp b/src/engine/GroupBy.cpp index 4bd05f36f2..9b7ca63e2a 100644 --- a/src/engine/GroupBy.cpp +++ b/src/engine/GroupBy.cpp @@ -125,7 +125,7 @@ vector GroupBy::computeSortColumns( // ____________________________________________________________________ VariableToColumnMap GroupBy::computeVariableToColumnMap() const { VariableToColumnMap result; - // The returned columns are all groupByVariables followed by aggregrates. + // The returned columns are all groupByVariables followed by aggregates. const auto& subtreeVars = _subtree->getVariableColumns(); size_t colIndex = 0; for (const auto& var : _groupByVariables) { @@ -222,9 +222,9 @@ void GroupBy::processGroup( * @param blockEnd Where the group ends. * @param input The input Table. * @param result - * @param inTable The input ResultTable, which is required for its local + * @param inTable The input Result, which is required for its local * vocabulary - * @param outTable The output ResultTable, the vocabulary of which needs to be + * @param outTable The output Result, the vocabulary of which needs to be * expanded for GROUP_CONCAT aggregates * @param distinctHashSet An empty hash set. This is only passed in as an * argument to allow for efficient reusage of its @@ -309,7 +309,7 @@ void GroupBy::doGroupBy(const IdTable& dynInput, *dynResult = std::move(result).toDynamic(); } -ResultTable GroupBy::computeResult() { +Result GroupBy::computeResult([[maybe_unused]] bool requestLaziness) { LOG(DEBUG) << "GroupBy result computation..." << std::endl; IdTable idTable{getExecutionContext()->getAllocator()}; @@ -335,7 +335,7 @@ ResultTable GroupBy::computeResult() { auto hashMapOptimizationParams = checkIfHashMapOptimizationPossible(aggregates); - std::shared_ptr subresult; + std::shared_ptr subresult; if (hashMapOptimizationParams.has_value()) { const auto* child = _subtree->getRootOperation()->getChildren().at(0); // Skip sorting diff --git a/src/engine/GroupBy.h b/src/engine/GroupBy.h index e53478c253..6ec1886969 100644 --- a/src/engine/GroupBy.h +++ b/src/engine/GroupBy.h @@ -89,7 +89,7 @@ class GroupBy : public Operation { private: VariableToColumnMap computeVariableToColumnMap() const override; - ResultTable computeResult() override; + Result computeResult([[maybe_unused]] bool requestLaziness) override; template void processGroup(const Aggregate& expression, @@ -142,7 +142,7 @@ class GroupBy : public Operation { // } GROUP BY ?y // // NOTE: This is exactly what we need for a context-sensitive object AC query - // without connected triples. The GROUP BY variable can also be ommitted in + // without connected triples. The GROUP BY variable can also be omitted in // the SELECT clause. bool computeGroupByObjectWithCount(IdTable* result); diff --git a/src/engine/GroupByHashMapOptimization.h b/src/engine/GroupByHashMapOptimization.h index afc57a6f77..d0be51bf36 100644 --- a/src/engine/GroupByHashMapOptimization.h +++ b/src/engine/GroupByHashMapOptimization.h @@ -90,8 +90,7 @@ struct ExtremumAggregationData { auto valueIdResultGetter = [](ValueId id) { return id; }; auto stringResultGetter = [localVocab](const ad_utility::triple_component::LiteralOrIri& str) { - auto localVocabIndex = localVocab->getIndexAndAddIfNotContained( - str.toStringRepresentation()); + auto localVocabIndex = localVocab->getIndexAndAddIfNotContained(str); return ValueId::makeFromLocalVocabIndex(localVocabIndex); }; return std::visit(ad_utility::OverloadCallOperator(valueIdResultGetter, @@ -163,8 +162,11 @@ struct GroupConcatAggregationData { // _____________________________________________________________________________ [[nodiscard]] ValueId calculateResult(LocalVocab* localVocab) const { - auto localVocabIndex = - localVocab->getIndexAndAddIfNotContained(currentValue_); + using namespace ad_utility::triple_component; + using Lit = ad_utility::triple_component::Literal; + auto localVocabIndex = localVocab->getIndexAndAddIfNotContained( + LiteralOrIri{Lit::literalWithNormalizedContent( + asNormalizedStringViewUnsafe(currentValue_))}); return ValueId::makeFromLocalVocabIndex(localVocabIndex); } diff --git a/src/engine/HasPredicateScan.cpp b/src/engine/HasPredicateScan.cpp index 897c5e575d..9c863d939d 100644 --- a/src/engine/HasPredicateScan.cpp +++ b/src/engine/HasPredicateScan.cpp @@ -254,7 +254,7 @@ size_t HasPredicateScan::getCostEstimate() { } // ___________________________________________________________________________ -ResultTable HasPredicateScan::computeResult() { +Result HasPredicateScan::computeResult([[maybe_unused]] bool requestLaziness) { IdTable idTable{getExecutionContext()->getAllocator()}; idTable.setNumColumns(getResultWidth()); @@ -365,7 +365,7 @@ void HasPredicateScan::computeFullScan( // ___________________________________________________________________________ template -ResultTable HasPredicateScan::computeSubqueryS( +Result HasPredicateScan::computeSubqueryS( IdTable* dynResult, const CompactVectorOfStrings& patterns) { auto subresult = subtree().getResult(); auto patternCol = subtreeColIdx(); diff --git a/src/engine/HasPredicateScan.h b/src/engine/HasPredicateScan.h index 954579afa1..8022bca543 100644 --- a/src/engine/HasPredicateScan.h +++ b/src/engine/HasPredicateScan.h @@ -105,11 +105,11 @@ class HasPredicateScan : public Operation { size_t resultSize); template - ResultTable computeSubqueryS(IdTable* result, - const CompactVectorOfStrings& patterns); + Result computeSubqueryS(IdTable* result, + const CompactVectorOfStrings& patterns); private: - ResultTable computeResult() override; + Result computeResult([[maybe_unused]] bool requestLaziness) override; [[nodiscard]] VariableToColumnMap computeVariableToColumnMap() const override; }; diff --git a/src/engine/IndexScan.cpp b/src/engine/IndexScan.cpp index 15ecb9fa83..0aec6a3e6a 100644 --- a/src/engine/IndexScan.cpp +++ b/src/engine/IndexScan.cpp @@ -123,7 +123,7 @@ VariableToColumnMap IndexScan::computeVariableToColumnMap() const { return variableToColumnMap; } // _____________________________________________________________________________ -ResultTable IndexScan::computeResult() { +Result IndexScan::computeResult([[maybe_unused]] bool requestLaziness) { LOG(DEBUG) << "IndexScan result computation...\n"; IdTable idTable{getExecutionContext()->getAllocator()}; diff --git a/src/engine/IndexScan.h b/src/engine/IndexScan.h index 87f688de17..c8aa89bba9 100644 --- a/src/engine/IndexScan.h +++ b/src/engine/IndexScan.h @@ -104,7 +104,7 @@ class IndexScan : public Operation { std::array getPermutedTriple() const; private: - ResultTable computeResult() override; + Result computeResult([[maybe_unused]] bool requestLaziness) override; vector getChildren() override { return {}; } diff --git a/src/engine/Join.cpp b/src/engine/Join.cpp index cba6ab70fb..9cf9fdc52a 100644 --- a/src/engine/Join.cpp +++ b/src/engine/Join.cpp @@ -90,7 +90,7 @@ string Join::getCacheKeyImpl() const { string Join::getDescriptor() const { return "Join on " + _joinVar.name(); } // _____________________________________________________________________________ -ResultTable Join::computeResult() { +Result Join::computeResult([[maybe_unused]] bool requestLaziness) { LOG(DEBUG) << "Getting sub-results for join result computation..." << endl; size_t leftWidth = _left->getResultWidth(); size_t rightWidth = _right->getResultWidth(); @@ -122,8 +122,10 @@ ResultTable Join::computeResult() { // The third argument means "only get the result if it can be read from the // cache". So effectively, this returns the result if it is small, contains // UNDEF values, or is contained in the cache, otherwise `nullptr`. - return tree.getRootOperation()->getResult(false, - !(isSmall || containsUndef)); + // TODO Add a unit test that checks the correct conditions + return tree.getRootOperation()->getResult( + false, (isSmall || containsUndef) ? ComputationMode::FULLY_MATERIALIZED + : ComputationMode::ONLY_IF_CACHED); }; auto leftResIfCached = getCachedOrSmallResult(*_left, _leftJoinCol); @@ -153,10 +155,10 @@ ResultTable Join::computeResult() { } } - shared_ptr leftRes = + std::shared_ptr leftRes = leftResIfCached ? leftResIfCached : _left->getResult(); checkCancellation(); - if (leftRes->size() == 0) { + if (leftRes->idTable().size() == 0) { _right->getRootOperation()->updateRuntimeInformationWhenOptimizedOut(); // TODO When we add triples to the // index, the vocabularies of index scans will not necessarily be empty and @@ -181,7 +183,7 @@ ResultTable Join::computeResult() { leftRes->getSharedLocalVocab()}; } - shared_ptr rightRes = + std::shared_ptr rightRes = rightResIfCached ? rightResIfCached : _right->getResult(); checkCancellation(); join(leftRes->idTable(), _leftJoinCol, rightRes->idTable(), _rightJoinCol, @@ -191,7 +193,7 @@ ResultTable Join::computeResult() { // If only one of the two operands has a non-empty local vocabulary, share // with that one (otherwise, throws an exception). return {std::move(idTable), resultSortedOn(), - ResultTable::getMergedLocalVocab(*leftRes, *rightRes)}; + Result::getMergedLocalVocab(*leftRes, *rightRes)}; } // _____________________________________________________________________________ diff --git a/src/engine/Join.h b/src/engine/Join.h index bd662f1b64..13f8d5cf8c 100644 --- a/src/engine/Join.h +++ b/src/engine/Join.h @@ -81,7 +81,7 @@ class Join : public Operation { * @brief Joins IdTables a and b on join column jc2, returning * the result in dynRes. Creates a cross product for matching rows. * - * This should be a switch, which shoud decide which algorithm to use for + * This should be a switch, which should decide which algorithm to use for * joining two IdTables. * The possible algorithms should be: * - The normal merge join. @@ -100,8 +100,8 @@ class Join : public Operation { * the result in dynRes. Creates a cross product for matching rows by putting * the smaller IdTable in a hash map and using that, to faster find the * matching rows. - * Needed to be a seperate function from the actual implementation, because - * compiler optimization keept inlining it, which make testing impossible, + * Needed to be a separate function from the actual implementation, because + * compiler optimization kept inlining it, which make testing impossible, * because you couldn't call the function after linking and just got * 'undefined reference' errors. * @@ -115,7 +115,7 @@ class Join : public Operation { virtual string getCacheKeyImpl() const override; private: - ResultTable computeResult() override; + Result computeResult([[maybe_unused]] bool requestLaziness) override; VariableToColumnMap computeVariableToColumnMap() const override; diff --git a/src/engine/LocalVocab.cpp b/src/engine/LocalVocab.cpp index 52b4267ca9..3c87ff5bdc 100644 --- a/src/engine/LocalVocab.cpp +++ b/src/engine/LocalVocab.cpp @@ -31,12 +31,7 @@ LocalVocab LocalVocab::merge(std::span vocabs) { // _____________________________________________________________________________ template LocalVocabIndex LocalVocab::getIndexAndAddIfNotContainedImpl(WordT&& word) { - // TODO As soon as we store `IdOrString` in the local vocab, we - // should definitely use `insert` instead of `emplace` here for some - // transparency optimizations. We currently need `emplace` because of the - // explicit conversion from `string` to `AlignedString16`. - auto [wordIterator, isNewWord] = - primaryWordSet().emplace(std::forward(word)); + auto [wordIterator, isNewWord] = primaryWordSet().insert(AD_FWD(word)); // TODO Use std::to_address (more idiomatic, but currently breaks // the MacOS build. return &(*wordIterator); @@ -44,19 +39,19 @@ LocalVocabIndex LocalVocab::getIndexAndAddIfNotContainedImpl(WordT&& word) { // _____________________________________________________________________________ LocalVocabIndex LocalVocab::getIndexAndAddIfNotContained( - const std::string& word) { + const LiteralOrIri& word) { return getIndexAndAddIfNotContainedImpl(word); } // _____________________________________________________________________________ -LocalVocabIndex LocalVocab::getIndexAndAddIfNotContained(std::string&& word) { +LocalVocabIndex LocalVocab::getIndexAndAddIfNotContained(LiteralOrIri&& word) { return getIndexAndAddIfNotContainedImpl(std::move(word)); } // _____________________________________________________________________________ std::optional LocalVocab::getIndexOrNullopt( - const std::string& word) const { - auto localVocabIndex = primaryWordSet().find(StringAligned16{word}); + const LiteralOrIri& word) const { + auto localVocabIndex = primaryWordSet().find(word); if (localVocabIndex != primaryWordSet().end()) { // TODO Use std::to_address (more idiomatic, but currently breaks // the MacOS build. @@ -67,13 +62,15 @@ std::optional LocalVocab::getIndexOrNullopt( } // _____________________________________________________________________________ -const std::string& LocalVocab::getWord(LocalVocabIndex localVocabIndex) const { +const LocalVocab::LiteralOrIri& LocalVocab::getWord( + LocalVocabIndex localVocabIndex) const { return *localVocabIndex; } // _____________________________________________________________________________ -std::vector LocalVocab::getAllWordsForTesting() const { - std::vector result; +std::vector LocalVocab::getAllWordsForTesting() + const { + std::vector result; std::ranges::copy(primaryWordSet(), std::back_inserter(result)); for (const auto& previous : otherWordSets_) { std::ranges::copy(*previous, std::back_inserter(result)); diff --git a/src/engine/LocalVocab.h b/src/engine/LocalVocab.h index 16ed3827a1..b8d167def4 100644 --- a/src/engine/LocalVocab.h +++ b/src/engine/LocalVocab.h @@ -12,21 +12,20 @@ #include "absl/container/node_hash_set.h" #include "global/Id.h" +#include "parser/LiteralOrIri.h" -// A class for maintaing a local vocabulary with contiguous (local) IDs. This is -// meant for words that are not part of the normal vocabulary (constructed from -// the input data at indexing time). +// A class for maintaining a local vocabulary with contiguous (local) IDs. This +// is meant for words that are not part of the normal vocabulary (constructed +// from the input data at indexing time). // -// TODO: This is a first version of this class with basic functionality. Note -// that the local vocabulary used to be a simple `std::vector` -// defined inside of the `ResultTable` class. You gotta start somewhere. class LocalVocab { private: + using LiteralOrIri = ad_utility::triple_component::LiteralOrIri; // A map of the words in the local vocabulary to their local IDs. This is a // node hash map because we need the addresses of the words (which are of type - // `std::string`) to remain stable over their lifetime in the hash map because - // we hand out pointers to them. - using Set = absl::node_hash_set; + // `LiteralOrIri`) to remain stable over their lifetime in the hash map + // because we hand out pointers to them. + using Set = absl::node_hash_set; std::shared_ptr primaryWordSet_ = std::make_shared(); // Local vocabularies from child operations that were merged into this @@ -58,13 +57,13 @@ class LocalVocab { // Get the index of a word in the local vocabulary. If the word was already // contained, return the already existing index. If the word was not yet // contained, add it, and return the new index. - LocalVocabIndex getIndexAndAddIfNotContained(const std::string& word); - LocalVocabIndex getIndexAndAddIfNotContained(std::string&& word); + LocalVocabIndex getIndexAndAddIfNotContained(const LiteralOrIri& word); + LocalVocabIndex getIndexAndAddIfNotContained(LiteralOrIri&& word); // Get the index of a word in the local vocabulary, or std::nullopt if it is // not contained. This is useful for testing. std::optional getIndexOrNullopt( - const std::string& word) const; + const LiteralOrIri& word) const; // The number of words in the vocabulary. // Note: This is not constant time, but linear in the number of word sets. @@ -80,14 +79,14 @@ class LocalVocab { bool empty() const { return size() == 0; } // Return a const reference to the word. - const std::string& getWord(LocalVocabIndex localVocabIndex) const; + const LiteralOrIri& getWord(LocalVocabIndex localVocabIndex) const; // Create a local vocab that contains and keeps alive all the words from each // of the `vocabs`. The primary word set of the newly created vocab is empty. static LocalVocab merge(std::span vocabs); // Return all the words from all the word sets as a vector. - std::vector getAllWordsForTesting() const; + std::vector getAllWordsForTesting() const; private: // Common implementation for the two variants of diff --git a/src/engine/Minus.cpp b/src/engine/Minus.cpp index 8b5c12c9ad..f3a3fd301b 100644 --- a/src/engine/Minus.cpp +++ b/src/engine/Minus.cpp @@ -32,7 +32,7 @@ string Minus::getCacheKeyImpl() const { string Minus::getDescriptor() const { return "Minus"; } // _____________________________________________________________________________ -ResultTable Minus::computeResult() { +Result Minus::computeResult([[maybe_unused]] bool requestLaziness) { LOG(DEBUG) << "Minus result computation..." << endl; IdTable idTable{getExecutionContext()->getAllocator()}; @@ -43,8 +43,9 @@ ResultTable Minus::computeResult() { LOG(DEBUG) << "Minus subresult computation done" << std::endl; - LOG(DEBUG) << "Computing minus of results of size " << leftResult->size() - << " and " << rightResult->size() << endl; + LOG(DEBUG) << "Computing minus of results of size " + << leftResult->idTable().size() << " and " + << rightResult->idTable().size() << endl; int leftWidth = leftResult->idTable().numColumns(); int rightWidth = rightResult->idTable().numColumns(); @@ -56,7 +57,7 @@ ResultTable Minus::computeResult() { // If only one of the two operands has a non-empty local vocabulary, share // with that one (otherwise, throws an exception). return {std::move(idTable), resultSortedOn(), - ResultTable::getMergedLocalVocab(*leftResult, *rightResult)}; + Result::getMergedLocalVocab(*leftResult, *rightResult)}; } // _____________________________________________________________________________ @@ -98,7 +99,7 @@ void Minus::computeMinus( const IdTable& dynA, const IdTable& dynB, const std::vector>& joinColumns, IdTable* dynResult) const { - // Substract dynB from dynA. The result should be all result mappings mu + // Subtract dynB from dynA. The result should be all result mappings mu // for which all result mappings mu' in dynB are not compatible (one value // for a variable defined in both differs) or the domain of mu and mu' are // disjoint (mu' defines no solution for any variables for which mu defines a diff --git a/src/engine/Minus.h b/src/engine/Minus.h index 7052935659..115f4ccba4 100644 --- a/src/engine/Minus.h +++ b/src/engine/Minus.h @@ -72,7 +72,7 @@ class Minus : public Operation { const IdTableView& a, const IdTableView& b, size_t ia, size_t ib, const vector>& matchedColumns); - ResultTable computeResult() override; + Result computeResult([[maybe_unused]] bool requestLaziness) override; VariableToColumnMap computeVariableToColumnMap() const override; }; diff --git a/src/engine/MultiColumnJoin.cpp b/src/engine/MultiColumnJoin.cpp index 0d4de5c978..20e3d491ce 100644 --- a/src/engine/MultiColumnJoin.cpp +++ b/src/engine/MultiColumnJoin.cpp @@ -6,6 +6,7 @@ #include "engine/AddCombinedRowToTable.h" #include "engine/CallFixedSize.h" +#include "engine/Engine.h" #include "util/JoinAlgorithms/JoinAlgorithms.h" using std::endl; @@ -59,7 +60,7 @@ string MultiColumnJoin::getDescriptor() const { } // _____________________________________________________________________________ -ResultTable MultiColumnJoin::computeResult() { +Result MultiColumnJoin::computeResult([[maybe_unused]] bool requestLaziness) { LOG(DEBUG) << "MultiColumnJoin result computation..." << endl; IdTable idTable{getExecutionContext()->getAllocator()}; @@ -75,7 +76,8 @@ ResultTable MultiColumnJoin::computeResult() { LOG(DEBUG) << "MultiColumnJoin subresult computation done." << std::endl; LOG(DEBUG) << "Computing a multi column join between results of size " - << leftResult->size() << " and " << rightResult->size() << endl; + << leftResult->idTable().size() << " and " + << rightResult->idTable().size() << endl; computeMultiColumnJoin(leftResult->idTable(), rightResult->idTable(), _joinColumns, &idTable); @@ -86,7 +88,7 @@ ResultTable MultiColumnJoin::computeResult() { // If only one of the two operands has a non-empty local vocabulary, share // with that one (otherwise, throws an exception). return {std::move(idTable), resultSortedOn(), - ResultTable::getMergedLocalVocab(*leftResult, *rightResult)}; + Result::getMergedLocalVocab(*leftResult, *rightResult)}; } // _____________________________________________________________________________ diff --git a/src/engine/MultiColumnJoin.h b/src/engine/MultiColumnJoin.h index 5b951d858e..6ed454e0ba 100644 --- a/src/engine/MultiColumnJoin.h +++ b/src/engine/MultiColumnJoin.h @@ -63,7 +63,7 @@ class MultiColumnJoin : public Operation { IdTable* resultMightBeUnsorted); private: - ResultTable computeResult() override; + Result computeResult([[maybe_unused]] bool requestLaziness) override; VariableToColumnMap computeVariableToColumnMap() const override; diff --git a/src/engine/NeutralElementOperation.h b/src/engine/NeutralElementOperation.h index 8729d9ab71..f0b5cdb62e 100644 --- a/src/engine/NeutralElementOperation.h +++ b/src/engine/NeutralElementOperation.h @@ -40,7 +40,7 @@ class NeutralElementOperation : public Operation { }; private: - ResultTable computeResult() override { + Result computeResult([[maybe_unused]] bool requestLaziness) override { IdTable idTable{getExecutionContext()->getAllocator()}; idTable.setNumColumns(0); idTable.resize(1); diff --git a/src/engine/Operation.cpp b/src/engine/Operation.cpp index 3516371ee7..3fc3ed925d 100644 --- a/src/engine/Operation.cpp +++ b/src/engine/Operation.cpp @@ -70,12 +70,12 @@ void Operation::recursivelySetTimeConstraint( } // ________________________________________________________________________ -shared_ptr Operation::getResult(bool isRoot, - bool onlyReadFromCache) { +std::shared_ptr Operation::getResult( + bool isRoot, ComputationMode computationMode) { ad_utility::Timer timer{ad_utility::Timer::Started}; if (isRoot) { - // Reset runtime info, tests may re-use Operation objects. + // Reset runtime info, tests may reuse Operation objects. _runtimeInfo = std::make_shared(); // Start with an estimated runtime info which will be updated as we go. createRuntimeInfoFromEstimates(getRuntimeInfoPointer()); @@ -120,11 +120,12 @@ shared_ptr Operation::getResult(bool isRoot, updateRuntimeInformationOnFailure(timer.msecs()); } }); - auto computeLambda = [this, &timer] { + auto computeLambda = [this, &timer, computationMode] { checkCancellation(); runtimeInfo().status_ = RuntimeInformation::Status::inProgress; signalQueryUpdate(); - ResultTable result = computeResult(); + Result result = + computeResult(computationMode == ComputationMode::LAZY_IF_SUPPORTED); checkCancellation(); // Compute the datatypes that occur in each column of the result. @@ -145,7 +146,12 @@ shared_ptr Operation::getResult(bool isRoot, timer.msecs(), std::nullopt); // Apply LIMIT and OFFSET, but only if the call to `computeResult` did not // already perform it. An example for an operation that directly computes - // the Limit is a full index scan with three variables. + // the Limit is a full index scan with three variables. Note that the + // `QueryPlanner` does currently only set the limit for operations that + // support it natively, except for operations in subqueries. This means + // that a lot of the time the limit is only artificially applied during + // export, allowing the cache to reuse the same operation for different + // limits and offsets. if (!supportsLimit()) { ad_utility::timer::Timer limitTimer{ad_utility::timer::Timer::Started}; // Note: both of the following calls have no effect and negligible @@ -159,10 +165,12 @@ shared_ptr Operation::getResult(bool isRoot, return CacheValue{std::move(result), runtimeInfo()}; }; - auto result = (pinResult) ? cache.computeOncePinned(cacheKey, computeLambda, - onlyReadFromCache) - : cache.computeOnce(cacheKey, computeLambda, - onlyReadFromCache); + bool onlyReadFromCache = computationMode == ComputationMode::ONLY_IF_CACHED; + + auto result = pinResult ? cache.computeOncePinned(cacheKey, computeLambda, + onlyReadFromCache) + : cache.computeOnce(cacheKey, computeLambda, + onlyReadFromCache); if (result._resultPointer == nullptr) { AD_CORRECTNESS_CHECK(onlyReadFromCache); @@ -170,8 +178,9 @@ shared_ptr Operation::getResult(bool isRoot, } updateRuntimeInformationOnSuccess(result, timer.msecs()); - auto resultNumRows = result._resultPointer->resultTable()->size(); - auto resultNumCols = result._resultPointer->resultTable()->width(); + auto resultNumRows = result._resultPointer->resultTable()->idTable().size(); + auto resultNumCols = + result._resultPointer->resultTable()->idTable().numColumns(); LOG(DEBUG) << "Computed result of size " << resultNumRows << " x " << resultNumCols << std::endl; return result._resultPointer->resultTable(); @@ -207,7 +216,7 @@ shared_ptr Operation::getResult(bool isRoot, // Rethrow as QUERY_ABORTED allowing us to print the Operation // only at innermost failure of a recursive call throw ad_utility::AbortException( - "Unexpected expection that is not a subclass of std::exception"); + "Unexpected exception that is not a subclass of std::exception"); } } @@ -221,10 +230,10 @@ std::chrono::milliseconds Operation::remainingTime() const { // _______________________________________________________________________ void Operation::updateRuntimeInformationOnSuccess( - const ResultTable& resultTable, ad_utility::CacheStatus cacheStatus, + const Result& resultTable, ad_utility::CacheStatus cacheStatus, Milliseconds duration, std::optional runtimeInfo) { _runtimeInfo->totalTime_ = duration; - _runtimeInfo->numRows_ = resultTable.size(); + _runtimeInfo->numRows_ = resultTable.idTable().size(); _runtimeInfo->cacheStatus_ = cacheStatus; _runtimeInfo->status_ = RuntimeInformation::Status::fullyMaterialized; diff --git a/src/engine/Operation.h b/src/engine/Operation.h index c9c7d30627..ef43ee36af 100644 --- a/src/engine/Operation.h +++ b/src/engine/Operation.h @@ -10,7 +10,7 @@ #include #include "engine/QueryExecutionContext.h" -#include "engine/ResultTable.h" +#include "engine/Result.h" #include "engine/RuntimeInformation.h" #include "engine/VariableToColumnMap.h" #include "parser/data/LimitOffsetClause.h" @@ -21,6 +21,12 @@ // forward declaration needed to break dependencies class QueryExecutionTree; +enum class ComputationMode { + FULLY_MATERIALIZED, + ONLY_IF_CACHED, + LAZY_IF_SUPPORTED +}; + class Operation { using SharedCancellationHandle = ad_utility::SharedCancellationHandle; using Milliseconds = std::chrono::milliseconds; @@ -140,14 +146,17 @@ class Operation { * @param isRoot Has be set to `true` iff this is the root operation of a * complete query to obtain the expected behavior wrt cache pinning and * runtime information in error cases. - * @param onlyReadFromCache If set to true the result is only returned if it - * can be read from the cache without any computation. If the result is not in - * the cache, `nullptr` will be returned. + * @param computationMode If set to `CACHE_ONLY` the result is only returned + * if it can be read from the cache without any computation. If the result is + * not in the cache, `nullptr` will be returned. If set to `LAZY` this will + * request the result to be computable at request in chunks. If the operation + * does not support this, it will do nothing. * @return A shared pointer to the result. May only be `nullptr` if * `onlyReadFromCache` is true. */ - shared_ptr getResult(bool isRoot = false, - bool onlyReadFromCache = false); + std::shared_ptr getResult( + bool isRoot = false, + ComputationMode computationMode = ComputationMode::FULLY_MATERIALIZED); // Use the same cancellation handle for all children of an operation (= query // plan rooted at that operation). As soon as one child is aborted, the whole @@ -195,10 +204,13 @@ class Operation { // Direct access to the `computeResult()` method. This should be only used for // testing, otherwise the `getResult()` function should be used which also // sets the runtime info and uses the cache. - virtual ResultTable computeResultOnlyForTesting() final { - return computeResult(); + virtual Result computeResultOnlyForTesting( + bool requestLaziness = false) final { + return computeResult(requestLaziness); } + const auto& getLimit() const { return _limit; } + protected: // The QueryExecutionContext for this particular element. // No ownership. @@ -210,8 +222,6 @@ class Operation { */ [[nodiscard]] virtual vector resultSortedOn() const = 0; - const auto& getLimit() const { return _limit; } - /// interface to the generated warnings of this operation std::vector& getWarnings() { return _warnings; } [[nodiscard]] const std::vector& getWarnings() const { @@ -246,10 +256,10 @@ class Operation { private: //! Compute the result of the query-subtree rooted at this element.. - virtual ResultTable computeResult() = 0; + virtual Result computeResult(bool requestLaziness) = 0; // Create and store the complete runtime information for this operation after - // it has either been succesfully computed or read from the cache. + // it has either been successfully computed or read from the cache. virtual void updateRuntimeInformationOnSuccess( const ConcurrentLruCache::ResultAndCacheStatus& resultAndCacheStatus, Milliseconds duration) final; @@ -260,7 +270,7 @@ class Operation { // allowed when `cacheStatus` is `cachedPinned` or `cachedNotPinned`, // otherwise a runtime check will fail. virtual void updateRuntimeInformationOnSuccess( - const ResultTable& resultTable, ad_utility::CacheStatus cacheStatus, + const Result& resultTable, ad_utility::CacheStatus cacheStatus, Milliseconds duration, std::optional runtimeInfo) final; diff --git a/src/engine/OptionalJoin.cpp b/src/engine/OptionalJoin.cpp index 6ec87dc456..0f042681cc 100644 --- a/src/engine/OptionalJoin.cpp +++ b/src/engine/OptionalJoin.cpp @@ -7,6 +7,7 @@ #include "engine/AddCombinedRowToTable.h" #include "engine/CallFixedSize.h" +#include "engine/Engine.h" #include "util/JoinAlgorithms/JoinAlgorithms.h" using std::endl; @@ -88,7 +89,7 @@ string OptionalJoin::getDescriptor() const { } // _____________________________________________________________________________ -ResultTable OptionalJoin::computeResult() { +Result OptionalJoin::computeResult([[maybe_unused]] bool requestLaziness) { LOG(DEBUG) << "OptionalJoin result computation..." << endl; IdTable idTable{getExecutionContext()->getAllocator()}; @@ -104,7 +105,8 @@ ResultTable OptionalJoin::computeResult() { LOG(DEBUG) << "OptionalJoin subresult computation done." << std::endl; LOG(DEBUG) << "Computing optional join between results of size " - << leftResult->size() << " and " << rightResult->size() << endl; + << leftResult->idTable().size() << " and " + << rightResult->idTable().size() << endl; optionalJoin(leftResult->idTable(), rightResult->idTable(), _joinColumns, &idTable, implementation_); @@ -115,7 +117,7 @@ ResultTable OptionalJoin::computeResult() { // If only one of the two operands has a non-empty local vocabulary, share // with that one (otherwise, throws an exception). return {std::move(idTable), resultSortedOn(), - ResultTable::getMergedLocalVocab(*leftResult, *rightResult)}; + Result::getMergedLocalVocab(*leftResult, *rightResult)}; } // _____________________________________________________________________________ diff --git a/src/engine/OptionalJoin.h b/src/engine/OptionalJoin.h index ddc2ae1fd2..37f712409a 100644 --- a/src/engine/OptionalJoin.h +++ b/src/engine/OptionalJoin.h @@ -75,7 +75,7 @@ class OptionalJoin : public Operation { private: void computeSizeEstimateAndMultiplicities(); - ResultTable computeResult() override; + Result computeResult([[maybe_unused]] bool requestLaziness) override; VariableToColumnMap computeVariableToColumnMap() const override; diff --git a/src/engine/OrderBy.cpp b/src/engine/OrderBy.cpp index 172bdf08fa..da005cf352 100644 --- a/src/engine/OrderBy.cpp +++ b/src/engine/OrderBy.cpp @@ -8,6 +8,7 @@ #include #include "engine/CallFixedSize.h" +#include "engine/Engine.h" #include "engine/QueryExecutionTree.h" #include "global/RuntimeParameters.h" #include "global/ValueIdComparators.h" @@ -62,16 +63,16 @@ std::string OrderBy::getDescriptor() const { } // _____________________________________________________________________________ -ResultTable OrderBy::computeResult() { +Result OrderBy::computeResult([[maybe_unused]] bool requestLaziness) { using std::endl; LOG(DEBUG) << "Getting sub-result for OrderBy result computation..." << endl; - shared_ptr subRes = subtree_->getResult(); + std::shared_ptr subRes = subtree_->getResult(); // TODO proper timeout for sorting operations auto sortEstimateCancellationFactor = RuntimeParameters().get<"sort-estimate-cancellation-factor">(); if (getExecutionContext()->getSortPerformanceEstimator().estimatedSortTime( - subRes->size(), subRes->width()) > + subRes->idTable().size(), subRes->idTable().numColumns()) > remainingTime() * sortEstimateCancellationFactor) { // The estimated time for this sort is much larger than the actually // remaining time, cancel this operation diff --git a/src/engine/OrderBy.h b/src/engine/OrderBy.h index 2ccc62c432..69289ae75e 100644 --- a/src/engine/OrderBy.h +++ b/src/engine/OrderBy.h @@ -78,7 +78,7 @@ class OrderBy : public Operation { } private: - ResultTable computeResult() override; + Result computeResult([[maybe_unused]] bool requestLaziness) override; VariableToColumnMap computeVariableToColumnMap() const override { return subtree_->getVariableColumns(); diff --git a/src/engine/QueryExecutionContext.h b/src/engine/QueryExecutionContext.h index c264cc5d41..ba2bc24487 100644 --- a/src/engine/QueryExecutionContext.h +++ b/src/engine/QueryExecutionContext.h @@ -9,38 +9,28 @@ #include #include #include -#include -#include "engine/Engine.h" #include "engine/QueryPlanningCostFactors.h" -#include "engine/ResultTable.h" +#include "engine/Result.h" #include "engine/RuntimeInformation.h" #include "engine/SortPerformanceEstimator.h" -#include "global/Constants.h" #include "global/Id.h" #include "index/Index.h" #include "util/Cache.h" #include "util/ConcurrentCache.h" -#include "util/Log.h" #include "util/Synchronized.h" -#include "util/http/websocket/QueryId.h" - -using std::shared_ptr; -using std::string; -using std::vector; class CacheValue { private: - std::shared_ptr _resultTable; + std::shared_ptr _resultTable; RuntimeInformation _runtimeInfo; public: - explicit CacheValue(ResultTable resultTable, RuntimeInformation runtimeInfo) - : _resultTable( - std::make_shared(std::move(resultTable))), + explicit CacheValue(Result resultTable, RuntimeInformation runtimeInfo) + : _resultTable(std::make_shared(std::move(resultTable))), _runtimeInfo(std::move(runtimeInfo)) {} - const shared_ptr& resultTable() const { + const std::shared_ptr& resultTable() const { return _resultTable; } @@ -50,8 +40,9 @@ class CacheValue { struct SizeGetter { ad_utility::MemorySize operator()(const CacheValue& cacheValue) const { if (const auto& tablePtr = cacheValue._resultTable; tablePtr) { - return ad_utility::MemorySize::bytes(tablePtr->size() * - tablePtr->width() * sizeof(Id)); + return ad_utility::MemorySize::bytes(tablePtr->idTable().size() * + tablePtr->idTable().numColumns() * + sizeof(Id)); } else { return 0_B; } diff --git a/src/engine/QueryExecutionTree.cpp b/src/engine/QueryExecutionTree.cpp index beab5b742b..35aa938614 100644 --- a/src/engine/QueryExecutionTree.cpp +++ b/src/engine/QueryExecutionTree.cpp @@ -84,7 +84,7 @@ size_t QueryExecutionTree::getCostEstimate() { size_t QueryExecutionTree::getSizeEstimate() { if (!sizeEstimate_.has_value()) { if (cachedResult_) { - sizeEstimate_ = cachedResult_->size(); + sizeEstimate_ = cachedResult_->idTable().size(); } else { // if we are in a unit test setting and there is no QueryExecutionContest // specified it is the rootOperation_'s obligation to handle this case @@ -98,7 +98,7 @@ size_t QueryExecutionTree::getSizeEstimate() { // _____________________________________________________________________________ bool QueryExecutionTree::knownEmptyResult() { if (cachedResult_) { - return cachedResult_->size() == 0; + return cachedResult_->idTable().size() == 0; } return rootOperation_->knownEmptyResult(); } @@ -158,7 +158,8 @@ std::vector> QueryExecutionTree::getJoinColumns( } // ____________________________________________________________________________ -std::pair, shared_ptr> +std::pair, + std::shared_ptr> QueryExecutionTree::createSortedTrees( std::shared_ptr qetA, std::shared_ptr qetB, diff --git a/src/engine/QueryExecutionTree.h b/src/engine/QueryExecutionTree.h index 3dde14c1eb..7f7871f494 100644 --- a/src/engine/QueryExecutionTree.h +++ b/src/engine/QueryExecutionTree.h @@ -51,8 +51,10 @@ class QueryExecutionTree { size_t getResultWidth() const { return rootOperation_->getResultWidth(); } - std::shared_ptr getResult() const { - return rootOperation_->getResult(isRoot()); + std::shared_ptr getResult(bool requestLaziness = false) const { + return rootOperation_->getResult( + isRoot(), requestLaziness ? ComputationMode::LAZY_IF_SUPPORTED + : ComputationMode::FULLY_MATERIALIZED); } // A variable, its column index in the Id space result, and the `ResultType` @@ -192,7 +194,7 @@ class QueryExecutionTree { bool isRoot_ = false; // used to distinguish the root from child // operations/subtrees when pinning only the result. - std::shared_ptr cachedResult_ = nullptr; + std::shared_ptr cachedResult_ = nullptr; public: // Helper class to avoid bug in g++ that leads to memory corruption when diff --git a/src/engine/QueryPlanner.cpp b/src/engine/QueryPlanner.cpp index f42e98eb69..c13348cb2a 100644 --- a/src/engine/QueryPlanner.cpp +++ b/src/engine/QueryPlanner.cpp @@ -6,8 +6,9 @@ #include "engine/QueryPlanner.h" +#include + #include -#include #include "engine/Bind.h" #include "engine/CartesianProductJoin.h" @@ -894,7 +895,7 @@ QueryPlanner::SubtreePlan QueryPlanner::getTextLeafPlan( if (node.triple_.p_._iri == CONTAINS_ENTITY_PREDICATE) { if (node._variables.size() == 2) { // TODO: This is not nice, refactor the whole TripleGraph class - // to make these checks more explicity. + // to make these checks more explicitly. Variable evar = *(node._variables.begin()) == cvar ? *(++node._variables.begin()) : *(node._variables.begin()); @@ -1162,8 +1163,8 @@ void QueryPlanner::applyTextLimitsIfPossible( if (((plan._idsOfIncludedNodes & textLimit.idsOfMustBeFinishedOperations_) ^ textLimit.idsOfMustBeFinishedOperations_) != 0) { - // Ther is still an operation that needs to be finished before this text - // limit can be applied + // There is still an operation that needs to be finished before this + // text limit can be applied i++; continue; } @@ -1533,7 +1534,7 @@ bool QueryPlanner::TripleGraph::isSimilar( LOG(INFO) << asString() << std::endl; LOG(INFO) << other.asString() << std::endl; LOG(INFO) << "Two nodes in this graph were matches to the same node in " - "the other grap" + "the other graph" << std::endl; return false; } @@ -1643,6 +1644,13 @@ std::vector QueryPlanner::createJoinCandidates( return {makeSubtreePlan(_qec, a._qet, b._qet)}; } + // Check if one of the two Operations is a SERVICE. If so, we can try + // to simplify the Service Query using the result of the other operation. + if (auto opt = createJoinWithService(a, b, jcs)) { + candidates.push_back(std::move(opt.value())); + return candidates; + } + if (jcs.size() >= 2) { // If there are two or more join columns and we are not using the // TwoColumnJoin (the if part before this comment), use a multiColumnJoin. @@ -1771,6 +1779,35 @@ auto QueryPlanner::createJoinWithHasPredicateScan( return plan; } +// _____________________________________________________________________ +auto QueryPlanner::createJoinWithService( + SubtreePlan a, SubtreePlan b, + const std::vector>& jcs) + -> std::optional { + auto aRootOp = std::dynamic_pointer_cast(a._qet->getRootOperation()); + auto bRootOp = std::dynamic_pointer_cast(b._qet->getRootOperation()); + + // Exactly one of the two Operations can be a service. + if (static_cast(aRootOp) == static_cast(bRootOp)) { + return std::nullopt; + } + + auto service = aRootOp ? aRootOp : bRootOp; + auto sibling = bRootOp ? a : b; + + service->setSiblingTree(sibling._qet); + + const auto& qec = service->getExecutionContext(); + + SubtreePlan plan = + jcs.size() == 1 + ? makeSubtreePlan(qec, a._qet, b._qet, jcs[0][0], jcs[0][1]) + : makeSubtreePlan(qec, a._qet, b._qet); + mergeSubtreePlanIds(plan, a, b); + + return plan; +} + // _____________________________________________________________________ void QueryPlanner::QueryGraph::setupGraph( const std::vector& leafOperations) { diff --git a/src/engine/QueryPlanner.h b/src/engine/QueryPlanner.h index 1547bdfe81..101621f246 100644 --- a/src/engine/QueryPlanner.h +++ b/src/engine/QueryPlanner.h @@ -5,23 +5,20 @@ // 2018- Johannes Kalmbach (kalmbach@informatik.uni-freiburg.de) #pragma once -#include + #include -#include "absl/strings/str_join.h" -#include "absl/strings/str_split.h" #include "engine/CheckUsePatternTrick.h" -#include "engine/Filter.h" #include "engine/QueryExecutionTree.h" #include "parser/GraphPattern.h" #include "parser/ParsedQuery.h" -using std::vector; - class QueryPlanner { using TextLimitMap = ad_utility::HashMap; using CancellationHandle = ad_utility::SharedCancellationHandle; + template + using vector = std::vector; public: explicit QueryPlanner(QueryExecutionContext* qec, @@ -136,7 +133,7 @@ class QueryPlanner { std::move(operation))} {} std::shared_ptr _qet; - std::shared_ptr _cachedResult; + std::shared_ptr _cachedResult; uint64_t _idsOfIncludedNodes = 0; uint64_t _idsOfIncludedFilters = 0; uint64_t idsOfIncludedTextLimits_ = 0; @@ -147,7 +144,7 @@ class QueryPlanner { size_t getSizeEstimate() const; }; - // A helper class to find connected componenents of an RDF query using DFS. + // A helper class to find connected components of an RDF query using DFS. class QueryGraph { private: // A simple class to represent a graph node as well as some data for a DFS. @@ -332,6 +329,10 @@ class QueryPlanner { SubtreePlan a, SubtreePlan b, const std::vector>& jcs); + [[nodiscard]] static std::optional createJoinWithService( + SubtreePlan a, SubtreePlan b, + const std::vector>& jcs); + [[nodiscard]] vector getOrderByRow( const ParsedQuery& pq, const std::vector>& dpTab) const; diff --git a/src/engine/ResultTable.cpp b/src/engine/Result.cpp similarity index 63% rename from src/engine/ResultTable.cpp rename to src/engine/Result.cpp index 73edbaa506..ab80343d65 100644 --- a/src/engine/ResultTable.cpp +++ b/src/engine/Result.cpp @@ -4,13 +4,13 @@ // Johannes Kalmbach // Hannah Bast -#include "engine/ResultTable.h" +#include "engine/Result.h" #include "engine/LocalVocab.h" #include "util/Exception.h" // _____________________________________________________________________________ -string ResultTable::asDebugString() const { +string Result::asDebugString() const { std::ostringstream os; os << "First (up to) 5 rows of result with size:\n"; for (size_t i = 0; i < std::min(5, idTable().size()); ++i) { @@ -23,26 +23,23 @@ string ResultTable::asDebugString() const { } // _____________________________________________________________________________ -auto ResultTable::getMergedLocalVocab(const ResultTable& resultTable1, - const ResultTable& resultTable2) +auto Result::getMergedLocalVocab(const Result& result1, const Result& result2) -> SharedLocalVocabWrapper { return getMergedLocalVocab( - std::array{std::cref(resultTable1), std::cref(resultTable2)}); + std::array{std::cref(result1), std::cref(result2)}); } // _____________________________________________________________________________ -LocalVocab ResultTable::getCopyOfLocalVocab() const { - return localVocab().clone(); -} +LocalVocab Result::getCopyOfLocalVocab() const { return localVocab().clone(); } // _____________________________________________________________________________ -ResultTable::ResultTable(IdTable idTable, vector sortedBy, - SharedLocalVocabWrapper localVocab) - : _idTable{std::move(idTable)}, - _sortedBy{std::move(sortedBy)}, +Result::Result(IdTable idTable, std::vector sortedBy, + SharedLocalVocabWrapper localVocab) + : idTable_{std::move(idTable)}, + sortedBy_{std::move(sortedBy)}, localVocab_{std::move(localVocab.localVocab_)} { AD_CONTRACT_CHECK(localVocab_ != nullptr); - AD_CONTRACT_CHECK(std::ranges::all_of(_sortedBy, [this](size_t numCols) { + AD_CONTRACT_CHECK(std::ranges::all_of(sortedBy_, [this](size_t numCols) { return numCols < this->idTable().numColumns(); })); @@ -60,40 +57,40 @@ ResultTable::ResultTable(IdTable idTable, vector sortedBy, } // _____________________________________________________________________________ -ResultTable::ResultTable(IdTable idTable, vector sortedBy, - LocalVocab&& localVocab) - : ResultTable(std::move(idTable), std::move(sortedBy), - SharedLocalVocabWrapper{std::move(localVocab)}) {} +Result::Result(IdTable idTable, std::vector sortedBy, + LocalVocab&& localVocab) + : Result(std::move(idTable), std::move(sortedBy), + SharedLocalVocabWrapper{std::move(localVocab)}) {} // _____________________________________________________________________________ -void ResultTable::applyLimitOffset(const LimitOffsetClause& limitOffset) { +void Result::applyLimitOffset(const LimitOffsetClause& limitOffset) { // Apply the OFFSET clause. If the offset is `0` or the offset is larger // than the size of the `IdTable`, then this has no effect and runtime // `O(1)` (see the docs for `std::shift_left`). std::ranges::for_each( - _idTable.getColumns(), - [offset = limitOffset.actualOffset(_idTable.numRows()), + idTable_.getColumns(), + [offset = limitOffset.actualOffset(idTable_.numRows()), upperBound = - limitOffset.upperBound(_idTable.numRows())](std::span column) { + limitOffset.upperBound(idTable_.numRows())](std::span column) { std::shift_left(column.begin(), column.begin() + upperBound, offset); }); // Resize the `IdTable` if necessary. - size_t targetSize = limitOffset.actualSize(_idTable.numRows()); - AD_CORRECTNESS_CHECK(targetSize <= _idTable.numRows()); - _idTable.resize(targetSize); - _idTable.shrinkToFit(); + size_t targetSize = limitOffset.actualSize(idTable_.numRows()); + AD_CORRECTNESS_CHECK(targetSize <= idTable_.numRows()); + idTable_.resize(targetSize); + idTable_.shrinkToFit(); } // _____________________________________________________________________________ -auto ResultTable::getOrComputeDatatypeCountsPerColumn() +auto Result::getOrComputeDatatypeCountsPerColumn() -> const DatatypeCountsPerColumn& { if (datatypeCountsPerColumn_.has_value()) { return datatypeCountsPerColumn_.value(); } auto& types = datatypeCountsPerColumn_.emplace(); - types.resize(_idTable.numColumns()); - for (size_t i = 0; i < _idTable.numColumns(); ++i) { - const auto& col = _idTable.getColumn(i); + types.resize(idTable_.numColumns()); + for (size_t i = 0; i < idTable_.numColumns(); ++i) { + const auto& col = idTable_.getColumn(i); auto& datatypes = types.at(i); for (Id id : col) { ++datatypes[static_cast(id.getDatatype())]; @@ -103,7 +100,7 @@ auto ResultTable::getOrComputeDatatypeCountsPerColumn() } // _____________________________________________________________ -bool ResultTable::checkDefinedness(const VariableToColumnMap& varColMap) { +bool Result::checkDefinedness(const VariableToColumnMap& varColMap) { const auto& datatypesPerColumn = getOrComputeDatatypeCountsPerColumn(); return std::ranges::all_of(varColMap, [&](const auto& varAndCol) { const auto& [columnIndex, mightContainUndef] = varAndCol.second; @@ -113,3 +110,12 @@ bool ResultTable::checkDefinedness(const VariableToColumnMap& varColMap) { !hasUndefined; }); } + +// _____________________________________________________________________________ +const IdTable& Result::idTable() const { return idTable_; } + +// _____________________________________________________________________________ +void Result::logResultSize() const { + LOG(INFO) << "Result has size " << idTable().size() << " x " + << idTable().numColumns() << std::endl; +} diff --git a/src/engine/ResultTable.h b/src/engine/Result.h similarity index 75% rename from src/engine/ResultTable.h rename to src/engine/Result.h index 605f9c64a2..5e66a998eb 100644 --- a/src/engine/ResultTable.h +++ b/src/engine/Result.h @@ -14,25 +14,18 @@ #include "engine/idTable/IdTable.h" #include "global/Id.h" #include "parser/data/LimitOffsetClause.h" -#include "util/Log.h" - -using std::vector; // The result of an `Operation`. This is the class QLever uses for all // intermediate or final results when processing a SPARQL query. The actual data // is always a table and contained in the member `idTable()`. -// -// TODO: I would find it more appropriate to simply call this class `Result`. -// Otherwise, it's not clear from the names what the difference between a -// `ResultTable` and an `IdTable` is. -class ResultTable { +class Result { private: // The actual entries. - IdTable _idTable; + IdTable idTable_; // The column indices by which the result is sorted (primary sort key first). // Empty if the result is not sorted on any column. - std::vector _sortedBy; + std::vector sortedBy_; using LocalVocabPtr = std::shared_ptr; // The local vocabulary of the result. @@ -45,20 +38,19 @@ class ResultTable { // This class is used to enforce the invariant, that the `localVocab_` (which // is stored in a shared_ptr) is only shared between instances of the - // `ResultTable` class (where it is `const`). This gives a provable guarantee + // `Result` class (where it is `const`). This gives a provable guarantee // that the `localVocab_` is not mutated through some other code that still // owns a pointer to the same local vocab. class SharedLocalVocabWrapper { private: - // Only the `ResultTable` class is allowed to read or write the stored + // Only the `Result` class is allowed to read or write the stored // `shared_ptr`. Other code can obtain a `SharedLocalVocabWrapper` from a - // `ResultTable` and pass this wrapper into another `ResultTable`, but it + // `Result` and pass this wrapper into another `Result`, but it // can never access the `shared_ptr` directly. - std::shared_ptr localVocab_ = - std::make_shared(); + std::shared_ptr localVocab_; explicit SharedLocalVocabWrapper(LocalVocabPtr localVocab) : localVocab_{std::move(localVocab)} {} - friend class ResultTable; + friend class Result; public: // Create a wrapper from a `LocalVocab`. This is safe to call also from @@ -84,35 +76,29 @@ class ResultTable { // if expensive checks are enabled, for example by not defining the `NDEBUG` // macro. // The first overload of the constructor is for local vocabs that are shared - // with another `ResultTable` via the `getSharedLocalVocab...` methods below. + // with another `Result` via the `getSharedLocalVocab...` methods below. // The second overload is for newly created local vocabularies. - ResultTable(IdTable idTable, std::vector sortedBy, - SharedLocalVocabWrapper localVocab); - ResultTable(IdTable idTable, std::vector sortedBy, - LocalVocab&& localVocab); + Result(IdTable idTable, std::vector sortedBy, + SharedLocalVocabWrapper localVocab); + Result(IdTable idTable, std::vector sortedBy, + LocalVocab&& localVocab); // Prevent accidental copying of a result table. - ResultTable(const ResultTable& other) = delete; - ResultTable& operator=(const ResultTable& other) = delete; + Result(const Result& other) = delete; + Result& operator=(const Result& other) = delete; // Moving of a result table is OK. - ResultTable(ResultTable&& other) = default; - ResultTable& operator=(ResultTable&& other) = default; + Result(Result&& other) = default; + Result& operator=(Result&& other) = default; // Default destructor. - virtual ~ResultTable() = default; - - // Get the number of rows of this result. - size_t size() const { return _idTable.size(); } - - // Get the number of columns of this result. - size_t width() const { return _idTable.numColumns(); } + virtual ~Result() = default; // Const access to the underlying `IdTable`. - const IdTable& idTable() const { return _idTable; } + const IdTable& idTable() const; // Const access to the columns by which the `idTable()` is sorted. - const std::vector& sortedBy() const { return _sortedBy; } + const std::vector& sortedBy() const { return sortedBy_; } // Get the local vocabulary of this result, used for lookup only. // @@ -135,16 +121,15 @@ class ResultTable { // Like `getSharedLocalVocabFrom`, but takes more than one result and merges // all the corresponding local vocabs. - static SharedLocalVocabWrapper getMergedLocalVocab( - const ResultTable& resultTable1, const ResultTable& resultTable2); + static SharedLocalVocabWrapper getMergedLocalVocab(const Result& result1, + const Result& result2); - // Overload for more than two `ResultTables` + // Overload for more than two `Results` template - requires std::convertible_to, - const ResultTable&> + requires std::convertible_to, const Result&> static SharedLocalVocabWrapper getMergedLocalVocab(R&& subResults) { std::vector vocabs; - for (const ResultTable& table : subResults) { + for (const Result& table : subResults) { vocabs.push_back(std::to_address(table.localVocab_)); } return SharedLocalVocabWrapper{LocalVocab::merge(vocabs)}; @@ -159,9 +144,7 @@ class ResultTable { // `Server::processQuery`. Ideally, this should only be called in one // place, but for now, this method at least makes sure that these log // messages look all the same. - void logResultSize() const { - LOG(INFO) << "Result has size " << size() << " x " << width() << std::endl; - } + void logResultSize() const; // The first rows of the result and its total size (for debugging). string asDebugString() const; @@ -180,6 +163,6 @@ class ResultTable { // Check that if the `varColMap` guarantees that a column is always defined // (i.e. that is contains no single undefined value) that there are indeed no // undefined values in the `_idTable` of this result. Return `true` iff the - // check is succesful. + // check is successful. bool checkDefinedness(const VariableToColumnMap& varColMap); }; diff --git a/src/engine/ResultType.h b/src/engine/ResultType.h index c7770821f6..f2f292cd3e 100644 --- a/src/engine/ResultType.h +++ b/src/engine/ResultType.h @@ -6,11 +6,11 @@ namespace qlever { -// Enumerate the types of entries we can have in a `ResultTable`. +// Enumerate the types of entries we can have in a `Result`. // // NOTE: This was used in an old version of the QLever code, but no longer is // (because reality is more complicated than "one type per column"). The class -// is still needed for the correctness of the code, see `ResultTable.h`. +// is still needed for the correctness of the code, see `Result.h`. // // TODO: Properly keep track of result types again. In particular, efficiency // should benefit in the common use case where all entries in a column have a diff --git a/src/engine/RuntimeInformation.cpp b/src/engine/RuntimeInformation.cpp index 840e25faed..f4d2e898ae 100644 --- a/src/engine/RuntimeInformation.cpp +++ b/src/engine/RuntimeInformation.cpp @@ -236,6 +236,7 @@ void RuntimeInformation::addLimitOffsetRow(const LimitOffsetClause& l, totalTime_ += timeForLimit; actualOperation->addDetail("not-written-to-cache-because-child-of-limit", fullResultIsNotCached); + addDetail("executed-implicitly-during-query-export", !fullResultIsNotCached); sizeEstimate_ = l.actualSize(sizeEstimate_); // Update the descriptor. diff --git a/src/engine/Server.cpp b/src/engine/Server.cpp index d0940213eb..6b872a6255 100644 --- a/src/engine/Server.cpp +++ b/src/engine/Server.cpp @@ -330,7 +330,7 @@ Awaitable Server::process( response = createJsonResponse(json, request); } - // Ping with or without messsage. + // Ping with or without message. if (urlPathAndParameters._path == "/ping") { if (auto msg = checkParameter("msg", std::nullopt)) { LOG(INFO) << "Alive check with message \"" << msg.value() << "\"" @@ -568,7 +568,7 @@ Awaitable Server::sendStreamableResponse( // propagate it, and log it directly, so the code doesn't try to send // an HTTP response containing the error message onto a HTTP stream // that is already partially written. The only way to pass metadata - // after the beginning is by using the trailer mechanism as decribed + // after the beginning is by using the trailer mechanism as described // here: // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Trailer#chunked_transfer_encoding_using_a_trailing_header // This won't be treated as an error by any regular HTTP client, so @@ -616,8 +616,6 @@ boost::asio::awaitable Server::processQuery( const std::string& expected) { return params.contains(param) && params.at(param) == expected; }; - size_t maxSend = params.contains("send") ? std::stoul(params.at("send")) - : MAX_NOF_ROWS_IN_RESULT; const bool pinSubtrees = containsParam("pinsubtrees", "true"); const bool pinResult = containsParam("pinresult", "true"); LOG(INFO) << "Processing the following SPARQL query:" @@ -654,6 +652,15 @@ boost::asio::awaitable Server::processQuery( mediaType = ad_utility::getMediaTypeFromAcceptHeader(acceptHeader); } + std::optional maxSend = + params.contains("send") ? std::optional{std::stoul(params.at("send"))} + : std::nullopt; + // Limit JSON requests by default + if (!maxSend.has_value() && (mediaType == MediaType::sparqlJson || + mediaType == MediaType::qleverJson)) { + maxSend = MAX_NOF_ROWS_IN_RESULT; + } + if (!mediaType.has_value()) { co_return co_await send(createBadRequestResponse( absl::StrCat("Did not find any supported media type " @@ -696,6 +703,21 @@ boost::asio::awaitable Server::processQuery( << " ms" << std::endl; LOG(TRACE) << qet.getCacheKey() << std::endl; + // Apply stricter limit for export if present + if (maxSend.has_value()) { + auto& pq = plannedQuery.value().parsedQuery_; + pq._limitOffset._limit = + std::min(maxSend.value(), pq._limitOffset.limitOrDefault()); + } + // Make sure we don't underflow here + AD_CORRECTNESS_CHECK( + plannedQuery.value().parsedQuery_._limitOffset._offset >= + qet.getRootOperation()->getLimit()._offset); + // Don't apply offset twice, if the offset was not applied to the operation + // then the exporter can safely apply it during export. + plannedQuery.value().parsedQuery_._limitOffset._offset -= + qet.getRootOperation()->getLimit()._offset; + // This actually processes the query and sends the result in the requested // format. switch (mediaType.value()) { @@ -713,10 +735,10 @@ boost::asio::awaitable Server::processQuery( case sparqlJson: { // Normal case: JSON response auto responseString = co_await computeInNewThread( - [&plannedQuery, &qet, &requestTimer, maxSend, mediaType, + [&plannedQuery, &qet, &requestTimer, mediaType, &cancellationHandle] { return ExportQueryExecutionTrees::computeResultAsJSON( - plannedQuery.value().parsedQuery_, qet, requestTimer, maxSend, + plannedQuery.value().parsedQuery_, qet, requestTimer, mediaType.value(), cancellationHandle); }, cancellationHandle); diff --git a/src/engine/Service.cpp b/src/engine/Service.cpp index ea2fea0402..c4252a9a8f 100644 --- a/src/engine/Service.cpp +++ b/src/engine/Service.cpp @@ -5,11 +5,14 @@ #include "engine/Service.h" #include +#include #include #include "engine/CallFixedSize.h" +#include "engine/ExportQueryExecutionTrees.h" #include "engine/Values.h" #include "engine/VariableToColumnMap.h" +#include "global/RuntimeParameters.h" #include "parser/TokenizerCtre.h" #include "parser/TurtleParser.h" #include "util/Exception.h" @@ -21,10 +24,12 @@ // ____________________________________________________________________________ Service::Service(QueryExecutionContext* qec, parsedQuery::Service parsedServiceClause, - GetTsvFunction getTsvFunction) + GetTsvFunction getTsvFunction, + std::shared_ptr siblingTree) : Operation{qec}, parsedServiceClause_{std::move(parsedServiceClause)}, - getTsvFunction_{std::move(getTsvFunction)} {} + getTsvFunction_{std::move(getTsvFunction)}, + siblingTree_{std::move(siblingTree)} {} // ____________________________________________________________________________ std::string Service::getCacheKeyImpl() const { @@ -32,7 +37,11 @@ std::string Service::getCacheKeyImpl() const { // TODO: This duplicates code in GraphPatternOperation.cpp . os << "SERVICE " << parsedServiceClause_.serviceIri_.toSparql() << " {\n" << parsedServiceClause_.prologue_ << "\n" - << parsedServiceClause_.graphPatternAsString_ << "\n}\n"; + << parsedServiceClause_.graphPatternAsString_ << "\n"; + if (siblingTree_ != nullptr) { + os << siblingTree_->getRootOperation()->getCacheKey() << "\n"; + } + os << "}\n"; return std::move(os).str(); } @@ -83,7 +92,7 @@ size_t Service::getCostEstimate() { } // ____________________________________________________________________________ -ResultTable Service::computeResult() { +Result Service::computeResult([[maybe_unused]] bool requestLaziness) { // Get the URL of the SPARQL endpoint. std::string_view serviceIriString = parsedServiceClause_.serviceIri_.iri(); AD_CONTRACT_CHECK(serviceIriString.starts_with("<") && @@ -92,6 +101,14 @@ ResultTable Service::computeResult() { serviceIriString.remove_suffix(1); ad_utility::httpUtils::Url serviceUrl{serviceIriString}; + // Try to simplify the Service Query using it's sibling Operation. + if (auto valuesClause = getSiblingValuesClause(); valuesClause.has_value()) { + auto openBracketPos = parsedServiceClause_.graphPatternAsString_.find('{'); + parsedServiceClause_.graphPatternAsString_ = + "{\n" + valuesClause.value() + '\n' + + parsedServiceClause_.graphPatternAsString_.substr(openBracketPos + 1); + } + // Construct the query to be sent to the SPARQL endpoint. std::string variablesForSelectClause = absl::StrJoin( parsedServiceClause_.visibleVariables_, " ", Variable::AbslFormatter); @@ -159,6 +176,66 @@ ResultTable Service::computeResult() { return {std::move(idTable), resultSortedOn(), std::move(localVocab)}; } +// ____________________________________________________________________________ +std::optional Service::getSiblingValuesClause() const { + if (siblingTree_ == nullptr) { + return std::nullopt; + } + + const auto& siblingResult = siblingTree_->getResult(); + if (siblingResult->idTable().size() > + RuntimeParameters().get<"service-max-value-rows">()) { + return std::nullopt; + } + + checkCancellation(); + + std::vector commonColumnIndices; + const auto& siblingVars = siblingTree_->getVariableColumns(); + std::string vars = "("; + for (const auto& localVar : parsedServiceClause_.visibleVariables_) { + auto it = siblingVars.find(localVar); + if (it == siblingVars.end()) { + continue; + } + absl::StrAppend(&vars, it->first.name(), " "); + commonColumnIndices.push_back(it->second.columnIndex_); + } + vars.back() = ')'; + + checkCancellation(); + + ad_utility::HashSet rowSet; + + std::string values = " { "; + for (size_t rowIndex = 0; rowIndex < siblingResult->idTable().size(); + ++rowIndex) { + std::string row = "("; + for (const auto& columnIdx : commonColumnIndices) { + const auto& optionalString = ExportQueryExecutionTrees::idToStringAndType( + siblingTree_->getRootOperation()->getIndex(), + siblingResult->idTable()(rowIndex, columnIdx), + siblingResult->localVocab()); + + if (optionalString.has_value()) { + absl::StrAppend(&row, optionalString.value().first, " "); + } + } + row.back() = ')'; + + if (rowSet.contains(row)) { + continue; + } + + rowSet.insert(row); + absl::StrAppend(&values, row, " "); + + checkCancellation(); + } + + return "VALUES " + vars + values + "} . "; +} + // ____________________________________________________________________________ template void Service::writeTsvResult(cppcoro::generator tsvResult, diff --git a/src/engine/Service.h b/src/engine/Service.h index c569d1f1cf..9594b66b19 100644 --- a/src/engine/Service.h +++ b/src/engine/Service.h @@ -46,6 +46,9 @@ class Service : public Operation { // The function used to obtain the result from the remote endpoint. GetTsvFunction getTsvFunction_; + // The siblingTree, used for SERVICE clause optimization. + std::shared_ptr siblingTree_; + public: // Construct from parsed Service clause. // @@ -54,7 +57,14 @@ class Service : public Operation { // but in our tests (`ServiceTest`) we use a mock function that does not // require a running `HttpServer`. Service(QueryExecutionContext* qec, parsedQuery::Service parsedServiceClause, - GetTsvFunction getTsvFunction = sendHttpOrHttpsRequest); + GetTsvFunction getTsvFunction = sendHttpOrHttpsRequest, + std::shared_ptr siblingTree = nullptr); + + // Set the siblingTree (subTree that will later be joined with the Result of + // the Service Operation), used to reduce the Service Queries Complexity. + void setSiblingTree(std::shared_ptr siblingTree) { + siblingTree_ = siblingTree; + } // Methods inherited from base class `Operation`. std::string getDescriptor() const override; @@ -62,6 +72,12 @@ class Service : public Operation { std::vector resultSortedOn() const override { return {}; } float getMultiplicity(size_t col) override; + // Getters for testing. + const auto& getSiblingTree() const { return siblingTree_; } + const auto& getGraphPatternAsString() const { + return parsedServiceClause_.graphPatternAsString_; + } + private: uint64_t getSizeEstimateBeforeLimit() override; @@ -80,7 +96,10 @@ class Service : public Operation { std::string getCacheKeyImpl() const override; // Compute the result using `getTsvFunction_`. - ResultTable computeResult() override; + Result computeResult([[maybe_unused]] bool requestLaziness) override; + + // Get a VALUES clause that contains the values of the siblingTree's result. + std::optional getSiblingValuesClause() const; // Write the given TSV result to the given result object. The `I` is the width // of the result table. diff --git a/src/engine/Sort.cpp b/src/engine/Sort.cpp index 3bb0207e35..28b6be76ac 100644 --- a/src/engine/Sort.cpp +++ b/src/engine/Sort.cpp @@ -8,6 +8,7 @@ #include #include "engine/CallFixedSize.h" +#include "engine/Engine.h" #include "engine/QueryExecutionTree.h" #include "global/RuntimeParameters.h" @@ -50,16 +51,16 @@ std::string Sort::getDescriptor() const { } // _____________________________________________________________________________ -ResultTable Sort::computeResult() { +Result Sort::computeResult([[maybe_unused]] bool requestLaziness) { using std::endl; LOG(DEBUG) << "Getting sub-result for Sort result computation..." << endl; - shared_ptr subRes = subtree_->getResult(); + std::shared_ptr subRes = subtree_->getResult(); // TODO proper timeout for sorting operations auto sortEstimateCancellationFactor = RuntimeParameters().get<"sort-estimate-cancellation-factor">(); if (getExecutionContext()->getSortPerformanceEstimator().estimatedSortTime( - subRes->size(), subRes->width()) > + subRes->idTable().size(), subRes->idTable().numColumns()) > remainingTime() * sortEstimateCancellationFactor) { // The estimated time for this sort is much larger than the actually // remaining time, cancel this operation diff --git a/src/engine/Sort.h b/src/engine/Sort.h index 4919133f9d..d8a77c4f8d 100644 --- a/src/engine/Sort.h +++ b/src/engine/Sort.h @@ -67,7 +67,7 @@ class Sort : public Operation { } private: - virtual ResultTable computeResult() override; + virtual Result computeResult([[maybe_unused]] bool requestLaziness) override; [[nodiscard]] VariableToColumnMap computeVariableToColumnMap() const override { diff --git a/src/engine/SortPerformanceEstimator.h b/src/engine/SortPerformanceEstimator.h index ad5aad93c9..c643ea9c92 100644 --- a/src/engine/SortPerformanceEstimator.h +++ b/src/engine/SortPerformanceEstimator.h @@ -43,7 +43,7 @@ class SortPerformanceEstimator { size_t maxNumberOfElementsToSort); /// Set up the sort estimates. This will take some time. Only samples, that - /// can be allocated by the allocator and that have less thatn + /// can be allocated by the allocator and that have less than /// `maxNumberOfElementsToSort` elements will actually be measured. void computeEstimatesExpensively( const ad_utility::AllocatorWithLimit& allocator, @@ -61,7 +61,7 @@ class SortPerformanceEstimator { static constexpr size_t NUM_SAMPLES_COLS = sampleValuesCols.size(); static constexpr size_t NUM_SAMPLES_ROWS = sampleValuesRows.size(); - // The time in seconds for the samples that are sorted during initializtion. + // The time in seconds for the samples that are sorted during initialization. // _samples[i][j] is the measured time it takes to sort an IdTable with // sampleValuesRows[i] rows and sampleValuesCols[j] columns. // The values are default-initialized to 0. diff --git a/src/engine/TextIndexScanForEntity.cpp b/src/engine/TextIndexScanForEntity.cpp index 352ecde5e1..80150ed29d 100644 --- a/src/engine/TextIndexScanForEntity.cpp +++ b/src/engine/TextIndexScanForEntity.cpp @@ -14,7 +14,8 @@ TextIndexScanForEntity::TextIndexScanForEntity( word_(std::move(word)) {} // _____________________________________________________________________________ -ResultTable TextIndexScanForEntity::computeResult() { +Result TextIndexScanForEntity::computeResult( + [[maybe_unused]] bool requestLaziness) { IdTable idTable = getExecutionContext()->getIndex().getEntityMentionsForWord( word_, getExecutionContext()->getAllocator()); diff --git a/src/engine/TextIndexScanForEntity.h b/src/engine/TextIndexScanForEntity.h index 6926b1d8d7..4679847f74 100644 --- a/src/engine/TextIndexScanForEntity.h +++ b/src/engine/TextIndexScanForEntity.h @@ -101,7 +101,7 @@ class TextIndexScanForEntity : public Operation { return std::get(varOrFixed_.entity_).second; } - ResultTable computeResult() override; + Result computeResult([[maybe_unused]] bool requestLaziness) override; vector getChildren() override { return {}; } }; diff --git a/src/engine/TextIndexScanForWord.cpp b/src/engine/TextIndexScanForWord.cpp index c490a88c6f..5a7fa19425 100644 --- a/src/engine/TextIndexScanForWord.cpp +++ b/src/engine/TextIndexScanForWord.cpp @@ -13,7 +13,8 @@ TextIndexScanForWord::TextIndexScanForWord(QueryExecutionContext* qec, isPrefix_(word_.ends_with('*')) {} // _____________________________________________________________________________ -ResultTable TextIndexScanForWord::computeResult() { +Result TextIndexScanForWord::computeResult( + [[maybe_unused]] bool requestLaziness) { IdTable idTable = getExecutionContext()->getIndex().getWordPostingsForTerm( word_, getExecutionContext()->getAllocator()); diff --git a/src/engine/TextIndexScanForWord.h b/src/engine/TextIndexScanForWord.h index a8d7033195..139c7d40fe 100644 --- a/src/engine/TextIndexScanForWord.h +++ b/src/engine/TextIndexScanForWord.h @@ -48,9 +48,9 @@ class TextIndexScanForWord : public Operation { VariableToColumnMap computeVariableToColumnMap() const override; private: - // Returns a ResultTable containing an IdTable with the columns being + // Returns a Result containing an IdTable with the columns being // the text variable and the completed word (if it was prefixed) - ResultTable computeResult() override; + Result computeResult([[maybe_unused]] bool requestLaziness) override; vector getChildren() override { return {}; } }; diff --git a/src/engine/TextLimit.cpp b/src/engine/TextLimit.cpp index 4b7eff3455..1988763a1a 100644 --- a/src/engine/TextLimit.cpp +++ b/src/engine/TextLimit.cpp @@ -18,11 +18,12 @@ TextLimit::TextLimit(QueryExecutionContext* qec, const size_t limit, scoreColumns_(scoreColumns) {} // _____________________________________________________________________________ -ResultTable TextLimit::computeResult() { - shared_ptr childRes = child_->getResult(); +Result TextLimit::computeResult([[maybe_unused]] bool requestLaziness) { + std::shared_ptr childRes = child_->getResult(); if (limit_ == 0) { - return {IdTable(childRes->width(), getExecutionContext()->getAllocator()), + return {IdTable(childRes->idTable().numColumns(), + getExecutionContext()->getAllocator()), resultSortedOn(), childRes->getSharedLocalVocab()}; } diff --git a/src/engine/TextLimit.h b/src/engine/TextLimit.h index 97f930674a..b3b08a1ebf 100644 --- a/src/engine/TextLimit.h +++ b/src/engine/TextLimit.h @@ -61,7 +61,7 @@ class TextLimit : public Operation { VariableToColumnMap computeVariableToColumnMap() const override; private: - ResultTable computeResult() override; + Result computeResult([[maybe_unused]] bool requestLaziness) override; vector getChildren() override { return {child_.get()}; } }; diff --git a/src/engine/TransitivePathBase.h b/src/engine/TransitivePathBase.h index 1fcfc56e2d..ce7c32ac3e 100644 --- a/src/engine/TransitivePathBase.h +++ b/src/engine/TransitivePathBase.h @@ -20,7 +20,7 @@ struct TransitivePathSide { // Column of the sub table where the Ids of this side are located size_t subCol_; std::variant value_; - // The column in the ouput table where this side Ids are written to. + // The column in the output table where this side Ids are written to. // This member is set by the TransitivePath class size_t outputCol_ = 0; @@ -270,8 +270,8 @@ class TransitivePathBase : public Operation { // Return a set of subtrees that can be used alternatively when the left or // right side is bound. This is used by the `TransitivePathBinSearch` class, - // which keeps both possible sortings of the predicate of which transitivity - // is computed. + // which has to store both ways to sort the subtree until it knows which side + // becomes bound. virtual std::span> alternativeSubtrees() const { return {}; diff --git a/src/engine/TransitivePathImpl.h b/src/engine/TransitivePathImpl.h index 16fe987dbb..ea4a7a8560 100644 --- a/src/engine/TransitivePathImpl.h +++ b/src/engine/TransitivePathImpl.h @@ -140,17 +140,18 @@ class TransitivePathImpl : public TransitivePathBase { * on the time it takes to compute the hull. The set of nodes on the * start side should be as small as possible. * - * @return ResultTable The result of the TransitivePath operation + * @return Result The result of the TransitivePath operation */ - ResultTable computeResult() override { + Result computeResult([[maybe_unused]] bool requestLaziness) override { if (minDist_ == 0 && !isBoundOrId() && lhs_.isVariable() && rhs_.isVariable()) { AD_THROW( - "This query might have to evalute the empty path, which is currently " + "This query might have to evaluate the empty path, which is " + "currently " "not supported"); } auto [startSide, targetSide] = decideDirection(); - shared_ptr subRes = subtree_->getResult(); + std::shared_ptr subRes = subtree_->getResult(); IdTable idTable{allocator()}; @@ -159,7 +160,7 @@ class TransitivePathImpl : public TransitivePathBase { size_t subWidth = subRes->idTable().numColumns(); if (startSide.isBoundVariable()) { - shared_ptr sideRes = + std::shared_ptr sideRes = startSide.treeAndCol_.value().first->getResult(); size_t sideWidth = sideRes->idTable().numColumns(); @@ -169,7 +170,7 @@ class TransitivePathImpl : public TransitivePathBase { sideRes->idTable()); return {std::move(idTable), resultSortedOn(), - ResultTable::getMergedLocalVocab(*sideRes, *subRes)}; + Result::getMergedLocalVocab(*sideRes, *subRes)}; } CALL_FIXED_SIZE((std::array{resultWidth_, subWidth}), &TransitivePathImpl::computeTransitivePath, this, diff --git a/src/engine/Union.cpp b/src/engine/Union.cpp index 82ed91aef3..901f1df7e3 100644 --- a/src/engine/Union.cpp +++ b/src/engine/Union.cpp @@ -75,7 +75,7 @@ VariableToColumnMap Union::computeVariableToColumnMap() const { // subtrees and if it is guaranteed to be bound in all the subtrees. auto mightContainUndef = [this](const Variable& var) { return std::ranges::any_of( - _subtrees, [&](const shared_ptr& subtree) { + _subtrees, [&](const std::shared_ptr& subtree) { const auto& varCols = subtree->getVariableColumns(); return !varCols.contains(var) || (varCols.at(var).mightContainUndef_ == @@ -158,10 +158,10 @@ size_t Union::getCostEstimate() { getSizeEstimateBeforeLimit(); } -ResultTable Union::computeResult() { +Result Union::computeResult([[maybe_unused]] bool requestLaziness) { LOG(DEBUG) << "Union result computation..." << std::endl; - shared_ptr subRes1 = _subtrees[0]->getResult(); - shared_ptr subRes2 = _subtrees[1]->getResult(); + std::shared_ptr subRes1 = _subtrees[0]->getResult(); + std::shared_ptr subRes2 = _subtrees[1]->getResult(); LOG(DEBUG) << "Union subresult computation done." << std::endl; IdTable idTable{getExecutionContext()->getAllocator()}; @@ -173,8 +173,8 @@ ResultTable Union::computeResult() { LOG(DEBUG) << "Union result computation done" << std::endl; // If only one of the two operands has a non-empty local vocabulary, share // with that one (otherwise, throws an exception). - return ResultTable{std::move(idTable), resultSortedOn(), - ResultTable::getMergedLocalVocab(*subRes1, *subRes2)}; + return Result{std::move(idTable), resultSortedOn(), + Result::getMergedLocalVocab(*subRes1, *subRes2)}; } void Union::computeUnion( diff --git a/src/engine/Union.h b/src/engine/Union.h index 4be8694e95..d70b715e5a 100644 --- a/src/engine/Union.h +++ b/src/engine/Union.h @@ -61,7 +61,7 @@ class Union : public Operation { } private: - virtual ResultTable computeResult() override; + virtual Result computeResult([[maybe_unused]] bool requestLaziness) override; VariableToColumnMap computeVariableToColumnMap() const override; }; diff --git a/src/engine/Values.cpp b/src/engine/Values.cpp index 3362317f55..5c61b3cfe7 100644 --- a/src/engine/Values.cpp +++ b/src/engine/Values.cpp @@ -108,7 +108,7 @@ void Values::computeMultiplicities() { } // ____________________________________________________________________________ -ResultTable Values::computeResult() { +Result Values::computeResult([[maybe_unused]] bool requestLaziness) { // Set basic properties of the result table. IdTable idTable{getExecutionContext()->getAllocator()}; idTable.setNumColumns(getResultWidth()); @@ -130,8 +130,10 @@ void Values::writeValues(IdTable* idTablePtr, LocalVocab* localVocab) { std::vector numLocalVocabPerColumn(idTable.numColumns()); for (auto& row : parsedValues_._values) { for (size_t colIdx = 0; colIdx < idTable.numColumns(); colIdx++) { - TripleComponent& tc = row[colIdx]; - Id id = std::move(tc).toValueId(getIndex().getVocab(), *localVocab); + const TripleComponent& tc = row[colIdx]; + // TODO We don't want to move, but also don't want to + // unconditionally copy. + Id id = TripleComponent{tc}.toValueId(getIndex().getVocab(), *localVocab); idTable(rowIdx, colIdx) = id; if (id.getDatatype() == Datatype::LocalVocabIndex) { ++numLocalVocabPerColumn[colIdx]; diff --git a/src/engine/Values.h b/src/engine/Values.h index b69c2392ea..52823bf5ea 100644 --- a/src/engine/Values.h +++ b/src/engine/Values.h @@ -48,7 +48,7 @@ class Values : public Operation { public: // These two are also used by class `Service`, hence public. - virtual ResultTable computeResult() override; + virtual Result computeResult([[maybe_unused]] bool requestLaziness) override; VariableToColumnMap computeVariableToColumnMap() const override; diff --git a/src/engine/idTable/CompressedExternalIdTable.h b/src/engine/idTable/CompressedExternalIdTable.h index d444db8e69..27b78c6121 100644 --- a/src/engine/idTable/CompressedExternalIdTable.h +++ b/src/engine/idTable/CompressedExternalIdTable.h @@ -469,7 +469,7 @@ class CompressedExternalIdTable // exactly once. auto getRows() { if (!this->transformAndPushLastBlock()) { - // For the case of only a single block we have to mimick the exact same + // For the case of only a single block we have to mimic the exact same // return type as that of `writer_.getGeneratorForAllRows()`, that's why // there are the seemingly redundant multiple calls to // join(OwningView(vector(...))). @@ -538,7 +538,7 @@ struct BlockSorter { #endif } }; -// Deduction guide for the implicit aggregate initializtion (its "constructor") +// Deduction guide for the implicit aggregate initialization (its "constructor") // in the aggregate above. Is actually not needed in C++20, but GCC 11 requires // it. template diff --git a/src/engine/idTable/IdTable.h b/src/engine/idTable/IdTable.h index 86dd34c78a..c2eb10acaa 100644 --- a/src/engine/idTable/IdTable.h +++ b/src/engine/idTable/IdTable.h @@ -618,7 +618,7 @@ class IdTable { // first copies the sorted input completely, and then calls `std::unique`, // followed by `erase` at the end. `DISTINCT` should be implemented via an // out-of-place algorithm that only writes the distinct elements. The the - // follwing two functions can be deleted. + // following two functions can be deleted. void erase(const iterator& beginIt, const iterator& endIt) requires(!isView) { AD_EXPENSIVE_CHECK(begin() <= beginIt && beginIt <= endIt && endIt <= end()); @@ -649,6 +649,18 @@ class IdTable { } } + // Add all entries from the `table` at the end of this IdTable. + void insertAtEnd(const IdTable& table) { + AD_CORRECTNESS_CHECK(table.numColumns() == numColumns()); + auto oldSize = size(); + resize(numRows() + table.numRows_); + std::ranges::for_each(ad_utility::integerRange(numColumns()), + [this, &table, oldSize](size_t i) { + std::ranges::copy(table.getColumn(i), + getColumn(i).begin() + oldSize); + }); + } + // Check whether two `IdTables` have the same content. Mostly used for unit // testing. bool operator==(const IdTable& other) const requires(!isView) { diff --git a/src/engine/raw_thoughts.txt b/src/engine/raw_thoughts.txt index b37fbc6021..df5ebe05bb 100644 --- a/src/engine/raw_thoughts.txt +++ b/src/engine/raw_thoughts.txt @@ -3,7 +3,7 @@ Thoughts on open TODOS: TODO: Evaluate filters as early as possible. - A filter with one variable is essentially another relation on that var. - A filter with two variables will be applied as soon as both nodes are collapsed -Right now Filters with two varibales are implemented but they are processed in the end. +Right now Filters with two variables are implemented but they are processed in the end. This is possibly not optimal. Think of: ?x mother ?m @@ -78,7 +78,7 @@ FOR THE SIMPLE CASE ?x -- ?c [word] -SOLUTION: no longer as weired semantics. +SOLUTION: no longer as weird semantics. need to collapse the smallest subtrees behind the variable first, then use the words as extra info during the final consume. @@ -131,7 +131,7 @@ PROBLEM3: Two different results. With co-occurring entity and without depending I WANT: Due to problem3, I do NOT create execution trees for context nodes (easy to detect). Depending on the rest of the query graph / tree, there cannot be one optimal operation to compute the context node's result. -When consuming a context node, into a higher up, I create a TEXT OEPRATION forEntity. +When consuming a context node, into a higher up, I create a TEXT OPERATION forEntity. This will be a consumption of an edge with target context-node. I will later add relations that can also consume context nodes. Those will create a TEXT OPERATION forContexts and a context->document mapping (easy Broccoli style with ranges). diff --git a/src/engine/sparqlExpressions/CMakeLists.txt b/src/engine/sparqlExpressions/CMakeLists.txt index 0aff558d2d..c8c998f1a1 100644 --- a/src/engine/sparqlExpressions/CMakeLists.txt +++ b/src/engine/sparqlExpressions/CMakeLists.txt @@ -15,6 +15,8 @@ add_library(sparqlExpressions IsSomethingExpressions.cpp ConditionalExpressions.cpp SparqlExpressionTypes.cpp - SparqlExpression.cpp) + SparqlExpression.cpp + ConvertToNumericExpression.cpp + RdfTermExpressions.cpp) qlever_target_link_libraries(sparqlExpressions util index Boost::url) diff --git a/src/engine/sparqlExpressions/ConvertToNumericExpression.cpp b/src/engine/sparqlExpressions/ConvertToNumericExpression.cpp new file mode 100644 index 0000000000..50ac26d7af --- /dev/null +++ b/src/engine/sparqlExpressions/ConvertToNumericExpression.cpp @@ -0,0 +1,76 @@ +// Copyright 2024, University of Freiburg, +// Chair of Algorithms and Data Structures +// Author: Hannes Baumann + +#include "engine/sparqlExpressions/NaryExpressionImpl.h" + +namespace sparqlExpression { +namespace detail::to_numeric { + +// class that converts an input `int64_t`, `double` or `std::string` +// to a numeric value `int64_t` or `double` +template +requires std::same_as || std::same_as +class ToNumericImpl { + private: + Id getFromString(const std::string& input) const { + auto str = absl::StripAsciiWhitespace(input); + auto strEnd = str.data() + str.size(); + auto strStart = str.data(); + T resT{}; + if constexpr (std::is_same_v) { + auto conv = std::from_chars(strStart, strEnd, resT); + if (conv.ec == std::error_code{} && conv.ptr == strEnd) { + return Id::makeFromInt(resT); + } + } else { + auto conv = absl::from_chars(strStart, strEnd, resT); + if (conv.ec == std::error_code{} && conv.ptr == strEnd) { + return Id::makeFromDouble(resT); + } + } + return Id::makeUndefined(); + }; + + // ___________________________________________________________________________ + template + requires std::integral || std::floating_point + Id getFromNumber(N number) const { + auto resNumber = static_cast(number); + if constexpr (std::is_same_v) { + return Id::makeFromInt(resNumber); + } else { + return Id::makeFromDouble(resNumber); + } + }; + + public: + Id operator()(IntDoubleStr value) const { + if (std::holds_alternative(value)) { + return getFromString(std::get(value)); + } else if (std::holds_alternative(value)) { + return getFromNumber(std::get(value)); + } else if (std::holds_alternative(value)) { + return getFromNumber(std::get(value)); + } else { + AD_CORRECTNESS_CHECK(std::holds_alternative(value)); + return Id::makeUndefined(); + } + } +}; + +using ToInteger = NARY<1, FV, ToNumericValueGetter>>; +using ToDouble = NARY<1, FV, ToNumericValueGetter>>; +} // namespace detail::to_numeric + +using namespace detail::to_numeric; +using Expr = SparqlExpression::Ptr; + +Expr makeConvertToIntExpression(Expr child) { + return std::make_unique(std::move(child)); +} + +Expr makeConvertToDoubleExpression(Expr child) { + return std::make_unique(std::move(child)); +} +} // namespace sparqlExpression diff --git a/src/engine/sparqlExpressions/DateExpressions.cpp b/src/engine/sparqlExpressions/DateExpressions.cpp index 4fc2742d16..2cb79fffc9 100644 --- a/src/engine/sparqlExpressions/DateExpressions.cpp +++ b/src/engine/sparqlExpressions/DateExpressions.cpp @@ -40,6 +40,19 @@ inline auto extractDay = [](std::optional d) { return Id::makeFromInt(optionalDay.value()); }; +using LiteralOrIri = ad_utility::triple_component::LiteralOrIri; +using Literal = ad_utility::triple_component::Literal; + +inline auto extractStrTimezone = + [](std::optional d) -> IdOrLiteralOrIri { + if (d.has_value()) { + auto timezoneStr = d.value().getStrTimezone(); + return LiteralOrIri{Literal::literalWithNormalizedContent( + asNormalizedStringViewUnsafe(timezoneStr))}; + } + return Id::makeUndefined(); +}; + template inline auto extractTimeComponentImpl = [](std::optional d) { if (!d.has_value() || !d->isDate()) { @@ -63,6 +76,8 @@ NARY_EXPRESSION(YearExpression, 1, FV); NARY_EXPRESSION(MonthExpression, 1, FV); NARY_EXPRESSION(DayExpression, 1, FV); +NARY_EXPRESSION(TimezoneStrExpression, 1, + FV); NARY_EXPRESSION(HoursExpression, 1, FV); NARY_EXPRESSION(MinutesExpression, 1, @@ -80,6 +95,10 @@ SparqlExpression::Ptr makeDayExpression(SparqlExpression::Ptr child) { return std::make_unique(std::move(child)); } +SparqlExpression::Ptr makeTimezoneStrExpression(SparqlExpression::Ptr child) { + return std::make_unique(std::move(child)); +} + SparqlExpression::Ptr makeMonthExpression(SparqlExpression::Ptr child) { return std::make_unique(std::move(child)); } diff --git a/src/engine/sparqlExpressions/LangExpression.h b/src/engine/sparqlExpressions/LangExpression.h index 9e1a6ac257..bad553f8db 100644 --- a/src/engine/sparqlExpressions/LangExpression.h +++ b/src/engine/sparqlExpressions/LangExpression.h @@ -28,8 +28,8 @@ class LangExpression : public SparqlExpression { // The following methods are required for the virtual interface of // `SparqlExpression`, but they will always fail at runtime when executed. All - // occurences of `LanguageExpression` should be detected and dealt with by the - // parser before any of these methods is ever called. + // occurrences of `LanguageExpression` should be detected and dealt with by + // the parser before any of these methods is ever called. ExpressionResult evaluate(EvaluationContext*) const override { AD_FAIL(); } std::string getCacheKey(const VariableToColumnMap&) const override { diff --git a/src/engine/sparqlExpressions/NaryExpression.h b/src/engine/sparqlExpressions/NaryExpression.h index 154e039f7b..680f54e368 100644 --- a/src/engine/sparqlExpressions/NaryExpression.h +++ b/src/engine/sparqlExpressions/NaryExpression.h @@ -52,9 +52,15 @@ SparqlExpression::Ptr makeSecondsExpression(SparqlExpression::Ptr child); SparqlExpression::Ptr makeMinutesExpression(SparqlExpression::Ptr child); SparqlExpression::Ptr makeHoursExpression(SparqlExpression::Ptr child); SparqlExpression::Ptr makeDayExpression(SparqlExpression::Ptr child); +SparqlExpression::Ptr makeTimezoneStrExpression(SparqlExpression::Ptr child); SparqlExpression::Ptr makeMonthExpression(SparqlExpression::Ptr child); SparqlExpression::Ptr makeYearExpression(SparqlExpression::Ptr child); +SparqlExpression::Ptr makeStrIriDtExpression(SparqlExpression::Ptr child1, + SparqlExpression::Ptr child2); +SparqlExpression::Ptr makeStrLangTagExpression(SparqlExpression::Ptr child1, + SparqlExpression::Ptr child2); + SparqlExpression::Ptr makeStrExpression(SparqlExpression::Ptr child); SparqlExpression::Ptr makeStrlenExpression(SparqlExpression::Ptr child); SparqlExpression::Ptr makeSubstrExpression(SparqlExpression::Ptr string, @@ -78,10 +84,24 @@ SparqlExpression::Ptr makeReplaceExpression(SparqlExpression::Ptr input, SparqlExpression::Ptr makeStrBeforeExpression(SparqlExpression::Ptr child1, SparqlExpression::Ptr child2); +SparqlExpression::Ptr makeMD5Expression(SparqlExpression::Ptr child); +SparqlExpression::Ptr makeSHA1Expression(SparqlExpression::Ptr child); +SparqlExpression::Ptr makeSHA256Expression(SparqlExpression::Ptr child); +SparqlExpression::Ptr makeSHA384Expression(SparqlExpression::Ptr child); +SparqlExpression::Ptr makeSHA512Expression(SparqlExpression::Ptr child); + SparqlExpression::Ptr makeIfExpression(SparqlExpression::Ptr child1, SparqlExpression::Ptr child2, SparqlExpression::Ptr child3); +// Implemented in ConvertToNumeric.cpp +SparqlExpression::Ptr makeConvertToIntExpression(SparqlExpression::Ptr child); +SparqlExpression::Ptr makeConvertToDoubleExpression( + SparqlExpression::Ptr child); + +// Implemented in RdfTermExpressions.cpp +SparqlExpression::Ptr makeDatatypeExpression(SparqlExpression::Ptr child); + SparqlExpression::Ptr makeEncodeForUriExpression(SparqlExpression::Ptr child); SparqlExpression::Ptr makeIsIriExpression(SparqlExpression::Ptr child); diff --git a/src/engine/sparqlExpressions/NaryExpressionImpl.h b/src/engine/sparqlExpressions/NaryExpressionImpl.h index f099f3eee6..0de7a5f16b 100644 --- a/src/engine/sparqlExpressions/NaryExpressionImpl.h +++ b/src/engine/sparqlExpressions/NaryExpressionImpl.h @@ -6,9 +6,12 @@ #include +#include "absl/strings/ascii.h" +#include "absl/strings/charconv.h" #include "engine/sparqlExpressions/NaryExpression.h" #include "engine/sparqlExpressions/SparqlExpressionGenerators.h" #include "engine/sparqlExpressions/SparqlExpressionValueGetters.h" +#include "util/CryptographicHashUtils.h" namespace sparqlExpression::detail { template diff --git a/src/engine/sparqlExpressions/NowDatetimeExpression.h b/src/engine/sparqlExpressions/NowDatetimeExpression.h new file mode 100644 index 0000000000..059e8522f0 --- /dev/null +++ b/src/engine/sparqlExpressions/NowDatetimeExpression.h @@ -0,0 +1,38 @@ +// Copyright 2024, University of Freiburg, +// Chair of Algorithms and Data Structures +// Author: Hannes Baumann + +#include "engine/sparqlExpressions/SparqlExpression.h" +#include "util/ChunkedForLoop.h" +#include "util/Date.h" +#include "util/Random.h" + +namespace sparqlExpression { + +// The expression `NOW()` is evaluated within NowDatetimeExpression.h. +// `NowDatetimeExpression` has to be explicitly constructed from a +// `date-formatted string`, which is for all evaluations within a Sparql +// query the same. +class NowDatetimeExpression : public SparqlExpression { + private: + DateOrLargeYear date_; + + public: + explicit NowDatetimeExpression(const std::string& dateTimeFormat) + : date_(DateOrLargeYear::parseXsdDatetime(dateTimeFormat)) {} + + std::string getCacheKey( + [[maybe_unused]] const VariableToColumnMap& varColMap) const override { + return absl::StrCat("NOW ", date_.toBits()); + } + + ExpressionResult evaluate( + [[maybe_unused]] EvaluationContext* context) const override { + return Id::makeFromDate(date_); + } + + private: + std::span childrenImpl() override { return {}; } +}; + +} // namespace sparqlExpression diff --git a/src/engine/sparqlExpressions/RdfTermExpressions.cpp b/src/engine/sparqlExpressions/RdfTermExpressions.cpp new file mode 100644 index 0000000000..d4e59b5643 --- /dev/null +++ b/src/engine/sparqlExpressions/RdfTermExpressions.cpp @@ -0,0 +1,29 @@ +// Copyright 2024, University of Freiburg, +// Chair of Algorithms and Data Structures +// Author: Hannes Baumann + +#include "engine/sparqlExpressions/NaryExpressionImpl.h" + +namespace sparqlExpression { +namespace detail::rdfExpressions { + +inline auto getDatatype = [](OptIri input) -> IdOrLiteralOrIri { + if (!input.has_value()) { + return Id::makeUndefined(); + } else { + return LiteralOrIri{std::move(input.value())}; + } +}; + +using GetDatatype = NARY<1, FV>; + +} // namespace detail::rdfExpressions + +using namespace detail::rdfExpressions; +using Expr = SparqlExpression::Ptr; + +Expr makeDatatypeExpression(Expr child) { + return std::make_unique(std::move(child)); +} + +} // namespace sparqlExpression diff --git a/src/engine/sparqlExpressions/RegexExpression.h b/src/engine/sparqlExpressions/RegexExpression.h index a584a94707..783acc22db 100644 --- a/src/engine/sparqlExpressions/RegexExpression.h +++ b/src/engine/sparqlExpressions/RegexExpression.h @@ -65,8 +65,8 @@ class RegexExpression : public SparqlExpression { namespace detail { // Check if `regex` is a prefix regex which means that it starts with `^` and // contains no other "special" regex characters like `*` or `.`. If this check -// suceeds, the prefix is returned without the leading `^` and with all escaping -// undone. Else, `std::nullopt` is returned. +// succeeds, the prefix is returned without the leading `^` and with all +// escaping undone. Else, `std::nullopt` is returned. std::optional getPrefixRegex(std::string regex); } // namespace detail } // namespace sparqlExpression diff --git a/src/engine/sparqlExpressions/SparqlExpressionTypes.h b/src/engine/sparqlExpressions/SparqlExpressionTypes.h index dc753e5b04..09e0b9b27f 100644 --- a/src/engine/sparqlExpressions/SparqlExpressionTypes.h +++ b/src/engine/sparqlExpressions/SparqlExpressionTypes.h @@ -195,8 +195,7 @@ Id constantExpressionResultToId(T&& result, LocalVocabT& localVocab) { if constexpr (ad_utility::isSimilar< R, ad_utility::triple_component::LiteralOrIri>) { return Id::makeFromLocalVocabIndex( - localVocab.getIndexAndAddIfNotContained( - AD_FWD(el).toStringRepresentation())); + localVocab.getIndexAndAddIfNotContained(AD_FWD(el))); } else { static_assert(ad_utility::isSimilar); return el; diff --git a/src/engine/sparqlExpressions/SparqlExpressionValueGetters.cpp b/src/engine/sparqlExpressions/SparqlExpressionValueGetters.cpp index ec0954967b..993e4dfa99 100644 --- a/src/engine/sparqlExpressions/SparqlExpressionValueGetters.cpp +++ b/src/engine/sparqlExpressions/SparqlExpressionValueGetters.cpp @@ -64,7 +64,9 @@ auto EffectiveBooleanValueGetter::operator()( : True; } case Datatype::LocalVocabIndex: { - return (context->_localVocab.getWord(id.getLocalVocabIndex()).empty()) + return (context->_localVocab.getWord(id.getLocalVocabIndex()) + .getContent() + .empty()) ? False : True; } @@ -113,7 +115,7 @@ template struct sparqlExpression::detail::IsSomethingValueGetter< template struct sparqlExpression::detail::IsSomethingValueGetter< &Index::Vocab::isLiteral, isLiteralPrefix>; -// ____________________________________________________________________________ +// _____________________________________________________________________________ std::optional LiteralFromIdGetter::operator()( ValueId id, const sparqlExpression::EvaluationContext* context) const { auto optionalStringAndType = @@ -126,7 +128,7 @@ std::optional LiteralFromIdGetter::operator()( } } -// ____________________________________________________________________________ +// _____________________________________________________________________________ bool IsValidValueGetter::operator()( ValueId id, [[maybe_unused]] const EvaluationContext* context) const { // Every knowledge base value that is bound converts to "True" @@ -134,3 +136,100 @@ bool IsValidValueGetter::operator()( // implement it in a further version. return id != ValueId::makeUndefined(); } + +// _____________________________________________________________________________ +IntDoubleStr ToNumericValueGetter::operator()( + ValueId id, [[maybe_unused]] const EvaluationContext* context) const { + switch (id.getDatatype()) { + case Datatype::Undefined: + return std::monostate{}; + case Datatype::Int: + return id.getInt(); + case Datatype::Double: + return id.getDouble(); + case Datatype::Bool: + return static_cast(id.getBool()); + case Datatype::VocabIndex: + case Datatype::LocalVocabIndex: + case Datatype::TextRecordIndex: + case Datatype::WordVocabIndex: + case Datatype::Date: + case Datatype::BlankNodeIndex: + auto optString = LiteralFromIdGetter{}(id, context); + if (optString.has_value()) { + return std::move(optString.value()); + } else { + return std::monostate{}; + } + } + AD_FAIL(); +} + +// _____________________________________________________________________________ +IntDoubleStr ToNumericValueGetter::operator()( + const LiteralOrIri& s, + [[maybe_unused]] const EvaluationContext* context) const { + return std::string(asStringViewUnsafe(s.getContent())); +} + +// _____________________________________________________________________________ +OptIri DatatypeValueGetter::operator()(ValueId id, + const EvaluationContext* context) const { + using enum Datatype; + auto datatype = id.getDatatype(); + std::optional entity; + switch (datatype) { + case Bool: + return Iri::fromIrirefWithoutBrackets(XSD_BOOLEAN_TYPE); + case Double: + return Iri::fromIrirefWithoutBrackets(XSD_DOUBLE_TYPE); + case Int: + return Iri::fromIrirefWithoutBrackets(XSD_INT_TYPE); + case Date: { + auto dateType = id.getDate().toStringAndType().second; + AD_CORRECTNESS_CHECK(dateType != nullptr); + return Iri::fromIrirefWithoutBrackets(dateType); + } + case LocalVocabIndex: + case VocabIndex: + return (*this)(ExportQueryExecutionTrees::getLiteralOrIriFromVocabIndex( + context->_qec.getIndex(), id, context->_localVocab), + context); + case Undefined: + case BlankNodeIndex: + case TextRecordIndex: + case WordVocabIndex: + return std::nullopt; + } + AD_FAIL(); +} + +// _____________________________________________________________________________ +OptIri DatatypeValueGetter::operator()( + const LiteralOrIri& litOrIri, + [[maybe_unused]] const EvaluationContext* context) const { + if (litOrIri.isLiteral()) { + const auto& literal = litOrIri.getLiteral(); + if (literal.hasLanguageTag()) { + return Iri::fromIrirefWithoutBrackets(RDF_LANGTAG_STRING); + } else if (literal.hasDatatype()) { + return Iri::fromIrirefWithoutBrackets( + asStringViewUnsafe(literal.getDatatype())); + } else { + return Iri::fromIrirefWithoutBrackets(XSD_STRING); + } + } else { + return std::nullopt; + } +} + +// _____________________________________________________________________________ +OptIri IriValueGetter::operator()( + const LiteralOrIri& s, + [[maybe_unused]] const EvaluationContext* context) const { + if (s.isIri()) { + return s.getIri(); + } else { + return std::nullopt; + } +} diff --git a/src/engine/sparqlExpressions/SparqlExpressionValueGetters.h b/src/engine/sparqlExpressions/SparqlExpressionValueGetters.h index 95c9f270b7..87f334c171 100644 --- a/src/engine/sparqlExpressions/SparqlExpressionValueGetters.h +++ b/src/engine/sparqlExpressions/SparqlExpressionValueGetters.h @@ -9,7 +9,7 @@ #include #include "engine/ExportQueryExecutionTrees.h" -#include "engine/ResultTable.h" +#include "engine/Result.h" #include "engine/sparqlExpressions/SparqlExpressionTypes.h" #include "global/Id.h" #include "util/ConstexprSmallString.h" @@ -21,6 +21,7 @@ namespace sparqlExpression::detail { using LiteralOrIri = ad_utility::triple_component::LiteralOrIri; +using Iri = ad_utility::triple_component::Iri; // An empty struct to represent a non-numeric value in a context where only // numeric values make sense. @@ -29,6 +30,18 @@ struct NotNumeric {}; using NumericValue = std::variant; using IntOrDouble = std::variant; +// Return type for `DatatypeValueGetter`. +using LiteralOrString = + std::variant; + +// Used as return type for `IriValueGetter` and `DatatypeValueGetter` +using OptIri = std::optional; + +// Used in `ConvertToNumericExpression.cpp` to allow for conversion of more +// general args to a numeric value (-> `int64_t or double`). +using IntDoubleStr = std::variant; + // Convert a numeric value (either a plain number, or the `NumericValue` variant // from above) into an `ID`. When `NanToUndef` is `true` then floating point NaN // values will become `Id::makeUndefined()`. @@ -227,4 +240,36 @@ struct RegexValueGetter { } }; +// `ToNumericValueGetter` returns `IntDoubleStr` a `std::variant` object which +// can contain: `int64_t`, `double`, `std::string` or `std::monostate`(empty). +struct ToNumericValueGetter : Mixin { + using Mixin::operator(); + IntDoubleStr operator()(ValueId id, const EvaluationContext*) const; + IntDoubleStr operator()(const LiteralOrIri& s, + const EvaluationContext*) const; +}; + +// ValueGetter for implementation of datatype() in RdfTermExpressions.cpp. +// Returns an object of type std::variant object. +struct DatatypeValueGetter : Mixin { + using Mixin::operator(); + OptIri operator()(ValueId id, const EvaluationContext* context) const; + OptIri operator()(const LiteralOrIri& litOrIri, + const EvaluationContext* context) const; +}; + +// `IriValueGetter` returns an +// `std::optional` object. If the +// `LiteralOrIri` object contains an `Iri`, the Iri is returned. This +// ValueGetter is currently used in `StringExpressions.cpp` within the +// implementation of `STRDT()`. +struct IriValueGetter : Mixin { + using Mixin::operator(); + OptIri operator()([[maybe_unused]] ValueId id, + const EvaluationContext*) const { + return std::nullopt; + } + OptIri operator()(const LiteralOrIri& s, const EvaluationContext*) const; +}; } // namespace sparqlExpression::detail diff --git a/src/engine/sparqlExpressions/StringExpressions.cpp b/src/engine/sparqlExpressions/StringExpressions.cpp index 7e48871a94..d8828fa748 100644 --- a/src/engine/sparqlExpressions/StringExpressions.cpp +++ b/src/engine/sparqlExpressions/StringExpressions.cpp @@ -399,6 +399,66 @@ class ConcatExpression : public detail::VariadicExpression { using EncodeForUriExpression = StringExpressionImpl<1, decltype(encodeForUriImpl)>; +// STRING WITH LANGUAGE TAG +[[maybe_unused]] inline auto strLangTag = + [](std::optional input, + std::optional langTag) -> IdOrLiteralOrIri { + if (!input.has_value() || !langTag.has_value()) { + return Id::makeUndefined(); + } else if (!ad_utility::strIsLangTag(langTag.value())) { + return Id::makeUndefined(); + } else { + auto lit = + ad_utility::triple_component::Literal::literalWithNormalizedContent( + asNormalizedStringViewUnsafe(input.value()), + std::move(langTag.value())); + return LiteralOrIri{lit}; + } +}; + +using StrLangTagged = StringExpressionImpl<2, decltype(strLangTag)>; + +// STRING WITH DATATYPE IRI +[[maybe_unused]] inline auto strIriDtTag = + [](std::optional inputStr, + OptIri inputIri) -> IdOrLiteralOrIri { + if (!inputStr.has_value() || !inputIri.has_value()) { + return Id::makeUndefined(); + } else { + auto lit = + ad_utility::triple_component::Literal::literalWithNormalizedContent( + asNormalizedStringViewUnsafe(inputStr.value()), inputIri.value()); + return LiteralOrIri{lit}; + } +}; + +using StrIriTagged = + StringExpressionImpl<2, decltype(strIriDtTag), IriValueGetter>; + +// HASH +template +[[maybe_unused]] inline constexpr auto hash = + [](std::optional input) -> IdOrLiteralOrIri { + if (!input.has_value()) { + return Id::makeUndefined(); + } else { + std::vector hashed = HashFunc(input.value()); + auto hexStr = absl::StrJoin(hashed, "", ad_utility::hexFormatter); + return toLiteral(std::move(hexStr)); + } +}; + +using MD5Expression = + StringExpressionImpl<1, decltype(hash)>; +using SHA1Expression = + StringExpressionImpl<1, decltype(hash)>; +using SHA256Expression = + StringExpressionImpl<1, decltype(hash)>; +using SHA384Expression = + StringExpressionImpl<1, decltype(hash)>; +using SHA512Expression = + StringExpressionImpl<1, decltype(hash)>; + } // namespace detail::string_expressions using namespace detail::string_expressions; using std::make_unique; @@ -452,4 +512,22 @@ Expr makeEncodeForUriExpression(Expr child) { return make(child); } +Expr makeStrLangTagExpression(Expr child1, Expr child2) { + return make(child1, child2); +} + +Expr makeStrIriDtExpression(Expr child1, Expr child2) { + return make(child1, child2); +} + +Expr makeMD5Expression(Expr child) { return make(child); } + +Expr makeSHA1Expression(Expr child) { return make(child); } + +Expr makeSHA256Expression(Expr child) { return make(child); } + +Expr makeSHA384Expression(Expr child) { return make(child); } + +Expr makeSHA512Expression(Expr child) { return make(child); } + } // namespace sparqlExpression diff --git a/src/engine/sparqlExpressions/UuidExpressions.h b/src/engine/sparqlExpressions/UuidExpressions.h new file mode 100644 index 0000000000..a11cf860d2 --- /dev/null +++ b/src/engine/sparqlExpressions/UuidExpressions.h @@ -0,0 +1,81 @@ +// Copyright 2024, University of Freiburg, +// Chair of Algorithms and Data Structures +// Author: Hannes Baumann + +// Test for UuidExpressionImpl can be found in RandomExpressionTest.cpp + +#pragma once + +#include "engine/sparqlExpressions/SparqlExpression.h" +#include "util/ChunkedForLoop.h" +#include "util/Random.h" + +namespace sparqlExpression { +namespace detail::uuidExpression { + +using LiteralOrIri = ad_utility::triple_component::LiteralOrIri; + +inline constexpr auto fromLiteral = [](std::string_view str) { + return LiteralOrIri{ + ad_utility::triple_component::Literal::literalWithNormalizedContent( + asNormalizedStringViewUnsafe(str))}; +}; + +inline constexpr auto fromIri = [](std::string_view str) { + return LiteralOrIri{ + ad_utility::triple_component::Iri::fromStringRepresentation( + absl::StrCat(""sv))}; +}; + +inline constexpr auto litUuidKey = [](int64_t randId) { + return absl::StrCat("STRUUID "sv, randId); +}; + +inline constexpr auto iriUuidKey = [](int64_t randId) { + return absl::StrCat("UUID "sv, randId); +}; + +// With UuidExpressionImpl, the UUIDs are returned as an +// Iri object: (example). With +// UuidExpressionImpl, the UUIDs are returned as an +// Literal object: "73cd4307-8a99-4691-a608-b5bda64fb6c1" (example). +template +class UuidExpressionImpl : public SparqlExpression { + private: + int64_t randId_ = ad_utility::FastRandomIntGenerator{}(); + + public: + ExpressionResult evaluate(EvaluationContext* context) const override { + VectorWithMemoryLimit result{context->_allocator}; + const size_t numElements = context->_endIndex - context->_beginIndex; + result.reserve(numElements); + ad_utility::UuidGenerator uuidGen; + + if (context->_isPartOfGroupBy) { + return FuncConv(uuidGen()); + } + + ad_utility::chunkedForLoop<1000>( + 0, numElements, + [&result, &uuidGen](size_t) { result.push_back(FuncConv(uuidGen())); }, + [context]() { context->cancellationHandle_->throwIfCancelled(); }); + return result; + } + + string getCacheKey( + [[maybe_unused]] const VariableToColumnMap& varColMap) const override { + return FuncKey(randId_); + } + + private: + std::span childrenImpl() override { return {}; } +}; + +} // namespace detail::uuidExpression + +using UuidExpression = detail::uuidExpression::UuidExpressionImpl< + detail::uuidExpression::fromIri, detail::uuidExpression::iriUuidKey>; +using StrUuidExpression = detail::uuidExpression::UuidExpressionImpl< + detail::uuidExpression::fromLiteral, detail::uuidExpression::litUuidKey>; + +} // namespace sparqlExpression diff --git a/src/global/Constants.h b/src/global/Constants.h index ad5a2ff99d..f4d0128211 100644 --- a/src/global/Constants.h +++ b/src/global/Constants.h @@ -23,7 +23,7 @@ static const ad_utility::MemorySize STXXL_DISK_SIZE_INDEX_BUILDER = 1_GB; static constexpr ad_utility::MemorySize DEFAULT_MEM_FOR_QUERIES = 4_GB; -static const size_t MAX_NOF_ROWS_IN_RESULT = 1'000'000; +constexpr uint64_t MAX_NOF_ROWS_IN_RESULT = 1'000'000; static const size_t MIN_WORD_PREFIX_SIZE = 4; static const char PREFIX_CHAR = '*'; @@ -60,6 +60,8 @@ static constexpr std::pair GEOF_PREFIX = { "geof:", "http://www.opengis.net/def/function/geosparql/"}; static constexpr std::pair MATH_PREFIX = { "math:", "http://www.w3.org/2005/xpath-functions/math#"}; +static constexpr std::pair XSD_PREFIX = { + "xsd", "http://www.w3.org/2001/XMLSchema#"}; static const std::string INTERNAL_VARIABLE_PREFIX = "?_QLever_internal_variable_"; @@ -75,6 +77,7 @@ static const std::string LANGUAGE_PREDICATE = makeInternalIri("langtag"); // TODO Move them to their own file, make them strings, remove // duplications, etc. +static const char XSD_STRING[] = "http://www.w3.org/2001/XMLSchema#string"; static const char XSD_DATETIME_TYPE[] = "http://www.w3.org/2001/XMLSchema#dateTime"; static const char XSD_DATE_TYPE[] = "http://www.w3.org/2001/XMLSchema#date"; @@ -110,6 +113,8 @@ static const char XSD_POSITIVE_INTEGER_TYPE[] = constexpr inline char XSD_BOOLEAN_TYPE[] = "http://www.w3.org/2001/XMLSchema#boolean"; static const char RDF_PREFIX[] = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; +static const char RDF_LANGTAG_STRING[] = + "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString"; static const std::string INTERNAL_VOCAB_SUFFIX = ".vocabulary.internal"; static const std::string EXTERNAL_VOCAB_SUFFIX = ".vocabulary.external"; diff --git a/src/global/IdTriple.h b/src/global/IdTriple.h new file mode 100644 index 0000000000..425fec2d10 --- /dev/null +++ b/src/global/IdTriple.h @@ -0,0 +1,12 @@ +// Copyright 2024, University of Freiburg +// Chair of Algorithms and Data Structures +// Authors: Hannah Bast + +#pragma once + +#include + +#include "global/Id.h" + +// Should we have an own class for this? We need this at several places. +using IdTriple = std::array; diff --git a/src/global/IndexTypes.h b/src/global/IndexTypes.h index adde06bbbc..a8bd21cba6 100644 --- a/src/global/IndexTypes.h +++ b/src/global/IndexTypes.h @@ -6,6 +6,7 @@ #define QLEVER_INDEXTYPES_H #include "./TypedIndex.h" +#include "parser/LiteralOrIri.h" // Typedefs for several kinds of typed indices that are used across QLever. @@ -14,13 +15,7 @@ // requests. using VocabIndex = ad_utility::TypedIndex; -// A `std::string` that is aligned to 16 bytes s.t. pointers always end with 4 -// bits that are zero and that are reused for payloads in the `ValueId` class. -struct alignas(16) StringAligned16 : public std::string { - using std::string::basic_string; - explicit StringAligned16(std::string s) : std::string{std::move(s)} {} -}; -using LocalVocabIndex = const StringAligned16*; +using LocalVocabIndex = const ad_utility::triple_component::LiteralOrIri*; using TextRecordIndex = ad_utility::TypedIndex; using WordVocabIndex = ad_utility::TypedIndex; using BlankNodeIndex = ad_utility::TypedIndex; diff --git a/src/global/RuntimeParameters.h b/src/global/RuntimeParameters.h index 5bea460cc9..1d23896032 100644 --- a/src/global/RuntimeParameters.h +++ b/src/global/RuntimeParameters.h @@ -46,7 +46,8 @@ inline auto& RuntimeParameters() { 30s}), SizeT<"lazy-index-scan-max-size-materialization">{1'000'000}, Bool<"use-binsearch-transitive-path">{true}, - Bool<"group-by-hash-map-enabled">{false}}; + Bool<"group-by-hash-map-enabled">{false}, + SizeT<"service-max-value-rows">{100}}; }(); return params; } diff --git a/src/global/ValueId.h b/src/global/ValueId.h index 1967bc83e7..121a2bd6d4 100644 --- a/src/global/ValueId.h +++ b/src/global/ValueId.h @@ -125,7 +125,7 @@ class ValueId { // NOTE: (Also for the operator<=> below: These comparisons only work // correctly if we only store entries in the local vocab that are NOT part of // the vocabulary. This is currently not true for expression results from - // GROUP BY and BIND operations (for performance reaons). So a join with such + // GROUP BY and BIND operations (for performance reasons). So a join with such // results will currently lead to wrong results. constexpr bool operator==(const ValueId& other) const { if (getDatatype() == Datatype::LocalVocabIndex && @@ -326,10 +326,15 @@ class ValueId { /// This operator is only for debugging and testing. It returns a /// human-readable representation. friend std::ostream& operator<<(std::ostream& ostr, const ValueId& id) { - ostr << toString(id.getDatatype()) << ':'; + ostr << toString(id.getDatatype())[0] << ':'; + if (id.getDatatype() == Datatype::Undefined) { + return ostr << id.getBits(); + } + auto visitor = [&ostr](T&& value) { if constexpr (ad_utility::isSimilar) { - ostr << "Undefined"; + // already handled above + AD_FAIL(); } else if constexpr (ad_utility::isSimilar || ad_utility::isSimilar) { ostr << std::to_string(value); @@ -339,7 +344,7 @@ class ValueId { ostr << value.toStringAndType().first; } else if constexpr (ad_utility::isSimilar) { AD_CORRECTNESS_CHECK(value != nullptr); - ostr << *value; + ostr << value->toStringRepresentation(); } else { // T is `VocabIndex | TextRecordIndex` ostr << std::to_string(value.get()); diff --git a/src/index/CompressedRelation.cpp b/src/index/CompressedRelation.cpp index 498cf741f4..b2d26c3b13 100644 --- a/src/index/CompressedRelation.cpp +++ b/src/index/CompressedRelation.cpp @@ -314,110 +314,19 @@ IdTable CompressedRelationReader::scan( auto columnIndices = prepareColumnIndices(scanSpec, additionalColumns); IdTable result(columnIndices.size(), allocator_); - // Get all the blocks that possibly might contain our pair of col0Id and - // col1Id + // Compute an upper bound for the size and reserve enough space in the result. auto relevantBlocks = getRelevantBlocks(scanSpec, blocks); - auto beginBlock = relevantBlocks.begin(); - auto endBlock = relevantBlocks.end(); - - // The first and the last block might be incomplete (that is, only - // a part of these blocks is actually part of the result, - // set up a lambda which allows us to read these blocks, and returns - // the result as a vector. - auto readIncompleteBlock = [&](const auto& block) { - return readPossiblyIncompleteBlock(scanSpec, block, std::nullopt, - columnIndices); - }; - - // The first and the last block might be incomplete, compute - // and store the partial results from them. - std::optional firstBlockResult; - std::optional lastBlockResult; - size_t totalResultSize = 0; - if (beginBlock < endBlock) { - firstBlockResult = readIncompleteBlock(*beginBlock); - totalResultSize += firstBlockResult.value().size(); - ++beginBlock; - cancellationHandle->throwIfCancelled(); - } - if (beginBlock < endBlock) { - lastBlockResult = readIncompleteBlock(*(endBlock - 1)); - totalResultSize += lastBlockResult.value().size(); - endBlock--; - cancellationHandle->throwIfCancelled(); + auto sizes = relevantBlocks | + std::views::transform(&CompressedBlockMetadata::numRows_); + auto upperBoundSize = std::accumulate(sizes.begin(), sizes.end(), 0ULL); + result.reserve(upperBoundSize); + + for (const auto& block : + lazyScan(scanSpec, {relevantBlocks.begin(), relevantBlocks.end()}, + {additionalColumns.begin(), additionalColumns.end()}, + cancellationHandle)) { + result.insertAtEnd(block); } - - // Determine the total size of the result. - // First accumulate the complete blocks in the "middle" - totalResultSize += std::accumulate(beginBlock, endBlock, 0UL, - [](const auto& count, const auto& block) { - return count + block.numRows_; - }); - result.resize(totalResultSize); - cancellationHandle->throwIfCancelled(); - - size_t rowIndexOfNextBlockStart = 0; - // Lambda that appends a possibly incomplete block (the first or last block) - // to the `result`. - auto addIncompleteBlockIfExists = - [&rowIndexOfNextBlockStart, &result]( - const std::optional& incompleteBlock) mutable { - if (!incompleteBlock.has_value()) { - return; - } - AD_CORRECTNESS_CHECK(incompleteBlock->numColumns() == - result.numColumns()); - for (auto i : ad_utility::integerRange(result.numColumns())) { - std::ranges::copy( - incompleteBlock->getColumn(i), - result.getColumn(i).data() + rowIndexOfNextBlockStart); - } - rowIndexOfNextBlockStart += incompleteBlock->numRows(); - }; - - addIncompleteBlockIfExists(firstBlockResult); - cancellationHandle->throwIfCancelled(); - - // Insert the complete blocks from the middle in parallel - if (beginBlock < endBlock) { -#pragma omp parallel -#pragma omp single - for (; beginBlock < endBlock; ++beginBlock) { - const auto& block = *beginBlock; - - // Read the block serially, only read the second column. - AD_CORRECTNESS_CHECK(block.offsetsAndCompressedSize_.size() >= 2); - CompressedBlock compressedBuffer = - readCompressedBlockFromFile(block, columnIndices); - - // A lambda that owns the compressed block decompresses it to the - // correct position in the result. It may safely be run in parallel - auto decompressLambda = [rowIndexOfNextBlockStart, &block, &result, - compressedBuffer = - std::move(compressedBuffer)]() mutable { - ad_utility::TimeBlockAndLog tbl{"Decompression a block"}; - - decompressBlockToExistingIdTable(compressedBuffer, block.numRows_, - result, rowIndexOfNextBlockStart); - }; - - // Register an OpenMP task that performs the decompression of this - // block in parallel -#pragma omp task - { - if (!cancellationHandle->isCancelled()) { - decompressLambda(); - } - } - - // update the pointers - rowIndexOfNextBlockStart += block.numRows_; - } // end of parallel region - } - cancellationHandle->throwIfCancelled(); - // Add the last block. - addIncompleteBlockIfExists(lastBlockResult); - AD_CORRECTNESS_CHECK(rowIndexOfNextBlockStart == result.size()); cancellationHandle->throwIfCancelled(); return result; } @@ -674,20 +583,6 @@ DecompressedBlock CompressedRelationReader::decompressBlock( return decompressedBlock; } -// ____________________________________________________________________________ -void CompressedRelationReader::decompressBlockToExistingIdTable( - const CompressedBlock& compressedBlock, size_t numRowsToRead, - IdTable& table, size_t offsetInTable) { - AD_CORRECTNESS_CHECK(table.numRows() >= offsetInTable + numRowsToRead); - // TODO use zip_view. - AD_CORRECTNESS_CHECK(compressedBlock.size() == table.numColumns()); - for (size_t i = 0; i < compressedBlock.size(); ++i) { - auto col = table.getColumn(i); - decompressColumn(compressedBlock[i], numRowsToRead, - col.data() + offsetInTable); - } -} - // ____________________________________________________________________________ template void CompressedRelationReader::decompressColumn( diff --git a/src/index/CompressedRelation.h b/src/index/CompressedRelation.h index de94bd743c..1acfb7ebe3 100644 --- a/src/index/CompressedRelation.h +++ b/src/index/CompressedRelation.h @@ -522,7 +522,7 @@ class CompressedRelationReader { // Get the first and the last triple that the result of a `scan` with the // given arguments would lead to. Throw an exception if the scan result would // be empty. This function is used to more efficiently filter the blocks of - // index scans between joining them to get better estimates for the begginning + // index scans between joining them to get better estimates for the beginning // and end of incomplete blocks. MetadataAndBlocks::FirstAndLastTriple getFirstAndLastTriple( const MetadataAndBlocks& metadataAndBlocks) const; @@ -544,14 +544,6 @@ class CompressedRelationReader { DecompressedBlock decompressBlock(const CompressedBlock& compressedBlock, size_t numRowsToRead) const; - // Similar to `decompressBlock`, but the block is directly decompressed into - // the `table`, starting at the `offsetInTable`-th row. The `table` and the - // `compressedBlock` must have the same number of columns, and the `table` - // must have at least `numRowsToRead + offsetInTable` rows. - static void decompressBlockToExistingIdTable( - const CompressedBlock& compressedBlock, size_t numRowsToRead, - IdTable& table, size_t offsetInTable); - // Helper function used by `decompressBlock` and // `decompressBlockToExistingIdTable`. Decompress the `compressedColumn` and // store the result at the `iterator`. For the `numRowsToRead` argument, see diff --git a/src/index/ConstantsIndexBuilding.h b/src/index/ConstantsIndexBuilding.h index 7ce99a6648..dd65b5cd7c 100644 --- a/src/index/ConstantsIndexBuilding.h +++ b/src/index/ConstantsIndexBuilding.h @@ -39,7 +39,7 @@ inline std::atomic BUFFER_SIZE_JOIN_PATTERNS_WITH_OSP = 50'000; // before they are written to the output. inline std::atomic BATCH_SIZE_VOCABULARY_MERGE = 10'000'000; -// When the BZIP2 parser encouters a parsing exception it will increase its +// When the BZIP2 parser encounters a parsing exception it will increase its // buffer and try again (we have no other way currently to determine if the // exception was "real" or only because we cut a statement in the middle. Once // it holds this many bytes in total, it will assume that there was indeed an @@ -82,7 +82,7 @@ constexpr size_t QUEUE_SIZE_BEFORE_PARALLEL_PARSING = 10; constexpr size_t QUEUE_SIZE_AFTER_PARALLEL_PARSING = 10; // The blocksize parameter of the parallel vocabulary merging. Higher values -// mean higher memory consumption, wherease a too low value will impact the +// mean higher memory consumption, whereas a too low value will impact the // performance negatively. static constexpr size_t BLOCKSIZE_VOCABULARY_MERGING = 100; diff --git a/src/index/Index.h b/src/index/Index.h index 60d19ba7eb..48c2717687 100644 --- a/src/index/Index.h +++ b/src/index/Index.h @@ -134,8 +134,8 @@ class Index { [[nodiscard]] const CompactVectorOfStrings& getPatterns() const; /** - * @return The multiplicity of the entites column (0) of the full has-relation - * relation after unrolling the patterns. + * @return The multiplicity of the entities column (0) of the full + * has-relation relation after unrolling the patterns. */ [[nodiscard]] double getAvgNumDistinctPredicatesPerSubject() const; diff --git a/src/index/IndexImpl.Text.cpp b/src/index/IndexImpl.Text.cpp index 6fd591b47e..68d1ab87d0 100644 --- a/src/index/IndexImpl.Text.cpp +++ b/src/index/IndexImpl.Text.cpp @@ -25,7 +25,7 @@ namespace { // Custom delimiter class for tokenization of literals using `absl::StrSplit`. // The `Find` function returns the next delimiter in `text` after the given -// `pos` or an empty subtring if there is no next delimiter. +// `pos` or an empty substring if there is no next delimiter. struct LiteralsTokenizationDelimiter { absl::string_view Find(absl::string_view text, size_t pos) { auto isWordChar = [](char c) -> bool { return std::isalnum(c); }; @@ -56,8 +56,8 @@ cppcoro::generator IndexImpl::wordsInTextRecords( contextId = contextId.incremented(); } } - // ROUND 2: Optionally, consider each literal from the interal vocabulary as a - // text record. + // ROUND 2: Optionally, consider each literal from the internal vocabulary as + // a text record. if (addWordsFromLiterals) { for (VocabIndex index = VocabIndex::make(0); index.get() < vocab_.size(); index = index.incremented()) { diff --git a/src/index/IndexImpl.cpp b/src/index/IndexImpl.cpp index 705dc182dc..49b55cb763 100644 --- a/src/index/IndexImpl.cpp +++ b/src/index/IndexImpl.cpp @@ -33,10 +33,10 @@ using std::array; using namespace ad_utility::memory_literals; -// During the index building we typically have two permutation sortings present -// at the same time, as we directly push the triples from the first sorting to -// the second sorting. We therefore have to adjust the amount of memory per -// external sorter. +// During the index building we typically have two permutations present at the +// same time, as we directly push the triples from the first sorting to the +// second sorting. We therefore have to adjust the amount of memory per external +// sorter. static constexpr size_t NUM_EXTERNAL_SORTERS_AT_SAME_TIME = 2u; // _____________________________________________________________________________ @@ -152,7 +152,7 @@ std::unique_ptr> IndexImpl::buildOspWithPatterns( // the additional permutation. hasPatternPredicateSortedByPSO->moveResultOnMerge() = false; // The column with index 1 always is `has-predicate` and is not needed here. - // Note that the order of the columns during index building is alwasy `SPO`, + // Note that the order of the columns during index building is always `SPO`, // but the sorting might be different (PSO in this case). auto lazyPatternScan = lazyScanWithPermutedColumns( hasPatternPredicateSortedByPSO, std::array{0, 2}); @@ -679,10 +679,12 @@ IndexImpl::createPermutations(size_t numColumns, auto&& sortedTriples, } // ________________________________________________________________________ -size_t IndexImpl::createPermutationPair(size_t numColumns, auto&& sortedTriples, +template +size_t IndexImpl::createPermutationPair(size_t numColumns, + SortedTriplesType&& sortedTriples, const Permutation& p1, const Permutation& p2, - auto&&... perTripleCallbacks) { + CallbackTypes&&... perTripleCallbacks) { auto [numDistinctC0, metaData1, metaData2] = createPermutations( numColumns, AD_FWD(sortedTriples), p1, p2, AD_FWD(perTripleCallbacks)...); // Set the name of this newly created pair of `IndexMetaData` objects. @@ -1377,7 +1379,7 @@ IdTable IndexImpl::scan( if (!col0Id.has_value() || (col1String.has_value() && !col1Id.has_value())) { size_t numColumns = col1String.has_value() ? 1 : 2; cancellationHandle->throwIfCancelled(); - return IdTable{numColumns, allocator_}; + return IdTable{numColumns + additionalColumns.size(), allocator_}; } return scan(col0Id.value(), col1Id, permutation, additionalColumns, cancellationHandle); @@ -1416,7 +1418,7 @@ namespace { // Return a lambda that is called repeatedly with triples that are sorted by the // `idx`-th column and counts the number of distinct entities that occur in a // triple where none of the elements fulfills the `isQleverInternalId` -// predicate. This is used to cound the number of distinct subjects, objects, +// predicate. This is used to count the number of distinct subjects, objects, // and predicates during the index building. template auto makeNumDistinctIdsCounter = diff --git a/src/index/IndexImpl.h b/src/index/IndexImpl.h index 46c01e47c6..10c6ff0c79 100644 --- a/src/index/IndexImpl.h +++ b/src/index/IndexImpl.h @@ -12,7 +12,7 @@ #include #include -#include "engine/ResultTable.h" +#include "engine/Result.h" #include "engine/idTable/CompressedExternalIdTable.h" #include "global/Pattern.h" #include "global/SpecialIds.h" @@ -272,8 +272,8 @@ class IndexImpl { const CompactVectorOfStrings& getPatterns() const; /** - * @return The multiplicity of the Entites column (0) of the full has-relation - * relation after unrolling the patterns. + * @return The multiplicity of the Entities column (0) of the full + * has-relation relation after unrolling the patterns. */ double getAvgNumDistinctPredicatesPerSubject() const; @@ -490,17 +490,20 @@ class IndexImpl { // OSP-OPS, SPO-SOP). First creates the permutation and then exchanges the // multiplicities and also writes the MetaData to disk. So we end up with // fully functional permutations. + // + // TODO: The rest of this comment looks outdated. + // // performUnique must be set for the first pair created using vec to enforce // RDF standard (no duplicate triples). // createPatternsAfterFirst is only valid when the pair is SPO-SOP because // the SPO permutation is also needed for patterns (see usage in // IndexImpl::createFromFile function) - [[nodiscard]] size_t createPermutationPair(size_t numColumns, - auto&& sortedTriples, - const Permutation& p1, - const Permutation& p2, - auto&&... perTripleCallbacks); + template + [[nodiscard]] size_t createPermutationPair( + size_t numColumns, SortedTriplesType&& sortedTriples, + const Permutation& p1, const Permutation& p2, + CallbackTypes&&... perTripleCallbacks); // wrapper for createPermutation that saves a lot of code duplications // Writes the permutation that is specified by argument permutation @@ -608,7 +611,7 @@ class IndexImpl { private: /** * @brief Throws an exception if no patterns are loaded. Should be called from - * whithin any index method that returns data requiring the patterns + * within any index method that returns data requiring the patterns * file. */ void throwExceptionIfNoPatterns() const; diff --git a/src/index/IndexMetaData.h b/src/index/IndexMetaData.h index fca769d644..a3b4cdccd6 100644 --- a/src/index/IndexMetaData.h +++ b/src/index/IndexMetaData.h @@ -1,6 +1,7 @@ // Copyright 2015, University of Freiburg, // Chair of Algorithms and Data Structures. // Author: Björn Buchhold (buchhold@informatik.uni-freiburg.de) + #pragma once #include @@ -13,14 +14,14 @@ #include #include -#include "../global/Id.h" -#include "../util/File.h" -#include "../util/HashMap.h" -#include "../util/MmapVector.h" -#include "../util/ReadableNumberFact.h" -#include "../util/Serializer/Serializer.h" -#include "./MetaDataHandler.h" -#include "CompressedRelation.h" +#include "global/Id.h" +#include "index/CompressedRelation.h" +#include "index/MetaDataHandler.h" +#include "util/File.h" +#include "util/HashMap.h" +#include "util/MmapVector.h" +#include "util/ReadableNumberFact.h" +#include "util/Serializer/Serializer.h" using std::array; using std::pair; @@ -109,8 +110,8 @@ class IndexMetaData { // `isPersistentMetaData` is true when we do not need to add relation meta // data to data_, but assume that it is already contained in data_. This must - // be a compile time parameter because we have to avoid instantation of member - // function set() when `MapType` is read only (e.g., when based on + // be a compile time parameter because we have to avoid instantiation of + // member function set() when `MapType` is read only (e.g., when based on // MmapVectorView). template void add(AddType addedValue); @@ -131,7 +132,7 @@ class IndexMetaData { static const bool value = std::is_same::value || std::is_same::value; }; - // Compile time information whether this instatiation if MMapBased or not + // Compile time information whether this instantiation if MMapBased or not static constexpr bool isMmapBased_ = IsMmapBased::value; // This magic number is written when serializing the IndexMetaData to a file. @@ -218,7 +219,8 @@ template ad_utility::File& operator<<(ad_utility::File& f, const IndexMetaData& imd); -// aliases for easier use in Index class +// Aliases for easier use in classes that build or query permutations, like +// `IndexImpl`. using MetaWrapperMmap = MetaDataWrapperDense>; using MetaWrapperMmapView = MetaDataWrapperDense< diff --git a/src/index/MetaDataHandler.h b/src/index/MetaDataHandler.h index da84f1158a..1060f1143d 100644 --- a/src/index/MetaDataHandler.h +++ b/src/index/MetaDataHandler.h @@ -1,24 +1,40 @@ -// Copyright 2018, University of Freiburg, +// Copyright 2018 - 2023, University of Freiburg // Chair of Algorithms and Data Structures -// Author: Johannes Kalmbach (johannes.kalmbach@gmail.com) -// +// Authors: Johannes Kalmbach +// Hannah Bast + #pragma once #include #include -#include "../global/Id.h" -#include "../util/Exception.h" -#include "../util/HashMap.h" -#include "../util/Iterators.h" -#include "../util/Log.h" -#include "../util/Serializer/Serializer.h" -#include "./CompressedRelation.h" - -// _____________________________________________________________________ +#include "global/Id.h" +#include "index/CompressedRelation.h" +#include "util/Exception.h" +#include "util/HashMap.h" +#include "util/Iterators.h" +#include "util/Log.h" +#include "util/Serializer/Serializer.h" + +// Wrapper class for access to `CompressedRelationMetadata` objects (one per +// relation) stored in a vector. Specifically, our index uses this with `M = +// MmapVector>`; see `index/IndexMetaData.h` at the +// bottom. +// +// TODO: We needed this at some point because we used to have two implementation +// of `IndexMetaData`, one using mmaps and one using hash maps, and we wanted to +// have a common interface for both. We no longer use the hash map +// implementation and so the wrapper class (and the complexity that goes along +// with it) is probably no longer needed. template class MetaDataWrapperDense { + private: + // A vector of metadata objects. + M _vec; + public: + // An iterator with an additional method `getId()` that gives the relation ID + // of the current metadata object. template struct AddGetIdIterator : BaseIterator { using BaseIterator::BaseIterator; @@ -39,6 +55,7 @@ class MetaDataWrapperDense { // The underlying array is sorted, so all iterators are ordered iterators using ConstOrderedIterator = ConstIterator; + // The type of the stored metadata objects. using value_type = typename M::value_type; // _________________________________________________________ @@ -51,7 +68,7 @@ class MetaDataWrapperDense { MetaDataWrapperDense& operator=(MetaDataWrapperDense&& other) = default; // Templated setup version - // Arguments are passsed through to template argument M. + // Arguments are passed through to template argument M. // TODO: enable_if for better error messages template void setup(Args... args) { @@ -88,7 +105,7 @@ class MetaDataWrapperDense { // ____________________________________________________________ void set(Id id, const value_type& value) { - // Assert that the ids are ascending. + // Check that the `Id`s are added in strictly ascending order. AD_CONTRACT_CHECK(_vec.size() == 0 || _vec.back().col0Id_ < id); _vec.push_back(value); } @@ -116,5 +133,10 @@ class MetaDataWrapperDense { }; return std::lower_bound(_vec.begin(), _vec.end(), id, cmp); } - M _vec; + Iterator lower_bound(Id id) { + auto cmp = [](const auto& metaData, Id id) { + return metaData.col0Id_ < id; + }; + return std::lower_bound(_vec.begin(), _vec.end(), id, cmp); + } }; diff --git a/src/index/PatternCreator.h b/src/index/PatternCreator.h index 02349ef40b..7a044c5e34 100644 --- a/src/index/PatternCreator.h +++ b/src/index/PatternCreator.h @@ -111,8 +111,8 @@ class PatternCreator { ad_utility::BufferedVector tripleBuffer_; TripleSorter tripleSorter_; - // The predicates which have already occured in one of the patterns. Needed to - // count the number of distinct predicates. + // The predicates which have already occurred in one of the patterns. Needed + // to count the number of distinct predicates. ad_utility::HashSet distinctPredicates_; // The number of distinct subjects and distinct subject-predicate pairs. diff --git a/src/index/PrefixHeuristic.cpp b/src/index/PrefixHeuristic.cpp index 47ab3821ae..2353362f9c 100644 --- a/src/index/PrefixHeuristic.cpp +++ b/src/index/PrefixHeuristic.cpp @@ -84,7 +84,7 @@ TreeNode* TreeNode::insert(string_view value) { // ___________________________________________________________________________ std::pair TreeNode::getMaximum(size_t codelength) { - // _sharedCount = _ownCount + sum over childrens _sharedCount + // _sharedCount = _ownCount + sum over childrens' _sharedCount _sharedCount = _ownCount; // get Maximum score and node from all the children @@ -118,7 +118,7 @@ std::pair TreeNode::getMaximum(size_t codelength) { _score = _sharedCount * relevantLength; - // Check if our own score is greater than any of the childrens + // Check if our own score is greater than the score any of the childrens' // we choose >= so we get a valid pointer when there is only the root with // score 0 left. if (_score >= maxScore) { diff --git a/src/index/PrefixHeuristic.h b/src/index/PrefixHeuristic.h index c812429989..a7c783a050 100644 --- a/src/index/PrefixHeuristic.h +++ b/src/index/PrefixHeuristic.h @@ -21,7 +21,7 @@ // be added to every word, no matter if it is // actually compressed. (This is true for the // vocabulary in QLever). The Algorithm has to know -// this in order to chosse the correct prefixes. +// this in order to choose the correct prefixes. // // Returns: Vector of suitable prefixes which have been selected by the // algorithm diff --git a/src/index/vocabulary/CombinedVocabulary.h b/src/index/vocabulary/CombinedVocabulary.h index 117e9c2fa6..fb1efb76fc 100644 --- a/src/index/vocabulary/CombinedVocabulary.h +++ b/src/index/vocabulary/CombinedVocabulary.h @@ -136,7 +136,7 @@ class CombinedVocabulary { } // Return a global ID (sometimes just an index) that is the largest global ID - // occuring in either of the underlying vocabularies plus 1. This ID can be + // occurring in either of the underlying vocabularies plus 1. This ID can be // used as the "end" ID to indicate "not found". [[nodiscard]] uint64_t getEndIndex() const { uint64_t endA = _firstVocab.size() == 0 diff --git a/src/parser/Iri.cpp b/src/parser/Iri.cpp index 0fd8254f89..9b5a70d91a 100644 --- a/src/parser/Iri.cpp +++ b/src/parser/Iri.cpp @@ -10,20 +10,20 @@ #include "util/StringUtils.h" namespace ad_utility::triple_component { -// __________________________________________ +// ____________________________________________________________________________ Iri::Iri(std::string iri) : iri_{std::move(iri)} {} -// __________________________________________ +// ____________________________________________________________________________ Iri::Iri(const Iri& prefix, NormalizedStringView suffix) : iri_{absl::StrCat("<"sv, asStringViewUnsafe(prefix.getContent()), asStringViewUnsafe(suffix), ">"sv)} {}; -// __________________________________________ +// ____________________________________________________________________________ NormalizedStringView Iri::getContent() const { return asNormalizedStringViewUnsafe(iri_).substr(1, iri_.size() - 2); } -// __________________________________________ +// ____________________________________________________________________________ Iri Iri::fromIriref(std::string_view stringWithBrackets) { auto first = stringWithBrackets.find('<'); AD_CORRECTNESS_CHECK(first != std::string_view::npos); @@ -34,21 +34,29 @@ Iri Iri::fromIriref(std::string_view stringWithBrackets) { ">"sv)}; } -// __________________________________________ +// ____________________________________________________________________________ +Iri Iri::fromIrirefWithoutBrackets(std::string_view stringWithoutBrackets) { + AD_CORRECTNESS_CHECK(!stringWithoutBrackets.starts_with('<') && + !stringWithoutBrackets.ends_with('>')); + return Iri{absl::StrCat("<"sv, stringWithoutBrackets, ">"sv)}; +} + +// ____________________________________________________________________________ Iri Iri::fromPrefixAndSuffix(const Iri& prefix, std::string_view suffix) { auto suffixNormalized = RdfEscaping::unescapePrefixedIri(suffix); return Iri{prefix, asNormalizedStringViewUnsafe(suffixNormalized)}; } -// __________________________________________ +// ____________________________________________________________________________ Iri Iri::fromStringRepresentation(std::string s) { AD_CORRECTNESS_CHECK(s.starts_with("<") || s.starts_with("@")); return Iri{std::move(s)}; } -// __________________________________________ +// ____________________________________________________________________________ const std::string& Iri::toStringRepresentation() const { return iri_; } -// __________________________________________ + +// ____________________________________________________________________________ std::string& Iri::toStringRepresentation() { return iri_; } } // namespace ad_utility::triple_component diff --git a/src/parser/Iri.h b/src/parser/Iri.h index 69f3ee8085..6ccdfa29b6 100644 --- a/src/parser/Iri.h +++ b/src/parser/Iri.h @@ -39,6 +39,9 @@ class Iri { // Create a new iri given an iri with brackets static Iri fromIriref(std::string_view stringWithBrackets); + // create a new iri given an iri without brackets + static Iri fromIrirefWithoutBrackets(std::string_view stringWithoutBrackets); + // Create a new iri given a prefix iri and its suffix static Iri fromPrefixAndSuffix(const Iri& prefix, std::string_view suffix); diff --git a/src/parser/LiteralOrIri.h b/src/parser/LiteralOrIri.h index 5a6724a15d..b617dfd99d 100644 --- a/src/parser/LiteralOrIri.h +++ b/src/parser/LiteralOrIri.h @@ -18,7 +18,7 @@ static constexpr char iriPrefixChar = '<'; static constexpr std::string_view iriPrefix{&iriPrefixChar, 1}; static constexpr std::string_view literalPrefix{&literalPrefixChar, 1}; // A wrapper class that can contain either an Iri or a Literal object. -class LiteralOrIri { +class alignas(16) LiteralOrIri { private: using LiteralOrIriVariant = std::variant; LiteralOrIriVariant data_; @@ -46,12 +46,11 @@ class LiteralOrIri { static LiteralOrIri fromStringRepresentation(std::string internal) { char tag = internal.front(); - if (tag == iriPrefixChar) { - return LiteralOrIri{Iri::fromStringRepresentation(std::move(internal))}; - } else { - AD_CORRECTNESS_CHECK(tag == literalPrefixChar); + if (tag == literalPrefixChar) { return LiteralOrIri{ Literal::fromStringRepresentation(std::move(internal))}; + } else { + return LiteralOrIri{Iri::fromStringRepresentation(std::move(internal))}; } } template @@ -61,6 +60,11 @@ class LiteralOrIri { } bool operator==(const LiteralOrIri&) const = default; + auto operator<=>(const LiteralOrIri& rhs) const { + // TODO Use something unicode-based for this. + return toStringRepresentation() <=> rhs.toStringRepresentation(); + } + // Return true if object contains an Iri object bool isIri() const; diff --git a/src/parser/ParallelBuffer.h b/src/parser/ParallelBuffer.h index fda663b0c6..79eb8f55c1 100644 --- a/src/parser/ParallelBuffer.h +++ b/src/parser/ParallelBuffer.h @@ -39,7 +39,7 @@ class ParallelBuffer { */ virtual void open(const string& filename) = 0; /** - * @brief Get (approximately) the next blocksize_ bytes from the inut stream. + * @brief Get (approximately) the next blocksize_ bytes from the input stream. * * Only valid after a call to open(). * diff --git a/src/parser/ParsedQuery.cpp b/src/parser/ParsedQuery.cpp index 7dcd07f39f..5c480e4a34 100644 --- a/src/parser/ParsedQuery.cpp +++ b/src/parser/ParsedQuery.cpp @@ -292,7 +292,7 @@ void ParsedQuery::GraphPattern::addLanguageFilter(const Variable& variable, // If necessary create an empty `BasicGraphPattern` at the end to which we // can append a triple. // TODO It might be beneficial to place this triple not at the - // end but close to other occurences of `variable`. + // end but close to other occurrences of `variable`. if (_graphPatterns.empty() || !std::holds_alternative( _graphPatterns.back())) { diff --git a/src/parser/ParsedQuery.h b/src/parser/ParsedQuery.h index 2b8dd8320c..4201a3c783 100644 --- a/src/parser/ParsedQuery.h +++ b/src/parser/ParsedQuery.h @@ -18,6 +18,7 @@ #include "parser/PropertyPath.h" #include "parser/SelectClause.h" #include "parser/TripleComponent.h" +#include "parser/UpdateClause.h" #include "parser/data/GroupKey.h" #include "parser/data/LimitOffsetClause.h" #include "parser/data/OrderKey.h" @@ -49,75 +50,8 @@ class SparqlPrefix { bool operator==(const SparqlPrefix&) const = default; }; -inline bool isVariable(const string& elem) { return elem.starts_with("?"); } -inline bool isVariable(const TripleComponent& elem) { - return elem.isVariable(); -} - -inline bool isVariable(const PropertyPath& elem) { - return elem._operation == PropertyPath::Operation::IRI && - isVariable(elem._iri); -} - std::ostream& operator<<(std::ostream& out, const PropertyPath& p); -// Data container for parsed triples from the where clause. -// It is templated on the predicate type, see the instantiations below. -template -class SparqlTripleBase { - public: - using AdditionalScanColumns = std::vector>; - SparqlTripleBase(TripleComponent s, Predicate p, TripleComponent o, - AdditionalScanColumns additionalScanColumns = {}) - : s_(std::move(s)), - p_(std::move(p)), - o_(std::move(o)), - additionalScanColumns_(std::move(additionalScanColumns)) {} - - bool operator==(const SparqlTripleBase& other) const = default; - TripleComponent s_; - Predicate p_; - TripleComponent o_; - // The additional columns (e.g. patterns) that are to be attached when - // performing an index scan using this triple. - // TODO On this level we should not store `ColumnIndex`, but the - // special predicate IRIs that are to be attached here. - std::vector> additionalScanColumns_; -}; - -// A triple where the predicate is a `TripleComponent`, so a fixed entity or a -// variable, but not a property path. -class SparqlTripleSimple : public SparqlTripleBase { - using Base = SparqlTripleBase; - using Base::Base; -}; - -// A triple where the predicate is a `PropertyPath` (which technically still -// might be a variable or fixed entity in the current implementation). -class SparqlTriple : public SparqlTripleBase { - public: - using Base = SparqlTripleBase; - using Base::Base; - - // ___________________________________________________________________________ - SparqlTriple(TripleComponent s, const std::string& p_iri, TripleComponent o) - : Base{std::move(s), PropertyPath::fromIri(p_iri), std::move(o)} {} - - // ___________________________________________________________________________ - [[nodiscard]] string asString() const; - - // Convert to a simple triple. Fails with an exception if the predicate - // actually is a property path. - SparqlTripleSimple getSimple() const { - AD_CONTRACT_CHECK(p_.isIri()); - TripleComponent p = - isVariable(p_._iri) - ? TripleComponent{Variable{p_._iri}} - : TripleComponent(TripleComponent::Iri::fromIriref(p_._iri)); - return {s_, p, o_, additionalScanColumns_}; - } -}; - // Forward declaration namespace parsedQuery { struct GraphPatternOperation; @@ -132,6 +66,8 @@ class ParsedQuery { using ConstructClause = parsedQuery::ConstructClause; + using UpdateClause = parsedQuery::UpdateClause; + ParsedQuery() = default; GraphPattern _rootGraphPattern; @@ -147,7 +83,8 @@ class ParsedQuery { // explicit default initialisation because the constructor // of SelectClause is private - std::variant _clause{SelectClause{}}; + std::variant _clause{ + SelectClause{}}; [[nodiscard]] bool hasSelectClause() const { return std::holds_alternative(_clause); @@ -157,6 +94,10 @@ class ParsedQuery { return std::holds_alternative(_clause); } + [[nodiscard]] bool hasUpdateClause() const { + return std::holds_alternative(_clause); + } + [[nodiscard]] decltype(auto) selectClause() const { return std::get(_clause); } @@ -165,6 +106,10 @@ class ParsedQuery { return std::get(_clause); } + [[nodiscard]] decltype(auto) updateClause() const { + return std::get(_clause); + } + [[nodiscard]] decltype(auto) selectClause() { return std::get(_clause); } @@ -173,6 +118,10 @@ class ParsedQuery { return std::get(_clause); } + [[nodiscard]] decltype(auto) updateClause() { + return std::get(_clause); + } + // Add a variable, that was found in the query body. void registerVariableVisibleInQueryBody(const Variable& variable); diff --git a/src/parser/SelectClause.cpp b/src/parser/SelectClause.cpp index bb32be05e0..92ec043c26 100644 --- a/src/parser/SelectClause.cpp +++ b/src/parser/SelectClause.cpp @@ -103,6 +103,6 @@ void SelectClause::deleteAliasesButKeepVariables() { } auto& varsAndAliases = std::get(varsAndAliasesOrAsterisk_); // The variables that the aliases are bound to have previously been stored - // seperately in `varsAndAliases.vars_`, so we can simply delete the aliases. + // separately in `varsAndAliases.vars_`, so we can simply delete the aliases. varsAndAliases.aliases_.clear(); } diff --git a/src/parser/SparqlParser.cpp b/src/parser/SparqlParser.cpp index df941955ae..f19ecd6fe3 100644 --- a/src/parser/SparqlParser.cpp +++ b/src/parser/SparqlParser.cpp @@ -17,7 +17,8 @@ ParsedQuery SparqlParser::parseQuery(std::string query) { // Note: `AntlrParser::query` is a method of `AntlrParser` (which is an alias // for `SparqlAutomaticParser`) that returns the `QueryContext*` for the whole // query. - auto resultOfParseAndRemainingText = p.parseTypesafe(&AntlrParser::query); + auto resultOfParseAndRemainingText = + p.parseTypesafe(&AntlrParser::queryOrUpdate); // The query rule ends with so the parse always has to consume the whole // input. If this is not the case a ParseException should have been thrown at // an earlier point. diff --git a/src/parser/SparqlTriple.h b/src/parser/SparqlTriple.h new file mode 100644 index 0000000000..0efe19b8bd --- /dev/null +++ b/src/parser/SparqlTriple.h @@ -0,0 +1,91 @@ +// Copyright 2024, University of Freiburg, +// Chair of Algorithms and Data Structures. +// Authors: Björn Buchhold (buchhold@informatik.uni-freiburg.de) +// Johannes Kalmbach + +#pragma once + +#include + +#include "PropertyPath.h" +#include "TripleComponent.h" +#include "global/Id.h" +#include "parser/data/Variable.h" + +inline bool isVariable(const string& elem) { return elem.starts_with("?"); } +inline bool isVariable(const TripleComponent& elem) { + return elem.isVariable(); +} + +inline bool isVariable(const PropertyPath& elem) { + return elem._operation == PropertyPath::Operation::IRI && + isVariable(elem._iri); +} + +// Data container for parsed triples from the where clause. +// It is templated on the predicate type, see the instantiations below. +template +class SparqlTripleBase { + public: + using AdditionalScanColumns = std::vector>; + SparqlTripleBase(TripleComponent s, Predicate p, TripleComponent o, + AdditionalScanColumns additionalScanColumns = {}) + : s_(std::move(s)), + p_(std::move(p)), + o_(std::move(o)), + additionalScanColumns_(std::move(additionalScanColumns)) {} + + bool operator==(const SparqlTripleBase& other) const = default; + TripleComponent s_; + Predicate p_; + TripleComponent o_; + // The additional columns (e.g. patterns) that are to be attached when + // performing an index scan using this triple. + // TODO On this level we should not store `ColumnIndex`, but the + // special predicate IRIs that are to be attached here. + std::vector> additionalScanColumns_; +}; + +// A triple where the predicate is a `TripleComponent`, so a fixed entity or a +// variable, but not a property path. +class SparqlTripleSimple : public SparqlTripleBase { + using Base = SparqlTripleBase; + using Base::Base; +}; + +// A triple where the predicate is a `PropertyPath` (which technically still +// might be a variable or fixed entity in the current implementation). +class SparqlTriple : public SparqlTripleBase { + public: + using Base = SparqlTripleBase; + using Base::Base; + + // ___________________________________________________________________________ + SparqlTriple(TripleComponent s, const std::string& iri, TripleComponent o) + : Base{std::move(s), PropertyPath::fromIri(iri), std::move(o)} {} + + // ___________________________________________________________________________ + [[nodiscard]] string asString() const; + + // Convert to a simple triple. Fails with an exception if the predicate + // actually is a property path. + SparqlTripleSimple getSimple() const { + AD_CONTRACT_CHECK(p_.isIri()); + TripleComponent p = + isVariable(p_._iri) + ? TripleComponent{Variable{p_._iri}} + : TripleComponent(TripleComponent::Iri::fromIriref(p_._iri)); + return {s_, p, o_, additionalScanColumns_}; + } + + // Constructs SparqlTriple from a simple triple. Fails with an exception if + // the predicate is neither a variable nor an iri. + static SparqlTriple fromSimple(const SparqlTripleSimple& triple) { + AD_CONTRACT_CHECK(triple.p_.isVariable() || triple.p_.isIri()); + PropertyPath p = triple.p_.isVariable() + ? PropertyPath::fromVariable(triple.p_.getVariable()) + : PropertyPath::fromIri( + triple.p_.getIri().toStringRepresentation()); + return {triple.s_, p, triple.o_}; + } +}; diff --git a/src/parser/Tokenizer.h b/src/parser/Tokenizer.h index 7d97bdcd09..74701f3afa 100644 --- a/src/parser/Tokenizer.h +++ b/src/parser/Tokenizer.h @@ -211,7 +211,7 @@ struct SkipWhitespaceAndCommentsMixin { void skipWhitespaceAndComments() { // Call `skipWhitespace` and `skipComments` in a loop until no more input // was consumed. This is necessary because we might have multiple lines of - // comments that are spearated by whitespace. + // comments that are separated by whitespace. while (true) { bool a = skipWhitespace(); bool b = skipComments(); diff --git a/src/parser/TokenizerCtre.h b/src/parser/TokenizerCtre.h index 6bded41e55..1801b448f1 100644 --- a/src/parser/TokenizerCtre.h +++ b/src/parser/TokenizerCtre.h @@ -330,10 +330,10 @@ class TokenizerCtre : public SkipWhitespaceAndCommentsMixin { } /* - * The helper struct used for the intenal apply function + * The helper struct used for the internal apply function * Its static function process(string_view) * tries to match a prefix of the string_view with the regex and returns - * on sucess and on failure + * on success and on failure */ struct Matcher { template diff --git a/src/parser/TripleComponent.h b/src/parser/TripleComponent.h index 3eb6dfb8ac..85fe3788f7 100644 --- a/src/parser/TripleComponent.h +++ b/src/parser/TripleComponent.h @@ -219,22 +219,19 @@ class TripleComponent { if (!id) { // If `toValueId` could not convert to `Id`, we have a string, which we // look up in (and potentially add to) our local vocabulary. - AD_CORRECTNESS_CHECK(isString() || isLiteral() || isIri()); - std::string& newWord = [&]() -> std::string& { - if (isString()) { - return getString(); + AD_CORRECTNESS_CHECK(isLiteral() || isIri()); + using LiteralOrIri = ad_utility::triple_component::LiteralOrIri; + auto moveWord = [&]() -> LiteralOrIri { + if (isLiteral()) { + return LiteralOrIri{std::move(getLiteral())}; } else { - if (isLiteral()) { - return getLiteral().toStringRepresentation(); - } else { - return getIri().toStringRepresentation(); - } + return LiteralOrIri{std::move(getIri())}; } - }(); + }; // NOTE: There is a `&&` version of `getIndexAndAddIfNotContained`. // Otherwise, `newWord` would be copied here despite the `std::move`. id = Id::makeFromLocalVocabIndex( - localVocab.getIndexAndAddIfNotContained(std::move(newWord))); + localVocab.getIndexAndAddIfNotContained(moveWord())); } return id.value(); } diff --git a/src/parser/TurtleParser.cpp b/src/parser/TurtleParser.cpp index bdd7dbb096..c2496070bb 100644 --- a/src/parser/TurtleParser.cpp +++ b/src/parser/TurtleParser.cpp @@ -697,7 +697,7 @@ bool TurtleStreamParser::resetStateAndRead( byteVec_ = std::move(buf); tok_.reset(byteVec_.data(), byteVec_.size()); - LOG(TRACE) << "Succesfully decompressed next batch of " << nextBytes.size() + LOG(TRACE) << "Successfully decompressed next batch of " << nextBytes.size() << " << bytes to parser\n"; // repair the backup state, its pointers might have changed due to @@ -734,7 +734,7 @@ bool TurtleStreamParser::getLine(TurtleTriple* triple) { !isParserExhausted_) { bool parsedStatement; std::optional ex; - // If this buffer reads from an mmaped file, then exceptions are + // If this buffer reads from a memory-mapped file, then exceptions are // immediately rethrown. If we are reading from a stream in chunks of // bytes, we can try again with a larger buffer. try { @@ -751,7 +751,7 @@ bool TurtleStreamParser::getLine(TurtleTriple* triple) { // try to parse with a larger buffer and repeat the reading process // (maybe the failure was due to statements crossing our block). if (resetStateAndRead(&b)) { - // we have succesfully extended our buffer + // we have successfully extended our buffer if (byteVec_.size() > BZIP2_MAX_TOTAL_BUFFER_SIZE) { auto d = tok_.view(); LOG(ERROR) << "Could not parse " << PARSER_MIN_TRIPLES_AT_ONCE diff --git a/src/parser/UpdateClause.h b/src/parser/UpdateClause.h new file mode 100644 index 0000000000..85f79bc046 --- /dev/null +++ b/src/parser/UpdateClause.h @@ -0,0 +1,21 @@ +// Copyright 2024, University of Freiburg, +// Chair of Algorithms and Data Structures. +// Author: Julian Mundhahs (mundhahj@informatik.uni-freiburg.de) + +#pragma once + +#include "parser/SelectClause.h" +#include "parser/SparqlTriple.h" +#include "parser/data/Types.h" + +namespace parsedQuery { +struct UpdateClause : ClauseBase { + std::vector toInsert_; + std::vector toDelete_; + + UpdateClause() = default; + UpdateClause(std::vector toInsert, + std::vector toDelete) + : toInsert_{std::move(toInsert)}, toDelete_{std::move(toDelete)} {} +}; +} // namespace parsedQuery diff --git a/src/parser/data/ConstructQueryExportContext.h b/src/parser/data/ConstructQueryExportContext.h index 13b78826e5..253e8614bb 100644 --- a/src/parser/data/ConstructQueryExportContext.h +++ b/src/parser/data/ConstructQueryExportContext.h @@ -6,7 +6,7 @@ #include -#include "engine/ResultTable.h" +#include "engine/Result.h" #include "engine/VariableToColumnMap.h" #include "parser/data/Variable.h" #include "util/HashMap.h" @@ -18,7 +18,7 @@ enum struct PositionInTriple : int { SUBJECT, PREDICATE, OBJECT }; // All the data that is needed to evaluate an element in a construct query. struct ConstructQueryExportContext { const size_t _row; - const ResultTable& _res; + const Result& _res; const VariableToColumnMap& _variableColumns; const Index& _qecIndex; }; diff --git a/src/parser/data/GraphRef.h b/src/parser/data/GraphRef.h new file mode 100644 index 0000000000..fff4f19bee --- /dev/null +++ b/src/parser/data/GraphRef.h @@ -0,0 +1,17 @@ +// Copyright 2024, University of Freiburg, +// Chair of Algorithms and Data Structures. +// Author: Julian Mundhahs (mundhahj@informatik.uni-freiburg.de) + +#pragma once + +#include + +#include "parser/Iri.h" + +using GraphRef = TripleComponent::Iri; +struct DEFAULT {}; +struct NAMED {}; +struct ALL {}; + +using GraphRefAll = std::variant; +using GraphOrDefault = std::variant; diff --git a/src/parser/data/Variable.cpp b/src/parser/data/Variable.cpp index bf0f5e5e82..8b7a3207e7 100644 --- a/src/parser/data/Variable.cpp +++ b/src/parser/data/Variable.cpp @@ -29,7 +29,7 @@ Variable::Variable(std::string name) : _name{std::move(name)} { // Call stack. Most notably the check which columns belongs to this variable // should be much further up in the call stack. size_t row = context._row; - const ResultTable& res = context._res; + const Result& res = context._res; const auto& variableColumns = context._variableColumns; const Index& qecIndex = context._qecIndex; const auto& idTable = res.idTable(); diff --git a/src/parser/sparqlParser/SparqlQleverVisitor.cpp b/src/parser/sparqlParser/SparqlQleverVisitor.cpp index e44fff2699..d5c0f640db 100644 --- a/src/parser/sparqlParser/SparqlQleverVisitor.cpp +++ b/src/parser/sparqlParser/SparqlQleverVisitor.cpp @@ -13,15 +13,20 @@ #include #include +#include "absl/time/time.h" +#include "engine/sparqlExpressions/GroupConcatExpression.h" #include "engine/sparqlExpressions/LangExpression.h" +#include "engine/sparqlExpressions/LiteralExpression.h" +#include "engine/sparqlExpressions/NowDatetimeExpression.h" #include "engine/sparqlExpressions/RandomExpression.h" #include "engine/sparqlExpressions/RegexExpression.h" #include "engine/sparqlExpressions/RelationalExpressions.h" +#include "engine/sparqlExpressions/SampleExpression.h" +#include "engine/sparqlExpressions/UuidExpressions.h" #include "parser/SparqlParser.h" #include "parser/TokenizerCtre.h" #include "parser/TurtleParser.h" #include "parser/data/Variable.h" -#include "util/OnDestructionDontThrowDuringStackUnwinding.h" #include "util/StringUtils.h" #include "util/TransparentFunctors.h" #include "util/antlr/GenerateAntlrExceptionMetadata.h" @@ -54,6 +59,12 @@ std::string Visitor::getOriginalInputForContext( ad_utility::getUTF8Substring(fullInput, posBeg, posEnd - posBeg + 1)}; } +// _____________________________________________________________________________ +std::string Visitor::currentTimeAsXsdString() { + return absl::FormatTime("%Y-%m-%dT%H:%M:%E3S%Ez", absl::Now(), + absl::LocalTimeZone()); +} + // ___________________________________________________________________________ ExpressionPtr Visitor::processIriFunctionCall( const TripleComponent::Iri& iri, std::vector argList, @@ -121,6 +132,16 @@ ExpressionPtr Visitor::processIriFunctionCall( checkNumArgs(1); return sparqlExpression::makeTanExpression(std::move(argList[0])); } + } else if (checkPrefix(XSD_PREFIX)) { + if (functionName == "integer" || functionName == "int") { + checkNumArgs(1); + return sparqlExpression::makeConvertToIntExpression( + std::move(argList[0])); + } else if (functionName == "double" || functionName == "decimal") { + checkNumArgs(1); + return sparqlExpression::makeConvertToDoubleExpression( + std::move(argList[0])); + } } reportNotSupported(ctx, "Function \""s + iri.toStringRepresentation() + "\" is"); @@ -167,6 +188,15 @@ ParsedQuery Visitor::visit(Parser::QueryContext* ctx) { return query; } +// ____________________________________________________________________________________ +ParsedQuery Visitor::visit(Parser::QueryOrUpdateContext* ctx) { + if (ctx->update()) { + reportNotSupported(ctx->update(), "SPARQL 1.1 Update"); + } else { + return visit(ctx->query()); + } +} + // ____________________________________________________________________________________ SelectClause Visitor::visit(Parser::SelectClauseContext* ctx) { SelectClause select; @@ -306,6 +336,230 @@ std::optional Visitor::visit(Parser::ValuesClauseContext* ctx) { return visitOptional(ctx->dataBlock()); } +// ____________________________________________________________________________________ +ParsedQuery Visitor::visit(Parser::UpdateContext* ctx) { + visit(ctx->prologue()); + + auto query = visit(ctx->update1()); + + if (ctx->update()) { + parsedQuery_ = ParsedQuery{}; + reportNotSupported(ctx->update(), "Multiple updates in one query are"); + } + + return query; +} + +// ____________________________________________________________________________________ +ParsedQuery Visitor::visit(Parser::Update1Context* ctx) { + if (ctx->modify()) { + return visit(ctx->modify()); + } else if (ctx->clear()) { + return visit(ctx->clear()); + } + + parsedQuery_._clause = parsedQuery::UpdateClause(); + + if (ctx->insertData() || ctx->deleteData()) { + // handles insertData and deleteData cases + visitIf(&parsedQuery_.updateClause().toInsert_, ctx->insertData()); + visitIf(&parsedQuery_.updateClause().toDelete_, ctx->deleteData()); + } else if (ctx->deleteWhere()) { + auto [toDelete, pattern] = visit(ctx->deleteWhere()); + parsedQuery_.updateClause().toDelete_ = std::move(toDelete); + parsedQuery_._rootGraphPattern = std::move(pattern); + } else { + visitAlternative(ctx->load(), ctx->drop(), ctx->add(), ctx->move(), + ctx->copy(), ctx->create()); + AD_FAIL(); + } + + return parsedQuery_; +} + +// ____________________________________________________________________________________ +void Visitor::visit(const Parser::LoadContext* ctx) const { + reportNotSupported(ctx, "SPARQL 1.1 Update Load is"); +} + +// ____________________________________________________________________________________ +ParsedQuery Visitor::visit(Parser::ClearContext* ctx) { + auto graphRef = visit(ctx->graphRefAll()); + + if (holds_alternative(graphRef)) { + parsedQuery_._clause = parsedQuery::UpdateClause(); + parsedQuery_.updateClause().toDelete_ = { + {Variable("?s"), Variable("?p"), Variable("?o")}}; + parsedQuery_._rootGraphPattern._graphPatterns.emplace_back( + BasicGraphPattern{{{Variable("?s"), "?p", Variable("?o")}}}); + return parsedQuery_; + } else { + reportNotSupported(ctx, "Named Graphs are"); + } +} + +// ____________________________________________________________________________________ +void Visitor::visit(const Parser::DropContext* ctx) const { + reportNotSupported(ctx, "SPARQL 1.1 Update Drop is"); +} + +// ____________________________________________________________________________________ +void Visitor::visit(const Parser::CreateContext* ctx) const { + reportNotSupported(ctx, "SPARQL 1.1 Update Create is"); +} + +// ____________________________________________________________________________________ +void Visitor::visit(const Parser::AddContext* ctx) const { + reportNotSupported(ctx, "SPARQL 1.1 Update Add is"); +} + +// ____________________________________________________________________________________ +void Visitor::visit(const Parser::MoveContext* ctx) const { + reportNotSupported(ctx, "SPARQL 1.1 Update Move is"); +} + +// ____________________________________________________________________________________ +void Visitor::visit(const Parser::CopyContext* ctx) const { + reportNotSupported(ctx, "SPARQL 1.1 Update Copy is"); +} + +// ____________________________________________________________________________________ +vector Visitor::visit(Parser::InsertDataContext* ctx) { + return visit(ctx->quadData()); +} + +// ____________________________________________________________________________________ +vector Visitor::visit(Parser::DeleteDataContext* ctx) { + return visit(ctx->quadData()); +} + +// ____________________________________________________________________________________ +std::pair, ParsedQuery::GraphPattern> Visitor::visit( + Parser::DeleteWhereContext* ctx) { + auto triples = visit(ctx->quadPattern()); + auto registerIfVariable = [this](const TripleComponent& component) { + if (component.isVariable()) { + addVisibleVariable(component.getVariable()); + } + }; + auto transformAndRegisterTriple = + [registerIfVariable](const SparqlTripleSimple& triple) { + registerIfVariable(triple.s_); + registerIfVariable(triple.p_); + registerIfVariable(triple.o_); + + // The predicate comes from a rule in the grammar (`verb`) which only + // allows variables and IRIs. + AD_CORRECTNESS_CHECK(triple.p_.isVariable() || triple.p_.isIri()); + return SparqlTriple::fromSimple(triple); + }; + GraphPattern pattern; + pattern._graphPatterns.emplace_back(BasicGraphPattern{ + ad_utility::transform(triples, transformAndRegisterTriple)}); + + return {std::move(triples), std::move(pattern)}; +} + +// ____________________________________________________________________________________ +ParsedQuery Visitor::visit(Parser::ModifyContext* ctx) { + if (ctx->iri()) { + reportNotSupported(ctx->iri(), "Named graphs are"); + } + if (!ctx->usingClause().empty()) { + reportNotSupported(ctx->usingClause(0), + "USING inside an DELETE or INSERT is"); + } + + parsedQuery_._rootGraphPattern = visit(ctx->groupGraphPattern()); + + parsedQuery_._clause = parsedQuery::UpdateClause(); + visitIf(&parsedQuery_.updateClause().toInsert_, ctx->insertClause()); + visitIf(&parsedQuery_.updateClause().toDelete_, ctx->deleteClause()); + + return parsedQuery_; +} + +// ____________________________________________________________________________________ +vector Visitor::visit(Parser::DeleteClauseContext* ctx) { + return visit(ctx->quadPattern()); +} + +// ____________________________________________________________________________________ +vector Visitor::visit(Parser::InsertClauseContext* ctx) { + return visit(ctx->quadPattern()); +} + +// ____________________________________________________________________________________ +GraphOrDefault Visitor::visit(Parser::GraphOrDefaultContext* ctx) { + if (ctx->iri()) { + return visit(ctx->iri()); + } else { + return DEFAULT{}; + } +} + +// ____________________________________________________________________________________ +GraphRef Visitor::visit(Parser::GraphRefContext* ctx) { + return visit(ctx->iri()); +} + +// ____________________________________________________________________________________ +GraphRefAll Visitor::visit(Parser::GraphRefAllContext* ctx) { + if (ctx->graphRef()) { + return visit(ctx->graphRef()); + } else if (ctx->DEFAULT()) { + return DEFAULT{}; + } else if (ctx->NAMED()) { + return NAMED{}; + } else if (ctx->ALL()) { + return ALL{}; + } else { + AD_FAIL(); + } +} + +// ____________________________________________________________________________________ +vector Visitor::visit(Parser::QuadPatternContext* ctx) { + return visit(ctx->quads()); +} + +// ____________________________________________________________________________________ +vector Visitor::visit(Parser::QuadDataContext* ctx) { + auto quads = visit(ctx->quads()); + auto checkAndReportVar = [&ctx](const TripleComponent& term) { + if (term.isVariable()) { + reportError(ctx->quads(), "Variables (" + term.getVariable().name() + + ") are not allowed here."); + } + }; + + for (const auto& quad : quads) { + checkAndReportVar(quad.s_); + checkAndReportVar(quad.p_); + checkAndReportVar(quad.o_); + } + + return quads; +} + +// ____________________________________________________________________________________ +vector Visitor::visit(Parser::QuadsContext* ctx) { + if (!ctx->quadsNotTriples().empty()) { + // Could also be default; disallow completely for now. + reportNotSupported(ctx->quadsNotTriples(0), "Named graphs are"); + } + + AD_CORRECTNESS_CHECK(ctx->triplesTemplate().size() == 1); + + auto convertTriple = + [](const std::array& triple) -> SparqlTripleSimple { + return {visitGraphTerm(triple[0]), visitGraphTerm(triple[1]), + visitGraphTerm(triple[2])}; + }; + + return ad_utility::transform(visit(ctx->triplesTemplate(0)), convertTriple); +} + // ____________________________________________________________________________________ GraphPattern Visitor::visit(Parser::GroupGraphPatternContext* ctx) { GraphPattern pattern; @@ -392,19 +646,6 @@ Visitor::OperationOrFilterAndMaybeTriples Visitor::visit( // ____________________________________________________________________________________ BasicGraphPattern Visitor::visit(Parser::TriplesBlockContext* ctx) { - auto visitGraphTerm = [](const GraphTerm& graphTerm) { - return graphTerm.visit([](const T& element) -> TripleComponent { - if constexpr (std::is_same_v) { - return element; - } else if constexpr (std::is_same_v || - std::is_same_v) { - return TurtleStringParser::parseTripleObject( - element.toSparql()); - } else { - return element.toSparql(); - } - }); - }; auto varToPropertyPath = [](const Variable& var) { return PropertyPath::fromVariable(var); }; @@ -417,15 +658,13 @@ BasicGraphPattern Visitor::visit(Parser::TriplesBlockContext* ctx) { propertyPathIdentity}, varOrPath); }; - auto registerIfVariable = [this](const auto& variant) { if (holds_alternative(variant)) { addVisibleVariable(std::get(variant)); } }; - auto convertAndRegisterTriple = - [&visitGraphTerm, &visitVarOrPath, ®isterIfVariable]( + [&visitVarOrPath, ®isterIfVariable]( const TripleWithPropertyPath& triple) -> SparqlTriple { registerIfVariable(triple.subject_); registerIfVariable(triple.predicate_); @@ -904,7 +1143,7 @@ vector Visitor::visit(Parser::ArgListContext* ctx) { if (ctx->NIL()) { return std::vector{}; } - // The grammar allows an optional DISTICT before the argument list (the + // The grammar allows an optional DISTINCT before the argument list (the // whole list, not the individual arguments), but we currently don't support // it. if (ctx->DISTINCT()) { @@ -1771,6 +2010,10 @@ ExpressionPtr Visitor::visit([[maybe_unused]] Parser::BuiltInCallContext* ctx) { }; if (functionName == "str") { return createUnary(&makeStrExpression); + } else if (functionName == "strlang") { + return createBinary(&makeStrLangTagExpression); + } else if (functionName == "strdt") { + return createBinary(&makeStrIriDtExpression); } else if (functionName == "strlen") { return createUnary(&makeStrlenExpression); } else if (functionName == "strbefore") { @@ -1793,15 +2036,36 @@ ExpressionPtr Visitor::visit([[maybe_unused]] Parser::BuiltInCallContext* ctx) { return createUnary(&makeMonthExpression); } else if (functionName == "day") { return createUnary(&makeDayExpression); + } else if (functionName == "tz") { + return createUnary(&makeTimezoneStrExpression); + } else if (functionName == "now") { + AD_CONTRACT_CHECK(argList.empty()); + return std::make_unique(startTime_); } else if (functionName == "hours") { return createUnary(&makeHoursExpression); } else if (functionName == "minutes") { return createUnary(&makeMinutesExpression); } else if (functionName == "seconds") { return createUnary(&makeSecondsExpression); + } else if (functionName == "md5") { + return createUnary(&makeMD5Expression); + } else if (functionName == "sha1") { + return createUnary(&makeSHA1Expression); + } else if (functionName == "sha256") { + return createUnary(&makeSHA256Expression); + } else if (functionName == "sha384") { + return createUnary(&makeSHA384Expression); + } else if (functionName == "sha512") { + return createUnary(&makeSHA512Expression); } else if (functionName == "rand") { AD_CONTRACT_CHECK(argList.empty()); return std::make_unique(); + } else if (functionName == "uuid") { + AD_CONTRACT_CHECK(argList.empty()); + return std::make_unique(); + } else if (functionName == "struuid") { + AD_CONTRACT_CHECK(argList.empty()); + return std::make_unique(); } else if (functionName == "ceil") { return createUnary(&makeCeilExpression); } else if (functionName == "abs") { @@ -1828,6 +2092,8 @@ ExpressionPtr Visitor::visit([[maybe_unused]] Parser::BuiltInCallContext* ctx) { return createUnary(&makeIsLiteralExpression); } else if (functionName == "isnumeric") { return createUnary(&makeIsNumericExpression); + } else if (functionName == "datatype") { + return createUnary(&makeDatatypeExpression); } else if (functionName == "bound") { return makeBoundExpression( std::make_unique(visit(ctx->var()))); @@ -2168,3 +2434,18 @@ void Visitor::checkUnsupportedLangOperationAllowFilters( ad_utility::antlr_utility::generateAntlrExceptionMetadata(ctx)); } } + +// _____________________________________________________________________________ +TripleComponent SparqlQleverVisitor::visitGraphTerm( + const GraphTerm& graphTerm) { + return graphTerm.visit([](const T& element) -> TripleComponent { + if constexpr (std::is_same_v) { + return element; + } else if constexpr (std::is_same_v || std::is_same_v) { + return TurtleStringParser::parseTripleObject( + element.toSparql()); + } else { + return element.toSparql(); + } + }); +} diff --git a/src/parser/sparqlParser/SparqlQleverVisitor.h b/src/parser/sparqlParser/SparqlQleverVisitor.h index 73766bfbd8..195ca98975 100644 --- a/src/parser/sparqlParser/SparqlQleverVisitor.h +++ b/src/parser/sparqlParser/SparqlQleverVisitor.h @@ -9,25 +9,11 @@ #include #include "engine/sparqlExpressions/AggregateExpression.h" -#include "engine/sparqlExpressions/GroupConcatExpression.h" -#include "engine/sparqlExpressions/LiteralExpression.h" #include "engine/sparqlExpressions/NaryExpression.h" -#include "engine/sparqlExpressions/SampleExpression.h" -#include "engine/sparqlExpressions/SparqlExpressionPimpl.h" -#include "parser/Alias.h" -#include "parser/ConstructClause.h" -#include "parser/ParsedQuery.h" -#include "parser/RdfEscaping.h" -#include "parser/data/BlankNode.h" -#include "parser/data/Iri.h" -#include "parser/data/SolutionModifiers.h" -#include "parser/data/Types.h" +#include "parser/data/GraphRef.h" #undef EOF #include "parser/sparqlParser/generated/SparqlAutomaticVisitor.h" #define EOF std::char_traits::eof() -#include "util/HashMap.h" -#include "util/OverloadCallOperator.h" -#include "util/StringUtils.h" template class Reversed { @@ -124,7 +110,10 @@ class SparqlQleverVisitor { } // ___________________________________________________________________________ - [[nodiscard]] ParsedQuery visit(Parser::QueryContext* ctx); + ParsedQuery visit(Parser::QueryOrUpdateContext* ctx); + + // ___________________________________________________________________________ + ParsedQuery visit(Parser::QueryContext* ctx); // ___________________________________________________________________________ void visit(Parser::PrologueContext* ctx); @@ -135,21 +124,19 @@ class SparqlQleverVisitor { // ___________________________________________________________________________ void visit(Parser::PrefixDeclContext* ctx); - [[nodiscard]] ParsedQuery visit(Parser::SelectQueryContext* ctx); + ParsedQuery visit(Parser::SelectQueryContext* ctx); - [[nodiscard]] SubQueryAndMaybeValues visit(Parser::SubSelectContext* ctx); + SubQueryAndMaybeValues visit(Parser::SubSelectContext* ctx); - [[nodiscard]] parsedQuery::SelectClause visit( - Parser::SelectClauseContext* ctx); + parsedQuery::SelectClause visit(Parser::SelectClauseContext* ctx); - [[nodiscard]] std::variant visit( - Parser::VarOrAliasContext* ctx); + std::variant visit(Parser::VarOrAliasContext* ctx); - [[nodiscard]] Alias visit(Parser::AliasContext* ctx); + Alias visit(Parser::AliasContext* ctx); - [[nodiscard]] Alias visit(Parser::AliasWithoutBracketsContext* ctx); + Alias visit(Parser::AliasWithoutBracketsContext* ctx); - [[nodiscard]] ParsedQuery visit(Parser::ConstructQueryContext* ctx); + ParsedQuery visit(Parser::ConstructQueryContext* ctx); // The parser rules for which the visit overload is annotated [[noreturn]] // will always throw an exception because the corresponding feature is not @@ -168,156 +155,180 @@ class SparqlQleverVisitor { [[noreturn]] static void visit(Parser::SourceSelectorContext* ctx); - [[nodiscard]] PatternAndVisibleVariables visit( - Parser::WhereClauseContext* ctx); + PatternAndVisibleVariables visit(Parser::WhereClauseContext* ctx); + + SolutionModifiers visit(Parser::SolutionModifierContext* ctx); + + vector visit(Parser::GroupClauseContext* ctx); + + GroupKey visit(Parser::GroupConditionContext* ctx); + + vector visit(Parser::HavingClauseContext* ctx); + + SparqlFilter visit(Parser::HavingConditionContext* ctx); + + OrderClause visit(Parser::OrderClauseContext* ctx); + + OrderKey visit(Parser::OrderConditionContext* ctx); + + LimitOffsetClause visit(Parser::LimitOffsetClausesContext* ctx); + + static uint64_t visit(Parser::LimitClauseContext* ctx); + + static uint64_t visit(Parser::OffsetClauseContext* ctx); + + static uint64_t visit(Parser::TextLimitClauseContext* ctx); - [[nodiscard]] SolutionModifiers visit(Parser::SolutionModifierContext* ctx); + std::optional visit(Parser::ValuesClauseContext* ctx); - [[nodiscard]] vector visit(Parser::GroupClauseContext* ctx); + ParsedQuery visit(Parser::UpdateContext* ctx); - [[nodiscard]] GroupKey visit(Parser::GroupConditionContext* ctx); + ParsedQuery visit(Parser::Update1Context* ctx); - [[nodiscard]] vector visit(Parser::HavingClauseContext* ctx); + [[noreturn]] void visit(const Parser::LoadContext* ctx) const; - [[nodiscard]] SparqlFilter visit(Parser::HavingConditionContext* ctx); + ParsedQuery visit(Parser::ClearContext* ctx); - [[nodiscard]] OrderClause visit(Parser::OrderClauseContext* ctx); + [[noreturn]] void visit(const Parser::DropContext* ctx) const; - [[nodiscard]] OrderKey visit(Parser::OrderConditionContext* ctx); + [[noreturn]] void visit(const Parser::CreateContext* ctx) const; - [[nodiscard]] LimitOffsetClause visit(Parser::LimitOffsetClausesContext* ctx); + [[noreturn]] void visit(const Parser::AddContext* ctx) const; - [[nodiscard]] static uint64_t visit(Parser::LimitClauseContext* ctx); + [[noreturn]] void visit(const Parser::MoveContext* ctx) const; - [[nodiscard]] static uint64_t visit(Parser::OffsetClauseContext* ctx); + [[noreturn]] void visit(const Parser::CopyContext* ctx) const; - [[nodiscard]] static uint64_t visit(Parser::TextLimitClauseContext* ctx); + vector visit(Parser::InsertDataContext* ctx); - [[nodiscard]] std::optional visit( - Parser::ValuesClauseContext* ctx); + vector visit(Parser::DeleteDataContext* ctx); - [[nodiscard]] Triples visit(Parser::TriplesTemplateContext* ctx); + std::pair, ParsedQuery::GraphPattern> visit( + Parser::DeleteWhereContext* ctx); - [[nodiscard]] ParsedQuery::GraphPattern visit( - Parser::GroupGraphPatternContext* ctx); + ParsedQuery visit(Parser::ModifyContext* ctx); - [[nodiscard]] OperationsAndFilters visit( - Parser::GroupGraphPatternSubContext* ctx); + vector visit(Parser::DeleteClauseContext* ctx); - [[nodiscard]] OperationOrFilterAndMaybeTriples visit( + vector visit(Parser::InsertClauseContext* ctx); + + GraphOrDefault visit(Parser::GraphOrDefaultContext* ctx); + + GraphRef visit(Parser::GraphRefContext* ctx); + + GraphRefAll visit(Parser::GraphRefAllContext* ctx); + + vector visit(Parser::QuadPatternContext* ctx); + + vector visit(Parser::QuadDataContext* ctx); + + vector visit(Parser::QuadsContext* ctx); + + Triples visit(Parser::TriplesTemplateContext* ctx); + + ParsedQuery::GraphPattern visit(Parser::GroupGraphPatternContext* ctx); + + OperationsAndFilters visit(Parser::GroupGraphPatternSubContext* ctx); + + OperationOrFilterAndMaybeTriples visit( Parser::GraphPatternNotTriplesAndMaybeTriplesContext* ctx); - [[nodiscard]] parsedQuery::BasicGraphPattern visit( - Parser::TriplesBlockContext* graphTerm); + parsedQuery::BasicGraphPattern visit(Parser::TriplesBlockContext* graphTerm); // Filter clauses are no independent graph patterns themselves, but their // scope is always the complete graph pattern enclosing them. - [[nodiscard]] OperationOrFilter visit( - Parser::GraphPatternNotTriplesContext* ctx); + OperationOrFilter visit(Parser::GraphPatternNotTriplesContext* ctx); - [[nodiscard]] parsedQuery::GraphPatternOperation visit( + parsedQuery::GraphPatternOperation visit( Parser::OptionalGraphPatternContext* ctx); [[noreturn]] static parsedQuery::GraphPatternOperation visit( const Parser::GraphGraphPatternContext* ctx); - [[nodiscard]] GraphPatternOperation visit( - Parser::ServiceGraphPatternContext* ctx); + parsedQuery::GraphPatternOperation visit(Parser::ServiceGraphPatternContext* ctx); - [[nodiscard]] parsedQuery::GraphPatternOperation visit( - Parser::BindContext* ctx); + parsedQuery::GraphPatternOperation visit(Parser::BindContext* ctx); - [[nodiscard]] parsedQuery::GraphPatternOperation visit( - Parser::InlineDataContext* ctx); + parsedQuery::GraphPatternOperation visit(Parser::InlineDataContext* ctx); - [[nodiscard]] parsedQuery::Values visit(Parser::DataBlockContext* ctx); + parsedQuery::Values visit(Parser::DataBlockContext* ctx); - [[nodiscard]] parsedQuery::SparqlValues visit( - Parser::InlineDataOneVarContext* ctx); + parsedQuery::SparqlValues visit(Parser::InlineDataOneVarContext* ctx); - [[nodiscard]] parsedQuery::SparqlValues visit( - Parser::InlineDataFullContext* ctx); + parsedQuery::SparqlValues visit(Parser::InlineDataFullContext* ctx); - [[nodiscard]] vector visit( - Parser::DataBlockSingleContext* ctx); + vector visit(Parser::DataBlockSingleContext* ctx); - [[nodiscard]] TripleComponent visit(Parser::DataBlockValueContext* ctx); + TripleComponent visit(Parser::DataBlockValueContext* ctx); - [[nodiscard]] GraphPatternOperation visit( - Parser::MinusGraphPatternContext* ctx); + GraphPatternOperation visit(Parser::MinusGraphPatternContext* ctx); - [[nodiscard]] GraphPatternOperation visit( - Parser::GroupOrUnionGraphPatternContext* ctx); + GraphPatternOperation visit(Parser::GroupOrUnionGraphPatternContext* ctx); - [[nodiscard]] SparqlFilter visit(Parser::FilterRContext* ctx); + SparqlFilter visit(Parser::FilterRContext* ctx); - [[nodiscard]] ExpressionPtr visit(Parser::ConstraintContext* ctx); + ExpressionPtr visit(Parser::ConstraintContext* ctx); - [[nodiscard]] ExpressionPtr visit(Parser::FunctionCallContext* ctx); + ExpressionPtr visit(Parser::FunctionCallContext* ctx); - [[nodiscard]] vector visit(Parser::ArgListContext* ctx); + vector visit(Parser::ArgListContext* ctx); std::vector visit(Parser::ExpressionListContext* ctx); - [[nodiscard]] std::optional visit( + std::optional visit( Parser::ConstructTemplateContext* ctx); - [[nodiscard]] Triples visit(Parser::ConstructTriplesContext* ctx); + Triples visit(Parser::ConstructTriplesContext* ctx); - [[nodiscard]] Triples visit(Parser::TriplesSameSubjectContext* ctx); + Triples visit(Parser::TriplesSameSubjectContext* ctx); - [[nodiscard]] PredicateObjectPairsAndTriples visit( - Parser::PropertyListContext* ctx); + PredicateObjectPairsAndTriples visit(Parser::PropertyListContext* ctx); - [[nodiscard]] PredicateObjectPairsAndTriples visit( + PredicateObjectPairsAndTriples visit( Parser::PropertyListNotEmptyContext* ctx); - [[nodiscard]] GraphTerm visit(Parser::VerbContext* ctx); + GraphTerm visit(Parser::VerbContext* ctx); - [[nodiscard]] ObjectsAndTriples visit(Parser::ObjectListContext* ctx); + ObjectsAndTriples visit(Parser::ObjectListContext* ctx); - [[nodiscard]] SubjectOrObjectAndTriples visit(Parser::ObjectRContext* ctx); + SubjectOrObjectAndTriples visit(Parser::ObjectRContext* ctx); - [[nodiscard]] vector visit( + vector visit( Parser::TriplesSameSubjectPathContext* ctx); - [[nodiscard]] std::optional visit( + std::optional visit( Parser::PropertyListPathContext* ctx); - [[nodiscard]] PathObjectPairsAndTriples visit( - Parser::PropertyListPathNotEmptyContext* ctx); + PathObjectPairsAndTriples visit(Parser::PropertyListPathNotEmptyContext* ctx); - [[nodiscard]] PropertyPath visit(Parser::VerbPathContext* ctx); + PropertyPath visit(Parser::VerbPathContext* ctx); - [[nodiscard]] static Variable visit(Parser::VerbSimpleContext* ctx); + static Variable visit(Parser::VerbSimpleContext* ctx); - [[nodiscard]] PathObjectPairsAndTriples visit( - Parser::TupleWithoutPathContext* term); + PathObjectPairsAndTriples visit(Parser::TupleWithoutPathContext* term); - [[nodiscard]] PathObjectPairsAndTriples visit( - Parser::TupleWithPathContext* ctx); + PathObjectPairsAndTriples visit(Parser::TupleWithPathContext* ctx); - [[nodiscard]] ad_utility::sparql_types::VarOrPath visit( + ad_utility::sparql_types::VarOrPath visit( Parser::VerbPathOrSimpleContext* ctx); - [[nodiscard]] ObjectsAndPathTriples visit(Parser::ObjectListPathContext* ctx); + ObjectsAndPathTriples visit(Parser::ObjectListPathContext* ctx); - [[nodiscard]] SubjectOrObjectAndPathTriples visit( - Parser::ObjectPathContext* ctx); + SubjectOrObjectAndPathTriples visit(Parser::ObjectPathContext* ctx); - [[nodiscard]] PropertyPath visit(Parser::PathContext* ctx); + PropertyPath visit(Parser::PathContext* ctx); - [[nodiscard]] PropertyPath visit(Parser::PathAlternativeContext* ctx); + PropertyPath visit(Parser::PathAlternativeContext* ctx); - [[nodiscard]] PropertyPath visit(Parser::PathSequenceContext* ctx); + PropertyPath visit(Parser::PathSequenceContext* ctx); - [[nodiscard]] PropertyPath visit(Parser::PathEltContext* ctx); + PropertyPath visit(Parser::PathEltContext* ctx); - [[nodiscard]] PropertyPath visit(Parser::PathEltOrInverseContext* ctx); + PropertyPath visit(Parser::PathEltOrInverseContext* ctx); [[noreturn]] static void visit(Parser::PathModContext* ctx); - [[nodiscard]] PropertyPath visit(Parser::PathPrimaryContext* ctx); + PropertyPath visit(Parser::PathPrimaryContext* ctx); [[noreturn]] static PropertyPath visit( const Parser::PathNegatedPropertySetContext*); @@ -327,52 +338,47 @@ class SparqlQleverVisitor { /// Note that in the SPARQL grammar the INTEGER rule refers to positive /// integers without an explicit sign. - [[nodiscard]] static uint64_t visit(Parser::IntegerContext* ctx); + static uint64_t visit(Parser::IntegerContext* ctx); - [[nodiscard]] SubjectOrObjectAndTriples visit( - Parser::TriplesNodeContext* ctx); + SubjectOrObjectAndTriples visit(Parser::TriplesNodeContext* ctx); - [[nodiscard]] SubjectOrObjectAndTriples visit( - Parser::BlankNodePropertyListContext* ctx); + SubjectOrObjectAndTriples visit(Parser::BlankNodePropertyListContext* ctx); SubjectOrObjectAndPathTriples visit(Parser::TriplesNodePathContext* ctx); SubjectOrObjectAndPathTriples visit( Parser::BlankNodePropertyListPathContext* ctx); - [[nodiscard]] SubjectOrObjectAndTriples visit(Parser::CollectionContext* ctx); + SubjectOrObjectAndTriples visit(Parser::CollectionContext* ctx); [[noreturn]] SubjectOrObjectAndPathTriples visit( Parser::CollectionPathContext* ctx); - [[nodiscard]] SubjectOrObjectAndTriples visit(Parser::GraphNodeContext* ctx); + SubjectOrObjectAndTriples visit(Parser::GraphNodeContext* ctx); - [[nodiscard]] SubjectOrObjectAndPathTriples visit( - Parser::GraphNodePathContext* ctx); + SubjectOrObjectAndPathTriples visit(Parser::GraphNodePathContext* ctx); - [[nodiscard]] GraphTerm visit(Parser::VarOrTermContext* ctx); + GraphTerm visit(Parser::VarOrTermContext* ctx); - [[nodiscard]] GraphTerm visit(Parser::VarOrIriContext* ctx); + GraphTerm visit(Parser::VarOrIriContext* ctx); - [[nodiscard]] static Variable visit(Parser::VarContext* ctx); + static Variable visit(Parser::VarContext* ctx); - [[nodiscard]] GraphTerm visit(Parser::GraphTermContext* ctx); + GraphTerm visit(Parser::GraphTermContext* ctx); - [[nodiscard]] ExpressionPtr visit(Parser::ExpressionContext* ctx); + ExpressionPtr visit(Parser::ExpressionContext* ctx); - [[nodiscard]] ExpressionPtr visit( - Parser::ConditionalOrExpressionContext* ctx); + ExpressionPtr visit(Parser::ConditionalOrExpressionContext* ctx); - [[nodiscard]] ExpressionPtr visit( - Parser::ConditionalAndExpressionContext* ctx); + ExpressionPtr visit(Parser::ConditionalAndExpressionContext* ctx); - [[nodiscard]] ExpressionPtr visit(Parser::ValueLogicalContext* ctx); + ExpressionPtr visit(Parser::ValueLogicalContext* ctx); - [[nodiscard]] ExpressionPtr visit(Parser::RelationalExpressionContext* ctx); + ExpressionPtr visit(Parser::RelationalExpressionContext* ctx); - [[nodiscard]] ExpressionPtr visit(Parser::NumericExpressionContext* ctx); + ExpressionPtr visit(Parser::NumericExpressionContext* ctx); - [[nodiscard]] ExpressionPtr visit(Parser::AdditiveExpressionContext* ctx); + ExpressionPtr visit(Parser::AdditiveExpressionContext* ctx); // Helper structs, needed in the following `visit` functions. Combine an // explicit operator (+ - * /) with an expression. @@ -382,41 +388,35 @@ class SparqlQleverVisitor { ExpressionPtr expression_; }; - [[nodiscard]] OperatorAndExpression visit( + OperatorAndExpression visit( Parser::MultiplicativeExpressionWithSignContext* ctx); - [[nodiscard]] OperatorAndExpression visit( - Parser::PlusSubexpressionContext* ctx); + OperatorAndExpression visit(Parser::PlusSubexpressionContext* ctx); - [[nodiscard]] OperatorAndExpression visit( - Parser::MinusSubexpressionContext* ctx); + OperatorAndExpression visit(Parser::MinusSubexpressionContext* ctx); - [[nodiscard]] OperatorAndExpression visit( + OperatorAndExpression visit( Parser::MultiplicativeExpressionWithLeadingSignButNoSpaceContext* ctx); - [[nodiscard]] ExpressionPtr visit( - Parser::MultiplicativeExpressionContext* ctx); + ExpressionPtr visit(Parser::MultiplicativeExpressionContext* ctx); - [[nodiscard]] OperatorAndExpression visit( - Parser::MultiplyOrDivideExpressionContext* ctx); + OperatorAndExpression visit(Parser::MultiplyOrDivideExpressionContext* ctx); - [[nodiscard]] OperatorAndExpression visit( - Parser::MultiplyExpressionContext* ctx); + OperatorAndExpression visit(Parser::MultiplyExpressionContext* ctx); - [[nodiscard]] OperatorAndExpression visit( - Parser::DivideExpressionContext* ctx); + OperatorAndExpression visit(Parser::DivideExpressionContext* ctx); - [[nodiscard]] ExpressionPtr visit(Parser::UnaryExpressionContext* ctx); + ExpressionPtr visit(Parser::UnaryExpressionContext* ctx); - [[nodiscard]] ExpressionPtr visit(Parser::PrimaryExpressionContext* ctx); + ExpressionPtr visit(Parser::PrimaryExpressionContext* ctx); - [[nodiscard]] ExpressionPtr visit(Parser::BrackettedExpressionContext* ctx); + ExpressionPtr visit(Parser::BrackettedExpressionContext* ctx); - [[nodiscard]] ExpressionPtr visit(Parser::BuiltInCallContext* ctx); + ExpressionPtr visit(Parser::BuiltInCallContext* ctx); - [[nodiscard]] ExpressionPtr visit(Parser::RegexExpressionContext* ctx); + ExpressionPtr visit(Parser::RegexExpressionContext* ctx); - [[nodiscard]] ExpressionPtr visit(Parser::LangExpressionContext* ctx); + ExpressionPtr visit(Parser::LangExpressionContext* ctx); ExpressionPtr visit(Parser::SubstringExpressionContext* ctx); @@ -426,47 +426,51 @@ class SparqlQleverVisitor { [[noreturn]] static void visit(const Parser::NotExistsFuncContext* ctx); - [[nodiscard]] ExpressionPtr visit(Parser::AggregateContext* ctx); + ExpressionPtr visit(Parser::AggregateContext* ctx); - [[nodiscard]] ExpressionPtr visit(Parser::IriOrFunctionContext* ctx); + ExpressionPtr visit(Parser::IriOrFunctionContext* ctx); - [[nodiscard]] std::string visit(Parser::RdfLiteralContext* ctx); + std::string visit(Parser::RdfLiteralContext* ctx); - [[nodiscard]] IntOrDouble visit(Parser::NumericLiteralContext* ctx); + IntOrDouble visit(Parser::NumericLiteralContext* ctx); - [[nodiscard]] static IntOrDouble visit( - Parser::NumericLiteralUnsignedContext* ctx); + static IntOrDouble visit(Parser::NumericLiteralUnsignedContext* ctx); - [[nodiscard]] static IntOrDouble visit( - Parser::NumericLiteralPositiveContext* ctx); + static IntOrDouble visit(Parser::NumericLiteralPositiveContext* ctx); - [[nodiscard]] static IntOrDouble visit( - Parser::NumericLiteralNegativeContext* ctx); + static IntOrDouble visit(Parser::NumericLiteralNegativeContext* ctx); - [[nodiscard]] static bool visit(Parser::BooleanLiteralContext* ctx); + static bool visit(Parser::BooleanLiteralContext* ctx); - [[nodiscard]] static RdfEscaping::NormalizedRDFString visit( - Parser::StringContext* ctx); + static RdfEscaping::NormalizedRDFString visit(Parser::StringContext* ctx); - [[nodiscard]] TripleComponent::Iri visit(Parser::IriContext* ctx); + TripleComponent::Iri visit(Parser::IriContext* ctx); - [[nodiscard]] static string visit(Parser::IrirefContext* ctx); + static string visit(Parser::IrirefContext* ctx); - [[nodiscard]] string visit(Parser::PrefixedNameContext* ctx); + string visit(Parser::PrefixedNameContext* ctx); - [[nodiscard]] GraphTerm visit(Parser::BlankNodeContext* ctx); + GraphTerm visit(Parser::BlankNodeContext* ctx); - [[nodiscard]] string visit(Parser::PnameLnContext* ctx); + string visit(Parser::PnameLnContext* ctx); - [[nodiscard]] string visit(Parser::PnameNsContext* ctx); + string visit(Parser::PnameNsContext* ctx); private: + // Helper to assign variable `startTime_` a correctly formatted time string. + static std::string currentTimeAsXsdString(); + + // Member starTime_ is needed for the NOW expression. All calls within + // the query execution reference it. The underlying date time format is e.g.: + // 2011-01-10T14:45:13.815-05:00 + std::string startTime_ = currentTimeAsXsdString(); + template static constexpr bool voidWhenVisited = std::is_void_v().visit( std::declval()))>; - [[nodiscard]] BlankNode newBlankNode() { + BlankNode newBlankNode() { std::string label = std::to_string(_blankNodeCounter); _blankNodeCounter++; // true means automatically generated @@ -484,7 +488,7 @@ class SparqlQleverVisitor { // Process an IRI function call. This is used in both `visitFunctionCall` and // `visitIriOrFunction`. - [[nodiscard]] static ExpressionPtr processIriFunctionCall( + static ExpressionPtr processIriFunctionCall( const TripleComponent::Iri& iri, std::vector argList, const antlr4::ParserRuleContext*); @@ -497,11 +501,11 @@ class SparqlQleverVisitor { // Return the `SparqlExpressionPimpl` for a context that returns a // `ExpressionPtr` when visited. The descriptor is set automatically on the // `SparqlExpressionPimpl`. - [[nodiscard]] SparqlExpressionPimpl visitExpressionPimpl( - auto* ctx, bool allowLanguageFilters = false); + SparqlExpressionPimpl visitExpressionPimpl(auto* ctx, + bool allowLanguageFilters = false); template - [[nodiscard]] ExpressionPtr createExpression(auto... children) { + ExpressionPtr createExpression(auto... children) { return std::make_unique( std::array{std::move(children)...}); } @@ -513,7 +517,7 @@ class SparqlQleverVisitor { // Call `visit` for each of the `childContexts` and return the results of // those calls as a `vector`. template - [[nodiscard]] auto visitVector(const std::vector& childContexts) + auto visitVector(const std::vector& childContexts) -> std::vector requires(!voidWhenVisited); @@ -521,13 +525,12 @@ class SparqlQleverVisitor { // cast the result to `Out` and return it. Requires that for all of the // `ctxs`, `visit(ctxs)` is convertible to `Out`. template - [[nodiscard]] Out visitAlternative(Contexts*... ctxs); + Out visitAlternative(Contexts*... ctxs); // Returns `std::nullopt` if the pointer is the `nullptr`. Otherwise return // `visit(ctx)`. template - [[nodiscard]] auto visitOptional(Ctx* ctx) - -> std::optional; + auto visitOptional(Ctx* ctx) -> std::optional; /// If `ctx` is not `nullptr`, visit it, convert the result to `Intermediate` /// and assign it to `*target`. The case where `Intermediate!=Target` is @@ -566,7 +569,7 @@ class SparqlQleverVisitor { // Parse both `ConstructTriplesContext` and `TriplesTemplateContext` because // they have the same structure. template - [[nodiscard]] Triples parseTriplesConstruction(Context* ctx); + Triples parseTriplesConstruction(Context* ctx); // If the triple is a special triple for the text index (i.e. its predicate is // either `ql:contains-word` or `ql:contains-entity`, register the magic @@ -575,4 +578,7 @@ class SparqlQleverVisitor { // part of the query result. void setMatchingWordAndScoreVisibleIfPresent( auto* ctx, const TripleWithPropertyPath& triple); + + // Constructs a TripleComponent from a GraphTerm. + static TripleComponent visitGraphTerm(const GraphTerm& graphTerm); }; diff --git a/src/parser/sparqlParser/generated/SparqlAutomatic.g4 b/src/parser/sparqlParser/generated/SparqlAutomatic.g4 index 13cfe66897..2102a0ef11 100644 --- a/src/parser/sparqlParser/generated/SparqlAutomatic.g4 +++ b/src/parser/sparqlParser/generated/SparqlAutomatic.g4 @@ -38,11 +38,14 @@ grammar SparqlAutomatic; -query - : prologue (selectQuery | constructQuery | describeQuery | askQuery) valuesClause EOF +// query and update are disjoint in the grammar; +// add a common parent for easier parsing +queryOrUpdate: query | update EOF ; -//updateUnit : update; +query + : prologue (selectQuery | constructQuery | describeQuery | askQuery) valuesClause + ; prologue : (baseDecl | prefixDecl)* @@ -146,7 +149,51 @@ textLimitClause valuesClause : ( VALUES dataBlock )?; - // omitted rules 29 - 50 which are there for unsupported query types ( not select) +update: prologue (update1 (';' update)? )? ; + +update1: load | clear | drop | add | move | copy | create | insertData | deleteData | deleteWhere | modify ; + +load: LOAD SILENT? iri (INTO graphRef)? ; + +clear: CLEAR SILENT? graphRefAll ; + +drop: DROP SILENT? graphRefAll ; + +create: CREATE SILENT? graphRef ; + +add: ADD SILENT? graphOrDefault TO graphOrDefault ; + +move: MOVE SILENT? graphOrDefault TO graphOrDefault ; + +copy: COPY SILENT? graphOrDefault TO graphOrDefault ; + +insertData: INSERT DATA quadData ; + +deleteData: DELETE DATA quadData ; + +deleteWhere: DELETE WHERE quadPattern ; + +modify: (WITH iri)? ( deleteClause insertClause? | insertClause ) usingClause* WHERE groupGraphPattern ; + +deleteClause: DELETE quadPattern ; + +insertClause: INSERT quadPattern ; + +usingClause: USING (IRI | NAMED iri) ; + +graphOrDefault: DEFAULT | GRAPH iri ; + +graphRef: GRAPH iri ; + +graphRefAll: graphRef | DEFAULT | NAMED | ALL ; + +quadPattern: '{' quads '}' ; + +quadData: '{' quads '}' ; + +quads: triplesTemplate? ( quadsNotTriples '.'? triplesTemplate? )* ; + +quadsNotTriples: GRAPH varOrIri '{' triplesTemplate? '}' ; triplesTemplate: triplesSameSubject ( '.' triplesTemplate? )?; @@ -632,10 +679,12 @@ TEXTLIMIT: T E X T L I M I T; VALUES : V A L U E S; LOAD : L O A D; SILENT : S I L E N T; +INTO: I N T O; CLEAR : C L E A R; DROP : D R O P; CREATE: C R E A T E; ADD: A D D; +TO: T O; DATA: D A T A; MOVE: M O V E; COPY: C O P Y; @@ -692,7 +741,7 @@ UUID : U U I D; STRUUID : S T R U U I D; SHA1 : S H A '1'; SHA256 : S H A '256'; -SHA384 : S H A '382'; +SHA384 : S H A '384'; SHA512 : S H A '512'; MD5 : M D '5'; COALESCE : C O A L E S C E; diff --git a/src/parser/sparqlParser/generated/SparqlAutomatic.interp b/src/parser/sparqlParser/generated/SparqlAutomatic.interp index 67f5795ca2..1936655c40 100644 --- a/src/parser/sparqlParser/generated/SparqlAutomatic.interp +++ b/src/parser/sparqlParser/generated/SparqlAutomatic.interp @@ -5,9 +5,9 @@ null ')' '{' '}' +';' '.' ',' -';' 'a' '|' '/' @@ -173,6 +173,8 @@ null null null null +null +null token symbolic names: null @@ -230,10 +232,12 @@ TEXTLIMIT VALUES LOAD SILENT +INTO CLEAR DROP CREATE ADD +TO DATA MOVE COPY @@ -351,6 +355,7 @@ WS COMMENTS rule names: +queryOrUpdate query prologue baseDecl @@ -381,6 +386,29 @@ limitClause offsetClause textLimitClause valuesClause +update +update1 +load +clear +drop +create +add +move +copy +insertData +deleteData +deleteWhere +modify +deleteClause +insertClause +usingClause +graphOrDefault +graphRef +graphRefAll +quadPattern +quadData +quads +quadsNotTriples triplesTemplate groupGraphPattern groupGraphPatternSub @@ -487,4 +515,4 @@ pnameNs atn: -[4, 1, 173, 1433, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 2, 93, 7, 93, 2, 94, 7, 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, 2, 103, 7, 103, 2, 104, 7, 104, 2, 105, 7, 105, 2, 106, 7, 106, 2, 107, 7, 107, 2, 108, 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, 111, 7, 111, 2, 112, 7, 112, 2, 113, 7, 113, 2, 114, 7, 114, 2, 115, 7, 115, 2, 116, 7, 116, 2, 117, 7, 117, 2, 118, 7, 118, 2, 119, 7, 119, 2, 120, 7, 120, 2, 121, 7, 121, 2, 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, 7, 130, 2, 131, 7, 131, 2, 132, 7, 132, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 3, 0, 272, 8, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 5, 1, 279, 8, 1, 10, 1, 12, 1, 282, 9, 1, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 5, 4, 293, 8, 4, 10, 4, 12, 4, 296, 9, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 3, 6, 308, 8, 6, 1, 6, 4, 6, 311, 8, 6, 11, 6, 12, 6, 312, 1, 6, 3, 6, 316, 8, 6, 1, 7, 1, 7, 3, 7, 320, 8, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 5, 10, 333, 8, 10, 10, 10, 12, 10, 336, 9, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, 10, 342, 8, 10, 10, 10, 12, 10, 345, 9, 10, 1, 10, 1, 10, 1, 10, 3, 10, 350, 8, 10, 1, 10, 1, 10, 3, 10, 354, 8, 10, 1, 11, 1, 11, 4, 11, 358, 8, 11, 11, 11, 12, 11, 359, 1, 11, 3, 11, 363, 8, 11, 1, 11, 5, 11, 366, 8, 11, 10, 11, 12, 11, 369, 9, 11, 1, 11, 3, 11, 372, 8, 11, 1, 11, 1, 11, 1, 12, 1, 12, 5, 12, 378, 8, 12, 10, 12, 12, 12, 381, 9, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 3, 13, 389, 8, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 3, 17, 399, 8, 17, 1, 17, 1, 17, 1, 18, 3, 18, 404, 8, 18, 1, 18, 3, 18, 407, 8, 18, 1, 18, 3, 18, 410, 8, 18, 1, 18, 3, 18, 413, 8, 18, 1, 19, 1, 19, 4, 19, 417, 8, 19, 11, 19, 12, 19, 418, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 3, 20, 427, 8, 20, 1, 20, 1, 20, 1, 20, 3, 20, 432, 8, 20, 1, 21, 1, 21, 4, 21, 436, 8, 21, 11, 21, 12, 21, 437, 1, 22, 1, 22, 1, 23, 1, 23, 3, 23, 444, 8, 23, 1, 23, 4, 23, 447, 8, 23, 11, 23, 12, 23, 448, 1, 24, 1, 24, 1, 24, 1, 24, 3, 24, 455, 8, 24, 3, 24, 457, 8, 24, 1, 25, 1, 25, 3, 25, 461, 8, 25, 1, 25, 3, 25, 464, 8, 25, 1, 25, 1, 25, 3, 25, 468, 8, 25, 1, 25, 3, 25, 471, 8, 25, 1, 25, 1, 25, 3, 25, 475, 8, 25, 1, 25, 3, 25, 478, 8, 25, 1, 25, 1, 25, 3, 25, 482, 8, 25, 1, 25, 3, 25, 485, 8, 25, 1, 25, 1, 25, 3, 25, 489, 8, 25, 1, 25, 3, 25, 492, 8, 25, 1, 25, 1, 25, 3, 25, 496, 8, 25, 1, 25, 3, 25, 499, 8, 25, 3, 25, 501, 8, 25, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 3, 29, 514, 8, 29, 1, 30, 1, 30, 1, 30, 3, 30, 519, 8, 30, 3, 30, 521, 8, 30, 1, 31, 1, 31, 1, 31, 3, 31, 526, 8, 31, 1, 31, 1, 31, 1, 32, 3, 32, 531, 8, 32, 1, 32, 5, 32, 534, 8, 32, 10, 32, 12, 32, 537, 9, 32, 1, 33, 1, 33, 3, 33, 541, 8, 33, 1, 33, 3, 33, 544, 8, 33, 1, 34, 1, 34, 1, 34, 3, 34, 549, 8, 34, 3, 34, 551, 8, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 3, 35, 561, 8, 35, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 3, 38, 572, 8, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 3, 41, 589, 8, 41, 1, 42, 1, 42, 1, 42, 5, 42, 594, 8, 42, 10, 42, 12, 42, 597, 9, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 5, 43, 604, 8, 43, 10, 43, 12, 43, 607, 9, 43, 1, 43, 3, 43, 610, 8, 43, 1, 43, 1, 43, 5, 43, 614, 8, 43, 10, 43, 12, 43, 617, 9, 43, 1, 43, 1, 43, 1, 44, 1, 44, 5, 44, 623, 8, 44, 10, 44, 12, 44, 626, 9, 44, 1, 44, 1, 44, 3, 44, 630, 8, 44, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 3, 45, 637, 8, 45, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 5, 47, 645, 8, 47, 10, 47, 12, 47, 648, 9, 47, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 3, 49, 656, 8, 49, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 3, 51, 664, 8, 51, 1, 51, 1, 51, 1, 51, 5, 51, 669, 8, 51, 10, 51, 12, 51, 672, 9, 51, 1, 51, 1, 51, 3, 51, 676, 8, 51, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 5, 52, 683, 8, 52, 10, 52, 12, 52, 686, 9, 52, 1, 52, 1, 52, 3, 52, 690, 8, 52, 1, 53, 1, 53, 3, 53, 694, 8, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 3, 54, 701, 8, 54, 3, 54, 703, 8, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 3, 55, 711, 8, 55, 1, 56, 3, 56, 714, 8, 56, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 3, 57, 722, 8, 57, 5, 57, 724, 8, 57, 10, 57, 12, 57, 727, 9, 57, 1, 58, 1, 58, 3, 58, 731, 8, 58, 1, 59, 1, 59, 1, 59, 5, 59, 736, 8, 59, 10, 59, 12, 59, 739, 9, 59, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 3, 61, 749, 8, 61, 1, 62, 3, 62, 752, 8, 62, 1, 63, 1, 63, 1, 63, 3, 63, 757, 8, 63, 5, 63, 759, 8, 63, 10, 63, 12, 63, 762, 9, 63, 1, 64, 1, 64, 1, 65, 1, 65, 1, 66, 1, 66, 1, 66, 1, 67, 1, 67, 1, 67, 1, 68, 1, 68, 3, 68, 776, 8, 68, 1, 69, 1, 69, 1, 69, 5, 69, 781, 8, 69, 10, 69, 12, 69, 784, 9, 69, 1, 70, 1, 70, 1, 71, 1, 71, 1, 72, 1, 72, 1, 72, 5, 72, 793, 8, 72, 10, 72, 12, 72, 796, 9, 72, 1, 73, 1, 73, 1, 73, 5, 73, 801, 8, 73, 10, 73, 12, 73, 804, 9, 73, 1, 74, 1, 74, 3, 74, 808, 8, 74, 1, 75, 1, 75, 1, 75, 3, 75, 813, 8, 75, 1, 76, 1, 76, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 3, 77, 825, 8, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 5, 78, 832, 8, 78, 10, 78, 12, 78, 835, 9, 78, 3, 78, 837, 8, 78, 1, 78, 3, 78, 840, 8, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 3, 79, 847, 8, 79, 3, 79, 849, 8, 79, 1, 80, 1, 80, 1, 81, 1, 81, 3, 81, 855, 8, 81, 1, 82, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 3, 83, 863, 8, 83, 1, 84, 1, 84, 1, 84, 1, 84, 1, 85, 1, 85, 4, 85, 871, 8, 85, 11, 85, 12, 85, 872, 1, 85, 1, 85, 1, 86, 1, 86, 4, 86, 879, 8, 86, 11, 86, 12, 86, 880, 1, 86, 1, 86, 1, 87, 1, 87, 3, 87, 887, 8, 87, 1, 88, 1, 88, 3, 88, 891, 8, 88, 1, 89, 1, 89, 3, 89, 895, 8, 89, 1, 90, 1, 90, 3, 90, 899, 8, 90, 1, 91, 1, 91, 1, 92, 1, 92, 1, 92, 1, 92, 1, 92, 1, 92, 3, 92, 909, 8, 92, 1, 93, 1, 93, 1, 94, 1, 94, 1, 94, 5, 94, 916, 8, 94, 10, 94, 12, 94, 919, 9, 94, 1, 95, 1, 95, 1, 95, 5, 95, 924, 8, 95, 10, 95, 12, 95, 927, 9, 95, 1, 96, 1, 96, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 3, 97, 949, 8, 97, 1, 98, 1, 98, 1, 99, 1, 99, 5, 99, 955, 8, 99, 10, 99, 12, 99, 958, 9, 99, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 3, 100, 965, 8, 100, 1, 101, 1, 101, 1, 102, 1, 102, 1, 103, 1, 103, 3, 103, 973, 8, 103, 1, 103, 5, 103, 976, 8, 103, 10, 103, 12, 103, 979, 9, 103, 1, 104, 1, 104, 5, 104, 983, 8, 104, 10, 104, 12, 104, 986, 9, 104, 1, 105, 1, 105, 3, 105, 990, 8, 105, 1, 106, 1, 106, 1, 106, 1, 107, 1, 107, 1, 107, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 3, 108, 1005, 8, 108, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 3, 109, 1014, 8, 109, 1, 110, 1, 110, 1, 110, 1, 110, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 3, 111, 1060, 8, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 3, 111, 1274, 8, 111, 1, 112, 1, 112, 1, 112, 1, 112, 1, 112, 1, 112, 1, 112, 3, 112, 1283, 8, 112, 1, 112, 1, 112, 1, 113, 1, 113, 1, 113, 1, 113, 1, 113, 1, 114, 1, 114, 1, 114, 1, 114, 1, 114, 1, 114, 1, 114, 3, 114, 1299, 8, 114, 1, 114, 1, 114, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 3, 115, 1312, 8, 115, 1, 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, 117, 1, 117, 1, 117, 1, 117, 1, 118, 1, 118, 1, 118, 3, 118, 1326, 8, 118, 1, 118, 1, 118, 3, 118, 1330, 8, 118, 1, 118, 1, 118, 1, 118, 1, 118, 3, 118, 1336, 8, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 3, 118, 1344, 8, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 3, 118, 1352, 8, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 3, 118, 1360, 8, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 3, 118, 1368, 8, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 3, 118, 1376, 8, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 3, 118, 1383, 8, 118, 1, 118, 1, 118, 3, 118, 1387, 8, 118, 1, 119, 1, 119, 3, 119, 1391, 8, 119, 1, 120, 1, 120, 1, 120, 1, 120, 3, 120, 1397, 8, 120, 1, 121, 1, 121, 1, 121, 3, 121, 1402, 8, 121, 1, 122, 1, 122, 1, 123, 1, 123, 1, 124, 1, 124, 1, 125, 1, 125, 1, 126, 1, 126, 1, 127, 3, 127, 1415, 8, 127, 1, 127, 1, 127, 3, 127, 1419, 8, 127, 1, 128, 1, 128, 3, 128, 1423, 8, 128, 1, 129, 1, 129, 1, 130, 1, 130, 1, 131, 1, 131, 1, 132, 1, 132, 1, 132, 0, 0, 133, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 0, 10, 1, 0, 33, 34, 1, 0, 47, 48, 2, 0, 1, 1, 13, 14, 1, 0, 143, 144, 1, 0, 147, 149, 1, 0, 150, 152, 1, 0, 153, 155, 1, 0, 28, 29, 1, 0, 157, 160, 2, 0, 142, 142, 163, 163, 1536, 0, 266, 1, 0, 0, 0, 2, 280, 1, 0, 0, 0, 4, 283, 1, 0, 0, 0, 6, 286, 1, 0, 0, 0, 8, 290, 1, 0, 0, 0, 10, 300, 1, 0, 0, 0, 12, 305, 1, 0, 0, 0, 14, 319, 1, 0, 0, 0, 16, 321, 1, 0, 0, 0, 18, 325, 1, 0, 0, 0, 20, 329, 1, 0, 0, 0, 22, 355, 1, 0, 0, 0, 24, 375, 1, 0, 0, 0, 26, 385, 1, 0, 0, 0, 28, 390, 1, 0, 0, 0, 30, 392, 1, 0, 0, 0, 32, 395, 1, 0, 0, 0, 34, 398, 1, 0, 0, 0, 36, 403, 1, 0, 0, 0, 38, 414, 1, 0, 0, 0, 40, 431, 1, 0, 0, 0, 42, 433, 1, 0, 0, 0, 44, 439, 1, 0, 0, 0, 46, 443, 1, 0, 0, 0, 48, 456, 1, 0, 0, 0, 50, 500, 1, 0, 0, 0, 52, 502, 1, 0, 0, 0, 54, 505, 1, 0, 0, 0, 56, 508, 1, 0, 0, 0, 58, 513, 1, 0, 0, 0, 60, 515, 1, 0, 0, 0, 62, 522, 1, 0, 0, 0, 64, 530, 1, 0, 0, 0, 66, 538, 1, 0, 0, 0, 68, 545, 1, 0, 0, 0, 70, 560, 1, 0, 0, 0, 72, 562, 1, 0, 0, 0, 74, 565, 1, 0, 0, 0, 76, 569, 1, 0, 0, 0, 78, 576, 1, 0, 0, 0, 80, 583, 1, 0, 0, 0, 82, 588, 1, 0, 0, 0, 84, 590, 1, 0, 0, 0, 86, 609, 1, 0, 0, 0, 88, 629, 1, 0, 0, 0, 90, 636, 1, 0, 0, 0, 92, 638, 1, 0, 0, 0, 94, 641, 1, 0, 0, 0, 96, 649, 1, 0, 0, 0, 98, 655, 1, 0, 0, 0, 100, 657, 1, 0, 0, 0, 102, 675, 1, 0, 0, 0, 104, 689, 1, 0, 0, 0, 106, 691, 1, 0, 0, 0, 108, 697, 1, 0, 0, 0, 110, 710, 1, 0, 0, 0, 112, 713, 1, 0, 0, 0, 114, 715, 1, 0, 0, 0, 116, 730, 1, 0, 0, 0, 118, 732, 1, 0, 0, 0, 120, 740, 1, 0, 0, 0, 122, 748, 1, 0, 0, 0, 124, 751, 1, 0, 0, 0, 126, 753, 1, 0, 0, 0, 128, 763, 1, 0, 0, 0, 130, 765, 1, 0, 0, 0, 132, 767, 1, 0, 0, 0, 134, 770, 1, 0, 0, 0, 136, 775, 1, 0, 0, 0, 138, 777, 1, 0, 0, 0, 140, 785, 1, 0, 0, 0, 142, 787, 1, 0, 0, 0, 144, 789, 1, 0, 0, 0, 146, 797, 1, 0, 0, 0, 148, 805, 1, 0, 0, 0, 150, 812, 1, 0, 0, 0, 152, 814, 1, 0, 0, 0, 154, 824, 1, 0, 0, 0, 156, 839, 1, 0, 0, 0, 158, 848, 1, 0, 0, 0, 160, 850, 1, 0, 0, 0, 162, 854, 1, 0, 0, 0, 164, 856, 1, 0, 0, 0, 166, 862, 1, 0, 0, 0, 168, 864, 1, 0, 0, 0, 170, 868, 1, 0, 0, 0, 172, 876, 1, 0, 0, 0, 174, 886, 1, 0, 0, 0, 176, 890, 1, 0, 0, 0, 178, 894, 1, 0, 0, 0, 180, 898, 1, 0, 0, 0, 182, 900, 1, 0, 0, 0, 184, 908, 1, 0, 0, 0, 186, 910, 1, 0, 0, 0, 188, 912, 1, 0, 0, 0, 190, 920, 1, 0, 0, 0, 192, 928, 1, 0, 0, 0, 194, 930, 1, 0, 0, 0, 196, 950, 1, 0, 0, 0, 198, 952, 1, 0, 0, 0, 200, 964, 1, 0, 0, 0, 202, 966, 1, 0, 0, 0, 204, 968, 1, 0, 0, 0, 206, 972, 1, 0, 0, 0, 208, 980, 1, 0, 0, 0, 210, 989, 1, 0, 0, 0, 212, 991, 1, 0, 0, 0, 214, 994, 1, 0, 0, 0, 216, 1004, 1, 0, 0, 0, 218, 1013, 1, 0, 0, 0, 220, 1015, 1, 0, 0, 0, 222, 1273, 1, 0, 0, 0, 224, 1275, 1, 0, 0, 0, 226, 1286, 1, 0, 0, 0, 228, 1291, 1, 0, 0, 0, 230, 1302, 1, 0, 0, 0, 232, 1315, 1, 0, 0, 0, 234, 1318, 1, 0, 0, 0, 236, 1386, 1, 0, 0, 0, 238, 1388, 1, 0, 0, 0, 240, 1392, 1, 0, 0, 0, 242, 1401, 1, 0, 0, 0, 244, 1403, 1, 0, 0, 0, 246, 1405, 1, 0, 0, 0, 248, 1407, 1, 0, 0, 0, 250, 1409, 1, 0, 0, 0, 252, 1411, 1, 0, 0, 0, 254, 1414, 1, 0, 0, 0, 256, 1422, 1, 0, 0, 0, 258, 1424, 1, 0, 0, 0, 260, 1426, 1, 0, 0, 0, 262, 1428, 1, 0, 0, 0, 264, 1430, 1, 0, 0, 0, 266, 271, 3, 2, 1, 0, 267, 272, 3, 8, 4, 0, 268, 272, 3, 20, 10, 0, 269, 272, 3, 22, 11, 0, 270, 272, 3, 24, 12, 0, 271, 267, 1, 0, 0, 0, 271, 268, 1, 0, 0, 0, 271, 269, 1, 0, 0, 0, 271, 270, 1, 0, 0, 0, 272, 273, 1, 0, 0, 0, 273, 274, 3, 58, 29, 0, 274, 275, 5, 0, 0, 1, 275, 1, 1, 0, 0, 0, 276, 279, 3, 4, 2, 0, 277, 279, 3, 6, 3, 0, 278, 276, 1, 0, 0, 0, 278, 277, 1, 0, 0, 0, 279, 282, 1, 0, 0, 0, 280, 278, 1, 0, 0, 0, 280, 281, 1, 0, 0, 0, 281, 3, 1, 0, 0, 0, 282, 280, 1, 0, 0, 0, 283, 284, 5, 30, 0, 0, 284, 285, 3, 260, 130, 0, 285, 5, 1, 0, 0, 0, 286, 287, 5, 31, 0, 0, 287, 288, 5, 140, 0, 0, 288, 289, 3, 260, 130, 0, 289, 7, 1, 0, 0, 0, 290, 294, 3, 12, 6, 0, 291, 293, 3, 26, 13, 0, 292, 291, 1, 0, 0, 0, 293, 296, 1, 0, 0, 0, 294, 292, 1, 0, 0, 0, 294, 295, 1, 0, 0, 0, 295, 297, 1, 0, 0, 0, 296, 294, 1, 0, 0, 0, 297, 298, 3, 34, 17, 0, 298, 299, 3, 36, 18, 0, 299, 9, 1, 0, 0, 0, 300, 301, 3, 12, 6, 0, 301, 302, 3, 34, 17, 0, 302, 303, 3, 36, 18, 0, 303, 304, 3, 58, 29, 0, 304, 11, 1, 0, 0, 0, 305, 307, 5, 32, 0, 0, 306, 308, 7, 0, 0, 0, 307, 306, 1, 0, 0, 0, 307, 308, 1, 0, 0, 0, 308, 315, 1, 0, 0, 0, 309, 311, 3, 14, 7, 0, 310, 309, 1, 0, 0, 0, 311, 312, 1, 0, 0, 0, 312, 310, 1, 0, 0, 0, 312, 313, 1, 0, 0, 0, 313, 316, 1, 0, 0, 0, 314, 316, 5, 1, 0, 0, 315, 310, 1, 0, 0, 0, 315, 314, 1, 0, 0, 0, 316, 13, 1, 0, 0, 0, 317, 320, 3, 182, 91, 0, 318, 320, 3, 16, 8, 0, 319, 317, 1, 0, 0, 0, 319, 318, 1, 0, 0, 0, 320, 15, 1, 0, 0, 0, 321, 322, 5, 2, 0, 0, 322, 323, 3, 18, 9, 0, 323, 324, 5, 3, 0, 0, 324, 17, 1, 0, 0, 0, 325, 326, 3, 186, 93, 0, 326, 327, 5, 35, 0, 0, 327, 328, 3, 182, 91, 0, 328, 19, 1, 0, 0, 0, 329, 353, 5, 36, 0, 0, 330, 334, 3, 106, 53, 0, 331, 333, 3, 26, 13, 0, 332, 331, 1, 0, 0, 0, 333, 336, 1, 0, 0, 0, 334, 332, 1, 0, 0, 0, 334, 335, 1, 0, 0, 0, 335, 337, 1, 0, 0, 0, 336, 334, 1, 0, 0, 0, 337, 338, 3, 34, 17, 0, 338, 339, 3, 36, 18, 0, 339, 354, 1, 0, 0, 0, 340, 342, 3, 26, 13, 0, 341, 340, 1, 0, 0, 0, 342, 345, 1, 0, 0, 0, 343, 341, 1, 0, 0, 0, 343, 344, 1, 0, 0, 0, 344, 346, 1, 0, 0, 0, 345, 343, 1, 0, 0, 0, 346, 347, 5, 37, 0, 0, 347, 349, 5, 4, 0, 0, 348, 350, 3, 60, 30, 0, 349, 348, 1, 0, 0, 0, 349, 350, 1, 0, 0, 0, 350, 351, 1, 0, 0, 0, 351, 352, 5, 5, 0, 0, 352, 354, 3, 36, 18, 0, 353, 330, 1, 0, 0, 0, 353, 343, 1, 0, 0, 0, 354, 21, 1, 0, 0, 0, 355, 362, 5, 38, 0, 0, 356, 358, 3, 180, 90, 0, 357, 356, 1, 0, 0, 0, 358, 359, 1, 0, 0, 0, 359, 357, 1, 0, 0, 0, 359, 360, 1, 0, 0, 0, 360, 363, 1, 0, 0, 0, 361, 363, 5, 1, 0, 0, 362, 357, 1, 0, 0, 0, 362, 361, 1, 0, 0, 0, 363, 367, 1, 0, 0, 0, 364, 366, 3, 26, 13, 0, 365, 364, 1, 0, 0, 0, 366, 369, 1, 0, 0, 0, 367, 365, 1, 0, 0, 0, 367, 368, 1, 0, 0, 0, 368, 371, 1, 0, 0, 0, 369, 367, 1, 0, 0, 0, 370, 372, 3, 34, 17, 0, 371, 370, 1, 0, 0, 0, 371, 372, 1, 0, 0, 0, 372, 373, 1, 0, 0, 0, 373, 374, 3, 36, 18, 0, 374, 23, 1, 0, 0, 0, 375, 379, 5, 39, 0, 0, 376, 378, 3, 26, 13, 0, 377, 376, 1, 0, 0, 0, 378, 381, 1, 0, 0, 0, 379, 377, 1, 0, 0, 0, 379, 380, 1, 0, 0, 0, 380, 382, 1, 0, 0, 0, 381, 379, 1, 0, 0, 0, 382, 383, 3, 34, 17, 0, 383, 384, 3, 36, 18, 0, 384, 25, 1, 0, 0, 0, 385, 388, 5, 40, 0, 0, 386, 389, 3, 28, 14, 0, 387, 389, 3, 30, 15, 0, 388, 386, 1, 0, 0, 0, 388, 387, 1, 0, 0, 0, 389, 27, 1, 0, 0, 0, 390, 391, 3, 32, 16, 0, 391, 29, 1, 0, 0, 0, 392, 393, 5, 41, 0, 0, 393, 394, 3, 32, 16, 0, 394, 31, 1, 0, 0, 0, 395, 396, 3, 254, 127, 0, 396, 33, 1, 0, 0, 0, 397, 399, 5, 37, 0, 0, 398, 397, 1, 0, 0, 0, 398, 399, 1, 0, 0, 0, 399, 400, 1, 0, 0, 0, 400, 401, 3, 62, 31, 0, 401, 35, 1, 0, 0, 0, 402, 404, 3, 38, 19, 0, 403, 402, 1, 0, 0, 0, 403, 404, 1, 0, 0, 0, 404, 406, 1, 0, 0, 0, 405, 407, 3, 42, 21, 0, 406, 405, 1, 0, 0, 0, 406, 407, 1, 0, 0, 0, 407, 409, 1, 0, 0, 0, 408, 410, 3, 46, 23, 0, 409, 408, 1, 0, 0, 0, 409, 410, 1, 0, 0, 0, 410, 412, 1, 0, 0, 0, 411, 413, 3, 50, 25, 0, 412, 411, 1, 0, 0, 0, 412, 413, 1, 0, 0, 0, 413, 37, 1, 0, 0, 0, 414, 416, 5, 42, 0, 0, 415, 417, 3, 40, 20, 0, 416, 415, 1, 0, 0, 0, 417, 418, 1, 0, 0, 0, 418, 416, 1, 0, 0, 0, 418, 419, 1, 0, 0, 0, 419, 39, 1, 0, 0, 0, 420, 432, 3, 222, 111, 0, 421, 432, 3, 100, 50, 0, 422, 423, 5, 2, 0, 0, 423, 426, 3, 186, 93, 0, 424, 425, 5, 35, 0, 0, 425, 427, 3, 182, 91, 0, 426, 424, 1, 0, 0, 0, 426, 427, 1, 0, 0, 0, 427, 428, 1, 0, 0, 0, 428, 429, 5, 3, 0, 0, 429, 432, 1, 0, 0, 0, 430, 432, 3, 182, 91, 0, 431, 420, 1, 0, 0, 0, 431, 421, 1, 0, 0, 0, 431, 422, 1, 0, 0, 0, 431, 430, 1, 0, 0, 0, 432, 41, 1, 0, 0, 0, 433, 435, 5, 44, 0, 0, 434, 436, 3, 44, 22, 0, 435, 434, 1, 0, 0, 0, 436, 437, 1, 0, 0, 0, 437, 435, 1, 0, 0, 0, 437, 438, 1, 0, 0, 0, 438, 43, 1, 0, 0, 0, 439, 440, 3, 98, 49, 0, 440, 45, 1, 0, 0, 0, 441, 444, 5, 45, 0, 0, 442, 444, 5, 46, 0, 0, 443, 441, 1, 0, 0, 0, 443, 442, 1, 0, 0, 0, 444, 446, 1, 0, 0, 0, 445, 447, 3, 48, 24, 0, 446, 445, 1, 0, 0, 0, 447, 448, 1, 0, 0, 0, 448, 446, 1, 0, 0, 0, 448, 449, 1, 0, 0, 0, 449, 47, 1, 0, 0, 0, 450, 451, 7, 1, 0, 0, 451, 457, 3, 220, 110, 0, 452, 455, 3, 98, 49, 0, 453, 455, 3, 182, 91, 0, 454, 452, 1, 0, 0, 0, 454, 453, 1, 0, 0, 0, 455, 457, 1, 0, 0, 0, 456, 450, 1, 0, 0, 0, 456, 454, 1, 0, 0, 0, 457, 49, 1, 0, 0, 0, 458, 460, 3, 52, 26, 0, 459, 461, 3, 54, 27, 0, 460, 459, 1, 0, 0, 0, 460, 461, 1, 0, 0, 0, 461, 463, 1, 0, 0, 0, 462, 464, 3, 56, 28, 0, 463, 462, 1, 0, 0, 0, 463, 464, 1, 0, 0, 0, 464, 501, 1, 0, 0, 0, 465, 467, 3, 52, 26, 0, 466, 468, 3, 56, 28, 0, 467, 466, 1, 0, 0, 0, 467, 468, 1, 0, 0, 0, 468, 470, 1, 0, 0, 0, 469, 471, 3, 54, 27, 0, 470, 469, 1, 0, 0, 0, 470, 471, 1, 0, 0, 0, 471, 501, 1, 0, 0, 0, 472, 474, 3, 54, 27, 0, 473, 475, 3, 52, 26, 0, 474, 473, 1, 0, 0, 0, 474, 475, 1, 0, 0, 0, 475, 477, 1, 0, 0, 0, 476, 478, 3, 56, 28, 0, 477, 476, 1, 0, 0, 0, 477, 478, 1, 0, 0, 0, 478, 501, 1, 0, 0, 0, 479, 481, 3, 54, 27, 0, 480, 482, 3, 56, 28, 0, 481, 480, 1, 0, 0, 0, 481, 482, 1, 0, 0, 0, 482, 484, 1, 0, 0, 0, 483, 485, 3, 52, 26, 0, 484, 483, 1, 0, 0, 0, 484, 485, 1, 0, 0, 0, 485, 501, 1, 0, 0, 0, 486, 488, 3, 56, 28, 0, 487, 489, 3, 54, 27, 0, 488, 487, 1, 0, 0, 0, 488, 489, 1, 0, 0, 0, 489, 491, 1, 0, 0, 0, 490, 492, 3, 52, 26, 0, 491, 490, 1, 0, 0, 0, 491, 492, 1, 0, 0, 0, 492, 501, 1, 0, 0, 0, 493, 495, 3, 56, 28, 0, 494, 496, 3, 52, 26, 0, 495, 494, 1, 0, 0, 0, 495, 496, 1, 0, 0, 0, 496, 498, 1, 0, 0, 0, 497, 499, 3, 54, 27, 0, 498, 497, 1, 0, 0, 0, 498, 499, 1, 0, 0, 0, 499, 501, 1, 0, 0, 0, 500, 458, 1, 0, 0, 0, 500, 465, 1, 0, 0, 0, 500, 472, 1, 0, 0, 0, 500, 479, 1, 0, 0, 0, 500, 486, 1, 0, 0, 0, 500, 493, 1, 0, 0, 0, 501, 51, 1, 0, 0, 0, 502, 503, 5, 49, 0, 0, 503, 504, 3, 160, 80, 0, 504, 53, 1, 0, 0, 0, 505, 506, 5, 50, 0, 0, 506, 507, 3, 160, 80, 0, 507, 55, 1, 0, 0, 0, 508, 509, 5, 51, 0, 0, 509, 510, 3, 160, 80, 0, 510, 57, 1, 0, 0, 0, 511, 512, 5, 52, 0, 0, 512, 514, 3, 82, 41, 0, 513, 511, 1, 0, 0, 0, 513, 514, 1, 0, 0, 0, 514, 59, 1, 0, 0, 0, 515, 520, 3, 110, 55, 0, 516, 518, 5, 6, 0, 0, 517, 519, 3, 60, 30, 0, 518, 517, 1, 0, 0, 0, 518, 519, 1, 0, 0, 0, 519, 521, 1, 0, 0, 0, 520, 516, 1, 0, 0, 0, 520, 521, 1, 0, 0, 0, 521, 61, 1, 0, 0, 0, 522, 525, 5, 4, 0, 0, 523, 526, 3, 10, 5, 0, 524, 526, 3, 64, 32, 0, 525, 523, 1, 0, 0, 0, 525, 524, 1, 0, 0, 0, 526, 527, 1, 0, 0, 0, 527, 528, 5, 5, 0, 0, 528, 63, 1, 0, 0, 0, 529, 531, 3, 68, 34, 0, 530, 529, 1, 0, 0, 0, 530, 531, 1, 0, 0, 0, 531, 535, 1, 0, 0, 0, 532, 534, 3, 66, 33, 0, 533, 532, 1, 0, 0, 0, 534, 537, 1, 0, 0, 0, 535, 533, 1, 0, 0, 0, 535, 536, 1, 0, 0, 0, 536, 65, 1, 0, 0, 0, 537, 535, 1, 0, 0, 0, 538, 540, 3, 70, 35, 0, 539, 541, 5, 6, 0, 0, 540, 539, 1, 0, 0, 0, 540, 541, 1, 0, 0, 0, 541, 543, 1, 0, 0, 0, 542, 544, 3, 68, 34, 0, 543, 542, 1, 0, 0, 0, 543, 544, 1, 0, 0, 0, 544, 67, 1, 0, 0, 0, 545, 550, 3, 122, 61, 0, 546, 548, 5, 6, 0, 0, 547, 549, 3, 68, 34, 0, 548, 547, 1, 0, 0, 0, 548, 549, 1, 0, 0, 0, 549, 551, 1, 0, 0, 0, 550, 546, 1, 0, 0, 0, 550, 551, 1, 0, 0, 0, 551, 69, 1, 0, 0, 0, 552, 561, 3, 94, 47, 0, 553, 561, 3, 72, 36, 0, 554, 561, 3, 92, 46, 0, 555, 561, 3, 74, 37, 0, 556, 561, 3, 76, 38, 0, 557, 561, 3, 96, 48, 0, 558, 561, 3, 78, 39, 0, 559, 561, 3, 80, 40, 0, 560, 552, 1, 0, 0, 0, 560, 553, 1, 0, 0, 0, 560, 554, 1, 0, 0, 0, 560, 555, 1, 0, 0, 0, 560, 556, 1, 0, 0, 0, 560, 557, 1, 0, 0, 0, 560, 558, 1, 0, 0, 0, 560, 559, 1, 0, 0, 0, 561, 71, 1, 0, 0, 0, 562, 563, 5, 69, 0, 0, 563, 564, 3, 62, 31, 0, 564, 73, 1, 0, 0, 0, 565, 566, 5, 67, 0, 0, 566, 567, 3, 180, 90, 0, 567, 568, 3, 62, 31, 0, 568, 75, 1, 0, 0, 0, 569, 571, 5, 70, 0, 0, 570, 572, 5, 54, 0, 0, 571, 570, 1, 0, 0, 0, 571, 572, 1, 0, 0, 0, 572, 573, 1, 0, 0, 0, 573, 574, 3, 180, 90, 0, 574, 575, 3, 62, 31, 0, 575, 77, 1, 0, 0, 0, 576, 577, 5, 71, 0, 0, 577, 578, 5, 2, 0, 0, 578, 579, 3, 186, 93, 0, 579, 580, 5, 35, 0, 0, 580, 581, 3, 182, 91, 0, 581, 582, 5, 3, 0, 0, 582, 79, 1, 0, 0, 0, 583, 584, 5, 52, 0, 0, 584, 585, 3, 82, 41, 0, 585, 81, 1, 0, 0, 0, 586, 589, 3, 84, 42, 0, 587, 589, 3, 86, 43, 0, 588, 586, 1, 0, 0, 0, 588, 587, 1, 0, 0, 0, 589, 83, 1, 0, 0, 0, 590, 591, 3, 182, 91, 0, 591, 595, 5, 4, 0, 0, 592, 594, 3, 90, 45, 0, 593, 592, 1, 0, 0, 0, 594, 597, 1, 0, 0, 0, 595, 593, 1, 0, 0, 0, 595, 596, 1, 0, 0, 0, 596, 598, 1, 0, 0, 0, 597, 595, 1, 0, 0, 0, 598, 599, 5, 5, 0, 0, 599, 85, 1, 0, 0, 0, 600, 610, 5, 162, 0, 0, 601, 605, 5, 2, 0, 0, 602, 604, 3, 182, 91, 0, 603, 602, 1, 0, 0, 0, 604, 607, 1, 0, 0, 0, 605, 603, 1, 0, 0, 0, 605, 606, 1, 0, 0, 0, 606, 608, 1, 0, 0, 0, 607, 605, 1, 0, 0, 0, 608, 610, 5, 3, 0, 0, 609, 600, 1, 0, 0, 0, 609, 601, 1, 0, 0, 0, 610, 611, 1, 0, 0, 0, 611, 615, 5, 4, 0, 0, 612, 614, 3, 88, 44, 0, 613, 612, 1, 0, 0, 0, 614, 617, 1, 0, 0, 0, 615, 613, 1, 0, 0, 0, 615, 616, 1, 0, 0, 0, 616, 618, 1, 0, 0, 0, 617, 615, 1, 0, 0, 0, 618, 619, 5, 5, 0, 0, 619, 87, 1, 0, 0, 0, 620, 624, 5, 2, 0, 0, 621, 623, 3, 90, 45, 0, 622, 621, 1, 0, 0, 0, 623, 626, 1, 0, 0, 0, 624, 622, 1, 0, 0, 0, 624, 625, 1, 0, 0, 0, 625, 627, 1, 0, 0, 0, 626, 624, 1, 0, 0, 0, 627, 630, 5, 3, 0, 0, 628, 630, 5, 162, 0, 0, 629, 620, 1, 0, 0, 0, 629, 628, 1, 0, 0, 0, 630, 89, 1, 0, 0, 0, 631, 637, 3, 254, 127, 0, 632, 637, 3, 240, 120, 0, 633, 637, 3, 242, 121, 0, 634, 637, 3, 250, 125, 0, 635, 637, 5, 72, 0, 0, 636, 631, 1, 0, 0, 0, 636, 632, 1, 0, 0, 0, 636, 633, 1, 0, 0, 0, 636, 634, 1, 0, 0, 0, 636, 635, 1, 0, 0, 0, 637, 91, 1, 0, 0, 0, 638, 639, 5, 73, 0, 0, 639, 640, 3, 62, 31, 0, 640, 93, 1, 0, 0, 0, 641, 646, 3, 62, 31, 0, 642, 643, 5, 74, 0, 0, 643, 645, 3, 62, 31, 0, 644, 642, 1, 0, 0, 0, 645, 648, 1, 0, 0, 0, 646, 644, 1, 0, 0, 0, 646, 647, 1, 0, 0, 0, 647, 95, 1, 0, 0, 0, 648, 646, 1, 0, 0, 0, 649, 650, 5, 75, 0, 0, 650, 651, 3, 98, 49, 0, 651, 97, 1, 0, 0, 0, 652, 656, 3, 220, 110, 0, 653, 656, 3, 222, 111, 0, 654, 656, 3, 100, 50, 0, 655, 652, 1, 0, 0, 0, 655, 653, 1, 0, 0, 0, 655, 654, 1, 0, 0, 0, 656, 99, 1, 0, 0, 0, 657, 658, 3, 254, 127, 0, 658, 659, 3, 102, 51, 0, 659, 101, 1, 0, 0, 0, 660, 676, 5, 162, 0, 0, 661, 663, 5, 2, 0, 0, 662, 664, 5, 33, 0, 0, 663, 662, 1, 0, 0, 0, 663, 664, 1, 0, 0, 0, 664, 665, 1, 0, 0, 0, 665, 670, 3, 186, 93, 0, 666, 667, 5, 7, 0, 0, 667, 669, 3, 186, 93, 0, 668, 666, 1, 0, 0, 0, 669, 672, 1, 0, 0, 0, 670, 668, 1, 0, 0, 0, 670, 671, 1, 0, 0, 0, 671, 673, 1, 0, 0, 0, 672, 670, 1, 0, 0, 0, 673, 674, 5, 3, 0, 0, 674, 676, 1, 0, 0, 0, 675, 660, 1, 0, 0, 0, 675, 661, 1, 0, 0, 0, 676, 103, 1, 0, 0, 0, 677, 690, 5, 162, 0, 0, 678, 679, 5, 2, 0, 0, 679, 684, 3, 186, 93, 0, 680, 681, 5, 7, 0, 0, 681, 683, 3, 186, 93, 0, 682, 680, 1, 0, 0, 0, 683, 686, 1, 0, 0, 0, 684, 682, 1, 0, 0, 0, 684, 685, 1, 0, 0, 0, 685, 687, 1, 0, 0, 0, 686, 684, 1, 0, 0, 0, 687, 688, 5, 3, 0, 0, 688, 690, 1, 0, 0, 0, 689, 677, 1, 0, 0, 0, 689, 678, 1, 0, 0, 0, 690, 105, 1, 0, 0, 0, 691, 693, 5, 4, 0, 0, 692, 694, 3, 108, 54, 0, 693, 692, 1, 0, 0, 0, 693, 694, 1, 0, 0, 0, 694, 695, 1, 0, 0, 0, 695, 696, 5, 5, 0, 0, 696, 107, 1, 0, 0, 0, 697, 702, 3, 110, 55, 0, 698, 700, 5, 6, 0, 0, 699, 701, 3, 108, 54, 0, 700, 699, 1, 0, 0, 0, 700, 701, 1, 0, 0, 0, 701, 703, 1, 0, 0, 0, 702, 698, 1, 0, 0, 0, 702, 703, 1, 0, 0, 0, 703, 109, 1, 0, 0, 0, 704, 705, 3, 178, 89, 0, 705, 706, 3, 114, 57, 0, 706, 711, 1, 0, 0, 0, 707, 708, 3, 162, 81, 0, 708, 709, 3, 112, 56, 0, 709, 711, 1, 0, 0, 0, 710, 704, 1, 0, 0, 0, 710, 707, 1, 0, 0, 0, 711, 111, 1, 0, 0, 0, 712, 714, 3, 114, 57, 0, 713, 712, 1, 0, 0, 0, 713, 714, 1, 0, 0, 0, 714, 113, 1, 0, 0, 0, 715, 716, 3, 116, 58, 0, 716, 725, 3, 118, 59, 0, 717, 721, 5, 8, 0, 0, 718, 719, 3, 116, 58, 0, 719, 720, 3, 118, 59, 0, 720, 722, 1, 0, 0, 0, 721, 718, 1, 0, 0, 0, 721, 722, 1, 0, 0, 0, 722, 724, 1, 0, 0, 0, 723, 717, 1, 0, 0, 0, 724, 727, 1, 0, 0, 0, 725, 723, 1, 0, 0, 0, 725, 726, 1, 0, 0, 0, 726, 115, 1, 0, 0, 0, 727, 725, 1, 0, 0, 0, 728, 731, 3, 180, 90, 0, 729, 731, 5, 9, 0, 0, 730, 728, 1, 0, 0, 0, 730, 729, 1, 0, 0, 0, 731, 117, 1, 0, 0, 0, 732, 737, 3, 120, 60, 0, 733, 734, 5, 7, 0, 0, 734, 736, 3, 120, 60, 0, 735, 733, 1, 0, 0, 0, 736, 739, 1, 0, 0, 0, 737, 735, 1, 0, 0, 0, 737, 738, 1, 0, 0, 0, 738, 119, 1, 0, 0, 0, 739, 737, 1, 0, 0, 0, 740, 741, 3, 174, 87, 0, 741, 121, 1, 0, 0, 0, 742, 743, 3, 178, 89, 0, 743, 744, 3, 126, 63, 0, 744, 749, 1, 0, 0, 0, 745, 746, 3, 166, 83, 0, 746, 747, 3, 124, 62, 0, 747, 749, 1, 0, 0, 0, 748, 742, 1, 0, 0, 0, 748, 745, 1, 0, 0, 0, 749, 123, 1, 0, 0, 0, 750, 752, 3, 126, 63, 0, 751, 750, 1, 0, 0, 0, 751, 752, 1, 0, 0, 0, 752, 125, 1, 0, 0, 0, 753, 760, 3, 134, 67, 0, 754, 756, 5, 8, 0, 0, 755, 757, 3, 132, 66, 0, 756, 755, 1, 0, 0, 0, 756, 757, 1, 0, 0, 0, 757, 759, 1, 0, 0, 0, 758, 754, 1, 0, 0, 0, 759, 762, 1, 0, 0, 0, 760, 758, 1, 0, 0, 0, 760, 761, 1, 0, 0, 0, 761, 127, 1, 0, 0, 0, 762, 760, 1, 0, 0, 0, 763, 764, 3, 142, 71, 0, 764, 129, 1, 0, 0, 0, 765, 766, 3, 182, 91, 0, 766, 131, 1, 0, 0, 0, 767, 768, 3, 136, 68, 0, 768, 769, 3, 118, 59, 0, 769, 133, 1, 0, 0, 0, 770, 771, 3, 136, 68, 0, 771, 772, 3, 138, 69, 0, 772, 135, 1, 0, 0, 0, 773, 776, 3, 128, 64, 0, 774, 776, 3, 130, 65, 0, 775, 773, 1, 0, 0, 0, 775, 774, 1, 0, 0, 0, 776, 137, 1, 0, 0, 0, 777, 782, 3, 140, 70, 0, 778, 779, 5, 7, 0, 0, 779, 781, 3, 140, 70, 0, 780, 778, 1, 0, 0, 0, 781, 784, 1, 0, 0, 0, 782, 780, 1, 0, 0, 0, 782, 783, 1, 0, 0, 0, 783, 139, 1, 0, 0, 0, 784, 782, 1, 0, 0, 0, 785, 786, 3, 176, 88, 0, 786, 141, 1, 0, 0, 0, 787, 788, 3, 144, 72, 0, 788, 143, 1, 0, 0, 0, 789, 794, 3, 146, 73, 0, 790, 791, 5, 10, 0, 0, 791, 793, 3, 146, 73, 0, 792, 790, 1, 0, 0, 0, 793, 796, 1, 0, 0, 0, 794, 792, 1, 0, 0, 0, 794, 795, 1, 0, 0, 0, 795, 145, 1, 0, 0, 0, 796, 794, 1, 0, 0, 0, 797, 802, 3, 150, 75, 0, 798, 799, 5, 11, 0, 0, 799, 801, 3, 150, 75, 0, 800, 798, 1, 0, 0, 0, 801, 804, 1, 0, 0, 0, 802, 800, 1, 0, 0, 0, 802, 803, 1, 0, 0, 0, 803, 147, 1, 0, 0, 0, 804, 802, 1, 0, 0, 0, 805, 807, 3, 154, 77, 0, 806, 808, 3, 152, 76, 0, 807, 806, 1, 0, 0, 0, 807, 808, 1, 0, 0, 0, 808, 149, 1, 0, 0, 0, 809, 813, 3, 148, 74, 0, 810, 811, 5, 12, 0, 0, 811, 813, 3, 148, 74, 0, 812, 809, 1, 0, 0, 0, 812, 810, 1, 0, 0, 0, 813, 151, 1, 0, 0, 0, 814, 815, 7, 2, 0, 0, 815, 153, 1, 0, 0, 0, 816, 825, 3, 254, 127, 0, 817, 825, 5, 9, 0, 0, 818, 819, 5, 15, 0, 0, 819, 825, 3, 156, 78, 0, 820, 821, 5, 2, 0, 0, 821, 822, 3, 142, 71, 0, 822, 823, 5, 3, 0, 0, 823, 825, 1, 0, 0, 0, 824, 816, 1, 0, 0, 0, 824, 817, 1, 0, 0, 0, 824, 818, 1, 0, 0, 0, 824, 820, 1, 0, 0, 0, 825, 155, 1, 0, 0, 0, 826, 840, 3, 158, 79, 0, 827, 836, 5, 2, 0, 0, 828, 833, 3, 158, 79, 0, 829, 830, 5, 10, 0, 0, 830, 832, 3, 158, 79, 0, 831, 829, 1, 0, 0, 0, 832, 835, 1, 0, 0, 0, 833, 831, 1, 0, 0, 0, 833, 834, 1, 0, 0, 0, 834, 837, 1, 0, 0, 0, 835, 833, 1, 0, 0, 0, 836, 828, 1, 0, 0, 0, 836, 837, 1, 0, 0, 0, 837, 838, 1, 0, 0, 0, 838, 840, 5, 3, 0, 0, 839, 826, 1, 0, 0, 0, 839, 827, 1, 0, 0, 0, 840, 157, 1, 0, 0, 0, 841, 849, 3, 254, 127, 0, 842, 849, 5, 9, 0, 0, 843, 846, 5, 12, 0, 0, 844, 847, 3, 254, 127, 0, 845, 847, 5, 9, 0, 0, 846, 844, 1, 0, 0, 0, 846, 845, 1, 0, 0, 0, 847, 849, 1, 0, 0, 0, 848, 841, 1, 0, 0, 0, 848, 842, 1, 0, 0, 0, 848, 843, 1, 0, 0, 0, 849, 159, 1, 0, 0, 0, 850, 851, 5, 147, 0, 0, 851, 161, 1, 0, 0, 0, 852, 855, 3, 170, 85, 0, 853, 855, 3, 164, 82, 0, 854, 852, 1, 0, 0, 0, 854, 853, 1, 0, 0, 0, 855, 163, 1, 0, 0, 0, 856, 857, 5, 16, 0, 0, 857, 858, 3, 114, 57, 0, 858, 859, 5, 17, 0, 0, 859, 165, 1, 0, 0, 0, 860, 863, 3, 172, 86, 0, 861, 863, 3, 168, 84, 0, 862, 860, 1, 0, 0, 0, 862, 861, 1, 0, 0, 0, 863, 167, 1, 0, 0, 0, 864, 865, 5, 16, 0, 0, 865, 866, 3, 126, 63, 0, 866, 867, 5, 17, 0, 0, 867, 169, 1, 0, 0, 0, 868, 870, 5, 2, 0, 0, 869, 871, 3, 174, 87, 0, 870, 869, 1, 0, 0, 0, 871, 872, 1, 0, 0, 0, 872, 870, 1, 0, 0, 0, 872, 873, 1, 0, 0, 0, 873, 874, 1, 0, 0, 0, 874, 875, 5, 3, 0, 0, 875, 171, 1, 0, 0, 0, 876, 878, 5, 2, 0, 0, 877, 879, 3, 176, 88, 0, 878, 877, 1, 0, 0, 0, 879, 880, 1, 0, 0, 0, 880, 878, 1, 0, 0, 0, 880, 881, 1, 0, 0, 0, 881, 882, 1, 0, 0, 0, 882, 883, 5, 3, 0, 0, 883, 173, 1, 0, 0, 0, 884, 887, 3, 178, 89, 0, 885, 887, 3, 162, 81, 0, 886, 884, 1, 0, 0, 0, 886, 885, 1, 0, 0, 0, 887, 175, 1, 0, 0, 0, 888, 891, 3, 178, 89, 0, 889, 891, 3, 166, 83, 0, 890, 888, 1, 0, 0, 0, 890, 889, 1, 0, 0, 0, 891, 177, 1, 0, 0, 0, 892, 895, 3, 182, 91, 0, 893, 895, 3, 184, 92, 0, 894, 892, 1, 0, 0, 0, 894, 893, 1, 0, 0, 0, 895, 179, 1, 0, 0, 0, 896, 899, 3, 182, 91, 0, 897, 899, 3, 254, 127, 0, 898, 896, 1, 0, 0, 0, 898, 897, 1, 0, 0, 0, 899, 181, 1, 0, 0, 0, 900, 901, 7, 3, 0, 0, 901, 183, 1, 0, 0, 0, 902, 909, 3, 254, 127, 0, 903, 909, 3, 240, 120, 0, 904, 909, 3, 242, 121, 0, 905, 909, 3, 250, 125, 0, 906, 909, 3, 258, 129, 0, 907, 909, 5, 162, 0, 0, 908, 902, 1, 0, 0, 0, 908, 903, 1, 0, 0, 0, 908, 904, 1, 0, 0, 0, 908, 905, 1, 0, 0, 0, 908, 906, 1, 0, 0, 0, 908, 907, 1, 0, 0, 0, 909, 185, 1, 0, 0, 0, 910, 911, 3, 188, 94, 0, 911, 187, 1, 0, 0, 0, 912, 917, 3, 190, 95, 0, 913, 914, 5, 18, 0, 0, 914, 916, 3, 190, 95, 0, 915, 913, 1, 0, 0, 0, 916, 919, 1, 0, 0, 0, 917, 915, 1, 0, 0, 0, 917, 918, 1, 0, 0, 0, 918, 189, 1, 0, 0, 0, 919, 917, 1, 0, 0, 0, 920, 925, 3, 192, 96, 0, 921, 922, 5, 19, 0, 0, 922, 924, 3, 192, 96, 0, 923, 921, 1, 0, 0, 0, 924, 927, 1, 0, 0, 0, 925, 923, 1, 0, 0, 0, 925, 926, 1, 0, 0, 0, 926, 191, 1, 0, 0, 0, 927, 925, 1, 0, 0, 0, 928, 929, 3, 194, 97, 0, 929, 193, 1, 0, 0, 0, 930, 948, 3, 196, 98, 0, 931, 932, 5, 20, 0, 0, 932, 949, 3, 196, 98, 0, 933, 934, 5, 21, 0, 0, 934, 949, 3, 196, 98, 0, 935, 936, 5, 22, 0, 0, 936, 949, 3, 196, 98, 0, 937, 938, 5, 23, 0, 0, 938, 949, 3, 196, 98, 0, 939, 940, 5, 24, 0, 0, 940, 949, 3, 196, 98, 0, 941, 942, 5, 25, 0, 0, 942, 949, 3, 196, 98, 0, 943, 944, 5, 77, 0, 0, 944, 949, 3, 104, 52, 0, 945, 946, 5, 76, 0, 0, 946, 947, 5, 77, 0, 0, 947, 949, 3, 104, 52, 0, 948, 931, 1, 0, 0, 0, 948, 933, 1, 0, 0, 0, 948, 935, 1, 0, 0, 0, 948, 937, 1, 0, 0, 0, 948, 939, 1, 0, 0, 0, 948, 941, 1, 0, 0, 0, 948, 943, 1, 0, 0, 0, 948, 945, 1, 0, 0, 0, 948, 949, 1, 0, 0, 0, 949, 195, 1, 0, 0, 0, 950, 951, 3, 198, 99, 0, 951, 197, 1, 0, 0, 0, 952, 956, 3, 208, 104, 0, 953, 955, 3, 200, 100, 0, 954, 953, 1, 0, 0, 0, 955, 958, 1, 0, 0, 0, 956, 954, 1, 0, 0, 0, 956, 957, 1, 0, 0, 0, 957, 199, 1, 0, 0, 0, 958, 956, 1, 0, 0, 0, 959, 960, 5, 13, 0, 0, 960, 965, 3, 202, 101, 0, 961, 962, 5, 26, 0, 0, 962, 965, 3, 204, 102, 0, 963, 965, 3, 206, 103, 0, 964, 959, 1, 0, 0, 0, 964, 961, 1, 0, 0, 0, 964, 963, 1, 0, 0, 0, 965, 201, 1, 0, 0, 0, 966, 967, 3, 208, 104, 0, 967, 203, 1, 0, 0, 0, 968, 969, 3, 208, 104, 0, 969, 205, 1, 0, 0, 0, 970, 973, 3, 246, 123, 0, 971, 973, 3, 248, 124, 0, 972, 970, 1, 0, 0, 0, 972, 971, 1, 0, 0, 0, 973, 977, 1, 0, 0, 0, 974, 976, 3, 210, 105, 0, 975, 974, 1, 0, 0, 0, 976, 979, 1, 0, 0, 0, 977, 975, 1, 0, 0, 0, 977, 978, 1, 0, 0, 0, 978, 207, 1, 0, 0, 0, 979, 977, 1, 0, 0, 0, 980, 984, 3, 216, 108, 0, 981, 983, 3, 210, 105, 0, 982, 981, 1, 0, 0, 0, 983, 986, 1, 0, 0, 0, 984, 982, 1, 0, 0, 0, 984, 985, 1, 0, 0, 0, 985, 209, 1, 0, 0, 0, 986, 984, 1, 0, 0, 0, 987, 990, 3, 212, 106, 0, 988, 990, 3, 214, 107, 0, 989, 987, 1, 0, 0, 0, 989, 988, 1, 0, 0, 0, 990, 211, 1, 0, 0, 0, 991, 992, 5, 1, 0, 0, 992, 993, 3, 216, 108, 0, 993, 213, 1, 0, 0, 0, 994, 995, 5, 11, 0, 0, 995, 996, 3, 216, 108, 0, 996, 215, 1, 0, 0, 0, 997, 998, 5, 15, 0, 0, 998, 1005, 3, 218, 109, 0, 999, 1000, 5, 13, 0, 0, 1000, 1005, 3, 218, 109, 0, 1001, 1002, 5, 26, 0, 0, 1002, 1005, 3, 218, 109, 0, 1003, 1005, 3, 218, 109, 0, 1004, 997, 1, 0, 0, 0, 1004, 999, 1, 0, 0, 0, 1004, 1001, 1, 0, 0, 0, 1004, 1003, 1, 0, 0, 0, 1005, 217, 1, 0, 0, 0, 1006, 1014, 3, 220, 110, 0, 1007, 1014, 3, 222, 111, 0, 1008, 1014, 3, 238, 119, 0, 1009, 1014, 3, 240, 120, 0, 1010, 1014, 3, 242, 121, 0, 1011, 1014, 3, 250, 125, 0, 1012, 1014, 3, 182, 91, 0, 1013, 1006, 1, 0, 0, 0, 1013, 1007, 1, 0, 0, 0, 1013, 1008, 1, 0, 0, 0, 1013, 1009, 1, 0, 0, 0, 1013, 1010, 1, 0, 0, 0, 1013, 1011, 1, 0, 0, 0, 1013, 1012, 1, 0, 0, 0, 1014, 219, 1, 0, 0, 0, 1015, 1016, 5, 2, 0, 0, 1016, 1017, 3, 186, 93, 0, 1017, 1018, 5, 3, 0, 0, 1018, 221, 1, 0, 0, 0, 1019, 1274, 3, 236, 118, 0, 1020, 1021, 5, 78, 0, 0, 1021, 1022, 5, 2, 0, 0, 1022, 1023, 3, 186, 93, 0, 1023, 1024, 5, 3, 0, 0, 1024, 1274, 1, 0, 0, 0, 1025, 1274, 3, 226, 113, 0, 1026, 1027, 5, 80, 0, 0, 1027, 1028, 5, 2, 0, 0, 1028, 1029, 3, 186, 93, 0, 1029, 1030, 5, 7, 0, 0, 1030, 1031, 3, 186, 93, 0, 1031, 1032, 5, 3, 0, 0, 1032, 1274, 1, 0, 0, 0, 1033, 1034, 5, 81, 0, 0, 1034, 1035, 5, 2, 0, 0, 1035, 1036, 3, 186, 93, 0, 1036, 1037, 5, 3, 0, 0, 1037, 1274, 1, 0, 0, 0, 1038, 1039, 5, 82, 0, 0, 1039, 1040, 5, 2, 0, 0, 1040, 1041, 3, 182, 91, 0, 1041, 1042, 5, 3, 0, 0, 1042, 1274, 1, 0, 0, 0, 1043, 1044, 5, 83, 0, 0, 1044, 1045, 5, 2, 0, 0, 1045, 1046, 3, 186, 93, 0, 1046, 1047, 5, 3, 0, 0, 1047, 1274, 1, 0, 0, 0, 1048, 1049, 5, 84, 0, 0, 1049, 1050, 5, 2, 0, 0, 1050, 1051, 3, 186, 93, 0, 1051, 1052, 5, 3, 0, 0, 1052, 1274, 1, 0, 0, 0, 1053, 1059, 5, 85, 0, 0, 1054, 1055, 5, 2, 0, 0, 1055, 1056, 3, 186, 93, 0, 1056, 1057, 5, 3, 0, 0, 1057, 1060, 1, 0, 0, 0, 1058, 1060, 5, 162, 0, 0, 1059, 1054, 1, 0, 0, 0, 1059, 1058, 1, 0, 0, 0, 1060, 1274, 1, 0, 0, 0, 1061, 1062, 5, 86, 0, 0, 1062, 1274, 5, 162, 0, 0, 1063, 1064, 5, 87, 0, 0, 1064, 1065, 5, 2, 0, 0, 1065, 1066, 3, 186, 93, 0, 1066, 1067, 5, 3, 0, 0, 1067, 1274, 1, 0, 0, 0, 1068, 1069, 5, 88, 0, 0, 1069, 1070, 5, 2, 0, 0, 1070, 1071, 3, 186, 93, 0, 1071, 1072, 5, 3, 0, 0, 1072, 1274, 1, 0, 0, 0, 1073, 1074, 5, 89, 0, 0, 1074, 1075, 5, 2, 0, 0, 1075, 1076, 3, 186, 93, 0, 1076, 1077, 5, 3, 0, 0, 1077, 1274, 1, 0, 0, 0, 1078, 1079, 5, 90, 0, 0, 1079, 1080, 5, 2, 0, 0, 1080, 1081, 3, 186, 93, 0, 1081, 1082, 5, 3, 0, 0, 1082, 1274, 1, 0, 0, 0, 1083, 1084, 5, 91, 0, 0, 1084, 1274, 3, 104, 52, 0, 1085, 1274, 3, 228, 114, 0, 1086, 1087, 5, 92, 0, 0, 1087, 1088, 5, 2, 0, 0, 1088, 1089, 3, 186, 93, 0, 1089, 1090, 5, 3, 0, 0, 1090, 1274, 1, 0, 0, 0, 1091, 1274, 3, 230, 115, 0, 1092, 1093, 5, 93, 0, 0, 1093, 1094, 5, 2, 0, 0, 1094, 1095, 3, 186, 93, 0, 1095, 1096, 5, 3, 0, 0, 1096, 1274, 1, 0, 0, 0, 1097, 1098, 5, 94, 0, 0, 1098, 1099, 5, 2, 0, 0, 1099, 1100, 3, 186, 93, 0, 1100, 1101, 5, 3, 0, 0, 1101, 1274, 1, 0, 0, 0, 1102, 1103, 5, 95, 0, 0, 1103, 1104, 5, 2, 0, 0, 1104, 1105, 3, 186, 93, 0, 1105, 1106, 5, 3, 0, 0, 1106, 1274, 1, 0, 0, 0, 1107, 1108, 5, 97, 0, 0, 1108, 1109, 5, 2, 0, 0, 1109, 1110, 3, 186, 93, 0, 1110, 1111, 5, 7, 0, 0, 1111, 1112, 3, 186, 93, 0, 1112, 1113, 5, 3, 0, 0, 1113, 1274, 1, 0, 0, 0, 1114, 1115, 5, 98, 0, 0, 1115, 1116, 5, 2, 0, 0, 1116, 1117, 3, 186, 93, 0, 1117, 1118, 5, 7, 0, 0, 1118, 1119, 3, 186, 93, 0, 1119, 1120, 5, 3, 0, 0, 1120, 1274, 1, 0, 0, 0, 1121, 1122, 5, 99, 0, 0, 1122, 1123, 5, 2, 0, 0, 1123, 1124, 3, 186, 93, 0, 1124, 1125, 5, 7, 0, 0, 1125, 1126, 3, 186, 93, 0, 1126, 1127, 5, 3, 0, 0, 1127, 1274, 1, 0, 0, 0, 1128, 1129, 5, 100, 0, 0, 1129, 1130, 5, 2, 0, 0, 1130, 1131, 3, 186, 93, 0, 1131, 1132, 5, 7, 0, 0, 1132, 1133, 3, 186, 93, 0, 1133, 1134, 5, 3, 0, 0, 1134, 1274, 1, 0, 0, 0, 1135, 1136, 5, 101, 0, 0, 1136, 1137, 5, 2, 0, 0, 1137, 1138, 3, 186, 93, 0, 1138, 1139, 5, 7, 0, 0, 1139, 1140, 3, 186, 93, 0, 1140, 1141, 5, 3, 0, 0, 1141, 1274, 1, 0, 0, 0, 1142, 1143, 5, 102, 0, 0, 1143, 1144, 5, 2, 0, 0, 1144, 1145, 3, 186, 93, 0, 1145, 1146, 5, 3, 0, 0, 1146, 1274, 1, 0, 0, 0, 1147, 1148, 5, 103, 0, 0, 1148, 1149, 5, 2, 0, 0, 1149, 1150, 3, 186, 93, 0, 1150, 1151, 5, 3, 0, 0, 1151, 1274, 1, 0, 0, 0, 1152, 1153, 5, 104, 0, 0, 1153, 1154, 5, 2, 0, 0, 1154, 1155, 3, 186, 93, 0, 1155, 1156, 5, 3, 0, 0, 1156, 1274, 1, 0, 0, 0, 1157, 1158, 5, 105, 0, 0, 1158, 1159, 5, 2, 0, 0, 1159, 1160, 3, 186, 93, 0, 1160, 1161, 5, 3, 0, 0, 1161, 1274, 1, 0, 0, 0, 1162, 1163, 5, 106, 0, 0, 1163, 1164, 5, 2, 0, 0, 1164, 1165, 3, 186, 93, 0, 1165, 1166, 5, 3, 0, 0, 1166, 1274, 1, 0, 0, 0, 1167, 1168, 5, 107, 0, 0, 1168, 1169, 5, 2, 0, 0, 1169, 1170, 3, 186, 93, 0, 1170, 1171, 5, 3, 0, 0, 1171, 1274, 1, 0, 0, 0, 1172, 1173, 5, 108, 0, 0, 1173, 1174, 5, 2, 0, 0, 1174, 1175, 3, 186, 93, 0, 1175, 1176, 5, 3, 0, 0, 1176, 1274, 1, 0, 0, 0, 1177, 1178, 5, 109, 0, 0, 1178, 1179, 5, 2, 0, 0, 1179, 1180, 3, 186, 93, 0, 1180, 1181, 5, 3, 0, 0, 1181, 1274, 1, 0, 0, 0, 1182, 1183, 5, 110, 0, 0, 1183, 1274, 5, 162, 0, 0, 1184, 1185, 5, 111, 0, 0, 1185, 1274, 5, 162, 0, 0, 1186, 1187, 5, 112, 0, 0, 1187, 1274, 5, 162, 0, 0, 1188, 1189, 5, 117, 0, 0, 1189, 1190, 5, 2, 0, 0, 1190, 1191, 3, 186, 93, 0, 1191, 1192, 5, 3, 0, 0, 1192, 1274, 1, 0, 0, 0, 1193, 1194, 5, 113, 0, 0, 1194, 1195, 5, 2, 0, 0, 1195, 1196, 3, 186, 93, 0, 1196, 1197, 5, 3, 0, 0, 1197, 1274, 1, 0, 0, 0, 1198, 1199, 5, 114, 0, 0, 1199, 1200, 5, 2, 0, 0, 1200, 1201, 3, 186, 93, 0, 1201, 1202, 5, 3, 0, 0, 1202, 1274, 1, 0, 0, 0, 1203, 1204, 5, 115, 0, 0, 1204, 1205, 5, 2, 0, 0, 1205, 1206, 3, 186, 93, 0, 1206, 1207, 5, 3, 0, 0, 1207, 1274, 1, 0, 0, 0, 1208, 1209, 5, 116, 0, 0, 1209, 1210, 5, 2, 0, 0, 1210, 1211, 3, 186, 93, 0, 1211, 1212, 5, 3, 0, 0, 1212, 1274, 1, 0, 0, 0, 1213, 1214, 5, 118, 0, 0, 1214, 1274, 3, 104, 52, 0, 1215, 1216, 5, 119, 0, 0, 1216, 1217, 5, 2, 0, 0, 1217, 1218, 3, 186, 93, 0, 1218, 1219, 5, 7, 0, 0, 1219, 1220, 3, 186, 93, 0, 1220, 1221, 5, 7, 0, 0, 1221, 1222, 3, 186, 93, 0, 1222, 1223, 5, 3, 0, 0, 1223, 1274, 1, 0, 0, 0, 1224, 1225, 5, 120, 0, 0, 1225, 1226, 5, 2, 0, 0, 1226, 1227, 3, 186, 93, 0, 1227, 1228, 5, 7, 0, 0, 1228, 1229, 3, 186, 93, 0, 1229, 1230, 5, 3, 0, 0, 1230, 1274, 1, 0, 0, 0, 1231, 1232, 5, 121, 0, 0, 1232, 1233, 5, 2, 0, 0, 1233, 1234, 3, 186, 93, 0, 1234, 1235, 5, 7, 0, 0, 1235, 1236, 3, 186, 93, 0, 1236, 1237, 5, 3, 0, 0, 1237, 1274, 1, 0, 0, 0, 1238, 1239, 5, 122, 0, 0, 1239, 1240, 5, 2, 0, 0, 1240, 1241, 3, 186, 93, 0, 1241, 1242, 5, 7, 0, 0, 1242, 1243, 3, 186, 93, 0, 1243, 1244, 5, 3, 0, 0, 1244, 1274, 1, 0, 0, 0, 1245, 1246, 5, 123, 0, 0, 1246, 1247, 5, 2, 0, 0, 1247, 1248, 3, 186, 93, 0, 1248, 1249, 5, 3, 0, 0, 1249, 1274, 1, 0, 0, 0, 1250, 1251, 5, 124, 0, 0, 1251, 1252, 5, 2, 0, 0, 1252, 1253, 3, 186, 93, 0, 1253, 1254, 5, 3, 0, 0, 1254, 1274, 1, 0, 0, 0, 1255, 1256, 5, 125, 0, 0, 1256, 1257, 5, 2, 0, 0, 1257, 1258, 3, 186, 93, 0, 1258, 1259, 5, 3, 0, 0, 1259, 1274, 1, 0, 0, 0, 1260, 1261, 5, 126, 0, 0, 1261, 1262, 5, 2, 0, 0, 1262, 1263, 3, 186, 93, 0, 1263, 1264, 5, 3, 0, 0, 1264, 1274, 1, 0, 0, 0, 1265, 1266, 5, 127, 0, 0, 1266, 1267, 5, 2, 0, 0, 1267, 1268, 3, 186, 93, 0, 1268, 1269, 5, 3, 0, 0, 1269, 1274, 1, 0, 0, 0, 1270, 1274, 3, 224, 112, 0, 1271, 1274, 3, 232, 116, 0, 1272, 1274, 3, 234, 117, 0, 1273, 1019, 1, 0, 0, 0, 1273, 1020, 1, 0, 0, 0, 1273, 1025, 1, 0, 0, 0, 1273, 1026, 1, 0, 0, 0, 1273, 1033, 1, 0, 0, 0, 1273, 1038, 1, 0, 0, 0, 1273, 1043, 1, 0, 0, 0, 1273, 1048, 1, 0, 0, 0, 1273, 1053, 1, 0, 0, 0, 1273, 1061, 1, 0, 0, 0, 1273, 1063, 1, 0, 0, 0, 1273, 1068, 1, 0, 0, 0, 1273, 1073, 1, 0, 0, 0, 1273, 1078, 1, 0, 0, 0, 1273, 1083, 1, 0, 0, 0, 1273, 1085, 1, 0, 0, 0, 1273, 1086, 1, 0, 0, 0, 1273, 1091, 1, 0, 0, 0, 1273, 1092, 1, 0, 0, 0, 1273, 1097, 1, 0, 0, 0, 1273, 1102, 1, 0, 0, 0, 1273, 1107, 1, 0, 0, 0, 1273, 1114, 1, 0, 0, 0, 1273, 1121, 1, 0, 0, 0, 1273, 1128, 1, 0, 0, 0, 1273, 1135, 1, 0, 0, 0, 1273, 1142, 1, 0, 0, 0, 1273, 1147, 1, 0, 0, 0, 1273, 1152, 1, 0, 0, 0, 1273, 1157, 1, 0, 0, 0, 1273, 1162, 1, 0, 0, 0, 1273, 1167, 1, 0, 0, 0, 1273, 1172, 1, 0, 0, 0, 1273, 1177, 1, 0, 0, 0, 1273, 1182, 1, 0, 0, 0, 1273, 1184, 1, 0, 0, 0, 1273, 1186, 1, 0, 0, 0, 1273, 1188, 1, 0, 0, 0, 1273, 1193, 1, 0, 0, 0, 1273, 1198, 1, 0, 0, 0, 1273, 1203, 1, 0, 0, 0, 1273, 1208, 1, 0, 0, 0, 1273, 1213, 1, 0, 0, 0, 1273, 1215, 1, 0, 0, 0, 1273, 1224, 1, 0, 0, 0, 1273, 1231, 1, 0, 0, 0, 1273, 1238, 1, 0, 0, 0, 1273, 1245, 1, 0, 0, 0, 1273, 1250, 1, 0, 0, 0, 1273, 1255, 1, 0, 0, 0, 1273, 1260, 1, 0, 0, 0, 1273, 1265, 1, 0, 0, 0, 1273, 1270, 1, 0, 0, 0, 1273, 1271, 1, 0, 0, 0, 1273, 1272, 1, 0, 0, 0, 1274, 223, 1, 0, 0, 0, 1275, 1276, 5, 128, 0, 0, 1276, 1277, 5, 2, 0, 0, 1277, 1278, 3, 186, 93, 0, 1278, 1279, 5, 7, 0, 0, 1279, 1282, 3, 186, 93, 0, 1280, 1281, 5, 7, 0, 0, 1281, 1283, 3, 186, 93, 0, 1282, 1280, 1, 0, 0, 0, 1282, 1283, 1, 0, 0, 0, 1283, 1284, 1, 0, 0, 0, 1284, 1285, 5, 3, 0, 0, 1285, 225, 1, 0, 0, 0, 1286, 1287, 5, 79, 0, 0, 1287, 1288, 5, 2, 0, 0, 1288, 1289, 3, 186, 93, 0, 1289, 1290, 5, 3, 0, 0, 1290, 227, 1, 0, 0, 0, 1291, 1292, 5, 129, 0, 0, 1292, 1293, 5, 2, 0, 0, 1293, 1294, 3, 186, 93, 0, 1294, 1295, 5, 7, 0, 0, 1295, 1298, 3, 186, 93, 0, 1296, 1297, 5, 7, 0, 0, 1297, 1299, 3, 186, 93, 0, 1298, 1296, 1, 0, 0, 0, 1298, 1299, 1, 0, 0, 0, 1299, 1300, 1, 0, 0, 0, 1300, 1301, 5, 3, 0, 0, 1301, 229, 1, 0, 0, 0, 1302, 1303, 5, 130, 0, 0, 1303, 1304, 5, 2, 0, 0, 1304, 1305, 3, 186, 93, 0, 1305, 1306, 5, 7, 0, 0, 1306, 1307, 3, 186, 93, 0, 1307, 1308, 5, 7, 0, 0, 1308, 1311, 3, 186, 93, 0, 1309, 1310, 5, 7, 0, 0, 1310, 1312, 3, 186, 93, 0, 1311, 1309, 1, 0, 0, 0, 1311, 1312, 1, 0, 0, 0, 1312, 1313, 1, 0, 0, 0, 1313, 1314, 5, 3, 0, 0, 1314, 231, 1, 0, 0, 0, 1315, 1316, 5, 131, 0, 0, 1316, 1317, 3, 62, 31, 0, 1317, 233, 1, 0, 0, 0, 1318, 1319, 5, 76, 0, 0, 1319, 1320, 5, 131, 0, 0, 1320, 1321, 3, 62, 31, 0, 1321, 235, 1, 0, 0, 0, 1322, 1323, 5, 132, 0, 0, 1323, 1325, 5, 2, 0, 0, 1324, 1326, 5, 33, 0, 0, 1325, 1324, 1, 0, 0, 0, 1325, 1326, 1, 0, 0, 0, 1326, 1329, 1, 0, 0, 0, 1327, 1330, 5, 1, 0, 0, 1328, 1330, 3, 186, 93, 0, 1329, 1327, 1, 0, 0, 0, 1329, 1328, 1, 0, 0, 0, 1330, 1331, 1, 0, 0, 0, 1331, 1387, 5, 3, 0, 0, 1332, 1333, 5, 133, 0, 0, 1333, 1335, 5, 2, 0, 0, 1334, 1336, 5, 33, 0, 0, 1335, 1334, 1, 0, 0, 0, 1335, 1336, 1, 0, 0, 0, 1336, 1337, 1, 0, 0, 0, 1337, 1338, 3, 186, 93, 0, 1338, 1339, 5, 3, 0, 0, 1339, 1387, 1, 0, 0, 0, 1340, 1341, 5, 134, 0, 0, 1341, 1343, 5, 2, 0, 0, 1342, 1344, 5, 33, 0, 0, 1343, 1342, 1, 0, 0, 0, 1343, 1344, 1, 0, 0, 0, 1344, 1345, 1, 0, 0, 0, 1345, 1346, 3, 186, 93, 0, 1346, 1347, 5, 3, 0, 0, 1347, 1387, 1, 0, 0, 0, 1348, 1349, 5, 135, 0, 0, 1349, 1351, 5, 2, 0, 0, 1350, 1352, 5, 33, 0, 0, 1351, 1350, 1, 0, 0, 0, 1351, 1352, 1, 0, 0, 0, 1352, 1353, 1, 0, 0, 0, 1353, 1354, 3, 186, 93, 0, 1354, 1355, 5, 3, 0, 0, 1355, 1387, 1, 0, 0, 0, 1356, 1357, 5, 136, 0, 0, 1357, 1359, 5, 2, 0, 0, 1358, 1360, 5, 33, 0, 0, 1359, 1358, 1, 0, 0, 0, 1359, 1360, 1, 0, 0, 0, 1360, 1361, 1, 0, 0, 0, 1361, 1362, 3, 186, 93, 0, 1362, 1363, 5, 3, 0, 0, 1363, 1387, 1, 0, 0, 0, 1364, 1365, 5, 137, 0, 0, 1365, 1367, 5, 2, 0, 0, 1366, 1368, 5, 33, 0, 0, 1367, 1366, 1, 0, 0, 0, 1367, 1368, 1, 0, 0, 0, 1368, 1369, 1, 0, 0, 0, 1369, 1370, 3, 186, 93, 0, 1370, 1371, 5, 3, 0, 0, 1371, 1387, 1, 0, 0, 0, 1372, 1373, 5, 43, 0, 0, 1373, 1375, 5, 2, 0, 0, 1374, 1376, 5, 33, 0, 0, 1375, 1374, 1, 0, 0, 0, 1375, 1376, 1, 0, 0, 0, 1376, 1377, 1, 0, 0, 0, 1377, 1382, 3, 186, 93, 0, 1378, 1379, 5, 8, 0, 0, 1379, 1380, 5, 138, 0, 0, 1380, 1381, 5, 20, 0, 0, 1381, 1383, 3, 252, 126, 0, 1382, 1378, 1, 0, 0, 0, 1382, 1383, 1, 0, 0, 0, 1383, 1384, 1, 0, 0, 0, 1384, 1385, 5, 3, 0, 0, 1385, 1387, 1, 0, 0, 0, 1386, 1322, 1, 0, 0, 0, 1386, 1332, 1, 0, 0, 0, 1386, 1340, 1, 0, 0, 0, 1386, 1348, 1, 0, 0, 0, 1386, 1356, 1, 0, 0, 0, 1386, 1364, 1, 0, 0, 0, 1386, 1372, 1, 0, 0, 0, 1387, 237, 1, 0, 0, 0, 1388, 1390, 3, 254, 127, 0, 1389, 1391, 3, 102, 51, 0, 1390, 1389, 1, 0, 0, 0, 1390, 1391, 1, 0, 0, 0, 1391, 239, 1, 0, 0, 0, 1392, 1396, 3, 252, 126, 0, 1393, 1397, 5, 145, 0, 0, 1394, 1395, 5, 27, 0, 0, 1395, 1397, 3, 254, 127, 0, 1396, 1393, 1, 0, 0, 0, 1396, 1394, 1, 0, 0, 0, 1396, 1397, 1, 0, 0, 0, 1397, 241, 1, 0, 0, 0, 1398, 1402, 3, 244, 122, 0, 1399, 1402, 3, 246, 123, 0, 1400, 1402, 3, 248, 124, 0, 1401, 1398, 1, 0, 0, 0, 1401, 1399, 1, 0, 0, 0, 1401, 1400, 1, 0, 0, 0, 1402, 243, 1, 0, 0, 0, 1403, 1404, 7, 4, 0, 0, 1404, 245, 1, 0, 0, 0, 1405, 1406, 7, 5, 0, 0, 1406, 247, 1, 0, 0, 0, 1407, 1408, 7, 6, 0, 0, 1408, 249, 1, 0, 0, 0, 1409, 1410, 7, 7, 0, 0, 1410, 251, 1, 0, 0, 0, 1411, 1412, 7, 8, 0, 0, 1412, 253, 1, 0, 0, 0, 1413, 1415, 5, 146, 0, 0, 1414, 1413, 1, 0, 0, 0, 1414, 1415, 1, 0, 0, 0, 1415, 1418, 1, 0, 0, 0, 1416, 1419, 3, 260, 130, 0, 1417, 1419, 3, 256, 128, 0, 1418, 1416, 1, 0, 0, 0, 1418, 1417, 1, 0, 0, 0, 1419, 255, 1, 0, 0, 0, 1420, 1423, 3, 262, 131, 0, 1421, 1423, 3, 264, 132, 0, 1422, 1420, 1, 0, 0, 0, 1422, 1421, 1, 0, 0, 0, 1423, 257, 1, 0, 0, 0, 1424, 1425, 7, 9, 0, 0, 1425, 259, 1, 0, 0, 0, 1426, 1427, 5, 139, 0, 0, 1427, 261, 1, 0, 0, 0, 1428, 1429, 5, 141, 0, 0, 1429, 263, 1, 0, 0, 0, 1430, 1431, 5, 140, 0, 0, 1431, 265, 1, 0, 0, 0, 137, 271, 278, 280, 294, 307, 312, 315, 319, 334, 343, 349, 353, 359, 362, 367, 371, 379, 388, 398, 403, 406, 409, 412, 418, 426, 431, 437, 443, 448, 454, 456, 460, 463, 467, 470, 474, 477, 481, 484, 488, 491, 495, 498, 500, 513, 518, 520, 525, 530, 535, 540, 543, 548, 550, 560, 571, 588, 595, 605, 609, 615, 624, 629, 636, 646, 655, 663, 670, 675, 684, 689, 693, 700, 702, 710, 713, 721, 725, 730, 737, 748, 751, 756, 760, 775, 782, 794, 802, 807, 812, 824, 833, 836, 839, 846, 848, 854, 862, 872, 880, 886, 890, 894, 898, 908, 917, 925, 948, 956, 964, 972, 977, 984, 989, 1004, 1013, 1059, 1273, 1282, 1298, 1311, 1325, 1329, 1335, 1343, 1351, 1359, 1367, 1375, 1382, 1386, 1390, 1396, 1401, 1414, 1418, 1422] \ No newline at end of file +[4, 1, 175, 1647, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 2, 93, 7, 93, 2, 94, 7, 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, 2, 103, 7, 103, 2, 104, 7, 104, 2, 105, 7, 105, 2, 106, 7, 106, 2, 107, 7, 107, 2, 108, 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, 111, 7, 111, 2, 112, 7, 112, 2, 113, 7, 113, 2, 114, 7, 114, 2, 115, 7, 115, 2, 116, 7, 116, 2, 117, 7, 117, 2, 118, 7, 118, 2, 119, 7, 119, 2, 120, 7, 120, 2, 121, 7, 121, 2, 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, 7, 130, 2, 131, 7, 131, 2, 132, 7, 132, 2, 133, 7, 133, 2, 134, 7, 134, 2, 135, 7, 135, 2, 136, 7, 136, 2, 137, 7, 137, 2, 138, 7, 138, 2, 139, 7, 139, 2, 140, 7, 140, 2, 141, 7, 141, 2, 142, 7, 142, 2, 143, 7, 143, 2, 144, 7, 144, 2, 145, 7, 145, 2, 146, 7, 146, 2, 147, 7, 147, 2, 148, 7, 148, 2, 149, 7, 149, 2, 150, 7, 150, 2, 151, 7, 151, 2, 152, 7, 152, 2, 153, 7, 153, 2, 154, 7, 154, 2, 155, 7, 155, 2, 156, 7, 156, 1, 0, 1, 0, 1, 0, 1, 0, 3, 0, 319, 8, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 326, 8, 1, 1, 1, 1, 1, 1, 2, 1, 2, 5, 2, 332, 8, 2, 10, 2, 12, 2, 335, 9, 2, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 5, 5, 346, 8, 5, 10, 5, 12, 5, 349, 9, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 3, 7, 361, 8, 7, 1, 7, 4, 7, 364, 8, 7, 11, 7, 12, 7, 365, 1, 7, 3, 7, 369, 8, 7, 1, 8, 1, 8, 3, 8, 373, 8, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 5, 11, 386, 8, 11, 10, 11, 12, 11, 389, 9, 11, 1, 11, 1, 11, 1, 11, 1, 11, 5, 11, 395, 8, 11, 10, 11, 12, 11, 398, 9, 11, 1, 11, 1, 11, 1, 11, 3, 11, 403, 8, 11, 1, 11, 1, 11, 3, 11, 407, 8, 11, 1, 12, 1, 12, 4, 12, 411, 8, 12, 11, 12, 12, 12, 412, 1, 12, 3, 12, 416, 8, 12, 1, 12, 5, 12, 419, 8, 12, 10, 12, 12, 12, 422, 9, 12, 1, 12, 3, 12, 425, 8, 12, 1, 12, 1, 12, 1, 13, 1, 13, 5, 13, 431, 8, 13, 10, 13, 12, 13, 434, 9, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 3, 14, 442, 8, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 3, 18, 452, 8, 18, 1, 18, 1, 18, 1, 19, 3, 19, 457, 8, 19, 1, 19, 3, 19, 460, 8, 19, 1, 19, 3, 19, 463, 8, 19, 1, 19, 3, 19, 466, 8, 19, 1, 20, 1, 20, 4, 20, 470, 8, 20, 11, 20, 12, 20, 471, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 3, 21, 480, 8, 21, 1, 21, 1, 21, 1, 21, 3, 21, 485, 8, 21, 1, 22, 1, 22, 4, 22, 489, 8, 22, 11, 22, 12, 22, 490, 1, 23, 1, 23, 1, 24, 1, 24, 3, 24, 497, 8, 24, 1, 24, 4, 24, 500, 8, 24, 11, 24, 12, 24, 501, 1, 25, 1, 25, 1, 25, 1, 25, 3, 25, 508, 8, 25, 3, 25, 510, 8, 25, 1, 26, 1, 26, 3, 26, 514, 8, 26, 1, 26, 3, 26, 517, 8, 26, 1, 26, 1, 26, 3, 26, 521, 8, 26, 1, 26, 3, 26, 524, 8, 26, 1, 26, 1, 26, 3, 26, 528, 8, 26, 1, 26, 3, 26, 531, 8, 26, 1, 26, 1, 26, 3, 26, 535, 8, 26, 1, 26, 3, 26, 538, 8, 26, 1, 26, 1, 26, 3, 26, 542, 8, 26, 1, 26, 3, 26, 545, 8, 26, 1, 26, 1, 26, 3, 26, 549, 8, 26, 1, 26, 3, 26, 552, 8, 26, 3, 26, 554, 8, 26, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 3, 30, 567, 8, 30, 1, 31, 1, 31, 1, 31, 1, 31, 3, 31, 573, 8, 31, 3, 31, 575, 8, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 3, 32, 588, 8, 32, 1, 33, 1, 33, 3, 33, 592, 8, 33, 1, 33, 1, 33, 1, 33, 3, 33, 597, 8, 33, 1, 34, 1, 34, 3, 34, 601, 8, 34, 1, 34, 1, 34, 1, 35, 1, 35, 3, 35, 607, 8, 35, 1, 35, 1, 35, 1, 36, 1, 36, 3, 36, 613, 8, 36, 1, 36, 1, 36, 1, 37, 1, 37, 3, 37, 619, 8, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 3, 38, 627, 8, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 3, 39, 635, 8, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 3, 43, 655, 8, 43, 1, 43, 1, 43, 3, 43, 659, 8, 43, 1, 43, 3, 43, 662, 8, 43, 1, 43, 5, 43, 665, 8, 43, 10, 43, 12, 43, 668, 9, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 3, 46, 683, 8, 46, 1, 47, 1, 47, 1, 47, 3, 47, 688, 8, 47, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 3, 49, 697, 8, 49, 1, 50, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 3, 52, 708, 8, 52, 1, 52, 1, 52, 3, 52, 712, 8, 52, 1, 52, 3, 52, 715, 8, 52, 5, 52, 717, 8, 52, 10, 52, 12, 52, 720, 9, 52, 1, 53, 1, 53, 1, 53, 1, 53, 3, 53, 726, 8, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 3, 54, 733, 8, 54, 3, 54, 735, 8, 54, 1, 55, 1, 55, 1, 55, 3, 55, 740, 8, 55, 1, 55, 1, 55, 1, 56, 3, 56, 745, 8, 56, 1, 56, 5, 56, 748, 8, 56, 10, 56, 12, 56, 751, 9, 56, 1, 57, 1, 57, 3, 57, 755, 8, 57, 1, 57, 3, 57, 758, 8, 57, 1, 58, 1, 58, 1, 58, 3, 58, 763, 8, 58, 3, 58, 765, 8, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 3, 59, 775, 8, 59, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 3, 62, 786, 8, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 65, 1, 65, 3, 65, 803, 8, 65, 1, 66, 1, 66, 1, 66, 5, 66, 808, 8, 66, 10, 66, 12, 66, 811, 9, 66, 1, 66, 1, 66, 1, 67, 1, 67, 1, 67, 5, 67, 818, 8, 67, 10, 67, 12, 67, 821, 9, 67, 1, 67, 3, 67, 824, 8, 67, 1, 67, 1, 67, 5, 67, 828, 8, 67, 10, 67, 12, 67, 831, 9, 67, 1, 67, 1, 67, 1, 68, 1, 68, 5, 68, 837, 8, 68, 10, 68, 12, 68, 840, 9, 68, 1, 68, 1, 68, 3, 68, 844, 8, 68, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 3, 69, 851, 8, 69, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 5, 71, 859, 8, 71, 10, 71, 12, 71, 862, 9, 71, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 73, 3, 73, 870, 8, 73, 1, 74, 1, 74, 1, 74, 1, 75, 1, 75, 1, 75, 3, 75, 878, 8, 75, 1, 75, 1, 75, 1, 75, 5, 75, 883, 8, 75, 10, 75, 12, 75, 886, 9, 75, 1, 75, 1, 75, 3, 75, 890, 8, 75, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 5, 76, 897, 8, 76, 10, 76, 12, 76, 900, 9, 76, 1, 76, 1, 76, 3, 76, 904, 8, 76, 1, 77, 1, 77, 3, 77, 908, 8, 77, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 3, 78, 915, 8, 78, 3, 78, 917, 8, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 3, 79, 925, 8, 79, 1, 80, 3, 80, 928, 8, 80, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 3, 81, 936, 8, 81, 5, 81, 938, 8, 81, 10, 81, 12, 81, 941, 9, 81, 1, 82, 1, 82, 3, 82, 945, 8, 82, 1, 83, 1, 83, 1, 83, 5, 83, 950, 8, 83, 10, 83, 12, 83, 953, 9, 83, 1, 84, 1, 84, 1, 85, 1, 85, 1, 85, 1, 85, 1, 85, 1, 85, 3, 85, 963, 8, 85, 1, 86, 3, 86, 966, 8, 86, 1, 87, 1, 87, 1, 87, 3, 87, 971, 8, 87, 5, 87, 973, 8, 87, 10, 87, 12, 87, 976, 9, 87, 1, 88, 1, 88, 1, 89, 1, 89, 1, 90, 1, 90, 1, 90, 1, 91, 1, 91, 1, 91, 1, 92, 1, 92, 3, 92, 990, 8, 92, 1, 93, 1, 93, 1, 93, 5, 93, 995, 8, 93, 10, 93, 12, 93, 998, 9, 93, 1, 94, 1, 94, 1, 95, 1, 95, 1, 96, 1, 96, 1, 96, 5, 96, 1007, 8, 96, 10, 96, 12, 96, 1010, 9, 96, 1, 97, 1, 97, 1, 97, 5, 97, 1015, 8, 97, 10, 97, 12, 97, 1018, 9, 97, 1, 98, 1, 98, 3, 98, 1022, 8, 98, 1, 99, 1, 99, 1, 99, 3, 99, 1027, 8, 99, 1, 100, 1, 100, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 3, 101, 1039, 8, 101, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 5, 102, 1046, 8, 102, 10, 102, 12, 102, 1049, 9, 102, 3, 102, 1051, 8, 102, 1, 102, 3, 102, 1054, 8, 102, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, 3, 103, 1061, 8, 103, 3, 103, 1063, 8, 103, 1, 104, 1, 104, 1, 105, 1, 105, 3, 105, 1069, 8, 105, 1, 106, 1, 106, 1, 106, 1, 106, 1, 107, 1, 107, 3, 107, 1077, 8, 107, 1, 108, 1, 108, 1, 108, 1, 108, 1, 109, 1, 109, 4, 109, 1085, 8, 109, 11, 109, 12, 109, 1086, 1, 109, 1, 109, 1, 110, 1, 110, 4, 110, 1093, 8, 110, 11, 110, 12, 110, 1094, 1, 110, 1, 110, 1, 111, 1, 111, 3, 111, 1101, 8, 111, 1, 112, 1, 112, 3, 112, 1105, 8, 112, 1, 113, 1, 113, 3, 113, 1109, 8, 113, 1, 114, 1, 114, 3, 114, 1113, 8, 114, 1, 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, 116, 1, 116, 1, 116, 3, 116, 1123, 8, 116, 1, 117, 1, 117, 1, 118, 1, 118, 1, 118, 5, 118, 1130, 8, 118, 10, 118, 12, 118, 1133, 9, 118, 1, 119, 1, 119, 1, 119, 5, 119, 1138, 8, 119, 10, 119, 12, 119, 1141, 9, 119, 1, 120, 1, 120, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 3, 121, 1163, 8, 121, 1, 122, 1, 122, 1, 123, 1, 123, 5, 123, 1169, 8, 123, 10, 123, 12, 123, 1172, 9, 123, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 3, 124, 1179, 8, 124, 1, 125, 1, 125, 1, 126, 1, 126, 1, 127, 1, 127, 3, 127, 1187, 8, 127, 1, 127, 5, 127, 1190, 8, 127, 10, 127, 12, 127, 1193, 9, 127, 1, 128, 1, 128, 5, 128, 1197, 8, 128, 10, 128, 12, 128, 1200, 9, 128, 1, 129, 1, 129, 3, 129, 1204, 8, 129, 1, 130, 1, 130, 1, 130, 1, 131, 1, 131, 1, 131, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 3, 132, 1219, 8, 132, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 3, 133, 1228, 8, 133, 1, 134, 1, 134, 1, 134, 1, 134, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 3, 135, 1274, 8, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 3, 135, 1488, 8, 135, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 3, 136, 1497, 8, 136, 1, 136, 1, 136, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 3, 138, 1513, 8, 138, 1, 138, 1, 138, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 3, 139, 1526, 8, 139, 1, 139, 1, 139, 1, 140, 1, 140, 1, 140, 1, 141, 1, 141, 1, 141, 1, 141, 1, 142, 1, 142, 1, 142, 3, 142, 1540, 8, 142, 1, 142, 1, 142, 3, 142, 1544, 8, 142, 1, 142, 1, 142, 1, 142, 1, 142, 3, 142, 1550, 8, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 3, 142, 1558, 8, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 3, 142, 1566, 8, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 3, 142, 1574, 8, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 3, 142, 1582, 8, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 3, 142, 1590, 8, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 3, 142, 1597, 8, 142, 1, 142, 1, 142, 3, 142, 1601, 8, 142, 1, 143, 1, 143, 3, 143, 1605, 8, 143, 1, 144, 1, 144, 1, 144, 1, 144, 3, 144, 1611, 8, 144, 1, 145, 1, 145, 1, 145, 3, 145, 1616, 8, 145, 1, 146, 1, 146, 1, 147, 1, 147, 1, 148, 1, 148, 1, 149, 1, 149, 1, 150, 1, 150, 1, 151, 3, 151, 1629, 8, 151, 1, 151, 1, 151, 3, 151, 1633, 8, 151, 1, 152, 1, 152, 3, 152, 1637, 8, 152, 1, 153, 1, 153, 1, 154, 1, 154, 1, 155, 1, 155, 1, 156, 1, 156, 1, 156, 0, 0, 157, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312, 0, 10, 1, 0, 33, 34, 1, 0, 47, 48, 2, 0, 1, 1, 13, 14, 1, 0, 145, 146, 1, 0, 149, 151, 1, 0, 152, 154, 1, 0, 155, 157, 1, 0, 28, 29, 1, 0, 159, 162, 2, 0, 144, 144, 165, 165, 1761, 0, 318, 1, 0, 0, 0, 2, 320, 1, 0, 0, 0, 4, 333, 1, 0, 0, 0, 6, 336, 1, 0, 0, 0, 8, 339, 1, 0, 0, 0, 10, 343, 1, 0, 0, 0, 12, 353, 1, 0, 0, 0, 14, 358, 1, 0, 0, 0, 16, 372, 1, 0, 0, 0, 18, 374, 1, 0, 0, 0, 20, 378, 1, 0, 0, 0, 22, 382, 1, 0, 0, 0, 24, 408, 1, 0, 0, 0, 26, 428, 1, 0, 0, 0, 28, 438, 1, 0, 0, 0, 30, 443, 1, 0, 0, 0, 32, 445, 1, 0, 0, 0, 34, 448, 1, 0, 0, 0, 36, 451, 1, 0, 0, 0, 38, 456, 1, 0, 0, 0, 40, 467, 1, 0, 0, 0, 42, 484, 1, 0, 0, 0, 44, 486, 1, 0, 0, 0, 46, 492, 1, 0, 0, 0, 48, 496, 1, 0, 0, 0, 50, 509, 1, 0, 0, 0, 52, 553, 1, 0, 0, 0, 54, 555, 1, 0, 0, 0, 56, 558, 1, 0, 0, 0, 58, 561, 1, 0, 0, 0, 60, 566, 1, 0, 0, 0, 62, 568, 1, 0, 0, 0, 64, 587, 1, 0, 0, 0, 66, 589, 1, 0, 0, 0, 68, 598, 1, 0, 0, 0, 70, 604, 1, 0, 0, 0, 72, 610, 1, 0, 0, 0, 74, 616, 1, 0, 0, 0, 76, 624, 1, 0, 0, 0, 78, 632, 1, 0, 0, 0, 80, 640, 1, 0, 0, 0, 82, 644, 1, 0, 0, 0, 84, 648, 1, 0, 0, 0, 86, 654, 1, 0, 0, 0, 88, 672, 1, 0, 0, 0, 90, 675, 1, 0, 0, 0, 92, 678, 1, 0, 0, 0, 94, 687, 1, 0, 0, 0, 96, 689, 1, 0, 0, 0, 98, 696, 1, 0, 0, 0, 100, 698, 1, 0, 0, 0, 102, 702, 1, 0, 0, 0, 104, 707, 1, 0, 0, 0, 106, 721, 1, 0, 0, 0, 108, 729, 1, 0, 0, 0, 110, 736, 1, 0, 0, 0, 112, 744, 1, 0, 0, 0, 114, 752, 1, 0, 0, 0, 116, 759, 1, 0, 0, 0, 118, 774, 1, 0, 0, 0, 120, 776, 1, 0, 0, 0, 122, 779, 1, 0, 0, 0, 124, 783, 1, 0, 0, 0, 126, 790, 1, 0, 0, 0, 128, 797, 1, 0, 0, 0, 130, 802, 1, 0, 0, 0, 132, 804, 1, 0, 0, 0, 134, 823, 1, 0, 0, 0, 136, 843, 1, 0, 0, 0, 138, 850, 1, 0, 0, 0, 140, 852, 1, 0, 0, 0, 142, 855, 1, 0, 0, 0, 144, 863, 1, 0, 0, 0, 146, 869, 1, 0, 0, 0, 148, 871, 1, 0, 0, 0, 150, 889, 1, 0, 0, 0, 152, 903, 1, 0, 0, 0, 154, 905, 1, 0, 0, 0, 156, 911, 1, 0, 0, 0, 158, 924, 1, 0, 0, 0, 160, 927, 1, 0, 0, 0, 162, 929, 1, 0, 0, 0, 164, 944, 1, 0, 0, 0, 166, 946, 1, 0, 0, 0, 168, 954, 1, 0, 0, 0, 170, 962, 1, 0, 0, 0, 172, 965, 1, 0, 0, 0, 174, 967, 1, 0, 0, 0, 176, 977, 1, 0, 0, 0, 178, 979, 1, 0, 0, 0, 180, 981, 1, 0, 0, 0, 182, 984, 1, 0, 0, 0, 184, 989, 1, 0, 0, 0, 186, 991, 1, 0, 0, 0, 188, 999, 1, 0, 0, 0, 190, 1001, 1, 0, 0, 0, 192, 1003, 1, 0, 0, 0, 194, 1011, 1, 0, 0, 0, 196, 1019, 1, 0, 0, 0, 198, 1026, 1, 0, 0, 0, 200, 1028, 1, 0, 0, 0, 202, 1038, 1, 0, 0, 0, 204, 1053, 1, 0, 0, 0, 206, 1062, 1, 0, 0, 0, 208, 1064, 1, 0, 0, 0, 210, 1068, 1, 0, 0, 0, 212, 1070, 1, 0, 0, 0, 214, 1076, 1, 0, 0, 0, 216, 1078, 1, 0, 0, 0, 218, 1082, 1, 0, 0, 0, 220, 1090, 1, 0, 0, 0, 222, 1100, 1, 0, 0, 0, 224, 1104, 1, 0, 0, 0, 226, 1108, 1, 0, 0, 0, 228, 1112, 1, 0, 0, 0, 230, 1114, 1, 0, 0, 0, 232, 1122, 1, 0, 0, 0, 234, 1124, 1, 0, 0, 0, 236, 1126, 1, 0, 0, 0, 238, 1134, 1, 0, 0, 0, 240, 1142, 1, 0, 0, 0, 242, 1144, 1, 0, 0, 0, 244, 1164, 1, 0, 0, 0, 246, 1166, 1, 0, 0, 0, 248, 1178, 1, 0, 0, 0, 250, 1180, 1, 0, 0, 0, 252, 1182, 1, 0, 0, 0, 254, 1186, 1, 0, 0, 0, 256, 1194, 1, 0, 0, 0, 258, 1203, 1, 0, 0, 0, 260, 1205, 1, 0, 0, 0, 262, 1208, 1, 0, 0, 0, 264, 1218, 1, 0, 0, 0, 266, 1227, 1, 0, 0, 0, 268, 1229, 1, 0, 0, 0, 270, 1487, 1, 0, 0, 0, 272, 1489, 1, 0, 0, 0, 274, 1500, 1, 0, 0, 0, 276, 1505, 1, 0, 0, 0, 278, 1516, 1, 0, 0, 0, 280, 1529, 1, 0, 0, 0, 282, 1532, 1, 0, 0, 0, 284, 1600, 1, 0, 0, 0, 286, 1602, 1, 0, 0, 0, 288, 1606, 1, 0, 0, 0, 290, 1615, 1, 0, 0, 0, 292, 1617, 1, 0, 0, 0, 294, 1619, 1, 0, 0, 0, 296, 1621, 1, 0, 0, 0, 298, 1623, 1, 0, 0, 0, 300, 1625, 1, 0, 0, 0, 302, 1628, 1, 0, 0, 0, 304, 1636, 1, 0, 0, 0, 306, 1638, 1, 0, 0, 0, 308, 1640, 1, 0, 0, 0, 310, 1642, 1, 0, 0, 0, 312, 1644, 1, 0, 0, 0, 314, 319, 3, 2, 1, 0, 315, 316, 3, 62, 31, 0, 316, 317, 5, 0, 0, 1, 317, 319, 1, 0, 0, 0, 318, 314, 1, 0, 0, 0, 318, 315, 1, 0, 0, 0, 319, 1, 1, 0, 0, 0, 320, 325, 3, 4, 2, 0, 321, 326, 3, 10, 5, 0, 322, 326, 3, 22, 11, 0, 323, 326, 3, 24, 12, 0, 324, 326, 3, 26, 13, 0, 325, 321, 1, 0, 0, 0, 325, 322, 1, 0, 0, 0, 325, 323, 1, 0, 0, 0, 325, 324, 1, 0, 0, 0, 326, 327, 1, 0, 0, 0, 327, 328, 3, 60, 30, 0, 328, 3, 1, 0, 0, 0, 329, 332, 3, 6, 3, 0, 330, 332, 3, 8, 4, 0, 331, 329, 1, 0, 0, 0, 331, 330, 1, 0, 0, 0, 332, 335, 1, 0, 0, 0, 333, 331, 1, 0, 0, 0, 333, 334, 1, 0, 0, 0, 334, 5, 1, 0, 0, 0, 335, 333, 1, 0, 0, 0, 336, 337, 5, 30, 0, 0, 337, 338, 3, 308, 154, 0, 338, 7, 1, 0, 0, 0, 339, 340, 5, 31, 0, 0, 340, 341, 5, 142, 0, 0, 341, 342, 3, 308, 154, 0, 342, 9, 1, 0, 0, 0, 343, 347, 3, 14, 7, 0, 344, 346, 3, 28, 14, 0, 345, 344, 1, 0, 0, 0, 346, 349, 1, 0, 0, 0, 347, 345, 1, 0, 0, 0, 347, 348, 1, 0, 0, 0, 348, 350, 1, 0, 0, 0, 349, 347, 1, 0, 0, 0, 350, 351, 3, 36, 18, 0, 351, 352, 3, 38, 19, 0, 352, 11, 1, 0, 0, 0, 353, 354, 3, 14, 7, 0, 354, 355, 3, 36, 18, 0, 355, 356, 3, 38, 19, 0, 356, 357, 3, 60, 30, 0, 357, 13, 1, 0, 0, 0, 358, 360, 5, 32, 0, 0, 359, 361, 7, 0, 0, 0, 360, 359, 1, 0, 0, 0, 360, 361, 1, 0, 0, 0, 361, 368, 1, 0, 0, 0, 362, 364, 3, 16, 8, 0, 363, 362, 1, 0, 0, 0, 364, 365, 1, 0, 0, 0, 365, 363, 1, 0, 0, 0, 365, 366, 1, 0, 0, 0, 366, 369, 1, 0, 0, 0, 367, 369, 5, 1, 0, 0, 368, 363, 1, 0, 0, 0, 368, 367, 1, 0, 0, 0, 369, 15, 1, 0, 0, 0, 370, 373, 3, 230, 115, 0, 371, 373, 3, 18, 9, 0, 372, 370, 1, 0, 0, 0, 372, 371, 1, 0, 0, 0, 373, 17, 1, 0, 0, 0, 374, 375, 5, 2, 0, 0, 375, 376, 3, 20, 10, 0, 376, 377, 5, 3, 0, 0, 377, 19, 1, 0, 0, 0, 378, 379, 3, 234, 117, 0, 379, 380, 5, 35, 0, 0, 380, 381, 3, 230, 115, 0, 381, 21, 1, 0, 0, 0, 382, 406, 5, 36, 0, 0, 383, 387, 3, 154, 77, 0, 384, 386, 3, 28, 14, 0, 385, 384, 1, 0, 0, 0, 386, 389, 1, 0, 0, 0, 387, 385, 1, 0, 0, 0, 387, 388, 1, 0, 0, 0, 388, 390, 1, 0, 0, 0, 389, 387, 1, 0, 0, 0, 390, 391, 3, 36, 18, 0, 391, 392, 3, 38, 19, 0, 392, 407, 1, 0, 0, 0, 393, 395, 3, 28, 14, 0, 394, 393, 1, 0, 0, 0, 395, 398, 1, 0, 0, 0, 396, 394, 1, 0, 0, 0, 396, 397, 1, 0, 0, 0, 397, 399, 1, 0, 0, 0, 398, 396, 1, 0, 0, 0, 399, 400, 5, 37, 0, 0, 400, 402, 5, 4, 0, 0, 401, 403, 3, 108, 54, 0, 402, 401, 1, 0, 0, 0, 402, 403, 1, 0, 0, 0, 403, 404, 1, 0, 0, 0, 404, 405, 5, 5, 0, 0, 405, 407, 3, 38, 19, 0, 406, 383, 1, 0, 0, 0, 406, 396, 1, 0, 0, 0, 407, 23, 1, 0, 0, 0, 408, 415, 5, 38, 0, 0, 409, 411, 3, 228, 114, 0, 410, 409, 1, 0, 0, 0, 411, 412, 1, 0, 0, 0, 412, 410, 1, 0, 0, 0, 412, 413, 1, 0, 0, 0, 413, 416, 1, 0, 0, 0, 414, 416, 5, 1, 0, 0, 415, 410, 1, 0, 0, 0, 415, 414, 1, 0, 0, 0, 416, 420, 1, 0, 0, 0, 417, 419, 3, 28, 14, 0, 418, 417, 1, 0, 0, 0, 419, 422, 1, 0, 0, 0, 420, 418, 1, 0, 0, 0, 420, 421, 1, 0, 0, 0, 421, 424, 1, 0, 0, 0, 422, 420, 1, 0, 0, 0, 423, 425, 3, 36, 18, 0, 424, 423, 1, 0, 0, 0, 424, 425, 1, 0, 0, 0, 425, 426, 1, 0, 0, 0, 426, 427, 3, 38, 19, 0, 427, 25, 1, 0, 0, 0, 428, 432, 5, 39, 0, 0, 429, 431, 3, 28, 14, 0, 430, 429, 1, 0, 0, 0, 431, 434, 1, 0, 0, 0, 432, 430, 1, 0, 0, 0, 432, 433, 1, 0, 0, 0, 433, 435, 1, 0, 0, 0, 434, 432, 1, 0, 0, 0, 435, 436, 3, 36, 18, 0, 436, 437, 3, 38, 19, 0, 437, 27, 1, 0, 0, 0, 438, 441, 5, 40, 0, 0, 439, 442, 3, 30, 15, 0, 440, 442, 3, 32, 16, 0, 441, 439, 1, 0, 0, 0, 441, 440, 1, 0, 0, 0, 442, 29, 1, 0, 0, 0, 443, 444, 3, 34, 17, 0, 444, 31, 1, 0, 0, 0, 445, 446, 5, 41, 0, 0, 446, 447, 3, 34, 17, 0, 447, 33, 1, 0, 0, 0, 448, 449, 3, 302, 151, 0, 449, 35, 1, 0, 0, 0, 450, 452, 5, 37, 0, 0, 451, 450, 1, 0, 0, 0, 451, 452, 1, 0, 0, 0, 452, 453, 1, 0, 0, 0, 453, 454, 3, 110, 55, 0, 454, 37, 1, 0, 0, 0, 455, 457, 3, 40, 20, 0, 456, 455, 1, 0, 0, 0, 456, 457, 1, 0, 0, 0, 457, 459, 1, 0, 0, 0, 458, 460, 3, 44, 22, 0, 459, 458, 1, 0, 0, 0, 459, 460, 1, 0, 0, 0, 460, 462, 1, 0, 0, 0, 461, 463, 3, 48, 24, 0, 462, 461, 1, 0, 0, 0, 462, 463, 1, 0, 0, 0, 463, 465, 1, 0, 0, 0, 464, 466, 3, 52, 26, 0, 465, 464, 1, 0, 0, 0, 465, 466, 1, 0, 0, 0, 466, 39, 1, 0, 0, 0, 467, 469, 5, 42, 0, 0, 468, 470, 3, 42, 21, 0, 469, 468, 1, 0, 0, 0, 470, 471, 1, 0, 0, 0, 471, 469, 1, 0, 0, 0, 471, 472, 1, 0, 0, 0, 472, 41, 1, 0, 0, 0, 473, 485, 3, 270, 135, 0, 474, 485, 3, 148, 74, 0, 475, 476, 5, 2, 0, 0, 476, 479, 3, 234, 117, 0, 477, 478, 5, 35, 0, 0, 478, 480, 3, 230, 115, 0, 479, 477, 1, 0, 0, 0, 479, 480, 1, 0, 0, 0, 480, 481, 1, 0, 0, 0, 481, 482, 5, 3, 0, 0, 482, 485, 1, 0, 0, 0, 483, 485, 3, 230, 115, 0, 484, 473, 1, 0, 0, 0, 484, 474, 1, 0, 0, 0, 484, 475, 1, 0, 0, 0, 484, 483, 1, 0, 0, 0, 485, 43, 1, 0, 0, 0, 486, 488, 5, 44, 0, 0, 487, 489, 3, 46, 23, 0, 488, 487, 1, 0, 0, 0, 489, 490, 1, 0, 0, 0, 490, 488, 1, 0, 0, 0, 490, 491, 1, 0, 0, 0, 491, 45, 1, 0, 0, 0, 492, 493, 3, 146, 73, 0, 493, 47, 1, 0, 0, 0, 494, 497, 5, 45, 0, 0, 495, 497, 5, 46, 0, 0, 496, 494, 1, 0, 0, 0, 496, 495, 1, 0, 0, 0, 497, 499, 1, 0, 0, 0, 498, 500, 3, 50, 25, 0, 499, 498, 1, 0, 0, 0, 500, 501, 1, 0, 0, 0, 501, 499, 1, 0, 0, 0, 501, 502, 1, 0, 0, 0, 502, 49, 1, 0, 0, 0, 503, 504, 7, 1, 0, 0, 504, 510, 3, 268, 134, 0, 505, 508, 3, 146, 73, 0, 506, 508, 3, 230, 115, 0, 507, 505, 1, 0, 0, 0, 507, 506, 1, 0, 0, 0, 508, 510, 1, 0, 0, 0, 509, 503, 1, 0, 0, 0, 509, 507, 1, 0, 0, 0, 510, 51, 1, 0, 0, 0, 511, 513, 3, 54, 27, 0, 512, 514, 3, 56, 28, 0, 513, 512, 1, 0, 0, 0, 513, 514, 1, 0, 0, 0, 514, 516, 1, 0, 0, 0, 515, 517, 3, 58, 29, 0, 516, 515, 1, 0, 0, 0, 516, 517, 1, 0, 0, 0, 517, 554, 1, 0, 0, 0, 518, 520, 3, 54, 27, 0, 519, 521, 3, 58, 29, 0, 520, 519, 1, 0, 0, 0, 520, 521, 1, 0, 0, 0, 521, 523, 1, 0, 0, 0, 522, 524, 3, 56, 28, 0, 523, 522, 1, 0, 0, 0, 523, 524, 1, 0, 0, 0, 524, 554, 1, 0, 0, 0, 525, 527, 3, 56, 28, 0, 526, 528, 3, 54, 27, 0, 527, 526, 1, 0, 0, 0, 527, 528, 1, 0, 0, 0, 528, 530, 1, 0, 0, 0, 529, 531, 3, 58, 29, 0, 530, 529, 1, 0, 0, 0, 530, 531, 1, 0, 0, 0, 531, 554, 1, 0, 0, 0, 532, 534, 3, 56, 28, 0, 533, 535, 3, 58, 29, 0, 534, 533, 1, 0, 0, 0, 534, 535, 1, 0, 0, 0, 535, 537, 1, 0, 0, 0, 536, 538, 3, 54, 27, 0, 537, 536, 1, 0, 0, 0, 537, 538, 1, 0, 0, 0, 538, 554, 1, 0, 0, 0, 539, 541, 3, 58, 29, 0, 540, 542, 3, 56, 28, 0, 541, 540, 1, 0, 0, 0, 541, 542, 1, 0, 0, 0, 542, 544, 1, 0, 0, 0, 543, 545, 3, 54, 27, 0, 544, 543, 1, 0, 0, 0, 544, 545, 1, 0, 0, 0, 545, 554, 1, 0, 0, 0, 546, 548, 3, 58, 29, 0, 547, 549, 3, 54, 27, 0, 548, 547, 1, 0, 0, 0, 548, 549, 1, 0, 0, 0, 549, 551, 1, 0, 0, 0, 550, 552, 3, 56, 28, 0, 551, 550, 1, 0, 0, 0, 551, 552, 1, 0, 0, 0, 552, 554, 1, 0, 0, 0, 553, 511, 1, 0, 0, 0, 553, 518, 1, 0, 0, 0, 553, 525, 1, 0, 0, 0, 553, 532, 1, 0, 0, 0, 553, 539, 1, 0, 0, 0, 553, 546, 1, 0, 0, 0, 554, 53, 1, 0, 0, 0, 555, 556, 5, 49, 0, 0, 556, 557, 3, 208, 104, 0, 557, 55, 1, 0, 0, 0, 558, 559, 5, 50, 0, 0, 559, 560, 3, 208, 104, 0, 560, 57, 1, 0, 0, 0, 561, 562, 5, 51, 0, 0, 562, 563, 3, 208, 104, 0, 563, 59, 1, 0, 0, 0, 564, 565, 5, 52, 0, 0, 565, 567, 3, 130, 65, 0, 566, 564, 1, 0, 0, 0, 566, 567, 1, 0, 0, 0, 567, 61, 1, 0, 0, 0, 568, 574, 3, 4, 2, 0, 569, 572, 3, 64, 32, 0, 570, 571, 5, 6, 0, 0, 571, 573, 3, 62, 31, 0, 572, 570, 1, 0, 0, 0, 572, 573, 1, 0, 0, 0, 573, 575, 1, 0, 0, 0, 574, 569, 1, 0, 0, 0, 574, 575, 1, 0, 0, 0, 575, 63, 1, 0, 0, 0, 576, 588, 3, 66, 33, 0, 577, 588, 3, 68, 34, 0, 578, 588, 3, 70, 35, 0, 579, 588, 3, 74, 37, 0, 580, 588, 3, 76, 38, 0, 581, 588, 3, 78, 39, 0, 582, 588, 3, 72, 36, 0, 583, 588, 3, 80, 40, 0, 584, 588, 3, 82, 41, 0, 585, 588, 3, 84, 42, 0, 586, 588, 3, 86, 43, 0, 587, 576, 1, 0, 0, 0, 587, 577, 1, 0, 0, 0, 587, 578, 1, 0, 0, 0, 587, 579, 1, 0, 0, 0, 587, 580, 1, 0, 0, 0, 587, 581, 1, 0, 0, 0, 587, 582, 1, 0, 0, 0, 587, 583, 1, 0, 0, 0, 587, 584, 1, 0, 0, 0, 587, 585, 1, 0, 0, 0, 587, 586, 1, 0, 0, 0, 588, 65, 1, 0, 0, 0, 589, 591, 5, 53, 0, 0, 590, 592, 5, 54, 0, 0, 591, 590, 1, 0, 0, 0, 591, 592, 1, 0, 0, 0, 592, 593, 1, 0, 0, 0, 593, 596, 3, 302, 151, 0, 594, 595, 5, 55, 0, 0, 595, 597, 3, 96, 48, 0, 596, 594, 1, 0, 0, 0, 596, 597, 1, 0, 0, 0, 597, 67, 1, 0, 0, 0, 598, 600, 5, 56, 0, 0, 599, 601, 5, 54, 0, 0, 600, 599, 1, 0, 0, 0, 600, 601, 1, 0, 0, 0, 601, 602, 1, 0, 0, 0, 602, 603, 3, 98, 49, 0, 603, 69, 1, 0, 0, 0, 604, 606, 5, 57, 0, 0, 605, 607, 5, 54, 0, 0, 606, 605, 1, 0, 0, 0, 606, 607, 1, 0, 0, 0, 607, 608, 1, 0, 0, 0, 608, 609, 3, 98, 49, 0, 609, 71, 1, 0, 0, 0, 610, 612, 5, 58, 0, 0, 611, 613, 5, 54, 0, 0, 612, 611, 1, 0, 0, 0, 612, 613, 1, 0, 0, 0, 613, 614, 1, 0, 0, 0, 614, 615, 3, 96, 48, 0, 615, 73, 1, 0, 0, 0, 616, 618, 5, 59, 0, 0, 617, 619, 5, 54, 0, 0, 618, 617, 1, 0, 0, 0, 618, 619, 1, 0, 0, 0, 619, 620, 1, 0, 0, 0, 620, 621, 3, 94, 47, 0, 621, 622, 5, 60, 0, 0, 622, 623, 3, 94, 47, 0, 623, 75, 1, 0, 0, 0, 624, 626, 5, 62, 0, 0, 625, 627, 5, 54, 0, 0, 626, 625, 1, 0, 0, 0, 626, 627, 1, 0, 0, 0, 627, 628, 1, 0, 0, 0, 628, 629, 3, 94, 47, 0, 629, 630, 5, 60, 0, 0, 630, 631, 3, 94, 47, 0, 631, 77, 1, 0, 0, 0, 632, 634, 5, 63, 0, 0, 633, 635, 5, 54, 0, 0, 634, 633, 1, 0, 0, 0, 634, 635, 1, 0, 0, 0, 635, 636, 1, 0, 0, 0, 636, 637, 3, 94, 47, 0, 637, 638, 5, 60, 0, 0, 638, 639, 3, 94, 47, 0, 639, 79, 1, 0, 0, 0, 640, 641, 5, 64, 0, 0, 641, 642, 5, 61, 0, 0, 642, 643, 3, 102, 51, 0, 643, 81, 1, 0, 0, 0, 644, 645, 5, 65, 0, 0, 645, 646, 5, 61, 0, 0, 646, 647, 3, 102, 51, 0, 647, 83, 1, 0, 0, 0, 648, 649, 5, 65, 0, 0, 649, 650, 5, 37, 0, 0, 650, 651, 3, 100, 50, 0, 651, 85, 1, 0, 0, 0, 652, 653, 5, 66, 0, 0, 653, 655, 3, 302, 151, 0, 654, 652, 1, 0, 0, 0, 654, 655, 1, 0, 0, 0, 655, 661, 1, 0, 0, 0, 656, 658, 3, 88, 44, 0, 657, 659, 3, 90, 45, 0, 658, 657, 1, 0, 0, 0, 658, 659, 1, 0, 0, 0, 659, 662, 1, 0, 0, 0, 660, 662, 3, 90, 45, 0, 661, 656, 1, 0, 0, 0, 661, 660, 1, 0, 0, 0, 662, 666, 1, 0, 0, 0, 663, 665, 3, 92, 46, 0, 664, 663, 1, 0, 0, 0, 665, 668, 1, 0, 0, 0, 666, 664, 1, 0, 0, 0, 666, 667, 1, 0, 0, 0, 667, 669, 1, 0, 0, 0, 668, 666, 1, 0, 0, 0, 669, 670, 5, 37, 0, 0, 670, 671, 3, 110, 55, 0, 671, 87, 1, 0, 0, 0, 672, 673, 5, 65, 0, 0, 673, 674, 3, 100, 50, 0, 674, 89, 1, 0, 0, 0, 675, 676, 5, 64, 0, 0, 676, 677, 3, 100, 50, 0, 677, 91, 1, 0, 0, 0, 678, 682, 5, 67, 0, 0, 679, 683, 5, 85, 0, 0, 680, 681, 5, 41, 0, 0, 681, 683, 3, 302, 151, 0, 682, 679, 1, 0, 0, 0, 682, 680, 1, 0, 0, 0, 683, 93, 1, 0, 0, 0, 684, 688, 5, 68, 0, 0, 685, 686, 5, 69, 0, 0, 686, 688, 3, 302, 151, 0, 687, 684, 1, 0, 0, 0, 687, 685, 1, 0, 0, 0, 688, 95, 1, 0, 0, 0, 689, 690, 5, 69, 0, 0, 690, 691, 3, 302, 151, 0, 691, 97, 1, 0, 0, 0, 692, 697, 3, 96, 48, 0, 693, 697, 5, 68, 0, 0, 694, 697, 5, 41, 0, 0, 695, 697, 5, 70, 0, 0, 696, 692, 1, 0, 0, 0, 696, 693, 1, 0, 0, 0, 696, 694, 1, 0, 0, 0, 696, 695, 1, 0, 0, 0, 697, 99, 1, 0, 0, 0, 698, 699, 5, 4, 0, 0, 699, 700, 3, 104, 52, 0, 700, 701, 5, 5, 0, 0, 701, 101, 1, 0, 0, 0, 702, 703, 5, 4, 0, 0, 703, 704, 3, 104, 52, 0, 704, 705, 5, 5, 0, 0, 705, 103, 1, 0, 0, 0, 706, 708, 3, 108, 54, 0, 707, 706, 1, 0, 0, 0, 707, 708, 1, 0, 0, 0, 708, 718, 1, 0, 0, 0, 709, 711, 3, 106, 53, 0, 710, 712, 5, 7, 0, 0, 711, 710, 1, 0, 0, 0, 711, 712, 1, 0, 0, 0, 712, 714, 1, 0, 0, 0, 713, 715, 3, 108, 54, 0, 714, 713, 1, 0, 0, 0, 714, 715, 1, 0, 0, 0, 715, 717, 1, 0, 0, 0, 716, 709, 1, 0, 0, 0, 717, 720, 1, 0, 0, 0, 718, 716, 1, 0, 0, 0, 718, 719, 1, 0, 0, 0, 719, 105, 1, 0, 0, 0, 720, 718, 1, 0, 0, 0, 721, 722, 5, 69, 0, 0, 722, 723, 3, 228, 114, 0, 723, 725, 5, 4, 0, 0, 724, 726, 3, 108, 54, 0, 725, 724, 1, 0, 0, 0, 725, 726, 1, 0, 0, 0, 726, 727, 1, 0, 0, 0, 727, 728, 5, 5, 0, 0, 728, 107, 1, 0, 0, 0, 729, 734, 3, 158, 79, 0, 730, 732, 5, 7, 0, 0, 731, 733, 3, 108, 54, 0, 732, 731, 1, 0, 0, 0, 732, 733, 1, 0, 0, 0, 733, 735, 1, 0, 0, 0, 734, 730, 1, 0, 0, 0, 734, 735, 1, 0, 0, 0, 735, 109, 1, 0, 0, 0, 736, 739, 5, 4, 0, 0, 737, 740, 3, 12, 6, 0, 738, 740, 3, 112, 56, 0, 739, 737, 1, 0, 0, 0, 739, 738, 1, 0, 0, 0, 740, 741, 1, 0, 0, 0, 741, 742, 5, 5, 0, 0, 742, 111, 1, 0, 0, 0, 743, 745, 3, 116, 58, 0, 744, 743, 1, 0, 0, 0, 744, 745, 1, 0, 0, 0, 745, 749, 1, 0, 0, 0, 746, 748, 3, 114, 57, 0, 747, 746, 1, 0, 0, 0, 748, 751, 1, 0, 0, 0, 749, 747, 1, 0, 0, 0, 749, 750, 1, 0, 0, 0, 750, 113, 1, 0, 0, 0, 751, 749, 1, 0, 0, 0, 752, 754, 3, 118, 59, 0, 753, 755, 5, 7, 0, 0, 754, 753, 1, 0, 0, 0, 754, 755, 1, 0, 0, 0, 755, 757, 1, 0, 0, 0, 756, 758, 3, 116, 58, 0, 757, 756, 1, 0, 0, 0, 757, 758, 1, 0, 0, 0, 758, 115, 1, 0, 0, 0, 759, 764, 3, 170, 85, 0, 760, 762, 5, 7, 0, 0, 761, 763, 3, 116, 58, 0, 762, 761, 1, 0, 0, 0, 762, 763, 1, 0, 0, 0, 763, 765, 1, 0, 0, 0, 764, 760, 1, 0, 0, 0, 764, 765, 1, 0, 0, 0, 765, 117, 1, 0, 0, 0, 766, 775, 3, 142, 71, 0, 767, 775, 3, 120, 60, 0, 768, 775, 3, 140, 70, 0, 769, 775, 3, 122, 61, 0, 770, 775, 3, 124, 62, 0, 771, 775, 3, 144, 72, 0, 772, 775, 3, 126, 63, 0, 773, 775, 3, 128, 64, 0, 774, 766, 1, 0, 0, 0, 774, 767, 1, 0, 0, 0, 774, 768, 1, 0, 0, 0, 774, 769, 1, 0, 0, 0, 774, 770, 1, 0, 0, 0, 774, 771, 1, 0, 0, 0, 774, 772, 1, 0, 0, 0, 774, 773, 1, 0, 0, 0, 775, 119, 1, 0, 0, 0, 776, 777, 5, 71, 0, 0, 777, 778, 3, 110, 55, 0, 778, 121, 1, 0, 0, 0, 779, 780, 5, 69, 0, 0, 780, 781, 3, 228, 114, 0, 781, 782, 3, 110, 55, 0, 782, 123, 1, 0, 0, 0, 783, 785, 5, 72, 0, 0, 784, 786, 5, 54, 0, 0, 785, 784, 1, 0, 0, 0, 785, 786, 1, 0, 0, 0, 786, 787, 1, 0, 0, 0, 787, 788, 3, 228, 114, 0, 788, 789, 3, 110, 55, 0, 789, 125, 1, 0, 0, 0, 790, 791, 5, 73, 0, 0, 791, 792, 5, 2, 0, 0, 792, 793, 3, 234, 117, 0, 793, 794, 5, 35, 0, 0, 794, 795, 3, 230, 115, 0, 795, 796, 5, 3, 0, 0, 796, 127, 1, 0, 0, 0, 797, 798, 5, 52, 0, 0, 798, 799, 3, 130, 65, 0, 799, 129, 1, 0, 0, 0, 800, 803, 3, 132, 66, 0, 801, 803, 3, 134, 67, 0, 802, 800, 1, 0, 0, 0, 802, 801, 1, 0, 0, 0, 803, 131, 1, 0, 0, 0, 804, 805, 3, 230, 115, 0, 805, 809, 5, 4, 0, 0, 806, 808, 3, 138, 69, 0, 807, 806, 1, 0, 0, 0, 808, 811, 1, 0, 0, 0, 809, 807, 1, 0, 0, 0, 809, 810, 1, 0, 0, 0, 810, 812, 1, 0, 0, 0, 811, 809, 1, 0, 0, 0, 812, 813, 5, 5, 0, 0, 813, 133, 1, 0, 0, 0, 814, 824, 5, 164, 0, 0, 815, 819, 5, 2, 0, 0, 816, 818, 3, 230, 115, 0, 817, 816, 1, 0, 0, 0, 818, 821, 1, 0, 0, 0, 819, 817, 1, 0, 0, 0, 819, 820, 1, 0, 0, 0, 820, 822, 1, 0, 0, 0, 821, 819, 1, 0, 0, 0, 822, 824, 5, 3, 0, 0, 823, 814, 1, 0, 0, 0, 823, 815, 1, 0, 0, 0, 824, 825, 1, 0, 0, 0, 825, 829, 5, 4, 0, 0, 826, 828, 3, 136, 68, 0, 827, 826, 1, 0, 0, 0, 828, 831, 1, 0, 0, 0, 829, 827, 1, 0, 0, 0, 829, 830, 1, 0, 0, 0, 830, 832, 1, 0, 0, 0, 831, 829, 1, 0, 0, 0, 832, 833, 5, 5, 0, 0, 833, 135, 1, 0, 0, 0, 834, 838, 5, 2, 0, 0, 835, 837, 3, 138, 69, 0, 836, 835, 1, 0, 0, 0, 837, 840, 1, 0, 0, 0, 838, 836, 1, 0, 0, 0, 838, 839, 1, 0, 0, 0, 839, 841, 1, 0, 0, 0, 840, 838, 1, 0, 0, 0, 841, 844, 5, 3, 0, 0, 842, 844, 5, 164, 0, 0, 843, 834, 1, 0, 0, 0, 843, 842, 1, 0, 0, 0, 844, 137, 1, 0, 0, 0, 845, 851, 3, 302, 151, 0, 846, 851, 3, 288, 144, 0, 847, 851, 3, 290, 145, 0, 848, 851, 3, 298, 149, 0, 849, 851, 5, 74, 0, 0, 850, 845, 1, 0, 0, 0, 850, 846, 1, 0, 0, 0, 850, 847, 1, 0, 0, 0, 850, 848, 1, 0, 0, 0, 850, 849, 1, 0, 0, 0, 851, 139, 1, 0, 0, 0, 852, 853, 5, 75, 0, 0, 853, 854, 3, 110, 55, 0, 854, 141, 1, 0, 0, 0, 855, 860, 3, 110, 55, 0, 856, 857, 5, 76, 0, 0, 857, 859, 3, 110, 55, 0, 858, 856, 1, 0, 0, 0, 859, 862, 1, 0, 0, 0, 860, 858, 1, 0, 0, 0, 860, 861, 1, 0, 0, 0, 861, 143, 1, 0, 0, 0, 862, 860, 1, 0, 0, 0, 863, 864, 5, 77, 0, 0, 864, 865, 3, 146, 73, 0, 865, 145, 1, 0, 0, 0, 866, 870, 3, 268, 134, 0, 867, 870, 3, 270, 135, 0, 868, 870, 3, 148, 74, 0, 869, 866, 1, 0, 0, 0, 869, 867, 1, 0, 0, 0, 869, 868, 1, 0, 0, 0, 870, 147, 1, 0, 0, 0, 871, 872, 3, 302, 151, 0, 872, 873, 3, 150, 75, 0, 873, 149, 1, 0, 0, 0, 874, 890, 5, 164, 0, 0, 875, 877, 5, 2, 0, 0, 876, 878, 5, 33, 0, 0, 877, 876, 1, 0, 0, 0, 877, 878, 1, 0, 0, 0, 878, 879, 1, 0, 0, 0, 879, 884, 3, 234, 117, 0, 880, 881, 5, 8, 0, 0, 881, 883, 3, 234, 117, 0, 882, 880, 1, 0, 0, 0, 883, 886, 1, 0, 0, 0, 884, 882, 1, 0, 0, 0, 884, 885, 1, 0, 0, 0, 885, 887, 1, 0, 0, 0, 886, 884, 1, 0, 0, 0, 887, 888, 5, 3, 0, 0, 888, 890, 1, 0, 0, 0, 889, 874, 1, 0, 0, 0, 889, 875, 1, 0, 0, 0, 890, 151, 1, 0, 0, 0, 891, 904, 5, 164, 0, 0, 892, 893, 5, 2, 0, 0, 893, 898, 3, 234, 117, 0, 894, 895, 5, 8, 0, 0, 895, 897, 3, 234, 117, 0, 896, 894, 1, 0, 0, 0, 897, 900, 1, 0, 0, 0, 898, 896, 1, 0, 0, 0, 898, 899, 1, 0, 0, 0, 899, 901, 1, 0, 0, 0, 900, 898, 1, 0, 0, 0, 901, 902, 5, 3, 0, 0, 902, 904, 1, 0, 0, 0, 903, 891, 1, 0, 0, 0, 903, 892, 1, 0, 0, 0, 904, 153, 1, 0, 0, 0, 905, 907, 5, 4, 0, 0, 906, 908, 3, 156, 78, 0, 907, 906, 1, 0, 0, 0, 907, 908, 1, 0, 0, 0, 908, 909, 1, 0, 0, 0, 909, 910, 5, 5, 0, 0, 910, 155, 1, 0, 0, 0, 911, 916, 3, 158, 79, 0, 912, 914, 5, 7, 0, 0, 913, 915, 3, 156, 78, 0, 914, 913, 1, 0, 0, 0, 914, 915, 1, 0, 0, 0, 915, 917, 1, 0, 0, 0, 916, 912, 1, 0, 0, 0, 916, 917, 1, 0, 0, 0, 917, 157, 1, 0, 0, 0, 918, 919, 3, 226, 113, 0, 919, 920, 3, 162, 81, 0, 920, 925, 1, 0, 0, 0, 921, 922, 3, 210, 105, 0, 922, 923, 3, 160, 80, 0, 923, 925, 1, 0, 0, 0, 924, 918, 1, 0, 0, 0, 924, 921, 1, 0, 0, 0, 925, 159, 1, 0, 0, 0, 926, 928, 3, 162, 81, 0, 927, 926, 1, 0, 0, 0, 927, 928, 1, 0, 0, 0, 928, 161, 1, 0, 0, 0, 929, 930, 3, 164, 82, 0, 930, 939, 3, 166, 83, 0, 931, 935, 5, 6, 0, 0, 932, 933, 3, 164, 82, 0, 933, 934, 3, 166, 83, 0, 934, 936, 1, 0, 0, 0, 935, 932, 1, 0, 0, 0, 935, 936, 1, 0, 0, 0, 936, 938, 1, 0, 0, 0, 937, 931, 1, 0, 0, 0, 938, 941, 1, 0, 0, 0, 939, 937, 1, 0, 0, 0, 939, 940, 1, 0, 0, 0, 940, 163, 1, 0, 0, 0, 941, 939, 1, 0, 0, 0, 942, 945, 3, 228, 114, 0, 943, 945, 5, 9, 0, 0, 944, 942, 1, 0, 0, 0, 944, 943, 1, 0, 0, 0, 945, 165, 1, 0, 0, 0, 946, 951, 3, 168, 84, 0, 947, 948, 5, 8, 0, 0, 948, 950, 3, 168, 84, 0, 949, 947, 1, 0, 0, 0, 950, 953, 1, 0, 0, 0, 951, 949, 1, 0, 0, 0, 951, 952, 1, 0, 0, 0, 952, 167, 1, 0, 0, 0, 953, 951, 1, 0, 0, 0, 954, 955, 3, 222, 111, 0, 955, 169, 1, 0, 0, 0, 956, 957, 3, 226, 113, 0, 957, 958, 3, 174, 87, 0, 958, 963, 1, 0, 0, 0, 959, 960, 3, 214, 107, 0, 960, 961, 3, 172, 86, 0, 961, 963, 1, 0, 0, 0, 962, 956, 1, 0, 0, 0, 962, 959, 1, 0, 0, 0, 963, 171, 1, 0, 0, 0, 964, 966, 3, 174, 87, 0, 965, 964, 1, 0, 0, 0, 965, 966, 1, 0, 0, 0, 966, 173, 1, 0, 0, 0, 967, 974, 3, 182, 91, 0, 968, 970, 5, 6, 0, 0, 969, 971, 3, 180, 90, 0, 970, 969, 1, 0, 0, 0, 970, 971, 1, 0, 0, 0, 971, 973, 1, 0, 0, 0, 972, 968, 1, 0, 0, 0, 973, 976, 1, 0, 0, 0, 974, 972, 1, 0, 0, 0, 974, 975, 1, 0, 0, 0, 975, 175, 1, 0, 0, 0, 976, 974, 1, 0, 0, 0, 977, 978, 3, 190, 95, 0, 978, 177, 1, 0, 0, 0, 979, 980, 3, 230, 115, 0, 980, 179, 1, 0, 0, 0, 981, 982, 3, 184, 92, 0, 982, 983, 3, 166, 83, 0, 983, 181, 1, 0, 0, 0, 984, 985, 3, 184, 92, 0, 985, 986, 3, 186, 93, 0, 986, 183, 1, 0, 0, 0, 987, 990, 3, 176, 88, 0, 988, 990, 3, 178, 89, 0, 989, 987, 1, 0, 0, 0, 989, 988, 1, 0, 0, 0, 990, 185, 1, 0, 0, 0, 991, 996, 3, 188, 94, 0, 992, 993, 5, 8, 0, 0, 993, 995, 3, 188, 94, 0, 994, 992, 1, 0, 0, 0, 995, 998, 1, 0, 0, 0, 996, 994, 1, 0, 0, 0, 996, 997, 1, 0, 0, 0, 997, 187, 1, 0, 0, 0, 998, 996, 1, 0, 0, 0, 999, 1000, 3, 224, 112, 0, 1000, 189, 1, 0, 0, 0, 1001, 1002, 3, 192, 96, 0, 1002, 191, 1, 0, 0, 0, 1003, 1008, 3, 194, 97, 0, 1004, 1005, 5, 10, 0, 0, 1005, 1007, 3, 194, 97, 0, 1006, 1004, 1, 0, 0, 0, 1007, 1010, 1, 0, 0, 0, 1008, 1006, 1, 0, 0, 0, 1008, 1009, 1, 0, 0, 0, 1009, 193, 1, 0, 0, 0, 1010, 1008, 1, 0, 0, 0, 1011, 1016, 3, 198, 99, 0, 1012, 1013, 5, 11, 0, 0, 1013, 1015, 3, 198, 99, 0, 1014, 1012, 1, 0, 0, 0, 1015, 1018, 1, 0, 0, 0, 1016, 1014, 1, 0, 0, 0, 1016, 1017, 1, 0, 0, 0, 1017, 195, 1, 0, 0, 0, 1018, 1016, 1, 0, 0, 0, 1019, 1021, 3, 202, 101, 0, 1020, 1022, 3, 200, 100, 0, 1021, 1020, 1, 0, 0, 0, 1021, 1022, 1, 0, 0, 0, 1022, 197, 1, 0, 0, 0, 1023, 1027, 3, 196, 98, 0, 1024, 1025, 5, 12, 0, 0, 1025, 1027, 3, 196, 98, 0, 1026, 1023, 1, 0, 0, 0, 1026, 1024, 1, 0, 0, 0, 1027, 199, 1, 0, 0, 0, 1028, 1029, 7, 2, 0, 0, 1029, 201, 1, 0, 0, 0, 1030, 1039, 3, 302, 151, 0, 1031, 1039, 5, 9, 0, 0, 1032, 1033, 5, 15, 0, 0, 1033, 1039, 3, 204, 102, 0, 1034, 1035, 5, 2, 0, 0, 1035, 1036, 3, 190, 95, 0, 1036, 1037, 5, 3, 0, 0, 1037, 1039, 1, 0, 0, 0, 1038, 1030, 1, 0, 0, 0, 1038, 1031, 1, 0, 0, 0, 1038, 1032, 1, 0, 0, 0, 1038, 1034, 1, 0, 0, 0, 1039, 203, 1, 0, 0, 0, 1040, 1054, 3, 206, 103, 0, 1041, 1050, 5, 2, 0, 0, 1042, 1047, 3, 206, 103, 0, 1043, 1044, 5, 10, 0, 0, 1044, 1046, 3, 206, 103, 0, 1045, 1043, 1, 0, 0, 0, 1046, 1049, 1, 0, 0, 0, 1047, 1045, 1, 0, 0, 0, 1047, 1048, 1, 0, 0, 0, 1048, 1051, 1, 0, 0, 0, 1049, 1047, 1, 0, 0, 0, 1050, 1042, 1, 0, 0, 0, 1050, 1051, 1, 0, 0, 0, 1051, 1052, 1, 0, 0, 0, 1052, 1054, 5, 3, 0, 0, 1053, 1040, 1, 0, 0, 0, 1053, 1041, 1, 0, 0, 0, 1054, 205, 1, 0, 0, 0, 1055, 1063, 3, 302, 151, 0, 1056, 1063, 5, 9, 0, 0, 1057, 1060, 5, 12, 0, 0, 1058, 1061, 3, 302, 151, 0, 1059, 1061, 5, 9, 0, 0, 1060, 1058, 1, 0, 0, 0, 1060, 1059, 1, 0, 0, 0, 1061, 1063, 1, 0, 0, 0, 1062, 1055, 1, 0, 0, 0, 1062, 1056, 1, 0, 0, 0, 1062, 1057, 1, 0, 0, 0, 1063, 207, 1, 0, 0, 0, 1064, 1065, 5, 149, 0, 0, 1065, 209, 1, 0, 0, 0, 1066, 1069, 3, 218, 109, 0, 1067, 1069, 3, 212, 106, 0, 1068, 1066, 1, 0, 0, 0, 1068, 1067, 1, 0, 0, 0, 1069, 211, 1, 0, 0, 0, 1070, 1071, 5, 16, 0, 0, 1071, 1072, 3, 162, 81, 0, 1072, 1073, 5, 17, 0, 0, 1073, 213, 1, 0, 0, 0, 1074, 1077, 3, 220, 110, 0, 1075, 1077, 3, 216, 108, 0, 1076, 1074, 1, 0, 0, 0, 1076, 1075, 1, 0, 0, 0, 1077, 215, 1, 0, 0, 0, 1078, 1079, 5, 16, 0, 0, 1079, 1080, 3, 174, 87, 0, 1080, 1081, 5, 17, 0, 0, 1081, 217, 1, 0, 0, 0, 1082, 1084, 5, 2, 0, 0, 1083, 1085, 3, 222, 111, 0, 1084, 1083, 1, 0, 0, 0, 1085, 1086, 1, 0, 0, 0, 1086, 1084, 1, 0, 0, 0, 1086, 1087, 1, 0, 0, 0, 1087, 1088, 1, 0, 0, 0, 1088, 1089, 5, 3, 0, 0, 1089, 219, 1, 0, 0, 0, 1090, 1092, 5, 2, 0, 0, 1091, 1093, 3, 224, 112, 0, 1092, 1091, 1, 0, 0, 0, 1093, 1094, 1, 0, 0, 0, 1094, 1092, 1, 0, 0, 0, 1094, 1095, 1, 0, 0, 0, 1095, 1096, 1, 0, 0, 0, 1096, 1097, 5, 3, 0, 0, 1097, 221, 1, 0, 0, 0, 1098, 1101, 3, 226, 113, 0, 1099, 1101, 3, 210, 105, 0, 1100, 1098, 1, 0, 0, 0, 1100, 1099, 1, 0, 0, 0, 1101, 223, 1, 0, 0, 0, 1102, 1105, 3, 226, 113, 0, 1103, 1105, 3, 214, 107, 0, 1104, 1102, 1, 0, 0, 0, 1104, 1103, 1, 0, 0, 0, 1105, 225, 1, 0, 0, 0, 1106, 1109, 3, 230, 115, 0, 1107, 1109, 3, 232, 116, 0, 1108, 1106, 1, 0, 0, 0, 1108, 1107, 1, 0, 0, 0, 1109, 227, 1, 0, 0, 0, 1110, 1113, 3, 230, 115, 0, 1111, 1113, 3, 302, 151, 0, 1112, 1110, 1, 0, 0, 0, 1112, 1111, 1, 0, 0, 0, 1113, 229, 1, 0, 0, 0, 1114, 1115, 7, 3, 0, 0, 1115, 231, 1, 0, 0, 0, 1116, 1123, 3, 302, 151, 0, 1117, 1123, 3, 288, 144, 0, 1118, 1123, 3, 290, 145, 0, 1119, 1123, 3, 298, 149, 0, 1120, 1123, 3, 306, 153, 0, 1121, 1123, 5, 164, 0, 0, 1122, 1116, 1, 0, 0, 0, 1122, 1117, 1, 0, 0, 0, 1122, 1118, 1, 0, 0, 0, 1122, 1119, 1, 0, 0, 0, 1122, 1120, 1, 0, 0, 0, 1122, 1121, 1, 0, 0, 0, 1123, 233, 1, 0, 0, 0, 1124, 1125, 3, 236, 118, 0, 1125, 235, 1, 0, 0, 0, 1126, 1131, 3, 238, 119, 0, 1127, 1128, 5, 18, 0, 0, 1128, 1130, 3, 238, 119, 0, 1129, 1127, 1, 0, 0, 0, 1130, 1133, 1, 0, 0, 0, 1131, 1129, 1, 0, 0, 0, 1131, 1132, 1, 0, 0, 0, 1132, 237, 1, 0, 0, 0, 1133, 1131, 1, 0, 0, 0, 1134, 1139, 3, 240, 120, 0, 1135, 1136, 5, 19, 0, 0, 1136, 1138, 3, 240, 120, 0, 1137, 1135, 1, 0, 0, 0, 1138, 1141, 1, 0, 0, 0, 1139, 1137, 1, 0, 0, 0, 1139, 1140, 1, 0, 0, 0, 1140, 239, 1, 0, 0, 0, 1141, 1139, 1, 0, 0, 0, 1142, 1143, 3, 242, 121, 0, 1143, 241, 1, 0, 0, 0, 1144, 1162, 3, 244, 122, 0, 1145, 1146, 5, 20, 0, 0, 1146, 1163, 3, 244, 122, 0, 1147, 1148, 5, 21, 0, 0, 1148, 1163, 3, 244, 122, 0, 1149, 1150, 5, 22, 0, 0, 1150, 1163, 3, 244, 122, 0, 1151, 1152, 5, 23, 0, 0, 1152, 1163, 3, 244, 122, 0, 1153, 1154, 5, 24, 0, 0, 1154, 1163, 3, 244, 122, 0, 1155, 1156, 5, 25, 0, 0, 1156, 1163, 3, 244, 122, 0, 1157, 1158, 5, 79, 0, 0, 1158, 1163, 3, 152, 76, 0, 1159, 1160, 5, 78, 0, 0, 1160, 1161, 5, 79, 0, 0, 1161, 1163, 3, 152, 76, 0, 1162, 1145, 1, 0, 0, 0, 1162, 1147, 1, 0, 0, 0, 1162, 1149, 1, 0, 0, 0, 1162, 1151, 1, 0, 0, 0, 1162, 1153, 1, 0, 0, 0, 1162, 1155, 1, 0, 0, 0, 1162, 1157, 1, 0, 0, 0, 1162, 1159, 1, 0, 0, 0, 1162, 1163, 1, 0, 0, 0, 1163, 243, 1, 0, 0, 0, 1164, 1165, 3, 246, 123, 0, 1165, 245, 1, 0, 0, 0, 1166, 1170, 3, 256, 128, 0, 1167, 1169, 3, 248, 124, 0, 1168, 1167, 1, 0, 0, 0, 1169, 1172, 1, 0, 0, 0, 1170, 1168, 1, 0, 0, 0, 1170, 1171, 1, 0, 0, 0, 1171, 247, 1, 0, 0, 0, 1172, 1170, 1, 0, 0, 0, 1173, 1174, 5, 13, 0, 0, 1174, 1179, 3, 250, 125, 0, 1175, 1176, 5, 26, 0, 0, 1176, 1179, 3, 252, 126, 0, 1177, 1179, 3, 254, 127, 0, 1178, 1173, 1, 0, 0, 0, 1178, 1175, 1, 0, 0, 0, 1178, 1177, 1, 0, 0, 0, 1179, 249, 1, 0, 0, 0, 1180, 1181, 3, 256, 128, 0, 1181, 251, 1, 0, 0, 0, 1182, 1183, 3, 256, 128, 0, 1183, 253, 1, 0, 0, 0, 1184, 1187, 3, 294, 147, 0, 1185, 1187, 3, 296, 148, 0, 1186, 1184, 1, 0, 0, 0, 1186, 1185, 1, 0, 0, 0, 1187, 1191, 1, 0, 0, 0, 1188, 1190, 3, 258, 129, 0, 1189, 1188, 1, 0, 0, 0, 1190, 1193, 1, 0, 0, 0, 1191, 1189, 1, 0, 0, 0, 1191, 1192, 1, 0, 0, 0, 1192, 255, 1, 0, 0, 0, 1193, 1191, 1, 0, 0, 0, 1194, 1198, 3, 264, 132, 0, 1195, 1197, 3, 258, 129, 0, 1196, 1195, 1, 0, 0, 0, 1197, 1200, 1, 0, 0, 0, 1198, 1196, 1, 0, 0, 0, 1198, 1199, 1, 0, 0, 0, 1199, 257, 1, 0, 0, 0, 1200, 1198, 1, 0, 0, 0, 1201, 1204, 3, 260, 130, 0, 1202, 1204, 3, 262, 131, 0, 1203, 1201, 1, 0, 0, 0, 1203, 1202, 1, 0, 0, 0, 1204, 259, 1, 0, 0, 0, 1205, 1206, 5, 1, 0, 0, 1206, 1207, 3, 264, 132, 0, 1207, 261, 1, 0, 0, 0, 1208, 1209, 5, 11, 0, 0, 1209, 1210, 3, 264, 132, 0, 1210, 263, 1, 0, 0, 0, 1211, 1212, 5, 15, 0, 0, 1212, 1219, 3, 266, 133, 0, 1213, 1214, 5, 13, 0, 0, 1214, 1219, 3, 266, 133, 0, 1215, 1216, 5, 26, 0, 0, 1216, 1219, 3, 266, 133, 0, 1217, 1219, 3, 266, 133, 0, 1218, 1211, 1, 0, 0, 0, 1218, 1213, 1, 0, 0, 0, 1218, 1215, 1, 0, 0, 0, 1218, 1217, 1, 0, 0, 0, 1219, 265, 1, 0, 0, 0, 1220, 1228, 3, 268, 134, 0, 1221, 1228, 3, 270, 135, 0, 1222, 1228, 3, 286, 143, 0, 1223, 1228, 3, 288, 144, 0, 1224, 1228, 3, 290, 145, 0, 1225, 1228, 3, 298, 149, 0, 1226, 1228, 3, 230, 115, 0, 1227, 1220, 1, 0, 0, 0, 1227, 1221, 1, 0, 0, 0, 1227, 1222, 1, 0, 0, 0, 1227, 1223, 1, 0, 0, 0, 1227, 1224, 1, 0, 0, 0, 1227, 1225, 1, 0, 0, 0, 1227, 1226, 1, 0, 0, 0, 1228, 267, 1, 0, 0, 0, 1229, 1230, 5, 2, 0, 0, 1230, 1231, 3, 234, 117, 0, 1231, 1232, 5, 3, 0, 0, 1232, 269, 1, 0, 0, 0, 1233, 1488, 3, 284, 142, 0, 1234, 1235, 5, 80, 0, 0, 1235, 1236, 5, 2, 0, 0, 1236, 1237, 3, 234, 117, 0, 1237, 1238, 5, 3, 0, 0, 1238, 1488, 1, 0, 0, 0, 1239, 1488, 3, 274, 137, 0, 1240, 1241, 5, 82, 0, 0, 1241, 1242, 5, 2, 0, 0, 1242, 1243, 3, 234, 117, 0, 1243, 1244, 5, 8, 0, 0, 1244, 1245, 3, 234, 117, 0, 1245, 1246, 5, 3, 0, 0, 1246, 1488, 1, 0, 0, 0, 1247, 1248, 5, 83, 0, 0, 1248, 1249, 5, 2, 0, 0, 1249, 1250, 3, 234, 117, 0, 1250, 1251, 5, 3, 0, 0, 1251, 1488, 1, 0, 0, 0, 1252, 1253, 5, 84, 0, 0, 1253, 1254, 5, 2, 0, 0, 1254, 1255, 3, 230, 115, 0, 1255, 1256, 5, 3, 0, 0, 1256, 1488, 1, 0, 0, 0, 1257, 1258, 5, 85, 0, 0, 1258, 1259, 5, 2, 0, 0, 1259, 1260, 3, 234, 117, 0, 1260, 1261, 5, 3, 0, 0, 1261, 1488, 1, 0, 0, 0, 1262, 1263, 5, 86, 0, 0, 1263, 1264, 5, 2, 0, 0, 1264, 1265, 3, 234, 117, 0, 1265, 1266, 5, 3, 0, 0, 1266, 1488, 1, 0, 0, 0, 1267, 1273, 5, 87, 0, 0, 1268, 1269, 5, 2, 0, 0, 1269, 1270, 3, 234, 117, 0, 1270, 1271, 5, 3, 0, 0, 1271, 1274, 1, 0, 0, 0, 1272, 1274, 5, 164, 0, 0, 1273, 1268, 1, 0, 0, 0, 1273, 1272, 1, 0, 0, 0, 1274, 1488, 1, 0, 0, 0, 1275, 1276, 5, 88, 0, 0, 1276, 1488, 5, 164, 0, 0, 1277, 1278, 5, 89, 0, 0, 1278, 1279, 5, 2, 0, 0, 1279, 1280, 3, 234, 117, 0, 1280, 1281, 5, 3, 0, 0, 1281, 1488, 1, 0, 0, 0, 1282, 1283, 5, 90, 0, 0, 1283, 1284, 5, 2, 0, 0, 1284, 1285, 3, 234, 117, 0, 1285, 1286, 5, 3, 0, 0, 1286, 1488, 1, 0, 0, 0, 1287, 1288, 5, 91, 0, 0, 1288, 1289, 5, 2, 0, 0, 1289, 1290, 3, 234, 117, 0, 1290, 1291, 5, 3, 0, 0, 1291, 1488, 1, 0, 0, 0, 1292, 1293, 5, 92, 0, 0, 1293, 1294, 5, 2, 0, 0, 1294, 1295, 3, 234, 117, 0, 1295, 1296, 5, 3, 0, 0, 1296, 1488, 1, 0, 0, 0, 1297, 1298, 5, 93, 0, 0, 1298, 1488, 3, 152, 76, 0, 1299, 1488, 3, 276, 138, 0, 1300, 1301, 5, 94, 0, 0, 1301, 1302, 5, 2, 0, 0, 1302, 1303, 3, 234, 117, 0, 1303, 1304, 5, 3, 0, 0, 1304, 1488, 1, 0, 0, 0, 1305, 1488, 3, 278, 139, 0, 1306, 1307, 5, 95, 0, 0, 1307, 1308, 5, 2, 0, 0, 1308, 1309, 3, 234, 117, 0, 1309, 1310, 5, 3, 0, 0, 1310, 1488, 1, 0, 0, 0, 1311, 1312, 5, 96, 0, 0, 1312, 1313, 5, 2, 0, 0, 1313, 1314, 3, 234, 117, 0, 1314, 1315, 5, 3, 0, 0, 1315, 1488, 1, 0, 0, 0, 1316, 1317, 5, 97, 0, 0, 1317, 1318, 5, 2, 0, 0, 1318, 1319, 3, 234, 117, 0, 1319, 1320, 5, 3, 0, 0, 1320, 1488, 1, 0, 0, 0, 1321, 1322, 5, 99, 0, 0, 1322, 1323, 5, 2, 0, 0, 1323, 1324, 3, 234, 117, 0, 1324, 1325, 5, 8, 0, 0, 1325, 1326, 3, 234, 117, 0, 1326, 1327, 5, 3, 0, 0, 1327, 1488, 1, 0, 0, 0, 1328, 1329, 5, 100, 0, 0, 1329, 1330, 5, 2, 0, 0, 1330, 1331, 3, 234, 117, 0, 1331, 1332, 5, 8, 0, 0, 1332, 1333, 3, 234, 117, 0, 1333, 1334, 5, 3, 0, 0, 1334, 1488, 1, 0, 0, 0, 1335, 1336, 5, 101, 0, 0, 1336, 1337, 5, 2, 0, 0, 1337, 1338, 3, 234, 117, 0, 1338, 1339, 5, 8, 0, 0, 1339, 1340, 3, 234, 117, 0, 1340, 1341, 5, 3, 0, 0, 1341, 1488, 1, 0, 0, 0, 1342, 1343, 5, 102, 0, 0, 1343, 1344, 5, 2, 0, 0, 1344, 1345, 3, 234, 117, 0, 1345, 1346, 5, 8, 0, 0, 1346, 1347, 3, 234, 117, 0, 1347, 1348, 5, 3, 0, 0, 1348, 1488, 1, 0, 0, 0, 1349, 1350, 5, 103, 0, 0, 1350, 1351, 5, 2, 0, 0, 1351, 1352, 3, 234, 117, 0, 1352, 1353, 5, 8, 0, 0, 1353, 1354, 3, 234, 117, 0, 1354, 1355, 5, 3, 0, 0, 1355, 1488, 1, 0, 0, 0, 1356, 1357, 5, 104, 0, 0, 1357, 1358, 5, 2, 0, 0, 1358, 1359, 3, 234, 117, 0, 1359, 1360, 5, 3, 0, 0, 1360, 1488, 1, 0, 0, 0, 1361, 1362, 5, 105, 0, 0, 1362, 1363, 5, 2, 0, 0, 1363, 1364, 3, 234, 117, 0, 1364, 1365, 5, 3, 0, 0, 1365, 1488, 1, 0, 0, 0, 1366, 1367, 5, 106, 0, 0, 1367, 1368, 5, 2, 0, 0, 1368, 1369, 3, 234, 117, 0, 1369, 1370, 5, 3, 0, 0, 1370, 1488, 1, 0, 0, 0, 1371, 1372, 5, 107, 0, 0, 1372, 1373, 5, 2, 0, 0, 1373, 1374, 3, 234, 117, 0, 1374, 1375, 5, 3, 0, 0, 1375, 1488, 1, 0, 0, 0, 1376, 1377, 5, 108, 0, 0, 1377, 1378, 5, 2, 0, 0, 1378, 1379, 3, 234, 117, 0, 1379, 1380, 5, 3, 0, 0, 1380, 1488, 1, 0, 0, 0, 1381, 1382, 5, 109, 0, 0, 1382, 1383, 5, 2, 0, 0, 1383, 1384, 3, 234, 117, 0, 1384, 1385, 5, 3, 0, 0, 1385, 1488, 1, 0, 0, 0, 1386, 1387, 5, 110, 0, 0, 1387, 1388, 5, 2, 0, 0, 1388, 1389, 3, 234, 117, 0, 1389, 1390, 5, 3, 0, 0, 1390, 1488, 1, 0, 0, 0, 1391, 1392, 5, 111, 0, 0, 1392, 1393, 5, 2, 0, 0, 1393, 1394, 3, 234, 117, 0, 1394, 1395, 5, 3, 0, 0, 1395, 1488, 1, 0, 0, 0, 1396, 1397, 5, 112, 0, 0, 1397, 1488, 5, 164, 0, 0, 1398, 1399, 5, 113, 0, 0, 1399, 1488, 5, 164, 0, 0, 1400, 1401, 5, 114, 0, 0, 1401, 1488, 5, 164, 0, 0, 1402, 1403, 5, 119, 0, 0, 1403, 1404, 5, 2, 0, 0, 1404, 1405, 3, 234, 117, 0, 1405, 1406, 5, 3, 0, 0, 1406, 1488, 1, 0, 0, 0, 1407, 1408, 5, 115, 0, 0, 1408, 1409, 5, 2, 0, 0, 1409, 1410, 3, 234, 117, 0, 1410, 1411, 5, 3, 0, 0, 1411, 1488, 1, 0, 0, 0, 1412, 1413, 5, 116, 0, 0, 1413, 1414, 5, 2, 0, 0, 1414, 1415, 3, 234, 117, 0, 1415, 1416, 5, 3, 0, 0, 1416, 1488, 1, 0, 0, 0, 1417, 1418, 5, 117, 0, 0, 1418, 1419, 5, 2, 0, 0, 1419, 1420, 3, 234, 117, 0, 1420, 1421, 5, 3, 0, 0, 1421, 1488, 1, 0, 0, 0, 1422, 1423, 5, 118, 0, 0, 1423, 1424, 5, 2, 0, 0, 1424, 1425, 3, 234, 117, 0, 1425, 1426, 5, 3, 0, 0, 1426, 1488, 1, 0, 0, 0, 1427, 1428, 5, 120, 0, 0, 1428, 1488, 3, 152, 76, 0, 1429, 1430, 5, 121, 0, 0, 1430, 1431, 5, 2, 0, 0, 1431, 1432, 3, 234, 117, 0, 1432, 1433, 5, 8, 0, 0, 1433, 1434, 3, 234, 117, 0, 1434, 1435, 5, 8, 0, 0, 1435, 1436, 3, 234, 117, 0, 1436, 1437, 5, 3, 0, 0, 1437, 1488, 1, 0, 0, 0, 1438, 1439, 5, 122, 0, 0, 1439, 1440, 5, 2, 0, 0, 1440, 1441, 3, 234, 117, 0, 1441, 1442, 5, 8, 0, 0, 1442, 1443, 3, 234, 117, 0, 1443, 1444, 5, 3, 0, 0, 1444, 1488, 1, 0, 0, 0, 1445, 1446, 5, 123, 0, 0, 1446, 1447, 5, 2, 0, 0, 1447, 1448, 3, 234, 117, 0, 1448, 1449, 5, 8, 0, 0, 1449, 1450, 3, 234, 117, 0, 1450, 1451, 5, 3, 0, 0, 1451, 1488, 1, 0, 0, 0, 1452, 1453, 5, 124, 0, 0, 1453, 1454, 5, 2, 0, 0, 1454, 1455, 3, 234, 117, 0, 1455, 1456, 5, 8, 0, 0, 1456, 1457, 3, 234, 117, 0, 1457, 1458, 5, 3, 0, 0, 1458, 1488, 1, 0, 0, 0, 1459, 1460, 5, 125, 0, 0, 1460, 1461, 5, 2, 0, 0, 1461, 1462, 3, 234, 117, 0, 1462, 1463, 5, 3, 0, 0, 1463, 1488, 1, 0, 0, 0, 1464, 1465, 5, 126, 0, 0, 1465, 1466, 5, 2, 0, 0, 1466, 1467, 3, 234, 117, 0, 1467, 1468, 5, 3, 0, 0, 1468, 1488, 1, 0, 0, 0, 1469, 1470, 5, 127, 0, 0, 1470, 1471, 5, 2, 0, 0, 1471, 1472, 3, 234, 117, 0, 1472, 1473, 5, 3, 0, 0, 1473, 1488, 1, 0, 0, 0, 1474, 1475, 5, 128, 0, 0, 1475, 1476, 5, 2, 0, 0, 1476, 1477, 3, 234, 117, 0, 1477, 1478, 5, 3, 0, 0, 1478, 1488, 1, 0, 0, 0, 1479, 1480, 5, 129, 0, 0, 1480, 1481, 5, 2, 0, 0, 1481, 1482, 3, 234, 117, 0, 1482, 1483, 5, 3, 0, 0, 1483, 1488, 1, 0, 0, 0, 1484, 1488, 3, 272, 136, 0, 1485, 1488, 3, 280, 140, 0, 1486, 1488, 3, 282, 141, 0, 1487, 1233, 1, 0, 0, 0, 1487, 1234, 1, 0, 0, 0, 1487, 1239, 1, 0, 0, 0, 1487, 1240, 1, 0, 0, 0, 1487, 1247, 1, 0, 0, 0, 1487, 1252, 1, 0, 0, 0, 1487, 1257, 1, 0, 0, 0, 1487, 1262, 1, 0, 0, 0, 1487, 1267, 1, 0, 0, 0, 1487, 1275, 1, 0, 0, 0, 1487, 1277, 1, 0, 0, 0, 1487, 1282, 1, 0, 0, 0, 1487, 1287, 1, 0, 0, 0, 1487, 1292, 1, 0, 0, 0, 1487, 1297, 1, 0, 0, 0, 1487, 1299, 1, 0, 0, 0, 1487, 1300, 1, 0, 0, 0, 1487, 1305, 1, 0, 0, 0, 1487, 1306, 1, 0, 0, 0, 1487, 1311, 1, 0, 0, 0, 1487, 1316, 1, 0, 0, 0, 1487, 1321, 1, 0, 0, 0, 1487, 1328, 1, 0, 0, 0, 1487, 1335, 1, 0, 0, 0, 1487, 1342, 1, 0, 0, 0, 1487, 1349, 1, 0, 0, 0, 1487, 1356, 1, 0, 0, 0, 1487, 1361, 1, 0, 0, 0, 1487, 1366, 1, 0, 0, 0, 1487, 1371, 1, 0, 0, 0, 1487, 1376, 1, 0, 0, 0, 1487, 1381, 1, 0, 0, 0, 1487, 1386, 1, 0, 0, 0, 1487, 1391, 1, 0, 0, 0, 1487, 1396, 1, 0, 0, 0, 1487, 1398, 1, 0, 0, 0, 1487, 1400, 1, 0, 0, 0, 1487, 1402, 1, 0, 0, 0, 1487, 1407, 1, 0, 0, 0, 1487, 1412, 1, 0, 0, 0, 1487, 1417, 1, 0, 0, 0, 1487, 1422, 1, 0, 0, 0, 1487, 1427, 1, 0, 0, 0, 1487, 1429, 1, 0, 0, 0, 1487, 1438, 1, 0, 0, 0, 1487, 1445, 1, 0, 0, 0, 1487, 1452, 1, 0, 0, 0, 1487, 1459, 1, 0, 0, 0, 1487, 1464, 1, 0, 0, 0, 1487, 1469, 1, 0, 0, 0, 1487, 1474, 1, 0, 0, 0, 1487, 1479, 1, 0, 0, 0, 1487, 1484, 1, 0, 0, 0, 1487, 1485, 1, 0, 0, 0, 1487, 1486, 1, 0, 0, 0, 1488, 271, 1, 0, 0, 0, 1489, 1490, 5, 130, 0, 0, 1490, 1491, 5, 2, 0, 0, 1491, 1492, 3, 234, 117, 0, 1492, 1493, 5, 8, 0, 0, 1493, 1496, 3, 234, 117, 0, 1494, 1495, 5, 8, 0, 0, 1495, 1497, 3, 234, 117, 0, 1496, 1494, 1, 0, 0, 0, 1496, 1497, 1, 0, 0, 0, 1497, 1498, 1, 0, 0, 0, 1498, 1499, 5, 3, 0, 0, 1499, 273, 1, 0, 0, 0, 1500, 1501, 5, 81, 0, 0, 1501, 1502, 5, 2, 0, 0, 1502, 1503, 3, 234, 117, 0, 1503, 1504, 5, 3, 0, 0, 1504, 275, 1, 0, 0, 0, 1505, 1506, 5, 131, 0, 0, 1506, 1507, 5, 2, 0, 0, 1507, 1508, 3, 234, 117, 0, 1508, 1509, 5, 8, 0, 0, 1509, 1512, 3, 234, 117, 0, 1510, 1511, 5, 8, 0, 0, 1511, 1513, 3, 234, 117, 0, 1512, 1510, 1, 0, 0, 0, 1512, 1513, 1, 0, 0, 0, 1513, 1514, 1, 0, 0, 0, 1514, 1515, 5, 3, 0, 0, 1515, 277, 1, 0, 0, 0, 1516, 1517, 5, 132, 0, 0, 1517, 1518, 5, 2, 0, 0, 1518, 1519, 3, 234, 117, 0, 1519, 1520, 5, 8, 0, 0, 1520, 1521, 3, 234, 117, 0, 1521, 1522, 5, 8, 0, 0, 1522, 1525, 3, 234, 117, 0, 1523, 1524, 5, 8, 0, 0, 1524, 1526, 3, 234, 117, 0, 1525, 1523, 1, 0, 0, 0, 1525, 1526, 1, 0, 0, 0, 1526, 1527, 1, 0, 0, 0, 1527, 1528, 5, 3, 0, 0, 1528, 279, 1, 0, 0, 0, 1529, 1530, 5, 133, 0, 0, 1530, 1531, 3, 110, 55, 0, 1531, 281, 1, 0, 0, 0, 1532, 1533, 5, 78, 0, 0, 1533, 1534, 5, 133, 0, 0, 1534, 1535, 3, 110, 55, 0, 1535, 283, 1, 0, 0, 0, 1536, 1537, 5, 134, 0, 0, 1537, 1539, 5, 2, 0, 0, 1538, 1540, 5, 33, 0, 0, 1539, 1538, 1, 0, 0, 0, 1539, 1540, 1, 0, 0, 0, 1540, 1543, 1, 0, 0, 0, 1541, 1544, 5, 1, 0, 0, 1542, 1544, 3, 234, 117, 0, 1543, 1541, 1, 0, 0, 0, 1543, 1542, 1, 0, 0, 0, 1544, 1545, 1, 0, 0, 0, 1545, 1601, 5, 3, 0, 0, 1546, 1547, 5, 135, 0, 0, 1547, 1549, 5, 2, 0, 0, 1548, 1550, 5, 33, 0, 0, 1549, 1548, 1, 0, 0, 0, 1549, 1550, 1, 0, 0, 0, 1550, 1551, 1, 0, 0, 0, 1551, 1552, 3, 234, 117, 0, 1552, 1553, 5, 3, 0, 0, 1553, 1601, 1, 0, 0, 0, 1554, 1555, 5, 136, 0, 0, 1555, 1557, 5, 2, 0, 0, 1556, 1558, 5, 33, 0, 0, 1557, 1556, 1, 0, 0, 0, 1557, 1558, 1, 0, 0, 0, 1558, 1559, 1, 0, 0, 0, 1559, 1560, 3, 234, 117, 0, 1560, 1561, 5, 3, 0, 0, 1561, 1601, 1, 0, 0, 0, 1562, 1563, 5, 137, 0, 0, 1563, 1565, 5, 2, 0, 0, 1564, 1566, 5, 33, 0, 0, 1565, 1564, 1, 0, 0, 0, 1565, 1566, 1, 0, 0, 0, 1566, 1567, 1, 0, 0, 0, 1567, 1568, 3, 234, 117, 0, 1568, 1569, 5, 3, 0, 0, 1569, 1601, 1, 0, 0, 0, 1570, 1571, 5, 138, 0, 0, 1571, 1573, 5, 2, 0, 0, 1572, 1574, 5, 33, 0, 0, 1573, 1572, 1, 0, 0, 0, 1573, 1574, 1, 0, 0, 0, 1574, 1575, 1, 0, 0, 0, 1575, 1576, 3, 234, 117, 0, 1576, 1577, 5, 3, 0, 0, 1577, 1601, 1, 0, 0, 0, 1578, 1579, 5, 139, 0, 0, 1579, 1581, 5, 2, 0, 0, 1580, 1582, 5, 33, 0, 0, 1581, 1580, 1, 0, 0, 0, 1581, 1582, 1, 0, 0, 0, 1582, 1583, 1, 0, 0, 0, 1583, 1584, 3, 234, 117, 0, 1584, 1585, 5, 3, 0, 0, 1585, 1601, 1, 0, 0, 0, 1586, 1587, 5, 43, 0, 0, 1587, 1589, 5, 2, 0, 0, 1588, 1590, 5, 33, 0, 0, 1589, 1588, 1, 0, 0, 0, 1589, 1590, 1, 0, 0, 0, 1590, 1591, 1, 0, 0, 0, 1591, 1596, 3, 234, 117, 0, 1592, 1593, 5, 6, 0, 0, 1593, 1594, 5, 140, 0, 0, 1594, 1595, 5, 20, 0, 0, 1595, 1597, 3, 300, 150, 0, 1596, 1592, 1, 0, 0, 0, 1596, 1597, 1, 0, 0, 0, 1597, 1598, 1, 0, 0, 0, 1598, 1599, 5, 3, 0, 0, 1599, 1601, 1, 0, 0, 0, 1600, 1536, 1, 0, 0, 0, 1600, 1546, 1, 0, 0, 0, 1600, 1554, 1, 0, 0, 0, 1600, 1562, 1, 0, 0, 0, 1600, 1570, 1, 0, 0, 0, 1600, 1578, 1, 0, 0, 0, 1600, 1586, 1, 0, 0, 0, 1601, 285, 1, 0, 0, 0, 1602, 1604, 3, 302, 151, 0, 1603, 1605, 3, 150, 75, 0, 1604, 1603, 1, 0, 0, 0, 1604, 1605, 1, 0, 0, 0, 1605, 287, 1, 0, 0, 0, 1606, 1610, 3, 300, 150, 0, 1607, 1611, 5, 147, 0, 0, 1608, 1609, 5, 27, 0, 0, 1609, 1611, 3, 302, 151, 0, 1610, 1607, 1, 0, 0, 0, 1610, 1608, 1, 0, 0, 0, 1610, 1611, 1, 0, 0, 0, 1611, 289, 1, 0, 0, 0, 1612, 1616, 3, 292, 146, 0, 1613, 1616, 3, 294, 147, 0, 1614, 1616, 3, 296, 148, 0, 1615, 1612, 1, 0, 0, 0, 1615, 1613, 1, 0, 0, 0, 1615, 1614, 1, 0, 0, 0, 1616, 291, 1, 0, 0, 0, 1617, 1618, 7, 4, 0, 0, 1618, 293, 1, 0, 0, 0, 1619, 1620, 7, 5, 0, 0, 1620, 295, 1, 0, 0, 0, 1621, 1622, 7, 6, 0, 0, 1622, 297, 1, 0, 0, 0, 1623, 1624, 7, 7, 0, 0, 1624, 299, 1, 0, 0, 0, 1625, 1626, 7, 8, 0, 0, 1626, 301, 1, 0, 0, 0, 1627, 1629, 5, 148, 0, 0, 1628, 1627, 1, 0, 0, 0, 1628, 1629, 1, 0, 0, 0, 1629, 1632, 1, 0, 0, 0, 1630, 1633, 3, 308, 154, 0, 1631, 1633, 3, 304, 152, 0, 1632, 1630, 1, 0, 0, 0, 1632, 1631, 1, 0, 0, 0, 1633, 303, 1, 0, 0, 0, 1634, 1637, 3, 310, 155, 0, 1635, 1637, 3, 312, 156, 0, 1636, 1634, 1, 0, 0, 0, 1636, 1635, 1, 0, 0, 0, 1637, 305, 1, 0, 0, 0, 1638, 1639, 7, 9, 0, 0, 1639, 307, 1, 0, 0, 0, 1640, 1641, 5, 141, 0, 0, 1641, 309, 1, 0, 0, 0, 1642, 1643, 5, 143, 0, 0, 1643, 311, 1, 0, 0, 0, 1644, 1645, 5, 142, 0, 0, 1645, 313, 1, 0, 0, 0, 161, 318, 325, 331, 333, 347, 360, 365, 368, 372, 387, 396, 402, 406, 412, 415, 420, 424, 432, 441, 451, 456, 459, 462, 465, 471, 479, 484, 490, 496, 501, 507, 509, 513, 516, 520, 523, 527, 530, 534, 537, 541, 544, 548, 551, 553, 566, 572, 574, 587, 591, 596, 600, 606, 612, 618, 626, 634, 654, 658, 661, 666, 682, 687, 696, 707, 711, 714, 718, 725, 732, 734, 739, 744, 749, 754, 757, 762, 764, 774, 785, 802, 809, 819, 823, 829, 838, 843, 850, 860, 869, 877, 884, 889, 898, 903, 907, 914, 916, 924, 927, 935, 939, 944, 951, 962, 965, 970, 974, 989, 996, 1008, 1016, 1021, 1026, 1038, 1047, 1050, 1053, 1060, 1062, 1068, 1076, 1086, 1094, 1100, 1104, 1108, 1112, 1122, 1131, 1139, 1162, 1170, 1178, 1186, 1191, 1198, 1203, 1218, 1227, 1273, 1487, 1496, 1512, 1525, 1539, 1543, 1549, 1557, 1565, 1573, 1581, 1589, 1596, 1600, 1604, 1610, 1615, 1628, 1632, 1636] \ No newline at end of file diff --git a/src/parser/sparqlParser/generated/SparqlAutomatic.tokens b/src/parser/sparqlParser/generated/SparqlAutomatic.tokens index 05124f86e3..4d2a3fec0c 100644 --- a/src/parser/sparqlParser/generated/SparqlAutomatic.tokens +++ b/src/parser/sparqlParser/generated/SparqlAutomatic.tokens @@ -52,133 +52,135 @@ TEXTLIMIT=51 VALUES=52 LOAD=53 SILENT=54 -CLEAR=55 -DROP=56 -CREATE=57 -ADD=58 -DATA=59 -MOVE=60 -COPY=61 -INSERT=62 -DELETE=63 -WITH=64 -USING=65 -DEFAULT=66 -GRAPH=67 -ALL=68 -OPTIONAL=69 -SERVICE=70 -BIND=71 -UNDEF=72 -MINUS=73 -UNION=74 -FILTER=75 -NOT=76 -IN=77 -STR=78 -LANG=79 -LANGMATCHES=80 -DATATYPE=81 -BOUND=82 -IRI=83 -URI=84 -BNODE=85 -RAND=86 -ABS=87 -CEIL=88 -FLOOR=89 -ROUND=90 -CONCAT=91 -STRLEN=92 -UCASE=93 -LCASE=94 -ENCODE_FOR_URI=95 -FOR=96 -CONTAINS=97 -STRSTARTS=98 -STRENDS=99 -STRBEFORE=100 -STRAFTER=101 -YEAR=102 -MONTH=103 -DAY=104 -HOURS=105 -MINUTES=106 -SECONDS=107 -TIMEZONE=108 -TZ=109 -NOW=110 -UUID=111 -STRUUID=112 -SHA1=113 -SHA256=114 -SHA384=115 -SHA512=116 -MD5=117 -COALESCE=118 -IF=119 -STRLANG=120 -STRDT=121 -SAMETERM=122 -ISIRI=123 -ISURI=124 -ISBLANK=125 -ISLITERAL=126 -ISNUMERIC=127 -REGEX=128 -SUBSTR=129 -REPLACE=130 -EXISTS=131 -COUNT=132 -SUM=133 -MIN=134 -MAX=135 -AVG=136 -SAMPLE=137 -SEPARATOR=138 -IRI_REF=139 -PNAME_NS=140 -PNAME_LN=141 -BLANK_NODE_LABEL=142 -VAR1=143 -VAR2=144 -LANGTAG=145 -PREFIX_LANGTAG=146 -INTEGER=147 -DECIMAL=148 -DOUBLE=149 -INTEGER_POSITIVE=150 -DECIMAL_POSITIVE=151 -DOUBLE_POSITIVE=152 -INTEGER_NEGATIVE=153 -DECIMAL_NEGATIVE=154 -DOUBLE_NEGATIVE=155 -EXPONENT=156 -STRING_LITERAL1=157 -STRING_LITERAL2=158 -STRING_LITERAL_LONG1=159 -STRING_LITERAL_LONG2=160 -ECHAR=161 -NIL=162 -ANON=163 -PN_CHARS_U=164 -VARNAME=165 -PN_PREFIX=166 -PN_LOCAL=167 -PLX=168 -PERCENT=169 -HEX=170 -PN_LOCAL_ESC=171 -WS=172 -COMMENTS=173 +INTO=55 +CLEAR=56 +DROP=57 +CREATE=58 +ADD=59 +TO=60 +DATA=61 +MOVE=62 +COPY=63 +INSERT=64 +DELETE=65 +WITH=66 +USING=67 +DEFAULT=68 +GRAPH=69 +ALL=70 +OPTIONAL=71 +SERVICE=72 +BIND=73 +UNDEF=74 +MINUS=75 +UNION=76 +FILTER=77 +NOT=78 +IN=79 +STR=80 +LANG=81 +LANGMATCHES=82 +DATATYPE=83 +BOUND=84 +IRI=85 +URI=86 +BNODE=87 +RAND=88 +ABS=89 +CEIL=90 +FLOOR=91 +ROUND=92 +CONCAT=93 +STRLEN=94 +UCASE=95 +LCASE=96 +ENCODE_FOR_URI=97 +FOR=98 +CONTAINS=99 +STRSTARTS=100 +STRENDS=101 +STRBEFORE=102 +STRAFTER=103 +YEAR=104 +MONTH=105 +DAY=106 +HOURS=107 +MINUTES=108 +SECONDS=109 +TIMEZONE=110 +TZ=111 +NOW=112 +UUID=113 +STRUUID=114 +SHA1=115 +SHA256=116 +SHA384=117 +SHA512=118 +MD5=119 +COALESCE=120 +IF=121 +STRLANG=122 +STRDT=123 +SAMETERM=124 +ISIRI=125 +ISURI=126 +ISBLANK=127 +ISLITERAL=128 +ISNUMERIC=129 +REGEX=130 +SUBSTR=131 +REPLACE=132 +EXISTS=133 +COUNT=134 +SUM=135 +MIN=136 +MAX=137 +AVG=138 +SAMPLE=139 +SEPARATOR=140 +IRI_REF=141 +PNAME_NS=142 +PNAME_LN=143 +BLANK_NODE_LABEL=144 +VAR1=145 +VAR2=146 +LANGTAG=147 +PREFIX_LANGTAG=148 +INTEGER=149 +DECIMAL=150 +DOUBLE=151 +INTEGER_POSITIVE=152 +DECIMAL_POSITIVE=153 +DOUBLE_POSITIVE=154 +INTEGER_NEGATIVE=155 +DECIMAL_NEGATIVE=156 +DOUBLE_NEGATIVE=157 +EXPONENT=158 +STRING_LITERAL1=159 +STRING_LITERAL2=160 +STRING_LITERAL_LONG1=161 +STRING_LITERAL_LONG2=162 +ECHAR=163 +NIL=164 +ANON=165 +PN_CHARS_U=166 +VARNAME=167 +PN_PREFIX=168 +PN_LOCAL=169 +PLX=170 +PERCENT=171 +HEX=172 +PN_LOCAL_ESC=173 +WS=174 +COMMENTS=175 '*'=1 '('=2 ')'=3 '{'=4 '}'=5 -'.'=6 -','=7 -';'=8 +';'=6 +'.'=7 +','=8 'a'=9 '|'=10 '/'=11 diff --git a/src/parser/sparqlParser/generated/SparqlAutomaticBaseListener.h b/src/parser/sparqlParser/generated/SparqlAutomaticBaseListener.h index 579182a362..87394990a8 100644 --- a/src/parser/sparqlParser/generated/SparqlAutomaticBaseListener.h +++ b/src/parser/sparqlParser/generated/SparqlAutomaticBaseListener.h @@ -13,6 +13,11 @@ */ class SparqlAutomaticBaseListener : public SparqlAutomaticListener { public: + virtual void enterQueryOrUpdate( + SparqlAutomaticParser::QueryOrUpdateContext* /*ctx*/) override {} + virtual void exitQueryOrUpdate( + SparqlAutomaticParser::QueryOrUpdateContext* /*ctx*/) override {} + virtual void enterQuery( SparqlAutomaticParser::QueryContext* /*ctx*/) override {} virtual void exitQuery( @@ -163,6 +168,115 @@ class SparqlAutomaticBaseListener : public SparqlAutomaticListener { virtual void exitValuesClause( SparqlAutomaticParser::ValuesClauseContext* /*ctx*/) override {} + virtual void enterUpdate( + SparqlAutomaticParser::UpdateContext* /*ctx*/) override {} + virtual void exitUpdate( + SparqlAutomaticParser::UpdateContext* /*ctx*/) override {} + + virtual void enterUpdate1( + SparqlAutomaticParser::Update1Context* /*ctx*/) override {} + virtual void exitUpdate1( + SparqlAutomaticParser::Update1Context* /*ctx*/) override {} + + virtual void enterLoad(SparqlAutomaticParser::LoadContext* /*ctx*/) override { + } + virtual void exitLoad(SparqlAutomaticParser::LoadContext* /*ctx*/) override {} + + virtual void enterClear( + SparqlAutomaticParser::ClearContext* /*ctx*/) override {} + virtual void exitClear( + SparqlAutomaticParser::ClearContext* /*ctx*/) override {} + + virtual void enterDrop(SparqlAutomaticParser::DropContext* /*ctx*/) override { + } + virtual void exitDrop(SparqlAutomaticParser::DropContext* /*ctx*/) override {} + + virtual void enterCreate( + SparqlAutomaticParser::CreateContext* /*ctx*/) override {} + virtual void exitCreate( + SparqlAutomaticParser::CreateContext* /*ctx*/) override {} + + virtual void enterAdd(SparqlAutomaticParser::AddContext* /*ctx*/) override {} + virtual void exitAdd(SparqlAutomaticParser::AddContext* /*ctx*/) override {} + + virtual void enterMove(SparqlAutomaticParser::MoveContext* /*ctx*/) override { + } + virtual void exitMove(SparqlAutomaticParser::MoveContext* /*ctx*/) override {} + + virtual void enterCopy(SparqlAutomaticParser::CopyContext* /*ctx*/) override { + } + virtual void exitCopy(SparqlAutomaticParser::CopyContext* /*ctx*/) override {} + + virtual void enterInsertData( + SparqlAutomaticParser::InsertDataContext* /*ctx*/) override {} + virtual void exitInsertData( + SparqlAutomaticParser::InsertDataContext* /*ctx*/) override {} + + virtual void enterDeleteData( + SparqlAutomaticParser::DeleteDataContext* /*ctx*/) override {} + virtual void exitDeleteData( + SparqlAutomaticParser::DeleteDataContext* /*ctx*/) override {} + + virtual void enterDeleteWhere( + SparqlAutomaticParser::DeleteWhereContext* /*ctx*/) override {} + virtual void exitDeleteWhere( + SparqlAutomaticParser::DeleteWhereContext* /*ctx*/) override {} + + virtual void enterModify( + SparqlAutomaticParser::ModifyContext* /*ctx*/) override {} + virtual void exitModify( + SparqlAutomaticParser::ModifyContext* /*ctx*/) override {} + + virtual void enterDeleteClause( + SparqlAutomaticParser::DeleteClauseContext* /*ctx*/) override {} + virtual void exitDeleteClause( + SparqlAutomaticParser::DeleteClauseContext* /*ctx*/) override {} + + virtual void enterInsertClause( + SparqlAutomaticParser::InsertClauseContext* /*ctx*/) override {} + virtual void exitInsertClause( + SparqlAutomaticParser::InsertClauseContext* /*ctx*/) override {} + + virtual void enterUsingClause( + SparqlAutomaticParser::UsingClauseContext* /*ctx*/) override {} + virtual void exitUsingClause( + SparqlAutomaticParser::UsingClauseContext* /*ctx*/) override {} + + virtual void enterGraphOrDefault( + SparqlAutomaticParser::GraphOrDefaultContext* /*ctx*/) override {} + virtual void exitGraphOrDefault( + SparqlAutomaticParser::GraphOrDefaultContext* /*ctx*/) override {} + + virtual void enterGraphRef( + SparqlAutomaticParser::GraphRefContext* /*ctx*/) override {} + virtual void exitGraphRef( + SparqlAutomaticParser::GraphRefContext* /*ctx*/) override {} + + virtual void enterGraphRefAll( + SparqlAutomaticParser::GraphRefAllContext* /*ctx*/) override {} + virtual void exitGraphRefAll( + SparqlAutomaticParser::GraphRefAllContext* /*ctx*/) override {} + + virtual void enterQuadPattern( + SparqlAutomaticParser::QuadPatternContext* /*ctx*/) override {} + virtual void exitQuadPattern( + SparqlAutomaticParser::QuadPatternContext* /*ctx*/) override {} + + virtual void enterQuadData( + SparqlAutomaticParser::QuadDataContext* /*ctx*/) override {} + virtual void exitQuadData( + SparqlAutomaticParser::QuadDataContext* /*ctx*/) override {} + + virtual void enterQuads( + SparqlAutomaticParser::QuadsContext* /*ctx*/) override {} + virtual void exitQuads( + SparqlAutomaticParser::QuadsContext* /*ctx*/) override {} + + virtual void enterQuadsNotTriples( + SparqlAutomaticParser::QuadsNotTriplesContext* /*ctx*/) override {} + virtual void exitQuadsNotTriples( + SparqlAutomaticParser::QuadsNotTriplesContext* /*ctx*/) override {} + virtual void enterTriplesTemplate( SparqlAutomaticParser::TriplesTemplateContext* /*ctx*/) override {} virtual void exitTriplesTemplate( diff --git a/src/parser/sparqlParser/generated/SparqlAutomaticBaseVisitor.h b/src/parser/sparqlParser/generated/SparqlAutomaticBaseVisitor.h index 4fbf333065..3d5eef44d5 100644 --- a/src/parser/sparqlParser/generated/SparqlAutomaticBaseVisitor.h +++ b/src/parser/sparqlParser/generated/SparqlAutomaticBaseVisitor.h @@ -13,6 +13,11 @@ */ class SparqlAutomaticBaseVisitor : public SparqlAutomaticVisitor { public: + virtual std::any visitQueryOrUpdate( + SparqlAutomaticParser::QueryOrUpdateContext* ctx) override { + return visitChildren(ctx); + } + virtual std::any visitQuery( SparqlAutomaticParser::QueryContext* ctx) override { return visitChildren(ctx); @@ -163,6 +168,116 @@ class SparqlAutomaticBaseVisitor : public SparqlAutomaticVisitor { return visitChildren(ctx); } + virtual std::any visitUpdate( + SparqlAutomaticParser::UpdateContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitUpdate1( + SparqlAutomaticParser::Update1Context* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitLoad(SparqlAutomaticParser::LoadContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitClear( + SparqlAutomaticParser::ClearContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitDrop(SparqlAutomaticParser::DropContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitCreate( + SparqlAutomaticParser::CreateContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitAdd(SparqlAutomaticParser::AddContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitMove(SparqlAutomaticParser::MoveContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitCopy(SparqlAutomaticParser::CopyContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitInsertData( + SparqlAutomaticParser::InsertDataContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitDeleteData( + SparqlAutomaticParser::DeleteDataContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitDeleteWhere( + SparqlAutomaticParser::DeleteWhereContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitModify( + SparqlAutomaticParser::ModifyContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitDeleteClause( + SparqlAutomaticParser::DeleteClauseContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitInsertClause( + SparqlAutomaticParser::InsertClauseContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitUsingClause( + SparqlAutomaticParser::UsingClauseContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitGraphOrDefault( + SparqlAutomaticParser::GraphOrDefaultContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitGraphRef( + SparqlAutomaticParser::GraphRefContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitGraphRefAll( + SparqlAutomaticParser::GraphRefAllContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitQuadPattern( + SparqlAutomaticParser::QuadPatternContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitQuadData( + SparqlAutomaticParser::QuadDataContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitQuads( + SparqlAutomaticParser::QuadsContext* ctx) override { + return visitChildren(ctx); + } + + virtual std::any visitQuadsNotTriples( + SparqlAutomaticParser::QuadsNotTriplesContext* ctx) override { + return visitChildren(ctx); + } + virtual std::any visitTriplesTemplate( SparqlAutomaticParser::TriplesTemplateContext* ctx) override { return visitChildren(ctx); diff --git a/src/parser/sparqlParser/generated/SparqlAutomaticLexer.cpp b/src/parser/sparqlParser/generated/SparqlAutomaticLexer.cpp index 8da0f789fc..a1c2bd1aaf 100644 --- a/src/parser/sparqlParser/generated/SparqlAutomaticLexer.cpp +++ b/src/parser/sparqlParser/generated/SparqlAutomaticLexer.cpp @@ -102,10 +102,12 @@ void sparqlautomaticlexerLexerInitialize() { "VALUES", "LOAD", "SILENT", + "INTO", "CLEAR", "DROP", "CREATE", "ADD", + "TO", "DATA", "MOVE", "COPY", @@ -253,7 +255,7 @@ void sparqlautomaticlexerLexerInitialize() { std::vector{"DEFAULT_TOKEN_CHANNEL", "HIDDEN"}, std::vector{"DEFAULT_MODE"}, std::vector{"", "'*'", "'('", "')'", "'{'", - "'}'", "'.'", "','", "';'", "'a'", + "'}'", "';'", "'.'", "','", "'a'", "'|'", "'/'", "'^'", "'+'", "'\\u003F'", "'!'", "'['", "']'", "'||'", "'&&'", "'='", "'!='", "'<'", "'>'", "'<='", @@ -313,10 +315,12 @@ void sparqlautomaticlexerLexerInitialize() { "VALUES", "LOAD", "SILENT", + "INTO", "CLEAR", "DROP", "CREATE", "ADD", + "TO", "DATA", "MOVE", "COPY", @@ -433,1250 +437,1260 @@ void sparqlautomaticlexerLexerInitialize() { "WS", "COMMENTS"}); static const int32_t serializedATNSegment[] = { - 4, 0, 173, 1578, 6, -1, 2, 0, 7, 0, 2, - 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, - 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, - 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, - 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, - 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, - 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, - 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, - 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, - 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, - 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, - 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, - 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, - 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, - 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, - 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, - 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, - 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, - 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, - 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, - 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, - 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, - 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, - 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, - 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, - 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, - 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, - 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, - 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, - 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, - 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, - 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, - 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, - 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, - 2, 92, 7, 92, 2, 93, 7, 93, 2, 94, 7, - 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, - 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, - 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, - 2, 103, 7, 103, 2, 104, 7, 104, 2, 105, 7, - 105, 2, 106, 7, 106, 2, 107, 7, 107, 2, 108, - 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, - 111, 7, 111, 2, 112, 7, 112, 2, 113, 7, 113, - 2, 114, 7, 114, 2, 115, 7, 115, 2, 116, 7, - 116, 2, 117, 7, 117, 2, 118, 7, 118, 2, 119, - 7, 119, 2, 120, 7, 120, 2, 121, 7, 121, 2, - 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, - 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, - 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, - 7, 130, 2, 131, 7, 131, 2, 132, 7, 132, 2, - 133, 7, 133, 2, 134, 7, 134, 2, 135, 7, 135, - 2, 136, 7, 136, 2, 137, 7, 137, 2, 138, 7, - 138, 2, 139, 7, 139, 2, 140, 7, 140, 2, 141, - 7, 141, 2, 142, 7, 142, 2, 143, 7, 143, 2, - 144, 7, 144, 2, 145, 7, 145, 2, 146, 7, 146, - 2, 147, 7, 147, 2, 148, 7, 148, 2, 149, 7, - 149, 2, 150, 7, 150, 2, 151, 7, 151, 2, 152, - 7, 152, 2, 153, 7, 153, 2, 154, 7, 154, 2, - 155, 7, 155, 2, 156, 7, 156, 2, 157, 7, 157, - 2, 158, 7, 158, 2, 159, 7, 159, 2, 160, 7, - 160, 2, 161, 7, 161, 2, 162, 7, 162, 2, 163, - 7, 163, 2, 164, 7, 164, 2, 165, 7, 165, 2, - 166, 7, 166, 2, 167, 7, 167, 2, 168, 7, 168, - 2, 169, 7, 169, 2, 170, 7, 170, 2, 171, 7, - 171, 2, 172, 7, 172, 2, 173, 7, 173, 2, 174, - 7, 174, 2, 175, 7, 175, 2, 176, 7, 176, 2, - 177, 7, 177, 2, 178, 7, 178, 2, 179, 7, 179, - 2, 180, 7, 180, 2, 181, 7, 181, 2, 182, 7, - 182, 2, 183, 7, 183, 2, 184, 7, 184, 2, 185, - 7, 185, 2, 186, 7, 186, 2, 187, 7, 187, 2, - 188, 7, 188, 2, 189, 7, 189, 2, 190, 7, 190, - 2, 191, 7, 191, 2, 192, 7, 192, 2, 193, 7, - 193, 2, 194, 7, 194, 2, 195, 7, 195, 2, 196, - 7, 196, 2, 197, 7, 197, 2, 198, 7, 198, 2, - 199, 7, 199, 2, 200, 7, 200, 2, 201, 7, 201, - 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, - 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, - 1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, - 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, - 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, - 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 16, - 1, 16, 1, 17, 1, 17, 1, 17, 1, 18, 1, - 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, - 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, - 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, - 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, - 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, - 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, - 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, - 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, - 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, - 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, - 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, - 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, - 33, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, - 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, - 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 36, - 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, - 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, - 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, - 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, - 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, - 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, - 1, 41, 1, 41, 4, 41, 562, 8, 41, 11, 41, - 12, 41, 563, 1, 41, 1, 41, 1, 41, 1, 42, - 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, - 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, - 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, - 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, - 1, 44, 1, 44, 1, 44, 4, 44, 595, 8, 44, - 11, 44, 12, 44, 596, 1, 44, 1, 44, 1, 44, - 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, - 45, 1, 45, 1, 45, 1, 45, 4, 45, 611, 8, - 45, 11, 45, 12, 45, 612, 1, 45, 1, 45, 1, - 45, 1, 45, 1, 45, 4, 45, 620, 8, 45, 11, - 45, 12, 45, 621, 1, 45, 1, 45, 1, 45, 1, - 46, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, - 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, - 48, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, - 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, - 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, - 1, 50, 1, 50, 1, 50, 1, 50, 1, 51, 1, - 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, - 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, - 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, - 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, - 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, - 1, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, - 56, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, - 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, - 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, - 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, - 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, - 1, 61, 1, 62, 1, 62, 1, 62, 1, 62, 1, - 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, - 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, - 64, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, - 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, - 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, - 1, 67, 1, 67, 1, 67, 1, 67, 1, 68, 1, - 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, - 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, - 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 70, - 1, 70, 1, 70, 1, 70, 1, 70, 1, 71, 1, - 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 72, - 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, - 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, - 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, - 74, 1, 74, 1, 75, 1, 75, 1, 75, 1, 75, - 1, 76, 1, 76, 1, 76, 1, 77, 1, 77, 1, - 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 78, - 1, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, - 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, - 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, - 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, - 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, - 81, 1, 82, 1, 82, 1, 82, 1, 82, 1, 83, - 1, 83, 1, 83, 1, 83, 1, 84, 1, 84, 1, - 84, 1, 84, 1, 84, 1, 84, 1, 85, 1, 85, - 1, 85, 1, 85, 1, 85, 1, 86, 1, 86, 1, - 86, 1, 86, 1, 87, 1, 87, 1, 87, 1, 87, - 1, 87, 1, 88, 1, 88, 1, 88, 1, 88, 1, - 88, 1, 88, 1, 89, 1, 89, 1, 89, 1, 89, - 1, 89, 1, 89, 1, 90, 1, 90, 1, 90, 1, - 90, 1, 90, 1, 90, 1, 90, 1, 91, 1, 91, - 1, 91, 1, 91, 1, 91, 1, 91, 1, 91, 1, - 92, 1, 92, 1, 92, 1, 92, 1, 92, 1, 92, - 1, 93, 1, 93, 1, 93, 1, 93, 1, 93, 1, - 93, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, - 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, - 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 95, - 1, 95, 1, 95, 1, 95, 1, 96, 1, 96, 1, - 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, - 1, 96, 1, 97, 1, 97, 1, 97, 1, 97, 1, - 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, - 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, - 98, 1, 98, 1, 98, 1, 99, 1, 99, 1, 99, - 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, - 99, 1, 99, 1, 100, 1, 100, 1, 100, 1, 100, - 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, - 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 102, - 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, - 103, 1, 103, 1, 103, 1, 103, 1, 104, 1, 104, - 1, 104, 1, 104, 1, 104, 1, 104, 1, 105, 1, - 105, 1, 105, 1, 105, 1, 105, 1, 105, 1, 105, - 1, 105, 1, 106, 1, 106, 1, 106, 1, 106, 1, - 106, 1, 106, 1, 106, 1, 106, 1, 107, 1, 107, - 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, - 107, 1, 107, 1, 108, 1, 108, 1, 108, 1, 109, - 1, 109, 1, 109, 1, 109, 1, 110, 1, 110, 1, - 110, 1, 110, 1, 110, 1, 111, 1, 111, 1, 111, - 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 112, 1, 112, 1, 112, 1, 112, 1, 112, 1, 113, - 1, 113, 1, 113, 1, 113, 1, 113, 1, 113, 1, - 113, 1, 114, 1, 114, 1, 114, 1, 114, 1, 114, - 1, 114, 1, 114, 1, 115, 1, 115, 1, 115, 1, - 115, 1, 115, 1, 115, 1, 115, 1, 116, 1, 116, - 1, 116, 1, 116, 1, 117, 1, 117, 1, 117, 1, - 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, - 1, 118, 1, 118, 1, 118, 1, 119, 1, 119, 1, - 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, - 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, - 120, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, - 1, 121, 1, 121, 1, 121, 1, 121, 1, 122, 1, - 122, 1, 122, 1, 122, 1, 122, 1, 122, 1, 123, - 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, - 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, - 1, 124, 1, 124, 1, 125, 1, 125, 1, 125, 1, - 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, - 1, 125, 1, 126, 1, 126, 1, 126, 1, 126, 1, - 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, - 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, - 127, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, - 1, 128, 1, 128, 1, 129, 1, 129, 1, 129, 1, - 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 130, - 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, - 130, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, - 1, 131, 1, 132, 1, 132, 1, 132, 1, 132, 1, - 133, 1, 133, 1, 133, 1, 133, 1, 134, 1, 134, - 1, 134, 1, 134, 1, 135, 1, 135, 1, 135, 1, - 135, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, - 1, 136, 1, 136, 1, 137, 1, 137, 1, 137, 1, - 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, - 1, 137, 1, 138, 1, 138, 5, 138, 1219, 8, 138, - 10, 138, 12, 138, 1222, 9, 138, 1, 138, 1, 138, - 1, 139, 3, 139, 1227, 8, 139, 1, 139, 1, 139, - 1, 140, 1, 140, 1, 140, 1, 141, 1, 141, 1, - 141, 1, 141, 1, 141, 3, 141, 1239, 8, 141, 1, - 141, 1, 141, 5, 141, 1243, 8, 141, 10, 141, 12, - 141, 1246, 9, 141, 1, 141, 3, 141, 1249, 8, 141, - 1, 142, 1, 142, 1, 142, 1, 143, 1, 143, 1, - 143, 1, 144, 1, 144, 4, 144, 1259, 8, 144, 11, - 144, 12, 144, 1260, 1, 144, 1, 144, 1, 144, 4, - 144, 1266, 8, 144, 11, 144, 12, 144, 1267, 5, 144, - 1270, 8, 144, 10, 144, 12, 144, 1273, 9, 144, 1, - 145, 1, 145, 1, 145, 1, 146, 4, 146, 1279, 8, - 146, 11, 146, 12, 146, 1280, 1, 147, 5, 147, 1284, - 8, 147, 10, 147, 12, 147, 1287, 9, 147, 1, 147, - 1, 147, 4, 147, 1291, 8, 147, 11, 147, 12, 147, - 1292, 1, 148, 4, 148, 1296, 8, 148, 11, 148, 12, - 148, 1297, 1, 148, 1, 148, 5, 148, 1302, 8, 148, - 10, 148, 12, 148, 1305, 9, 148, 1, 148, 1, 148, - 1, 148, 1, 148, 4, 148, 1311, 8, 148, 11, 148, - 12, 148, 1312, 1, 148, 1, 148, 1, 148, 4, 148, - 1318, 8, 148, 11, 148, 12, 148, 1319, 1, 148, 1, - 148, 3, 148, 1324, 8, 148, 1, 149, 1, 149, 1, - 149, 1, 150, 1, 150, 1, 150, 1, 151, 1, 151, - 1, 151, 1, 152, 1, 152, 1, 152, 1, 153, 1, - 153, 1, 153, 1, 154, 1, 154, 1, 154, 1, 155, - 1, 155, 3, 155, 1346, 8, 155, 1, 155, 4, 155, - 1349, 8, 155, 11, 155, 12, 155, 1350, 1, 156, 1, - 156, 1, 156, 5, 156, 1356, 8, 156, 10, 156, 12, - 156, 1359, 9, 156, 1, 156, 1, 156, 1, 157, 1, - 157, 1, 157, 5, 157, 1366, 8, 157, 10, 157, 12, - 157, 1369, 9, 157, 1, 157, 1, 157, 1, 158, 1, - 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, - 3, 158, 1380, 8, 158, 1, 158, 1, 158, 3, 158, - 1384, 8, 158, 5, 158, 1386, 8, 158, 10, 158, 12, - 158, 1389, 9, 158, 1, 158, 1, 158, 1, 158, 1, - 158, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, - 1, 159, 1, 159, 3, 159, 1402, 8, 159, 1, 159, - 1, 159, 3, 159, 1406, 8, 159, 5, 159, 1408, 8, - 159, 10, 159, 12, 159, 1411, 9, 159, 1, 159, 1, - 159, 1, 159, 1, 159, 1, 160, 1, 160, 1, 160, - 1, 161, 1, 161, 5, 161, 1422, 8, 161, 10, 161, - 12, 161, 1425, 9, 161, 1, 161, 1, 161, 1, 162, - 1, 162, 5, 162, 1431, 8, 162, 10, 162, 12, 162, - 1434, 9, 162, 1, 162, 1, 162, 1, 163, 1, 163, - 3, 163, 1440, 8, 163, 1, 164, 1, 164, 3, 164, - 1444, 8, 164, 1, 164, 1, 164, 1, 164, 5, 164, - 1449, 8, 164, 10, 164, 12, 164, 1452, 9, 164, 1, - 165, 1, 165, 1, 165, 1, 165, 3, 165, 1458, 8, - 165, 1, 166, 1, 166, 1, 166, 5, 166, 1463, 8, - 166, 10, 166, 12, 166, 1466, 9, 166, 1, 166, 3, - 166, 1469, 8, 166, 1, 167, 1, 167, 1, 167, 1, - 167, 3, 167, 1475, 8, 167, 1, 167, 1, 167, 1, - 167, 5, 167, 1480, 8, 167, 10, 167, 12, 167, 1483, - 9, 167, 1, 167, 1, 167, 1, 167, 3, 167, 1488, - 8, 167, 3, 167, 1490, 8, 167, 1, 168, 1, 168, - 3, 168, 1494, 8, 168, 1, 169, 1, 169, 1, 169, - 1, 169, 1, 170, 1, 170, 3, 170, 1502, 8, 170, - 1, 171, 1, 171, 1, 171, 1, 172, 1, 172, 1, - 173, 1, 173, 1, 174, 4, 174, 1512, 8, 174, 11, - 174, 12, 174, 1513, 1, 174, 1, 174, 1, 175, 1, - 175, 5, 175, 1520, 8, 175, 10, 175, 12, 175, 1523, - 9, 175, 1, 175, 1, 175, 1, 176, 1, 176, 1, - 177, 1, 177, 1, 178, 1, 178, 1, 179, 1, 179, - 1, 180, 1, 180, 1, 181, 1, 181, 1, 182, 1, - 182, 1, 183, 1, 183, 1, 184, 1, 184, 1, 185, - 1, 185, 1, 186, 1, 186, 1, 187, 1, 187, 1, - 188, 1, 188, 1, 189, 1, 189, 1, 190, 1, 190, - 1, 191, 1, 191, 1, 192, 1, 192, 1, 193, 1, - 193, 1, 194, 1, 194, 1, 195, 1, 195, 1, 196, - 1, 196, 1, 197, 1, 197, 1, 198, 1, 198, 1, - 199, 1, 199, 1, 200, 1, 200, 1, 201, 1, 201, - 0, 0, 202, 1, 1, 3, 2, 5, 3, 7, 4, - 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, - 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, - 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, - 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, - 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, - 32, 65, 33, 67, 34, 69, 35, 71, 36, 73, 37, - 75, 38, 77, 39, 79, 40, 81, 41, 83, 42, 85, - 43, 87, 44, 89, 45, 91, 46, 93, 47, 95, 48, - 97, 49, 99, 50, 101, 51, 103, 52, 105, 53, 107, - 54, 109, 55, 111, 56, 113, 57, 115, 58, 117, 59, - 119, 60, 121, 61, 123, 62, 125, 63, 127, 64, 129, - 65, 131, 66, 133, 67, 135, 68, 137, 69, 139, 70, - 141, 71, 143, 72, 145, 73, 147, 74, 149, 75, 151, - 76, 153, 77, 155, 78, 157, 79, 159, 80, 161, 81, - 163, 82, 165, 83, 167, 84, 169, 85, 171, 86, 173, - 87, 175, 88, 177, 89, 179, 90, 181, 91, 183, 92, - 185, 93, 187, 94, 189, 95, 191, 96, 193, 97, 195, - 98, 197, 99, 199, 100, 201, 101, 203, 102, 205, 103, - 207, 104, 209, 105, 211, 106, 213, 107, 215, 108, 217, - 109, 219, 110, 221, 111, 223, 112, 225, 113, 227, 114, - 229, 115, 231, 116, 233, 117, 235, 118, 237, 119, 239, - 120, 241, 121, 243, 122, 245, 123, 247, 124, 249, 125, - 251, 126, 253, 127, 255, 128, 257, 129, 259, 130, 261, - 131, 263, 132, 265, 133, 267, 134, 269, 135, 271, 136, - 273, 137, 275, 138, 277, 139, 279, 140, 281, 141, 283, - 142, 285, 143, 287, 144, 289, 145, 291, 146, 293, 147, - 295, 148, 297, 149, 299, 150, 301, 151, 303, 152, 305, - 153, 307, 154, 309, 155, 311, 156, 313, 157, 315, 158, - 317, 159, 319, 160, 321, 161, 323, 162, 325, 163, 327, - 164, 329, 165, 331, 0, 333, 166, 335, 167, 337, 168, - 339, 169, 341, 170, 343, 171, 345, 0, 347, 0, 349, - 172, 351, 173, 353, 0, 355, 0, 357, 0, 359, 0, - 361, 0, 363, 0, 365, 0, 367, 0, 369, 0, 371, - 0, 373, 0, 375, 0, 377, 0, 379, 0, 381, 0, - 383, 0, 385, 0, 387, 0, 389, 0, 391, 0, 393, - 0, 395, 0, 397, 0, 399, 0, 401, 0, 403, 0, - 1, 0, 41, 8, 0, 0, 32, 34, 34, 60, 60, - 62, 62, 92, 92, 94, 94, 96, 96, 123, 125, 2, - 0, 65, 90, 97, 122, 2, 0, 69, 69, 101, 101, - 2, 0, 43, 43, 45, 45, 4, 0, 10, 10, 13, - 13, 39, 39, 92, 92, 4, 0, 10, 10, 13, 13, - 34, 34, 92, 92, 2, 0, 39, 39, 92, 92, 2, - 0, 34, 34, 92, 92, 8, 0, 34, 34, 39, 39, - 92, 92, 98, 98, 102, 102, 110, 110, 114, 114, 116, - 116, 3, 0, 183, 183, 768, 879, 8255, 8256, 2, 0, - 46, 46, 58, 58, 2, 0, 65, 70, 97, 102, 7, - 0, 33, 33, 35, 47, 59, 59, 61, 61, 63, 64, - 95, 95, 126, 126, 13, 0, 65, 90, 97, 122, 192, - 214, 216, 246, 248, 767, 880, 893, 895, 8191, 8204, 8205, - 8304, 8591, 11264, 12271, 12289, 55295, 63744, 64975, 65008, 65533, 3, - 0, 9, 10, 13, 13, 32, 32, 2, 0, 10, 10, - 13, 13, 2, 0, 65, 65, 97, 97, 2, 0, 66, - 66, 98, 98, 2, 0, 67, 67, 99, 99, 2, 0, - 68, 68, 100, 100, 2, 0, 70, 70, 102, 102, 2, - 0, 71, 71, 103, 103, 2, 0, 72, 72, 104, 104, - 2, 0, 73, 73, 105, 105, 2, 0, 74, 74, 106, - 106, 2, 0, 75, 75, 107, 107, 2, 0, 76, 76, - 108, 108, 2, 0, 77, 77, 109, 109, 2, 0, 78, - 78, 110, 110, 2, 0, 79, 79, 111, 111, 2, 0, - 80, 80, 112, 112, 2, 0, 81, 81, 113, 113, 2, - 0, 82, 82, 114, 114, 2, 0, 83, 83, 115, 115, - 2, 0, 84, 84, 116, 116, 2, 0, 85, 85, 117, - 117, 2, 0, 86, 86, 118, 118, 2, 0, 87, 87, - 119, 119, 2, 0, 88, 88, 120, 120, 2, 0, 89, - 89, 121, 121, 2, 0, 90, 90, 122, 122, 1611, 0, - 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, - 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, - 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, - 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, - 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, - 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, - 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, - 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, - 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, - 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, - 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, - 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, - 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, - 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, - 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, - 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, - 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, - 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, - 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, - 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, - 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, - 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, - 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, - 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, - 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, - 0, 93, 1, 0, 0, 0, 0, 95, 1, 0, 0, - 0, 0, 97, 1, 0, 0, 0, 0, 99, 1, 0, - 0, 0, 0, 101, 1, 0, 0, 0, 0, 103, 1, - 0, 0, 0, 0, 105, 1, 0, 0, 0, 0, 107, - 1, 0, 0, 0, 0, 109, 1, 0, 0, 0, 0, - 111, 1, 0, 0, 0, 0, 113, 1, 0, 0, 0, - 0, 115, 1, 0, 0, 0, 0, 117, 1, 0, 0, - 0, 0, 119, 1, 0, 0, 0, 0, 121, 1, 0, - 0, 0, 0, 123, 1, 0, 0, 0, 0, 125, 1, - 0, 0, 0, 0, 127, 1, 0, 0, 0, 0, 129, - 1, 0, 0, 0, 0, 131, 1, 0, 0, 0, 0, - 133, 1, 0, 0, 0, 0, 135, 1, 0, 0, 0, - 0, 137, 1, 0, 0, 0, 0, 139, 1, 0, 0, - 0, 0, 141, 1, 0, 0, 0, 0, 143, 1, 0, - 0, 0, 0, 145, 1, 0, 0, 0, 0, 147, 1, - 0, 0, 0, 0, 149, 1, 0, 0, 0, 0, 151, - 1, 0, 0, 0, 0, 153, 1, 0, 0, 0, 0, - 155, 1, 0, 0, 0, 0, 157, 1, 0, 0, 0, - 0, 159, 1, 0, 0, 0, 0, 161, 1, 0, 0, - 0, 0, 163, 1, 0, 0, 0, 0, 165, 1, 0, - 0, 0, 0, 167, 1, 0, 0, 0, 0, 169, 1, - 0, 0, 0, 0, 171, 1, 0, 0, 0, 0, 173, - 1, 0, 0, 0, 0, 175, 1, 0, 0, 0, 0, - 177, 1, 0, 0, 0, 0, 179, 1, 0, 0, 0, - 0, 181, 1, 0, 0, 0, 0, 183, 1, 0, 0, - 0, 0, 185, 1, 0, 0, 0, 0, 187, 1, 0, - 0, 0, 0, 189, 1, 0, 0, 0, 0, 191, 1, - 0, 0, 0, 0, 193, 1, 0, 0, 0, 0, 195, - 1, 0, 0, 0, 0, 197, 1, 0, 0, 0, 0, - 199, 1, 0, 0, 0, 0, 201, 1, 0, 0, 0, - 0, 203, 1, 0, 0, 0, 0, 205, 1, 0, 0, - 0, 0, 207, 1, 0, 0, 0, 0, 209, 1, 0, - 0, 0, 0, 211, 1, 0, 0, 0, 0, 213, 1, - 0, 0, 0, 0, 215, 1, 0, 0, 0, 0, 217, - 1, 0, 0, 0, 0, 219, 1, 0, 0, 0, 0, - 221, 1, 0, 0, 0, 0, 223, 1, 0, 0, 0, - 0, 225, 1, 0, 0, 0, 0, 227, 1, 0, 0, - 0, 0, 229, 1, 0, 0, 0, 0, 231, 1, 0, - 0, 0, 0, 233, 1, 0, 0, 0, 0, 235, 1, - 0, 0, 0, 0, 237, 1, 0, 0, 0, 0, 239, - 1, 0, 0, 0, 0, 241, 1, 0, 0, 0, 0, - 243, 1, 0, 0, 0, 0, 245, 1, 0, 0, 0, - 0, 247, 1, 0, 0, 0, 0, 249, 1, 0, 0, - 0, 0, 251, 1, 0, 0, 0, 0, 253, 1, 0, - 0, 0, 0, 255, 1, 0, 0, 0, 0, 257, 1, - 0, 0, 0, 0, 259, 1, 0, 0, 0, 0, 261, - 1, 0, 0, 0, 0, 263, 1, 0, 0, 0, 0, - 265, 1, 0, 0, 0, 0, 267, 1, 0, 0, 0, - 0, 269, 1, 0, 0, 0, 0, 271, 1, 0, 0, - 0, 0, 273, 1, 0, 0, 0, 0, 275, 1, 0, - 0, 0, 0, 277, 1, 0, 0, 0, 0, 279, 1, - 0, 0, 0, 0, 281, 1, 0, 0, 0, 0, 283, - 1, 0, 0, 0, 0, 285, 1, 0, 0, 0, 0, - 287, 1, 0, 0, 0, 0, 289, 1, 0, 0, 0, - 0, 291, 1, 0, 0, 0, 0, 293, 1, 0, 0, - 0, 0, 295, 1, 0, 0, 0, 0, 297, 1, 0, - 0, 0, 0, 299, 1, 0, 0, 0, 0, 301, 1, - 0, 0, 0, 0, 303, 1, 0, 0, 0, 0, 305, - 1, 0, 0, 0, 0, 307, 1, 0, 0, 0, 0, - 309, 1, 0, 0, 0, 0, 311, 1, 0, 0, 0, - 0, 313, 1, 0, 0, 0, 0, 315, 1, 0, 0, - 0, 0, 317, 1, 0, 0, 0, 0, 319, 1, 0, - 0, 0, 0, 321, 1, 0, 0, 0, 0, 323, 1, - 0, 0, 0, 0, 325, 1, 0, 0, 0, 0, 327, - 1, 0, 0, 0, 0, 329, 1, 0, 0, 0, 0, - 333, 1, 0, 0, 0, 0, 335, 1, 0, 0, 0, - 0, 337, 1, 0, 0, 0, 0, 339, 1, 0, 0, - 0, 0, 341, 1, 0, 0, 0, 0, 343, 1, 0, - 0, 0, 0, 349, 1, 0, 0, 0, 0, 351, 1, - 0, 0, 0, 1, 405, 1, 0, 0, 0, 3, 407, - 1, 0, 0, 0, 5, 409, 1, 0, 0, 0, 7, - 411, 1, 0, 0, 0, 9, 413, 1, 0, 0, 0, - 11, 415, 1, 0, 0, 0, 13, 417, 1, 0, 0, - 0, 15, 419, 1, 0, 0, 0, 17, 421, 1, 0, - 0, 0, 19, 423, 1, 0, 0, 0, 21, 425, 1, - 0, 0, 0, 23, 427, 1, 0, 0, 0, 25, 429, - 1, 0, 0, 0, 27, 431, 1, 0, 0, 0, 29, - 433, 1, 0, 0, 0, 31, 435, 1, 0, 0, 0, - 33, 437, 1, 0, 0, 0, 35, 439, 1, 0, 0, - 0, 37, 442, 1, 0, 0, 0, 39, 445, 1, 0, - 0, 0, 41, 447, 1, 0, 0, 0, 43, 450, 1, - 0, 0, 0, 45, 452, 1, 0, 0, 0, 47, 454, - 1, 0, 0, 0, 49, 457, 1, 0, 0, 0, 51, - 460, 1, 0, 0, 0, 53, 462, 1, 0, 0, 0, - 55, 465, 1, 0, 0, 0, 57, 470, 1, 0, 0, - 0, 59, 476, 1, 0, 0, 0, 61, 481, 1, 0, - 0, 0, 63, 488, 1, 0, 0, 0, 65, 495, 1, - 0, 0, 0, 67, 504, 1, 0, 0, 0, 69, 512, - 1, 0, 0, 0, 71, 515, 1, 0, 0, 0, 73, - 525, 1, 0, 0, 0, 75, 531, 1, 0, 0, 0, - 77, 540, 1, 0, 0, 0, 79, 544, 1, 0, 0, - 0, 81, 549, 1, 0, 0, 0, 83, 555, 1, 0, - 0, 0, 85, 568, 1, 0, 0, 0, 87, 581, 1, - 0, 0, 0, 89, 588, 1, 0, 0, 0, 91, 601, - 1, 0, 0, 0, 93, 626, 1, 0, 0, 0, 95, - 630, 1, 0, 0, 0, 97, 635, 1, 0, 0, 0, - 99, 641, 1, 0, 0, 0, 101, 648, 1, 0, 0, - 0, 103, 658, 1, 0, 0, 0, 105, 665, 1, 0, - 0, 0, 107, 670, 1, 0, 0, 0, 109, 677, 1, - 0, 0, 0, 111, 683, 1, 0, 0, 0, 113, 688, - 1, 0, 0, 0, 115, 695, 1, 0, 0, 0, 117, - 699, 1, 0, 0, 0, 119, 704, 1, 0, 0, 0, - 121, 709, 1, 0, 0, 0, 123, 714, 1, 0, 0, - 0, 125, 721, 1, 0, 0, 0, 127, 728, 1, 0, - 0, 0, 129, 733, 1, 0, 0, 0, 131, 739, 1, - 0, 0, 0, 133, 747, 1, 0, 0, 0, 135, 753, - 1, 0, 0, 0, 137, 757, 1, 0, 0, 0, 139, - 766, 1, 0, 0, 0, 141, 774, 1, 0, 0, 0, - 143, 779, 1, 0, 0, 0, 145, 785, 1, 0, 0, - 0, 147, 791, 1, 0, 0, 0, 149, 797, 1, 0, - 0, 0, 151, 804, 1, 0, 0, 0, 153, 808, 1, - 0, 0, 0, 155, 811, 1, 0, 0, 0, 157, 815, - 1, 0, 0, 0, 159, 820, 1, 0, 0, 0, 161, - 832, 1, 0, 0, 0, 163, 841, 1, 0, 0, 0, - 165, 847, 1, 0, 0, 0, 167, 851, 1, 0, 0, - 0, 169, 855, 1, 0, 0, 0, 171, 861, 1, 0, - 0, 0, 173, 866, 1, 0, 0, 0, 175, 870, 1, - 0, 0, 0, 177, 875, 1, 0, 0, 0, 179, 881, - 1, 0, 0, 0, 181, 887, 1, 0, 0, 0, 183, - 894, 1, 0, 0, 0, 185, 901, 1, 0, 0, 0, - 187, 907, 1, 0, 0, 0, 189, 913, 1, 0, 0, - 0, 191, 928, 1, 0, 0, 0, 193, 932, 1, 0, - 0, 0, 195, 941, 1, 0, 0, 0, 197, 951, 1, - 0, 0, 0, 199, 959, 1, 0, 0, 0, 201, 969, - 1, 0, 0, 0, 203, 978, 1, 0, 0, 0, 205, - 983, 1, 0, 0, 0, 207, 989, 1, 0, 0, 0, - 209, 993, 1, 0, 0, 0, 211, 999, 1, 0, 0, - 0, 213, 1007, 1, 0, 0, 0, 215, 1015, 1, 0, - 0, 0, 217, 1024, 1, 0, 0, 0, 219, 1027, 1, - 0, 0, 0, 221, 1031, 1, 0, 0, 0, 223, 1036, - 1, 0, 0, 0, 225, 1044, 1, 0, 0, 0, 227, - 1049, 1, 0, 0, 0, 229, 1056, 1, 0, 0, 0, - 231, 1063, 1, 0, 0, 0, 233, 1070, 1, 0, 0, - 0, 235, 1074, 1, 0, 0, 0, 237, 1083, 1, 0, - 0, 0, 239, 1086, 1, 0, 0, 0, 241, 1094, 1, - 0, 0, 0, 243, 1100, 1, 0, 0, 0, 245, 1109, - 1, 0, 0, 0, 247, 1115, 1, 0, 0, 0, 249, - 1121, 1, 0, 0, 0, 251, 1129, 1, 0, 0, 0, - 253, 1139, 1, 0, 0, 0, 255, 1149, 1, 0, 0, - 0, 257, 1155, 1, 0, 0, 0, 259, 1162, 1, 0, - 0, 0, 261, 1170, 1, 0, 0, 0, 263, 1177, 1, - 0, 0, 0, 265, 1183, 1, 0, 0, 0, 267, 1187, - 1, 0, 0, 0, 269, 1191, 1, 0, 0, 0, 271, - 1195, 1, 0, 0, 0, 273, 1199, 1, 0, 0, 0, - 275, 1206, 1, 0, 0, 0, 277, 1216, 1, 0, 0, - 0, 279, 1226, 1, 0, 0, 0, 281, 1230, 1, 0, - 0, 0, 283, 1233, 1, 0, 0, 0, 285, 1250, 1, - 0, 0, 0, 287, 1253, 1, 0, 0, 0, 289, 1256, - 1, 0, 0, 0, 291, 1274, 1, 0, 0, 0, 293, - 1278, 1, 0, 0, 0, 295, 1285, 1, 0, 0, 0, - 297, 1323, 1, 0, 0, 0, 299, 1325, 1, 0, 0, - 0, 301, 1328, 1, 0, 0, 0, 303, 1331, 1, 0, - 0, 0, 305, 1334, 1, 0, 0, 0, 307, 1337, 1, - 0, 0, 0, 309, 1340, 1, 0, 0, 0, 311, 1343, - 1, 0, 0, 0, 313, 1352, 1, 0, 0, 0, 315, - 1362, 1, 0, 0, 0, 317, 1372, 1, 0, 0, 0, - 319, 1394, 1, 0, 0, 0, 321, 1416, 1, 0, 0, - 0, 323, 1419, 1, 0, 0, 0, 325, 1428, 1, 0, - 0, 0, 327, 1439, 1, 0, 0, 0, 329, 1443, 1, - 0, 0, 0, 331, 1457, 1, 0, 0, 0, 333, 1459, - 1, 0, 0, 0, 335, 1474, 1, 0, 0, 0, 337, - 1493, 1, 0, 0, 0, 339, 1495, 1, 0, 0, 0, - 341, 1501, 1, 0, 0, 0, 343, 1503, 1, 0, 0, - 0, 345, 1506, 1, 0, 0, 0, 347, 1508, 1, 0, - 0, 0, 349, 1511, 1, 0, 0, 0, 351, 1517, 1, - 0, 0, 0, 353, 1526, 1, 0, 0, 0, 355, 1528, - 1, 0, 0, 0, 357, 1530, 1, 0, 0, 0, 359, - 1532, 1, 0, 0, 0, 361, 1534, 1, 0, 0, 0, - 363, 1536, 1, 0, 0, 0, 365, 1538, 1, 0, 0, - 0, 367, 1540, 1, 0, 0, 0, 369, 1542, 1, 0, - 0, 0, 371, 1544, 1, 0, 0, 0, 373, 1546, 1, - 0, 0, 0, 375, 1548, 1, 0, 0, 0, 377, 1550, - 1, 0, 0, 0, 379, 1552, 1, 0, 0, 0, 381, - 1554, 1, 0, 0, 0, 383, 1556, 1, 0, 0, 0, - 385, 1558, 1, 0, 0, 0, 387, 1560, 1, 0, 0, - 0, 389, 1562, 1, 0, 0, 0, 391, 1564, 1, 0, - 0, 0, 393, 1566, 1, 0, 0, 0, 395, 1568, 1, - 0, 0, 0, 397, 1570, 1, 0, 0, 0, 399, 1572, - 1, 0, 0, 0, 401, 1574, 1, 0, 0, 0, 403, - 1576, 1, 0, 0, 0, 405, 406, 5, 42, 0, 0, - 406, 2, 1, 0, 0, 0, 407, 408, 5, 40, 0, - 0, 408, 4, 1, 0, 0, 0, 409, 410, 5, 41, - 0, 0, 410, 6, 1, 0, 0, 0, 411, 412, 5, - 123, 0, 0, 412, 8, 1, 0, 0, 0, 413, 414, - 5, 125, 0, 0, 414, 10, 1, 0, 0, 0, 415, - 416, 5, 46, 0, 0, 416, 12, 1, 0, 0, 0, - 417, 418, 5, 44, 0, 0, 418, 14, 1, 0, 0, - 0, 419, 420, 5, 59, 0, 0, 420, 16, 1, 0, - 0, 0, 421, 422, 5, 97, 0, 0, 422, 18, 1, - 0, 0, 0, 423, 424, 5, 124, 0, 0, 424, 20, - 1, 0, 0, 0, 425, 426, 5, 47, 0, 0, 426, - 22, 1, 0, 0, 0, 427, 428, 5, 94, 0, 0, - 428, 24, 1, 0, 0, 0, 429, 430, 5, 43, 0, - 0, 430, 26, 1, 0, 0, 0, 431, 432, 5, 63, - 0, 0, 432, 28, 1, 0, 0, 0, 433, 434, 5, - 33, 0, 0, 434, 30, 1, 0, 0, 0, 435, 436, - 5, 91, 0, 0, 436, 32, 1, 0, 0, 0, 437, - 438, 5, 93, 0, 0, 438, 34, 1, 0, 0, 0, - 439, 440, 5, 124, 0, 0, 440, 441, 5, 124, 0, - 0, 441, 36, 1, 0, 0, 0, 442, 443, 5, 38, - 0, 0, 443, 444, 5, 38, 0, 0, 444, 38, 1, - 0, 0, 0, 445, 446, 5, 61, 0, 0, 446, 40, - 1, 0, 0, 0, 447, 448, 5, 33, 0, 0, 448, - 449, 5, 61, 0, 0, 449, 42, 1, 0, 0, 0, - 450, 451, 5, 60, 0, 0, 451, 44, 1, 0, 0, - 0, 452, 453, 5, 62, 0, 0, 453, 46, 1, 0, - 0, 0, 454, 455, 5, 60, 0, 0, 455, 456, 5, - 61, 0, 0, 456, 48, 1, 0, 0, 0, 457, 458, - 5, 62, 0, 0, 458, 459, 5, 61, 0, 0, 459, - 50, 1, 0, 0, 0, 460, 461, 5, 45, 0, 0, - 461, 52, 1, 0, 0, 0, 462, 463, 5, 94, 0, - 0, 463, 464, 5, 94, 0, 0, 464, 54, 1, 0, - 0, 0, 465, 466, 5, 116, 0, 0, 466, 467, 5, - 114, 0, 0, 467, 468, 5, 117, 0, 0, 468, 469, - 5, 101, 0, 0, 469, 56, 1, 0, 0, 0, 470, - 471, 5, 102, 0, 0, 471, 472, 5, 97, 0, 0, - 472, 473, 5, 108, 0, 0, 473, 474, 5, 115, 0, - 0, 474, 475, 5, 101, 0, 0, 475, 58, 1, 0, - 0, 0, 476, 477, 3, 355, 177, 0, 477, 478, 3, - 353, 176, 0, 478, 479, 3, 389, 194, 0, 479, 480, - 3, 361, 180, 0, 480, 60, 1, 0, 0, 0, 481, - 482, 3, 383, 191, 0, 482, 483, 3, 387, 193, 0, - 483, 484, 3, 361, 180, 0, 484, 485, 3, 363, 181, - 0, 485, 486, 3, 369, 184, 0, 486, 487, 3, 399, - 199, 0, 487, 62, 1, 0, 0, 0, 488, 489, 3, - 389, 194, 0, 489, 490, 3, 361, 180, 0, 490, 491, - 3, 375, 187, 0, 491, 492, 3, 361, 180, 0, 492, - 493, 3, 357, 178, 0, 493, 494, 3, 391, 195, 0, - 494, 64, 1, 0, 0, 0, 495, 496, 3, 359, 179, - 0, 496, 497, 3, 369, 184, 0, 497, 498, 3, 389, - 194, 0, 498, 499, 3, 391, 195, 0, 499, 500, 3, - 369, 184, 0, 500, 501, 3, 379, 189, 0, 501, 502, - 3, 357, 178, 0, 502, 503, 3, 391, 195, 0, 503, - 66, 1, 0, 0, 0, 504, 505, 3, 387, 193, 0, - 505, 506, 3, 361, 180, 0, 506, 507, 3, 359, 179, - 0, 507, 508, 3, 393, 196, 0, 508, 509, 3, 357, - 178, 0, 509, 510, 3, 361, 180, 0, 510, 511, 3, - 359, 179, 0, 511, 68, 1, 0, 0, 0, 512, 513, - 3, 353, 176, 0, 513, 514, 3, 389, 194, 0, 514, - 70, 1, 0, 0, 0, 515, 516, 3, 357, 178, 0, - 516, 517, 3, 381, 190, 0, 517, 518, 3, 379, 189, - 0, 518, 519, 3, 389, 194, 0, 519, 520, 3, 391, - 195, 0, 520, 521, 3, 387, 193, 0, 521, 522, 3, - 393, 196, 0, 522, 523, 3, 357, 178, 0, 523, 524, - 3, 391, 195, 0, 524, 72, 1, 0, 0, 0, 525, - 526, 3, 397, 198, 0, 526, 527, 3, 367, 183, 0, - 527, 528, 3, 361, 180, 0, 528, 529, 3, 387, 193, - 0, 529, 530, 3, 361, 180, 0, 530, 74, 1, 0, - 0, 0, 531, 532, 3, 359, 179, 0, 532, 533, 3, - 361, 180, 0, 533, 534, 3, 389, 194, 0, 534, 535, - 3, 357, 178, 0, 535, 536, 3, 387, 193, 0, 536, - 537, 3, 369, 184, 0, 537, 538, 3, 355, 177, 0, - 538, 539, 3, 361, 180, 0, 539, 76, 1, 0, 0, - 0, 540, 541, 3, 353, 176, 0, 541, 542, 3, 389, - 194, 0, 542, 543, 3, 373, 186, 0, 543, 78, 1, - 0, 0, 0, 544, 545, 3, 363, 181, 0, 545, 546, - 3, 387, 193, 0, 546, 547, 3, 381, 190, 0, 547, - 548, 3, 377, 188, 0, 548, 80, 1, 0, 0, 0, - 549, 550, 3, 379, 189, 0, 550, 551, 3, 353, 176, - 0, 551, 552, 3, 377, 188, 0, 552, 553, 3, 361, - 180, 0, 553, 554, 3, 359, 179, 0, 554, 82, 1, - 0, 0, 0, 555, 556, 3, 365, 182, 0, 556, 557, - 3, 387, 193, 0, 557, 558, 3, 381, 190, 0, 558, - 559, 3, 393, 196, 0, 559, 561, 3, 383, 191, 0, - 560, 562, 3, 349, 174, 0, 561, 560, 1, 0, 0, - 0, 562, 563, 1, 0, 0, 0, 563, 561, 1, 0, - 0, 0, 563, 564, 1, 0, 0, 0, 564, 565, 1, - 0, 0, 0, 565, 566, 3, 355, 177, 0, 566, 567, - 3, 401, 200, 0, 567, 84, 1, 0, 0, 0, 568, - 569, 3, 365, 182, 0, 569, 570, 3, 387, 193, 0, - 570, 571, 3, 381, 190, 0, 571, 572, 3, 393, 196, - 0, 572, 573, 3, 383, 191, 0, 573, 574, 5, 95, - 0, 0, 574, 575, 3, 357, 178, 0, 575, 576, 3, - 381, 190, 0, 576, 577, 3, 379, 189, 0, 577, 578, - 3, 357, 178, 0, 578, 579, 3, 353, 176, 0, 579, - 580, 3, 391, 195, 0, 580, 86, 1, 0, 0, 0, - 581, 582, 3, 367, 183, 0, 582, 583, 3, 353, 176, - 0, 583, 584, 3, 395, 197, 0, 584, 585, 3, 369, - 184, 0, 585, 586, 3, 379, 189, 0, 586, 587, 3, - 365, 182, 0, 587, 88, 1, 0, 0, 0, 588, 589, - 3, 381, 190, 0, 589, 590, 3, 387, 193, 0, 590, - 591, 3, 359, 179, 0, 591, 592, 3, 361, 180, 0, - 592, 594, 3, 387, 193, 0, 593, 595, 3, 349, 174, - 0, 594, 593, 1, 0, 0, 0, 595, 596, 1, 0, - 0, 0, 596, 594, 1, 0, 0, 0, 596, 597, 1, - 0, 0, 0, 597, 598, 1, 0, 0, 0, 598, 599, - 3, 355, 177, 0, 599, 600, 3, 401, 200, 0, 600, - 90, 1, 0, 0, 0, 601, 602, 3, 369, 184, 0, - 602, 603, 3, 379, 189, 0, 603, 604, 3, 391, 195, - 0, 604, 605, 3, 361, 180, 0, 605, 606, 3, 387, - 193, 0, 606, 607, 3, 379, 189, 0, 607, 608, 3, - 353, 176, 0, 608, 610, 3, 375, 187, 0, 609, 611, - 3, 349, 174, 0, 610, 609, 1, 0, 0, 0, 611, - 612, 1, 0, 0, 0, 612, 610, 1, 0, 0, 0, - 612, 613, 1, 0, 0, 0, 613, 614, 1, 0, 0, - 0, 614, 615, 3, 389, 194, 0, 615, 616, 3, 381, - 190, 0, 616, 617, 3, 387, 193, 0, 617, 619, 3, - 391, 195, 0, 618, 620, 3, 349, 174, 0, 619, 618, - 1, 0, 0, 0, 620, 621, 1, 0, 0, 0, 621, - 619, 1, 0, 0, 0, 621, 622, 1, 0, 0, 0, - 622, 623, 1, 0, 0, 0, 623, 624, 3, 355, 177, - 0, 624, 625, 3, 401, 200, 0, 625, 92, 1, 0, - 0, 0, 626, 627, 3, 353, 176, 0, 627, 628, 3, - 389, 194, 0, 628, 629, 3, 357, 178, 0, 629, 94, - 1, 0, 0, 0, 630, 631, 3, 359, 179, 0, 631, - 632, 3, 361, 180, 0, 632, 633, 3, 389, 194, 0, - 633, 634, 3, 357, 178, 0, 634, 96, 1, 0, 0, - 0, 635, 636, 3, 375, 187, 0, 636, 637, 3, 369, - 184, 0, 637, 638, 3, 377, 188, 0, 638, 639, 3, - 369, 184, 0, 639, 640, 3, 391, 195, 0, 640, 98, - 1, 0, 0, 0, 641, 642, 3, 381, 190, 0, 642, - 643, 3, 363, 181, 0, 643, 644, 3, 363, 181, 0, - 644, 645, 3, 389, 194, 0, 645, 646, 3, 361, 180, - 0, 646, 647, 3, 391, 195, 0, 647, 100, 1, 0, - 0, 0, 648, 649, 3, 391, 195, 0, 649, 650, 3, - 361, 180, 0, 650, 651, 3, 399, 199, 0, 651, 652, - 3, 391, 195, 0, 652, 653, 3, 375, 187, 0, 653, - 654, 3, 369, 184, 0, 654, 655, 3, 377, 188, 0, - 655, 656, 3, 369, 184, 0, 656, 657, 3, 391, 195, - 0, 657, 102, 1, 0, 0, 0, 658, 659, 3, 395, - 197, 0, 659, 660, 3, 353, 176, 0, 660, 661, 3, - 375, 187, 0, 661, 662, 3, 393, 196, 0, 662, 663, - 3, 361, 180, 0, 663, 664, 3, 389, 194, 0, 664, - 104, 1, 0, 0, 0, 665, 666, 3, 375, 187, 0, - 666, 667, 3, 381, 190, 0, 667, 668, 3, 353, 176, - 0, 668, 669, 3, 359, 179, 0, 669, 106, 1, 0, - 0, 0, 670, 671, 3, 389, 194, 0, 671, 672, 3, - 369, 184, 0, 672, 673, 3, 375, 187, 0, 673, 674, - 3, 361, 180, 0, 674, 675, 3, 379, 189, 0, 675, - 676, 3, 391, 195, 0, 676, 108, 1, 0, 0, 0, - 677, 678, 3, 357, 178, 0, 678, 679, 3, 375, 187, - 0, 679, 680, 3, 361, 180, 0, 680, 681, 3, 353, - 176, 0, 681, 682, 3, 387, 193, 0, 682, 110, 1, - 0, 0, 0, 683, 684, 3, 359, 179, 0, 684, 685, - 3, 387, 193, 0, 685, 686, 3, 381, 190, 0, 686, - 687, 3, 383, 191, 0, 687, 112, 1, 0, 0, 0, - 688, 689, 3, 357, 178, 0, 689, 690, 3, 387, 193, - 0, 690, 691, 3, 361, 180, 0, 691, 692, 3, 353, - 176, 0, 692, 693, 3, 391, 195, 0, 693, 694, 3, - 361, 180, 0, 694, 114, 1, 0, 0, 0, 695, 696, - 3, 353, 176, 0, 696, 697, 3, 359, 179, 0, 697, - 698, 3, 359, 179, 0, 698, 116, 1, 0, 0, 0, - 699, 700, 3, 359, 179, 0, 700, 701, 3, 353, 176, - 0, 701, 702, 3, 391, 195, 0, 702, 703, 3, 353, - 176, 0, 703, 118, 1, 0, 0, 0, 704, 705, 3, - 377, 188, 0, 705, 706, 3, 381, 190, 0, 706, 707, - 3, 395, 197, 0, 707, 708, 3, 361, 180, 0, 708, - 120, 1, 0, 0, 0, 709, 710, 3, 357, 178, 0, - 710, 711, 3, 381, 190, 0, 711, 712, 3, 383, 191, - 0, 712, 713, 3, 401, 200, 0, 713, 122, 1, 0, - 0, 0, 714, 715, 3, 369, 184, 0, 715, 716, 3, - 379, 189, 0, 716, 717, 3, 389, 194, 0, 717, 718, - 3, 361, 180, 0, 718, 719, 3, 387, 193, 0, 719, - 720, 3, 391, 195, 0, 720, 124, 1, 0, 0, 0, - 721, 722, 3, 359, 179, 0, 722, 723, 3, 361, 180, - 0, 723, 724, 3, 375, 187, 0, 724, 725, 3, 361, - 180, 0, 725, 726, 3, 391, 195, 0, 726, 727, 3, - 361, 180, 0, 727, 126, 1, 0, 0, 0, 728, 729, - 3, 397, 198, 0, 729, 730, 3, 369, 184, 0, 730, - 731, 3, 391, 195, 0, 731, 732, 3, 367, 183, 0, - 732, 128, 1, 0, 0, 0, 733, 734, 3, 393, 196, - 0, 734, 735, 3, 389, 194, 0, 735, 736, 3, 369, - 184, 0, 736, 737, 3, 379, 189, 0, 737, 738, 3, - 365, 182, 0, 738, 130, 1, 0, 0, 0, 739, 740, - 3, 359, 179, 0, 740, 741, 3, 361, 180, 0, 741, - 742, 3, 363, 181, 0, 742, 743, 3, 353, 176, 0, - 743, 744, 3, 393, 196, 0, 744, 745, 3, 375, 187, - 0, 745, 746, 3, 391, 195, 0, 746, 132, 1, 0, - 0, 0, 747, 748, 3, 365, 182, 0, 748, 749, 3, - 387, 193, 0, 749, 750, 3, 353, 176, 0, 750, 751, - 3, 383, 191, 0, 751, 752, 3, 367, 183, 0, 752, - 134, 1, 0, 0, 0, 753, 754, 3, 353, 176, 0, - 754, 755, 3, 375, 187, 0, 755, 756, 3, 375, 187, - 0, 756, 136, 1, 0, 0, 0, 757, 758, 3, 381, - 190, 0, 758, 759, 3, 383, 191, 0, 759, 760, 3, - 391, 195, 0, 760, 761, 3, 369, 184, 0, 761, 762, - 3, 381, 190, 0, 762, 763, 3, 379, 189, 0, 763, - 764, 3, 353, 176, 0, 764, 765, 3, 375, 187, 0, - 765, 138, 1, 0, 0, 0, 766, 767, 3, 389, 194, - 0, 767, 768, 3, 361, 180, 0, 768, 769, 3, 387, - 193, 0, 769, 770, 3, 395, 197, 0, 770, 771, 3, - 369, 184, 0, 771, 772, 3, 357, 178, 0, 772, 773, - 3, 361, 180, 0, 773, 140, 1, 0, 0, 0, 774, - 775, 3, 355, 177, 0, 775, 776, 3, 369, 184, 0, - 776, 777, 3, 379, 189, 0, 777, 778, 3, 359, 179, - 0, 778, 142, 1, 0, 0, 0, 779, 780, 3, 393, - 196, 0, 780, 781, 3, 379, 189, 0, 781, 782, 3, - 359, 179, 0, 782, 783, 3, 361, 180, 0, 783, 784, - 3, 363, 181, 0, 784, 144, 1, 0, 0, 0, 785, - 786, 3, 377, 188, 0, 786, 787, 3, 369, 184, 0, - 787, 788, 3, 379, 189, 0, 788, 789, 3, 393, 196, - 0, 789, 790, 3, 389, 194, 0, 790, 146, 1, 0, - 0, 0, 791, 792, 3, 393, 196, 0, 792, 793, 3, - 379, 189, 0, 793, 794, 3, 369, 184, 0, 794, 795, - 3, 381, 190, 0, 795, 796, 3, 379, 189, 0, 796, - 148, 1, 0, 0, 0, 797, 798, 3, 363, 181, 0, - 798, 799, 3, 369, 184, 0, 799, 800, 3, 375, 187, - 0, 800, 801, 3, 391, 195, 0, 801, 802, 3, 361, - 180, 0, 802, 803, 3, 387, 193, 0, 803, 150, 1, - 0, 0, 0, 804, 805, 3, 379, 189, 0, 805, 806, - 3, 381, 190, 0, 806, 807, 3, 391, 195, 0, 807, - 152, 1, 0, 0, 0, 808, 809, 3, 369, 184, 0, - 809, 810, 3, 379, 189, 0, 810, 154, 1, 0, 0, - 0, 811, 812, 3, 389, 194, 0, 812, 813, 3, 391, - 195, 0, 813, 814, 3, 387, 193, 0, 814, 156, 1, - 0, 0, 0, 815, 816, 3, 375, 187, 0, 816, 817, - 3, 353, 176, 0, 817, 818, 3, 379, 189, 0, 818, - 819, 3, 365, 182, 0, 819, 158, 1, 0, 0, 0, - 820, 821, 3, 375, 187, 0, 821, 822, 3, 353, 176, - 0, 822, 823, 3, 379, 189, 0, 823, 824, 3, 365, - 182, 0, 824, 825, 3, 377, 188, 0, 825, 826, 3, - 353, 176, 0, 826, 827, 3, 391, 195, 0, 827, 828, - 3, 357, 178, 0, 828, 829, 3, 367, 183, 0, 829, - 830, 3, 361, 180, 0, 830, 831, 3, 389, 194, 0, - 831, 160, 1, 0, 0, 0, 832, 833, 3, 359, 179, - 0, 833, 834, 3, 353, 176, 0, 834, 835, 3, 391, - 195, 0, 835, 836, 3, 353, 176, 0, 836, 837, 3, - 391, 195, 0, 837, 838, 3, 401, 200, 0, 838, 839, - 3, 383, 191, 0, 839, 840, 3, 361, 180, 0, 840, - 162, 1, 0, 0, 0, 841, 842, 3, 355, 177, 0, - 842, 843, 3, 381, 190, 0, 843, 844, 3, 393, 196, - 0, 844, 845, 3, 379, 189, 0, 845, 846, 3, 359, - 179, 0, 846, 164, 1, 0, 0, 0, 847, 848, 3, - 369, 184, 0, 848, 849, 3, 387, 193, 0, 849, 850, - 3, 369, 184, 0, 850, 166, 1, 0, 0, 0, 851, - 852, 3, 393, 196, 0, 852, 853, 3, 387, 193, 0, - 853, 854, 3, 369, 184, 0, 854, 168, 1, 0, 0, - 0, 855, 856, 3, 355, 177, 0, 856, 857, 3, 379, - 189, 0, 857, 858, 3, 381, 190, 0, 858, 859, 3, - 359, 179, 0, 859, 860, 3, 361, 180, 0, 860, 170, - 1, 0, 0, 0, 861, 862, 3, 387, 193, 0, 862, - 863, 3, 353, 176, 0, 863, 864, 3, 379, 189, 0, - 864, 865, 3, 359, 179, 0, 865, 172, 1, 0, 0, - 0, 866, 867, 3, 353, 176, 0, 867, 868, 3, 355, - 177, 0, 868, 869, 3, 389, 194, 0, 869, 174, 1, - 0, 0, 0, 870, 871, 3, 357, 178, 0, 871, 872, - 3, 361, 180, 0, 872, 873, 3, 369, 184, 0, 873, - 874, 3, 375, 187, 0, 874, 176, 1, 0, 0, 0, - 875, 876, 3, 363, 181, 0, 876, 877, 3, 375, 187, - 0, 877, 878, 3, 381, 190, 0, 878, 879, 3, 381, - 190, 0, 879, 880, 3, 387, 193, 0, 880, 178, 1, - 0, 0, 0, 881, 882, 3, 387, 193, 0, 882, 883, - 3, 381, 190, 0, 883, 884, 3, 393, 196, 0, 884, - 885, 3, 379, 189, 0, 885, 886, 3, 359, 179, 0, - 886, 180, 1, 0, 0, 0, 887, 888, 3, 357, 178, - 0, 888, 889, 3, 381, 190, 0, 889, 890, 3, 379, - 189, 0, 890, 891, 3, 357, 178, 0, 891, 892, 3, - 353, 176, 0, 892, 893, 3, 391, 195, 0, 893, 182, - 1, 0, 0, 0, 894, 895, 3, 389, 194, 0, 895, - 896, 3, 391, 195, 0, 896, 897, 3, 387, 193, 0, - 897, 898, 3, 375, 187, 0, 898, 899, 3, 361, 180, - 0, 899, 900, 3, 379, 189, 0, 900, 184, 1, 0, - 0, 0, 901, 902, 3, 393, 196, 0, 902, 903, 3, - 357, 178, 0, 903, 904, 3, 353, 176, 0, 904, 905, - 3, 389, 194, 0, 905, 906, 3, 361, 180, 0, 906, - 186, 1, 0, 0, 0, 907, 908, 3, 375, 187, 0, - 908, 909, 3, 357, 178, 0, 909, 910, 3, 353, 176, - 0, 910, 911, 3, 389, 194, 0, 911, 912, 3, 361, - 180, 0, 912, 188, 1, 0, 0, 0, 913, 914, 3, - 361, 180, 0, 914, 915, 3, 379, 189, 0, 915, 916, - 3, 357, 178, 0, 916, 917, 3, 381, 190, 0, 917, - 918, 3, 359, 179, 0, 918, 919, 3, 361, 180, 0, - 919, 920, 5, 95, 0, 0, 920, 921, 3, 363, 181, - 0, 921, 922, 3, 381, 190, 0, 922, 923, 3, 387, - 193, 0, 923, 924, 5, 95, 0, 0, 924, 925, 3, - 393, 196, 0, 925, 926, 3, 387, 193, 0, 926, 927, - 3, 369, 184, 0, 927, 190, 1, 0, 0, 0, 928, - 929, 3, 363, 181, 0, 929, 930, 3, 381, 190, 0, - 930, 931, 3, 387, 193, 0, 931, 192, 1, 0, 0, - 0, 932, 933, 3, 357, 178, 0, 933, 934, 3, 381, - 190, 0, 934, 935, 3, 379, 189, 0, 935, 936, 3, - 391, 195, 0, 936, 937, 3, 353, 176, 0, 937, 938, - 3, 369, 184, 0, 938, 939, 3, 379, 189, 0, 939, - 940, 3, 389, 194, 0, 940, 194, 1, 0, 0, 0, - 941, 942, 3, 389, 194, 0, 942, 943, 3, 391, 195, - 0, 943, 944, 3, 387, 193, 0, 944, 945, 3, 389, - 194, 0, 945, 946, 3, 391, 195, 0, 946, 947, 3, - 353, 176, 0, 947, 948, 3, 387, 193, 0, 948, 949, - 3, 391, 195, 0, 949, 950, 3, 389, 194, 0, 950, - 196, 1, 0, 0, 0, 951, 952, 3, 389, 194, 0, - 952, 953, 3, 391, 195, 0, 953, 954, 3, 387, 193, - 0, 954, 955, 3, 361, 180, 0, 955, 956, 3, 379, - 189, 0, 956, 957, 3, 359, 179, 0, 957, 958, 3, - 389, 194, 0, 958, 198, 1, 0, 0, 0, 959, 960, - 3, 389, 194, 0, 960, 961, 3, 391, 195, 0, 961, - 962, 3, 387, 193, 0, 962, 963, 3, 355, 177, 0, - 963, 964, 3, 361, 180, 0, 964, 965, 3, 363, 181, - 0, 965, 966, 3, 381, 190, 0, 966, 967, 3, 387, - 193, 0, 967, 968, 3, 361, 180, 0, 968, 200, 1, - 0, 0, 0, 969, 970, 3, 389, 194, 0, 970, 971, - 3, 391, 195, 0, 971, 972, 3, 387, 193, 0, 972, - 973, 3, 353, 176, 0, 973, 974, 3, 363, 181, 0, - 974, 975, 3, 391, 195, 0, 975, 976, 3, 361, 180, - 0, 976, 977, 3, 387, 193, 0, 977, 202, 1, 0, - 0, 0, 978, 979, 3, 401, 200, 0, 979, 980, 3, - 361, 180, 0, 980, 981, 3, 353, 176, 0, 981, 982, - 3, 387, 193, 0, 982, 204, 1, 0, 0, 0, 983, - 984, 3, 377, 188, 0, 984, 985, 3, 381, 190, 0, - 985, 986, 3, 379, 189, 0, 986, 987, 3, 391, 195, - 0, 987, 988, 3, 367, 183, 0, 988, 206, 1, 0, - 0, 0, 989, 990, 3, 359, 179, 0, 990, 991, 3, - 353, 176, 0, 991, 992, 3, 401, 200, 0, 992, 208, - 1, 0, 0, 0, 993, 994, 3, 367, 183, 0, 994, - 995, 3, 381, 190, 0, 995, 996, 3, 393, 196, 0, - 996, 997, 3, 387, 193, 0, 997, 998, 3, 389, 194, - 0, 998, 210, 1, 0, 0, 0, 999, 1000, 3, 377, - 188, 0, 1000, 1001, 3, 369, 184, 0, 1001, 1002, 3, - 379, 189, 0, 1002, 1003, 3, 393, 196, 0, 1003, 1004, - 3, 391, 195, 0, 1004, 1005, 3, 361, 180, 0, 1005, - 1006, 3, 389, 194, 0, 1006, 212, 1, 0, 0, 0, - 1007, 1008, 3, 389, 194, 0, 1008, 1009, 3, 361, 180, - 0, 1009, 1010, 3, 357, 178, 0, 1010, 1011, 3, 381, - 190, 0, 1011, 1012, 3, 379, 189, 0, 1012, 1013, 3, - 359, 179, 0, 1013, 1014, 3, 389, 194, 0, 1014, 214, - 1, 0, 0, 0, 1015, 1016, 3, 391, 195, 0, 1016, - 1017, 3, 369, 184, 0, 1017, 1018, 3, 377, 188, 0, - 1018, 1019, 3, 361, 180, 0, 1019, 1020, 3, 403, 201, - 0, 1020, 1021, 3, 381, 190, 0, 1021, 1022, 3, 379, - 189, 0, 1022, 1023, 3, 361, 180, 0, 1023, 216, 1, - 0, 0, 0, 1024, 1025, 3, 391, 195, 0, 1025, 1026, - 3, 403, 201, 0, 1026, 218, 1, 0, 0, 0, 1027, - 1028, 3, 379, 189, 0, 1028, 1029, 3, 381, 190, 0, - 1029, 1030, 3, 397, 198, 0, 1030, 220, 1, 0, 0, - 0, 1031, 1032, 3, 393, 196, 0, 1032, 1033, 3, 393, - 196, 0, 1033, 1034, 3, 369, 184, 0, 1034, 1035, 3, - 359, 179, 0, 1035, 222, 1, 0, 0, 0, 1036, 1037, - 3, 389, 194, 0, 1037, 1038, 3, 391, 195, 0, 1038, - 1039, 3, 387, 193, 0, 1039, 1040, 3, 393, 196, 0, - 1040, 1041, 3, 393, 196, 0, 1041, 1042, 3, 369, 184, - 0, 1042, 1043, 3, 359, 179, 0, 1043, 224, 1, 0, - 0, 0, 1044, 1045, 3, 389, 194, 0, 1045, 1046, 3, - 367, 183, 0, 1046, 1047, 3, 353, 176, 0, 1047, 1048, - 5, 49, 0, 0, 1048, 226, 1, 0, 0, 0, 1049, - 1050, 3, 389, 194, 0, 1050, 1051, 3, 367, 183, 0, - 1051, 1052, 3, 353, 176, 0, 1052, 1053, 5, 50, 0, - 0, 1053, 1054, 5, 53, 0, 0, 1054, 1055, 5, 54, - 0, 0, 1055, 228, 1, 0, 0, 0, 1056, 1057, 3, - 389, 194, 0, 1057, 1058, 3, 367, 183, 0, 1058, 1059, - 3, 353, 176, 0, 1059, 1060, 5, 51, 0, 0, 1060, - 1061, 5, 56, 0, 0, 1061, 1062, 5, 50, 0, 0, - 1062, 230, 1, 0, 0, 0, 1063, 1064, 3, 389, 194, - 0, 1064, 1065, 3, 367, 183, 0, 1065, 1066, 3, 353, - 176, 0, 1066, 1067, 5, 53, 0, 0, 1067, 1068, 5, - 49, 0, 0, 1068, 1069, 5, 50, 0, 0, 1069, 232, - 1, 0, 0, 0, 1070, 1071, 3, 377, 188, 0, 1071, - 1072, 3, 359, 179, 0, 1072, 1073, 5, 53, 0, 0, - 1073, 234, 1, 0, 0, 0, 1074, 1075, 3, 357, 178, - 0, 1075, 1076, 3, 381, 190, 0, 1076, 1077, 3, 353, - 176, 0, 1077, 1078, 3, 375, 187, 0, 1078, 1079, 3, - 361, 180, 0, 1079, 1080, 3, 389, 194, 0, 1080, 1081, - 3, 357, 178, 0, 1081, 1082, 3, 361, 180, 0, 1082, - 236, 1, 0, 0, 0, 1083, 1084, 3, 369, 184, 0, - 1084, 1085, 3, 363, 181, 0, 1085, 238, 1, 0, 0, - 0, 1086, 1087, 3, 389, 194, 0, 1087, 1088, 3, 391, - 195, 0, 1088, 1089, 3, 387, 193, 0, 1089, 1090, 3, - 375, 187, 0, 1090, 1091, 3, 353, 176, 0, 1091, 1092, - 3, 379, 189, 0, 1092, 1093, 3, 365, 182, 0, 1093, - 240, 1, 0, 0, 0, 1094, 1095, 3, 389, 194, 0, - 1095, 1096, 3, 391, 195, 0, 1096, 1097, 3, 387, 193, - 0, 1097, 1098, 3, 359, 179, 0, 1098, 1099, 3, 391, - 195, 0, 1099, 242, 1, 0, 0, 0, 1100, 1101, 3, - 389, 194, 0, 1101, 1102, 3, 353, 176, 0, 1102, 1103, - 3, 377, 188, 0, 1103, 1104, 3, 361, 180, 0, 1104, - 1105, 3, 391, 195, 0, 1105, 1106, 3, 361, 180, 0, - 1106, 1107, 3, 387, 193, 0, 1107, 1108, 3, 377, 188, - 0, 1108, 244, 1, 0, 0, 0, 1109, 1110, 3, 369, - 184, 0, 1110, 1111, 3, 389, 194, 0, 1111, 1112, 3, - 369, 184, 0, 1112, 1113, 3, 387, 193, 0, 1113, 1114, - 3, 369, 184, 0, 1114, 246, 1, 0, 0, 0, 1115, - 1116, 3, 369, 184, 0, 1116, 1117, 3, 389, 194, 0, - 1117, 1118, 3, 393, 196, 0, 1118, 1119, 3, 387, 193, - 0, 1119, 1120, 3, 369, 184, 0, 1120, 248, 1, 0, - 0, 0, 1121, 1122, 3, 369, 184, 0, 1122, 1123, 3, - 389, 194, 0, 1123, 1124, 3, 355, 177, 0, 1124, 1125, - 3, 375, 187, 0, 1125, 1126, 3, 353, 176, 0, 1126, - 1127, 3, 379, 189, 0, 1127, 1128, 3, 373, 186, 0, - 1128, 250, 1, 0, 0, 0, 1129, 1130, 3, 369, 184, - 0, 1130, 1131, 3, 389, 194, 0, 1131, 1132, 3, 375, - 187, 0, 1132, 1133, 3, 369, 184, 0, 1133, 1134, 3, - 391, 195, 0, 1134, 1135, 3, 361, 180, 0, 1135, 1136, - 3, 387, 193, 0, 1136, 1137, 3, 353, 176, 0, 1137, - 1138, 3, 375, 187, 0, 1138, 252, 1, 0, 0, 0, - 1139, 1140, 3, 369, 184, 0, 1140, 1141, 3, 389, 194, - 0, 1141, 1142, 3, 379, 189, 0, 1142, 1143, 3, 393, - 196, 0, 1143, 1144, 3, 377, 188, 0, 1144, 1145, 3, - 361, 180, 0, 1145, 1146, 3, 387, 193, 0, 1146, 1147, - 3, 369, 184, 0, 1147, 1148, 3, 357, 178, 0, 1148, - 254, 1, 0, 0, 0, 1149, 1150, 3, 387, 193, 0, - 1150, 1151, 3, 361, 180, 0, 1151, 1152, 3, 365, 182, - 0, 1152, 1153, 3, 361, 180, 0, 1153, 1154, 3, 399, - 199, 0, 1154, 256, 1, 0, 0, 0, 1155, 1156, 3, - 389, 194, 0, 1156, 1157, 3, 393, 196, 0, 1157, 1158, - 3, 355, 177, 0, 1158, 1159, 3, 389, 194, 0, 1159, - 1160, 3, 391, 195, 0, 1160, 1161, 3, 387, 193, 0, - 1161, 258, 1, 0, 0, 0, 1162, 1163, 3, 387, 193, - 0, 1163, 1164, 3, 361, 180, 0, 1164, 1165, 3, 383, - 191, 0, 1165, 1166, 3, 375, 187, 0, 1166, 1167, 3, - 353, 176, 0, 1167, 1168, 3, 357, 178, 0, 1168, 1169, - 3, 361, 180, 0, 1169, 260, 1, 0, 0, 0, 1170, - 1171, 3, 361, 180, 0, 1171, 1172, 3, 399, 199, 0, - 1172, 1173, 3, 369, 184, 0, 1173, 1174, 3, 389, 194, - 0, 1174, 1175, 3, 391, 195, 0, 1175, 1176, 3, 389, - 194, 0, 1176, 262, 1, 0, 0, 0, 1177, 1178, 3, - 357, 178, 0, 1178, 1179, 3, 381, 190, 0, 1179, 1180, - 3, 393, 196, 0, 1180, 1181, 3, 379, 189, 0, 1181, - 1182, 3, 391, 195, 0, 1182, 264, 1, 0, 0, 0, - 1183, 1184, 3, 389, 194, 0, 1184, 1185, 3, 393, 196, - 0, 1185, 1186, 3, 377, 188, 0, 1186, 266, 1, 0, - 0, 0, 1187, 1188, 3, 377, 188, 0, 1188, 1189, 3, - 369, 184, 0, 1189, 1190, 3, 379, 189, 0, 1190, 268, - 1, 0, 0, 0, 1191, 1192, 3, 377, 188, 0, 1192, - 1193, 3, 353, 176, 0, 1193, 1194, 3, 399, 199, 0, - 1194, 270, 1, 0, 0, 0, 1195, 1196, 3, 353, 176, - 0, 1196, 1197, 3, 395, 197, 0, 1197, 1198, 3, 365, - 182, 0, 1198, 272, 1, 0, 0, 0, 1199, 1200, 3, - 389, 194, 0, 1200, 1201, 3, 353, 176, 0, 1201, 1202, - 3, 377, 188, 0, 1202, 1203, 3, 383, 191, 0, 1203, - 1204, 3, 375, 187, 0, 1204, 1205, 3, 361, 180, 0, - 1205, 274, 1, 0, 0, 0, 1206, 1207, 3, 389, 194, - 0, 1207, 1208, 3, 361, 180, 0, 1208, 1209, 3, 383, - 191, 0, 1209, 1210, 3, 353, 176, 0, 1210, 1211, 3, - 387, 193, 0, 1211, 1212, 3, 353, 176, 0, 1212, 1213, - 3, 391, 195, 0, 1213, 1214, 3, 381, 190, 0, 1214, - 1215, 3, 387, 193, 0, 1215, 276, 1, 0, 0, 0, - 1216, 1220, 5, 60, 0, 0, 1217, 1219, 8, 0, 0, - 0, 1218, 1217, 1, 0, 0, 0, 1219, 1222, 1, 0, - 0, 0, 1220, 1218, 1, 0, 0, 0, 1220, 1221, 1, - 0, 0, 0, 1221, 1223, 1, 0, 0, 0, 1222, 1220, - 1, 0, 0, 0, 1223, 1224, 5, 62, 0, 0, 1224, - 278, 1, 0, 0, 0, 1225, 1227, 3, 333, 166, 0, - 1226, 1225, 1, 0, 0, 0, 1226, 1227, 1, 0, 0, - 0, 1227, 1228, 1, 0, 0, 0, 1228, 1229, 5, 58, - 0, 0, 1229, 280, 1, 0, 0, 0, 1230, 1231, 3, - 279, 139, 0, 1231, 1232, 3, 335, 167, 0, 1232, 282, - 1, 0, 0, 0, 1233, 1234, 5, 95, 0, 0, 1234, - 1235, 5, 58, 0, 0, 1235, 1238, 1, 0, 0, 0, - 1236, 1239, 3, 327, 163, 0, 1237, 1239, 3, 347, 173, - 0, 1238, 1236, 1, 0, 0, 0, 1238, 1237, 1, 0, - 0, 0, 1239, 1248, 1, 0, 0, 0, 1240, 1243, 3, - 331, 165, 0, 1241, 1243, 5, 46, 0, 0, 1242, 1240, - 1, 0, 0, 0, 1242, 1241, 1, 0, 0, 0, 1243, - 1246, 1, 0, 0, 0, 1244, 1242, 1, 0, 0, 0, - 1244, 1245, 1, 0, 0, 0, 1245, 1247, 1, 0, 0, - 0, 1246, 1244, 1, 0, 0, 0, 1247, 1249, 3, 331, - 165, 0, 1248, 1244, 1, 0, 0, 0, 1248, 1249, 1, - 0, 0, 0, 1249, 284, 1, 0, 0, 0, 1250, 1251, - 5, 63, 0, 0, 1251, 1252, 3, 329, 164, 0, 1252, - 286, 1, 0, 0, 0, 1253, 1254, 5, 36, 0, 0, - 1254, 1255, 3, 329, 164, 0, 1255, 288, 1, 0, 0, - 0, 1256, 1258, 5, 64, 0, 0, 1257, 1259, 7, 1, - 0, 0, 1258, 1257, 1, 0, 0, 0, 1259, 1260, 1, - 0, 0, 0, 1260, 1258, 1, 0, 0, 0, 1260, 1261, - 1, 0, 0, 0, 1261, 1271, 1, 0, 0, 0, 1262, - 1265, 5, 45, 0, 0, 1263, 1266, 7, 1, 0, 0, - 1264, 1266, 3, 347, 173, 0, 1265, 1263, 1, 0, 0, - 0, 1265, 1264, 1, 0, 0, 0, 1266, 1267, 1, 0, - 0, 0, 1267, 1265, 1, 0, 0, 0, 1267, 1268, 1, - 0, 0, 0, 1268, 1270, 1, 0, 0, 0, 1269, 1262, - 1, 0, 0, 0, 1270, 1273, 1, 0, 0, 0, 1271, - 1269, 1, 0, 0, 0, 1271, 1272, 1, 0, 0, 0, - 1272, 290, 1, 0, 0, 0, 1273, 1271, 1, 0, 0, - 0, 1274, 1275, 3, 289, 144, 0, 1275, 1276, 5, 64, - 0, 0, 1276, 292, 1, 0, 0, 0, 1277, 1279, 3, - 347, 173, 0, 1278, 1277, 1, 0, 0, 0, 1279, 1280, - 1, 0, 0, 0, 1280, 1278, 1, 0, 0, 0, 1280, - 1281, 1, 0, 0, 0, 1281, 294, 1, 0, 0, 0, - 1282, 1284, 3, 347, 173, 0, 1283, 1282, 1, 0, 0, - 0, 1284, 1287, 1, 0, 0, 0, 1285, 1283, 1, 0, - 0, 0, 1285, 1286, 1, 0, 0, 0, 1286, 1288, 1, - 0, 0, 0, 1287, 1285, 1, 0, 0, 0, 1288, 1290, - 5, 46, 0, 0, 1289, 1291, 3, 347, 173, 0, 1290, - 1289, 1, 0, 0, 0, 1291, 1292, 1, 0, 0, 0, - 1292, 1290, 1, 0, 0, 0, 1292, 1293, 1, 0, 0, - 0, 1293, 296, 1, 0, 0, 0, 1294, 1296, 3, 347, - 173, 0, 1295, 1294, 1, 0, 0, 0, 1296, 1297, 1, - 0, 0, 0, 1297, 1295, 1, 0, 0, 0, 1297, 1298, - 1, 0, 0, 0, 1298, 1299, 1, 0, 0, 0, 1299, - 1303, 5, 46, 0, 0, 1300, 1302, 3, 347, 173, 0, - 1301, 1300, 1, 0, 0, 0, 1302, 1305, 1, 0, 0, - 0, 1303, 1301, 1, 0, 0, 0, 1303, 1304, 1, 0, - 0, 0, 1304, 1306, 1, 0, 0, 0, 1305, 1303, 1, - 0, 0, 0, 1306, 1307, 3, 311, 155, 0, 1307, 1324, - 1, 0, 0, 0, 1308, 1310, 5, 46, 0, 0, 1309, - 1311, 3, 347, 173, 0, 1310, 1309, 1, 0, 0, 0, - 1311, 1312, 1, 0, 0, 0, 1312, 1310, 1, 0, 0, - 0, 1312, 1313, 1, 0, 0, 0, 1313, 1314, 1, 0, - 0, 0, 1314, 1315, 3, 311, 155, 0, 1315, 1324, 1, - 0, 0, 0, 1316, 1318, 3, 347, 173, 0, 1317, 1316, - 1, 0, 0, 0, 1318, 1319, 1, 0, 0, 0, 1319, - 1317, 1, 0, 0, 0, 1319, 1320, 1, 0, 0, 0, - 1320, 1321, 1, 0, 0, 0, 1321, 1322, 3, 311, 155, - 0, 1322, 1324, 1, 0, 0, 0, 1323, 1295, 1, 0, - 0, 0, 1323, 1308, 1, 0, 0, 0, 1323, 1317, 1, - 0, 0, 0, 1324, 298, 1, 0, 0, 0, 1325, 1326, - 5, 43, 0, 0, 1326, 1327, 3, 293, 146, 0, 1327, - 300, 1, 0, 0, 0, 1328, 1329, 5, 43, 0, 0, - 1329, 1330, 3, 295, 147, 0, 1330, 302, 1, 0, 0, - 0, 1331, 1332, 5, 43, 0, 0, 1332, 1333, 3, 297, - 148, 0, 1333, 304, 1, 0, 0, 0, 1334, 1335, 5, - 45, 0, 0, 1335, 1336, 3, 293, 146, 0, 1336, 306, - 1, 0, 0, 0, 1337, 1338, 5, 45, 0, 0, 1338, - 1339, 3, 295, 147, 0, 1339, 308, 1, 0, 0, 0, - 1340, 1341, 5, 45, 0, 0, 1341, 1342, 3, 297, 148, - 0, 1342, 310, 1, 0, 0, 0, 1343, 1345, 7, 2, - 0, 0, 1344, 1346, 7, 3, 0, 0, 1345, 1344, 1, - 0, 0, 0, 1345, 1346, 1, 0, 0, 0, 1346, 1348, - 1, 0, 0, 0, 1347, 1349, 3, 347, 173, 0, 1348, - 1347, 1, 0, 0, 0, 1349, 1350, 1, 0, 0, 0, - 1350, 1348, 1, 0, 0, 0, 1350, 1351, 1, 0, 0, - 0, 1351, 312, 1, 0, 0, 0, 1352, 1357, 5, 39, - 0, 0, 1353, 1356, 8, 4, 0, 0, 1354, 1356, 3, - 321, 160, 0, 1355, 1353, 1, 0, 0, 0, 1355, 1354, - 1, 0, 0, 0, 1356, 1359, 1, 0, 0, 0, 1357, - 1355, 1, 0, 0, 0, 1357, 1358, 1, 0, 0, 0, - 1358, 1360, 1, 0, 0, 0, 1359, 1357, 1, 0, 0, - 0, 1360, 1361, 5, 39, 0, 0, 1361, 314, 1, 0, - 0, 0, 1362, 1367, 5, 34, 0, 0, 1363, 1366, 8, - 5, 0, 0, 1364, 1366, 3, 321, 160, 0, 1365, 1363, - 1, 0, 0, 0, 1365, 1364, 1, 0, 0, 0, 1366, - 1369, 1, 0, 0, 0, 1367, 1365, 1, 0, 0, 0, - 1367, 1368, 1, 0, 0, 0, 1368, 1370, 1, 0, 0, - 0, 1369, 1367, 1, 0, 0, 0, 1370, 1371, 5, 34, - 0, 0, 1371, 316, 1, 0, 0, 0, 1372, 1373, 5, - 39, 0, 0, 1373, 1374, 5, 39, 0, 0, 1374, 1375, - 5, 39, 0, 0, 1375, 1387, 1, 0, 0, 0, 1376, - 1380, 5, 39, 0, 0, 1377, 1378, 5, 39, 0, 0, - 1378, 1380, 5, 39, 0, 0, 1379, 1376, 1, 0, 0, - 0, 1379, 1377, 1, 0, 0, 0, 1379, 1380, 1, 0, - 0, 0, 1380, 1383, 1, 0, 0, 0, 1381, 1384, 8, - 6, 0, 0, 1382, 1384, 3, 321, 160, 0, 1383, 1381, - 1, 0, 0, 0, 1383, 1382, 1, 0, 0, 0, 1384, - 1386, 1, 0, 0, 0, 1385, 1379, 1, 0, 0, 0, - 1386, 1389, 1, 0, 0, 0, 1387, 1385, 1, 0, 0, - 0, 1387, 1388, 1, 0, 0, 0, 1388, 1390, 1, 0, - 0, 0, 1389, 1387, 1, 0, 0, 0, 1390, 1391, 5, - 39, 0, 0, 1391, 1392, 5, 39, 0, 0, 1392, 1393, - 5, 39, 0, 0, 1393, 318, 1, 0, 0, 0, 1394, - 1395, 5, 34, 0, 0, 1395, 1396, 5, 34, 0, 0, - 1396, 1397, 5, 34, 0, 0, 1397, 1409, 1, 0, 0, - 0, 1398, 1402, 5, 34, 0, 0, 1399, 1400, 5, 34, - 0, 0, 1400, 1402, 5, 34, 0, 0, 1401, 1398, 1, - 0, 0, 0, 1401, 1399, 1, 0, 0, 0, 1401, 1402, - 1, 0, 0, 0, 1402, 1405, 1, 0, 0, 0, 1403, - 1406, 8, 7, 0, 0, 1404, 1406, 3, 321, 160, 0, - 1405, 1403, 1, 0, 0, 0, 1405, 1404, 1, 0, 0, - 0, 1406, 1408, 1, 0, 0, 0, 1407, 1401, 1, 0, - 0, 0, 1408, 1411, 1, 0, 0, 0, 1409, 1407, 1, - 0, 0, 0, 1409, 1410, 1, 0, 0, 0, 1410, 1412, - 1, 0, 0, 0, 1411, 1409, 1, 0, 0, 0, 1412, - 1413, 5, 34, 0, 0, 1413, 1414, 5, 34, 0, 0, - 1414, 1415, 5, 34, 0, 0, 1415, 320, 1, 0, 0, - 0, 1416, 1417, 5, 92, 0, 0, 1417, 1418, 7, 8, - 0, 0, 1418, 322, 1, 0, 0, 0, 1419, 1423, 5, - 40, 0, 0, 1420, 1422, 3, 349, 174, 0, 1421, 1420, - 1, 0, 0, 0, 1422, 1425, 1, 0, 0, 0, 1423, - 1421, 1, 0, 0, 0, 1423, 1424, 1, 0, 0, 0, - 1424, 1426, 1, 0, 0, 0, 1425, 1423, 1, 0, 0, - 0, 1426, 1427, 5, 41, 0, 0, 1427, 324, 1, 0, - 0, 0, 1428, 1432, 5, 91, 0, 0, 1429, 1431, 3, - 349, 174, 0, 1430, 1429, 1, 0, 0, 0, 1431, 1434, - 1, 0, 0, 0, 1432, 1430, 1, 0, 0, 0, 1432, - 1433, 1, 0, 0, 0, 1433, 1435, 1, 0, 0, 0, - 1434, 1432, 1, 0, 0, 0, 1435, 1436, 5, 93, 0, - 0, 1436, 326, 1, 0, 0, 0, 1437, 1440, 3, 345, - 172, 0, 1438, 1440, 5, 95, 0, 0, 1439, 1437, 1, - 0, 0, 0, 1439, 1438, 1, 0, 0, 0, 1440, 328, - 1, 0, 0, 0, 1441, 1444, 3, 327, 163, 0, 1442, - 1444, 3, 347, 173, 0, 1443, 1441, 1, 0, 0, 0, - 1443, 1442, 1, 0, 0, 0, 1444, 1450, 1, 0, 0, - 0, 1445, 1449, 3, 327, 163, 0, 1446, 1449, 3, 347, - 173, 0, 1447, 1449, 7, 9, 0, 0, 1448, 1445, 1, - 0, 0, 0, 1448, 1446, 1, 0, 0, 0, 1448, 1447, - 1, 0, 0, 0, 1449, 1452, 1, 0, 0, 0, 1450, - 1448, 1, 0, 0, 0, 1450, 1451, 1, 0, 0, 0, - 1451, 330, 1, 0, 0, 0, 1452, 1450, 1, 0, 0, - 0, 1453, 1458, 3, 327, 163, 0, 1454, 1458, 5, 45, - 0, 0, 1455, 1458, 3, 347, 173, 0, 1456, 1458, 7, - 9, 0, 0, 1457, 1453, 1, 0, 0, 0, 1457, 1454, - 1, 0, 0, 0, 1457, 1455, 1, 0, 0, 0, 1457, - 1456, 1, 0, 0, 0, 1458, 332, 1, 0, 0, 0, - 1459, 1468, 3, 345, 172, 0, 1460, 1463, 3, 331, 165, - 0, 1461, 1463, 5, 46, 0, 0, 1462, 1460, 1, 0, - 0, 0, 1462, 1461, 1, 0, 0, 0, 1463, 1466, 1, - 0, 0, 0, 1464, 1462, 1, 0, 0, 0, 1464, 1465, - 1, 0, 0, 0, 1465, 1467, 1, 0, 0, 0, 1466, - 1464, 1, 0, 0, 0, 1467, 1469, 3, 331, 165, 0, - 1468, 1464, 1, 0, 0, 0, 1468, 1469, 1, 0, 0, - 0, 1469, 334, 1, 0, 0, 0, 1470, 1475, 3, 327, - 163, 0, 1471, 1475, 5, 58, 0, 0, 1472, 1475, 3, - 347, 173, 0, 1473, 1475, 3, 337, 168, 0, 1474, 1470, - 1, 0, 0, 0, 1474, 1471, 1, 0, 0, 0, 1474, - 1472, 1, 0, 0, 0, 1474, 1473, 1, 0, 0, 0, - 1475, 1489, 1, 0, 0, 0, 1476, 1480, 3, 331, 165, - 0, 1477, 1480, 7, 10, 0, 0, 1478, 1480, 3, 337, - 168, 0, 1479, 1476, 1, 0, 0, 0, 1479, 1477, 1, - 0, 0, 0, 1479, 1478, 1, 0, 0, 0, 1480, 1483, - 1, 0, 0, 0, 1481, 1479, 1, 0, 0, 0, 1481, - 1482, 1, 0, 0, 0, 1482, 1487, 1, 0, 0, 0, - 1483, 1481, 1, 0, 0, 0, 1484, 1488, 3, 331, 165, - 0, 1485, 1488, 5, 58, 0, 0, 1486, 1488, 3, 337, - 168, 0, 1487, 1484, 1, 0, 0, 0, 1487, 1485, 1, - 0, 0, 0, 1487, 1486, 1, 0, 0, 0, 1488, 1490, - 1, 0, 0, 0, 1489, 1481, 1, 0, 0, 0, 1489, - 1490, 1, 0, 0, 0, 1490, 336, 1, 0, 0, 0, - 1491, 1494, 3, 339, 169, 0, 1492, 1494, 3, 343, 171, - 0, 1493, 1491, 1, 0, 0, 0, 1493, 1492, 1, 0, - 0, 0, 1494, 338, 1, 0, 0, 0, 1495, 1496, 5, - 37, 0, 0, 1496, 1497, 3, 341, 170, 0, 1497, 1498, - 3, 341, 170, 0, 1498, 340, 1, 0, 0, 0, 1499, - 1502, 3, 347, 173, 0, 1500, 1502, 7, 11, 0, 0, - 1501, 1499, 1, 0, 0, 0, 1501, 1500, 1, 0, 0, - 0, 1502, 342, 1, 0, 0, 0, 1503, 1504, 5, 92, - 0, 0, 1504, 1505, 7, 12, 0, 0, 1505, 344, 1, - 0, 0, 0, 1506, 1507, 7, 13, 0, 0, 1507, 346, - 1, 0, 0, 0, 1508, 1509, 2, 48, 57, 0, 1509, - 348, 1, 0, 0, 0, 1510, 1512, 7, 14, 0, 0, - 1511, 1510, 1, 0, 0, 0, 1512, 1513, 1, 0, 0, - 0, 1513, 1511, 1, 0, 0, 0, 1513, 1514, 1, 0, - 0, 0, 1514, 1515, 1, 0, 0, 0, 1515, 1516, 6, - 174, 0, 0, 1516, 350, 1, 0, 0, 0, 1517, 1521, - 5, 35, 0, 0, 1518, 1520, 8, 15, 0, 0, 1519, - 1518, 1, 0, 0, 0, 1520, 1523, 1, 0, 0, 0, - 1521, 1519, 1, 0, 0, 0, 1521, 1522, 1, 0, 0, - 0, 1522, 1524, 1, 0, 0, 0, 1523, 1521, 1, 0, - 0, 0, 1524, 1525, 6, 175, 0, 0, 1525, 352, 1, - 0, 0, 0, 1526, 1527, 7, 16, 0, 0, 1527, 354, - 1, 0, 0, 0, 1528, 1529, 7, 17, 0, 0, 1529, - 356, 1, 0, 0, 0, 1530, 1531, 7, 18, 0, 0, - 1531, 358, 1, 0, 0, 0, 1532, 1533, 7, 19, 0, - 0, 1533, 360, 1, 0, 0, 0, 1534, 1535, 7, 2, - 0, 0, 1535, 362, 1, 0, 0, 0, 1536, 1537, 7, - 20, 0, 0, 1537, 364, 1, 0, 0, 0, 1538, 1539, - 7, 21, 0, 0, 1539, 366, 1, 0, 0, 0, 1540, - 1541, 7, 22, 0, 0, 1541, 368, 1, 0, 0, 0, - 1542, 1543, 7, 23, 0, 0, 1543, 370, 1, 0, 0, - 0, 1544, 1545, 7, 24, 0, 0, 1545, 372, 1, 0, - 0, 0, 1546, 1547, 7, 25, 0, 0, 1547, 374, 1, - 0, 0, 0, 1548, 1549, 7, 26, 0, 0, 1549, 376, - 1, 0, 0, 0, 1550, 1551, 7, 27, 0, 0, 1551, - 378, 1, 0, 0, 0, 1552, 1553, 7, 28, 0, 0, - 1553, 380, 1, 0, 0, 0, 1554, 1555, 7, 29, 0, - 0, 1555, 382, 1, 0, 0, 0, 1556, 1557, 7, 30, - 0, 0, 1557, 384, 1, 0, 0, 0, 1558, 1559, 7, - 31, 0, 0, 1559, 386, 1, 0, 0, 0, 1560, 1561, - 7, 32, 0, 0, 1561, 388, 1, 0, 0, 0, 1562, - 1563, 7, 33, 0, 0, 1563, 390, 1, 0, 0, 0, - 1564, 1565, 7, 34, 0, 0, 1565, 392, 1, 0, 0, - 0, 1566, 1567, 7, 35, 0, 0, 1567, 394, 1, 0, - 0, 0, 1568, 1569, 7, 36, 0, 0, 1569, 396, 1, - 0, 0, 0, 1570, 1571, 7, 37, 0, 0, 1571, 398, - 1, 0, 0, 0, 1572, 1573, 7, 38, 0, 0, 1573, - 400, 1, 0, 0, 0, 1574, 1575, 7, 39, 0, 0, - 1575, 402, 1, 0, 0, 0, 1576, 1577, 7, 40, 0, - 0, 1577, 404, 1, 0, 0, 0, 54, 0, 563, 596, - 612, 621, 1220, 1226, 1238, 1242, 1244, 1248, 1260, 1265, 1267, - 1271, 1280, 1285, 1292, 1297, 1303, 1312, 1319, 1323, 1345, 1350, - 1355, 1357, 1365, 1367, 1379, 1383, 1387, 1401, 1405, 1409, 1423, - 1432, 1439, 1443, 1448, 1450, 1457, 1462, 1464, 1468, 1474, 1479, - 1481, 1487, 1489, 1493, 1501, 1513, 1521, 1, 6, 0, 0}; + 4, 0, 175, 1590, 6, -1, 2, 0, 7, 0, 2, + 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, + 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, + 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, + 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, + 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, + 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, + 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, + 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, + 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, + 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, + 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, + 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, + 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, + 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, + 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, + 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, + 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, + 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, + 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, + 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, + 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, + 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, + 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, + 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, + 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, + 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, + 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, + 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, + 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, + 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, + 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, + 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, + 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, + 2, 92, 7, 92, 2, 93, 7, 93, 2, 94, 7, + 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, + 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, + 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, + 2, 103, 7, 103, 2, 104, 7, 104, 2, 105, 7, + 105, 2, 106, 7, 106, 2, 107, 7, 107, 2, 108, + 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, + 111, 7, 111, 2, 112, 7, 112, 2, 113, 7, 113, + 2, 114, 7, 114, 2, 115, 7, 115, 2, 116, 7, + 116, 2, 117, 7, 117, 2, 118, 7, 118, 2, 119, + 7, 119, 2, 120, 7, 120, 2, 121, 7, 121, 2, + 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, + 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, + 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, + 7, 130, 2, 131, 7, 131, 2, 132, 7, 132, 2, + 133, 7, 133, 2, 134, 7, 134, 2, 135, 7, 135, + 2, 136, 7, 136, 2, 137, 7, 137, 2, 138, 7, + 138, 2, 139, 7, 139, 2, 140, 7, 140, 2, 141, + 7, 141, 2, 142, 7, 142, 2, 143, 7, 143, 2, + 144, 7, 144, 2, 145, 7, 145, 2, 146, 7, 146, + 2, 147, 7, 147, 2, 148, 7, 148, 2, 149, 7, + 149, 2, 150, 7, 150, 2, 151, 7, 151, 2, 152, + 7, 152, 2, 153, 7, 153, 2, 154, 7, 154, 2, + 155, 7, 155, 2, 156, 7, 156, 2, 157, 7, 157, + 2, 158, 7, 158, 2, 159, 7, 159, 2, 160, 7, + 160, 2, 161, 7, 161, 2, 162, 7, 162, 2, 163, + 7, 163, 2, 164, 7, 164, 2, 165, 7, 165, 2, + 166, 7, 166, 2, 167, 7, 167, 2, 168, 7, 168, + 2, 169, 7, 169, 2, 170, 7, 170, 2, 171, 7, + 171, 2, 172, 7, 172, 2, 173, 7, 173, 2, 174, + 7, 174, 2, 175, 7, 175, 2, 176, 7, 176, 2, + 177, 7, 177, 2, 178, 7, 178, 2, 179, 7, 179, + 2, 180, 7, 180, 2, 181, 7, 181, 2, 182, 7, + 182, 2, 183, 7, 183, 2, 184, 7, 184, 2, 185, + 7, 185, 2, 186, 7, 186, 2, 187, 7, 187, 2, + 188, 7, 188, 2, 189, 7, 189, 2, 190, 7, 190, + 2, 191, 7, 191, 2, 192, 7, 192, 2, 193, 7, + 193, 2, 194, 7, 194, 2, 195, 7, 195, 2, 196, + 7, 196, 2, 197, 7, 197, 2, 198, 7, 198, 2, + 199, 7, 199, 2, 200, 7, 200, 2, 201, 7, 201, + 2, 202, 7, 202, 2, 203, 7, 203, 1, 0, 1, + 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, + 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, + 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, + 1, 9, 1, 9, 1, 10, 1, 10, 1, 11, 1, + 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, + 1, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, + 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, + 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, + 21, 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, + 1, 23, 1, 24, 1, 24, 1, 24, 1, 25, 1, + 25, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, + 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, + 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, + 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, + 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, + 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, + 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, + 1, 32, 1, 32, 1, 32, 1, 32, 1, 33, 1, + 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, + 1, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, + 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, + 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, + 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, + 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, + 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, + 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, + 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, + 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, + 41, 4, 41, 566, 8, 41, 11, 41, 12, 41, 567, + 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, + 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, + 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, + 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, + 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, + 44, 1, 44, 4, 44, 599, 8, 44, 11, 44, 12, + 44, 600, 1, 44, 1, 44, 1, 44, 1, 45, 1, + 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, + 1, 45, 1, 45, 4, 45, 615, 8, 45, 11, 45, + 12, 45, 616, 1, 45, 1, 45, 1, 45, 1, 45, + 1, 45, 4, 45, 624, 8, 45, 11, 45, 12, 45, + 625, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, + 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, + 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 48, + 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, + 49, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, + 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, + 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, + 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, + 52, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, + 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, + 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, + 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, + 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 57, + 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, + 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 59, + 1, 59, 1, 59, 1, 60, 1, 60, 1, 60, 1, + 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, + 1, 61, 1, 62, 1, 62, 1, 62, 1, 62, 1, + 62, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, + 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, + 64, 1, 64, 1, 64, 1, 64, 1, 65, 1, 65, + 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, + 66, 1, 66, 1, 66, 1, 66, 1, 67, 1, 67, + 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, + 67, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, + 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 1, + 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, + 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, + 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, + 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, + 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, + 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, + 74, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, + 1, 75, 1, 76, 1, 76, 1, 76, 1, 76, 1, + 76, 1, 76, 1, 76, 1, 77, 1, 77, 1, 77, + 1, 77, 1, 78, 1, 78, 1, 78, 1, 79, 1, + 79, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, + 1, 80, 1, 80, 1, 81, 1, 81, 1, 81, 1, + 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, + 1, 81, 1, 81, 1, 81, 1, 82, 1, 82, 1, + 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, + 1, 82, 1, 83, 1, 83, 1, 83, 1, 83, 1, + 83, 1, 83, 1, 84, 1, 84, 1, 84, 1, 84, + 1, 85, 1, 85, 1, 85, 1, 85, 1, 86, 1, + 86, 1, 86, 1, 86, 1, 86, 1, 86, 1, 87, + 1, 87, 1, 87, 1, 87, 1, 87, 1, 88, 1, + 88, 1, 88, 1, 88, 1, 89, 1, 89, 1, 89, + 1, 89, 1, 89, 1, 90, 1, 90, 1, 90, 1, + 90, 1, 90, 1, 90, 1, 91, 1, 91, 1, 91, + 1, 91, 1, 91, 1, 91, 1, 92, 1, 92, 1, + 92, 1, 92, 1, 92, 1, 92, 1, 92, 1, 93, + 1, 93, 1, 93, 1, 93, 1, 93, 1, 93, 1, + 93, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, + 1, 94, 1, 95, 1, 95, 1, 95, 1, 95, 1, + 95, 1, 95, 1, 96, 1, 96, 1, 96, 1, 96, + 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, + 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, + 1, 97, 1, 97, 1, 97, 1, 97, 1, 98, 1, + 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, + 1, 98, 1, 98, 1, 99, 1, 99, 1, 99, 1, + 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, + 1, 99, 1, 100, 1, 100, 1, 100, 1, 100, 1, + 100, 1, 100, 1, 100, 1, 100, 1, 101, 1, 101, + 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, + 101, 1, 101, 1, 101, 1, 102, 1, 102, 1, 102, + 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, + 102, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, + 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, + 104, 1, 105, 1, 105, 1, 105, 1, 105, 1, 106, + 1, 106, 1, 106, 1, 106, 1, 106, 1, 106, 1, + 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, + 1, 107, 1, 107, 1, 108, 1, 108, 1, 108, 1, + 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 109, + 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, + 109, 1, 109, 1, 109, 1, 110, 1, 110, 1, 110, + 1, 111, 1, 111, 1, 111, 1, 111, 1, 112, 1, + 112, 1, 112, 1, 112, 1, 112, 1, 113, 1, 113, + 1, 113, 1, 113, 1, 113, 1, 113, 1, 113, 1, + 113, 1, 114, 1, 114, 1, 114, 1, 114, 1, 114, + 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, + 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, 116, + 1, 116, 1, 116, 1, 116, 1, 117, 1, 117, 1, + 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 118, + 1, 118, 1, 118, 1, 118, 1, 119, 1, 119, 1, + 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, + 1, 119, 1, 120, 1, 120, 1, 120, 1, 121, 1, + 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, + 1, 121, 1, 122, 1, 122, 1, 122, 1, 122, 1, + 122, 1, 122, 1, 123, 1, 123, 1, 123, 1, 123, + 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, + 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, + 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, + 125, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, + 1, 126, 1, 126, 1, 126, 1, 127, 1, 127, 1, + 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, + 1, 127, 1, 127, 1, 128, 1, 128, 1, 128, 1, + 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, + 1, 128, 1, 129, 1, 129, 1, 129, 1, 129, 1, + 129, 1, 129, 1, 130, 1, 130, 1, 130, 1, 130, + 1, 130, 1, 130, 1, 130, 1, 131, 1, 131, 1, + 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, + 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, + 132, 1, 132, 1, 133, 1, 133, 1, 133, 1, 133, + 1, 133, 1, 133, 1, 134, 1, 134, 1, 134, 1, + 134, 1, 135, 1, 135, 1, 135, 1, 135, 1, 136, + 1, 136, 1, 136, 1, 136, 1, 137, 1, 137, 1, + 137, 1, 137, 1, 138, 1, 138, 1, 138, 1, 138, + 1, 138, 1, 138, 1, 138, 1, 139, 1, 139, 1, + 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, + 1, 139, 1, 139, 1, 140, 1, 140, 5, 140, 1231, + 8, 140, 10, 140, 12, 140, 1234, 9, 140, 1, 140, + 1, 140, 1, 141, 3, 141, 1239, 8, 141, 1, 141, + 1, 141, 1, 142, 1, 142, 1, 142, 1, 143, 1, + 143, 1, 143, 1, 143, 1, 143, 3, 143, 1251, 8, + 143, 1, 143, 1, 143, 5, 143, 1255, 8, 143, 10, + 143, 12, 143, 1258, 9, 143, 1, 143, 3, 143, 1261, + 8, 143, 1, 144, 1, 144, 1, 144, 1, 145, 1, + 145, 1, 145, 1, 146, 1, 146, 4, 146, 1271, 8, + 146, 11, 146, 12, 146, 1272, 1, 146, 1, 146, 1, + 146, 4, 146, 1278, 8, 146, 11, 146, 12, 146, 1279, + 5, 146, 1282, 8, 146, 10, 146, 12, 146, 1285, 9, + 146, 1, 147, 1, 147, 1, 147, 1, 148, 4, 148, + 1291, 8, 148, 11, 148, 12, 148, 1292, 1, 149, 5, + 149, 1296, 8, 149, 10, 149, 12, 149, 1299, 9, 149, + 1, 149, 1, 149, 4, 149, 1303, 8, 149, 11, 149, + 12, 149, 1304, 1, 150, 4, 150, 1308, 8, 150, 11, + 150, 12, 150, 1309, 1, 150, 1, 150, 5, 150, 1314, + 8, 150, 10, 150, 12, 150, 1317, 9, 150, 1, 150, + 1, 150, 1, 150, 1, 150, 4, 150, 1323, 8, 150, + 11, 150, 12, 150, 1324, 1, 150, 1, 150, 1, 150, + 4, 150, 1330, 8, 150, 11, 150, 12, 150, 1331, 1, + 150, 1, 150, 3, 150, 1336, 8, 150, 1, 151, 1, + 151, 1, 151, 1, 152, 1, 152, 1, 152, 1, 153, + 1, 153, 1, 153, 1, 154, 1, 154, 1, 154, 1, + 155, 1, 155, 1, 155, 1, 156, 1, 156, 1, 156, + 1, 157, 1, 157, 3, 157, 1358, 8, 157, 1, 157, + 4, 157, 1361, 8, 157, 11, 157, 12, 157, 1362, 1, + 158, 1, 158, 1, 158, 5, 158, 1368, 8, 158, 10, + 158, 12, 158, 1371, 9, 158, 1, 158, 1, 158, 1, + 159, 1, 159, 1, 159, 5, 159, 1378, 8, 159, 10, + 159, 12, 159, 1381, 9, 159, 1, 159, 1, 159, 1, + 160, 1, 160, 1, 160, 1, 160, 1, 160, 1, 160, + 1, 160, 3, 160, 1392, 8, 160, 1, 160, 1, 160, + 3, 160, 1396, 8, 160, 5, 160, 1398, 8, 160, 10, + 160, 12, 160, 1401, 9, 160, 1, 160, 1, 160, 1, + 160, 1, 160, 1, 161, 1, 161, 1, 161, 1, 161, + 1, 161, 1, 161, 1, 161, 3, 161, 1414, 8, 161, + 1, 161, 1, 161, 3, 161, 1418, 8, 161, 5, 161, + 1420, 8, 161, 10, 161, 12, 161, 1423, 9, 161, 1, + 161, 1, 161, 1, 161, 1, 161, 1, 162, 1, 162, + 1, 162, 1, 163, 1, 163, 5, 163, 1434, 8, 163, + 10, 163, 12, 163, 1437, 9, 163, 1, 163, 1, 163, + 1, 164, 1, 164, 5, 164, 1443, 8, 164, 10, 164, + 12, 164, 1446, 9, 164, 1, 164, 1, 164, 1, 165, + 1, 165, 3, 165, 1452, 8, 165, 1, 166, 1, 166, + 3, 166, 1456, 8, 166, 1, 166, 1, 166, 1, 166, + 5, 166, 1461, 8, 166, 10, 166, 12, 166, 1464, 9, + 166, 1, 167, 1, 167, 1, 167, 1, 167, 3, 167, + 1470, 8, 167, 1, 168, 1, 168, 1, 168, 5, 168, + 1475, 8, 168, 10, 168, 12, 168, 1478, 9, 168, 1, + 168, 3, 168, 1481, 8, 168, 1, 169, 1, 169, 1, + 169, 1, 169, 3, 169, 1487, 8, 169, 1, 169, 1, + 169, 1, 169, 5, 169, 1492, 8, 169, 10, 169, 12, + 169, 1495, 9, 169, 1, 169, 1, 169, 1, 169, 3, + 169, 1500, 8, 169, 3, 169, 1502, 8, 169, 1, 170, + 1, 170, 3, 170, 1506, 8, 170, 1, 171, 1, 171, + 1, 171, 1, 171, 1, 172, 1, 172, 3, 172, 1514, + 8, 172, 1, 173, 1, 173, 1, 173, 1, 174, 1, + 174, 1, 175, 1, 175, 1, 176, 4, 176, 1524, 8, + 176, 11, 176, 12, 176, 1525, 1, 176, 1, 176, 1, + 177, 1, 177, 5, 177, 1532, 8, 177, 10, 177, 12, + 177, 1535, 9, 177, 1, 177, 1, 177, 1, 178, 1, + 178, 1, 179, 1, 179, 1, 180, 1, 180, 1, 181, + 1, 181, 1, 182, 1, 182, 1, 183, 1, 183, 1, + 184, 1, 184, 1, 185, 1, 185, 1, 186, 1, 186, + 1, 187, 1, 187, 1, 188, 1, 188, 1, 189, 1, + 189, 1, 190, 1, 190, 1, 191, 1, 191, 1, 192, + 1, 192, 1, 193, 1, 193, 1, 194, 1, 194, 1, + 195, 1, 195, 1, 196, 1, 196, 1, 197, 1, 197, + 1, 198, 1, 198, 1, 199, 1, 199, 1, 200, 1, + 200, 1, 201, 1, 201, 1, 202, 1, 202, 1, 203, + 1, 203, 0, 0, 204, 1, 1, 3, 2, 5, 3, + 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, + 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, + 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, + 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, + 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, + 31, 63, 32, 65, 33, 67, 34, 69, 35, 71, 36, + 73, 37, 75, 38, 77, 39, 79, 40, 81, 41, 83, + 42, 85, 43, 87, 44, 89, 45, 91, 46, 93, 47, + 95, 48, 97, 49, 99, 50, 101, 51, 103, 52, 105, + 53, 107, 54, 109, 55, 111, 56, 113, 57, 115, 58, + 117, 59, 119, 60, 121, 61, 123, 62, 125, 63, 127, + 64, 129, 65, 131, 66, 133, 67, 135, 68, 137, 69, + 139, 70, 141, 71, 143, 72, 145, 73, 147, 74, 149, + 75, 151, 76, 153, 77, 155, 78, 157, 79, 159, 80, + 161, 81, 163, 82, 165, 83, 167, 84, 169, 85, 171, + 86, 173, 87, 175, 88, 177, 89, 179, 90, 181, 91, + 183, 92, 185, 93, 187, 94, 189, 95, 191, 96, 193, + 97, 195, 98, 197, 99, 199, 100, 201, 101, 203, 102, + 205, 103, 207, 104, 209, 105, 211, 106, 213, 107, 215, + 108, 217, 109, 219, 110, 221, 111, 223, 112, 225, 113, + 227, 114, 229, 115, 231, 116, 233, 117, 235, 118, 237, + 119, 239, 120, 241, 121, 243, 122, 245, 123, 247, 124, + 249, 125, 251, 126, 253, 127, 255, 128, 257, 129, 259, + 130, 261, 131, 263, 132, 265, 133, 267, 134, 269, 135, + 271, 136, 273, 137, 275, 138, 277, 139, 279, 140, 281, + 141, 283, 142, 285, 143, 287, 144, 289, 145, 291, 146, + 293, 147, 295, 148, 297, 149, 299, 150, 301, 151, 303, + 152, 305, 153, 307, 154, 309, 155, 311, 156, 313, 157, + 315, 158, 317, 159, 319, 160, 321, 161, 323, 162, 325, + 163, 327, 164, 329, 165, 331, 166, 333, 167, 335, 0, + 337, 168, 339, 169, 341, 170, 343, 171, 345, 172, 347, + 173, 349, 0, 351, 0, 353, 174, 355, 175, 357, 0, + 359, 0, 361, 0, 363, 0, 365, 0, 367, 0, 369, + 0, 371, 0, 373, 0, 375, 0, 377, 0, 379, 0, + 381, 0, 383, 0, 385, 0, 387, 0, 389, 0, 391, + 0, 393, 0, 395, 0, 397, 0, 399, 0, 401, 0, + 403, 0, 405, 0, 407, 0, 1, 0, 41, 8, 0, + 0, 32, 34, 34, 60, 60, 62, 62, 92, 92, 94, + 94, 96, 96, 123, 125, 2, 0, 65, 90, 97, 122, + 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, + 45, 4, 0, 10, 10, 13, 13, 39, 39, 92, 92, + 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 2, + 0, 39, 39, 92, 92, 2, 0, 34, 34, 92, 92, + 8, 0, 34, 34, 39, 39, 92, 92, 98, 98, 102, + 102, 110, 110, 114, 114, 116, 116, 3, 0, 183, 183, + 768, 879, 8255, 8256, 2, 0, 46, 46, 58, 58, 2, + 0, 65, 70, 97, 102, 7, 0, 33, 33, 35, 47, + 59, 59, 61, 61, 63, 64, 95, 95, 126, 126, 13, + 0, 65, 90, 97, 122, 192, 214, 216, 246, 248, 767, + 880, 893, 895, 8191, 8204, 8205, 8304, 8591, 11264, 12271, 12289, + 55295, 63744, 64975, 65008, 65533, 3, 0, 9, 10, 13, 13, + 32, 32, 2, 0, 10, 10, 13, 13, 2, 0, 65, + 65, 97, 97, 2, 0, 66, 66, 98, 98, 2, 0, + 67, 67, 99, 99, 2, 0, 68, 68, 100, 100, 2, + 0, 70, 70, 102, 102, 2, 0, 71, 71, 103, 103, + 2, 0, 72, 72, 104, 104, 2, 0, 73, 73, 105, + 105, 2, 0, 74, 74, 106, 106, 2, 0, 75, 75, + 107, 107, 2, 0, 76, 76, 108, 108, 2, 0, 77, + 77, 109, 109, 2, 0, 78, 78, 110, 110, 2, 0, + 79, 79, 111, 111, 2, 0, 80, 80, 112, 112, 2, + 0, 81, 81, 113, 113, 2, 0, 82, 82, 114, 114, + 2, 0, 83, 83, 115, 115, 2, 0, 84, 84, 116, + 116, 2, 0, 85, 85, 117, 117, 2, 0, 86, 86, + 118, 118, 2, 0, 87, 87, 119, 119, 2, 0, 88, + 88, 120, 120, 2, 0, 89, 89, 121, 121, 2, 0, + 90, 90, 122, 122, 1623, 0, 1, 1, 0, 0, 0, + 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, + 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, + 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, + 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, + 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, + 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, + 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, + 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, + 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, + 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, + 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, + 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, + 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, + 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, + 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, + 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, + 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, + 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, + 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, + 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, + 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, + 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, + 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, + 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, + 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, + 0, 0, 95, 1, 0, 0, 0, 0, 97, 1, 0, + 0, 0, 0, 99, 1, 0, 0, 0, 0, 101, 1, + 0, 0, 0, 0, 103, 1, 0, 0, 0, 0, 105, + 1, 0, 0, 0, 0, 107, 1, 0, 0, 0, 0, + 109, 1, 0, 0, 0, 0, 111, 1, 0, 0, 0, + 0, 113, 1, 0, 0, 0, 0, 115, 1, 0, 0, + 0, 0, 117, 1, 0, 0, 0, 0, 119, 1, 0, + 0, 0, 0, 121, 1, 0, 0, 0, 0, 123, 1, + 0, 0, 0, 0, 125, 1, 0, 0, 0, 0, 127, + 1, 0, 0, 0, 0, 129, 1, 0, 0, 0, 0, + 131, 1, 0, 0, 0, 0, 133, 1, 0, 0, 0, + 0, 135, 1, 0, 0, 0, 0, 137, 1, 0, 0, + 0, 0, 139, 1, 0, 0, 0, 0, 141, 1, 0, + 0, 0, 0, 143, 1, 0, 0, 0, 0, 145, 1, + 0, 0, 0, 0, 147, 1, 0, 0, 0, 0, 149, + 1, 0, 0, 0, 0, 151, 1, 0, 0, 0, 0, + 153, 1, 0, 0, 0, 0, 155, 1, 0, 0, 0, + 0, 157, 1, 0, 0, 0, 0, 159, 1, 0, 0, + 0, 0, 161, 1, 0, 0, 0, 0, 163, 1, 0, + 0, 0, 0, 165, 1, 0, 0, 0, 0, 167, 1, + 0, 0, 0, 0, 169, 1, 0, 0, 0, 0, 171, + 1, 0, 0, 0, 0, 173, 1, 0, 0, 0, 0, + 175, 1, 0, 0, 0, 0, 177, 1, 0, 0, 0, + 0, 179, 1, 0, 0, 0, 0, 181, 1, 0, 0, + 0, 0, 183, 1, 0, 0, 0, 0, 185, 1, 0, + 0, 0, 0, 187, 1, 0, 0, 0, 0, 189, 1, + 0, 0, 0, 0, 191, 1, 0, 0, 0, 0, 193, + 1, 0, 0, 0, 0, 195, 1, 0, 0, 0, 0, + 197, 1, 0, 0, 0, 0, 199, 1, 0, 0, 0, + 0, 201, 1, 0, 0, 0, 0, 203, 1, 0, 0, + 0, 0, 205, 1, 0, 0, 0, 0, 207, 1, 0, + 0, 0, 0, 209, 1, 0, 0, 0, 0, 211, 1, + 0, 0, 0, 0, 213, 1, 0, 0, 0, 0, 215, + 1, 0, 0, 0, 0, 217, 1, 0, 0, 0, 0, + 219, 1, 0, 0, 0, 0, 221, 1, 0, 0, 0, + 0, 223, 1, 0, 0, 0, 0, 225, 1, 0, 0, + 0, 0, 227, 1, 0, 0, 0, 0, 229, 1, 0, + 0, 0, 0, 231, 1, 0, 0, 0, 0, 233, 1, + 0, 0, 0, 0, 235, 1, 0, 0, 0, 0, 237, + 1, 0, 0, 0, 0, 239, 1, 0, 0, 0, 0, + 241, 1, 0, 0, 0, 0, 243, 1, 0, 0, 0, + 0, 245, 1, 0, 0, 0, 0, 247, 1, 0, 0, + 0, 0, 249, 1, 0, 0, 0, 0, 251, 1, 0, + 0, 0, 0, 253, 1, 0, 0, 0, 0, 255, 1, + 0, 0, 0, 0, 257, 1, 0, 0, 0, 0, 259, + 1, 0, 0, 0, 0, 261, 1, 0, 0, 0, 0, + 263, 1, 0, 0, 0, 0, 265, 1, 0, 0, 0, + 0, 267, 1, 0, 0, 0, 0, 269, 1, 0, 0, + 0, 0, 271, 1, 0, 0, 0, 0, 273, 1, 0, + 0, 0, 0, 275, 1, 0, 0, 0, 0, 277, 1, + 0, 0, 0, 0, 279, 1, 0, 0, 0, 0, 281, + 1, 0, 0, 0, 0, 283, 1, 0, 0, 0, 0, + 285, 1, 0, 0, 0, 0, 287, 1, 0, 0, 0, + 0, 289, 1, 0, 0, 0, 0, 291, 1, 0, 0, + 0, 0, 293, 1, 0, 0, 0, 0, 295, 1, 0, + 0, 0, 0, 297, 1, 0, 0, 0, 0, 299, 1, + 0, 0, 0, 0, 301, 1, 0, 0, 0, 0, 303, + 1, 0, 0, 0, 0, 305, 1, 0, 0, 0, 0, + 307, 1, 0, 0, 0, 0, 309, 1, 0, 0, 0, + 0, 311, 1, 0, 0, 0, 0, 313, 1, 0, 0, + 0, 0, 315, 1, 0, 0, 0, 0, 317, 1, 0, + 0, 0, 0, 319, 1, 0, 0, 0, 0, 321, 1, + 0, 0, 0, 0, 323, 1, 0, 0, 0, 0, 325, + 1, 0, 0, 0, 0, 327, 1, 0, 0, 0, 0, + 329, 1, 0, 0, 0, 0, 331, 1, 0, 0, 0, + 0, 333, 1, 0, 0, 0, 0, 337, 1, 0, 0, + 0, 0, 339, 1, 0, 0, 0, 0, 341, 1, 0, + 0, 0, 0, 343, 1, 0, 0, 0, 0, 345, 1, + 0, 0, 0, 0, 347, 1, 0, 0, 0, 0, 353, + 1, 0, 0, 0, 0, 355, 1, 0, 0, 0, 1, + 409, 1, 0, 0, 0, 3, 411, 1, 0, 0, 0, + 5, 413, 1, 0, 0, 0, 7, 415, 1, 0, 0, + 0, 9, 417, 1, 0, 0, 0, 11, 419, 1, 0, + 0, 0, 13, 421, 1, 0, 0, 0, 15, 423, 1, + 0, 0, 0, 17, 425, 1, 0, 0, 0, 19, 427, + 1, 0, 0, 0, 21, 429, 1, 0, 0, 0, 23, + 431, 1, 0, 0, 0, 25, 433, 1, 0, 0, 0, + 27, 435, 1, 0, 0, 0, 29, 437, 1, 0, 0, + 0, 31, 439, 1, 0, 0, 0, 33, 441, 1, 0, + 0, 0, 35, 443, 1, 0, 0, 0, 37, 446, 1, + 0, 0, 0, 39, 449, 1, 0, 0, 0, 41, 451, + 1, 0, 0, 0, 43, 454, 1, 0, 0, 0, 45, + 456, 1, 0, 0, 0, 47, 458, 1, 0, 0, 0, + 49, 461, 1, 0, 0, 0, 51, 464, 1, 0, 0, + 0, 53, 466, 1, 0, 0, 0, 55, 469, 1, 0, + 0, 0, 57, 474, 1, 0, 0, 0, 59, 480, 1, + 0, 0, 0, 61, 485, 1, 0, 0, 0, 63, 492, + 1, 0, 0, 0, 65, 499, 1, 0, 0, 0, 67, + 508, 1, 0, 0, 0, 69, 516, 1, 0, 0, 0, + 71, 519, 1, 0, 0, 0, 73, 529, 1, 0, 0, + 0, 75, 535, 1, 0, 0, 0, 77, 544, 1, 0, + 0, 0, 79, 548, 1, 0, 0, 0, 81, 553, 1, + 0, 0, 0, 83, 559, 1, 0, 0, 0, 85, 572, + 1, 0, 0, 0, 87, 585, 1, 0, 0, 0, 89, + 592, 1, 0, 0, 0, 91, 605, 1, 0, 0, 0, + 93, 630, 1, 0, 0, 0, 95, 634, 1, 0, 0, + 0, 97, 639, 1, 0, 0, 0, 99, 645, 1, 0, + 0, 0, 101, 652, 1, 0, 0, 0, 103, 662, 1, + 0, 0, 0, 105, 669, 1, 0, 0, 0, 107, 674, + 1, 0, 0, 0, 109, 681, 1, 0, 0, 0, 111, + 686, 1, 0, 0, 0, 113, 692, 1, 0, 0, 0, + 115, 697, 1, 0, 0, 0, 117, 704, 1, 0, 0, + 0, 119, 708, 1, 0, 0, 0, 121, 711, 1, 0, + 0, 0, 123, 716, 1, 0, 0, 0, 125, 721, 1, + 0, 0, 0, 127, 726, 1, 0, 0, 0, 129, 733, + 1, 0, 0, 0, 131, 740, 1, 0, 0, 0, 133, + 745, 1, 0, 0, 0, 135, 751, 1, 0, 0, 0, + 137, 759, 1, 0, 0, 0, 139, 765, 1, 0, 0, + 0, 141, 769, 1, 0, 0, 0, 143, 778, 1, 0, + 0, 0, 145, 786, 1, 0, 0, 0, 147, 791, 1, + 0, 0, 0, 149, 797, 1, 0, 0, 0, 151, 803, + 1, 0, 0, 0, 153, 809, 1, 0, 0, 0, 155, + 816, 1, 0, 0, 0, 157, 820, 1, 0, 0, 0, + 159, 823, 1, 0, 0, 0, 161, 827, 1, 0, 0, + 0, 163, 832, 1, 0, 0, 0, 165, 844, 1, 0, + 0, 0, 167, 853, 1, 0, 0, 0, 169, 859, 1, + 0, 0, 0, 171, 863, 1, 0, 0, 0, 173, 867, + 1, 0, 0, 0, 175, 873, 1, 0, 0, 0, 177, + 878, 1, 0, 0, 0, 179, 882, 1, 0, 0, 0, + 181, 887, 1, 0, 0, 0, 183, 893, 1, 0, 0, + 0, 185, 899, 1, 0, 0, 0, 187, 906, 1, 0, + 0, 0, 189, 913, 1, 0, 0, 0, 191, 919, 1, + 0, 0, 0, 193, 925, 1, 0, 0, 0, 195, 940, + 1, 0, 0, 0, 197, 944, 1, 0, 0, 0, 199, + 953, 1, 0, 0, 0, 201, 963, 1, 0, 0, 0, + 203, 971, 1, 0, 0, 0, 205, 981, 1, 0, 0, + 0, 207, 990, 1, 0, 0, 0, 209, 995, 1, 0, + 0, 0, 211, 1001, 1, 0, 0, 0, 213, 1005, 1, + 0, 0, 0, 215, 1011, 1, 0, 0, 0, 217, 1019, + 1, 0, 0, 0, 219, 1027, 1, 0, 0, 0, 221, + 1036, 1, 0, 0, 0, 223, 1039, 1, 0, 0, 0, + 225, 1043, 1, 0, 0, 0, 227, 1048, 1, 0, 0, + 0, 229, 1056, 1, 0, 0, 0, 231, 1061, 1, 0, + 0, 0, 233, 1068, 1, 0, 0, 0, 235, 1075, 1, + 0, 0, 0, 237, 1082, 1, 0, 0, 0, 239, 1086, + 1, 0, 0, 0, 241, 1095, 1, 0, 0, 0, 243, + 1098, 1, 0, 0, 0, 245, 1106, 1, 0, 0, 0, + 247, 1112, 1, 0, 0, 0, 249, 1121, 1, 0, 0, + 0, 251, 1127, 1, 0, 0, 0, 253, 1133, 1, 0, + 0, 0, 255, 1141, 1, 0, 0, 0, 257, 1151, 1, + 0, 0, 0, 259, 1161, 1, 0, 0, 0, 261, 1167, + 1, 0, 0, 0, 263, 1174, 1, 0, 0, 0, 265, + 1182, 1, 0, 0, 0, 267, 1189, 1, 0, 0, 0, + 269, 1195, 1, 0, 0, 0, 271, 1199, 1, 0, 0, + 0, 273, 1203, 1, 0, 0, 0, 275, 1207, 1, 0, + 0, 0, 277, 1211, 1, 0, 0, 0, 279, 1218, 1, + 0, 0, 0, 281, 1228, 1, 0, 0, 0, 283, 1238, + 1, 0, 0, 0, 285, 1242, 1, 0, 0, 0, 287, + 1245, 1, 0, 0, 0, 289, 1262, 1, 0, 0, 0, + 291, 1265, 1, 0, 0, 0, 293, 1268, 1, 0, 0, + 0, 295, 1286, 1, 0, 0, 0, 297, 1290, 1, 0, + 0, 0, 299, 1297, 1, 0, 0, 0, 301, 1335, 1, + 0, 0, 0, 303, 1337, 1, 0, 0, 0, 305, 1340, + 1, 0, 0, 0, 307, 1343, 1, 0, 0, 0, 309, + 1346, 1, 0, 0, 0, 311, 1349, 1, 0, 0, 0, + 313, 1352, 1, 0, 0, 0, 315, 1355, 1, 0, 0, + 0, 317, 1364, 1, 0, 0, 0, 319, 1374, 1, 0, + 0, 0, 321, 1384, 1, 0, 0, 0, 323, 1406, 1, + 0, 0, 0, 325, 1428, 1, 0, 0, 0, 327, 1431, + 1, 0, 0, 0, 329, 1440, 1, 0, 0, 0, 331, + 1451, 1, 0, 0, 0, 333, 1455, 1, 0, 0, 0, + 335, 1469, 1, 0, 0, 0, 337, 1471, 1, 0, 0, + 0, 339, 1486, 1, 0, 0, 0, 341, 1505, 1, 0, + 0, 0, 343, 1507, 1, 0, 0, 0, 345, 1513, 1, + 0, 0, 0, 347, 1515, 1, 0, 0, 0, 349, 1518, + 1, 0, 0, 0, 351, 1520, 1, 0, 0, 0, 353, + 1523, 1, 0, 0, 0, 355, 1529, 1, 0, 0, 0, + 357, 1538, 1, 0, 0, 0, 359, 1540, 1, 0, 0, + 0, 361, 1542, 1, 0, 0, 0, 363, 1544, 1, 0, + 0, 0, 365, 1546, 1, 0, 0, 0, 367, 1548, 1, + 0, 0, 0, 369, 1550, 1, 0, 0, 0, 371, 1552, + 1, 0, 0, 0, 373, 1554, 1, 0, 0, 0, 375, + 1556, 1, 0, 0, 0, 377, 1558, 1, 0, 0, 0, + 379, 1560, 1, 0, 0, 0, 381, 1562, 1, 0, 0, + 0, 383, 1564, 1, 0, 0, 0, 385, 1566, 1, 0, + 0, 0, 387, 1568, 1, 0, 0, 0, 389, 1570, 1, + 0, 0, 0, 391, 1572, 1, 0, 0, 0, 393, 1574, + 1, 0, 0, 0, 395, 1576, 1, 0, 0, 0, 397, + 1578, 1, 0, 0, 0, 399, 1580, 1, 0, 0, 0, + 401, 1582, 1, 0, 0, 0, 403, 1584, 1, 0, 0, + 0, 405, 1586, 1, 0, 0, 0, 407, 1588, 1, 0, + 0, 0, 409, 410, 5, 42, 0, 0, 410, 2, 1, + 0, 0, 0, 411, 412, 5, 40, 0, 0, 412, 4, + 1, 0, 0, 0, 413, 414, 5, 41, 0, 0, 414, + 6, 1, 0, 0, 0, 415, 416, 5, 123, 0, 0, + 416, 8, 1, 0, 0, 0, 417, 418, 5, 125, 0, + 0, 418, 10, 1, 0, 0, 0, 419, 420, 5, 59, + 0, 0, 420, 12, 1, 0, 0, 0, 421, 422, 5, + 46, 0, 0, 422, 14, 1, 0, 0, 0, 423, 424, + 5, 44, 0, 0, 424, 16, 1, 0, 0, 0, 425, + 426, 5, 97, 0, 0, 426, 18, 1, 0, 0, 0, + 427, 428, 5, 124, 0, 0, 428, 20, 1, 0, 0, + 0, 429, 430, 5, 47, 0, 0, 430, 22, 1, 0, + 0, 0, 431, 432, 5, 94, 0, 0, 432, 24, 1, + 0, 0, 0, 433, 434, 5, 43, 0, 0, 434, 26, + 1, 0, 0, 0, 435, 436, 5, 63, 0, 0, 436, + 28, 1, 0, 0, 0, 437, 438, 5, 33, 0, 0, + 438, 30, 1, 0, 0, 0, 439, 440, 5, 91, 0, + 0, 440, 32, 1, 0, 0, 0, 441, 442, 5, 93, + 0, 0, 442, 34, 1, 0, 0, 0, 443, 444, 5, + 124, 0, 0, 444, 445, 5, 124, 0, 0, 445, 36, + 1, 0, 0, 0, 446, 447, 5, 38, 0, 0, 447, + 448, 5, 38, 0, 0, 448, 38, 1, 0, 0, 0, + 449, 450, 5, 61, 0, 0, 450, 40, 1, 0, 0, + 0, 451, 452, 5, 33, 0, 0, 452, 453, 5, 61, + 0, 0, 453, 42, 1, 0, 0, 0, 454, 455, 5, + 60, 0, 0, 455, 44, 1, 0, 0, 0, 456, 457, + 5, 62, 0, 0, 457, 46, 1, 0, 0, 0, 458, + 459, 5, 60, 0, 0, 459, 460, 5, 61, 0, 0, + 460, 48, 1, 0, 0, 0, 461, 462, 5, 62, 0, + 0, 462, 463, 5, 61, 0, 0, 463, 50, 1, 0, + 0, 0, 464, 465, 5, 45, 0, 0, 465, 52, 1, + 0, 0, 0, 466, 467, 5, 94, 0, 0, 467, 468, + 5, 94, 0, 0, 468, 54, 1, 0, 0, 0, 469, + 470, 5, 116, 0, 0, 470, 471, 5, 114, 0, 0, + 471, 472, 5, 117, 0, 0, 472, 473, 5, 101, 0, + 0, 473, 56, 1, 0, 0, 0, 474, 475, 5, 102, + 0, 0, 475, 476, 5, 97, 0, 0, 476, 477, 5, + 108, 0, 0, 477, 478, 5, 115, 0, 0, 478, 479, + 5, 101, 0, 0, 479, 58, 1, 0, 0, 0, 480, + 481, 3, 359, 179, 0, 481, 482, 3, 357, 178, 0, + 482, 483, 3, 393, 196, 0, 483, 484, 3, 365, 182, + 0, 484, 60, 1, 0, 0, 0, 485, 486, 3, 387, + 193, 0, 486, 487, 3, 391, 195, 0, 487, 488, 3, + 365, 182, 0, 488, 489, 3, 367, 183, 0, 489, 490, + 3, 373, 186, 0, 490, 491, 3, 403, 201, 0, 491, + 62, 1, 0, 0, 0, 492, 493, 3, 393, 196, 0, + 493, 494, 3, 365, 182, 0, 494, 495, 3, 379, 189, + 0, 495, 496, 3, 365, 182, 0, 496, 497, 3, 361, + 180, 0, 497, 498, 3, 395, 197, 0, 498, 64, 1, + 0, 0, 0, 499, 500, 3, 363, 181, 0, 500, 501, + 3, 373, 186, 0, 501, 502, 3, 393, 196, 0, 502, + 503, 3, 395, 197, 0, 503, 504, 3, 373, 186, 0, + 504, 505, 3, 383, 191, 0, 505, 506, 3, 361, 180, + 0, 506, 507, 3, 395, 197, 0, 507, 66, 1, 0, + 0, 0, 508, 509, 3, 391, 195, 0, 509, 510, 3, + 365, 182, 0, 510, 511, 3, 363, 181, 0, 511, 512, + 3, 397, 198, 0, 512, 513, 3, 361, 180, 0, 513, + 514, 3, 365, 182, 0, 514, 515, 3, 363, 181, 0, + 515, 68, 1, 0, 0, 0, 516, 517, 3, 357, 178, + 0, 517, 518, 3, 393, 196, 0, 518, 70, 1, 0, + 0, 0, 519, 520, 3, 361, 180, 0, 520, 521, 3, + 385, 192, 0, 521, 522, 3, 383, 191, 0, 522, 523, + 3, 393, 196, 0, 523, 524, 3, 395, 197, 0, 524, + 525, 3, 391, 195, 0, 525, 526, 3, 397, 198, 0, + 526, 527, 3, 361, 180, 0, 527, 528, 3, 395, 197, + 0, 528, 72, 1, 0, 0, 0, 529, 530, 3, 401, + 200, 0, 530, 531, 3, 371, 185, 0, 531, 532, 3, + 365, 182, 0, 532, 533, 3, 391, 195, 0, 533, 534, + 3, 365, 182, 0, 534, 74, 1, 0, 0, 0, 535, + 536, 3, 363, 181, 0, 536, 537, 3, 365, 182, 0, + 537, 538, 3, 393, 196, 0, 538, 539, 3, 361, 180, + 0, 539, 540, 3, 391, 195, 0, 540, 541, 3, 373, + 186, 0, 541, 542, 3, 359, 179, 0, 542, 543, 3, + 365, 182, 0, 543, 76, 1, 0, 0, 0, 544, 545, + 3, 357, 178, 0, 545, 546, 3, 393, 196, 0, 546, + 547, 3, 377, 188, 0, 547, 78, 1, 0, 0, 0, + 548, 549, 3, 367, 183, 0, 549, 550, 3, 391, 195, + 0, 550, 551, 3, 385, 192, 0, 551, 552, 3, 381, + 190, 0, 552, 80, 1, 0, 0, 0, 553, 554, 3, + 383, 191, 0, 554, 555, 3, 357, 178, 0, 555, 556, + 3, 381, 190, 0, 556, 557, 3, 365, 182, 0, 557, + 558, 3, 363, 181, 0, 558, 82, 1, 0, 0, 0, + 559, 560, 3, 369, 184, 0, 560, 561, 3, 391, 195, + 0, 561, 562, 3, 385, 192, 0, 562, 563, 3, 397, + 198, 0, 563, 565, 3, 387, 193, 0, 564, 566, 3, + 353, 176, 0, 565, 564, 1, 0, 0, 0, 566, 567, + 1, 0, 0, 0, 567, 565, 1, 0, 0, 0, 567, + 568, 1, 0, 0, 0, 568, 569, 1, 0, 0, 0, + 569, 570, 3, 359, 179, 0, 570, 571, 3, 405, 202, + 0, 571, 84, 1, 0, 0, 0, 572, 573, 3, 369, + 184, 0, 573, 574, 3, 391, 195, 0, 574, 575, 3, + 385, 192, 0, 575, 576, 3, 397, 198, 0, 576, 577, + 3, 387, 193, 0, 577, 578, 5, 95, 0, 0, 578, + 579, 3, 361, 180, 0, 579, 580, 3, 385, 192, 0, + 580, 581, 3, 383, 191, 0, 581, 582, 3, 361, 180, + 0, 582, 583, 3, 357, 178, 0, 583, 584, 3, 395, + 197, 0, 584, 86, 1, 0, 0, 0, 585, 586, 3, + 371, 185, 0, 586, 587, 3, 357, 178, 0, 587, 588, + 3, 399, 199, 0, 588, 589, 3, 373, 186, 0, 589, + 590, 3, 383, 191, 0, 590, 591, 3, 369, 184, 0, + 591, 88, 1, 0, 0, 0, 592, 593, 3, 385, 192, + 0, 593, 594, 3, 391, 195, 0, 594, 595, 3, 363, + 181, 0, 595, 596, 3, 365, 182, 0, 596, 598, 3, + 391, 195, 0, 597, 599, 3, 353, 176, 0, 598, 597, + 1, 0, 0, 0, 599, 600, 1, 0, 0, 0, 600, + 598, 1, 0, 0, 0, 600, 601, 1, 0, 0, 0, + 601, 602, 1, 0, 0, 0, 602, 603, 3, 359, 179, + 0, 603, 604, 3, 405, 202, 0, 604, 90, 1, 0, + 0, 0, 605, 606, 3, 373, 186, 0, 606, 607, 3, + 383, 191, 0, 607, 608, 3, 395, 197, 0, 608, 609, + 3, 365, 182, 0, 609, 610, 3, 391, 195, 0, 610, + 611, 3, 383, 191, 0, 611, 612, 3, 357, 178, 0, + 612, 614, 3, 379, 189, 0, 613, 615, 3, 353, 176, + 0, 614, 613, 1, 0, 0, 0, 615, 616, 1, 0, + 0, 0, 616, 614, 1, 0, 0, 0, 616, 617, 1, + 0, 0, 0, 617, 618, 1, 0, 0, 0, 618, 619, + 3, 393, 196, 0, 619, 620, 3, 385, 192, 0, 620, + 621, 3, 391, 195, 0, 621, 623, 3, 395, 197, 0, + 622, 624, 3, 353, 176, 0, 623, 622, 1, 0, 0, + 0, 624, 625, 1, 0, 0, 0, 625, 623, 1, 0, + 0, 0, 625, 626, 1, 0, 0, 0, 626, 627, 1, + 0, 0, 0, 627, 628, 3, 359, 179, 0, 628, 629, + 3, 405, 202, 0, 629, 92, 1, 0, 0, 0, 630, + 631, 3, 357, 178, 0, 631, 632, 3, 393, 196, 0, + 632, 633, 3, 361, 180, 0, 633, 94, 1, 0, 0, + 0, 634, 635, 3, 363, 181, 0, 635, 636, 3, 365, + 182, 0, 636, 637, 3, 393, 196, 0, 637, 638, 3, + 361, 180, 0, 638, 96, 1, 0, 0, 0, 639, 640, + 3, 379, 189, 0, 640, 641, 3, 373, 186, 0, 641, + 642, 3, 381, 190, 0, 642, 643, 3, 373, 186, 0, + 643, 644, 3, 395, 197, 0, 644, 98, 1, 0, 0, + 0, 645, 646, 3, 385, 192, 0, 646, 647, 3, 367, + 183, 0, 647, 648, 3, 367, 183, 0, 648, 649, 3, + 393, 196, 0, 649, 650, 3, 365, 182, 0, 650, 651, + 3, 395, 197, 0, 651, 100, 1, 0, 0, 0, 652, + 653, 3, 395, 197, 0, 653, 654, 3, 365, 182, 0, + 654, 655, 3, 403, 201, 0, 655, 656, 3, 395, 197, + 0, 656, 657, 3, 379, 189, 0, 657, 658, 3, 373, + 186, 0, 658, 659, 3, 381, 190, 0, 659, 660, 3, + 373, 186, 0, 660, 661, 3, 395, 197, 0, 661, 102, + 1, 0, 0, 0, 662, 663, 3, 399, 199, 0, 663, + 664, 3, 357, 178, 0, 664, 665, 3, 379, 189, 0, + 665, 666, 3, 397, 198, 0, 666, 667, 3, 365, 182, + 0, 667, 668, 3, 393, 196, 0, 668, 104, 1, 0, + 0, 0, 669, 670, 3, 379, 189, 0, 670, 671, 3, + 385, 192, 0, 671, 672, 3, 357, 178, 0, 672, 673, + 3, 363, 181, 0, 673, 106, 1, 0, 0, 0, 674, + 675, 3, 393, 196, 0, 675, 676, 3, 373, 186, 0, + 676, 677, 3, 379, 189, 0, 677, 678, 3, 365, 182, + 0, 678, 679, 3, 383, 191, 0, 679, 680, 3, 395, + 197, 0, 680, 108, 1, 0, 0, 0, 681, 682, 3, + 373, 186, 0, 682, 683, 3, 383, 191, 0, 683, 684, + 3, 395, 197, 0, 684, 685, 3, 385, 192, 0, 685, + 110, 1, 0, 0, 0, 686, 687, 3, 361, 180, 0, + 687, 688, 3, 379, 189, 0, 688, 689, 3, 365, 182, + 0, 689, 690, 3, 357, 178, 0, 690, 691, 3, 391, + 195, 0, 691, 112, 1, 0, 0, 0, 692, 693, 3, + 363, 181, 0, 693, 694, 3, 391, 195, 0, 694, 695, + 3, 385, 192, 0, 695, 696, 3, 387, 193, 0, 696, + 114, 1, 0, 0, 0, 697, 698, 3, 361, 180, 0, + 698, 699, 3, 391, 195, 0, 699, 700, 3, 365, 182, + 0, 700, 701, 3, 357, 178, 0, 701, 702, 3, 395, + 197, 0, 702, 703, 3, 365, 182, 0, 703, 116, 1, + 0, 0, 0, 704, 705, 3, 357, 178, 0, 705, 706, + 3, 363, 181, 0, 706, 707, 3, 363, 181, 0, 707, + 118, 1, 0, 0, 0, 708, 709, 3, 395, 197, 0, + 709, 710, 3, 385, 192, 0, 710, 120, 1, 0, 0, + 0, 711, 712, 3, 363, 181, 0, 712, 713, 3, 357, + 178, 0, 713, 714, 3, 395, 197, 0, 714, 715, 3, + 357, 178, 0, 715, 122, 1, 0, 0, 0, 716, 717, + 3, 381, 190, 0, 717, 718, 3, 385, 192, 0, 718, + 719, 3, 399, 199, 0, 719, 720, 3, 365, 182, 0, + 720, 124, 1, 0, 0, 0, 721, 722, 3, 361, 180, + 0, 722, 723, 3, 385, 192, 0, 723, 724, 3, 387, + 193, 0, 724, 725, 3, 405, 202, 0, 725, 126, 1, + 0, 0, 0, 726, 727, 3, 373, 186, 0, 727, 728, + 3, 383, 191, 0, 728, 729, 3, 393, 196, 0, 729, + 730, 3, 365, 182, 0, 730, 731, 3, 391, 195, 0, + 731, 732, 3, 395, 197, 0, 732, 128, 1, 0, 0, + 0, 733, 734, 3, 363, 181, 0, 734, 735, 3, 365, + 182, 0, 735, 736, 3, 379, 189, 0, 736, 737, 3, + 365, 182, 0, 737, 738, 3, 395, 197, 0, 738, 739, + 3, 365, 182, 0, 739, 130, 1, 0, 0, 0, 740, + 741, 3, 401, 200, 0, 741, 742, 3, 373, 186, 0, + 742, 743, 3, 395, 197, 0, 743, 744, 3, 371, 185, + 0, 744, 132, 1, 0, 0, 0, 745, 746, 3, 397, + 198, 0, 746, 747, 3, 393, 196, 0, 747, 748, 3, + 373, 186, 0, 748, 749, 3, 383, 191, 0, 749, 750, + 3, 369, 184, 0, 750, 134, 1, 0, 0, 0, 751, + 752, 3, 363, 181, 0, 752, 753, 3, 365, 182, 0, + 753, 754, 3, 367, 183, 0, 754, 755, 3, 357, 178, + 0, 755, 756, 3, 397, 198, 0, 756, 757, 3, 379, + 189, 0, 757, 758, 3, 395, 197, 0, 758, 136, 1, + 0, 0, 0, 759, 760, 3, 369, 184, 0, 760, 761, + 3, 391, 195, 0, 761, 762, 3, 357, 178, 0, 762, + 763, 3, 387, 193, 0, 763, 764, 3, 371, 185, 0, + 764, 138, 1, 0, 0, 0, 765, 766, 3, 357, 178, + 0, 766, 767, 3, 379, 189, 0, 767, 768, 3, 379, + 189, 0, 768, 140, 1, 0, 0, 0, 769, 770, 3, + 385, 192, 0, 770, 771, 3, 387, 193, 0, 771, 772, + 3, 395, 197, 0, 772, 773, 3, 373, 186, 0, 773, + 774, 3, 385, 192, 0, 774, 775, 3, 383, 191, 0, + 775, 776, 3, 357, 178, 0, 776, 777, 3, 379, 189, + 0, 777, 142, 1, 0, 0, 0, 778, 779, 3, 393, + 196, 0, 779, 780, 3, 365, 182, 0, 780, 781, 3, + 391, 195, 0, 781, 782, 3, 399, 199, 0, 782, 783, + 3, 373, 186, 0, 783, 784, 3, 361, 180, 0, 784, + 785, 3, 365, 182, 0, 785, 144, 1, 0, 0, 0, + 786, 787, 3, 359, 179, 0, 787, 788, 3, 373, 186, + 0, 788, 789, 3, 383, 191, 0, 789, 790, 3, 363, + 181, 0, 790, 146, 1, 0, 0, 0, 791, 792, 3, + 397, 198, 0, 792, 793, 3, 383, 191, 0, 793, 794, + 3, 363, 181, 0, 794, 795, 3, 365, 182, 0, 795, + 796, 3, 367, 183, 0, 796, 148, 1, 0, 0, 0, + 797, 798, 3, 381, 190, 0, 798, 799, 3, 373, 186, + 0, 799, 800, 3, 383, 191, 0, 800, 801, 3, 397, + 198, 0, 801, 802, 3, 393, 196, 0, 802, 150, 1, + 0, 0, 0, 803, 804, 3, 397, 198, 0, 804, 805, + 3, 383, 191, 0, 805, 806, 3, 373, 186, 0, 806, + 807, 3, 385, 192, 0, 807, 808, 3, 383, 191, 0, + 808, 152, 1, 0, 0, 0, 809, 810, 3, 367, 183, + 0, 810, 811, 3, 373, 186, 0, 811, 812, 3, 379, + 189, 0, 812, 813, 3, 395, 197, 0, 813, 814, 3, + 365, 182, 0, 814, 815, 3, 391, 195, 0, 815, 154, + 1, 0, 0, 0, 816, 817, 3, 383, 191, 0, 817, + 818, 3, 385, 192, 0, 818, 819, 3, 395, 197, 0, + 819, 156, 1, 0, 0, 0, 820, 821, 3, 373, 186, + 0, 821, 822, 3, 383, 191, 0, 822, 158, 1, 0, + 0, 0, 823, 824, 3, 393, 196, 0, 824, 825, 3, + 395, 197, 0, 825, 826, 3, 391, 195, 0, 826, 160, + 1, 0, 0, 0, 827, 828, 3, 379, 189, 0, 828, + 829, 3, 357, 178, 0, 829, 830, 3, 383, 191, 0, + 830, 831, 3, 369, 184, 0, 831, 162, 1, 0, 0, + 0, 832, 833, 3, 379, 189, 0, 833, 834, 3, 357, + 178, 0, 834, 835, 3, 383, 191, 0, 835, 836, 3, + 369, 184, 0, 836, 837, 3, 381, 190, 0, 837, 838, + 3, 357, 178, 0, 838, 839, 3, 395, 197, 0, 839, + 840, 3, 361, 180, 0, 840, 841, 3, 371, 185, 0, + 841, 842, 3, 365, 182, 0, 842, 843, 3, 393, 196, + 0, 843, 164, 1, 0, 0, 0, 844, 845, 3, 363, + 181, 0, 845, 846, 3, 357, 178, 0, 846, 847, 3, + 395, 197, 0, 847, 848, 3, 357, 178, 0, 848, 849, + 3, 395, 197, 0, 849, 850, 3, 405, 202, 0, 850, + 851, 3, 387, 193, 0, 851, 852, 3, 365, 182, 0, + 852, 166, 1, 0, 0, 0, 853, 854, 3, 359, 179, + 0, 854, 855, 3, 385, 192, 0, 855, 856, 3, 397, + 198, 0, 856, 857, 3, 383, 191, 0, 857, 858, 3, + 363, 181, 0, 858, 168, 1, 0, 0, 0, 859, 860, + 3, 373, 186, 0, 860, 861, 3, 391, 195, 0, 861, + 862, 3, 373, 186, 0, 862, 170, 1, 0, 0, 0, + 863, 864, 3, 397, 198, 0, 864, 865, 3, 391, 195, + 0, 865, 866, 3, 373, 186, 0, 866, 172, 1, 0, + 0, 0, 867, 868, 3, 359, 179, 0, 868, 869, 3, + 383, 191, 0, 869, 870, 3, 385, 192, 0, 870, 871, + 3, 363, 181, 0, 871, 872, 3, 365, 182, 0, 872, + 174, 1, 0, 0, 0, 873, 874, 3, 391, 195, 0, + 874, 875, 3, 357, 178, 0, 875, 876, 3, 383, 191, + 0, 876, 877, 3, 363, 181, 0, 877, 176, 1, 0, + 0, 0, 878, 879, 3, 357, 178, 0, 879, 880, 3, + 359, 179, 0, 880, 881, 3, 393, 196, 0, 881, 178, + 1, 0, 0, 0, 882, 883, 3, 361, 180, 0, 883, + 884, 3, 365, 182, 0, 884, 885, 3, 373, 186, 0, + 885, 886, 3, 379, 189, 0, 886, 180, 1, 0, 0, + 0, 887, 888, 3, 367, 183, 0, 888, 889, 3, 379, + 189, 0, 889, 890, 3, 385, 192, 0, 890, 891, 3, + 385, 192, 0, 891, 892, 3, 391, 195, 0, 892, 182, + 1, 0, 0, 0, 893, 894, 3, 391, 195, 0, 894, + 895, 3, 385, 192, 0, 895, 896, 3, 397, 198, 0, + 896, 897, 3, 383, 191, 0, 897, 898, 3, 363, 181, + 0, 898, 184, 1, 0, 0, 0, 899, 900, 3, 361, + 180, 0, 900, 901, 3, 385, 192, 0, 901, 902, 3, + 383, 191, 0, 902, 903, 3, 361, 180, 0, 903, 904, + 3, 357, 178, 0, 904, 905, 3, 395, 197, 0, 905, + 186, 1, 0, 0, 0, 906, 907, 3, 393, 196, 0, + 907, 908, 3, 395, 197, 0, 908, 909, 3, 391, 195, + 0, 909, 910, 3, 379, 189, 0, 910, 911, 3, 365, + 182, 0, 911, 912, 3, 383, 191, 0, 912, 188, 1, + 0, 0, 0, 913, 914, 3, 397, 198, 0, 914, 915, + 3, 361, 180, 0, 915, 916, 3, 357, 178, 0, 916, + 917, 3, 393, 196, 0, 917, 918, 3, 365, 182, 0, + 918, 190, 1, 0, 0, 0, 919, 920, 3, 379, 189, + 0, 920, 921, 3, 361, 180, 0, 921, 922, 3, 357, + 178, 0, 922, 923, 3, 393, 196, 0, 923, 924, 3, + 365, 182, 0, 924, 192, 1, 0, 0, 0, 925, 926, + 3, 365, 182, 0, 926, 927, 3, 383, 191, 0, 927, + 928, 3, 361, 180, 0, 928, 929, 3, 385, 192, 0, + 929, 930, 3, 363, 181, 0, 930, 931, 3, 365, 182, + 0, 931, 932, 5, 95, 0, 0, 932, 933, 3, 367, + 183, 0, 933, 934, 3, 385, 192, 0, 934, 935, 3, + 391, 195, 0, 935, 936, 5, 95, 0, 0, 936, 937, + 3, 397, 198, 0, 937, 938, 3, 391, 195, 0, 938, + 939, 3, 373, 186, 0, 939, 194, 1, 0, 0, 0, + 940, 941, 3, 367, 183, 0, 941, 942, 3, 385, 192, + 0, 942, 943, 3, 391, 195, 0, 943, 196, 1, 0, + 0, 0, 944, 945, 3, 361, 180, 0, 945, 946, 3, + 385, 192, 0, 946, 947, 3, 383, 191, 0, 947, 948, + 3, 395, 197, 0, 948, 949, 3, 357, 178, 0, 949, + 950, 3, 373, 186, 0, 950, 951, 3, 383, 191, 0, + 951, 952, 3, 393, 196, 0, 952, 198, 1, 0, 0, + 0, 953, 954, 3, 393, 196, 0, 954, 955, 3, 395, + 197, 0, 955, 956, 3, 391, 195, 0, 956, 957, 3, + 393, 196, 0, 957, 958, 3, 395, 197, 0, 958, 959, + 3, 357, 178, 0, 959, 960, 3, 391, 195, 0, 960, + 961, 3, 395, 197, 0, 961, 962, 3, 393, 196, 0, + 962, 200, 1, 0, 0, 0, 963, 964, 3, 393, 196, + 0, 964, 965, 3, 395, 197, 0, 965, 966, 3, 391, + 195, 0, 966, 967, 3, 365, 182, 0, 967, 968, 3, + 383, 191, 0, 968, 969, 3, 363, 181, 0, 969, 970, + 3, 393, 196, 0, 970, 202, 1, 0, 0, 0, 971, + 972, 3, 393, 196, 0, 972, 973, 3, 395, 197, 0, + 973, 974, 3, 391, 195, 0, 974, 975, 3, 359, 179, + 0, 975, 976, 3, 365, 182, 0, 976, 977, 3, 367, + 183, 0, 977, 978, 3, 385, 192, 0, 978, 979, 3, + 391, 195, 0, 979, 980, 3, 365, 182, 0, 980, 204, + 1, 0, 0, 0, 981, 982, 3, 393, 196, 0, 982, + 983, 3, 395, 197, 0, 983, 984, 3, 391, 195, 0, + 984, 985, 3, 357, 178, 0, 985, 986, 3, 367, 183, + 0, 986, 987, 3, 395, 197, 0, 987, 988, 3, 365, + 182, 0, 988, 989, 3, 391, 195, 0, 989, 206, 1, + 0, 0, 0, 990, 991, 3, 405, 202, 0, 991, 992, + 3, 365, 182, 0, 992, 993, 3, 357, 178, 0, 993, + 994, 3, 391, 195, 0, 994, 208, 1, 0, 0, 0, + 995, 996, 3, 381, 190, 0, 996, 997, 3, 385, 192, + 0, 997, 998, 3, 383, 191, 0, 998, 999, 3, 395, + 197, 0, 999, 1000, 3, 371, 185, 0, 1000, 210, 1, + 0, 0, 0, 1001, 1002, 3, 363, 181, 0, 1002, 1003, + 3, 357, 178, 0, 1003, 1004, 3, 405, 202, 0, 1004, + 212, 1, 0, 0, 0, 1005, 1006, 3, 371, 185, 0, + 1006, 1007, 3, 385, 192, 0, 1007, 1008, 3, 397, 198, + 0, 1008, 1009, 3, 391, 195, 0, 1009, 1010, 3, 393, + 196, 0, 1010, 214, 1, 0, 0, 0, 1011, 1012, 3, + 381, 190, 0, 1012, 1013, 3, 373, 186, 0, 1013, 1014, + 3, 383, 191, 0, 1014, 1015, 3, 397, 198, 0, 1015, + 1016, 3, 395, 197, 0, 1016, 1017, 3, 365, 182, 0, + 1017, 1018, 3, 393, 196, 0, 1018, 216, 1, 0, 0, + 0, 1019, 1020, 3, 393, 196, 0, 1020, 1021, 3, 365, + 182, 0, 1021, 1022, 3, 361, 180, 0, 1022, 1023, 3, + 385, 192, 0, 1023, 1024, 3, 383, 191, 0, 1024, 1025, + 3, 363, 181, 0, 1025, 1026, 3, 393, 196, 0, 1026, + 218, 1, 0, 0, 0, 1027, 1028, 3, 395, 197, 0, + 1028, 1029, 3, 373, 186, 0, 1029, 1030, 3, 381, 190, + 0, 1030, 1031, 3, 365, 182, 0, 1031, 1032, 3, 407, + 203, 0, 1032, 1033, 3, 385, 192, 0, 1033, 1034, 3, + 383, 191, 0, 1034, 1035, 3, 365, 182, 0, 1035, 220, + 1, 0, 0, 0, 1036, 1037, 3, 395, 197, 0, 1037, + 1038, 3, 407, 203, 0, 1038, 222, 1, 0, 0, 0, + 1039, 1040, 3, 383, 191, 0, 1040, 1041, 3, 385, 192, + 0, 1041, 1042, 3, 401, 200, 0, 1042, 224, 1, 0, + 0, 0, 1043, 1044, 3, 397, 198, 0, 1044, 1045, 3, + 397, 198, 0, 1045, 1046, 3, 373, 186, 0, 1046, 1047, + 3, 363, 181, 0, 1047, 226, 1, 0, 0, 0, 1048, + 1049, 3, 393, 196, 0, 1049, 1050, 3, 395, 197, 0, + 1050, 1051, 3, 391, 195, 0, 1051, 1052, 3, 397, 198, + 0, 1052, 1053, 3, 397, 198, 0, 1053, 1054, 3, 373, + 186, 0, 1054, 1055, 3, 363, 181, 0, 1055, 228, 1, + 0, 0, 0, 1056, 1057, 3, 393, 196, 0, 1057, 1058, + 3, 371, 185, 0, 1058, 1059, 3, 357, 178, 0, 1059, + 1060, 5, 49, 0, 0, 1060, 230, 1, 0, 0, 0, + 1061, 1062, 3, 393, 196, 0, 1062, 1063, 3, 371, 185, + 0, 1063, 1064, 3, 357, 178, 0, 1064, 1065, 5, 50, + 0, 0, 1065, 1066, 5, 53, 0, 0, 1066, 1067, 5, + 54, 0, 0, 1067, 232, 1, 0, 0, 0, 1068, 1069, + 3, 393, 196, 0, 1069, 1070, 3, 371, 185, 0, 1070, + 1071, 3, 357, 178, 0, 1071, 1072, 5, 51, 0, 0, + 1072, 1073, 5, 56, 0, 0, 1073, 1074, 5, 52, 0, + 0, 1074, 234, 1, 0, 0, 0, 1075, 1076, 3, 393, + 196, 0, 1076, 1077, 3, 371, 185, 0, 1077, 1078, 3, + 357, 178, 0, 1078, 1079, 5, 53, 0, 0, 1079, 1080, + 5, 49, 0, 0, 1080, 1081, 5, 50, 0, 0, 1081, + 236, 1, 0, 0, 0, 1082, 1083, 3, 381, 190, 0, + 1083, 1084, 3, 363, 181, 0, 1084, 1085, 5, 53, 0, + 0, 1085, 238, 1, 0, 0, 0, 1086, 1087, 3, 361, + 180, 0, 1087, 1088, 3, 385, 192, 0, 1088, 1089, 3, + 357, 178, 0, 1089, 1090, 3, 379, 189, 0, 1090, 1091, + 3, 365, 182, 0, 1091, 1092, 3, 393, 196, 0, 1092, + 1093, 3, 361, 180, 0, 1093, 1094, 3, 365, 182, 0, + 1094, 240, 1, 0, 0, 0, 1095, 1096, 3, 373, 186, + 0, 1096, 1097, 3, 367, 183, 0, 1097, 242, 1, 0, + 0, 0, 1098, 1099, 3, 393, 196, 0, 1099, 1100, 3, + 395, 197, 0, 1100, 1101, 3, 391, 195, 0, 1101, 1102, + 3, 379, 189, 0, 1102, 1103, 3, 357, 178, 0, 1103, + 1104, 3, 383, 191, 0, 1104, 1105, 3, 369, 184, 0, + 1105, 244, 1, 0, 0, 0, 1106, 1107, 3, 393, 196, + 0, 1107, 1108, 3, 395, 197, 0, 1108, 1109, 3, 391, + 195, 0, 1109, 1110, 3, 363, 181, 0, 1110, 1111, 3, + 395, 197, 0, 1111, 246, 1, 0, 0, 0, 1112, 1113, + 3, 393, 196, 0, 1113, 1114, 3, 357, 178, 0, 1114, + 1115, 3, 381, 190, 0, 1115, 1116, 3, 365, 182, 0, + 1116, 1117, 3, 395, 197, 0, 1117, 1118, 3, 365, 182, + 0, 1118, 1119, 3, 391, 195, 0, 1119, 1120, 3, 381, + 190, 0, 1120, 248, 1, 0, 0, 0, 1121, 1122, 3, + 373, 186, 0, 1122, 1123, 3, 393, 196, 0, 1123, 1124, + 3, 373, 186, 0, 1124, 1125, 3, 391, 195, 0, 1125, + 1126, 3, 373, 186, 0, 1126, 250, 1, 0, 0, 0, + 1127, 1128, 3, 373, 186, 0, 1128, 1129, 3, 393, 196, + 0, 1129, 1130, 3, 397, 198, 0, 1130, 1131, 3, 391, + 195, 0, 1131, 1132, 3, 373, 186, 0, 1132, 252, 1, + 0, 0, 0, 1133, 1134, 3, 373, 186, 0, 1134, 1135, + 3, 393, 196, 0, 1135, 1136, 3, 359, 179, 0, 1136, + 1137, 3, 379, 189, 0, 1137, 1138, 3, 357, 178, 0, + 1138, 1139, 3, 383, 191, 0, 1139, 1140, 3, 377, 188, + 0, 1140, 254, 1, 0, 0, 0, 1141, 1142, 3, 373, + 186, 0, 1142, 1143, 3, 393, 196, 0, 1143, 1144, 3, + 379, 189, 0, 1144, 1145, 3, 373, 186, 0, 1145, 1146, + 3, 395, 197, 0, 1146, 1147, 3, 365, 182, 0, 1147, + 1148, 3, 391, 195, 0, 1148, 1149, 3, 357, 178, 0, + 1149, 1150, 3, 379, 189, 0, 1150, 256, 1, 0, 0, + 0, 1151, 1152, 3, 373, 186, 0, 1152, 1153, 3, 393, + 196, 0, 1153, 1154, 3, 383, 191, 0, 1154, 1155, 3, + 397, 198, 0, 1155, 1156, 3, 381, 190, 0, 1156, 1157, + 3, 365, 182, 0, 1157, 1158, 3, 391, 195, 0, 1158, + 1159, 3, 373, 186, 0, 1159, 1160, 3, 361, 180, 0, + 1160, 258, 1, 0, 0, 0, 1161, 1162, 3, 391, 195, + 0, 1162, 1163, 3, 365, 182, 0, 1163, 1164, 3, 369, + 184, 0, 1164, 1165, 3, 365, 182, 0, 1165, 1166, 3, + 403, 201, 0, 1166, 260, 1, 0, 0, 0, 1167, 1168, + 3, 393, 196, 0, 1168, 1169, 3, 397, 198, 0, 1169, + 1170, 3, 359, 179, 0, 1170, 1171, 3, 393, 196, 0, + 1171, 1172, 3, 395, 197, 0, 1172, 1173, 3, 391, 195, + 0, 1173, 262, 1, 0, 0, 0, 1174, 1175, 3, 391, + 195, 0, 1175, 1176, 3, 365, 182, 0, 1176, 1177, 3, + 387, 193, 0, 1177, 1178, 3, 379, 189, 0, 1178, 1179, + 3, 357, 178, 0, 1179, 1180, 3, 361, 180, 0, 1180, + 1181, 3, 365, 182, 0, 1181, 264, 1, 0, 0, 0, + 1182, 1183, 3, 365, 182, 0, 1183, 1184, 3, 403, 201, + 0, 1184, 1185, 3, 373, 186, 0, 1185, 1186, 3, 393, + 196, 0, 1186, 1187, 3, 395, 197, 0, 1187, 1188, 3, + 393, 196, 0, 1188, 266, 1, 0, 0, 0, 1189, 1190, + 3, 361, 180, 0, 1190, 1191, 3, 385, 192, 0, 1191, + 1192, 3, 397, 198, 0, 1192, 1193, 3, 383, 191, 0, + 1193, 1194, 3, 395, 197, 0, 1194, 268, 1, 0, 0, + 0, 1195, 1196, 3, 393, 196, 0, 1196, 1197, 3, 397, + 198, 0, 1197, 1198, 3, 381, 190, 0, 1198, 270, 1, + 0, 0, 0, 1199, 1200, 3, 381, 190, 0, 1200, 1201, + 3, 373, 186, 0, 1201, 1202, 3, 383, 191, 0, 1202, + 272, 1, 0, 0, 0, 1203, 1204, 3, 381, 190, 0, + 1204, 1205, 3, 357, 178, 0, 1205, 1206, 3, 403, 201, + 0, 1206, 274, 1, 0, 0, 0, 1207, 1208, 3, 357, + 178, 0, 1208, 1209, 3, 399, 199, 0, 1209, 1210, 3, + 369, 184, 0, 1210, 276, 1, 0, 0, 0, 1211, 1212, + 3, 393, 196, 0, 1212, 1213, 3, 357, 178, 0, 1213, + 1214, 3, 381, 190, 0, 1214, 1215, 3, 387, 193, 0, + 1215, 1216, 3, 379, 189, 0, 1216, 1217, 3, 365, 182, + 0, 1217, 278, 1, 0, 0, 0, 1218, 1219, 3, 393, + 196, 0, 1219, 1220, 3, 365, 182, 0, 1220, 1221, 3, + 387, 193, 0, 1221, 1222, 3, 357, 178, 0, 1222, 1223, + 3, 391, 195, 0, 1223, 1224, 3, 357, 178, 0, 1224, + 1225, 3, 395, 197, 0, 1225, 1226, 3, 385, 192, 0, + 1226, 1227, 3, 391, 195, 0, 1227, 280, 1, 0, 0, + 0, 1228, 1232, 5, 60, 0, 0, 1229, 1231, 8, 0, + 0, 0, 1230, 1229, 1, 0, 0, 0, 1231, 1234, 1, + 0, 0, 0, 1232, 1230, 1, 0, 0, 0, 1232, 1233, + 1, 0, 0, 0, 1233, 1235, 1, 0, 0, 0, 1234, + 1232, 1, 0, 0, 0, 1235, 1236, 5, 62, 0, 0, + 1236, 282, 1, 0, 0, 0, 1237, 1239, 3, 337, 168, + 0, 1238, 1237, 1, 0, 0, 0, 1238, 1239, 1, 0, + 0, 0, 1239, 1240, 1, 0, 0, 0, 1240, 1241, 5, + 58, 0, 0, 1241, 284, 1, 0, 0, 0, 1242, 1243, + 3, 283, 141, 0, 1243, 1244, 3, 339, 169, 0, 1244, + 286, 1, 0, 0, 0, 1245, 1246, 5, 95, 0, 0, + 1246, 1247, 5, 58, 0, 0, 1247, 1250, 1, 0, 0, + 0, 1248, 1251, 3, 331, 165, 0, 1249, 1251, 3, 351, + 175, 0, 1250, 1248, 1, 0, 0, 0, 1250, 1249, 1, + 0, 0, 0, 1251, 1260, 1, 0, 0, 0, 1252, 1255, + 3, 335, 167, 0, 1253, 1255, 5, 46, 0, 0, 1254, + 1252, 1, 0, 0, 0, 1254, 1253, 1, 0, 0, 0, + 1255, 1258, 1, 0, 0, 0, 1256, 1254, 1, 0, 0, + 0, 1256, 1257, 1, 0, 0, 0, 1257, 1259, 1, 0, + 0, 0, 1258, 1256, 1, 0, 0, 0, 1259, 1261, 3, + 335, 167, 0, 1260, 1256, 1, 0, 0, 0, 1260, 1261, + 1, 0, 0, 0, 1261, 288, 1, 0, 0, 0, 1262, + 1263, 5, 63, 0, 0, 1263, 1264, 3, 333, 166, 0, + 1264, 290, 1, 0, 0, 0, 1265, 1266, 5, 36, 0, + 0, 1266, 1267, 3, 333, 166, 0, 1267, 292, 1, 0, + 0, 0, 1268, 1270, 5, 64, 0, 0, 1269, 1271, 7, + 1, 0, 0, 1270, 1269, 1, 0, 0, 0, 1271, 1272, + 1, 0, 0, 0, 1272, 1270, 1, 0, 0, 0, 1272, + 1273, 1, 0, 0, 0, 1273, 1283, 1, 0, 0, 0, + 1274, 1277, 5, 45, 0, 0, 1275, 1278, 7, 1, 0, + 0, 1276, 1278, 3, 351, 175, 0, 1277, 1275, 1, 0, + 0, 0, 1277, 1276, 1, 0, 0, 0, 1278, 1279, 1, + 0, 0, 0, 1279, 1277, 1, 0, 0, 0, 1279, 1280, + 1, 0, 0, 0, 1280, 1282, 1, 0, 0, 0, 1281, + 1274, 1, 0, 0, 0, 1282, 1285, 1, 0, 0, 0, + 1283, 1281, 1, 0, 0, 0, 1283, 1284, 1, 0, 0, + 0, 1284, 294, 1, 0, 0, 0, 1285, 1283, 1, 0, + 0, 0, 1286, 1287, 3, 293, 146, 0, 1287, 1288, 5, + 64, 0, 0, 1288, 296, 1, 0, 0, 0, 1289, 1291, + 3, 351, 175, 0, 1290, 1289, 1, 0, 0, 0, 1291, + 1292, 1, 0, 0, 0, 1292, 1290, 1, 0, 0, 0, + 1292, 1293, 1, 0, 0, 0, 1293, 298, 1, 0, 0, + 0, 1294, 1296, 3, 351, 175, 0, 1295, 1294, 1, 0, + 0, 0, 1296, 1299, 1, 0, 0, 0, 1297, 1295, 1, + 0, 0, 0, 1297, 1298, 1, 0, 0, 0, 1298, 1300, + 1, 0, 0, 0, 1299, 1297, 1, 0, 0, 0, 1300, + 1302, 5, 46, 0, 0, 1301, 1303, 3, 351, 175, 0, + 1302, 1301, 1, 0, 0, 0, 1303, 1304, 1, 0, 0, + 0, 1304, 1302, 1, 0, 0, 0, 1304, 1305, 1, 0, + 0, 0, 1305, 300, 1, 0, 0, 0, 1306, 1308, 3, + 351, 175, 0, 1307, 1306, 1, 0, 0, 0, 1308, 1309, + 1, 0, 0, 0, 1309, 1307, 1, 0, 0, 0, 1309, + 1310, 1, 0, 0, 0, 1310, 1311, 1, 0, 0, 0, + 1311, 1315, 5, 46, 0, 0, 1312, 1314, 3, 351, 175, + 0, 1313, 1312, 1, 0, 0, 0, 1314, 1317, 1, 0, + 0, 0, 1315, 1313, 1, 0, 0, 0, 1315, 1316, 1, + 0, 0, 0, 1316, 1318, 1, 0, 0, 0, 1317, 1315, + 1, 0, 0, 0, 1318, 1319, 3, 315, 157, 0, 1319, + 1336, 1, 0, 0, 0, 1320, 1322, 5, 46, 0, 0, + 1321, 1323, 3, 351, 175, 0, 1322, 1321, 1, 0, 0, + 0, 1323, 1324, 1, 0, 0, 0, 1324, 1322, 1, 0, + 0, 0, 1324, 1325, 1, 0, 0, 0, 1325, 1326, 1, + 0, 0, 0, 1326, 1327, 3, 315, 157, 0, 1327, 1336, + 1, 0, 0, 0, 1328, 1330, 3, 351, 175, 0, 1329, + 1328, 1, 0, 0, 0, 1330, 1331, 1, 0, 0, 0, + 1331, 1329, 1, 0, 0, 0, 1331, 1332, 1, 0, 0, + 0, 1332, 1333, 1, 0, 0, 0, 1333, 1334, 3, 315, + 157, 0, 1334, 1336, 1, 0, 0, 0, 1335, 1307, 1, + 0, 0, 0, 1335, 1320, 1, 0, 0, 0, 1335, 1329, + 1, 0, 0, 0, 1336, 302, 1, 0, 0, 0, 1337, + 1338, 5, 43, 0, 0, 1338, 1339, 3, 297, 148, 0, + 1339, 304, 1, 0, 0, 0, 1340, 1341, 5, 43, 0, + 0, 1341, 1342, 3, 299, 149, 0, 1342, 306, 1, 0, + 0, 0, 1343, 1344, 5, 43, 0, 0, 1344, 1345, 3, + 301, 150, 0, 1345, 308, 1, 0, 0, 0, 1346, 1347, + 5, 45, 0, 0, 1347, 1348, 3, 297, 148, 0, 1348, + 310, 1, 0, 0, 0, 1349, 1350, 5, 45, 0, 0, + 1350, 1351, 3, 299, 149, 0, 1351, 312, 1, 0, 0, + 0, 1352, 1353, 5, 45, 0, 0, 1353, 1354, 3, 301, + 150, 0, 1354, 314, 1, 0, 0, 0, 1355, 1357, 7, + 2, 0, 0, 1356, 1358, 7, 3, 0, 0, 1357, 1356, + 1, 0, 0, 0, 1357, 1358, 1, 0, 0, 0, 1358, + 1360, 1, 0, 0, 0, 1359, 1361, 3, 351, 175, 0, + 1360, 1359, 1, 0, 0, 0, 1361, 1362, 1, 0, 0, + 0, 1362, 1360, 1, 0, 0, 0, 1362, 1363, 1, 0, + 0, 0, 1363, 316, 1, 0, 0, 0, 1364, 1369, 5, + 39, 0, 0, 1365, 1368, 8, 4, 0, 0, 1366, 1368, + 3, 325, 162, 0, 1367, 1365, 1, 0, 0, 0, 1367, + 1366, 1, 0, 0, 0, 1368, 1371, 1, 0, 0, 0, + 1369, 1367, 1, 0, 0, 0, 1369, 1370, 1, 0, 0, + 0, 1370, 1372, 1, 0, 0, 0, 1371, 1369, 1, 0, + 0, 0, 1372, 1373, 5, 39, 0, 0, 1373, 318, 1, + 0, 0, 0, 1374, 1379, 5, 34, 0, 0, 1375, 1378, + 8, 5, 0, 0, 1376, 1378, 3, 325, 162, 0, 1377, + 1375, 1, 0, 0, 0, 1377, 1376, 1, 0, 0, 0, + 1378, 1381, 1, 0, 0, 0, 1379, 1377, 1, 0, 0, + 0, 1379, 1380, 1, 0, 0, 0, 1380, 1382, 1, 0, + 0, 0, 1381, 1379, 1, 0, 0, 0, 1382, 1383, 5, + 34, 0, 0, 1383, 320, 1, 0, 0, 0, 1384, 1385, + 5, 39, 0, 0, 1385, 1386, 5, 39, 0, 0, 1386, + 1387, 5, 39, 0, 0, 1387, 1399, 1, 0, 0, 0, + 1388, 1392, 5, 39, 0, 0, 1389, 1390, 5, 39, 0, + 0, 1390, 1392, 5, 39, 0, 0, 1391, 1388, 1, 0, + 0, 0, 1391, 1389, 1, 0, 0, 0, 1391, 1392, 1, + 0, 0, 0, 1392, 1395, 1, 0, 0, 0, 1393, 1396, + 8, 6, 0, 0, 1394, 1396, 3, 325, 162, 0, 1395, + 1393, 1, 0, 0, 0, 1395, 1394, 1, 0, 0, 0, + 1396, 1398, 1, 0, 0, 0, 1397, 1391, 1, 0, 0, + 0, 1398, 1401, 1, 0, 0, 0, 1399, 1397, 1, 0, + 0, 0, 1399, 1400, 1, 0, 0, 0, 1400, 1402, 1, + 0, 0, 0, 1401, 1399, 1, 0, 0, 0, 1402, 1403, + 5, 39, 0, 0, 1403, 1404, 5, 39, 0, 0, 1404, + 1405, 5, 39, 0, 0, 1405, 322, 1, 0, 0, 0, + 1406, 1407, 5, 34, 0, 0, 1407, 1408, 5, 34, 0, + 0, 1408, 1409, 5, 34, 0, 0, 1409, 1421, 1, 0, + 0, 0, 1410, 1414, 5, 34, 0, 0, 1411, 1412, 5, + 34, 0, 0, 1412, 1414, 5, 34, 0, 0, 1413, 1410, + 1, 0, 0, 0, 1413, 1411, 1, 0, 0, 0, 1413, + 1414, 1, 0, 0, 0, 1414, 1417, 1, 0, 0, 0, + 1415, 1418, 8, 7, 0, 0, 1416, 1418, 3, 325, 162, + 0, 1417, 1415, 1, 0, 0, 0, 1417, 1416, 1, 0, + 0, 0, 1418, 1420, 1, 0, 0, 0, 1419, 1413, 1, + 0, 0, 0, 1420, 1423, 1, 0, 0, 0, 1421, 1419, + 1, 0, 0, 0, 1421, 1422, 1, 0, 0, 0, 1422, + 1424, 1, 0, 0, 0, 1423, 1421, 1, 0, 0, 0, + 1424, 1425, 5, 34, 0, 0, 1425, 1426, 5, 34, 0, + 0, 1426, 1427, 5, 34, 0, 0, 1427, 324, 1, 0, + 0, 0, 1428, 1429, 5, 92, 0, 0, 1429, 1430, 7, + 8, 0, 0, 1430, 326, 1, 0, 0, 0, 1431, 1435, + 5, 40, 0, 0, 1432, 1434, 3, 353, 176, 0, 1433, + 1432, 1, 0, 0, 0, 1434, 1437, 1, 0, 0, 0, + 1435, 1433, 1, 0, 0, 0, 1435, 1436, 1, 0, 0, + 0, 1436, 1438, 1, 0, 0, 0, 1437, 1435, 1, 0, + 0, 0, 1438, 1439, 5, 41, 0, 0, 1439, 328, 1, + 0, 0, 0, 1440, 1444, 5, 91, 0, 0, 1441, 1443, + 3, 353, 176, 0, 1442, 1441, 1, 0, 0, 0, 1443, + 1446, 1, 0, 0, 0, 1444, 1442, 1, 0, 0, 0, + 1444, 1445, 1, 0, 0, 0, 1445, 1447, 1, 0, 0, + 0, 1446, 1444, 1, 0, 0, 0, 1447, 1448, 5, 93, + 0, 0, 1448, 330, 1, 0, 0, 0, 1449, 1452, 3, + 349, 174, 0, 1450, 1452, 5, 95, 0, 0, 1451, 1449, + 1, 0, 0, 0, 1451, 1450, 1, 0, 0, 0, 1452, + 332, 1, 0, 0, 0, 1453, 1456, 3, 331, 165, 0, + 1454, 1456, 3, 351, 175, 0, 1455, 1453, 1, 0, 0, + 0, 1455, 1454, 1, 0, 0, 0, 1456, 1462, 1, 0, + 0, 0, 1457, 1461, 3, 331, 165, 0, 1458, 1461, 3, + 351, 175, 0, 1459, 1461, 7, 9, 0, 0, 1460, 1457, + 1, 0, 0, 0, 1460, 1458, 1, 0, 0, 0, 1460, + 1459, 1, 0, 0, 0, 1461, 1464, 1, 0, 0, 0, + 1462, 1460, 1, 0, 0, 0, 1462, 1463, 1, 0, 0, + 0, 1463, 334, 1, 0, 0, 0, 1464, 1462, 1, 0, + 0, 0, 1465, 1470, 3, 331, 165, 0, 1466, 1470, 5, + 45, 0, 0, 1467, 1470, 3, 351, 175, 0, 1468, 1470, + 7, 9, 0, 0, 1469, 1465, 1, 0, 0, 0, 1469, + 1466, 1, 0, 0, 0, 1469, 1467, 1, 0, 0, 0, + 1469, 1468, 1, 0, 0, 0, 1470, 336, 1, 0, 0, + 0, 1471, 1480, 3, 349, 174, 0, 1472, 1475, 3, 335, + 167, 0, 1473, 1475, 5, 46, 0, 0, 1474, 1472, 1, + 0, 0, 0, 1474, 1473, 1, 0, 0, 0, 1475, 1478, + 1, 0, 0, 0, 1476, 1474, 1, 0, 0, 0, 1476, + 1477, 1, 0, 0, 0, 1477, 1479, 1, 0, 0, 0, + 1478, 1476, 1, 0, 0, 0, 1479, 1481, 3, 335, 167, + 0, 1480, 1476, 1, 0, 0, 0, 1480, 1481, 1, 0, + 0, 0, 1481, 338, 1, 0, 0, 0, 1482, 1487, 3, + 331, 165, 0, 1483, 1487, 5, 58, 0, 0, 1484, 1487, + 3, 351, 175, 0, 1485, 1487, 3, 341, 170, 0, 1486, + 1482, 1, 0, 0, 0, 1486, 1483, 1, 0, 0, 0, + 1486, 1484, 1, 0, 0, 0, 1486, 1485, 1, 0, 0, + 0, 1487, 1501, 1, 0, 0, 0, 1488, 1492, 3, 335, + 167, 0, 1489, 1492, 7, 10, 0, 0, 1490, 1492, 3, + 341, 170, 0, 1491, 1488, 1, 0, 0, 0, 1491, 1489, + 1, 0, 0, 0, 1491, 1490, 1, 0, 0, 0, 1492, + 1495, 1, 0, 0, 0, 1493, 1491, 1, 0, 0, 0, + 1493, 1494, 1, 0, 0, 0, 1494, 1499, 1, 0, 0, + 0, 1495, 1493, 1, 0, 0, 0, 1496, 1500, 3, 335, + 167, 0, 1497, 1500, 5, 58, 0, 0, 1498, 1500, 3, + 341, 170, 0, 1499, 1496, 1, 0, 0, 0, 1499, 1497, + 1, 0, 0, 0, 1499, 1498, 1, 0, 0, 0, 1500, + 1502, 1, 0, 0, 0, 1501, 1493, 1, 0, 0, 0, + 1501, 1502, 1, 0, 0, 0, 1502, 340, 1, 0, 0, + 0, 1503, 1506, 3, 343, 171, 0, 1504, 1506, 3, 347, + 173, 0, 1505, 1503, 1, 0, 0, 0, 1505, 1504, 1, + 0, 0, 0, 1506, 342, 1, 0, 0, 0, 1507, 1508, + 5, 37, 0, 0, 1508, 1509, 3, 345, 172, 0, 1509, + 1510, 3, 345, 172, 0, 1510, 344, 1, 0, 0, 0, + 1511, 1514, 3, 351, 175, 0, 1512, 1514, 7, 11, 0, + 0, 1513, 1511, 1, 0, 0, 0, 1513, 1512, 1, 0, + 0, 0, 1514, 346, 1, 0, 0, 0, 1515, 1516, 5, + 92, 0, 0, 1516, 1517, 7, 12, 0, 0, 1517, 348, + 1, 0, 0, 0, 1518, 1519, 7, 13, 0, 0, 1519, + 350, 1, 0, 0, 0, 1520, 1521, 2, 48, 57, 0, + 1521, 352, 1, 0, 0, 0, 1522, 1524, 7, 14, 0, + 0, 1523, 1522, 1, 0, 0, 0, 1524, 1525, 1, 0, + 0, 0, 1525, 1523, 1, 0, 0, 0, 1525, 1526, 1, + 0, 0, 0, 1526, 1527, 1, 0, 0, 0, 1527, 1528, + 6, 176, 0, 0, 1528, 354, 1, 0, 0, 0, 1529, + 1533, 5, 35, 0, 0, 1530, 1532, 8, 15, 0, 0, + 1531, 1530, 1, 0, 0, 0, 1532, 1535, 1, 0, 0, + 0, 1533, 1531, 1, 0, 0, 0, 1533, 1534, 1, 0, + 0, 0, 1534, 1536, 1, 0, 0, 0, 1535, 1533, 1, + 0, 0, 0, 1536, 1537, 6, 177, 0, 0, 1537, 356, + 1, 0, 0, 0, 1538, 1539, 7, 16, 0, 0, 1539, + 358, 1, 0, 0, 0, 1540, 1541, 7, 17, 0, 0, + 1541, 360, 1, 0, 0, 0, 1542, 1543, 7, 18, 0, + 0, 1543, 362, 1, 0, 0, 0, 1544, 1545, 7, 19, + 0, 0, 1545, 364, 1, 0, 0, 0, 1546, 1547, 7, + 2, 0, 0, 1547, 366, 1, 0, 0, 0, 1548, 1549, + 7, 20, 0, 0, 1549, 368, 1, 0, 0, 0, 1550, + 1551, 7, 21, 0, 0, 1551, 370, 1, 0, 0, 0, + 1552, 1553, 7, 22, 0, 0, 1553, 372, 1, 0, 0, + 0, 1554, 1555, 7, 23, 0, 0, 1555, 374, 1, 0, + 0, 0, 1556, 1557, 7, 24, 0, 0, 1557, 376, 1, + 0, 0, 0, 1558, 1559, 7, 25, 0, 0, 1559, 378, + 1, 0, 0, 0, 1560, 1561, 7, 26, 0, 0, 1561, + 380, 1, 0, 0, 0, 1562, 1563, 7, 27, 0, 0, + 1563, 382, 1, 0, 0, 0, 1564, 1565, 7, 28, 0, + 0, 1565, 384, 1, 0, 0, 0, 1566, 1567, 7, 29, + 0, 0, 1567, 386, 1, 0, 0, 0, 1568, 1569, 7, + 30, 0, 0, 1569, 388, 1, 0, 0, 0, 1570, 1571, + 7, 31, 0, 0, 1571, 390, 1, 0, 0, 0, 1572, + 1573, 7, 32, 0, 0, 1573, 392, 1, 0, 0, 0, + 1574, 1575, 7, 33, 0, 0, 1575, 394, 1, 0, 0, + 0, 1576, 1577, 7, 34, 0, 0, 1577, 396, 1, 0, + 0, 0, 1578, 1579, 7, 35, 0, 0, 1579, 398, 1, + 0, 0, 0, 1580, 1581, 7, 36, 0, 0, 1581, 400, + 1, 0, 0, 0, 1582, 1583, 7, 37, 0, 0, 1583, + 402, 1, 0, 0, 0, 1584, 1585, 7, 38, 0, 0, + 1585, 404, 1, 0, 0, 0, 1586, 1587, 7, 39, 0, + 0, 1587, 406, 1, 0, 0, 0, 1588, 1589, 7, 40, + 0, 0, 1589, 408, 1, 0, 0, 0, 54, 0, 567, + 600, 616, 625, 1232, 1238, 1250, 1254, 1256, 1260, 1272, 1277, + 1279, 1283, 1292, 1297, 1304, 1309, 1315, 1324, 1331, 1335, 1357, + 1362, 1367, 1369, 1377, 1379, 1391, 1395, 1399, 1413, 1417, 1421, + 1435, 1444, 1451, 1455, 1460, 1462, 1469, 1474, 1476, 1480, 1486, + 1491, 1493, 1499, 1501, 1505, 1513, 1525, 1533, 1, 6, 0, + 0}; staticData->serializedATN = antlr4::atn::SerializedATNView( serializedATNSegment, sizeof(serializedATNSegment) / sizeof(serializedATNSegment[0])); diff --git a/src/parser/sparqlParser/generated/SparqlAutomaticLexer.h b/src/parser/sparqlParser/generated/SparqlAutomaticLexer.h index 4242715194..b4e3b1a738 100644 --- a/src/parser/sparqlParser/generated/SparqlAutomaticLexer.h +++ b/src/parser/sparqlParser/generated/SparqlAutomaticLexer.h @@ -62,125 +62,127 @@ class SparqlAutomaticLexer : public antlr4::Lexer { VALUES = 52, LOAD = 53, SILENT = 54, - CLEAR = 55, - DROP = 56, - CREATE = 57, - ADD = 58, - DATA = 59, - MOVE = 60, - COPY = 61, - INSERT = 62, - DELETE = 63, - WITH = 64, - USING = 65, - DEFAULT = 66, - GRAPH = 67, - ALL = 68, - OPTIONAL = 69, - SERVICE = 70, - BIND = 71, - UNDEF = 72, - MINUS = 73, - UNION = 74, - FILTER = 75, - NOT = 76, - IN = 77, - STR = 78, - LANG = 79, - LANGMATCHES = 80, - DATATYPE = 81, - BOUND = 82, - IRI = 83, - URI = 84, - BNODE = 85, - RAND = 86, - ABS = 87, - CEIL = 88, - FLOOR = 89, - ROUND = 90, - CONCAT = 91, - STRLEN = 92, - UCASE = 93, - LCASE = 94, - ENCODE_FOR_URI = 95, - FOR = 96, - CONTAINS = 97, - STRSTARTS = 98, - STRENDS = 99, - STRBEFORE = 100, - STRAFTER = 101, - YEAR = 102, - MONTH = 103, - DAY = 104, - HOURS = 105, - MINUTES = 106, - SECONDS = 107, - TIMEZONE = 108, - TZ = 109, - NOW = 110, - UUID = 111, - STRUUID = 112, - SHA1 = 113, - SHA256 = 114, - SHA384 = 115, - SHA512 = 116, - MD5 = 117, - COALESCE = 118, - IF = 119, - STRLANG = 120, - STRDT = 121, - SAMETERM = 122, - ISIRI = 123, - ISURI = 124, - ISBLANK = 125, - ISLITERAL = 126, - ISNUMERIC = 127, - REGEX = 128, - SUBSTR = 129, - REPLACE = 130, - EXISTS = 131, - COUNT = 132, - SUM = 133, - MIN = 134, - MAX = 135, - AVG = 136, - SAMPLE = 137, - SEPARATOR = 138, - IRI_REF = 139, - PNAME_NS = 140, - PNAME_LN = 141, - BLANK_NODE_LABEL = 142, - VAR1 = 143, - VAR2 = 144, - LANGTAG = 145, - PREFIX_LANGTAG = 146, - INTEGER = 147, - DECIMAL = 148, - DOUBLE = 149, - INTEGER_POSITIVE = 150, - DECIMAL_POSITIVE = 151, - DOUBLE_POSITIVE = 152, - INTEGER_NEGATIVE = 153, - DECIMAL_NEGATIVE = 154, - DOUBLE_NEGATIVE = 155, - EXPONENT = 156, - STRING_LITERAL1 = 157, - STRING_LITERAL2 = 158, - STRING_LITERAL_LONG1 = 159, - STRING_LITERAL_LONG2 = 160, - ECHAR = 161, - NIL = 162, - ANON = 163, - PN_CHARS_U = 164, - VARNAME = 165, - PN_PREFIX = 166, - PN_LOCAL = 167, - PLX = 168, - PERCENT = 169, - HEX = 170, - PN_LOCAL_ESC = 171, - WS = 172, - COMMENTS = 173 + INTO = 55, + CLEAR = 56, + DROP = 57, + CREATE = 58, + ADD = 59, + TO = 60, + DATA = 61, + MOVE = 62, + COPY = 63, + INSERT = 64, + DELETE = 65, + WITH = 66, + USING = 67, + DEFAULT = 68, + GRAPH = 69, + ALL = 70, + OPTIONAL = 71, + SERVICE = 72, + BIND = 73, + UNDEF = 74, + MINUS = 75, + UNION = 76, + FILTER = 77, + NOT = 78, + IN = 79, + STR = 80, + LANG = 81, + LANGMATCHES = 82, + DATATYPE = 83, + BOUND = 84, + IRI = 85, + URI = 86, + BNODE = 87, + RAND = 88, + ABS = 89, + CEIL = 90, + FLOOR = 91, + ROUND = 92, + CONCAT = 93, + STRLEN = 94, + UCASE = 95, + LCASE = 96, + ENCODE_FOR_URI = 97, + FOR = 98, + CONTAINS = 99, + STRSTARTS = 100, + STRENDS = 101, + STRBEFORE = 102, + STRAFTER = 103, + YEAR = 104, + MONTH = 105, + DAY = 106, + HOURS = 107, + MINUTES = 108, + SECONDS = 109, + TIMEZONE = 110, + TZ = 111, + NOW = 112, + UUID = 113, + STRUUID = 114, + SHA1 = 115, + SHA256 = 116, + SHA384 = 117, + SHA512 = 118, + MD5 = 119, + COALESCE = 120, + IF = 121, + STRLANG = 122, + STRDT = 123, + SAMETERM = 124, + ISIRI = 125, + ISURI = 126, + ISBLANK = 127, + ISLITERAL = 128, + ISNUMERIC = 129, + REGEX = 130, + SUBSTR = 131, + REPLACE = 132, + EXISTS = 133, + COUNT = 134, + SUM = 135, + MIN = 136, + MAX = 137, + AVG = 138, + SAMPLE = 139, + SEPARATOR = 140, + IRI_REF = 141, + PNAME_NS = 142, + PNAME_LN = 143, + BLANK_NODE_LABEL = 144, + VAR1 = 145, + VAR2 = 146, + LANGTAG = 147, + PREFIX_LANGTAG = 148, + INTEGER = 149, + DECIMAL = 150, + DOUBLE = 151, + INTEGER_POSITIVE = 152, + DECIMAL_POSITIVE = 153, + DOUBLE_POSITIVE = 154, + INTEGER_NEGATIVE = 155, + DECIMAL_NEGATIVE = 156, + DOUBLE_NEGATIVE = 157, + EXPONENT = 158, + STRING_LITERAL1 = 159, + STRING_LITERAL2 = 160, + STRING_LITERAL_LONG1 = 161, + STRING_LITERAL_LONG2 = 162, + ECHAR = 163, + NIL = 164, + ANON = 165, + PN_CHARS_U = 166, + VARNAME = 167, + PN_PREFIX = 168, + PN_LOCAL = 169, + PLX = 170, + PERCENT = 171, + HEX = 172, + PN_LOCAL_ESC = 173, + WS = 174, + COMMENTS = 175 }; explicit SparqlAutomaticLexer(antlr4::CharStream* input); diff --git a/src/parser/sparqlParser/generated/SparqlAutomaticLexer.interp b/src/parser/sparqlParser/generated/SparqlAutomaticLexer.interp index a1422dbe58..24332ac764 100644 --- a/src/parser/sparqlParser/generated/SparqlAutomaticLexer.interp +++ b/src/parser/sparqlParser/generated/SparqlAutomaticLexer.interp @@ -5,9 +5,9 @@ null ')' '{' '}' +';' '.' ',' -';' 'a' '|' '/' @@ -173,6 +173,8 @@ null null null null +null +null token symbolic names: null @@ -230,10 +232,12 @@ TEXTLIMIT VALUES LOAD SILENT +INTO CLEAR DROP CREATE ADD +TO DATA MOVE COPY @@ -405,10 +409,12 @@ TEXTLIMIT VALUES LOAD SILENT +INTO CLEAR DROP CREATE ADD +TO DATA MOVE COPY @@ -562,4 +568,4 @@ mode names: DEFAULT_MODE atn: -[4, 0, 173, 1578, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 2, 93, 7, 93, 2, 94, 7, 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, 2, 103, 7, 103, 2, 104, 7, 104, 2, 105, 7, 105, 2, 106, 7, 106, 2, 107, 7, 107, 2, 108, 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, 111, 7, 111, 2, 112, 7, 112, 2, 113, 7, 113, 2, 114, 7, 114, 2, 115, 7, 115, 2, 116, 7, 116, 2, 117, 7, 117, 2, 118, 7, 118, 2, 119, 7, 119, 2, 120, 7, 120, 2, 121, 7, 121, 2, 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, 7, 130, 2, 131, 7, 131, 2, 132, 7, 132, 2, 133, 7, 133, 2, 134, 7, 134, 2, 135, 7, 135, 2, 136, 7, 136, 2, 137, 7, 137, 2, 138, 7, 138, 2, 139, 7, 139, 2, 140, 7, 140, 2, 141, 7, 141, 2, 142, 7, 142, 2, 143, 7, 143, 2, 144, 7, 144, 2, 145, 7, 145, 2, 146, 7, 146, 2, 147, 7, 147, 2, 148, 7, 148, 2, 149, 7, 149, 2, 150, 7, 150, 2, 151, 7, 151, 2, 152, 7, 152, 2, 153, 7, 153, 2, 154, 7, 154, 2, 155, 7, 155, 2, 156, 7, 156, 2, 157, 7, 157, 2, 158, 7, 158, 2, 159, 7, 159, 2, 160, 7, 160, 2, 161, 7, 161, 2, 162, 7, 162, 2, 163, 7, 163, 2, 164, 7, 164, 2, 165, 7, 165, 2, 166, 7, 166, 2, 167, 7, 167, 2, 168, 7, 168, 2, 169, 7, 169, 2, 170, 7, 170, 2, 171, 7, 171, 2, 172, 7, 172, 2, 173, 7, 173, 2, 174, 7, 174, 2, 175, 7, 175, 2, 176, 7, 176, 2, 177, 7, 177, 2, 178, 7, 178, 2, 179, 7, 179, 2, 180, 7, 180, 2, 181, 7, 181, 2, 182, 7, 182, 2, 183, 7, 183, 2, 184, 7, 184, 2, 185, 7, 185, 2, 186, 7, 186, 2, 187, 7, 187, 2, 188, 7, 188, 2, 189, 7, 189, 2, 190, 7, 190, 2, 191, 7, 191, 2, 192, 7, 192, 2, 193, 7, 193, 2, 194, 7, 194, 2, 195, 7, 195, 2, 196, 7, 196, 2, 197, 7, 197, 2, 198, 7, 198, 2, 199, 7, 199, 2, 200, 7, 200, 2, 201, 7, 201, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 4, 41, 562, 8, 41, 11, 41, 12, 41, 563, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 4, 44, 595, 8, 44, 11, 44, 12, 44, 596, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 4, 45, 611, 8, 45, 11, 45, 12, 45, 612, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 4, 45, 620, 8, 45, 11, 45, 12, 45, 621, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 75, 1, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 76, 1, 77, 1, 77, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 82, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 1, 83, 1, 83, 1, 84, 1, 84, 1, 84, 1, 84, 1, 84, 1, 84, 1, 85, 1, 85, 1, 85, 1, 85, 1, 85, 1, 86, 1, 86, 1, 86, 1, 86, 1, 87, 1, 87, 1, 87, 1, 87, 1, 87, 1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 89, 1, 89, 1, 89, 1, 89, 1, 89, 1, 89, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 91, 1, 91, 1, 91, 1, 91, 1, 91, 1, 91, 1, 91, 1, 92, 1, 92, 1, 92, 1, 92, 1, 92, 1, 92, 1, 93, 1, 93, 1, 93, 1, 93, 1, 93, 1, 93, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 95, 1, 95, 1, 95, 1, 95, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, 103, 1, 103, 1, 103, 1, 103, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 105, 1, 105, 1, 105, 1, 105, 1, 105, 1, 105, 1, 105, 1, 105, 1, 106, 1, 106, 1, 106, 1, 106, 1, 106, 1, 106, 1, 106, 1, 106, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 108, 1, 108, 1, 108, 1, 109, 1, 109, 1, 109, 1, 109, 1, 110, 1, 110, 1, 110, 1, 110, 1, 110, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 112, 1, 112, 1, 112, 1, 112, 1, 112, 1, 113, 1, 113, 1, 113, 1, 113, 1, 113, 1, 113, 1, 113, 1, 114, 1, 114, 1, 114, 1, 114, 1, 114, 1, 114, 1, 114, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, 116, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 118, 1, 118, 1, 118, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 122, 1, 122, 1, 122, 1, 122, 1, 122, 1, 122, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 132, 1, 132, 1, 132, 1, 132, 1, 133, 1, 133, 1, 133, 1, 133, 1, 134, 1, 134, 1, 134, 1, 134, 1, 135, 1, 135, 1, 135, 1, 135, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 138, 1, 138, 5, 138, 1219, 8, 138, 10, 138, 12, 138, 1222, 9, 138, 1, 138, 1, 138, 1, 139, 3, 139, 1227, 8, 139, 1, 139, 1, 139, 1, 140, 1, 140, 1, 140, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 3, 141, 1239, 8, 141, 1, 141, 1, 141, 5, 141, 1243, 8, 141, 10, 141, 12, 141, 1246, 9, 141, 1, 141, 3, 141, 1249, 8, 141, 1, 142, 1, 142, 1, 142, 1, 143, 1, 143, 1, 143, 1, 144, 1, 144, 4, 144, 1259, 8, 144, 11, 144, 12, 144, 1260, 1, 144, 1, 144, 1, 144, 4, 144, 1266, 8, 144, 11, 144, 12, 144, 1267, 5, 144, 1270, 8, 144, 10, 144, 12, 144, 1273, 9, 144, 1, 145, 1, 145, 1, 145, 1, 146, 4, 146, 1279, 8, 146, 11, 146, 12, 146, 1280, 1, 147, 5, 147, 1284, 8, 147, 10, 147, 12, 147, 1287, 9, 147, 1, 147, 1, 147, 4, 147, 1291, 8, 147, 11, 147, 12, 147, 1292, 1, 148, 4, 148, 1296, 8, 148, 11, 148, 12, 148, 1297, 1, 148, 1, 148, 5, 148, 1302, 8, 148, 10, 148, 12, 148, 1305, 9, 148, 1, 148, 1, 148, 1, 148, 1, 148, 4, 148, 1311, 8, 148, 11, 148, 12, 148, 1312, 1, 148, 1, 148, 1, 148, 4, 148, 1318, 8, 148, 11, 148, 12, 148, 1319, 1, 148, 1, 148, 3, 148, 1324, 8, 148, 1, 149, 1, 149, 1, 149, 1, 150, 1, 150, 1, 150, 1, 151, 1, 151, 1, 151, 1, 152, 1, 152, 1, 152, 1, 153, 1, 153, 1, 153, 1, 154, 1, 154, 1, 154, 1, 155, 1, 155, 3, 155, 1346, 8, 155, 1, 155, 4, 155, 1349, 8, 155, 11, 155, 12, 155, 1350, 1, 156, 1, 156, 1, 156, 5, 156, 1356, 8, 156, 10, 156, 12, 156, 1359, 9, 156, 1, 156, 1, 156, 1, 157, 1, 157, 1, 157, 5, 157, 1366, 8, 157, 10, 157, 12, 157, 1369, 9, 157, 1, 157, 1, 157, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 3, 158, 1380, 8, 158, 1, 158, 1, 158, 3, 158, 1384, 8, 158, 5, 158, 1386, 8, 158, 10, 158, 12, 158, 1389, 9, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 3, 159, 1402, 8, 159, 1, 159, 1, 159, 3, 159, 1406, 8, 159, 5, 159, 1408, 8, 159, 10, 159, 12, 159, 1411, 9, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 160, 1, 160, 1, 160, 1, 161, 1, 161, 5, 161, 1422, 8, 161, 10, 161, 12, 161, 1425, 9, 161, 1, 161, 1, 161, 1, 162, 1, 162, 5, 162, 1431, 8, 162, 10, 162, 12, 162, 1434, 9, 162, 1, 162, 1, 162, 1, 163, 1, 163, 3, 163, 1440, 8, 163, 1, 164, 1, 164, 3, 164, 1444, 8, 164, 1, 164, 1, 164, 1, 164, 5, 164, 1449, 8, 164, 10, 164, 12, 164, 1452, 9, 164, 1, 165, 1, 165, 1, 165, 1, 165, 3, 165, 1458, 8, 165, 1, 166, 1, 166, 1, 166, 5, 166, 1463, 8, 166, 10, 166, 12, 166, 1466, 9, 166, 1, 166, 3, 166, 1469, 8, 166, 1, 167, 1, 167, 1, 167, 1, 167, 3, 167, 1475, 8, 167, 1, 167, 1, 167, 1, 167, 5, 167, 1480, 8, 167, 10, 167, 12, 167, 1483, 9, 167, 1, 167, 1, 167, 1, 167, 3, 167, 1488, 8, 167, 3, 167, 1490, 8, 167, 1, 168, 1, 168, 3, 168, 1494, 8, 168, 1, 169, 1, 169, 1, 169, 1, 169, 1, 170, 1, 170, 3, 170, 1502, 8, 170, 1, 171, 1, 171, 1, 171, 1, 172, 1, 172, 1, 173, 1, 173, 1, 174, 4, 174, 1512, 8, 174, 11, 174, 12, 174, 1513, 1, 174, 1, 174, 1, 175, 1, 175, 5, 175, 1520, 8, 175, 10, 175, 12, 175, 1523, 9, 175, 1, 175, 1, 175, 1, 176, 1, 176, 1, 177, 1, 177, 1, 178, 1, 178, 1, 179, 1, 179, 1, 180, 1, 180, 1, 181, 1, 181, 1, 182, 1, 182, 1, 183, 1, 183, 1, 184, 1, 184, 1, 185, 1, 185, 1, 186, 1, 186, 1, 187, 1, 187, 1, 188, 1, 188, 1, 189, 1, 189, 1, 190, 1, 190, 1, 191, 1, 191, 1, 192, 1, 192, 1, 193, 1, 193, 1, 194, 1, 194, 1, 195, 1, 195, 1, 196, 1, 196, 1, 197, 1, 197, 1, 198, 1, 198, 1, 199, 1, 199, 1, 200, 1, 200, 1, 201, 1, 201, 0, 0, 202, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 34, 69, 35, 71, 36, 73, 37, 75, 38, 77, 39, 79, 40, 81, 41, 83, 42, 85, 43, 87, 44, 89, 45, 91, 46, 93, 47, 95, 48, 97, 49, 99, 50, 101, 51, 103, 52, 105, 53, 107, 54, 109, 55, 111, 56, 113, 57, 115, 58, 117, 59, 119, 60, 121, 61, 123, 62, 125, 63, 127, 64, 129, 65, 131, 66, 133, 67, 135, 68, 137, 69, 139, 70, 141, 71, 143, 72, 145, 73, 147, 74, 149, 75, 151, 76, 153, 77, 155, 78, 157, 79, 159, 80, 161, 81, 163, 82, 165, 83, 167, 84, 169, 85, 171, 86, 173, 87, 175, 88, 177, 89, 179, 90, 181, 91, 183, 92, 185, 93, 187, 94, 189, 95, 191, 96, 193, 97, 195, 98, 197, 99, 199, 100, 201, 101, 203, 102, 205, 103, 207, 104, 209, 105, 211, 106, 213, 107, 215, 108, 217, 109, 219, 110, 221, 111, 223, 112, 225, 113, 227, 114, 229, 115, 231, 116, 233, 117, 235, 118, 237, 119, 239, 120, 241, 121, 243, 122, 245, 123, 247, 124, 249, 125, 251, 126, 253, 127, 255, 128, 257, 129, 259, 130, 261, 131, 263, 132, 265, 133, 267, 134, 269, 135, 271, 136, 273, 137, 275, 138, 277, 139, 279, 140, 281, 141, 283, 142, 285, 143, 287, 144, 289, 145, 291, 146, 293, 147, 295, 148, 297, 149, 299, 150, 301, 151, 303, 152, 305, 153, 307, 154, 309, 155, 311, 156, 313, 157, 315, 158, 317, 159, 319, 160, 321, 161, 323, 162, 325, 163, 327, 164, 329, 165, 331, 0, 333, 166, 335, 167, 337, 168, 339, 169, 341, 170, 343, 171, 345, 0, 347, 0, 349, 172, 351, 173, 353, 0, 355, 0, 357, 0, 359, 0, 361, 0, 363, 0, 365, 0, 367, 0, 369, 0, 371, 0, 373, 0, 375, 0, 377, 0, 379, 0, 381, 0, 383, 0, 385, 0, 387, 0, 389, 0, 391, 0, 393, 0, 395, 0, 397, 0, 399, 0, 401, 0, 403, 0, 1, 0, 41, 8, 0, 0, 32, 34, 34, 60, 60, 62, 62, 92, 92, 94, 94, 96, 96, 123, 125, 2, 0, 65, 90, 97, 122, 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 4, 0, 10, 10, 13, 13, 39, 39, 92, 92, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 2, 0, 39, 39, 92, 92, 2, 0, 34, 34, 92, 92, 8, 0, 34, 34, 39, 39, 92, 92, 98, 98, 102, 102, 110, 110, 114, 114, 116, 116, 3, 0, 183, 183, 768, 879, 8255, 8256, 2, 0, 46, 46, 58, 58, 2, 0, 65, 70, 97, 102, 7, 0, 33, 33, 35, 47, 59, 59, 61, 61, 63, 64, 95, 95, 126, 126, 13, 0, 65, 90, 97, 122, 192, 214, 216, 246, 248, 767, 880, 893, 895, 8191, 8204, 8205, 8304, 8591, 11264, 12271, 12289, 55295, 63744, 64975, 65008, 65533, 3, 0, 9, 10, 13, 13, 32, 32, 2, 0, 10, 10, 13, 13, 2, 0, 65, 65, 97, 97, 2, 0, 66, 66, 98, 98, 2, 0, 67, 67, 99, 99, 2, 0, 68, 68, 100, 100, 2, 0, 70, 70, 102, 102, 2, 0, 71, 71, 103, 103, 2, 0, 72, 72, 104, 104, 2, 0, 73, 73, 105, 105, 2, 0, 74, 74, 106, 106, 2, 0, 75, 75, 107, 107, 2, 0, 76, 76, 108, 108, 2, 0, 77, 77, 109, 109, 2, 0, 78, 78, 110, 110, 2, 0, 79, 79, 111, 111, 2, 0, 80, 80, 112, 112, 2, 0, 81, 81, 113, 113, 2, 0, 82, 82, 114, 114, 2, 0, 83, 83, 115, 115, 2, 0, 84, 84, 116, 116, 2, 0, 85, 85, 117, 117, 2, 0, 86, 86, 118, 118, 2, 0, 87, 87, 119, 119, 2, 0, 88, 88, 120, 120, 2, 0, 89, 89, 121, 121, 2, 0, 90, 90, 122, 122, 1611, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, 0, 0, 95, 1, 0, 0, 0, 0, 97, 1, 0, 0, 0, 0, 99, 1, 0, 0, 0, 0, 101, 1, 0, 0, 0, 0, 103, 1, 0, 0, 0, 0, 105, 1, 0, 0, 0, 0, 107, 1, 0, 0, 0, 0, 109, 1, 0, 0, 0, 0, 111, 1, 0, 0, 0, 0, 113, 1, 0, 0, 0, 0, 115, 1, 0, 0, 0, 0, 117, 1, 0, 0, 0, 0, 119, 1, 0, 0, 0, 0, 121, 1, 0, 0, 0, 0, 123, 1, 0, 0, 0, 0, 125, 1, 0, 0, 0, 0, 127, 1, 0, 0, 0, 0, 129, 1, 0, 0, 0, 0, 131, 1, 0, 0, 0, 0, 133, 1, 0, 0, 0, 0, 135, 1, 0, 0, 0, 0, 137, 1, 0, 0, 0, 0, 139, 1, 0, 0, 0, 0, 141, 1, 0, 0, 0, 0, 143, 1, 0, 0, 0, 0, 145, 1, 0, 0, 0, 0, 147, 1, 0, 0, 0, 0, 149, 1, 0, 0, 0, 0, 151, 1, 0, 0, 0, 0, 153, 1, 0, 0, 0, 0, 155, 1, 0, 0, 0, 0, 157, 1, 0, 0, 0, 0, 159, 1, 0, 0, 0, 0, 161, 1, 0, 0, 0, 0, 163, 1, 0, 0, 0, 0, 165, 1, 0, 0, 0, 0, 167, 1, 0, 0, 0, 0, 169, 1, 0, 0, 0, 0, 171, 1, 0, 0, 0, 0, 173, 1, 0, 0, 0, 0, 175, 1, 0, 0, 0, 0, 177, 1, 0, 0, 0, 0, 179, 1, 0, 0, 0, 0, 181, 1, 0, 0, 0, 0, 183, 1, 0, 0, 0, 0, 185, 1, 0, 0, 0, 0, 187, 1, 0, 0, 0, 0, 189, 1, 0, 0, 0, 0, 191, 1, 0, 0, 0, 0, 193, 1, 0, 0, 0, 0, 195, 1, 0, 0, 0, 0, 197, 1, 0, 0, 0, 0, 199, 1, 0, 0, 0, 0, 201, 1, 0, 0, 0, 0, 203, 1, 0, 0, 0, 0, 205, 1, 0, 0, 0, 0, 207, 1, 0, 0, 0, 0, 209, 1, 0, 0, 0, 0, 211, 1, 0, 0, 0, 0, 213, 1, 0, 0, 0, 0, 215, 1, 0, 0, 0, 0, 217, 1, 0, 0, 0, 0, 219, 1, 0, 0, 0, 0, 221, 1, 0, 0, 0, 0, 223, 1, 0, 0, 0, 0, 225, 1, 0, 0, 0, 0, 227, 1, 0, 0, 0, 0, 229, 1, 0, 0, 0, 0, 231, 1, 0, 0, 0, 0, 233, 1, 0, 0, 0, 0, 235, 1, 0, 0, 0, 0, 237, 1, 0, 0, 0, 0, 239, 1, 0, 0, 0, 0, 241, 1, 0, 0, 0, 0, 243, 1, 0, 0, 0, 0, 245, 1, 0, 0, 0, 0, 247, 1, 0, 0, 0, 0, 249, 1, 0, 0, 0, 0, 251, 1, 0, 0, 0, 0, 253, 1, 0, 0, 0, 0, 255, 1, 0, 0, 0, 0, 257, 1, 0, 0, 0, 0, 259, 1, 0, 0, 0, 0, 261, 1, 0, 0, 0, 0, 263, 1, 0, 0, 0, 0, 265, 1, 0, 0, 0, 0, 267, 1, 0, 0, 0, 0, 269, 1, 0, 0, 0, 0, 271, 1, 0, 0, 0, 0, 273, 1, 0, 0, 0, 0, 275, 1, 0, 0, 0, 0, 277, 1, 0, 0, 0, 0, 279, 1, 0, 0, 0, 0, 281, 1, 0, 0, 0, 0, 283, 1, 0, 0, 0, 0, 285, 1, 0, 0, 0, 0, 287, 1, 0, 0, 0, 0, 289, 1, 0, 0, 0, 0, 291, 1, 0, 0, 0, 0, 293, 1, 0, 0, 0, 0, 295, 1, 0, 0, 0, 0, 297, 1, 0, 0, 0, 0, 299, 1, 0, 0, 0, 0, 301, 1, 0, 0, 0, 0, 303, 1, 0, 0, 0, 0, 305, 1, 0, 0, 0, 0, 307, 1, 0, 0, 0, 0, 309, 1, 0, 0, 0, 0, 311, 1, 0, 0, 0, 0, 313, 1, 0, 0, 0, 0, 315, 1, 0, 0, 0, 0, 317, 1, 0, 0, 0, 0, 319, 1, 0, 0, 0, 0, 321, 1, 0, 0, 0, 0, 323, 1, 0, 0, 0, 0, 325, 1, 0, 0, 0, 0, 327, 1, 0, 0, 0, 0, 329, 1, 0, 0, 0, 0, 333, 1, 0, 0, 0, 0, 335, 1, 0, 0, 0, 0, 337, 1, 0, 0, 0, 0, 339, 1, 0, 0, 0, 0, 341, 1, 0, 0, 0, 0, 343, 1, 0, 0, 0, 0, 349, 1, 0, 0, 0, 0, 351, 1, 0, 0, 0, 1, 405, 1, 0, 0, 0, 3, 407, 1, 0, 0, 0, 5, 409, 1, 0, 0, 0, 7, 411, 1, 0, 0, 0, 9, 413, 1, 0, 0, 0, 11, 415, 1, 0, 0, 0, 13, 417, 1, 0, 0, 0, 15, 419, 1, 0, 0, 0, 17, 421, 1, 0, 0, 0, 19, 423, 1, 0, 0, 0, 21, 425, 1, 0, 0, 0, 23, 427, 1, 0, 0, 0, 25, 429, 1, 0, 0, 0, 27, 431, 1, 0, 0, 0, 29, 433, 1, 0, 0, 0, 31, 435, 1, 0, 0, 0, 33, 437, 1, 0, 0, 0, 35, 439, 1, 0, 0, 0, 37, 442, 1, 0, 0, 0, 39, 445, 1, 0, 0, 0, 41, 447, 1, 0, 0, 0, 43, 450, 1, 0, 0, 0, 45, 452, 1, 0, 0, 0, 47, 454, 1, 0, 0, 0, 49, 457, 1, 0, 0, 0, 51, 460, 1, 0, 0, 0, 53, 462, 1, 0, 0, 0, 55, 465, 1, 0, 0, 0, 57, 470, 1, 0, 0, 0, 59, 476, 1, 0, 0, 0, 61, 481, 1, 0, 0, 0, 63, 488, 1, 0, 0, 0, 65, 495, 1, 0, 0, 0, 67, 504, 1, 0, 0, 0, 69, 512, 1, 0, 0, 0, 71, 515, 1, 0, 0, 0, 73, 525, 1, 0, 0, 0, 75, 531, 1, 0, 0, 0, 77, 540, 1, 0, 0, 0, 79, 544, 1, 0, 0, 0, 81, 549, 1, 0, 0, 0, 83, 555, 1, 0, 0, 0, 85, 568, 1, 0, 0, 0, 87, 581, 1, 0, 0, 0, 89, 588, 1, 0, 0, 0, 91, 601, 1, 0, 0, 0, 93, 626, 1, 0, 0, 0, 95, 630, 1, 0, 0, 0, 97, 635, 1, 0, 0, 0, 99, 641, 1, 0, 0, 0, 101, 648, 1, 0, 0, 0, 103, 658, 1, 0, 0, 0, 105, 665, 1, 0, 0, 0, 107, 670, 1, 0, 0, 0, 109, 677, 1, 0, 0, 0, 111, 683, 1, 0, 0, 0, 113, 688, 1, 0, 0, 0, 115, 695, 1, 0, 0, 0, 117, 699, 1, 0, 0, 0, 119, 704, 1, 0, 0, 0, 121, 709, 1, 0, 0, 0, 123, 714, 1, 0, 0, 0, 125, 721, 1, 0, 0, 0, 127, 728, 1, 0, 0, 0, 129, 733, 1, 0, 0, 0, 131, 739, 1, 0, 0, 0, 133, 747, 1, 0, 0, 0, 135, 753, 1, 0, 0, 0, 137, 757, 1, 0, 0, 0, 139, 766, 1, 0, 0, 0, 141, 774, 1, 0, 0, 0, 143, 779, 1, 0, 0, 0, 145, 785, 1, 0, 0, 0, 147, 791, 1, 0, 0, 0, 149, 797, 1, 0, 0, 0, 151, 804, 1, 0, 0, 0, 153, 808, 1, 0, 0, 0, 155, 811, 1, 0, 0, 0, 157, 815, 1, 0, 0, 0, 159, 820, 1, 0, 0, 0, 161, 832, 1, 0, 0, 0, 163, 841, 1, 0, 0, 0, 165, 847, 1, 0, 0, 0, 167, 851, 1, 0, 0, 0, 169, 855, 1, 0, 0, 0, 171, 861, 1, 0, 0, 0, 173, 866, 1, 0, 0, 0, 175, 870, 1, 0, 0, 0, 177, 875, 1, 0, 0, 0, 179, 881, 1, 0, 0, 0, 181, 887, 1, 0, 0, 0, 183, 894, 1, 0, 0, 0, 185, 901, 1, 0, 0, 0, 187, 907, 1, 0, 0, 0, 189, 913, 1, 0, 0, 0, 191, 928, 1, 0, 0, 0, 193, 932, 1, 0, 0, 0, 195, 941, 1, 0, 0, 0, 197, 951, 1, 0, 0, 0, 199, 959, 1, 0, 0, 0, 201, 969, 1, 0, 0, 0, 203, 978, 1, 0, 0, 0, 205, 983, 1, 0, 0, 0, 207, 989, 1, 0, 0, 0, 209, 993, 1, 0, 0, 0, 211, 999, 1, 0, 0, 0, 213, 1007, 1, 0, 0, 0, 215, 1015, 1, 0, 0, 0, 217, 1024, 1, 0, 0, 0, 219, 1027, 1, 0, 0, 0, 221, 1031, 1, 0, 0, 0, 223, 1036, 1, 0, 0, 0, 225, 1044, 1, 0, 0, 0, 227, 1049, 1, 0, 0, 0, 229, 1056, 1, 0, 0, 0, 231, 1063, 1, 0, 0, 0, 233, 1070, 1, 0, 0, 0, 235, 1074, 1, 0, 0, 0, 237, 1083, 1, 0, 0, 0, 239, 1086, 1, 0, 0, 0, 241, 1094, 1, 0, 0, 0, 243, 1100, 1, 0, 0, 0, 245, 1109, 1, 0, 0, 0, 247, 1115, 1, 0, 0, 0, 249, 1121, 1, 0, 0, 0, 251, 1129, 1, 0, 0, 0, 253, 1139, 1, 0, 0, 0, 255, 1149, 1, 0, 0, 0, 257, 1155, 1, 0, 0, 0, 259, 1162, 1, 0, 0, 0, 261, 1170, 1, 0, 0, 0, 263, 1177, 1, 0, 0, 0, 265, 1183, 1, 0, 0, 0, 267, 1187, 1, 0, 0, 0, 269, 1191, 1, 0, 0, 0, 271, 1195, 1, 0, 0, 0, 273, 1199, 1, 0, 0, 0, 275, 1206, 1, 0, 0, 0, 277, 1216, 1, 0, 0, 0, 279, 1226, 1, 0, 0, 0, 281, 1230, 1, 0, 0, 0, 283, 1233, 1, 0, 0, 0, 285, 1250, 1, 0, 0, 0, 287, 1253, 1, 0, 0, 0, 289, 1256, 1, 0, 0, 0, 291, 1274, 1, 0, 0, 0, 293, 1278, 1, 0, 0, 0, 295, 1285, 1, 0, 0, 0, 297, 1323, 1, 0, 0, 0, 299, 1325, 1, 0, 0, 0, 301, 1328, 1, 0, 0, 0, 303, 1331, 1, 0, 0, 0, 305, 1334, 1, 0, 0, 0, 307, 1337, 1, 0, 0, 0, 309, 1340, 1, 0, 0, 0, 311, 1343, 1, 0, 0, 0, 313, 1352, 1, 0, 0, 0, 315, 1362, 1, 0, 0, 0, 317, 1372, 1, 0, 0, 0, 319, 1394, 1, 0, 0, 0, 321, 1416, 1, 0, 0, 0, 323, 1419, 1, 0, 0, 0, 325, 1428, 1, 0, 0, 0, 327, 1439, 1, 0, 0, 0, 329, 1443, 1, 0, 0, 0, 331, 1457, 1, 0, 0, 0, 333, 1459, 1, 0, 0, 0, 335, 1474, 1, 0, 0, 0, 337, 1493, 1, 0, 0, 0, 339, 1495, 1, 0, 0, 0, 341, 1501, 1, 0, 0, 0, 343, 1503, 1, 0, 0, 0, 345, 1506, 1, 0, 0, 0, 347, 1508, 1, 0, 0, 0, 349, 1511, 1, 0, 0, 0, 351, 1517, 1, 0, 0, 0, 353, 1526, 1, 0, 0, 0, 355, 1528, 1, 0, 0, 0, 357, 1530, 1, 0, 0, 0, 359, 1532, 1, 0, 0, 0, 361, 1534, 1, 0, 0, 0, 363, 1536, 1, 0, 0, 0, 365, 1538, 1, 0, 0, 0, 367, 1540, 1, 0, 0, 0, 369, 1542, 1, 0, 0, 0, 371, 1544, 1, 0, 0, 0, 373, 1546, 1, 0, 0, 0, 375, 1548, 1, 0, 0, 0, 377, 1550, 1, 0, 0, 0, 379, 1552, 1, 0, 0, 0, 381, 1554, 1, 0, 0, 0, 383, 1556, 1, 0, 0, 0, 385, 1558, 1, 0, 0, 0, 387, 1560, 1, 0, 0, 0, 389, 1562, 1, 0, 0, 0, 391, 1564, 1, 0, 0, 0, 393, 1566, 1, 0, 0, 0, 395, 1568, 1, 0, 0, 0, 397, 1570, 1, 0, 0, 0, 399, 1572, 1, 0, 0, 0, 401, 1574, 1, 0, 0, 0, 403, 1576, 1, 0, 0, 0, 405, 406, 5, 42, 0, 0, 406, 2, 1, 0, 0, 0, 407, 408, 5, 40, 0, 0, 408, 4, 1, 0, 0, 0, 409, 410, 5, 41, 0, 0, 410, 6, 1, 0, 0, 0, 411, 412, 5, 123, 0, 0, 412, 8, 1, 0, 0, 0, 413, 414, 5, 125, 0, 0, 414, 10, 1, 0, 0, 0, 415, 416, 5, 46, 0, 0, 416, 12, 1, 0, 0, 0, 417, 418, 5, 44, 0, 0, 418, 14, 1, 0, 0, 0, 419, 420, 5, 59, 0, 0, 420, 16, 1, 0, 0, 0, 421, 422, 5, 97, 0, 0, 422, 18, 1, 0, 0, 0, 423, 424, 5, 124, 0, 0, 424, 20, 1, 0, 0, 0, 425, 426, 5, 47, 0, 0, 426, 22, 1, 0, 0, 0, 427, 428, 5, 94, 0, 0, 428, 24, 1, 0, 0, 0, 429, 430, 5, 43, 0, 0, 430, 26, 1, 0, 0, 0, 431, 432, 5, 63, 0, 0, 432, 28, 1, 0, 0, 0, 433, 434, 5, 33, 0, 0, 434, 30, 1, 0, 0, 0, 435, 436, 5, 91, 0, 0, 436, 32, 1, 0, 0, 0, 437, 438, 5, 93, 0, 0, 438, 34, 1, 0, 0, 0, 439, 440, 5, 124, 0, 0, 440, 441, 5, 124, 0, 0, 441, 36, 1, 0, 0, 0, 442, 443, 5, 38, 0, 0, 443, 444, 5, 38, 0, 0, 444, 38, 1, 0, 0, 0, 445, 446, 5, 61, 0, 0, 446, 40, 1, 0, 0, 0, 447, 448, 5, 33, 0, 0, 448, 449, 5, 61, 0, 0, 449, 42, 1, 0, 0, 0, 450, 451, 5, 60, 0, 0, 451, 44, 1, 0, 0, 0, 452, 453, 5, 62, 0, 0, 453, 46, 1, 0, 0, 0, 454, 455, 5, 60, 0, 0, 455, 456, 5, 61, 0, 0, 456, 48, 1, 0, 0, 0, 457, 458, 5, 62, 0, 0, 458, 459, 5, 61, 0, 0, 459, 50, 1, 0, 0, 0, 460, 461, 5, 45, 0, 0, 461, 52, 1, 0, 0, 0, 462, 463, 5, 94, 0, 0, 463, 464, 5, 94, 0, 0, 464, 54, 1, 0, 0, 0, 465, 466, 5, 116, 0, 0, 466, 467, 5, 114, 0, 0, 467, 468, 5, 117, 0, 0, 468, 469, 5, 101, 0, 0, 469, 56, 1, 0, 0, 0, 470, 471, 5, 102, 0, 0, 471, 472, 5, 97, 0, 0, 472, 473, 5, 108, 0, 0, 473, 474, 5, 115, 0, 0, 474, 475, 5, 101, 0, 0, 475, 58, 1, 0, 0, 0, 476, 477, 3, 355, 177, 0, 477, 478, 3, 353, 176, 0, 478, 479, 3, 389, 194, 0, 479, 480, 3, 361, 180, 0, 480, 60, 1, 0, 0, 0, 481, 482, 3, 383, 191, 0, 482, 483, 3, 387, 193, 0, 483, 484, 3, 361, 180, 0, 484, 485, 3, 363, 181, 0, 485, 486, 3, 369, 184, 0, 486, 487, 3, 399, 199, 0, 487, 62, 1, 0, 0, 0, 488, 489, 3, 389, 194, 0, 489, 490, 3, 361, 180, 0, 490, 491, 3, 375, 187, 0, 491, 492, 3, 361, 180, 0, 492, 493, 3, 357, 178, 0, 493, 494, 3, 391, 195, 0, 494, 64, 1, 0, 0, 0, 495, 496, 3, 359, 179, 0, 496, 497, 3, 369, 184, 0, 497, 498, 3, 389, 194, 0, 498, 499, 3, 391, 195, 0, 499, 500, 3, 369, 184, 0, 500, 501, 3, 379, 189, 0, 501, 502, 3, 357, 178, 0, 502, 503, 3, 391, 195, 0, 503, 66, 1, 0, 0, 0, 504, 505, 3, 387, 193, 0, 505, 506, 3, 361, 180, 0, 506, 507, 3, 359, 179, 0, 507, 508, 3, 393, 196, 0, 508, 509, 3, 357, 178, 0, 509, 510, 3, 361, 180, 0, 510, 511, 3, 359, 179, 0, 511, 68, 1, 0, 0, 0, 512, 513, 3, 353, 176, 0, 513, 514, 3, 389, 194, 0, 514, 70, 1, 0, 0, 0, 515, 516, 3, 357, 178, 0, 516, 517, 3, 381, 190, 0, 517, 518, 3, 379, 189, 0, 518, 519, 3, 389, 194, 0, 519, 520, 3, 391, 195, 0, 520, 521, 3, 387, 193, 0, 521, 522, 3, 393, 196, 0, 522, 523, 3, 357, 178, 0, 523, 524, 3, 391, 195, 0, 524, 72, 1, 0, 0, 0, 525, 526, 3, 397, 198, 0, 526, 527, 3, 367, 183, 0, 527, 528, 3, 361, 180, 0, 528, 529, 3, 387, 193, 0, 529, 530, 3, 361, 180, 0, 530, 74, 1, 0, 0, 0, 531, 532, 3, 359, 179, 0, 532, 533, 3, 361, 180, 0, 533, 534, 3, 389, 194, 0, 534, 535, 3, 357, 178, 0, 535, 536, 3, 387, 193, 0, 536, 537, 3, 369, 184, 0, 537, 538, 3, 355, 177, 0, 538, 539, 3, 361, 180, 0, 539, 76, 1, 0, 0, 0, 540, 541, 3, 353, 176, 0, 541, 542, 3, 389, 194, 0, 542, 543, 3, 373, 186, 0, 543, 78, 1, 0, 0, 0, 544, 545, 3, 363, 181, 0, 545, 546, 3, 387, 193, 0, 546, 547, 3, 381, 190, 0, 547, 548, 3, 377, 188, 0, 548, 80, 1, 0, 0, 0, 549, 550, 3, 379, 189, 0, 550, 551, 3, 353, 176, 0, 551, 552, 3, 377, 188, 0, 552, 553, 3, 361, 180, 0, 553, 554, 3, 359, 179, 0, 554, 82, 1, 0, 0, 0, 555, 556, 3, 365, 182, 0, 556, 557, 3, 387, 193, 0, 557, 558, 3, 381, 190, 0, 558, 559, 3, 393, 196, 0, 559, 561, 3, 383, 191, 0, 560, 562, 3, 349, 174, 0, 561, 560, 1, 0, 0, 0, 562, 563, 1, 0, 0, 0, 563, 561, 1, 0, 0, 0, 563, 564, 1, 0, 0, 0, 564, 565, 1, 0, 0, 0, 565, 566, 3, 355, 177, 0, 566, 567, 3, 401, 200, 0, 567, 84, 1, 0, 0, 0, 568, 569, 3, 365, 182, 0, 569, 570, 3, 387, 193, 0, 570, 571, 3, 381, 190, 0, 571, 572, 3, 393, 196, 0, 572, 573, 3, 383, 191, 0, 573, 574, 5, 95, 0, 0, 574, 575, 3, 357, 178, 0, 575, 576, 3, 381, 190, 0, 576, 577, 3, 379, 189, 0, 577, 578, 3, 357, 178, 0, 578, 579, 3, 353, 176, 0, 579, 580, 3, 391, 195, 0, 580, 86, 1, 0, 0, 0, 581, 582, 3, 367, 183, 0, 582, 583, 3, 353, 176, 0, 583, 584, 3, 395, 197, 0, 584, 585, 3, 369, 184, 0, 585, 586, 3, 379, 189, 0, 586, 587, 3, 365, 182, 0, 587, 88, 1, 0, 0, 0, 588, 589, 3, 381, 190, 0, 589, 590, 3, 387, 193, 0, 590, 591, 3, 359, 179, 0, 591, 592, 3, 361, 180, 0, 592, 594, 3, 387, 193, 0, 593, 595, 3, 349, 174, 0, 594, 593, 1, 0, 0, 0, 595, 596, 1, 0, 0, 0, 596, 594, 1, 0, 0, 0, 596, 597, 1, 0, 0, 0, 597, 598, 1, 0, 0, 0, 598, 599, 3, 355, 177, 0, 599, 600, 3, 401, 200, 0, 600, 90, 1, 0, 0, 0, 601, 602, 3, 369, 184, 0, 602, 603, 3, 379, 189, 0, 603, 604, 3, 391, 195, 0, 604, 605, 3, 361, 180, 0, 605, 606, 3, 387, 193, 0, 606, 607, 3, 379, 189, 0, 607, 608, 3, 353, 176, 0, 608, 610, 3, 375, 187, 0, 609, 611, 3, 349, 174, 0, 610, 609, 1, 0, 0, 0, 611, 612, 1, 0, 0, 0, 612, 610, 1, 0, 0, 0, 612, 613, 1, 0, 0, 0, 613, 614, 1, 0, 0, 0, 614, 615, 3, 389, 194, 0, 615, 616, 3, 381, 190, 0, 616, 617, 3, 387, 193, 0, 617, 619, 3, 391, 195, 0, 618, 620, 3, 349, 174, 0, 619, 618, 1, 0, 0, 0, 620, 621, 1, 0, 0, 0, 621, 619, 1, 0, 0, 0, 621, 622, 1, 0, 0, 0, 622, 623, 1, 0, 0, 0, 623, 624, 3, 355, 177, 0, 624, 625, 3, 401, 200, 0, 625, 92, 1, 0, 0, 0, 626, 627, 3, 353, 176, 0, 627, 628, 3, 389, 194, 0, 628, 629, 3, 357, 178, 0, 629, 94, 1, 0, 0, 0, 630, 631, 3, 359, 179, 0, 631, 632, 3, 361, 180, 0, 632, 633, 3, 389, 194, 0, 633, 634, 3, 357, 178, 0, 634, 96, 1, 0, 0, 0, 635, 636, 3, 375, 187, 0, 636, 637, 3, 369, 184, 0, 637, 638, 3, 377, 188, 0, 638, 639, 3, 369, 184, 0, 639, 640, 3, 391, 195, 0, 640, 98, 1, 0, 0, 0, 641, 642, 3, 381, 190, 0, 642, 643, 3, 363, 181, 0, 643, 644, 3, 363, 181, 0, 644, 645, 3, 389, 194, 0, 645, 646, 3, 361, 180, 0, 646, 647, 3, 391, 195, 0, 647, 100, 1, 0, 0, 0, 648, 649, 3, 391, 195, 0, 649, 650, 3, 361, 180, 0, 650, 651, 3, 399, 199, 0, 651, 652, 3, 391, 195, 0, 652, 653, 3, 375, 187, 0, 653, 654, 3, 369, 184, 0, 654, 655, 3, 377, 188, 0, 655, 656, 3, 369, 184, 0, 656, 657, 3, 391, 195, 0, 657, 102, 1, 0, 0, 0, 658, 659, 3, 395, 197, 0, 659, 660, 3, 353, 176, 0, 660, 661, 3, 375, 187, 0, 661, 662, 3, 393, 196, 0, 662, 663, 3, 361, 180, 0, 663, 664, 3, 389, 194, 0, 664, 104, 1, 0, 0, 0, 665, 666, 3, 375, 187, 0, 666, 667, 3, 381, 190, 0, 667, 668, 3, 353, 176, 0, 668, 669, 3, 359, 179, 0, 669, 106, 1, 0, 0, 0, 670, 671, 3, 389, 194, 0, 671, 672, 3, 369, 184, 0, 672, 673, 3, 375, 187, 0, 673, 674, 3, 361, 180, 0, 674, 675, 3, 379, 189, 0, 675, 676, 3, 391, 195, 0, 676, 108, 1, 0, 0, 0, 677, 678, 3, 357, 178, 0, 678, 679, 3, 375, 187, 0, 679, 680, 3, 361, 180, 0, 680, 681, 3, 353, 176, 0, 681, 682, 3, 387, 193, 0, 682, 110, 1, 0, 0, 0, 683, 684, 3, 359, 179, 0, 684, 685, 3, 387, 193, 0, 685, 686, 3, 381, 190, 0, 686, 687, 3, 383, 191, 0, 687, 112, 1, 0, 0, 0, 688, 689, 3, 357, 178, 0, 689, 690, 3, 387, 193, 0, 690, 691, 3, 361, 180, 0, 691, 692, 3, 353, 176, 0, 692, 693, 3, 391, 195, 0, 693, 694, 3, 361, 180, 0, 694, 114, 1, 0, 0, 0, 695, 696, 3, 353, 176, 0, 696, 697, 3, 359, 179, 0, 697, 698, 3, 359, 179, 0, 698, 116, 1, 0, 0, 0, 699, 700, 3, 359, 179, 0, 700, 701, 3, 353, 176, 0, 701, 702, 3, 391, 195, 0, 702, 703, 3, 353, 176, 0, 703, 118, 1, 0, 0, 0, 704, 705, 3, 377, 188, 0, 705, 706, 3, 381, 190, 0, 706, 707, 3, 395, 197, 0, 707, 708, 3, 361, 180, 0, 708, 120, 1, 0, 0, 0, 709, 710, 3, 357, 178, 0, 710, 711, 3, 381, 190, 0, 711, 712, 3, 383, 191, 0, 712, 713, 3, 401, 200, 0, 713, 122, 1, 0, 0, 0, 714, 715, 3, 369, 184, 0, 715, 716, 3, 379, 189, 0, 716, 717, 3, 389, 194, 0, 717, 718, 3, 361, 180, 0, 718, 719, 3, 387, 193, 0, 719, 720, 3, 391, 195, 0, 720, 124, 1, 0, 0, 0, 721, 722, 3, 359, 179, 0, 722, 723, 3, 361, 180, 0, 723, 724, 3, 375, 187, 0, 724, 725, 3, 361, 180, 0, 725, 726, 3, 391, 195, 0, 726, 727, 3, 361, 180, 0, 727, 126, 1, 0, 0, 0, 728, 729, 3, 397, 198, 0, 729, 730, 3, 369, 184, 0, 730, 731, 3, 391, 195, 0, 731, 732, 3, 367, 183, 0, 732, 128, 1, 0, 0, 0, 733, 734, 3, 393, 196, 0, 734, 735, 3, 389, 194, 0, 735, 736, 3, 369, 184, 0, 736, 737, 3, 379, 189, 0, 737, 738, 3, 365, 182, 0, 738, 130, 1, 0, 0, 0, 739, 740, 3, 359, 179, 0, 740, 741, 3, 361, 180, 0, 741, 742, 3, 363, 181, 0, 742, 743, 3, 353, 176, 0, 743, 744, 3, 393, 196, 0, 744, 745, 3, 375, 187, 0, 745, 746, 3, 391, 195, 0, 746, 132, 1, 0, 0, 0, 747, 748, 3, 365, 182, 0, 748, 749, 3, 387, 193, 0, 749, 750, 3, 353, 176, 0, 750, 751, 3, 383, 191, 0, 751, 752, 3, 367, 183, 0, 752, 134, 1, 0, 0, 0, 753, 754, 3, 353, 176, 0, 754, 755, 3, 375, 187, 0, 755, 756, 3, 375, 187, 0, 756, 136, 1, 0, 0, 0, 757, 758, 3, 381, 190, 0, 758, 759, 3, 383, 191, 0, 759, 760, 3, 391, 195, 0, 760, 761, 3, 369, 184, 0, 761, 762, 3, 381, 190, 0, 762, 763, 3, 379, 189, 0, 763, 764, 3, 353, 176, 0, 764, 765, 3, 375, 187, 0, 765, 138, 1, 0, 0, 0, 766, 767, 3, 389, 194, 0, 767, 768, 3, 361, 180, 0, 768, 769, 3, 387, 193, 0, 769, 770, 3, 395, 197, 0, 770, 771, 3, 369, 184, 0, 771, 772, 3, 357, 178, 0, 772, 773, 3, 361, 180, 0, 773, 140, 1, 0, 0, 0, 774, 775, 3, 355, 177, 0, 775, 776, 3, 369, 184, 0, 776, 777, 3, 379, 189, 0, 777, 778, 3, 359, 179, 0, 778, 142, 1, 0, 0, 0, 779, 780, 3, 393, 196, 0, 780, 781, 3, 379, 189, 0, 781, 782, 3, 359, 179, 0, 782, 783, 3, 361, 180, 0, 783, 784, 3, 363, 181, 0, 784, 144, 1, 0, 0, 0, 785, 786, 3, 377, 188, 0, 786, 787, 3, 369, 184, 0, 787, 788, 3, 379, 189, 0, 788, 789, 3, 393, 196, 0, 789, 790, 3, 389, 194, 0, 790, 146, 1, 0, 0, 0, 791, 792, 3, 393, 196, 0, 792, 793, 3, 379, 189, 0, 793, 794, 3, 369, 184, 0, 794, 795, 3, 381, 190, 0, 795, 796, 3, 379, 189, 0, 796, 148, 1, 0, 0, 0, 797, 798, 3, 363, 181, 0, 798, 799, 3, 369, 184, 0, 799, 800, 3, 375, 187, 0, 800, 801, 3, 391, 195, 0, 801, 802, 3, 361, 180, 0, 802, 803, 3, 387, 193, 0, 803, 150, 1, 0, 0, 0, 804, 805, 3, 379, 189, 0, 805, 806, 3, 381, 190, 0, 806, 807, 3, 391, 195, 0, 807, 152, 1, 0, 0, 0, 808, 809, 3, 369, 184, 0, 809, 810, 3, 379, 189, 0, 810, 154, 1, 0, 0, 0, 811, 812, 3, 389, 194, 0, 812, 813, 3, 391, 195, 0, 813, 814, 3, 387, 193, 0, 814, 156, 1, 0, 0, 0, 815, 816, 3, 375, 187, 0, 816, 817, 3, 353, 176, 0, 817, 818, 3, 379, 189, 0, 818, 819, 3, 365, 182, 0, 819, 158, 1, 0, 0, 0, 820, 821, 3, 375, 187, 0, 821, 822, 3, 353, 176, 0, 822, 823, 3, 379, 189, 0, 823, 824, 3, 365, 182, 0, 824, 825, 3, 377, 188, 0, 825, 826, 3, 353, 176, 0, 826, 827, 3, 391, 195, 0, 827, 828, 3, 357, 178, 0, 828, 829, 3, 367, 183, 0, 829, 830, 3, 361, 180, 0, 830, 831, 3, 389, 194, 0, 831, 160, 1, 0, 0, 0, 832, 833, 3, 359, 179, 0, 833, 834, 3, 353, 176, 0, 834, 835, 3, 391, 195, 0, 835, 836, 3, 353, 176, 0, 836, 837, 3, 391, 195, 0, 837, 838, 3, 401, 200, 0, 838, 839, 3, 383, 191, 0, 839, 840, 3, 361, 180, 0, 840, 162, 1, 0, 0, 0, 841, 842, 3, 355, 177, 0, 842, 843, 3, 381, 190, 0, 843, 844, 3, 393, 196, 0, 844, 845, 3, 379, 189, 0, 845, 846, 3, 359, 179, 0, 846, 164, 1, 0, 0, 0, 847, 848, 3, 369, 184, 0, 848, 849, 3, 387, 193, 0, 849, 850, 3, 369, 184, 0, 850, 166, 1, 0, 0, 0, 851, 852, 3, 393, 196, 0, 852, 853, 3, 387, 193, 0, 853, 854, 3, 369, 184, 0, 854, 168, 1, 0, 0, 0, 855, 856, 3, 355, 177, 0, 856, 857, 3, 379, 189, 0, 857, 858, 3, 381, 190, 0, 858, 859, 3, 359, 179, 0, 859, 860, 3, 361, 180, 0, 860, 170, 1, 0, 0, 0, 861, 862, 3, 387, 193, 0, 862, 863, 3, 353, 176, 0, 863, 864, 3, 379, 189, 0, 864, 865, 3, 359, 179, 0, 865, 172, 1, 0, 0, 0, 866, 867, 3, 353, 176, 0, 867, 868, 3, 355, 177, 0, 868, 869, 3, 389, 194, 0, 869, 174, 1, 0, 0, 0, 870, 871, 3, 357, 178, 0, 871, 872, 3, 361, 180, 0, 872, 873, 3, 369, 184, 0, 873, 874, 3, 375, 187, 0, 874, 176, 1, 0, 0, 0, 875, 876, 3, 363, 181, 0, 876, 877, 3, 375, 187, 0, 877, 878, 3, 381, 190, 0, 878, 879, 3, 381, 190, 0, 879, 880, 3, 387, 193, 0, 880, 178, 1, 0, 0, 0, 881, 882, 3, 387, 193, 0, 882, 883, 3, 381, 190, 0, 883, 884, 3, 393, 196, 0, 884, 885, 3, 379, 189, 0, 885, 886, 3, 359, 179, 0, 886, 180, 1, 0, 0, 0, 887, 888, 3, 357, 178, 0, 888, 889, 3, 381, 190, 0, 889, 890, 3, 379, 189, 0, 890, 891, 3, 357, 178, 0, 891, 892, 3, 353, 176, 0, 892, 893, 3, 391, 195, 0, 893, 182, 1, 0, 0, 0, 894, 895, 3, 389, 194, 0, 895, 896, 3, 391, 195, 0, 896, 897, 3, 387, 193, 0, 897, 898, 3, 375, 187, 0, 898, 899, 3, 361, 180, 0, 899, 900, 3, 379, 189, 0, 900, 184, 1, 0, 0, 0, 901, 902, 3, 393, 196, 0, 902, 903, 3, 357, 178, 0, 903, 904, 3, 353, 176, 0, 904, 905, 3, 389, 194, 0, 905, 906, 3, 361, 180, 0, 906, 186, 1, 0, 0, 0, 907, 908, 3, 375, 187, 0, 908, 909, 3, 357, 178, 0, 909, 910, 3, 353, 176, 0, 910, 911, 3, 389, 194, 0, 911, 912, 3, 361, 180, 0, 912, 188, 1, 0, 0, 0, 913, 914, 3, 361, 180, 0, 914, 915, 3, 379, 189, 0, 915, 916, 3, 357, 178, 0, 916, 917, 3, 381, 190, 0, 917, 918, 3, 359, 179, 0, 918, 919, 3, 361, 180, 0, 919, 920, 5, 95, 0, 0, 920, 921, 3, 363, 181, 0, 921, 922, 3, 381, 190, 0, 922, 923, 3, 387, 193, 0, 923, 924, 5, 95, 0, 0, 924, 925, 3, 393, 196, 0, 925, 926, 3, 387, 193, 0, 926, 927, 3, 369, 184, 0, 927, 190, 1, 0, 0, 0, 928, 929, 3, 363, 181, 0, 929, 930, 3, 381, 190, 0, 930, 931, 3, 387, 193, 0, 931, 192, 1, 0, 0, 0, 932, 933, 3, 357, 178, 0, 933, 934, 3, 381, 190, 0, 934, 935, 3, 379, 189, 0, 935, 936, 3, 391, 195, 0, 936, 937, 3, 353, 176, 0, 937, 938, 3, 369, 184, 0, 938, 939, 3, 379, 189, 0, 939, 940, 3, 389, 194, 0, 940, 194, 1, 0, 0, 0, 941, 942, 3, 389, 194, 0, 942, 943, 3, 391, 195, 0, 943, 944, 3, 387, 193, 0, 944, 945, 3, 389, 194, 0, 945, 946, 3, 391, 195, 0, 946, 947, 3, 353, 176, 0, 947, 948, 3, 387, 193, 0, 948, 949, 3, 391, 195, 0, 949, 950, 3, 389, 194, 0, 950, 196, 1, 0, 0, 0, 951, 952, 3, 389, 194, 0, 952, 953, 3, 391, 195, 0, 953, 954, 3, 387, 193, 0, 954, 955, 3, 361, 180, 0, 955, 956, 3, 379, 189, 0, 956, 957, 3, 359, 179, 0, 957, 958, 3, 389, 194, 0, 958, 198, 1, 0, 0, 0, 959, 960, 3, 389, 194, 0, 960, 961, 3, 391, 195, 0, 961, 962, 3, 387, 193, 0, 962, 963, 3, 355, 177, 0, 963, 964, 3, 361, 180, 0, 964, 965, 3, 363, 181, 0, 965, 966, 3, 381, 190, 0, 966, 967, 3, 387, 193, 0, 967, 968, 3, 361, 180, 0, 968, 200, 1, 0, 0, 0, 969, 970, 3, 389, 194, 0, 970, 971, 3, 391, 195, 0, 971, 972, 3, 387, 193, 0, 972, 973, 3, 353, 176, 0, 973, 974, 3, 363, 181, 0, 974, 975, 3, 391, 195, 0, 975, 976, 3, 361, 180, 0, 976, 977, 3, 387, 193, 0, 977, 202, 1, 0, 0, 0, 978, 979, 3, 401, 200, 0, 979, 980, 3, 361, 180, 0, 980, 981, 3, 353, 176, 0, 981, 982, 3, 387, 193, 0, 982, 204, 1, 0, 0, 0, 983, 984, 3, 377, 188, 0, 984, 985, 3, 381, 190, 0, 985, 986, 3, 379, 189, 0, 986, 987, 3, 391, 195, 0, 987, 988, 3, 367, 183, 0, 988, 206, 1, 0, 0, 0, 989, 990, 3, 359, 179, 0, 990, 991, 3, 353, 176, 0, 991, 992, 3, 401, 200, 0, 992, 208, 1, 0, 0, 0, 993, 994, 3, 367, 183, 0, 994, 995, 3, 381, 190, 0, 995, 996, 3, 393, 196, 0, 996, 997, 3, 387, 193, 0, 997, 998, 3, 389, 194, 0, 998, 210, 1, 0, 0, 0, 999, 1000, 3, 377, 188, 0, 1000, 1001, 3, 369, 184, 0, 1001, 1002, 3, 379, 189, 0, 1002, 1003, 3, 393, 196, 0, 1003, 1004, 3, 391, 195, 0, 1004, 1005, 3, 361, 180, 0, 1005, 1006, 3, 389, 194, 0, 1006, 212, 1, 0, 0, 0, 1007, 1008, 3, 389, 194, 0, 1008, 1009, 3, 361, 180, 0, 1009, 1010, 3, 357, 178, 0, 1010, 1011, 3, 381, 190, 0, 1011, 1012, 3, 379, 189, 0, 1012, 1013, 3, 359, 179, 0, 1013, 1014, 3, 389, 194, 0, 1014, 214, 1, 0, 0, 0, 1015, 1016, 3, 391, 195, 0, 1016, 1017, 3, 369, 184, 0, 1017, 1018, 3, 377, 188, 0, 1018, 1019, 3, 361, 180, 0, 1019, 1020, 3, 403, 201, 0, 1020, 1021, 3, 381, 190, 0, 1021, 1022, 3, 379, 189, 0, 1022, 1023, 3, 361, 180, 0, 1023, 216, 1, 0, 0, 0, 1024, 1025, 3, 391, 195, 0, 1025, 1026, 3, 403, 201, 0, 1026, 218, 1, 0, 0, 0, 1027, 1028, 3, 379, 189, 0, 1028, 1029, 3, 381, 190, 0, 1029, 1030, 3, 397, 198, 0, 1030, 220, 1, 0, 0, 0, 1031, 1032, 3, 393, 196, 0, 1032, 1033, 3, 393, 196, 0, 1033, 1034, 3, 369, 184, 0, 1034, 1035, 3, 359, 179, 0, 1035, 222, 1, 0, 0, 0, 1036, 1037, 3, 389, 194, 0, 1037, 1038, 3, 391, 195, 0, 1038, 1039, 3, 387, 193, 0, 1039, 1040, 3, 393, 196, 0, 1040, 1041, 3, 393, 196, 0, 1041, 1042, 3, 369, 184, 0, 1042, 1043, 3, 359, 179, 0, 1043, 224, 1, 0, 0, 0, 1044, 1045, 3, 389, 194, 0, 1045, 1046, 3, 367, 183, 0, 1046, 1047, 3, 353, 176, 0, 1047, 1048, 5, 49, 0, 0, 1048, 226, 1, 0, 0, 0, 1049, 1050, 3, 389, 194, 0, 1050, 1051, 3, 367, 183, 0, 1051, 1052, 3, 353, 176, 0, 1052, 1053, 5, 50, 0, 0, 1053, 1054, 5, 53, 0, 0, 1054, 1055, 5, 54, 0, 0, 1055, 228, 1, 0, 0, 0, 1056, 1057, 3, 389, 194, 0, 1057, 1058, 3, 367, 183, 0, 1058, 1059, 3, 353, 176, 0, 1059, 1060, 5, 51, 0, 0, 1060, 1061, 5, 56, 0, 0, 1061, 1062, 5, 50, 0, 0, 1062, 230, 1, 0, 0, 0, 1063, 1064, 3, 389, 194, 0, 1064, 1065, 3, 367, 183, 0, 1065, 1066, 3, 353, 176, 0, 1066, 1067, 5, 53, 0, 0, 1067, 1068, 5, 49, 0, 0, 1068, 1069, 5, 50, 0, 0, 1069, 232, 1, 0, 0, 0, 1070, 1071, 3, 377, 188, 0, 1071, 1072, 3, 359, 179, 0, 1072, 1073, 5, 53, 0, 0, 1073, 234, 1, 0, 0, 0, 1074, 1075, 3, 357, 178, 0, 1075, 1076, 3, 381, 190, 0, 1076, 1077, 3, 353, 176, 0, 1077, 1078, 3, 375, 187, 0, 1078, 1079, 3, 361, 180, 0, 1079, 1080, 3, 389, 194, 0, 1080, 1081, 3, 357, 178, 0, 1081, 1082, 3, 361, 180, 0, 1082, 236, 1, 0, 0, 0, 1083, 1084, 3, 369, 184, 0, 1084, 1085, 3, 363, 181, 0, 1085, 238, 1, 0, 0, 0, 1086, 1087, 3, 389, 194, 0, 1087, 1088, 3, 391, 195, 0, 1088, 1089, 3, 387, 193, 0, 1089, 1090, 3, 375, 187, 0, 1090, 1091, 3, 353, 176, 0, 1091, 1092, 3, 379, 189, 0, 1092, 1093, 3, 365, 182, 0, 1093, 240, 1, 0, 0, 0, 1094, 1095, 3, 389, 194, 0, 1095, 1096, 3, 391, 195, 0, 1096, 1097, 3, 387, 193, 0, 1097, 1098, 3, 359, 179, 0, 1098, 1099, 3, 391, 195, 0, 1099, 242, 1, 0, 0, 0, 1100, 1101, 3, 389, 194, 0, 1101, 1102, 3, 353, 176, 0, 1102, 1103, 3, 377, 188, 0, 1103, 1104, 3, 361, 180, 0, 1104, 1105, 3, 391, 195, 0, 1105, 1106, 3, 361, 180, 0, 1106, 1107, 3, 387, 193, 0, 1107, 1108, 3, 377, 188, 0, 1108, 244, 1, 0, 0, 0, 1109, 1110, 3, 369, 184, 0, 1110, 1111, 3, 389, 194, 0, 1111, 1112, 3, 369, 184, 0, 1112, 1113, 3, 387, 193, 0, 1113, 1114, 3, 369, 184, 0, 1114, 246, 1, 0, 0, 0, 1115, 1116, 3, 369, 184, 0, 1116, 1117, 3, 389, 194, 0, 1117, 1118, 3, 393, 196, 0, 1118, 1119, 3, 387, 193, 0, 1119, 1120, 3, 369, 184, 0, 1120, 248, 1, 0, 0, 0, 1121, 1122, 3, 369, 184, 0, 1122, 1123, 3, 389, 194, 0, 1123, 1124, 3, 355, 177, 0, 1124, 1125, 3, 375, 187, 0, 1125, 1126, 3, 353, 176, 0, 1126, 1127, 3, 379, 189, 0, 1127, 1128, 3, 373, 186, 0, 1128, 250, 1, 0, 0, 0, 1129, 1130, 3, 369, 184, 0, 1130, 1131, 3, 389, 194, 0, 1131, 1132, 3, 375, 187, 0, 1132, 1133, 3, 369, 184, 0, 1133, 1134, 3, 391, 195, 0, 1134, 1135, 3, 361, 180, 0, 1135, 1136, 3, 387, 193, 0, 1136, 1137, 3, 353, 176, 0, 1137, 1138, 3, 375, 187, 0, 1138, 252, 1, 0, 0, 0, 1139, 1140, 3, 369, 184, 0, 1140, 1141, 3, 389, 194, 0, 1141, 1142, 3, 379, 189, 0, 1142, 1143, 3, 393, 196, 0, 1143, 1144, 3, 377, 188, 0, 1144, 1145, 3, 361, 180, 0, 1145, 1146, 3, 387, 193, 0, 1146, 1147, 3, 369, 184, 0, 1147, 1148, 3, 357, 178, 0, 1148, 254, 1, 0, 0, 0, 1149, 1150, 3, 387, 193, 0, 1150, 1151, 3, 361, 180, 0, 1151, 1152, 3, 365, 182, 0, 1152, 1153, 3, 361, 180, 0, 1153, 1154, 3, 399, 199, 0, 1154, 256, 1, 0, 0, 0, 1155, 1156, 3, 389, 194, 0, 1156, 1157, 3, 393, 196, 0, 1157, 1158, 3, 355, 177, 0, 1158, 1159, 3, 389, 194, 0, 1159, 1160, 3, 391, 195, 0, 1160, 1161, 3, 387, 193, 0, 1161, 258, 1, 0, 0, 0, 1162, 1163, 3, 387, 193, 0, 1163, 1164, 3, 361, 180, 0, 1164, 1165, 3, 383, 191, 0, 1165, 1166, 3, 375, 187, 0, 1166, 1167, 3, 353, 176, 0, 1167, 1168, 3, 357, 178, 0, 1168, 1169, 3, 361, 180, 0, 1169, 260, 1, 0, 0, 0, 1170, 1171, 3, 361, 180, 0, 1171, 1172, 3, 399, 199, 0, 1172, 1173, 3, 369, 184, 0, 1173, 1174, 3, 389, 194, 0, 1174, 1175, 3, 391, 195, 0, 1175, 1176, 3, 389, 194, 0, 1176, 262, 1, 0, 0, 0, 1177, 1178, 3, 357, 178, 0, 1178, 1179, 3, 381, 190, 0, 1179, 1180, 3, 393, 196, 0, 1180, 1181, 3, 379, 189, 0, 1181, 1182, 3, 391, 195, 0, 1182, 264, 1, 0, 0, 0, 1183, 1184, 3, 389, 194, 0, 1184, 1185, 3, 393, 196, 0, 1185, 1186, 3, 377, 188, 0, 1186, 266, 1, 0, 0, 0, 1187, 1188, 3, 377, 188, 0, 1188, 1189, 3, 369, 184, 0, 1189, 1190, 3, 379, 189, 0, 1190, 268, 1, 0, 0, 0, 1191, 1192, 3, 377, 188, 0, 1192, 1193, 3, 353, 176, 0, 1193, 1194, 3, 399, 199, 0, 1194, 270, 1, 0, 0, 0, 1195, 1196, 3, 353, 176, 0, 1196, 1197, 3, 395, 197, 0, 1197, 1198, 3, 365, 182, 0, 1198, 272, 1, 0, 0, 0, 1199, 1200, 3, 389, 194, 0, 1200, 1201, 3, 353, 176, 0, 1201, 1202, 3, 377, 188, 0, 1202, 1203, 3, 383, 191, 0, 1203, 1204, 3, 375, 187, 0, 1204, 1205, 3, 361, 180, 0, 1205, 274, 1, 0, 0, 0, 1206, 1207, 3, 389, 194, 0, 1207, 1208, 3, 361, 180, 0, 1208, 1209, 3, 383, 191, 0, 1209, 1210, 3, 353, 176, 0, 1210, 1211, 3, 387, 193, 0, 1211, 1212, 3, 353, 176, 0, 1212, 1213, 3, 391, 195, 0, 1213, 1214, 3, 381, 190, 0, 1214, 1215, 3, 387, 193, 0, 1215, 276, 1, 0, 0, 0, 1216, 1220, 5, 60, 0, 0, 1217, 1219, 8, 0, 0, 0, 1218, 1217, 1, 0, 0, 0, 1219, 1222, 1, 0, 0, 0, 1220, 1218, 1, 0, 0, 0, 1220, 1221, 1, 0, 0, 0, 1221, 1223, 1, 0, 0, 0, 1222, 1220, 1, 0, 0, 0, 1223, 1224, 5, 62, 0, 0, 1224, 278, 1, 0, 0, 0, 1225, 1227, 3, 333, 166, 0, 1226, 1225, 1, 0, 0, 0, 1226, 1227, 1, 0, 0, 0, 1227, 1228, 1, 0, 0, 0, 1228, 1229, 5, 58, 0, 0, 1229, 280, 1, 0, 0, 0, 1230, 1231, 3, 279, 139, 0, 1231, 1232, 3, 335, 167, 0, 1232, 282, 1, 0, 0, 0, 1233, 1234, 5, 95, 0, 0, 1234, 1235, 5, 58, 0, 0, 1235, 1238, 1, 0, 0, 0, 1236, 1239, 3, 327, 163, 0, 1237, 1239, 3, 347, 173, 0, 1238, 1236, 1, 0, 0, 0, 1238, 1237, 1, 0, 0, 0, 1239, 1248, 1, 0, 0, 0, 1240, 1243, 3, 331, 165, 0, 1241, 1243, 5, 46, 0, 0, 1242, 1240, 1, 0, 0, 0, 1242, 1241, 1, 0, 0, 0, 1243, 1246, 1, 0, 0, 0, 1244, 1242, 1, 0, 0, 0, 1244, 1245, 1, 0, 0, 0, 1245, 1247, 1, 0, 0, 0, 1246, 1244, 1, 0, 0, 0, 1247, 1249, 3, 331, 165, 0, 1248, 1244, 1, 0, 0, 0, 1248, 1249, 1, 0, 0, 0, 1249, 284, 1, 0, 0, 0, 1250, 1251, 5, 63, 0, 0, 1251, 1252, 3, 329, 164, 0, 1252, 286, 1, 0, 0, 0, 1253, 1254, 5, 36, 0, 0, 1254, 1255, 3, 329, 164, 0, 1255, 288, 1, 0, 0, 0, 1256, 1258, 5, 64, 0, 0, 1257, 1259, 7, 1, 0, 0, 1258, 1257, 1, 0, 0, 0, 1259, 1260, 1, 0, 0, 0, 1260, 1258, 1, 0, 0, 0, 1260, 1261, 1, 0, 0, 0, 1261, 1271, 1, 0, 0, 0, 1262, 1265, 5, 45, 0, 0, 1263, 1266, 7, 1, 0, 0, 1264, 1266, 3, 347, 173, 0, 1265, 1263, 1, 0, 0, 0, 1265, 1264, 1, 0, 0, 0, 1266, 1267, 1, 0, 0, 0, 1267, 1265, 1, 0, 0, 0, 1267, 1268, 1, 0, 0, 0, 1268, 1270, 1, 0, 0, 0, 1269, 1262, 1, 0, 0, 0, 1270, 1273, 1, 0, 0, 0, 1271, 1269, 1, 0, 0, 0, 1271, 1272, 1, 0, 0, 0, 1272, 290, 1, 0, 0, 0, 1273, 1271, 1, 0, 0, 0, 1274, 1275, 3, 289, 144, 0, 1275, 1276, 5, 64, 0, 0, 1276, 292, 1, 0, 0, 0, 1277, 1279, 3, 347, 173, 0, 1278, 1277, 1, 0, 0, 0, 1279, 1280, 1, 0, 0, 0, 1280, 1278, 1, 0, 0, 0, 1280, 1281, 1, 0, 0, 0, 1281, 294, 1, 0, 0, 0, 1282, 1284, 3, 347, 173, 0, 1283, 1282, 1, 0, 0, 0, 1284, 1287, 1, 0, 0, 0, 1285, 1283, 1, 0, 0, 0, 1285, 1286, 1, 0, 0, 0, 1286, 1288, 1, 0, 0, 0, 1287, 1285, 1, 0, 0, 0, 1288, 1290, 5, 46, 0, 0, 1289, 1291, 3, 347, 173, 0, 1290, 1289, 1, 0, 0, 0, 1291, 1292, 1, 0, 0, 0, 1292, 1290, 1, 0, 0, 0, 1292, 1293, 1, 0, 0, 0, 1293, 296, 1, 0, 0, 0, 1294, 1296, 3, 347, 173, 0, 1295, 1294, 1, 0, 0, 0, 1296, 1297, 1, 0, 0, 0, 1297, 1295, 1, 0, 0, 0, 1297, 1298, 1, 0, 0, 0, 1298, 1299, 1, 0, 0, 0, 1299, 1303, 5, 46, 0, 0, 1300, 1302, 3, 347, 173, 0, 1301, 1300, 1, 0, 0, 0, 1302, 1305, 1, 0, 0, 0, 1303, 1301, 1, 0, 0, 0, 1303, 1304, 1, 0, 0, 0, 1304, 1306, 1, 0, 0, 0, 1305, 1303, 1, 0, 0, 0, 1306, 1307, 3, 311, 155, 0, 1307, 1324, 1, 0, 0, 0, 1308, 1310, 5, 46, 0, 0, 1309, 1311, 3, 347, 173, 0, 1310, 1309, 1, 0, 0, 0, 1311, 1312, 1, 0, 0, 0, 1312, 1310, 1, 0, 0, 0, 1312, 1313, 1, 0, 0, 0, 1313, 1314, 1, 0, 0, 0, 1314, 1315, 3, 311, 155, 0, 1315, 1324, 1, 0, 0, 0, 1316, 1318, 3, 347, 173, 0, 1317, 1316, 1, 0, 0, 0, 1318, 1319, 1, 0, 0, 0, 1319, 1317, 1, 0, 0, 0, 1319, 1320, 1, 0, 0, 0, 1320, 1321, 1, 0, 0, 0, 1321, 1322, 3, 311, 155, 0, 1322, 1324, 1, 0, 0, 0, 1323, 1295, 1, 0, 0, 0, 1323, 1308, 1, 0, 0, 0, 1323, 1317, 1, 0, 0, 0, 1324, 298, 1, 0, 0, 0, 1325, 1326, 5, 43, 0, 0, 1326, 1327, 3, 293, 146, 0, 1327, 300, 1, 0, 0, 0, 1328, 1329, 5, 43, 0, 0, 1329, 1330, 3, 295, 147, 0, 1330, 302, 1, 0, 0, 0, 1331, 1332, 5, 43, 0, 0, 1332, 1333, 3, 297, 148, 0, 1333, 304, 1, 0, 0, 0, 1334, 1335, 5, 45, 0, 0, 1335, 1336, 3, 293, 146, 0, 1336, 306, 1, 0, 0, 0, 1337, 1338, 5, 45, 0, 0, 1338, 1339, 3, 295, 147, 0, 1339, 308, 1, 0, 0, 0, 1340, 1341, 5, 45, 0, 0, 1341, 1342, 3, 297, 148, 0, 1342, 310, 1, 0, 0, 0, 1343, 1345, 7, 2, 0, 0, 1344, 1346, 7, 3, 0, 0, 1345, 1344, 1, 0, 0, 0, 1345, 1346, 1, 0, 0, 0, 1346, 1348, 1, 0, 0, 0, 1347, 1349, 3, 347, 173, 0, 1348, 1347, 1, 0, 0, 0, 1349, 1350, 1, 0, 0, 0, 1350, 1348, 1, 0, 0, 0, 1350, 1351, 1, 0, 0, 0, 1351, 312, 1, 0, 0, 0, 1352, 1357, 5, 39, 0, 0, 1353, 1356, 8, 4, 0, 0, 1354, 1356, 3, 321, 160, 0, 1355, 1353, 1, 0, 0, 0, 1355, 1354, 1, 0, 0, 0, 1356, 1359, 1, 0, 0, 0, 1357, 1355, 1, 0, 0, 0, 1357, 1358, 1, 0, 0, 0, 1358, 1360, 1, 0, 0, 0, 1359, 1357, 1, 0, 0, 0, 1360, 1361, 5, 39, 0, 0, 1361, 314, 1, 0, 0, 0, 1362, 1367, 5, 34, 0, 0, 1363, 1366, 8, 5, 0, 0, 1364, 1366, 3, 321, 160, 0, 1365, 1363, 1, 0, 0, 0, 1365, 1364, 1, 0, 0, 0, 1366, 1369, 1, 0, 0, 0, 1367, 1365, 1, 0, 0, 0, 1367, 1368, 1, 0, 0, 0, 1368, 1370, 1, 0, 0, 0, 1369, 1367, 1, 0, 0, 0, 1370, 1371, 5, 34, 0, 0, 1371, 316, 1, 0, 0, 0, 1372, 1373, 5, 39, 0, 0, 1373, 1374, 5, 39, 0, 0, 1374, 1375, 5, 39, 0, 0, 1375, 1387, 1, 0, 0, 0, 1376, 1380, 5, 39, 0, 0, 1377, 1378, 5, 39, 0, 0, 1378, 1380, 5, 39, 0, 0, 1379, 1376, 1, 0, 0, 0, 1379, 1377, 1, 0, 0, 0, 1379, 1380, 1, 0, 0, 0, 1380, 1383, 1, 0, 0, 0, 1381, 1384, 8, 6, 0, 0, 1382, 1384, 3, 321, 160, 0, 1383, 1381, 1, 0, 0, 0, 1383, 1382, 1, 0, 0, 0, 1384, 1386, 1, 0, 0, 0, 1385, 1379, 1, 0, 0, 0, 1386, 1389, 1, 0, 0, 0, 1387, 1385, 1, 0, 0, 0, 1387, 1388, 1, 0, 0, 0, 1388, 1390, 1, 0, 0, 0, 1389, 1387, 1, 0, 0, 0, 1390, 1391, 5, 39, 0, 0, 1391, 1392, 5, 39, 0, 0, 1392, 1393, 5, 39, 0, 0, 1393, 318, 1, 0, 0, 0, 1394, 1395, 5, 34, 0, 0, 1395, 1396, 5, 34, 0, 0, 1396, 1397, 5, 34, 0, 0, 1397, 1409, 1, 0, 0, 0, 1398, 1402, 5, 34, 0, 0, 1399, 1400, 5, 34, 0, 0, 1400, 1402, 5, 34, 0, 0, 1401, 1398, 1, 0, 0, 0, 1401, 1399, 1, 0, 0, 0, 1401, 1402, 1, 0, 0, 0, 1402, 1405, 1, 0, 0, 0, 1403, 1406, 8, 7, 0, 0, 1404, 1406, 3, 321, 160, 0, 1405, 1403, 1, 0, 0, 0, 1405, 1404, 1, 0, 0, 0, 1406, 1408, 1, 0, 0, 0, 1407, 1401, 1, 0, 0, 0, 1408, 1411, 1, 0, 0, 0, 1409, 1407, 1, 0, 0, 0, 1409, 1410, 1, 0, 0, 0, 1410, 1412, 1, 0, 0, 0, 1411, 1409, 1, 0, 0, 0, 1412, 1413, 5, 34, 0, 0, 1413, 1414, 5, 34, 0, 0, 1414, 1415, 5, 34, 0, 0, 1415, 320, 1, 0, 0, 0, 1416, 1417, 5, 92, 0, 0, 1417, 1418, 7, 8, 0, 0, 1418, 322, 1, 0, 0, 0, 1419, 1423, 5, 40, 0, 0, 1420, 1422, 3, 349, 174, 0, 1421, 1420, 1, 0, 0, 0, 1422, 1425, 1, 0, 0, 0, 1423, 1421, 1, 0, 0, 0, 1423, 1424, 1, 0, 0, 0, 1424, 1426, 1, 0, 0, 0, 1425, 1423, 1, 0, 0, 0, 1426, 1427, 5, 41, 0, 0, 1427, 324, 1, 0, 0, 0, 1428, 1432, 5, 91, 0, 0, 1429, 1431, 3, 349, 174, 0, 1430, 1429, 1, 0, 0, 0, 1431, 1434, 1, 0, 0, 0, 1432, 1430, 1, 0, 0, 0, 1432, 1433, 1, 0, 0, 0, 1433, 1435, 1, 0, 0, 0, 1434, 1432, 1, 0, 0, 0, 1435, 1436, 5, 93, 0, 0, 1436, 326, 1, 0, 0, 0, 1437, 1440, 3, 345, 172, 0, 1438, 1440, 5, 95, 0, 0, 1439, 1437, 1, 0, 0, 0, 1439, 1438, 1, 0, 0, 0, 1440, 328, 1, 0, 0, 0, 1441, 1444, 3, 327, 163, 0, 1442, 1444, 3, 347, 173, 0, 1443, 1441, 1, 0, 0, 0, 1443, 1442, 1, 0, 0, 0, 1444, 1450, 1, 0, 0, 0, 1445, 1449, 3, 327, 163, 0, 1446, 1449, 3, 347, 173, 0, 1447, 1449, 7, 9, 0, 0, 1448, 1445, 1, 0, 0, 0, 1448, 1446, 1, 0, 0, 0, 1448, 1447, 1, 0, 0, 0, 1449, 1452, 1, 0, 0, 0, 1450, 1448, 1, 0, 0, 0, 1450, 1451, 1, 0, 0, 0, 1451, 330, 1, 0, 0, 0, 1452, 1450, 1, 0, 0, 0, 1453, 1458, 3, 327, 163, 0, 1454, 1458, 5, 45, 0, 0, 1455, 1458, 3, 347, 173, 0, 1456, 1458, 7, 9, 0, 0, 1457, 1453, 1, 0, 0, 0, 1457, 1454, 1, 0, 0, 0, 1457, 1455, 1, 0, 0, 0, 1457, 1456, 1, 0, 0, 0, 1458, 332, 1, 0, 0, 0, 1459, 1468, 3, 345, 172, 0, 1460, 1463, 3, 331, 165, 0, 1461, 1463, 5, 46, 0, 0, 1462, 1460, 1, 0, 0, 0, 1462, 1461, 1, 0, 0, 0, 1463, 1466, 1, 0, 0, 0, 1464, 1462, 1, 0, 0, 0, 1464, 1465, 1, 0, 0, 0, 1465, 1467, 1, 0, 0, 0, 1466, 1464, 1, 0, 0, 0, 1467, 1469, 3, 331, 165, 0, 1468, 1464, 1, 0, 0, 0, 1468, 1469, 1, 0, 0, 0, 1469, 334, 1, 0, 0, 0, 1470, 1475, 3, 327, 163, 0, 1471, 1475, 5, 58, 0, 0, 1472, 1475, 3, 347, 173, 0, 1473, 1475, 3, 337, 168, 0, 1474, 1470, 1, 0, 0, 0, 1474, 1471, 1, 0, 0, 0, 1474, 1472, 1, 0, 0, 0, 1474, 1473, 1, 0, 0, 0, 1475, 1489, 1, 0, 0, 0, 1476, 1480, 3, 331, 165, 0, 1477, 1480, 7, 10, 0, 0, 1478, 1480, 3, 337, 168, 0, 1479, 1476, 1, 0, 0, 0, 1479, 1477, 1, 0, 0, 0, 1479, 1478, 1, 0, 0, 0, 1480, 1483, 1, 0, 0, 0, 1481, 1479, 1, 0, 0, 0, 1481, 1482, 1, 0, 0, 0, 1482, 1487, 1, 0, 0, 0, 1483, 1481, 1, 0, 0, 0, 1484, 1488, 3, 331, 165, 0, 1485, 1488, 5, 58, 0, 0, 1486, 1488, 3, 337, 168, 0, 1487, 1484, 1, 0, 0, 0, 1487, 1485, 1, 0, 0, 0, 1487, 1486, 1, 0, 0, 0, 1488, 1490, 1, 0, 0, 0, 1489, 1481, 1, 0, 0, 0, 1489, 1490, 1, 0, 0, 0, 1490, 336, 1, 0, 0, 0, 1491, 1494, 3, 339, 169, 0, 1492, 1494, 3, 343, 171, 0, 1493, 1491, 1, 0, 0, 0, 1493, 1492, 1, 0, 0, 0, 1494, 338, 1, 0, 0, 0, 1495, 1496, 5, 37, 0, 0, 1496, 1497, 3, 341, 170, 0, 1497, 1498, 3, 341, 170, 0, 1498, 340, 1, 0, 0, 0, 1499, 1502, 3, 347, 173, 0, 1500, 1502, 7, 11, 0, 0, 1501, 1499, 1, 0, 0, 0, 1501, 1500, 1, 0, 0, 0, 1502, 342, 1, 0, 0, 0, 1503, 1504, 5, 92, 0, 0, 1504, 1505, 7, 12, 0, 0, 1505, 344, 1, 0, 0, 0, 1506, 1507, 7, 13, 0, 0, 1507, 346, 1, 0, 0, 0, 1508, 1509, 2, 48, 57, 0, 1509, 348, 1, 0, 0, 0, 1510, 1512, 7, 14, 0, 0, 1511, 1510, 1, 0, 0, 0, 1512, 1513, 1, 0, 0, 0, 1513, 1511, 1, 0, 0, 0, 1513, 1514, 1, 0, 0, 0, 1514, 1515, 1, 0, 0, 0, 1515, 1516, 6, 174, 0, 0, 1516, 350, 1, 0, 0, 0, 1517, 1521, 5, 35, 0, 0, 1518, 1520, 8, 15, 0, 0, 1519, 1518, 1, 0, 0, 0, 1520, 1523, 1, 0, 0, 0, 1521, 1519, 1, 0, 0, 0, 1521, 1522, 1, 0, 0, 0, 1522, 1524, 1, 0, 0, 0, 1523, 1521, 1, 0, 0, 0, 1524, 1525, 6, 175, 0, 0, 1525, 352, 1, 0, 0, 0, 1526, 1527, 7, 16, 0, 0, 1527, 354, 1, 0, 0, 0, 1528, 1529, 7, 17, 0, 0, 1529, 356, 1, 0, 0, 0, 1530, 1531, 7, 18, 0, 0, 1531, 358, 1, 0, 0, 0, 1532, 1533, 7, 19, 0, 0, 1533, 360, 1, 0, 0, 0, 1534, 1535, 7, 2, 0, 0, 1535, 362, 1, 0, 0, 0, 1536, 1537, 7, 20, 0, 0, 1537, 364, 1, 0, 0, 0, 1538, 1539, 7, 21, 0, 0, 1539, 366, 1, 0, 0, 0, 1540, 1541, 7, 22, 0, 0, 1541, 368, 1, 0, 0, 0, 1542, 1543, 7, 23, 0, 0, 1543, 370, 1, 0, 0, 0, 1544, 1545, 7, 24, 0, 0, 1545, 372, 1, 0, 0, 0, 1546, 1547, 7, 25, 0, 0, 1547, 374, 1, 0, 0, 0, 1548, 1549, 7, 26, 0, 0, 1549, 376, 1, 0, 0, 0, 1550, 1551, 7, 27, 0, 0, 1551, 378, 1, 0, 0, 0, 1552, 1553, 7, 28, 0, 0, 1553, 380, 1, 0, 0, 0, 1554, 1555, 7, 29, 0, 0, 1555, 382, 1, 0, 0, 0, 1556, 1557, 7, 30, 0, 0, 1557, 384, 1, 0, 0, 0, 1558, 1559, 7, 31, 0, 0, 1559, 386, 1, 0, 0, 0, 1560, 1561, 7, 32, 0, 0, 1561, 388, 1, 0, 0, 0, 1562, 1563, 7, 33, 0, 0, 1563, 390, 1, 0, 0, 0, 1564, 1565, 7, 34, 0, 0, 1565, 392, 1, 0, 0, 0, 1566, 1567, 7, 35, 0, 0, 1567, 394, 1, 0, 0, 0, 1568, 1569, 7, 36, 0, 0, 1569, 396, 1, 0, 0, 0, 1570, 1571, 7, 37, 0, 0, 1571, 398, 1, 0, 0, 0, 1572, 1573, 7, 38, 0, 0, 1573, 400, 1, 0, 0, 0, 1574, 1575, 7, 39, 0, 0, 1575, 402, 1, 0, 0, 0, 1576, 1577, 7, 40, 0, 0, 1577, 404, 1, 0, 0, 0, 54, 0, 563, 596, 612, 621, 1220, 1226, 1238, 1242, 1244, 1248, 1260, 1265, 1267, 1271, 1280, 1285, 1292, 1297, 1303, 1312, 1319, 1323, 1345, 1350, 1355, 1357, 1365, 1367, 1379, 1383, 1387, 1401, 1405, 1409, 1423, 1432, 1439, 1443, 1448, 1450, 1457, 1462, 1464, 1468, 1474, 1479, 1481, 1487, 1489, 1493, 1501, 1513, 1521, 1, 6, 0, 0] \ No newline at end of file +[4, 0, 175, 1590, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 2, 93, 7, 93, 2, 94, 7, 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, 2, 103, 7, 103, 2, 104, 7, 104, 2, 105, 7, 105, 2, 106, 7, 106, 2, 107, 7, 107, 2, 108, 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, 111, 7, 111, 2, 112, 7, 112, 2, 113, 7, 113, 2, 114, 7, 114, 2, 115, 7, 115, 2, 116, 7, 116, 2, 117, 7, 117, 2, 118, 7, 118, 2, 119, 7, 119, 2, 120, 7, 120, 2, 121, 7, 121, 2, 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, 7, 130, 2, 131, 7, 131, 2, 132, 7, 132, 2, 133, 7, 133, 2, 134, 7, 134, 2, 135, 7, 135, 2, 136, 7, 136, 2, 137, 7, 137, 2, 138, 7, 138, 2, 139, 7, 139, 2, 140, 7, 140, 2, 141, 7, 141, 2, 142, 7, 142, 2, 143, 7, 143, 2, 144, 7, 144, 2, 145, 7, 145, 2, 146, 7, 146, 2, 147, 7, 147, 2, 148, 7, 148, 2, 149, 7, 149, 2, 150, 7, 150, 2, 151, 7, 151, 2, 152, 7, 152, 2, 153, 7, 153, 2, 154, 7, 154, 2, 155, 7, 155, 2, 156, 7, 156, 2, 157, 7, 157, 2, 158, 7, 158, 2, 159, 7, 159, 2, 160, 7, 160, 2, 161, 7, 161, 2, 162, 7, 162, 2, 163, 7, 163, 2, 164, 7, 164, 2, 165, 7, 165, 2, 166, 7, 166, 2, 167, 7, 167, 2, 168, 7, 168, 2, 169, 7, 169, 2, 170, 7, 170, 2, 171, 7, 171, 2, 172, 7, 172, 2, 173, 7, 173, 2, 174, 7, 174, 2, 175, 7, 175, 2, 176, 7, 176, 2, 177, 7, 177, 2, 178, 7, 178, 2, 179, 7, 179, 2, 180, 7, 180, 2, 181, 7, 181, 2, 182, 7, 182, 2, 183, 7, 183, 2, 184, 7, 184, 2, 185, 7, 185, 2, 186, 7, 186, 2, 187, 7, 187, 2, 188, 7, 188, 2, 189, 7, 189, 2, 190, 7, 190, 2, 191, 7, 191, 2, 192, 7, 192, 2, 193, 7, 193, 2, 194, 7, 194, 2, 195, 7, 195, 2, 196, 7, 196, 2, 197, 7, 197, 2, 198, 7, 198, 2, 199, 7, 199, 2, 200, 7, 200, 2, 201, 7, 201, 2, 202, 7, 202, 2, 203, 7, 203, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 4, 41, 566, 8, 41, 11, 41, 12, 41, 567, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 4, 44, 599, 8, 44, 11, 44, 12, 44, 600, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 4, 45, 615, 8, 45, 11, 45, 12, 45, 616, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 4, 45, 624, 8, 45, 11, 45, 12, 45, 625, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 77, 1, 77, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 84, 1, 84, 1, 84, 1, 84, 1, 85, 1, 85, 1, 85, 1, 85, 1, 86, 1, 86, 1, 86, 1, 86, 1, 86, 1, 86, 1, 87, 1, 87, 1, 87, 1, 87, 1, 87, 1, 88, 1, 88, 1, 88, 1, 88, 1, 89, 1, 89, 1, 89, 1, 89, 1, 89, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 91, 1, 91, 1, 91, 1, 91, 1, 91, 1, 91, 1, 92, 1, 92, 1, 92, 1, 92, 1, 92, 1, 92, 1, 92, 1, 93, 1, 93, 1, 93, 1, 93, 1, 93, 1, 93, 1, 93, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 95, 1, 95, 1, 95, 1, 95, 1, 95, 1, 95, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 97, 1, 97, 1, 97, 1, 97, 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 105, 1, 105, 1, 105, 1, 105, 1, 106, 1, 106, 1, 106, 1, 106, 1, 106, 1, 106, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 110, 1, 110, 1, 110, 1, 111, 1, 111, 1, 111, 1, 111, 1, 112, 1, 112, 1, 112, 1, 112, 1, 112, 1, 113, 1, 113, 1, 113, 1, 113, 1, 113, 1, 113, 1, 113, 1, 113, 1, 114, 1, 114, 1, 114, 1, 114, 1, 114, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, 116, 1, 116, 1, 116, 1, 116, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 118, 1, 118, 1, 118, 1, 118, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 120, 1, 120, 1, 120, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 122, 1, 122, 1, 122, 1, 122, 1, 122, 1, 122, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 134, 1, 134, 1, 134, 1, 134, 1, 135, 1, 135, 1, 135, 1, 135, 1, 136, 1, 136, 1, 136, 1, 136, 1, 137, 1, 137, 1, 137, 1, 137, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 140, 1, 140, 5, 140, 1231, 8, 140, 10, 140, 12, 140, 1234, 9, 140, 1, 140, 1, 140, 1, 141, 3, 141, 1239, 8, 141, 1, 141, 1, 141, 1, 142, 1, 142, 1, 142, 1, 143, 1, 143, 1, 143, 1, 143, 1, 143, 3, 143, 1251, 8, 143, 1, 143, 1, 143, 5, 143, 1255, 8, 143, 10, 143, 12, 143, 1258, 9, 143, 1, 143, 3, 143, 1261, 8, 143, 1, 144, 1, 144, 1, 144, 1, 145, 1, 145, 1, 145, 1, 146, 1, 146, 4, 146, 1271, 8, 146, 11, 146, 12, 146, 1272, 1, 146, 1, 146, 1, 146, 4, 146, 1278, 8, 146, 11, 146, 12, 146, 1279, 5, 146, 1282, 8, 146, 10, 146, 12, 146, 1285, 9, 146, 1, 147, 1, 147, 1, 147, 1, 148, 4, 148, 1291, 8, 148, 11, 148, 12, 148, 1292, 1, 149, 5, 149, 1296, 8, 149, 10, 149, 12, 149, 1299, 9, 149, 1, 149, 1, 149, 4, 149, 1303, 8, 149, 11, 149, 12, 149, 1304, 1, 150, 4, 150, 1308, 8, 150, 11, 150, 12, 150, 1309, 1, 150, 1, 150, 5, 150, 1314, 8, 150, 10, 150, 12, 150, 1317, 9, 150, 1, 150, 1, 150, 1, 150, 1, 150, 4, 150, 1323, 8, 150, 11, 150, 12, 150, 1324, 1, 150, 1, 150, 1, 150, 4, 150, 1330, 8, 150, 11, 150, 12, 150, 1331, 1, 150, 1, 150, 3, 150, 1336, 8, 150, 1, 151, 1, 151, 1, 151, 1, 152, 1, 152, 1, 152, 1, 153, 1, 153, 1, 153, 1, 154, 1, 154, 1, 154, 1, 155, 1, 155, 1, 155, 1, 156, 1, 156, 1, 156, 1, 157, 1, 157, 3, 157, 1358, 8, 157, 1, 157, 4, 157, 1361, 8, 157, 11, 157, 12, 157, 1362, 1, 158, 1, 158, 1, 158, 5, 158, 1368, 8, 158, 10, 158, 12, 158, 1371, 9, 158, 1, 158, 1, 158, 1, 159, 1, 159, 1, 159, 5, 159, 1378, 8, 159, 10, 159, 12, 159, 1381, 9, 159, 1, 159, 1, 159, 1, 160, 1, 160, 1, 160, 1, 160, 1, 160, 1, 160, 1, 160, 3, 160, 1392, 8, 160, 1, 160, 1, 160, 3, 160, 1396, 8, 160, 5, 160, 1398, 8, 160, 10, 160, 12, 160, 1401, 9, 160, 1, 160, 1, 160, 1, 160, 1, 160, 1, 161, 1, 161, 1, 161, 1, 161, 1, 161, 1, 161, 1, 161, 3, 161, 1414, 8, 161, 1, 161, 1, 161, 3, 161, 1418, 8, 161, 5, 161, 1420, 8, 161, 10, 161, 12, 161, 1423, 9, 161, 1, 161, 1, 161, 1, 161, 1, 161, 1, 162, 1, 162, 1, 162, 1, 163, 1, 163, 5, 163, 1434, 8, 163, 10, 163, 12, 163, 1437, 9, 163, 1, 163, 1, 163, 1, 164, 1, 164, 5, 164, 1443, 8, 164, 10, 164, 12, 164, 1446, 9, 164, 1, 164, 1, 164, 1, 165, 1, 165, 3, 165, 1452, 8, 165, 1, 166, 1, 166, 3, 166, 1456, 8, 166, 1, 166, 1, 166, 1, 166, 5, 166, 1461, 8, 166, 10, 166, 12, 166, 1464, 9, 166, 1, 167, 1, 167, 1, 167, 1, 167, 3, 167, 1470, 8, 167, 1, 168, 1, 168, 1, 168, 5, 168, 1475, 8, 168, 10, 168, 12, 168, 1478, 9, 168, 1, 168, 3, 168, 1481, 8, 168, 1, 169, 1, 169, 1, 169, 1, 169, 3, 169, 1487, 8, 169, 1, 169, 1, 169, 1, 169, 5, 169, 1492, 8, 169, 10, 169, 12, 169, 1495, 9, 169, 1, 169, 1, 169, 1, 169, 3, 169, 1500, 8, 169, 3, 169, 1502, 8, 169, 1, 170, 1, 170, 3, 170, 1506, 8, 170, 1, 171, 1, 171, 1, 171, 1, 171, 1, 172, 1, 172, 3, 172, 1514, 8, 172, 1, 173, 1, 173, 1, 173, 1, 174, 1, 174, 1, 175, 1, 175, 1, 176, 4, 176, 1524, 8, 176, 11, 176, 12, 176, 1525, 1, 176, 1, 176, 1, 177, 1, 177, 5, 177, 1532, 8, 177, 10, 177, 12, 177, 1535, 9, 177, 1, 177, 1, 177, 1, 178, 1, 178, 1, 179, 1, 179, 1, 180, 1, 180, 1, 181, 1, 181, 1, 182, 1, 182, 1, 183, 1, 183, 1, 184, 1, 184, 1, 185, 1, 185, 1, 186, 1, 186, 1, 187, 1, 187, 1, 188, 1, 188, 1, 189, 1, 189, 1, 190, 1, 190, 1, 191, 1, 191, 1, 192, 1, 192, 1, 193, 1, 193, 1, 194, 1, 194, 1, 195, 1, 195, 1, 196, 1, 196, 1, 197, 1, 197, 1, 198, 1, 198, 1, 199, 1, 199, 1, 200, 1, 200, 1, 201, 1, 201, 1, 202, 1, 202, 1, 203, 1, 203, 0, 0, 204, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 34, 69, 35, 71, 36, 73, 37, 75, 38, 77, 39, 79, 40, 81, 41, 83, 42, 85, 43, 87, 44, 89, 45, 91, 46, 93, 47, 95, 48, 97, 49, 99, 50, 101, 51, 103, 52, 105, 53, 107, 54, 109, 55, 111, 56, 113, 57, 115, 58, 117, 59, 119, 60, 121, 61, 123, 62, 125, 63, 127, 64, 129, 65, 131, 66, 133, 67, 135, 68, 137, 69, 139, 70, 141, 71, 143, 72, 145, 73, 147, 74, 149, 75, 151, 76, 153, 77, 155, 78, 157, 79, 159, 80, 161, 81, 163, 82, 165, 83, 167, 84, 169, 85, 171, 86, 173, 87, 175, 88, 177, 89, 179, 90, 181, 91, 183, 92, 185, 93, 187, 94, 189, 95, 191, 96, 193, 97, 195, 98, 197, 99, 199, 100, 201, 101, 203, 102, 205, 103, 207, 104, 209, 105, 211, 106, 213, 107, 215, 108, 217, 109, 219, 110, 221, 111, 223, 112, 225, 113, 227, 114, 229, 115, 231, 116, 233, 117, 235, 118, 237, 119, 239, 120, 241, 121, 243, 122, 245, 123, 247, 124, 249, 125, 251, 126, 253, 127, 255, 128, 257, 129, 259, 130, 261, 131, 263, 132, 265, 133, 267, 134, 269, 135, 271, 136, 273, 137, 275, 138, 277, 139, 279, 140, 281, 141, 283, 142, 285, 143, 287, 144, 289, 145, 291, 146, 293, 147, 295, 148, 297, 149, 299, 150, 301, 151, 303, 152, 305, 153, 307, 154, 309, 155, 311, 156, 313, 157, 315, 158, 317, 159, 319, 160, 321, 161, 323, 162, 325, 163, 327, 164, 329, 165, 331, 166, 333, 167, 335, 0, 337, 168, 339, 169, 341, 170, 343, 171, 345, 172, 347, 173, 349, 0, 351, 0, 353, 174, 355, 175, 357, 0, 359, 0, 361, 0, 363, 0, 365, 0, 367, 0, 369, 0, 371, 0, 373, 0, 375, 0, 377, 0, 379, 0, 381, 0, 383, 0, 385, 0, 387, 0, 389, 0, 391, 0, 393, 0, 395, 0, 397, 0, 399, 0, 401, 0, 403, 0, 405, 0, 407, 0, 1, 0, 41, 8, 0, 0, 32, 34, 34, 60, 60, 62, 62, 92, 92, 94, 94, 96, 96, 123, 125, 2, 0, 65, 90, 97, 122, 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 4, 0, 10, 10, 13, 13, 39, 39, 92, 92, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 2, 0, 39, 39, 92, 92, 2, 0, 34, 34, 92, 92, 8, 0, 34, 34, 39, 39, 92, 92, 98, 98, 102, 102, 110, 110, 114, 114, 116, 116, 3, 0, 183, 183, 768, 879, 8255, 8256, 2, 0, 46, 46, 58, 58, 2, 0, 65, 70, 97, 102, 7, 0, 33, 33, 35, 47, 59, 59, 61, 61, 63, 64, 95, 95, 126, 126, 13, 0, 65, 90, 97, 122, 192, 214, 216, 246, 248, 767, 880, 893, 895, 8191, 8204, 8205, 8304, 8591, 11264, 12271, 12289, 55295, 63744, 64975, 65008, 65533, 3, 0, 9, 10, 13, 13, 32, 32, 2, 0, 10, 10, 13, 13, 2, 0, 65, 65, 97, 97, 2, 0, 66, 66, 98, 98, 2, 0, 67, 67, 99, 99, 2, 0, 68, 68, 100, 100, 2, 0, 70, 70, 102, 102, 2, 0, 71, 71, 103, 103, 2, 0, 72, 72, 104, 104, 2, 0, 73, 73, 105, 105, 2, 0, 74, 74, 106, 106, 2, 0, 75, 75, 107, 107, 2, 0, 76, 76, 108, 108, 2, 0, 77, 77, 109, 109, 2, 0, 78, 78, 110, 110, 2, 0, 79, 79, 111, 111, 2, 0, 80, 80, 112, 112, 2, 0, 81, 81, 113, 113, 2, 0, 82, 82, 114, 114, 2, 0, 83, 83, 115, 115, 2, 0, 84, 84, 116, 116, 2, 0, 85, 85, 117, 117, 2, 0, 86, 86, 118, 118, 2, 0, 87, 87, 119, 119, 2, 0, 88, 88, 120, 120, 2, 0, 89, 89, 121, 121, 2, 0, 90, 90, 122, 122, 1623, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, 0, 0, 95, 1, 0, 0, 0, 0, 97, 1, 0, 0, 0, 0, 99, 1, 0, 0, 0, 0, 101, 1, 0, 0, 0, 0, 103, 1, 0, 0, 0, 0, 105, 1, 0, 0, 0, 0, 107, 1, 0, 0, 0, 0, 109, 1, 0, 0, 0, 0, 111, 1, 0, 0, 0, 0, 113, 1, 0, 0, 0, 0, 115, 1, 0, 0, 0, 0, 117, 1, 0, 0, 0, 0, 119, 1, 0, 0, 0, 0, 121, 1, 0, 0, 0, 0, 123, 1, 0, 0, 0, 0, 125, 1, 0, 0, 0, 0, 127, 1, 0, 0, 0, 0, 129, 1, 0, 0, 0, 0, 131, 1, 0, 0, 0, 0, 133, 1, 0, 0, 0, 0, 135, 1, 0, 0, 0, 0, 137, 1, 0, 0, 0, 0, 139, 1, 0, 0, 0, 0, 141, 1, 0, 0, 0, 0, 143, 1, 0, 0, 0, 0, 145, 1, 0, 0, 0, 0, 147, 1, 0, 0, 0, 0, 149, 1, 0, 0, 0, 0, 151, 1, 0, 0, 0, 0, 153, 1, 0, 0, 0, 0, 155, 1, 0, 0, 0, 0, 157, 1, 0, 0, 0, 0, 159, 1, 0, 0, 0, 0, 161, 1, 0, 0, 0, 0, 163, 1, 0, 0, 0, 0, 165, 1, 0, 0, 0, 0, 167, 1, 0, 0, 0, 0, 169, 1, 0, 0, 0, 0, 171, 1, 0, 0, 0, 0, 173, 1, 0, 0, 0, 0, 175, 1, 0, 0, 0, 0, 177, 1, 0, 0, 0, 0, 179, 1, 0, 0, 0, 0, 181, 1, 0, 0, 0, 0, 183, 1, 0, 0, 0, 0, 185, 1, 0, 0, 0, 0, 187, 1, 0, 0, 0, 0, 189, 1, 0, 0, 0, 0, 191, 1, 0, 0, 0, 0, 193, 1, 0, 0, 0, 0, 195, 1, 0, 0, 0, 0, 197, 1, 0, 0, 0, 0, 199, 1, 0, 0, 0, 0, 201, 1, 0, 0, 0, 0, 203, 1, 0, 0, 0, 0, 205, 1, 0, 0, 0, 0, 207, 1, 0, 0, 0, 0, 209, 1, 0, 0, 0, 0, 211, 1, 0, 0, 0, 0, 213, 1, 0, 0, 0, 0, 215, 1, 0, 0, 0, 0, 217, 1, 0, 0, 0, 0, 219, 1, 0, 0, 0, 0, 221, 1, 0, 0, 0, 0, 223, 1, 0, 0, 0, 0, 225, 1, 0, 0, 0, 0, 227, 1, 0, 0, 0, 0, 229, 1, 0, 0, 0, 0, 231, 1, 0, 0, 0, 0, 233, 1, 0, 0, 0, 0, 235, 1, 0, 0, 0, 0, 237, 1, 0, 0, 0, 0, 239, 1, 0, 0, 0, 0, 241, 1, 0, 0, 0, 0, 243, 1, 0, 0, 0, 0, 245, 1, 0, 0, 0, 0, 247, 1, 0, 0, 0, 0, 249, 1, 0, 0, 0, 0, 251, 1, 0, 0, 0, 0, 253, 1, 0, 0, 0, 0, 255, 1, 0, 0, 0, 0, 257, 1, 0, 0, 0, 0, 259, 1, 0, 0, 0, 0, 261, 1, 0, 0, 0, 0, 263, 1, 0, 0, 0, 0, 265, 1, 0, 0, 0, 0, 267, 1, 0, 0, 0, 0, 269, 1, 0, 0, 0, 0, 271, 1, 0, 0, 0, 0, 273, 1, 0, 0, 0, 0, 275, 1, 0, 0, 0, 0, 277, 1, 0, 0, 0, 0, 279, 1, 0, 0, 0, 0, 281, 1, 0, 0, 0, 0, 283, 1, 0, 0, 0, 0, 285, 1, 0, 0, 0, 0, 287, 1, 0, 0, 0, 0, 289, 1, 0, 0, 0, 0, 291, 1, 0, 0, 0, 0, 293, 1, 0, 0, 0, 0, 295, 1, 0, 0, 0, 0, 297, 1, 0, 0, 0, 0, 299, 1, 0, 0, 0, 0, 301, 1, 0, 0, 0, 0, 303, 1, 0, 0, 0, 0, 305, 1, 0, 0, 0, 0, 307, 1, 0, 0, 0, 0, 309, 1, 0, 0, 0, 0, 311, 1, 0, 0, 0, 0, 313, 1, 0, 0, 0, 0, 315, 1, 0, 0, 0, 0, 317, 1, 0, 0, 0, 0, 319, 1, 0, 0, 0, 0, 321, 1, 0, 0, 0, 0, 323, 1, 0, 0, 0, 0, 325, 1, 0, 0, 0, 0, 327, 1, 0, 0, 0, 0, 329, 1, 0, 0, 0, 0, 331, 1, 0, 0, 0, 0, 333, 1, 0, 0, 0, 0, 337, 1, 0, 0, 0, 0, 339, 1, 0, 0, 0, 0, 341, 1, 0, 0, 0, 0, 343, 1, 0, 0, 0, 0, 345, 1, 0, 0, 0, 0, 347, 1, 0, 0, 0, 0, 353, 1, 0, 0, 0, 0, 355, 1, 0, 0, 0, 1, 409, 1, 0, 0, 0, 3, 411, 1, 0, 0, 0, 5, 413, 1, 0, 0, 0, 7, 415, 1, 0, 0, 0, 9, 417, 1, 0, 0, 0, 11, 419, 1, 0, 0, 0, 13, 421, 1, 0, 0, 0, 15, 423, 1, 0, 0, 0, 17, 425, 1, 0, 0, 0, 19, 427, 1, 0, 0, 0, 21, 429, 1, 0, 0, 0, 23, 431, 1, 0, 0, 0, 25, 433, 1, 0, 0, 0, 27, 435, 1, 0, 0, 0, 29, 437, 1, 0, 0, 0, 31, 439, 1, 0, 0, 0, 33, 441, 1, 0, 0, 0, 35, 443, 1, 0, 0, 0, 37, 446, 1, 0, 0, 0, 39, 449, 1, 0, 0, 0, 41, 451, 1, 0, 0, 0, 43, 454, 1, 0, 0, 0, 45, 456, 1, 0, 0, 0, 47, 458, 1, 0, 0, 0, 49, 461, 1, 0, 0, 0, 51, 464, 1, 0, 0, 0, 53, 466, 1, 0, 0, 0, 55, 469, 1, 0, 0, 0, 57, 474, 1, 0, 0, 0, 59, 480, 1, 0, 0, 0, 61, 485, 1, 0, 0, 0, 63, 492, 1, 0, 0, 0, 65, 499, 1, 0, 0, 0, 67, 508, 1, 0, 0, 0, 69, 516, 1, 0, 0, 0, 71, 519, 1, 0, 0, 0, 73, 529, 1, 0, 0, 0, 75, 535, 1, 0, 0, 0, 77, 544, 1, 0, 0, 0, 79, 548, 1, 0, 0, 0, 81, 553, 1, 0, 0, 0, 83, 559, 1, 0, 0, 0, 85, 572, 1, 0, 0, 0, 87, 585, 1, 0, 0, 0, 89, 592, 1, 0, 0, 0, 91, 605, 1, 0, 0, 0, 93, 630, 1, 0, 0, 0, 95, 634, 1, 0, 0, 0, 97, 639, 1, 0, 0, 0, 99, 645, 1, 0, 0, 0, 101, 652, 1, 0, 0, 0, 103, 662, 1, 0, 0, 0, 105, 669, 1, 0, 0, 0, 107, 674, 1, 0, 0, 0, 109, 681, 1, 0, 0, 0, 111, 686, 1, 0, 0, 0, 113, 692, 1, 0, 0, 0, 115, 697, 1, 0, 0, 0, 117, 704, 1, 0, 0, 0, 119, 708, 1, 0, 0, 0, 121, 711, 1, 0, 0, 0, 123, 716, 1, 0, 0, 0, 125, 721, 1, 0, 0, 0, 127, 726, 1, 0, 0, 0, 129, 733, 1, 0, 0, 0, 131, 740, 1, 0, 0, 0, 133, 745, 1, 0, 0, 0, 135, 751, 1, 0, 0, 0, 137, 759, 1, 0, 0, 0, 139, 765, 1, 0, 0, 0, 141, 769, 1, 0, 0, 0, 143, 778, 1, 0, 0, 0, 145, 786, 1, 0, 0, 0, 147, 791, 1, 0, 0, 0, 149, 797, 1, 0, 0, 0, 151, 803, 1, 0, 0, 0, 153, 809, 1, 0, 0, 0, 155, 816, 1, 0, 0, 0, 157, 820, 1, 0, 0, 0, 159, 823, 1, 0, 0, 0, 161, 827, 1, 0, 0, 0, 163, 832, 1, 0, 0, 0, 165, 844, 1, 0, 0, 0, 167, 853, 1, 0, 0, 0, 169, 859, 1, 0, 0, 0, 171, 863, 1, 0, 0, 0, 173, 867, 1, 0, 0, 0, 175, 873, 1, 0, 0, 0, 177, 878, 1, 0, 0, 0, 179, 882, 1, 0, 0, 0, 181, 887, 1, 0, 0, 0, 183, 893, 1, 0, 0, 0, 185, 899, 1, 0, 0, 0, 187, 906, 1, 0, 0, 0, 189, 913, 1, 0, 0, 0, 191, 919, 1, 0, 0, 0, 193, 925, 1, 0, 0, 0, 195, 940, 1, 0, 0, 0, 197, 944, 1, 0, 0, 0, 199, 953, 1, 0, 0, 0, 201, 963, 1, 0, 0, 0, 203, 971, 1, 0, 0, 0, 205, 981, 1, 0, 0, 0, 207, 990, 1, 0, 0, 0, 209, 995, 1, 0, 0, 0, 211, 1001, 1, 0, 0, 0, 213, 1005, 1, 0, 0, 0, 215, 1011, 1, 0, 0, 0, 217, 1019, 1, 0, 0, 0, 219, 1027, 1, 0, 0, 0, 221, 1036, 1, 0, 0, 0, 223, 1039, 1, 0, 0, 0, 225, 1043, 1, 0, 0, 0, 227, 1048, 1, 0, 0, 0, 229, 1056, 1, 0, 0, 0, 231, 1061, 1, 0, 0, 0, 233, 1068, 1, 0, 0, 0, 235, 1075, 1, 0, 0, 0, 237, 1082, 1, 0, 0, 0, 239, 1086, 1, 0, 0, 0, 241, 1095, 1, 0, 0, 0, 243, 1098, 1, 0, 0, 0, 245, 1106, 1, 0, 0, 0, 247, 1112, 1, 0, 0, 0, 249, 1121, 1, 0, 0, 0, 251, 1127, 1, 0, 0, 0, 253, 1133, 1, 0, 0, 0, 255, 1141, 1, 0, 0, 0, 257, 1151, 1, 0, 0, 0, 259, 1161, 1, 0, 0, 0, 261, 1167, 1, 0, 0, 0, 263, 1174, 1, 0, 0, 0, 265, 1182, 1, 0, 0, 0, 267, 1189, 1, 0, 0, 0, 269, 1195, 1, 0, 0, 0, 271, 1199, 1, 0, 0, 0, 273, 1203, 1, 0, 0, 0, 275, 1207, 1, 0, 0, 0, 277, 1211, 1, 0, 0, 0, 279, 1218, 1, 0, 0, 0, 281, 1228, 1, 0, 0, 0, 283, 1238, 1, 0, 0, 0, 285, 1242, 1, 0, 0, 0, 287, 1245, 1, 0, 0, 0, 289, 1262, 1, 0, 0, 0, 291, 1265, 1, 0, 0, 0, 293, 1268, 1, 0, 0, 0, 295, 1286, 1, 0, 0, 0, 297, 1290, 1, 0, 0, 0, 299, 1297, 1, 0, 0, 0, 301, 1335, 1, 0, 0, 0, 303, 1337, 1, 0, 0, 0, 305, 1340, 1, 0, 0, 0, 307, 1343, 1, 0, 0, 0, 309, 1346, 1, 0, 0, 0, 311, 1349, 1, 0, 0, 0, 313, 1352, 1, 0, 0, 0, 315, 1355, 1, 0, 0, 0, 317, 1364, 1, 0, 0, 0, 319, 1374, 1, 0, 0, 0, 321, 1384, 1, 0, 0, 0, 323, 1406, 1, 0, 0, 0, 325, 1428, 1, 0, 0, 0, 327, 1431, 1, 0, 0, 0, 329, 1440, 1, 0, 0, 0, 331, 1451, 1, 0, 0, 0, 333, 1455, 1, 0, 0, 0, 335, 1469, 1, 0, 0, 0, 337, 1471, 1, 0, 0, 0, 339, 1486, 1, 0, 0, 0, 341, 1505, 1, 0, 0, 0, 343, 1507, 1, 0, 0, 0, 345, 1513, 1, 0, 0, 0, 347, 1515, 1, 0, 0, 0, 349, 1518, 1, 0, 0, 0, 351, 1520, 1, 0, 0, 0, 353, 1523, 1, 0, 0, 0, 355, 1529, 1, 0, 0, 0, 357, 1538, 1, 0, 0, 0, 359, 1540, 1, 0, 0, 0, 361, 1542, 1, 0, 0, 0, 363, 1544, 1, 0, 0, 0, 365, 1546, 1, 0, 0, 0, 367, 1548, 1, 0, 0, 0, 369, 1550, 1, 0, 0, 0, 371, 1552, 1, 0, 0, 0, 373, 1554, 1, 0, 0, 0, 375, 1556, 1, 0, 0, 0, 377, 1558, 1, 0, 0, 0, 379, 1560, 1, 0, 0, 0, 381, 1562, 1, 0, 0, 0, 383, 1564, 1, 0, 0, 0, 385, 1566, 1, 0, 0, 0, 387, 1568, 1, 0, 0, 0, 389, 1570, 1, 0, 0, 0, 391, 1572, 1, 0, 0, 0, 393, 1574, 1, 0, 0, 0, 395, 1576, 1, 0, 0, 0, 397, 1578, 1, 0, 0, 0, 399, 1580, 1, 0, 0, 0, 401, 1582, 1, 0, 0, 0, 403, 1584, 1, 0, 0, 0, 405, 1586, 1, 0, 0, 0, 407, 1588, 1, 0, 0, 0, 409, 410, 5, 42, 0, 0, 410, 2, 1, 0, 0, 0, 411, 412, 5, 40, 0, 0, 412, 4, 1, 0, 0, 0, 413, 414, 5, 41, 0, 0, 414, 6, 1, 0, 0, 0, 415, 416, 5, 123, 0, 0, 416, 8, 1, 0, 0, 0, 417, 418, 5, 125, 0, 0, 418, 10, 1, 0, 0, 0, 419, 420, 5, 59, 0, 0, 420, 12, 1, 0, 0, 0, 421, 422, 5, 46, 0, 0, 422, 14, 1, 0, 0, 0, 423, 424, 5, 44, 0, 0, 424, 16, 1, 0, 0, 0, 425, 426, 5, 97, 0, 0, 426, 18, 1, 0, 0, 0, 427, 428, 5, 124, 0, 0, 428, 20, 1, 0, 0, 0, 429, 430, 5, 47, 0, 0, 430, 22, 1, 0, 0, 0, 431, 432, 5, 94, 0, 0, 432, 24, 1, 0, 0, 0, 433, 434, 5, 43, 0, 0, 434, 26, 1, 0, 0, 0, 435, 436, 5, 63, 0, 0, 436, 28, 1, 0, 0, 0, 437, 438, 5, 33, 0, 0, 438, 30, 1, 0, 0, 0, 439, 440, 5, 91, 0, 0, 440, 32, 1, 0, 0, 0, 441, 442, 5, 93, 0, 0, 442, 34, 1, 0, 0, 0, 443, 444, 5, 124, 0, 0, 444, 445, 5, 124, 0, 0, 445, 36, 1, 0, 0, 0, 446, 447, 5, 38, 0, 0, 447, 448, 5, 38, 0, 0, 448, 38, 1, 0, 0, 0, 449, 450, 5, 61, 0, 0, 450, 40, 1, 0, 0, 0, 451, 452, 5, 33, 0, 0, 452, 453, 5, 61, 0, 0, 453, 42, 1, 0, 0, 0, 454, 455, 5, 60, 0, 0, 455, 44, 1, 0, 0, 0, 456, 457, 5, 62, 0, 0, 457, 46, 1, 0, 0, 0, 458, 459, 5, 60, 0, 0, 459, 460, 5, 61, 0, 0, 460, 48, 1, 0, 0, 0, 461, 462, 5, 62, 0, 0, 462, 463, 5, 61, 0, 0, 463, 50, 1, 0, 0, 0, 464, 465, 5, 45, 0, 0, 465, 52, 1, 0, 0, 0, 466, 467, 5, 94, 0, 0, 467, 468, 5, 94, 0, 0, 468, 54, 1, 0, 0, 0, 469, 470, 5, 116, 0, 0, 470, 471, 5, 114, 0, 0, 471, 472, 5, 117, 0, 0, 472, 473, 5, 101, 0, 0, 473, 56, 1, 0, 0, 0, 474, 475, 5, 102, 0, 0, 475, 476, 5, 97, 0, 0, 476, 477, 5, 108, 0, 0, 477, 478, 5, 115, 0, 0, 478, 479, 5, 101, 0, 0, 479, 58, 1, 0, 0, 0, 480, 481, 3, 359, 179, 0, 481, 482, 3, 357, 178, 0, 482, 483, 3, 393, 196, 0, 483, 484, 3, 365, 182, 0, 484, 60, 1, 0, 0, 0, 485, 486, 3, 387, 193, 0, 486, 487, 3, 391, 195, 0, 487, 488, 3, 365, 182, 0, 488, 489, 3, 367, 183, 0, 489, 490, 3, 373, 186, 0, 490, 491, 3, 403, 201, 0, 491, 62, 1, 0, 0, 0, 492, 493, 3, 393, 196, 0, 493, 494, 3, 365, 182, 0, 494, 495, 3, 379, 189, 0, 495, 496, 3, 365, 182, 0, 496, 497, 3, 361, 180, 0, 497, 498, 3, 395, 197, 0, 498, 64, 1, 0, 0, 0, 499, 500, 3, 363, 181, 0, 500, 501, 3, 373, 186, 0, 501, 502, 3, 393, 196, 0, 502, 503, 3, 395, 197, 0, 503, 504, 3, 373, 186, 0, 504, 505, 3, 383, 191, 0, 505, 506, 3, 361, 180, 0, 506, 507, 3, 395, 197, 0, 507, 66, 1, 0, 0, 0, 508, 509, 3, 391, 195, 0, 509, 510, 3, 365, 182, 0, 510, 511, 3, 363, 181, 0, 511, 512, 3, 397, 198, 0, 512, 513, 3, 361, 180, 0, 513, 514, 3, 365, 182, 0, 514, 515, 3, 363, 181, 0, 515, 68, 1, 0, 0, 0, 516, 517, 3, 357, 178, 0, 517, 518, 3, 393, 196, 0, 518, 70, 1, 0, 0, 0, 519, 520, 3, 361, 180, 0, 520, 521, 3, 385, 192, 0, 521, 522, 3, 383, 191, 0, 522, 523, 3, 393, 196, 0, 523, 524, 3, 395, 197, 0, 524, 525, 3, 391, 195, 0, 525, 526, 3, 397, 198, 0, 526, 527, 3, 361, 180, 0, 527, 528, 3, 395, 197, 0, 528, 72, 1, 0, 0, 0, 529, 530, 3, 401, 200, 0, 530, 531, 3, 371, 185, 0, 531, 532, 3, 365, 182, 0, 532, 533, 3, 391, 195, 0, 533, 534, 3, 365, 182, 0, 534, 74, 1, 0, 0, 0, 535, 536, 3, 363, 181, 0, 536, 537, 3, 365, 182, 0, 537, 538, 3, 393, 196, 0, 538, 539, 3, 361, 180, 0, 539, 540, 3, 391, 195, 0, 540, 541, 3, 373, 186, 0, 541, 542, 3, 359, 179, 0, 542, 543, 3, 365, 182, 0, 543, 76, 1, 0, 0, 0, 544, 545, 3, 357, 178, 0, 545, 546, 3, 393, 196, 0, 546, 547, 3, 377, 188, 0, 547, 78, 1, 0, 0, 0, 548, 549, 3, 367, 183, 0, 549, 550, 3, 391, 195, 0, 550, 551, 3, 385, 192, 0, 551, 552, 3, 381, 190, 0, 552, 80, 1, 0, 0, 0, 553, 554, 3, 383, 191, 0, 554, 555, 3, 357, 178, 0, 555, 556, 3, 381, 190, 0, 556, 557, 3, 365, 182, 0, 557, 558, 3, 363, 181, 0, 558, 82, 1, 0, 0, 0, 559, 560, 3, 369, 184, 0, 560, 561, 3, 391, 195, 0, 561, 562, 3, 385, 192, 0, 562, 563, 3, 397, 198, 0, 563, 565, 3, 387, 193, 0, 564, 566, 3, 353, 176, 0, 565, 564, 1, 0, 0, 0, 566, 567, 1, 0, 0, 0, 567, 565, 1, 0, 0, 0, 567, 568, 1, 0, 0, 0, 568, 569, 1, 0, 0, 0, 569, 570, 3, 359, 179, 0, 570, 571, 3, 405, 202, 0, 571, 84, 1, 0, 0, 0, 572, 573, 3, 369, 184, 0, 573, 574, 3, 391, 195, 0, 574, 575, 3, 385, 192, 0, 575, 576, 3, 397, 198, 0, 576, 577, 3, 387, 193, 0, 577, 578, 5, 95, 0, 0, 578, 579, 3, 361, 180, 0, 579, 580, 3, 385, 192, 0, 580, 581, 3, 383, 191, 0, 581, 582, 3, 361, 180, 0, 582, 583, 3, 357, 178, 0, 583, 584, 3, 395, 197, 0, 584, 86, 1, 0, 0, 0, 585, 586, 3, 371, 185, 0, 586, 587, 3, 357, 178, 0, 587, 588, 3, 399, 199, 0, 588, 589, 3, 373, 186, 0, 589, 590, 3, 383, 191, 0, 590, 591, 3, 369, 184, 0, 591, 88, 1, 0, 0, 0, 592, 593, 3, 385, 192, 0, 593, 594, 3, 391, 195, 0, 594, 595, 3, 363, 181, 0, 595, 596, 3, 365, 182, 0, 596, 598, 3, 391, 195, 0, 597, 599, 3, 353, 176, 0, 598, 597, 1, 0, 0, 0, 599, 600, 1, 0, 0, 0, 600, 598, 1, 0, 0, 0, 600, 601, 1, 0, 0, 0, 601, 602, 1, 0, 0, 0, 602, 603, 3, 359, 179, 0, 603, 604, 3, 405, 202, 0, 604, 90, 1, 0, 0, 0, 605, 606, 3, 373, 186, 0, 606, 607, 3, 383, 191, 0, 607, 608, 3, 395, 197, 0, 608, 609, 3, 365, 182, 0, 609, 610, 3, 391, 195, 0, 610, 611, 3, 383, 191, 0, 611, 612, 3, 357, 178, 0, 612, 614, 3, 379, 189, 0, 613, 615, 3, 353, 176, 0, 614, 613, 1, 0, 0, 0, 615, 616, 1, 0, 0, 0, 616, 614, 1, 0, 0, 0, 616, 617, 1, 0, 0, 0, 617, 618, 1, 0, 0, 0, 618, 619, 3, 393, 196, 0, 619, 620, 3, 385, 192, 0, 620, 621, 3, 391, 195, 0, 621, 623, 3, 395, 197, 0, 622, 624, 3, 353, 176, 0, 623, 622, 1, 0, 0, 0, 624, 625, 1, 0, 0, 0, 625, 623, 1, 0, 0, 0, 625, 626, 1, 0, 0, 0, 626, 627, 1, 0, 0, 0, 627, 628, 3, 359, 179, 0, 628, 629, 3, 405, 202, 0, 629, 92, 1, 0, 0, 0, 630, 631, 3, 357, 178, 0, 631, 632, 3, 393, 196, 0, 632, 633, 3, 361, 180, 0, 633, 94, 1, 0, 0, 0, 634, 635, 3, 363, 181, 0, 635, 636, 3, 365, 182, 0, 636, 637, 3, 393, 196, 0, 637, 638, 3, 361, 180, 0, 638, 96, 1, 0, 0, 0, 639, 640, 3, 379, 189, 0, 640, 641, 3, 373, 186, 0, 641, 642, 3, 381, 190, 0, 642, 643, 3, 373, 186, 0, 643, 644, 3, 395, 197, 0, 644, 98, 1, 0, 0, 0, 645, 646, 3, 385, 192, 0, 646, 647, 3, 367, 183, 0, 647, 648, 3, 367, 183, 0, 648, 649, 3, 393, 196, 0, 649, 650, 3, 365, 182, 0, 650, 651, 3, 395, 197, 0, 651, 100, 1, 0, 0, 0, 652, 653, 3, 395, 197, 0, 653, 654, 3, 365, 182, 0, 654, 655, 3, 403, 201, 0, 655, 656, 3, 395, 197, 0, 656, 657, 3, 379, 189, 0, 657, 658, 3, 373, 186, 0, 658, 659, 3, 381, 190, 0, 659, 660, 3, 373, 186, 0, 660, 661, 3, 395, 197, 0, 661, 102, 1, 0, 0, 0, 662, 663, 3, 399, 199, 0, 663, 664, 3, 357, 178, 0, 664, 665, 3, 379, 189, 0, 665, 666, 3, 397, 198, 0, 666, 667, 3, 365, 182, 0, 667, 668, 3, 393, 196, 0, 668, 104, 1, 0, 0, 0, 669, 670, 3, 379, 189, 0, 670, 671, 3, 385, 192, 0, 671, 672, 3, 357, 178, 0, 672, 673, 3, 363, 181, 0, 673, 106, 1, 0, 0, 0, 674, 675, 3, 393, 196, 0, 675, 676, 3, 373, 186, 0, 676, 677, 3, 379, 189, 0, 677, 678, 3, 365, 182, 0, 678, 679, 3, 383, 191, 0, 679, 680, 3, 395, 197, 0, 680, 108, 1, 0, 0, 0, 681, 682, 3, 373, 186, 0, 682, 683, 3, 383, 191, 0, 683, 684, 3, 395, 197, 0, 684, 685, 3, 385, 192, 0, 685, 110, 1, 0, 0, 0, 686, 687, 3, 361, 180, 0, 687, 688, 3, 379, 189, 0, 688, 689, 3, 365, 182, 0, 689, 690, 3, 357, 178, 0, 690, 691, 3, 391, 195, 0, 691, 112, 1, 0, 0, 0, 692, 693, 3, 363, 181, 0, 693, 694, 3, 391, 195, 0, 694, 695, 3, 385, 192, 0, 695, 696, 3, 387, 193, 0, 696, 114, 1, 0, 0, 0, 697, 698, 3, 361, 180, 0, 698, 699, 3, 391, 195, 0, 699, 700, 3, 365, 182, 0, 700, 701, 3, 357, 178, 0, 701, 702, 3, 395, 197, 0, 702, 703, 3, 365, 182, 0, 703, 116, 1, 0, 0, 0, 704, 705, 3, 357, 178, 0, 705, 706, 3, 363, 181, 0, 706, 707, 3, 363, 181, 0, 707, 118, 1, 0, 0, 0, 708, 709, 3, 395, 197, 0, 709, 710, 3, 385, 192, 0, 710, 120, 1, 0, 0, 0, 711, 712, 3, 363, 181, 0, 712, 713, 3, 357, 178, 0, 713, 714, 3, 395, 197, 0, 714, 715, 3, 357, 178, 0, 715, 122, 1, 0, 0, 0, 716, 717, 3, 381, 190, 0, 717, 718, 3, 385, 192, 0, 718, 719, 3, 399, 199, 0, 719, 720, 3, 365, 182, 0, 720, 124, 1, 0, 0, 0, 721, 722, 3, 361, 180, 0, 722, 723, 3, 385, 192, 0, 723, 724, 3, 387, 193, 0, 724, 725, 3, 405, 202, 0, 725, 126, 1, 0, 0, 0, 726, 727, 3, 373, 186, 0, 727, 728, 3, 383, 191, 0, 728, 729, 3, 393, 196, 0, 729, 730, 3, 365, 182, 0, 730, 731, 3, 391, 195, 0, 731, 732, 3, 395, 197, 0, 732, 128, 1, 0, 0, 0, 733, 734, 3, 363, 181, 0, 734, 735, 3, 365, 182, 0, 735, 736, 3, 379, 189, 0, 736, 737, 3, 365, 182, 0, 737, 738, 3, 395, 197, 0, 738, 739, 3, 365, 182, 0, 739, 130, 1, 0, 0, 0, 740, 741, 3, 401, 200, 0, 741, 742, 3, 373, 186, 0, 742, 743, 3, 395, 197, 0, 743, 744, 3, 371, 185, 0, 744, 132, 1, 0, 0, 0, 745, 746, 3, 397, 198, 0, 746, 747, 3, 393, 196, 0, 747, 748, 3, 373, 186, 0, 748, 749, 3, 383, 191, 0, 749, 750, 3, 369, 184, 0, 750, 134, 1, 0, 0, 0, 751, 752, 3, 363, 181, 0, 752, 753, 3, 365, 182, 0, 753, 754, 3, 367, 183, 0, 754, 755, 3, 357, 178, 0, 755, 756, 3, 397, 198, 0, 756, 757, 3, 379, 189, 0, 757, 758, 3, 395, 197, 0, 758, 136, 1, 0, 0, 0, 759, 760, 3, 369, 184, 0, 760, 761, 3, 391, 195, 0, 761, 762, 3, 357, 178, 0, 762, 763, 3, 387, 193, 0, 763, 764, 3, 371, 185, 0, 764, 138, 1, 0, 0, 0, 765, 766, 3, 357, 178, 0, 766, 767, 3, 379, 189, 0, 767, 768, 3, 379, 189, 0, 768, 140, 1, 0, 0, 0, 769, 770, 3, 385, 192, 0, 770, 771, 3, 387, 193, 0, 771, 772, 3, 395, 197, 0, 772, 773, 3, 373, 186, 0, 773, 774, 3, 385, 192, 0, 774, 775, 3, 383, 191, 0, 775, 776, 3, 357, 178, 0, 776, 777, 3, 379, 189, 0, 777, 142, 1, 0, 0, 0, 778, 779, 3, 393, 196, 0, 779, 780, 3, 365, 182, 0, 780, 781, 3, 391, 195, 0, 781, 782, 3, 399, 199, 0, 782, 783, 3, 373, 186, 0, 783, 784, 3, 361, 180, 0, 784, 785, 3, 365, 182, 0, 785, 144, 1, 0, 0, 0, 786, 787, 3, 359, 179, 0, 787, 788, 3, 373, 186, 0, 788, 789, 3, 383, 191, 0, 789, 790, 3, 363, 181, 0, 790, 146, 1, 0, 0, 0, 791, 792, 3, 397, 198, 0, 792, 793, 3, 383, 191, 0, 793, 794, 3, 363, 181, 0, 794, 795, 3, 365, 182, 0, 795, 796, 3, 367, 183, 0, 796, 148, 1, 0, 0, 0, 797, 798, 3, 381, 190, 0, 798, 799, 3, 373, 186, 0, 799, 800, 3, 383, 191, 0, 800, 801, 3, 397, 198, 0, 801, 802, 3, 393, 196, 0, 802, 150, 1, 0, 0, 0, 803, 804, 3, 397, 198, 0, 804, 805, 3, 383, 191, 0, 805, 806, 3, 373, 186, 0, 806, 807, 3, 385, 192, 0, 807, 808, 3, 383, 191, 0, 808, 152, 1, 0, 0, 0, 809, 810, 3, 367, 183, 0, 810, 811, 3, 373, 186, 0, 811, 812, 3, 379, 189, 0, 812, 813, 3, 395, 197, 0, 813, 814, 3, 365, 182, 0, 814, 815, 3, 391, 195, 0, 815, 154, 1, 0, 0, 0, 816, 817, 3, 383, 191, 0, 817, 818, 3, 385, 192, 0, 818, 819, 3, 395, 197, 0, 819, 156, 1, 0, 0, 0, 820, 821, 3, 373, 186, 0, 821, 822, 3, 383, 191, 0, 822, 158, 1, 0, 0, 0, 823, 824, 3, 393, 196, 0, 824, 825, 3, 395, 197, 0, 825, 826, 3, 391, 195, 0, 826, 160, 1, 0, 0, 0, 827, 828, 3, 379, 189, 0, 828, 829, 3, 357, 178, 0, 829, 830, 3, 383, 191, 0, 830, 831, 3, 369, 184, 0, 831, 162, 1, 0, 0, 0, 832, 833, 3, 379, 189, 0, 833, 834, 3, 357, 178, 0, 834, 835, 3, 383, 191, 0, 835, 836, 3, 369, 184, 0, 836, 837, 3, 381, 190, 0, 837, 838, 3, 357, 178, 0, 838, 839, 3, 395, 197, 0, 839, 840, 3, 361, 180, 0, 840, 841, 3, 371, 185, 0, 841, 842, 3, 365, 182, 0, 842, 843, 3, 393, 196, 0, 843, 164, 1, 0, 0, 0, 844, 845, 3, 363, 181, 0, 845, 846, 3, 357, 178, 0, 846, 847, 3, 395, 197, 0, 847, 848, 3, 357, 178, 0, 848, 849, 3, 395, 197, 0, 849, 850, 3, 405, 202, 0, 850, 851, 3, 387, 193, 0, 851, 852, 3, 365, 182, 0, 852, 166, 1, 0, 0, 0, 853, 854, 3, 359, 179, 0, 854, 855, 3, 385, 192, 0, 855, 856, 3, 397, 198, 0, 856, 857, 3, 383, 191, 0, 857, 858, 3, 363, 181, 0, 858, 168, 1, 0, 0, 0, 859, 860, 3, 373, 186, 0, 860, 861, 3, 391, 195, 0, 861, 862, 3, 373, 186, 0, 862, 170, 1, 0, 0, 0, 863, 864, 3, 397, 198, 0, 864, 865, 3, 391, 195, 0, 865, 866, 3, 373, 186, 0, 866, 172, 1, 0, 0, 0, 867, 868, 3, 359, 179, 0, 868, 869, 3, 383, 191, 0, 869, 870, 3, 385, 192, 0, 870, 871, 3, 363, 181, 0, 871, 872, 3, 365, 182, 0, 872, 174, 1, 0, 0, 0, 873, 874, 3, 391, 195, 0, 874, 875, 3, 357, 178, 0, 875, 876, 3, 383, 191, 0, 876, 877, 3, 363, 181, 0, 877, 176, 1, 0, 0, 0, 878, 879, 3, 357, 178, 0, 879, 880, 3, 359, 179, 0, 880, 881, 3, 393, 196, 0, 881, 178, 1, 0, 0, 0, 882, 883, 3, 361, 180, 0, 883, 884, 3, 365, 182, 0, 884, 885, 3, 373, 186, 0, 885, 886, 3, 379, 189, 0, 886, 180, 1, 0, 0, 0, 887, 888, 3, 367, 183, 0, 888, 889, 3, 379, 189, 0, 889, 890, 3, 385, 192, 0, 890, 891, 3, 385, 192, 0, 891, 892, 3, 391, 195, 0, 892, 182, 1, 0, 0, 0, 893, 894, 3, 391, 195, 0, 894, 895, 3, 385, 192, 0, 895, 896, 3, 397, 198, 0, 896, 897, 3, 383, 191, 0, 897, 898, 3, 363, 181, 0, 898, 184, 1, 0, 0, 0, 899, 900, 3, 361, 180, 0, 900, 901, 3, 385, 192, 0, 901, 902, 3, 383, 191, 0, 902, 903, 3, 361, 180, 0, 903, 904, 3, 357, 178, 0, 904, 905, 3, 395, 197, 0, 905, 186, 1, 0, 0, 0, 906, 907, 3, 393, 196, 0, 907, 908, 3, 395, 197, 0, 908, 909, 3, 391, 195, 0, 909, 910, 3, 379, 189, 0, 910, 911, 3, 365, 182, 0, 911, 912, 3, 383, 191, 0, 912, 188, 1, 0, 0, 0, 913, 914, 3, 397, 198, 0, 914, 915, 3, 361, 180, 0, 915, 916, 3, 357, 178, 0, 916, 917, 3, 393, 196, 0, 917, 918, 3, 365, 182, 0, 918, 190, 1, 0, 0, 0, 919, 920, 3, 379, 189, 0, 920, 921, 3, 361, 180, 0, 921, 922, 3, 357, 178, 0, 922, 923, 3, 393, 196, 0, 923, 924, 3, 365, 182, 0, 924, 192, 1, 0, 0, 0, 925, 926, 3, 365, 182, 0, 926, 927, 3, 383, 191, 0, 927, 928, 3, 361, 180, 0, 928, 929, 3, 385, 192, 0, 929, 930, 3, 363, 181, 0, 930, 931, 3, 365, 182, 0, 931, 932, 5, 95, 0, 0, 932, 933, 3, 367, 183, 0, 933, 934, 3, 385, 192, 0, 934, 935, 3, 391, 195, 0, 935, 936, 5, 95, 0, 0, 936, 937, 3, 397, 198, 0, 937, 938, 3, 391, 195, 0, 938, 939, 3, 373, 186, 0, 939, 194, 1, 0, 0, 0, 940, 941, 3, 367, 183, 0, 941, 942, 3, 385, 192, 0, 942, 943, 3, 391, 195, 0, 943, 196, 1, 0, 0, 0, 944, 945, 3, 361, 180, 0, 945, 946, 3, 385, 192, 0, 946, 947, 3, 383, 191, 0, 947, 948, 3, 395, 197, 0, 948, 949, 3, 357, 178, 0, 949, 950, 3, 373, 186, 0, 950, 951, 3, 383, 191, 0, 951, 952, 3, 393, 196, 0, 952, 198, 1, 0, 0, 0, 953, 954, 3, 393, 196, 0, 954, 955, 3, 395, 197, 0, 955, 956, 3, 391, 195, 0, 956, 957, 3, 393, 196, 0, 957, 958, 3, 395, 197, 0, 958, 959, 3, 357, 178, 0, 959, 960, 3, 391, 195, 0, 960, 961, 3, 395, 197, 0, 961, 962, 3, 393, 196, 0, 962, 200, 1, 0, 0, 0, 963, 964, 3, 393, 196, 0, 964, 965, 3, 395, 197, 0, 965, 966, 3, 391, 195, 0, 966, 967, 3, 365, 182, 0, 967, 968, 3, 383, 191, 0, 968, 969, 3, 363, 181, 0, 969, 970, 3, 393, 196, 0, 970, 202, 1, 0, 0, 0, 971, 972, 3, 393, 196, 0, 972, 973, 3, 395, 197, 0, 973, 974, 3, 391, 195, 0, 974, 975, 3, 359, 179, 0, 975, 976, 3, 365, 182, 0, 976, 977, 3, 367, 183, 0, 977, 978, 3, 385, 192, 0, 978, 979, 3, 391, 195, 0, 979, 980, 3, 365, 182, 0, 980, 204, 1, 0, 0, 0, 981, 982, 3, 393, 196, 0, 982, 983, 3, 395, 197, 0, 983, 984, 3, 391, 195, 0, 984, 985, 3, 357, 178, 0, 985, 986, 3, 367, 183, 0, 986, 987, 3, 395, 197, 0, 987, 988, 3, 365, 182, 0, 988, 989, 3, 391, 195, 0, 989, 206, 1, 0, 0, 0, 990, 991, 3, 405, 202, 0, 991, 992, 3, 365, 182, 0, 992, 993, 3, 357, 178, 0, 993, 994, 3, 391, 195, 0, 994, 208, 1, 0, 0, 0, 995, 996, 3, 381, 190, 0, 996, 997, 3, 385, 192, 0, 997, 998, 3, 383, 191, 0, 998, 999, 3, 395, 197, 0, 999, 1000, 3, 371, 185, 0, 1000, 210, 1, 0, 0, 0, 1001, 1002, 3, 363, 181, 0, 1002, 1003, 3, 357, 178, 0, 1003, 1004, 3, 405, 202, 0, 1004, 212, 1, 0, 0, 0, 1005, 1006, 3, 371, 185, 0, 1006, 1007, 3, 385, 192, 0, 1007, 1008, 3, 397, 198, 0, 1008, 1009, 3, 391, 195, 0, 1009, 1010, 3, 393, 196, 0, 1010, 214, 1, 0, 0, 0, 1011, 1012, 3, 381, 190, 0, 1012, 1013, 3, 373, 186, 0, 1013, 1014, 3, 383, 191, 0, 1014, 1015, 3, 397, 198, 0, 1015, 1016, 3, 395, 197, 0, 1016, 1017, 3, 365, 182, 0, 1017, 1018, 3, 393, 196, 0, 1018, 216, 1, 0, 0, 0, 1019, 1020, 3, 393, 196, 0, 1020, 1021, 3, 365, 182, 0, 1021, 1022, 3, 361, 180, 0, 1022, 1023, 3, 385, 192, 0, 1023, 1024, 3, 383, 191, 0, 1024, 1025, 3, 363, 181, 0, 1025, 1026, 3, 393, 196, 0, 1026, 218, 1, 0, 0, 0, 1027, 1028, 3, 395, 197, 0, 1028, 1029, 3, 373, 186, 0, 1029, 1030, 3, 381, 190, 0, 1030, 1031, 3, 365, 182, 0, 1031, 1032, 3, 407, 203, 0, 1032, 1033, 3, 385, 192, 0, 1033, 1034, 3, 383, 191, 0, 1034, 1035, 3, 365, 182, 0, 1035, 220, 1, 0, 0, 0, 1036, 1037, 3, 395, 197, 0, 1037, 1038, 3, 407, 203, 0, 1038, 222, 1, 0, 0, 0, 1039, 1040, 3, 383, 191, 0, 1040, 1041, 3, 385, 192, 0, 1041, 1042, 3, 401, 200, 0, 1042, 224, 1, 0, 0, 0, 1043, 1044, 3, 397, 198, 0, 1044, 1045, 3, 397, 198, 0, 1045, 1046, 3, 373, 186, 0, 1046, 1047, 3, 363, 181, 0, 1047, 226, 1, 0, 0, 0, 1048, 1049, 3, 393, 196, 0, 1049, 1050, 3, 395, 197, 0, 1050, 1051, 3, 391, 195, 0, 1051, 1052, 3, 397, 198, 0, 1052, 1053, 3, 397, 198, 0, 1053, 1054, 3, 373, 186, 0, 1054, 1055, 3, 363, 181, 0, 1055, 228, 1, 0, 0, 0, 1056, 1057, 3, 393, 196, 0, 1057, 1058, 3, 371, 185, 0, 1058, 1059, 3, 357, 178, 0, 1059, 1060, 5, 49, 0, 0, 1060, 230, 1, 0, 0, 0, 1061, 1062, 3, 393, 196, 0, 1062, 1063, 3, 371, 185, 0, 1063, 1064, 3, 357, 178, 0, 1064, 1065, 5, 50, 0, 0, 1065, 1066, 5, 53, 0, 0, 1066, 1067, 5, 54, 0, 0, 1067, 232, 1, 0, 0, 0, 1068, 1069, 3, 393, 196, 0, 1069, 1070, 3, 371, 185, 0, 1070, 1071, 3, 357, 178, 0, 1071, 1072, 5, 51, 0, 0, 1072, 1073, 5, 56, 0, 0, 1073, 1074, 5, 52, 0, 0, 1074, 234, 1, 0, 0, 0, 1075, 1076, 3, 393, 196, 0, 1076, 1077, 3, 371, 185, 0, 1077, 1078, 3, 357, 178, 0, 1078, 1079, 5, 53, 0, 0, 1079, 1080, 5, 49, 0, 0, 1080, 1081, 5, 50, 0, 0, 1081, 236, 1, 0, 0, 0, 1082, 1083, 3, 381, 190, 0, 1083, 1084, 3, 363, 181, 0, 1084, 1085, 5, 53, 0, 0, 1085, 238, 1, 0, 0, 0, 1086, 1087, 3, 361, 180, 0, 1087, 1088, 3, 385, 192, 0, 1088, 1089, 3, 357, 178, 0, 1089, 1090, 3, 379, 189, 0, 1090, 1091, 3, 365, 182, 0, 1091, 1092, 3, 393, 196, 0, 1092, 1093, 3, 361, 180, 0, 1093, 1094, 3, 365, 182, 0, 1094, 240, 1, 0, 0, 0, 1095, 1096, 3, 373, 186, 0, 1096, 1097, 3, 367, 183, 0, 1097, 242, 1, 0, 0, 0, 1098, 1099, 3, 393, 196, 0, 1099, 1100, 3, 395, 197, 0, 1100, 1101, 3, 391, 195, 0, 1101, 1102, 3, 379, 189, 0, 1102, 1103, 3, 357, 178, 0, 1103, 1104, 3, 383, 191, 0, 1104, 1105, 3, 369, 184, 0, 1105, 244, 1, 0, 0, 0, 1106, 1107, 3, 393, 196, 0, 1107, 1108, 3, 395, 197, 0, 1108, 1109, 3, 391, 195, 0, 1109, 1110, 3, 363, 181, 0, 1110, 1111, 3, 395, 197, 0, 1111, 246, 1, 0, 0, 0, 1112, 1113, 3, 393, 196, 0, 1113, 1114, 3, 357, 178, 0, 1114, 1115, 3, 381, 190, 0, 1115, 1116, 3, 365, 182, 0, 1116, 1117, 3, 395, 197, 0, 1117, 1118, 3, 365, 182, 0, 1118, 1119, 3, 391, 195, 0, 1119, 1120, 3, 381, 190, 0, 1120, 248, 1, 0, 0, 0, 1121, 1122, 3, 373, 186, 0, 1122, 1123, 3, 393, 196, 0, 1123, 1124, 3, 373, 186, 0, 1124, 1125, 3, 391, 195, 0, 1125, 1126, 3, 373, 186, 0, 1126, 250, 1, 0, 0, 0, 1127, 1128, 3, 373, 186, 0, 1128, 1129, 3, 393, 196, 0, 1129, 1130, 3, 397, 198, 0, 1130, 1131, 3, 391, 195, 0, 1131, 1132, 3, 373, 186, 0, 1132, 252, 1, 0, 0, 0, 1133, 1134, 3, 373, 186, 0, 1134, 1135, 3, 393, 196, 0, 1135, 1136, 3, 359, 179, 0, 1136, 1137, 3, 379, 189, 0, 1137, 1138, 3, 357, 178, 0, 1138, 1139, 3, 383, 191, 0, 1139, 1140, 3, 377, 188, 0, 1140, 254, 1, 0, 0, 0, 1141, 1142, 3, 373, 186, 0, 1142, 1143, 3, 393, 196, 0, 1143, 1144, 3, 379, 189, 0, 1144, 1145, 3, 373, 186, 0, 1145, 1146, 3, 395, 197, 0, 1146, 1147, 3, 365, 182, 0, 1147, 1148, 3, 391, 195, 0, 1148, 1149, 3, 357, 178, 0, 1149, 1150, 3, 379, 189, 0, 1150, 256, 1, 0, 0, 0, 1151, 1152, 3, 373, 186, 0, 1152, 1153, 3, 393, 196, 0, 1153, 1154, 3, 383, 191, 0, 1154, 1155, 3, 397, 198, 0, 1155, 1156, 3, 381, 190, 0, 1156, 1157, 3, 365, 182, 0, 1157, 1158, 3, 391, 195, 0, 1158, 1159, 3, 373, 186, 0, 1159, 1160, 3, 361, 180, 0, 1160, 258, 1, 0, 0, 0, 1161, 1162, 3, 391, 195, 0, 1162, 1163, 3, 365, 182, 0, 1163, 1164, 3, 369, 184, 0, 1164, 1165, 3, 365, 182, 0, 1165, 1166, 3, 403, 201, 0, 1166, 260, 1, 0, 0, 0, 1167, 1168, 3, 393, 196, 0, 1168, 1169, 3, 397, 198, 0, 1169, 1170, 3, 359, 179, 0, 1170, 1171, 3, 393, 196, 0, 1171, 1172, 3, 395, 197, 0, 1172, 1173, 3, 391, 195, 0, 1173, 262, 1, 0, 0, 0, 1174, 1175, 3, 391, 195, 0, 1175, 1176, 3, 365, 182, 0, 1176, 1177, 3, 387, 193, 0, 1177, 1178, 3, 379, 189, 0, 1178, 1179, 3, 357, 178, 0, 1179, 1180, 3, 361, 180, 0, 1180, 1181, 3, 365, 182, 0, 1181, 264, 1, 0, 0, 0, 1182, 1183, 3, 365, 182, 0, 1183, 1184, 3, 403, 201, 0, 1184, 1185, 3, 373, 186, 0, 1185, 1186, 3, 393, 196, 0, 1186, 1187, 3, 395, 197, 0, 1187, 1188, 3, 393, 196, 0, 1188, 266, 1, 0, 0, 0, 1189, 1190, 3, 361, 180, 0, 1190, 1191, 3, 385, 192, 0, 1191, 1192, 3, 397, 198, 0, 1192, 1193, 3, 383, 191, 0, 1193, 1194, 3, 395, 197, 0, 1194, 268, 1, 0, 0, 0, 1195, 1196, 3, 393, 196, 0, 1196, 1197, 3, 397, 198, 0, 1197, 1198, 3, 381, 190, 0, 1198, 270, 1, 0, 0, 0, 1199, 1200, 3, 381, 190, 0, 1200, 1201, 3, 373, 186, 0, 1201, 1202, 3, 383, 191, 0, 1202, 272, 1, 0, 0, 0, 1203, 1204, 3, 381, 190, 0, 1204, 1205, 3, 357, 178, 0, 1205, 1206, 3, 403, 201, 0, 1206, 274, 1, 0, 0, 0, 1207, 1208, 3, 357, 178, 0, 1208, 1209, 3, 399, 199, 0, 1209, 1210, 3, 369, 184, 0, 1210, 276, 1, 0, 0, 0, 1211, 1212, 3, 393, 196, 0, 1212, 1213, 3, 357, 178, 0, 1213, 1214, 3, 381, 190, 0, 1214, 1215, 3, 387, 193, 0, 1215, 1216, 3, 379, 189, 0, 1216, 1217, 3, 365, 182, 0, 1217, 278, 1, 0, 0, 0, 1218, 1219, 3, 393, 196, 0, 1219, 1220, 3, 365, 182, 0, 1220, 1221, 3, 387, 193, 0, 1221, 1222, 3, 357, 178, 0, 1222, 1223, 3, 391, 195, 0, 1223, 1224, 3, 357, 178, 0, 1224, 1225, 3, 395, 197, 0, 1225, 1226, 3, 385, 192, 0, 1226, 1227, 3, 391, 195, 0, 1227, 280, 1, 0, 0, 0, 1228, 1232, 5, 60, 0, 0, 1229, 1231, 8, 0, 0, 0, 1230, 1229, 1, 0, 0, 0, 1231, 1234, 1, 0, 0, 0, 1232, 1230, 1, 0, 0, 0, 1232, 1233, 1, 0, 0, 0, 1233, 1235, 1, 0, 0, 0, 1234, 1232, 1, 0, 0, 0, 1235, 1236, 5, 62, 0, 0, 1236, 282, 1, 0, 0, 0, 1237, 1239, 3, 337, 168, 0, 1238, 1237, 1, 0, 0, 0, 1238, 1239, 1, 0, 0, 0, 1239, 1240, 1, 0, 0, 0, 1240, 1241, 5, 58, 0, 0, 1241, 284, 1, 0, 0, 0, 1242, 1243, 3, 283, 141, 0, 1243, 1244, 3, 339, 169, 0, 1244, 286, 1, 0, 0, 0, 1245, 1246, 5, 95, 0, 0, 1246, 1247, 5, 58, 0, 0, 1247, 1250, 1, 0, 0, 0, 1248, 1251, 3, 331, 165, 0, 1249, 1251, 3, 351, 175, 0, 1250, 1248, 1, 0, 0, 0, 1250, 1249, 1, 0, 0, 0, 1251, 1260, 1, 0, 0, 0, 1252, 1255, 3, 335, 167, 0, 1253, 1255, 5, 46, 0, 0, 1254, 1252, 1, 0, 0, 0, 1254, 1253, 1, 0, 0, 0, 1255, 1258, 1, 0, 0, 0, 1256, 1254, 1, 0, 0, 0, 1256, 1257, 1, 0, 0, 0, 1257, 1259, 1, 0, 0, 0, 1258, 1256, 1, 0, 0, 0, 1259, 1261, 3, 335, 167, 0, 1260, 1256, 1, 0, 0, 0, 1260, 1261, 1, 0, 0, 0, 1261, 288, 1, 0, 0, 0, 1262, 1263, 5, 63, 0, 0, 1263, 1264, 3, 333, 166, 0, 1264, 290, 1, 0, 0, 0, 1265, 1266, 5, 36, 0, 0, 1266, 1267, 3, 333, 166, 0, 1267, 292, 1, 0, 0, 0, 1268, 1270, 5, 64, 0, 0, 1269, 1271, 7, 1, 0, 0, 1270, 1269, 1, 0, 0, 0, 1271, 1272, 1, 0, 0, 0, 1272, 1270, 1, 0, 0, 0, 1272, 1273, 1, 0, 0, 0, 1273, 1283, 1, 0, 0, 0, 1274, 1277, 5, 45, 0, 0, 1275, 1278, 7, 1, 0, 0, 1276, 1278, 3, 351, 175, 0, 1277, 1275, 1, 0, 0, 0, 1277, 1276, 1, 0, 0, 0, 1278, 1279, 1, 0, 0, 0, 1279, 1277, 1, 0, 0, 0, 1279, 1280, 1, 0, 0, 0, 1280, 1282, 1, 0, 0, 0, 1281, 1274, 1, 0, 0, 0, 1282, 1285, 1, 0, 0, 0, 1283, 1281, 1, 0, 0, 0, 1283, 1284, 1, 0, 0, 0, 1284, 294, 1, 0, 0, 0, 1285, 1283, 1, 0, 0, 0, 1286, 1287, 3, 293, 146, 0, 1287, 1288, 5, 64, 0, 0, 1288, 296, 1, 0, 0, 0, 1289, 1291, 3, 351, 175, 0, 1290, 1289, 1, 0, 0, 0, 1291, 1292, 1, 0, 0, 0, 1292, 1290, 1, 0, 0, 0, 1292, 1293, 1, 0, 0, 0, 1293, 298, 1, 0, 0, 0, 1294, 1296, 3, 351, 175, 0, 1295, 1294, 1, 0, 0, 0, 1296, 1299, 1, 0, 0, 0, 1297, 1295, 1, 0, 0, 0, 1297, 1298, 1, 0, 0, 0, 1298, 1300, 1, 0, 0, 0, 1299, 1297, 1, 0, 0, 0, 1300, 1302, 5, 46, 0, 0, 1301, 1303, 3, 351, 175, 0, 1302, 1301, 1, 0, 0, 0, 1303, 1304, 1, 0, 0, 0, 1304, 1302, 1, 0, 0, 0, 1304, 1305, 1, 0, 0, 0, 1305, 300, 1, 0, 0, 0, 1306, 1308, 3, 351, 175, 0, 1307, 1306, 1, 0, 0, 0, 1308, 1309, 1, 0, 0, 0, 1309, 1307, 1, 0, 0, 0, 1309, 1310, 1, 0, 0, 0, 1310, 1311, 1, 0, 0, 0, 1311, 1315, 5, 46, 0, 0, 1312, 1314, 3, 351, 175, 0, 1313, 1312, 1, 0, 0, 0, 1314, 1317, 1, 0, 0, 0, 1315, 1313, 1, 0, 0, 0, 1315, 1316, 1, 0, 0, 0, 1316, 1318, 1, 0, 0, 0, 1317, 1315, 1, 0, 0, 0, 1318, 1319, 3, 315, 157, 0, 1319, 1336, 1, 0, 0, 0, 1320, 1322, 5, 46, 0, 0, 1321, 1323, 3, 351, 175, 0, 1322, 1321, 1, 0, 0, 0, 1323, 1324, 1, 0, 0, 0, 1324, 1322, 1, 0, 0, 0, 1324, 1325, 1, 0, 0, 0, 1325, 1326, 1, 0, 0, 0, 1326, 1327, 3, 315, 157, 0, 1327, 1336, 1, 0, 0, 0, 1328, 1330, 3, 351, 175, 0, 1329, 1328, 1, 0, 0, 0, 1330, 1331, 1, 0, 0, 0, 1331, 1329, 1, 0, 0, 0, 1331, 1332, 1, 0, 0, 0, 1332, 1333, 1, 0, 0, 0, 1333, 1334, 3, 315, 157, 0, 1334, 1336, 1, 0, 0, 0, 1335, 1307, 1, 0, 0, 0, 1335, 1320, 1, 0, 0, 0, 1335, 1329, 1, 0, 0, 0, 1336, 302, 1, 0, 0, 0, 1337, 1338, 5, 43, 0, 0, 1338, 1339, 3, 297, 148, 0, 1339, 304, 1, 0, 0, 0, 1340, 1341, 5, 43, 0, 0, 1341, 1342, 3, 299, 149, 0, 1342, 306, 1, 0, 0, 0, 1343, 1344, 5, 43, 0, 0, 1344, 1345, 3, 301, 150, 0, 1345, 308, 1, 0, 0, 0, 1346, 1347, 5, 45, 0, 0, 1347, 1348, 3, 297, 148, 0, 1348, 310, 1, 0, 0, 0, 1349, 1350, 5, 45, 0, 0, 1350, 1351, 3, 299, 149, 0, 1351, 312, 1, 0, 0, 0, 1352, 1353, 5, 45, 0, 0, 1353, 1354, 3, 301, 150, 0, 1354, 314, 1, 0, 0, 0, 1355, 1357, 7, 2, 0, 0, 1356, 1358, 7, 3, 0, 0, 1357, 1356, 1, 0, 0, 0, 1357, 1358, 1, 0, 0, 0, 1358, 1360, 1, 0, 0, 0, 1359, 1361, 3, 351, 175, 0, 1360, 1359, 1, 0, 0, 0, 1361, 1362, 1, 0, 0, 0, 1362, 1360, 1, 0, 0, 0, 1362, 1363, 1, 0, 0, 0, 1363, 316, 1, 0, 0, 0, 1364, 1369, 5, 39, 0, 0, 1365, 1368, 8, 4, 0, 0, 1366, 1368, 3, 325, 162, 0, 1367, 1365, 1, 0, 0, 0, 1367, 1366, 1, 0, 0, 0, 1368, 1371, 1, 0, 0, 0, 1369, 1367, 1, 0, 0, 0, 1369, 1370, 1, 0, 0, 0, 1370, 1372, 1, 0, 0, 0, 1371, 1369, 1, 0, 0, 0, 1372, 1373, 5, 39, 0, 0, 1373, 318, 1, 0, 0, 0, 1374, 1379, 5, 34, 0, 0, 1375, 1378, 8, 5, 0, 0, 1376, 1378, 3, 325, 162, 0, 1377, 1375, 1, 0, 0, 0, 1377, 1376, 1, 0, 0, 0, 1378, 1381, 1, 0, 0, 0, 1379, 1377, 1, 0, 0, 0, 1379, 1380, 1, 0, 0, 0, 1380, 1382, 1, 0, 0, 0, 1381, 1379, 1, 0, 0, 0, 1382, 1383, 5, 34, 0, 0, 1383, 320, 1, 0, 0, 0, 1384, 1385, 5, 39, 0, 0, 1385, 1386, 5, 39, 0, 0, 1386, 1387, 5, 39, 0, 0, 1387, 1399, 1, 0, 0, 0, 1388, 1392, 5, 39, 0, 0, 1389, 1390, 5, 39, 0, 0, 1390, 1392, 5, 39, 0, 0, 1391, 1388, 1, 0, 0, 0, 1391, 1389, 1, 0, 0, 0, 1391, 1392, 1, 0, 0, 0, 1392, 1395, 1, 0, 0, 0, 1393, 1396, 8, 6, 0, 0, 1394, 1396, 3, 325, 162, 0, 1395, 1393, 1, 0, 0, 0, 1395, 1394, 1, 0, 0, 0, 1396, 1398, 1, 0, 0, 0, 1397, 1391, 1, 0, 0, 0, 1398, 1401, 1, 0, 0, 0, 1399, 1397, 1, 0, 0, 0, 1399, 1400, 1, 0, 0, 0, 1400, 1402, 1, 0, 0, 0, 1401, 1399, 1, 0, 0, 0, 1402, 1403, 5, 39, 0, 0, 1403, 1404, 5, 39, 0, 0, 1404, 1405, 5, 39, 0, 0, 1405, 322, 1, 0, 0, 0, 1406, 1407, 5, 34, 0, 0, 1407, 1408, 5, 34, 0, 0, 1408, 1409, 5, 34, 0, 0, 1409, 1421, 1, 0, 0, 0, 1410, 1414, 5, 34, 0, 0, 1411, 1412, 5, 34, 0, 0, 1412, 1414, 5, 34, 0, 0, 1413, 1410, 1, 0, 0, 0, 1413, 1411, 1, 0, 0, 0, 1413, 1414, 1, 0, 0, 0, 1414, 1417, 1, 0, 0, 0, 1415, 1418, 8, 7, 0, 0, 1416, 1418, 3, 325, 162, 0, 1417, 1415, 1, 0, 0, 0, 1417, 1416, 1, 0, 0, 0, 1418, 1420, 1, 0, 0, 0, 1419, 1413, 1, 0, 0, 0, 1420, 1423, 1, 0, 0, 0, 1421, 1419, 1, 0, 0, 0, 1421, 1422, 1, 0, 0, 0, 1422, 1424, 1, 0, 0, 0, 1423, 1421, 1, 0, 0, 0, 1424, 1425, 5, 34, 0, 0, 1425, 1426, 5, 34, 0, 0, 1426, 1427, 5, 34, 0, 0, 1427, 324, 1, 0, 0, 0, 1428, 1429, 5, 92, 0, 0, 1429, 1430, 7, 8, 0, 0, 1430, 326, 1, 0, 0, 0, 1431, 1435, 5, 40, 0, 0, 1432, 1434, 3, 353, 176, 0, 1433, 1432, 1, 0, 0, 0, 1434, 1437, 1, 0, 0, 0, 1435, 1433, 1, 0, 0, 0, 1435, 1436, 1, 0, 0, 0, 1436, 1438, 1, 0, 0, 0, 1437, 1435, 1, 0, 0, 0, 1438, 1439, 5, 41, 0, 0, 1439, 328, 1, 0, 0, 0, 1440, 1444, 5, 91, 0, 0, 1441, 1443, 3, 353, 176, 0, 1442, 1441, 1, 0, 0, 0, 1443, 1446, 1, 0, 0, 0, 1444, 1442, 1, 0, 0, 0, 1444, 1445, 1, 0, 0, 0, 1445, 1447, 1, 0, 0, 0, 1446, 1444, 1, 0, 0, 0, 1447, 1448, 5, 93, 0, 0, 1448, 330, 1, 0, 0, 0, 1449, 1452, 3, 349, 174, 0, 1450, 1452, 5, 95, 0, 0, 1451, 1449, 1, 0, 0, 0, 1451, 1450, 1, 0, 0, 0, 1452, 332, 1, 0, 0, 0, 1453, 1456, 3, 331, 165, 0, 1454, 1456, 3, 351, 175, 0, 1455, 1453, 1, 0, 0, 0, 1455, 1454, 1, 0, 0, 0, 1456, 1462, 1, 0, 0, 0, 1457, 1461, 3, 331, 165, 0, 1458, 1461, 3, 351, 175, 0, 1459, 1461, 7, 9, 0, 0, 1460, 1457, 1, 0, 0, 0, 1460, 1458, 1, 0, 0, 0, 1460, 1459, 1, 0, 0, 0, 1461, 1464, 1, 0, 0, 0, 1462, 1460, 1, 0, 0, 0, 1462, 1463, 1, 0, 0, 0, 1463, 334, 1, 0, 0, 0, 1464, 1462, 1, 0, 0, 0, 1465, 1470, 3, 331, 165, 0, 1466, 1470, 5, 45, 0, 0, 1467, 1470, 3, 351, 175, 0, 1468, 1470, 7, 9, 0, 0, 1469, 1465, 1, 0, 0, 0, 1469, 1466, 1, 0, 0, 0, 1469, 1467, 1, 0, 0, 0, 1469, 1468, 1, 0, 0, 0, 1470, 336, 1, 0, 0, 0, 1471, 1480, 3, 349, 174, 0, 1472, 1475, 3, 335, 167, 0, 1473, 1475, 5, 46, 0, 0, 1474, 1472, 1, 0, 0, 0, 1474, 1473, 1, 0, 0, 0, 1475, 1478, 1, 0, 0, 0, 1476, 1474, 1, 0, 0, 0, 1476, 1477, 1, 0, 0, 0, 1477, 1479, 1, 0, 0, 0, 1478, 1476, 1, 0, 0, 0, 1479, 1481, 3, 335, 167, 0, 1480, 1476, 1, 0, 0, 0, 1480, 1481, 1, 0, 0, 0, 1481, 338, 1, 0, 0, 0, 1482, 1487, 3, 331, 165, 0, 1483, 1487, 5, 58, 0, 0, 1484, 1487, 3, 351, 175, 0, 1485, 1487, 3, 341, 170, 0, 1486, 1482, 1, 0, 0, 0, 1486, 1483, 1, 0, 0, 0, 1486, 1484, 1, 0, 0, 0, 1486, 1485, 1, 0, 0, 0, 1487, 1501, 1, 0, 0, 0, 1488, 1492, 3, 335, 167, 0, 1489, 1492, 7, 10, 0, 0, 1490, 1492, 3, 341, 170, 0, 1491, 1488, 1, 0, 0, 0, 1491, 1489, 1, 0, 0, 0, 1491, 1490, 1, 0, 0, 0, 1492, 1495, 1, 0, 0, 0, 1493, 1491, 1, 0, 0, 0, 1493, 1494, 1, 0, 0, 0, 1494, 1499, 1, 0, 0, 0, 1495, 1493, 1, 0, 0, 0, 1496, 1500, 3, 335, 167, 0, 1497, 1500, 5, 58, 0, 0, 1498, 1500, 3, 341, 170, 0, 1499, 1496, 1, 0, 0, 0, 1499, 1497, 1, 0, 0, 0, 1499, 1498, 1, 0, 0, 0, 1500, 1502, 1, 0, 0, 0, 1501, 1493, 1, 0, 0, 0, 1501, 1502, 1, 0, 0, 0, 1502, 340, 1, 0, 0, 0, 1503, 1506, 3, 343, 171, 0, 1504, 1506, 3, 347, 173, 0, 1505, 1503, 1, 0, 0, 0, 1505, 1504, 1, 0, 0, 0, 1506, 342, 1, 0, 0, 0, 1507, 1508, 5, 37, 0, 0, 1508, 1509, 3, 345, 172, 0, 1509, 1510, 3, 345, 172, 0, 1510, 344, 1, 0, 0, 0, 1511, 1514, 3, 351, 175, 0, 1512, 1514, 7, 11, 0, 0, 1513, 1511, 1, 0, 0, 0, 1513, 1512, 1, 0, 0, 0, 1514, 346, 1, 0, 0, 0, 1515, 1516, 5, 92, 0, 0, 1516, 1517, 7, 12, 0, 0, 1517, 348, 1, 0, 0, 0, 1518, 1519, 7, 13, 0, 0, 1519, 350, 1, 0, 0, 0, 1520, 1521, 2, 48, 57, 0, 1521, 352, 1, 0, 0, 0, 1522, 1524, 7, 14, 0, 0, 1523, 1522, 1, 0, 0, 0, 1524, 1525, 1, 0, 0, 0, 1525, 1523, 1, 0, 0, 0, 1525, 1526, 1, 0, 0, 0, 1526, 1527, 1, 0, 0, 0, 1527, 1528, 6, 176, 0, 0, 1528, 354, 1, 0, 0, 0, 1529, 1533, 5, 35, 0, 0, 1530, 1532, 8, 15, 0, 0, 1531, 1530, 1, 0, 0, 0, 1532, 1535, 1, 0, 0, 0, 1533, 1531, 1, 0, 0, 0, 1533, 1534, 1, 0, 0, 0, 1534, 1536, 1, 0, 0, 0, 1535, 1533, 1, 0, 0, 0, 1536, 1537, 6, 177, 0, 0, 1537, 356, 1, 0, 0, 0, 1538, 1539, 7, 16, 0, 0, 1539, 358, 1, 0, 0, 0, 1540, 1541, 7, 17, 0, 0, 1541, 360, 1, 0, 0, 0, 1542, 1543, 7, 18, 0, 0, 1543, 362, 1, 0, 0, 0, 1544, 1545, 7, 19, 0, 0, 1545, 364, 1, 0, 0, 0, 1546, 1547, 7, 2, 0, 0, 1547, 366, 1, 0, 0, 0, 1548, 1549, 7, 20, 0, 0, 1549, 368, 1, 0, 0, 0, 1550, 1551, 7, 21, 0, 0, 1551, 370, 1, 0, 0, 0, 1552, 1553, 7, 22, 0, 0, 1553, 372, 1, 0, 0, 0, 1554, 1555, 7, 23, 0, 0, 1555, 374, 1, 0, 0, 0, 1556, 1557, 7, 24, 0, 0, 1557, 376, 1, 0, 0, 0, 1558, 1559, 7, 25, 0, 0, 1559, 378, 1, 0, 0, 0, 1560, 1561, 7, 26, 0, 0, 1561, 380, 1, 0, 0, 0, 1562, 1563, 7, 27, 0, 0, 1563, 382, 1, 0, 0, 0, 1564, 1565, 7, 28, 0, 0, 1565, 384, 1, 0, 0, 0, 1566, 1567, 7, 29, 0, 0, 1567, 386, 1, 0, 0, 0, 1568, 1569, 7, 30, 0, 0, 1569, 388, 1, 0, 0, 0, 1570, 1571, 7, 31, 0, 0, 1571, 390, 1, 0, 0, 0, 1572, 1573, 7, 32, 0, 0, 1573, 392, 1, 0, 0, 0, 1574, 1575, 7, 33, 0, 0, 1575, 394, 1, 0, 0, 0, 1576, 1577, 7, 34, 0, 0, 1577, 396, 1, 0, 0, 0, 1578, 1579, 7, 35, 0, 0, 1579, 398, 1, 0, 0, 0, 1580, 1581, 7, 36, 0, 0, 1581, 400, 1, 0, 0, 0, 1582, 1583, 7, 37, 0, 0, 1583, 402, 1, 0, 0, 0, 1584, 1585, 7, 38, 0, 0, 1585, 404, 1, 0, 0, 0, 1586, 1587, 7, 39, 0, 0, 1587, 406, 1, 0, 0, 0, 1588, 1589, 7, 40, 0, 0, 1589, 408, 1, 0, 0, 0, 54, 0, 567, 600, 616, 625, 1232, 1238, 1250, 1254, 1256, 1260, 1272, 1277, 1279, 1283, 1292, 1297, 1304, 1309, 1315, 1324, 1331, 1335, 1357, 1362, 1367, 1369, 1377, 1379, 1391, 1395, 1399, 1413, 1417, 1421, 1435, 1444, 1451, 1455, 1460, 1462, 1469, 1474, 1476, 1480, 1486, 1491, 1493, 1499, 1501, 1505, 1513, 1525, 1533, 1, 6, 0, 0] \ No newline at end of file diff --git a/src/parser/sparqlParser/generated/SparqlAutomaticLexer.tokens b/src/parser/sparqlParser/generated/SparqlAutomaticLexer.tokens index 05124f86e3..4d2a3fec0c 100644 --- a/src/parser/sparqlParser/generated/SparqlAutomaticLexer.tokens +++ b/src/parser/sparqlParser/generated/SparqlAutomaticLexer.tokens @@ -52,133 +52,135 @@ TEXTLIMIT=51 VALUES=52 LOAD=53 SILENT=54 -CLEAR=55 -DROP=56 -CREATE=57 -ADD=58 -DATA=59 -MOVE=60 -COPY=61 -INSERT=62 -DELETE=63 -WITH=64 -USING=65 -DEFAULT=66 -GRAPH=67 -ALL=68 -OPTIONAL=69 -SERVICE=70 -BIND=71 -UNDEF=72 -MINUS=73 -UNION=74 -FILTER=75 -NOT=76 -IN=77 -STR=78 -LANG=79 -LANGMATCHES=80 -DATATYPE=81 -BOUND=82 -IRI=83 -URI=84 -BNODE=85 -RAND=86 -ABS=87 -CEIL=88 -FLOOR=89 -ROUND=90 -CONCAT=91 -STRLEN=92 -UCASE=93 -LCASE=94 -ENCODE_FOR_URI=95 -FOR=96 -CONTAINS=97 -STRSTARTS=98 -STRENDS=99 -STRBEFORE=100 -STRAFTER=101 -YEAR=102 -MONTH=103 -DAY=104 -HOURS=105 -MINUTES=106 -SECONDS=107 -TIMEZONE=108 -TZ=109 -NOW=110 -UUID=111 -STRUUID=112 -SHA1=113 -SHA256=114 -SHA384=115 -SHA512=116 -MD5=117 -COALESCE=118 -IF=119 -STRLANG=120 -STRDT=121 -SAMETERM=122 -ISIRI=123 -ISURI=124 -ISBLANK=125 -ISLITERAL=126 -ISNUMERIC=127 -REGEX=128 -SUBSTR=129 -REPLACE=130 -EXISTS=131 -COUNT=132 -SUM=133 -MIN=134 -MAX=135 -AVG=136 -SAMPLE=137 -SEPARATOR=138 -IRI_REF=139 -PNAME_NS=140 -PNAME_LN=141 -BLANK_NODE_LABEL=142 -VAR1=143 -VAR2=144 -LANGTAG=145 -PREFIX_LANGTAG=146 -INTEGER=147 -DECIMAL=148 -DOUBLE=149 -INTEGER_POSITIVE=150 -DECIMAL_POSITIVE=151 -DOUBLE_POSITIVE=152 -INTEGER_NEGATIVE=153 -DECIMAL_NEGATIVE=154 -DOUBLE_NEGATIVE=155 -EXPONENT=156 -STRING_LITERAL1=157 -STRING_LITERAL2=158 -STRING_LITERAL_LONG1=159 -STRING_LITERAL_LONG2=160 -ECHAR=161 -NIL=162 -ANON=163 -PN_CHARS_U=164 -VARNAME=165 -PN_PREFIX=166 -PN_LOCAL=167 -PLX=168 -PERCENT=169 -HEX=170 -PN_LOCAL_ESC=171 -WS=172 -COMMENTS=173 +INTO=55 +CLEAR=56 +DROP=57 +CREATE=58 +ADD=59 +TO=60 +DATA=61 +MOVE=62 +COPY=63 +INSERT=64 +DELETE=65 +WITH=66 +USING=67 +DEFAULT=68 +GRAPH=69 +ALL=70 +OPTIONAL=71 +SERVICE=72 +BIND=73 +UNDEF=74 +MINUS=75 +UNION=76 +FILTER=77 +NOT=78 +IN=79 +STR=80 +LANG=81 +LANGMATCHES=82 +DATATYPE=83 +BOUND=84 +IRI=85 +URI=86 +BNODE=87 +RAND=88 +ABS=89 +CEIL=90 +FLOOR=91 +ROUND=92 +CONCAT=93 +STRLEN=94 +UCASE=95 +LCASE=96 +ENCODE_FOR_URI=97 +FOR=98 +CONTAINS=99 +STRSTARTS=100 +STRENDS=101 +STRBEFORE=102 +STRAFTER=103 +YEAR=104 +MONTH=105 +DAY=106 +HOURS=107 +MINUTES=108 +SECONDS=109 +TIMEZONE=110 +TZ=111 +NOW=112 +UUID=113 +STRUUID=114 +SHA1=115 +SHA256=116 +SHA384=117 +SHA512=118 +MD5=119 +COALESCE=120 +IF=121 +STRLANG=122 +STRDT=123 +SAMETERM=124 +ISIRI=125 +ISURI=126 +ISBLANK=127 +ISLITERAL=128 +ISNUMERIC=129 +REGEX=130 +SUBSTR=131 +REPLACE=132 +EXISTS=133 +COUNT=134 +SUM=135 +MIN=136 +MAX=137 +AVG=138 +SAMPLE=139 +SEPARATOR=140 +IRI_REF=141 +PNAME_NS=142 +PNAME_LN=143 +BLANK_NODE_LABEL=144 +VAR1=145 +VAR2=146 +LANGTAG=147 +PREFIX_LANGTAG=148 +INTEGER=149 +DECIMAL=150 +DOUBLE=151 +INTEGER_POSITIVE=152 +DECIMAL_POSITIVE=153 +DOUBLE_POSITIVE=154 +INTEGER_NEGATIVE=155 +DECIMAL_NEGATIVE=156 +DOUBLE_NEGATIVE=157 +EXPONENT=158 +STRING_LITERAL1=159 +STRING_LITERAL2=160 +STRING_LITERAL_LONG1=161 +STRING_LITERAL_LONG2=162 +ECHAR=163 +NIL=164 +ANON=165 +PN_CHARS_U=166 +VARNAME=167 +PN_PREFIX=168 +PN_LOCAL=169 +PLX=170 +PERCENT=171 +HEX=172 +PN_LOCAL_ESC=173 +WS=174 +COMMENTS=175 '*'=1 '('=2 ')'=3 '{'=4 '}'=5 -'.'=6 -','=7 -';'=8 +';'=6 +'.'=7 +','=8 'a'=9 '|'=10 '/'=11 diff --git a/src/parser/sparqlParser/generated/SparqlAutomaticListener.h b/src/parser/sparqlParser/generated/SparqlAutomaticListener.h index e0624f9bea..fea9f9130b 100644 --- a/src/parser/sparqlParser/generated/SparqlAutomaticListener.h +++ b/src/parser/sparqlParser/generated/SparqlAutomaticListener.h @@ -12,6 +12,11 @@ */ class SparqlAutomaticListener : public antlr4::tree::ParseTreeListener { public: + virtual void enterQueryOrUpdate( + SparqlAutomaticParser::QueryOrUpdateContext* ctx) = 0; + virtual void exitQueryOrUpdate( + SparqlAutomaticParser::QueryOrUpdateContext* ctx) = 0; + virtual void enterQuery(SparqlAutomaticParser::QueryContext* ctx) = 0; virtual void exitQuery(SparqlAutomaticParser::QueryContext* ctx) = 0; @@ -150,6 +155,95 @@ class SparqlAutomaticListener : public antlr4::tree::ParseTreeListener { virtual void exitValuesClause( SparqlAutomaticParser::ValuesClauseContext* ctx) = 0; + virtual void enterUpdate(SparqlAutomaticParser::UpdateContext* ctx) = 0; + virtual void exitUpdate(SparqlAutomaticParser::UpdateContext* ctx) = 0; + + virtual void enterUpdate1(SparqlAutomaticParser::Update1Context* ctx) = 0; + virtual void exitUpdate1(SparqlAutomaticParser::Update1Context* ctx) = 0; + + virtual void enterLoad(SparqlAutomaticParser::LoadContext* ctx) = 0; + virtual void exitLoad(SparqlAutomaticParser::LoadContext* ctx) = 0; + + virtual void enterClear(SparqlAutomaticParser::ClearContext* ctx) = 0; + virtual void exitClear(SparqlAutomaticParser::ClearContext* ctx) = 0; + + virtual void enterDrop(SparqlAutomaticParser::DropContext* ctx) = 0; + virtual void exitDrop(SparqlAutomaticParser::DropContext* ctx) = 0; + + virtual void enterCreate(SparqlAutomaticParser::CreateContext* ctx) = 0; + virtual void exitCreate(SparqlAutomaticParser::CreateContext* ctx) = 0; + + virtual void enterAdd(SparqlAutomaticParser::AddContext* ctx) = 0; + virtual void exitAdd(SparqlAutomaticParser::AddContext* ctx) = 0; + + virtual void enterMove(SparqlAutomaticParser::MoveContext* ctx) = 0; + virtual void exitMove(SparqlAutomaticParser::MoveContext* ctx) = 0; + + virtual void enterCopy(SparqlAutomaticParser::CopyContext* ctx) = 0; + virtual void exitCopy(SparqlAutomaticParser::CopyContext* ctx) = 0; + + virtual void enterInsertData( + SparqlAutomaticParser::InsertDataContext* ctx) = 0; + virtual void exitInsertData( + SparqlAutomaticParser::InsertDataContext* ctx) = 0; + + virtual void enterDeleteData( + SparqlAutomaticParser::DeleteDataContext* ctx) = 0; + virtual void exitDeleteData( + SparqlAutomaticParser::DeleteDataContext* ctx) = 0; + + virtual void enterDeleteWhere( + SparqlAutomaticParser::DeleteWhereContext* ctx) = 0; + virtual void exitDeleteWhere( + SparqlAutomaticParser::DeleteWhereContext* ctx) = 0; + + virtual void enterModify(SparqlAutomaticParser::ModifyContext* ctx) = 0; + virtual void exitModify(SparqlAutomaticParser::ModifyContext* ctx) = 0; + + virtual void enterDeleteClause( + SparqlAutomaticParser::DeleteClauseContext* ctx) = 0; + virtual void exitDeleteClause( + SparqlAutomaticParser::DeleteClauseContext* ctx) = 0; + + virtual void enterInsertClause( + SparqlAutomaticParser::InsertClauseContext* ctx) = 0; + virtual void exitInsertClause( + SparqlAutomaticParser::InsertClauseContext* ctx) = 0; + + virtual void enterUsingClause( + SparqlAutomaticParser::UsingClauseContext* ctx) = 0; + virtual void exitUsingClause( + SparqlAutomaticParser::UsingClauseContext* ctx) = 0; + + virtual void enterGraphOrDefault( + SparqlAutomaticParser::GraphOrDefaultContext* ctx) = 0; + virtual void exitGraphOrDefault( + SparqlAutomaticParser::GraphOrDefaultContext* ctx) = 0; + + virtual void enterGraphRef(SparqlAutomaticParser::GraphRefContext* ctx) = 0; + virtual void exitGraphRef(SparqlAutomaticParser::GraphRefContext* ctx) = 0; + + virtual void enterGraphRefAll( + SparqlAutomaticParser::GraphRefAllContext* ctx) = 0; + virtual void exitGraphRefAll( + SparqlAutomaticParser::GraphRefAllContext* ctx) = 0; + + virtual void enterQuadPattern( + SparqlAutomaticParser::QuadPatternContext* ctx) = 0; + virtual void exitQuadPattern( + SparqlAutomaticParser::QuadPatternContext* ctx) = 0; + + virtual void enterQuadData(SparqlAutomaticParser::QuadDataContext* ctx) = 0; + virtual void exitQuadData(SparqlAutomaticParser::QuadDataContext* ctx) = 0; + + virtual void enterQuads(SparqlAutomaticParser::QuadsContext* ctx) = 0; + virtual void exitQuads(SparqlAutomaticParser::QuadsContext* ctx) = 0; + + virtual void enterQuadsNotTriples( + SparqlAutomaticParser::QuadsNotTriplesContext* ctx) = 0; + virtual void exitQuadsNotTriples( + SparqlAutomaticParser::QuadsNotTriplesContext* ctx) = 0; + virtual void enterTriplesTemplate( SparqlAutomaticParser::TriplesTemplateContext* ctx) = 0; virtual void exitTriplesTemplate( diff --git a/src/parser/sparqlParser/generated/SparqlAutomaticParser.cpp b/src/parser/sparqlParser/generated/SparqlAutomaticParser.cpp index 2cd4164470..a3a79e52ed 100644 --- a/src/parser/sparqlParser/generated/SparqlAutomaticParser.cpp +++ b/src/parser/sparqlParser/generated/SparqlAutomaticParser.cpp @@ -46,6 +46,7 @@ void sparqlautomaticParserInitialize() { assert(sparqlautomaticParserStaticData == nullptr); auto staticData = std::make_unique( std::vector{ + "queryOrUpdate", "query", "prologue", "baseDecl", @@ -76,6 +77,29 @@ void sparqlautomaticParserInitialize() { "offsetClause", "textLimitClause", "valuesClause", + "update", + "update1", + "load", + "clear", + "drop", + "create", + "add", + "move", + "copy", + "insertData", + "deleteData", + "deleteWhere", + "modify", + "deleteClause", + "insertClause", + "usingClause", + "graphOrDefault", + "graphRef", + "graphRefAll", + "quadPattern", + "quadData", + "quads", + "quadsNotTriples", "triplesTemplate", "groupGraphPattern", "groupGraphPatternSub", @@ -180,7 +204,7 @@ void sparqlautomaticParserInitialize() { "pnameLn", "pnameNs"}, std::vector{"", "'*'", "'('", "')'", "'{'", - "'}'", "'.'", "','", "';'", "'a'", + "'}'", "';'", "'.'", "','", "'a'", "'|'", "'/'", "'^'", "'+'", "'\\u003F'", "'!'", "'['", "']'", "'||'", "'&&'", "'='", "'!='", "'<'", "'>'", "'<='", @@ -240,10 +264,12 @@ void sparqlautomaticParserInitialize() { "VALUES", "LOAD", "SILENT", + "INTO", "CLEAR", "DROP", "CREATE", "ADD", + "TO", "DATA", "MOVE", "COPY", @@ -360,7 +386,7 @@ void sparqlautomaticParserInitialize() { "WS", "COMMENTS"}); static const int32_t serializedATNSegment[] = { - 4, 1, 173, 1433, 2, 0, 7, 0, 2, 1, 7, 1, + 4, 1, 175, 1647, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, @@ -404,1010 +430,1165 @@ void sparqlautomaticParserInitialize() { 2, 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, 7, 130, - 2, 131, 7, 131, 2, 132, 7, 132, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 3, 0, 272, 8, 0, 1, - 0, 1, 0, 1, 0, 1, 1, 1, 1, 5, 1, 279, - 8, 1, 10, 1, 12, 1, 282, 9, 1, 1, 2, 1, - 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, - 4, 1, 4, 5, 4, 293, 8, 4, 10, 4, 12, 4, - 296, 9, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, - 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 3, - 6, 308, 8, 6, 1, 6, 4, 6, 311, 8, 6, 11, - 6, 12, 6, 312, 1, 6, 3, 6, 316, 8, 6, 1, - 7, 1, 7, 3, 7, 320, 8, 7, 1, 8, 1, 8, - 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, - 1, 10, 1, 10, 1, 10, 5, 10, 333, 8, 10, 10, - 10, 12, 10, 336, 9, 10, 1, 10, 1, 10, 1, 10, - 1, 10, 5, 10, 342, 8, 10, 10, 10, 12, 10, 345, - 9, 10, 1, 10, 1, 10, 1, 10, 3, 10, 350, 8, - 10, 1, 10, 1, 10, 3, 10, 354, 8, 10, 1, 11, - 1, 11, 4, 11, 358, 8, 11, 11, 11, 12, 11, 359, - 1, 11, 3, 11, 363, 8, 11, 1, 11, 5, 11, 366, - 8, 11, 10, 11, 12, 11, 369, 9, 11, 1, 11, 3, - 11, 372, 8, 11, 1, 11, 1, 11, 1, 12, 1, 12, - 5, 12, 378, 8, 12, 10, 12, 12, 12, 381, 9, 12, - 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, - 3, 13, 389, 8, 13, 1, 14, 1, 14, 1, 15, 1, - 15, 1, 15, 1, 16, 1, 16, 1, 17, 3, 17, 399, - 8, 17, 1, 17, 1, 17, 1, 18, 3, 18, 404, 8, - 18, 1, 18, 3, 18, 407, 8, 18, 1, 18, 3, 18, - 410, 8, 18, 1, 18, 3, 18, 413, 8, 18, 1, 19, - 1, 19, 4, 19, 417, 8, 19, 11, 19, 12, 19, 418, - 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, - 3, 20, 427, 8, 20, 1, 20, 1, 20, 1, 20, 3, - 20, 432, 8, 20, 1, 21, 1, 21, 4, 21, 436, 8, - 21, 11, 21, 12, 21, 437, 1, 22, 1, 22, 1, 23, - 1, 23, 3, 23, 444, 8, 23, 1, 23, 4, 23, 447, - 8, 23, 11, 23, 12, 23, 448, 1, 24, 1, 24, 1, - 24, 1, 24, 3, 24, 455, 8, 24, 3, 24, 457, 8, - 24, 1, 25, 1, 25, 3, 25, 461, 8, 25, 1, 25, - 3, 25, 464, 8, 25, 1, 25, 1, 25, 3, 25, 468, - 8, 25, 1, 25, 3, 25, 471, 8, 25, 1, 25, 1, - 25, 3, 25, 475, 8, 25, 1, 25, 3, 25, 478, 8, - 25, 1, 25, 1, 25, 3, 25, 482, 8, 25, 1, 25, - 3, 25, 485, 8, 25, 1, 25, 1, 25, 3, 25, 489, - 8, 25, 1, 25, 3, 25, 492, 8, 25, 1, 25, 1, - 25, 3, 25, 496, 8, 25, 1, 25, 3, 25, 499, 8, - 25, 3, 25, 501, 8, 25, 1, 26, 1, 26, 1, 26, - 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, - 1, 29, 1, 29, 3, 29, 514, 8, 29, 1, 30, 1, - 30, 1, 30, 3, 30, 519, 8, 30, 3, 30, 521, 8, - 30, 1, 31, 1, 31, 1, 31, 3, 31, 526, 8, 31, - 1, 31, 1, 31, 1, 32, 3, 32, 531, 8, 32, 1, - 32, 5, 32, 534, 8, 32, 10, 32, 12, 32, 537, 9, - 32, 1, 33, 1, 33, 3, 33, 541, 8, 33, 1, 33, - 3, 33, 544, 8, 33, 1, 34, 1, 34, 1, 34, 3, - 34, 549, 8, 34, 3, 34, 551, 8, 34, 1, 35, 1, - 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, - 35, 3, 35, 561, 8, 35, 1, 36, 1, 36, 1, 36, - 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, - 3, 38, 572, 8, 38, 1, 38, 1, 38, 1, 38, 1, - 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, - 39, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 3, - 41, 589, 8, 41, 1, 42, 1, 42, 1, 42, 5, 42, - 594, 8, 42, 10, 42, 12, 42, 597, 9, 42, 1, 42, - 1, 42, 1, 43, 1, 43, 1, 43, 5, 43, 604, 8, - 43, 10, 43, 12, 43, 607, 9, 43, 1, 43, 3, 43, - 610, 8, 43, 1, 43, 1, 43, 5, 43, 614, 8, 43, - 10, 43, 12, 43, 617, 9, 43, 1, 43, 1, 43, 1, - 44, 1, 44, 5, 44, 623, 8, 44, 10, 44, 12, 44, - 626, 9, 44, 1, 44, 1, 44, 3, 44, 630, 8, 44, - 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 3, 45, - 637, 8, 45, 1, 46, 1, 46, 1, 46, 1, 47, 1, - 47, 1, 47, 5, 47, 645, 8, 47, 10, 47, 12, 47, - 648, 9, 47, 1, 48, 1, 48, 1, 48, 1, 49, 1, - 49, 1, 49, 3, 49, 656, 8, 49, 1, 50, 1, 50, - 1, 50, 1, 51, 1, 51, 1, 51, 3, 51, 664, 8, - 51, 1, 51, 1, 51, 1, 51, 5, 51, 669, 8, 51, - 10, 51, 12, 51, 672, 9, 51, 1, 51, 1, 51, 3, - 51, 676, 8, 51, 1, 52, 1, 52, 1, 52, 1, 52, - 1, 52, 5, 52, 683, 8, 52, 10, 52, 12, 52, 686, - 9, 52, 1, 52, 1, 52, 3, 52, 690, 8, 52, 1, - 53, 1, 53, 3, 53, 694, 8, 53, 1, 53, 1, 53, - 1, 54, 1, 54, 1, 54, 3, 54, 701, 8, 54, 3, - 54, 703, 8, 54, 1, 55, 1, 55, 1, 55, 1, 55, - 1, 55, 1, 55, 3, 55, 711, 8, 55, 1, 56, 3, - 56, 714, 8, 56, 1, 57, 1, 57, 1, 57, 1, 57, - 1, 57, 1, 57, 3, 57, 722, 8, 57, 5, 57, 724, - 8, 57, 10, 57, 12, 57, 727, 9, 57, 1, 58, 1, - 58, 3, 58, 731, 8, 58, 1, 59, 1, 59, 1, 59, - 5, 59, 736, 8, 59, 10, 59, 12, 59, 739, 9, 59, - 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, - 1, 61, 1, 61, 3, 61, 749, 8, 61, 1, 62, 3, - 62, 752, 8, 62, 1, 63, 1, 63, 1, 63, 3, 63, - 757, 8, 63, 5, 63, 759, 8, 63, 10, 63, 12, 63, - 762, 9, 63, 1, 64, 1, 64, 1, 65, 1, 65, 1, - 66, 1, 66, 1, 66, 1, 67, 1, 67, 1, 67, 1, - 68, 1, 68, 3, 68, 776, 8, 68, 1, 69, 1, 69, - 1, 69, 5, 69, 781, 8, 69, 10, 69, 12, 69, 784, - 9, 69, 1, 70, 1, 70, 1, 71, 1, 71, 1, 72, - 1, 72, 1, 72, 5, 72, 793, 8, 72, 10, 72, 12, - 72, 796, 9, 72, 1, 73, 1, 73, 1, 73, 5, 73, - 801, 8, 73, 10, 73, 12, 73, 804, 9, 73, 1, 74, - 1, 74, 3, 74, 808, 8, 74, 1, 75, 1, 75, 1, - 75, 3, 75, 813, 8, 75, 1, 76, 1, 76, 1, 77, - 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, - 1, 77, 3, 77, 825, 8, 77, 1, 78, 1, 78, 1, - 78, 1, 78, 1, 78, 5, 78, 832, 8, 78, 10, 78, - 12, 78, 835, 9, 78, 3, 78, 837, 8, 78, 1, 78, - 3, 78, 840, 8, 78, 1, 79, 1, 79, 1, 79, 1, - 79, 1, 79, 3, 79, 847, 8, 79, 3, 79, 849, 8, - 79, 1, 80, 1, 80, 1, 81, 1, 81, 3, 81, 855, - 8, 81, 1, 82, 1, 82, 1, 82, 1, 82, 1, 83, - 1, 83, 3, 83, 863, 8, 83, 1, 84, 1, 84, 1, - 84, 1, 84, 1, 85, 1, 85, 4, 85, 871, 8, 85, - 11, 85, 12, 85, 872, 1, 85, 1, 85, 1, 86, 1, - 86, 4, 86, 879, 8, 86, 11, 86, 12, 86, 880, 1, - 86, 1, 86, 1, 87, 1, 87, 3, 87, 887, 8, 87, - 1, 88, 1, 88, 3, 88, 891, 8, 88, 1, 89, 1, - 89, 3, 89, 895, 8, 89, 1, 90, 1, 90, 3, 90, - 899, 8, 90, 1, 91, 1, 91, 1, 92, 1, 92, 1, - 92, 1, 92, 1, 92, 1, 92, 3, 92, 909, 8, 92, - 1, 93, 1, 93, 1, 94, 1, 94, 1, 94, 5, 94, - 916, 8, 94, 10, 94, 12, 94, 919, 9, 94, 1, 95, - 1, 95, 1, 95, 5, 95, 924, 8, 95, 10, 95, 12, - 95, 927, 9, 95, 1, 96, 1, 96, 1, 97, 1, 97, - 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, - 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, - 1, 97, 1, 97, 1, 97, 1, 97, 3, 97, 949, 8, - 97, 1, 98, 1, 98, 1, 99, 1, 99, 5, 99, 955, - 8, 99, 10, 99, 12, 99, 958, 9, 99, 1, 100, 1, - 100, 1, 100, 1, 100, 1, 100, 3, 100, 965, 8, 100, - 1, 101, 1, 101, 1, 102, 1, 102, 1, 103, 1, 103, - 3, 103, 973, 8, 103, 1, 103, 5, 103, 976, 8, 103, - 10, 103, 12, 103, 979, 9, 103, 1, 104, 1, 104, 5, - 104, 983, 8, 104, 10, 104, 12, 104, 986, 9, 104, 1, - 105, 1, 105, 3, 105, 990, 8, 105, 1, 106, 1, 106, - 1, 106, 1, 107, 1, 107, 1, 107, 1, 108, 1, 108, - 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 3, 108, - 1005, 8, 108, 1, 109, 1, 109, 1, 109, 1, 109, 1, - 109, 1, 109, 1, 109, 3, 109, 1014, 8, 109, 1, 110, - 1, 110, 1, 110, 1, 110, 1, 111, 1, 111, 1, 111, - 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, - 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, - 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, - 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, - 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, - 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, - 1, 111, 3, 111, 1060, 8, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, - 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 3, - 111, 1274, 8, 111, 1, 112, 1, 112, 1, 112, 1, 112, - 1, 112, 1, 112, 1, 112, 3, 112, 1283, 8, 112, 1, - 112, 1, 112, 1, 113, 1, 113, 1, 113, 1, 113, 1, - 113, 1, 114, 1, 114, 1, 114, 1, 114, 1, 114, 1, - 114, 1, 114, 3, 114, 1299, 8, 114, 1, 114, 1, 114, - 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, - 1, 115, 1, 115, 1, 115, 3, 115, 1312, 8, 115, 1, - 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, 117, 1, - 117, 1, 117, 1, 117, 1, 118, 1, 118, 1, 118, 3, - 118, 1326, 8, 118, 1, 118, 1, 118, 3, 118, 1330, 8, - 118, 1, 118, 1, 118, 1, 118, 1, 118, 3, 118, 1336, - 8, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, - 1, 118, 3, 118, 1344, 8, 118, 1, 118, 1, 118, 1, - 118, 1, 118, 1, 118, 1, 118, 3, 118, 1352, 8, 118, - 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, - 3, 118, 1360, 8, 118, 1, 118, 1, 118, 1, 118, 1, - 118, 1, 118, 1, 118, 3, 118, 1368, 8, 118, 1, 118, - 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 3, 118, - 1376, 8, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, - 118, 3, 118, 1383, 8, 118, 1, 118, 1, 118, 3, 118, - 1387, 8, 118, 1, 119, 1, 119, 3, 119, 1391, 8, 119, - 1, 120, 1, 120, 1, 120, 1, 120, 3, 120, 1397, 8, - 120, 1, 121, 1, 121, 1, 121, 3, 121, 1402, 8, 121, - 1, 122, 1, 122, 1, 123, 1, 123, 1, 124, 1, 124, - 1, 125, 1, 125, 1, 126, 1, 126, 1, 127, 3, 127, - 1415, 8, 127, 1, 127, 1, 127, 3, 127, 1419, 8, 127, - 1, 128, 1, 128, 3, 128, 1423, 8, 128, 1, 129, 1, - 129, 1, 130, 1, 130, 1, 131, 1, 131, 1, 132, 1, - 132, 1, 132, 0, 0, 133, 0, 2, 4, 6, 8, 10, - 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, - 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, - 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, - 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, - 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, - 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, - 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, - 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, - 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, - 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, - 252, 254, 256, 258, 260, 262, 264, 0, 10, 1, 0, 33, - 34, 1, 0, 47, 48, 2, 0, 1, 1, 13, 14, 1, - 0, 143, 144, 1, 0, 147, 149, 1, 0, 150, 152, 1, - 0, 153, 155, 1, 0, 28, 29, 1, 0, 157, 160, 2, - 0, 142, 142, 163, 163, 1536, 0, 266, 1, 0, 0, 0, - 2, 280, 1, 0, 0, 0, 4, 283, 1, 0, 0, 0, - 6, 286, 1, 0, 0, 0, 8, 290, 1, 0, 0, 0, - 10, 300, 1, 0, 0, 0, 12, 305, 1, 0, 0, 0, - 14, 319, 1, 0, 0, 0, 16, 321, 1, 0, 0, 0, - 18, 325, 1, 0, 0, 0, 20, 329, 1, 0, 0, 0, - 22, 355, 1, 0, 0, 0, 24, 375, 1, 0, 0, 0, - 26, 385, 1, 0, 0, 0, 28, 390, 1, 0, 0, 0, - 30, 392, 1, 0, 0, 0, 32, 395, 1, 0, 0, 0, - 34, 398, 1, 0, 0, 0, 36, 403, 1, 0, 0, 0, - 38, 414, 1, 0, 0, 0, 40, 431, 1, 0, 0, 0, - 42, 433, 1, 0, 0, 0, 44, 439, 1, 0, 0, 0, - 46, 443, 1, 0, 0, 0, 48, 456, 1, 0, 0, 0, - 50, 500, 1, 0, 0, 0, 52, 502, 1, 0, 0, 0, - 54, 505, 1, 0, 0, 0, 56, 508, 1, 0, 0, 0, - 58, 513, 1, 0, 0, 0, 60, 515, 1, 0, 0, 0, - 62, 522, 1, 0, 0, 0, 64, 530, 1, 0, 0, 0, - 66, 538, 1, 0, 0, 0, 68, 545, 1, 0, 0, 0, - 70, 560, 1, 0, 0, 0, 72, 562, 1, 0, 0, 0, - 74, 565, 1, 0, 0, 0, 76, 569, 1, 0, 0, 0, - 78, 576, 1, 0, 0, 0, 80, 583, 1, 0, 0, 0, - 82, 588, 1, 0, 0, 0, 84, 590, 1, 0, 0, 0, - 86, 609, 1, 0, 0, 0, 88, 629, 1, 0, 0, 0, - 90, 636, 1, 0, 0, 0, 92, 638, 1, 0, 0, 0, - 94, 641, 1, 0, 0, 0, 96, 649, 1, 0, 0, 0, - 98, 655, 1, 0, 0, 0, 100, 657, 1, 0, 0, 0, - 102, 675, 1, 0, 0, 0, 104, 689, 1, 0, 0, 0, - 106, 691, 1, 0, 0, 0, 108, 697, 1, 0, 0, 0, - 110, 710, 1, 0, 0, 0, 112, 713, 1, 0, 0, 0, - 114, 715, 1, 0, 0, 0, 116, 730, 1, 0, 0, 0, - 118, 732, 1, 0, 0, 0, 120, 740, 1, 0, 0, 0, - 122, 748, 1, 0, 0, 0, 124, 751, 1, 0, 0, 0, - 126, 753, 1, 0, 0, 0, 128, 763, 1, 0, 0, 0, - 130, 765, 1, 0, 0, 0, 132, 767, 1, 0, 0, 0, - 134, 770, 1, 0, 0, 0, 136, 775, 1, 0, 0, 0, - 138, 777, 1, 0, 0, 0, 140, 785, 1, 0, 0, 0, - 142, 787, 1, 0, 0, 0, 144, 789, 1, 0, 0, 0, - 146, 797, 1, 0, 0, 0, 148, 805, 1, 0, 0, 0, - 150, 812, 1, 0, 0, 0, 152, 814, 1, 0, 0, 0, - 154, 824, 1, 0, 0, 0, 156, 839, 1, 0, 0, 0, - 158, 848, 1, 0, 0, 0, 160, 850, 1, 0, 0, 0, - 162, 854, 1, 0, 0, 0, 164, 856, 1, 0, 0, 0, - 166, 862, 1, 0, 0, 0, 168, 864, 1, 0, 0, 0, - 170, 868, 1, 0, 0, 0, 172, 876, 1, 0, 0, 0, - 174, 886, 1, 0, 0, 0, 176, 890, 1, 0, 0, 0, - 178, 894, 1, 0, 0, 0, 180, 898, 1, 0, 0, 0, - 182, 900, 1, 0, 0, 0, 184, 908, 1, 0, 0, 0, - 186, 910, 1, 0, 0, 0, 188, 912, 1, 0, 0, 0, - 190, 920, 1, 0, 0, 0, 192, 928, 1, 0, 0, 0, - 194, 930, 1, 0, 0, 0, 196, 950, 1, 0, 0, 0, - 198, 952, 1, 0, 0, 0, 200, 964, 1, 0, 0, 0, - 202, 966, 1, 0, 0, 0, 204, 968, 1, 0, 0, 0, - 206, 972, 1, 0, 0, 0, 208, 980, 1, 0, 0, 0, - 210, 989, 1, 0, 0, 0, 212, 991, 1, 0, 0, 0, - 214, 994, 1, 0, 0, 0, 216, 1004, 1, 0, 0, 0, - 218, 1013, 1, 0, 0, 0, 220, 1015, 1, 0, 0, 0, - 222, 1273, 1, 0, 0, 0, 224, 1275, 1, 0, 0, 0, - 226, 1286, 1, 0, 0, 0, 228, 1291, 1, 0, 0, 0, - 230, 1302, 1, 0, 0, 0, 232, 1315, 1, 0, 0, 0, - 234, 1318, 1, 0, 0, 0, 236, 1386, 1, 0, 0, 0, - 238, 1388, 1, 0, 0, 0, 240, 1392, 1, 0, 0, 0, - 242, 1401, 1, 0, 0, 0, 244, 1403, 1, 0, 0, 0, - 246, 1405, 1, 0, 0, 0, 248, 1407, 1, 0, 0, 0, - 250, 1409, 1, 0, 0, 0, 252, 1411, 1, 0, 0, 0, - 254, 1414, 1, 0, 0, 0, 256, 1422, 1, 0, 0, 0, - 258, 1424, 1, 0, 0, 0, 260, 1426, 1, 0, 0, 0, - 262, 1428, 1, 0, 0, 0, 264, 1430, 1, 0, 0, 0, - 266, 271, 3, 2, 1, 0, 267, 272, 3, 8, 4, 0, - 268, 272, 3, 20, 10, 0, 269, 272, 3, 22, 11, 0, - 270, 272, 3, 24, 12, 0, 271, 267, 1, 0, 0, 0, - 271, 268, 1, 0, 0, 0, 271, 269, 1, 0, 0, 0, - 271, 270, 1, 0, 0, 0, 272, 273, 1, 0, 0, 0, - 273, 274, 3, 58, 29, 0, 274, 275, 5, 0, 0, 1, - 275, 1, 1, 0, 0, 0, 276, 279, 3, 4, 2, 0, - 277, 279, 3, 6, 3, 0, 278, 276, 1, 0, 0, 0, - 278, 277, 1, 0, 0, 0, 279, 282, 1, 0, 0, 0, - 280, 278, 1, 0, 0, 0, 280, 281, 1, 0, 0, 0, - 281, 3, 1, 0, 0, 0, 282, 280, 1, 0, 0, 0, - 283, 284, 5, 30, 0, 0, 284, 285, 3, 260, 130, 0, - 285, 5, 1, 0, 0, 0, 286, 287, 5, 31, 0, 0, - 287, 288, 5, 140, 0, 0, 288, 289, 3, 260, 130, 0, - 289, 7, 1, 0, 0, 0, 290, 294, 3, 12, 6, 0, - 291, 293, 3, 26, 13, 0, 292, 291, 1, 0, 0, 0, - 293, 296, 1, 0, 0, 0, 294, 292, 1, 0, 0, 0, - 294, 295, 1, 0, 0, 0, 295, 297, 1, 0, 0, 0, - 296, 294, 1, 0, 0, 0, 297, 298, 3, 34, 17, 0, - 298, 299, 3, 36, 18, 0, 299, 9, 1, 0, 0, 0, - 300, 301, 3, 12, 6, 0, 301, 302, 3, 34, 17, 0, - 302, 303, 3, 36, 18, 0, 303, 304, 3, 58, 29, 0, - 304, 11, 1, 0, 0, 0, 305, 307, 5, 32, 0, 0, - 306, 308, 7, 0, 0, 0, 307, 306, 1, 0, 0, 0, - 307, 308, 1, 0, 0, 0, 308, 315, 1, 0, 0, 0, - 309, 311, 3, 14, 7, 0, 310, 309, 1, 0, 0, 0, - 311, 312, 1, 0, 0, 0, 312, 310, 1, 0, 0, 0, - 312, 313, 1, 0, 0, 0, 313, 316, 1, 0, 0, 0, - 314, 316, 5, 1, 0, 0, 315, 310, 1, 0, 0, 0, - 315, 314, 1, 0, 0, 0, 316, 13, 1, 0, 0, 0, - 317, 320, 3, 182, 91, 0, 318, 320, 3, 16, 8, 0, - 319, 317, 1, 0, 0, 0, 319, 318, 1, 0, 0, 0, - 320, 15, 1, 0, 0, 0, 321, 322, 5, 2, 0, 0, - 322, 323, 3, 18, 9, 0, 323, 324, 5, 3, 0, 0, - 324, 17, 1, 0, 0, 0, 325, 326, 3, 186, 93, 0, - 326, 327, 5, 35, 0, 0, 327, 328, 3, 182, 91, 0, - 328, 19, 1, 0, 0, 0, 329, 353, 5, 36, 0, 0, - 330, 334, 3, 106, 53, 0, 331, 333, 3, 26, 13, 0, - 332, 331, 1, 0, 0, 0, 333, 336, 1, 0, 0, 0, - 334, 332, 1, 0, 0, 0, 334, 335, 1, 0, 0, 0, - 335, 337, 1, 0, 0, 0, 336, 334, 1, 0, 0, 0, - 337, 338, 3, 34, 17, 0, 338, 339, 3, 36, 18, 0, - 339, 354, 1, 0, 0, 0, 340, 342, 3, 26, 13, 0, - 341, 340, 1, 0, 0, 0, 342, 345, 1, 0, 0, 0, - 343, 341, 1, 0, 0, 0, 343, 344, 1, 0, 0, 0, - 344, 346, 1, 0, 0, 0, 345, 343, 1, 0, 0, 0, - 346, 347, 5, 37, 0, 0, 347, 349, 5, 4, 0, 0, - 348, 350, 3, 60, 30, 0, 349, 348, 1, 0, 0, 0, - 349, 350, 1, 0, 0, 0, 350, 351, 1, 0, 0, 0, - 351, 352, 5, 5, 0, 0, 352, 354, 3, 36, 18, 0, - 353, 330, 1, 0, 0, 0, 353, 343, 1, 0, 0, 0, - 354, 21, 1, 0, 0, 0, 355, 362, 5, 38, 0, 0, - 356, 358, 3, 180, 90, 0, 357, 356, 1, 0, 0, 0, - 358, 359, 1, 0, 0, 0, 359, 357, 1, 0, 0, 0, - 359, 360, 1, 0, 0, 0, 360, 363, 1, 0, 0, 0, - 361, 363, 5, 1, 0, 0, 362, 357, 1, 0, 0, 0, - 362, 361, 1, 0, 0, 0, 363, 367, 1, 0, 0, 0, - 364, 366, 3, 26, 13, 0, 365, 364, 1, 0, 0, 0, - 366, 369, 1, 0, 0, 0, 367, 365, 1, 0, 0, 0, - 367, 368, 1, 0, 0, 0, 368, 371, 1, 0, 0, 0, - 369, 367, 1, 0, 0, 0, 370, 372, 3, 34, 17, 0, - 371, 370, 1, 0, 0, 0, 371, 372, 1, 0, 0, 0, - 372, 373, 1, 0, 0, 0, 373, 374, 3, 36, 18, 0, - 374, 23, 1, 0, 0, 0, 375, 379, 5, 39, 0, 0, - 376, 378, 3, 26, 13, 0, 377, 376, 1, 0, 0, 0, - 378, 381, 1, 0, 0, 0, 379, 377, 1, 0, 0, 0, - 379, 380, 1, 0, 0, 0, 380, 382, 1, 0, 0, 0, - 381, 379, 1, 0, 0, 0, 382, 383, 3, 34, 17, 0, - 383, 384, 3, 36, 18, 0, 384, 25, 1, 0, 0, 0, - 385, 388, 5, 40, 0, 0, 386, 389, 3, 28, 14, 0, - 387, 389, 3, 30, 15, 0, 388, 386, 1, 0, 0, 0, - 388, 387, 1, 0, 0, 0, 389, 27, 1, 0, 0, 0, - 390, 391, 3, 32, 16, 0, 391, 29, 1, 0, 0, 0, - 392, 393, 5, 41, 0, 0, 393, 394, 3, 32, 16, 0, - 394, 31, 1, 0, 0, 0, 395, 396, 3, 254, 127, 0, - 396, 33, 1, 0, 0, 0, 397, 399, 5, 37, 0, 0, - 398, 397, 1, 0, 0, 0, 398, 399, 1, 0, 0, 0, - 399, 400, 1, 0, 0, 0, 400, 401, 3, 62, 31, 0, - 401, 35, 1, 0, 0, 0, 402, 404, 3, 38, 19, 0, - 403, 402, 1, 0, 0, 0, 403, 404, 1, 0, 0, 0, - 404, 406, 1, 0, 0, 0, 405, 407, 3, 42, 21, 0, - 406, 405, 1, 0, 0, 0, 406, 407, 1, 0, 0, 0, - 407, 409, 1, 0, 0, 0, 408, 410, 3, 46, 23, 0, - 409, 408, 1, 0, 0, 0, 409, 410, 1, 0, 0, 0, - 410, 412, 1, 0, 0, 0, 411, 413, 3, 50, 25, 0, - 412, 411, 1, 0, 0, 0, 412, 413, 1, 0, 0, 0, - 413, 37, 1, 0, 0, 0, 414, 416, 5, 42, 0, 0, - 415, 417, 3, 40, 20, 0, 416, 415, 1, 0, 0, 0, - 417, 418, 1, 0, 0, 0, 418, 416, 1, 0, 0, 0, - 418, 419, 1, 0, 0, 0, 419, 39, 1, 0, 0, 0, - 420, 432, 3, 222, 111, 0, 421, 432, 3, 100, 50, 0, - 422, 423, 5, 2, 0, 0, 423, 426, 3, 186, 93, 0, - 424, 425, 5, 35, 0, 0, 425, 427, 3, 182, 91, 0, - 426, 424, 1, 0, 0, 0, 426, 427, 1, 0, 0, 0, - 427, 428, 1, 0, 0, 0, 428, 429, 5, 3, 0, 0, - 429, 432, 1, 0, 0, 0, 430, 432, 3, 182, 91, 0, - 431, 420, 1, 0, 0, 0, 431, 421, 1, 0, 0, 0, - 431, 422, 1, 0, 0, 0, 431, 430, 1, 0, 0, 0, - 432, 41, 1, 0, 0, 0, 433, 435, 5, 44, 0, 0, - 434, 436, 3, 44, 22, 0, 435, 434, 1, 0, 0, 0, - 436, 437, 1, 0, 0, 0, 437, 435, 1, 0, 0, 0, - 437, 438, 1, 0, 0, 0, 438, 43, 1, 0, 0, 0, - 439, 440, 3, 98, 49, 0, 440, 45, 1, 0, 0, 0, - 441, 444, 5, 45, 0, 0, 442, 444, 5, 46, 0, 0, - 443, 441, 1, 0, 0, 0, 443, 442, 1, 0, 0, 0, - 444, 446, 1, 0, 0, 0, 445, 447, 3, 48, 24, 0, - 446, 445, 1, 0, 0, 0, 447, 448, 1, 0, 0, 0, - 448, 446, 1, 0, 0, 0, 448, 449, 1, 0, 0, 0, - 449, 47, 1, 0, 0, 0, 450, 451, 7, 1, 0, 0, - 451, 457, 3, 220, 110, 0, 452, 455, 3, 98, 49, 0, - 453, 455, 3, 182, 91, 0, 454, 452, 1, 0, 0, 0, - 454, 453, 1, 0, 0, 0, 455, 457, 1, 0, 0, 0, - 456, 450, 1, 0, 0, 0, 456, 454, 1, 0, 0, 0, - 457, 49, 1, 0, 0, 0, 458, 460, 3, 52, 26, 0, - 459, 461, 3, 54, 27, 0, 460, 459, 1, 0, 0, 0, - 460, 461, 1, 0, 0, 0, 461, 463, 1, 0, 0, 0, - 462, 464, 3, 56, 28, 0, 463, 462, 1, 0, 0, 0, - 463, 464, 1, 0, 0, 0, 464, 501, 1, 0, 0, 0, - 465, 467, 3, 52, 26, 0, 466, 468, 3, 56, 28, 0, - 467, 466, 1, 0, 0, 0, 467, 468, 1, 0, 0, 0, - 468, 470, 1, 0, 0, 0, 469, 471, 3, 54, 27, 0, - 470, 469, 1, 0, 0, 0, 470, 471, 1, 0, 0, 0, - 471, 501, 1, 0, 0, 0, 472, 474, 3, 54, 27, 0, - 473, 475, 3, 52, 26, 0, 474, 473, 1, 0, 0, 0, - 474, 475, 1, 0, 0, 0, 475, 477, 1, 0, 0, 0, - 476, 478, 3, 56, 28, 0, 477, 476, 1, 0, 0, 0, - 477, 478, 1, 0, 0, 0, 478, 501, 1, 0, 0, 0, - 479, 481, 3, 54, 27, 0, 480, 482, 3, 56, 28, 0, - 481, 480, 1, 0, 0, 0, 481, 482, 1, 0, 0, 0, - 482, 484, 1, 0, 0, 0, 483, 485, 3, 52, 26, 0, - 484, 483, 1, 0, 0, 0, 484, 485, 1, 0, 0, 0, - 485, 501, 1, 0, 0, 0, 486, 488, 3, 56, 28, 0, - 487, 489, 3, 54, 27, 0, 488, 487, 1, 0, 0, 0, - 488, 489, 1, 0, 0, 0, 489, 491, 1, 0, 0, 0, - 490, 492, 3, 52, 26, 0, 491, 490, 1, 0, 0, 0, - 491, 492, 1, 0, 0, 0, 492, 501, 1, 0, 0, 0, - 493, 495, 3, 56, 28, 0, 494, 496, 3, 52, 26, 0, - 495, 494, 1, 0, 0, 0, 495, 496, 1, 0, 0, 0, - 496, 498, 1, 0, 0, 0, 497, 499, 3, 54, 27, 0, - 498, 497, 1, 0, 0, 0, 498, 499, 1, 0, 0, 0, - 499, 501, 1, 0, 0, 0, 500, 458, 1, 0, 0, 0, - 500, 465, 1, 0, 0, 0, 500, 472, 1, 0, 0, 0, - 500, 479, 1, 0, 0, 0, 500, 486, 1, 0, 0, 0, - 500, 493, 1, 0, 0, 0, 501, 51, 1, 0, 0, 0, - 502, 503, 5, 49, 0, 0, 503, 504, 3, 160, 80, 0, - 504, 53, 1, 0, 0, 0, 505, 506, 5, 50, 0, 0, - 506, 507, 3, 160, 80, 0, 507, 55, 1, 0, 0, 0, - 508, 509, 5, 51, 0, 0, 509, 510, 3, 160, 80, 0, - 510, 57, 1, 0, 0, 0, 511, 512, 5, 52, 0, 0, - 512, 514, 3, 82, 41, 0, 513, 511, 1, 0, 0, 0, - 513, 514, 1, 0, 0, 0, 514, 59, 1, 0, 0, 0, - 515, 520, 3, 110, 55, 0, 516, 518, 5, 6, 0, 0, - 517, 519, 3, 60, 30, 0, 518, 517, 1, 0, 0, 0, - 518, 519, 1, 0, 0, 0, 519, 521, 1, 0, 0, 0, - 520, 516, 1, 0, 0, 0, 520, 521, 1, 0, 0, 0, - 521, 61, 1, 0, 0, 0, 522, 525, 5, 4, 0, 0, - 523, 526, 3, 10, 5, 0, 524, 526, 3, 64, 32, 0, - 525, 523, 1, 0, 0, 0, 525, 524, 1, 0, 0, 0, - 526, 527, 1, 0, 0, 0, 527, 528, 5, 5, 0, 0, - 528, 63, 1, 0, 0, 0, 529, 531, 3, 68, 34, 0, - 530, 529, 1, 0, 0, 0, 530, 531, 1, 0, 0, 0, - 531, 535, 1, 0, 0, 0, 532, 534, 3, 66, 33, 0, - 533, 532, 1, 0, 0, 0, 534, 537, 1, 0, 0, 0, - 535, 533, 1, 0, 0, 0, 535, 536, 1, 0, 0, 0, - 536, 65, 1, 0, 0, 0, 537, 535, 1, 0, 0, 0, - 538, 540, 3, 70, 35, 0, 539, 541, 5, 6, 0, 0, - 540, 539, 1, 0, 0, 0, 540, 541, 1, 0, 0, 0, - 541, 543, 1, 0, 0, 0, 542, 544, 3, 68, 34, 0, - 543, 542, 1, 0, 0, 0, 543, 544, 1, 0, 0, 0, - 544, 67, 1, 0, 0, 0, 545, 550, 3, 122, 61, 0, - 546, 548, 5, 6, 0, 0, 547, 549, 3, 68, 34, 0, - 548, 547, 1, 0, 0, 0, 548, 549, 1, 0, 0, 0, - 549, 551, 1, 0, 0, 0, 550, 546, 1, 0, 0, 0, - 550, 551, 1, 0, 0, 0, 551, 69, 1, 0, 0, 0, - 552, 561, 3, 94, 47, 0, 553, 561, 3, 72, 36, 0, - 554, 561, 3, 92, 46, 0, 555, 561, 3, 74, 37, 0, - 556, 561, 3, 76, 38, 0, 557, 561, 3, 96, 48, 0, - 558, 561, 3, 78, 39, 0, 559, 561, 3, 80, 40, 0, - 560, 552, 1, 0, 0, 0, 560, 553, 1, 0, 0, 0, - 560, 554, 1, 0, 0, 0, 560, 555, 1, 0, 0, 0, - 560, 556, 1, 0, 0, 0, 560, 557, 1, 0, 0, 0, - 560, 558, 1, 0, 0, 0, 560, 559, 1, 0, 0, 0, - 561, 71, 1, 0, 0, 0, 562, 563, 5, 69, 0, 0, - 563, 564, 3, 62, 31, 0, 564, 73, 1, 0, 0, 0, - 565, 566, 5, 67, 0, 0, 566, 567, 3, 180, 90, 0, - 567, 568, 3, 62, 31, 0, 568, 75, 1, 0, 0, 0, - 569, 571, 5, 70, 0, 0, 570, 572, 5, 54, 0, 0, - 571, 570, 1, 0, 0, 0, 571, 572, 1, 0, 0, 0, - 572, 573, 1, 0, 0, 0, 573, 574, 3, 180, 90, 0, - 574, 575, 3, 62, 31, 0, 575, 77, 1, 0, 0, 0, - 576, 577, 5, 71, 0, 0, 577, 578, 5, 2, 0, 0, - 578, 579, 3, 186, 93, 0, 579, 580, 5, 35, 0, 0, - 580, 581, 3, 182, 91, 0, 581, 582, 5, 3, 0, 0, - 582, 79, 1, 0, 0, 0, 583, 584, 5, 52, 0, 0, - 584, 585, 3, 82, 41, 0, 585, 81, 1, 0, 0, 0, - 586, 589, 3, 84, 42, 0, 587, 589, 3, 86, 43, 0, - 588, 586, 1, 0, 0, 0, 588, 587, 1, 0, 0, 0, - 589, 83, 1, 0, 0, 0, 590, 591, 3, 182, 91, 0, - 591, 595, 5, 4, 0, 0, 592, 594, 3, 90, 45, 0, - 593, 592, 1, 0, 0, 0, 594, 597, 1, 0, 0, 0, - 595, 593, 1, 0, 0, 0, 595, 596, 1, 0, 0, 0, - 596, 598, 1, 0, 0, 0, 597, 595, 1, 0, 0, 0, - 598, 599, 5, 5, 0, 0, 599, 85, 1, 0, 0, 0, - 600, 610, 5, 162, 0, 0, 601, 605, 5, 2, 0, 0, - 602, 604, 3, 182, 91, 0, 603, 602, 1, 0, 0, 0, - 604, 607, 1, 0, 0, 0, 605, 603, 1, 0, 0, 0, - 605, 606, 1, 0, 0, 0, 606, 608, 1, 0, 0, 0, - 607, 605, 1, 0, 0, 0, 608, 610, 5, 3, 0, 0, - 609, 600, 1, 0, 0, 0, 609, 601, 1, 0, 0, 0, - 610, 611, 1, 0, 0, 0, 611, 615, 5, 4, 0, 0, - 612, 614, 3, 88, 44, 0, 613, 612, 1, 0, 0, 0, - 614, 617, 1, 0, 0, 0, 615, 613, 1, 0, 0, 0, - 615, 616, 1, 0, 0, 0, 616, 618, 1, 0, 0, 0, - 617, 615, 1, 0, 0, 0, 618, 619, 5, 5, 0, 0, - 619, 87, 1, 0, 0, 0, 620, 624, 5, 2, 0, 0, - 621, 623, 3, 90, 45, 0, 622, 621, 1, 0, 0, 0, - 623, 626, 1, 0, 0, 0, 624, 622, 1, 0, 0, 0, - 624, 625, 1, 0, 0, 0, 625, 627, 1, 0, 0, 0, - 626, 624, 1, 0, 0, 0, 627, 630, 5, 3, 0, 0, - 628, 630, 5, 162, 0, 0, 629, 620, 1, 0, 0, 0, - 629, 628, 1, 0, 0, 0, 630, 89, 1, 0, 0, 0, - 631, 637, 3, 254, 127, 0, 632, 637, 3, 240, 120, 0, - 633, 637, 3, 242, 121, 0, 634, 637, 3, 250, 125, 0, - 635, 637, 5, 72, 0, 0, 636, 631, 1, 0, 0, 0, - 636, 632, 1, 0, 0, 0, 636, 633, 1, 0, 0, 0, - 636, 634, 1, 0, 0, 0, 636, 635, 1, 0, 0, 0, - 637, 91, 1, 0, 0, 0, 638, 639, 5, 73, 0, 0, - 639, 640, 3, 62, 31, 0, 640, 93, 1, 0, 0, 0, - 641, 646, 3, 62, 31, 0, 642, 643, 5, 74, 0, 0, - 643, 645, 3, 62, 31, 0, 644, 642, 1, 0, 0, 0, - 645, 648, 1, 0, 0, 0, 646, 644, 1, 0, 0, 0, - 646, 647, 1, 0, 0, 0, 647, 95, 1, 0, 0, 0, - 648, 646, 1, 0, 0, 0, 649, 650, 5, 75, 0, 0, - 650, 651, 3, 98, 49, 0, 651, 97, 1, 0, 0, 0, - 652, 656, 3, 220, 110, 0, 653, 656, 3, 222, 111, 0, - 654, 656, 3, 100, 50, 0, 655, 652, 1, 0, 0, 0, - 655, 653, 1, 0, 0, 0, 655, 654, 1, 0, 0, 0, - 656, 99, 1, 0, 0, 0, 657, 658, 3, 254, 127, 0, - 658, 659, 3, 102, 51, 0, 659, 101, 1, 0, 0, 0, - 660, 676, 5, 162, 0, 0, 661, 663, 5, 2, 0, 0, - 662, 664, 5, 33, 0, 0, 663, 662, 1, 0, 0, 0, - 663, 664, 1, 0, 0, 0, 664, 665, 1, 0, 0, 0, - 665, 670, 3, 186, 93, 0, 666, 667, 5, 7, 0, 0, - 667, 669, 3, 186, 93, 0, 668, 666, 1, 0, 0, 0, - 669, 672, 1, 0, 0, 0, 670, 668, 1, 0, 0, 0, - 670, 671, 1, 0, 0, 0, 671, 673, 1, 0, 0, 0, - 672, 670, 1, 0, 0, 0, 673, 674, 5, 3, 0, 0, - 674, 676, 1, 0, 0, 0, 675, 660, 1, 0, 0, 0, - 675, 661, 1, 0, 0, 0, 676, 103, 1, 0, 0, 0, - 677, 690, 5, 162, 0, 0, 678, 679, 5, 2, 0, 0, - 679, 684, 3, 186, 93, 0, 680, 681, 5, 7, 0, 0, - 681, 683, 3, 186, 93, 0, 682, 680, 1, 0, 0, 0, - 683, 686, 1, 0, 0, 0, 684, 682, 1, 0, 0, 0, - 684, 685, 1, 0, 0, 0, 685, 687, 1, 0, 0, 0, - 686, 684, 1, 0, 0, 0, 687, 688, 5, 3, 0, 0, - 688, 690, 1, 0, 0, 0, 689, 677, 1, 0, 0, 0, - 689, 678, 1, 0, 0, 0, 690, 105, 1, 0, 0, 0, - 691, 693, 5, 4, 0, 0, 692, 694, 3, 108, 54, 0, - 693, 692, 1, 0, 0, 0, 693, 694, 1, 0, 0, 0, - 694, 695, 1, 0, 0, 0, 695, 696, 5, 5, 0, 0, - 696, 107, 1, 0, 0, 0, 697, 702, 3, 110, 55, 0, - 698, 700, 5, 6, 0, 0, 699, 701, 3, 108, 54, 0, - 700, 699, 1, 0, 0, 0, 700, 701, 1, 0, 0, 0, - 701, 703, 1, 0, 0, 0, 702, 698, 1, 0, 0, 0, - 702, 703, 1, 0, 0, 0, 703, 109, 1, 0, 0, 0, - 704, 705, 3, 178, 89, 0, 705, 706, 3, 114, 57, 0, - 706, 711, 1, 0, 0, 0, 707, 708, 3, 162, 81, 0, - 708, 709, 3, 112, 56, 0, 709, 711, 1, 0, 0, 0, - 710, 704, 1, 0, 0, 0, 710, 707, 1, 0, 0, 0, - 711, 111, 1, 0, 0, 0, 712, 714, 3, 114, 57, 0, - 713, 712, 1, 0, 0, 0, 713, 714, 1, 0, 0, 0, - 714, 113, 1, 0, 0, 0, 715, 716, 3, 116, 58, 0, - 716, 725, 3, 118, 59, 0, 717, 721, 5, 8, 0, 0, - 718, 719, 3, 116, 58, 0, 719, 720, 3, 118, 59, 0, - 720, 722, 1, 0, 0, 0, 721, 718, 1, 0, 0, 0, - 721, 722, 1, 0, 0, 0, 722, 724, 1, 0, 0, 0, - 723, 717, 1, 0, 0, 0, 724, 727, 1, 0, 0, 0, - 725, 723, 1, 0, 0, 0, 725, 726, 1, 0, 0, 0, - 726, 115, 1, 0, 0, 0, 727, 725, 1, 0, 0, 0, - 728, 731, 3, 180, 90, 0, 729, 731, 5, 9, 0, 0, - 730, 728, 1, 0, 0, 0, 730, 729, 1, 0, 0, 0, - 731, 117, 1, 0, 0, 0, 732, 737, 3, 120, 60, 0, - 733, 734, 5, 7, 0, 0, 734, 736, 3, 120, 60, 0, - 735, 733, 1, 0, 0, 0, 736, 739, 1, 0, 0, 0, - 737, 735, 1, 0, 0, 0, 737, 738, 1, 0, 0, 0, - 738, 119, 1, 0, 0, 0, 739, 737, 1, 0, 0, 0, - 740, 741, 3, 174, 87, 0, 741, 121, 1, 0, 0, 0, - 742, 743, 3, 178, 89, 0, 743, 744, 3, 126, 63, 0, - 744, 749, 1, 0, 0, 0, 745, 746, 3, 166, 83, 0, - 746, 747, 3, 124, 62, 0, 747, 749, 1, 0, 0, 0, - 748, 742, 1, 0, 0, 0, 748, 745, 1, 0, 0, 0, - 749, 123, 1, 0, 0, 0, 750, 752, 3, 126, 63, 0, - 751, 750, 1, 0, 0, 0, 751, 752, 1, 0, 0, 0, - 752, 125, 1, 0, 0, 0, 753, 760, 3, 134, 67, 0, - 754, 756, 5, 8, 0, 0, 755, 757, 3, 132, 66, 0, - 756, 755, 1, 0, 0, 0, 756, 757, 1, 0, 0, 0, - 757, 759, 1, 0, 0, 0, 758, 754, 1, 0, 0, 0, - 759, 762, 1, 0, 0, 0, 760, 758, 1, 0, 0, 0, - 760, 761, 1, 0, 0, 0, 761, 127, 1, 0, 0, 0, - 762, 760, 1, 0, 0, 0, 763, 764, 3, 142, 71, 0, - 764, 129, 1, 0, 0, 0, 765, 766, 3, 182, 91, 0, - 766, 131, 1, 0, 0, 0, 767, 768, 3, 136, 68, 0, - 768, 769, 3, 118, 59, 0, 769, 133, 1, 0, 0, 0, - 770, 771, 3, 136, 68, 0, 771, 772, 3, 138, 69, 0, - 772, 135, 1, 0, 0, 0, 773, 776, 3, 128, 64, 0, - 774, 776, 3, 130, 65, 0, 775, 773, 1, 0, 0, 0, - 775, 774, 1, 0, 0, 0, 776, 137, 1, 0, 0, 0, - 777, 782, 3, 140, 70, 0, 778, 779, 5, 7, 0, 0, - 779, 781, 3, 140, 70, 0, 780, 778, 1, 0, 0, 0, - 781, 784, 1, 0, 0, 0, 782, 780, 1, 0, 0, 0, - 782, 783, 1, 0, 0, 0, 783, 139, 1, 0, 0, 0, - 784, 782, 1, 0, 0, 0, 785, 786, 3, 176, 88, 0, - 786, 141, 1, 0, 0, 0, 787, 788, 3, 144, 72, 0, - 788, 143, 1, 0, 0, 0, 789, 794, 3, 146, 73, 0, - 790, 791, 5, 10, 0, 0, 791, 793, 3, 146, 73, 0, - 792, 790, 1, 0, 0, 0, 793, 796, 1, 0, 0, 0, - 794, 792, 1, 0, 0, 0, 794, 795, 1, 0, 0, 0, - 795, 145, 1, 0, 0, 0, 796, 794, 1, 0, 0, 0, - 797, 802, 3, 150, 75, 0, 798, 799, 5, 11, 0, 0, - 799, 801, 3, 150, 75, 0, 800, 798, 1, 0, 0, 0, - 801, 804, 1, 0, 0, 0, 802, 800, 1, 0, 0, 0, - 802, 803, 1, 0, 0, 0, 803, 147, 1, 0, 0, 0, - 804, 802, 1, 0, 0, 0, 805, 807, 3, 154, 77, 0, - 806, 808, 3, 152, 76, 0, 807, 806, 1, 0, 0, 0, - 807, 808, 1, 0, 0, 0, 808, 149, 1, 0, 0, 0, - 809, 813, 3, 148, 74, 0, 810, 811, 5, 12, 0, 0, - 811, 813, 3, 148, 74, 0, 812, 809, 1, 0, 0, 0, - 812, 810, 1, 0, 0, 0, 813, 151, 1, 0, 0, 0, - 814, 815, 7, 2, 0, 0, 815, 153, 1, 0, 0, 0, - 816, 825, 3, 254, 127, 0, 817, 825, 5, 9, 0, 0, - 818, 819, 5, 15, 0, 0, 819, 825, 3, 156, 78, 0, - 820, 821, 5, 2, 0, 0, 821, 822, 3, 142, 71, 0, - 822, 823, 5, 3, 0, 0, 823, 825, 1, 0, 0, 0, - 824, 816, 1, 0, 0, 0, 824, 817, 1, 0, 0, 0, - 824, 818, 1, 0, 0, 0, 824, 820, 1, 0, 0, 0, - 825, 155, 1, 0, 0, 0, 826, 840, 3, 158, 79, 0, - 827, 836, 5, 2, 0, 0, 828, 833, 3, 158, 79, 0, - 829, 830, 5, 10, 0, 0, 830, 832, 3, 158, 79, 0, - 831, 829, 1, 0, 0, 0, 832, 835, 1, 0, 0, 0, - 833, 831, 1, 0, 0, 0, 833, 834, 1, 0, 0, 0, - 834, 837, 1, 0, 0, 0, 835, 833, 1, 0, 0, 0, - 836, 828, 1, 0, 0, 0, 836, 837, 1, 0, 0, 0, - 837, 838, 1, 0, 0, 0, 838, 840, 5, 3, 0, 0, - 839, 826, 1, 0, 0, 0, 839, 827, 1, 0, 0, 0, - 840, 157, 1, 0, 0, 0, 841, 849, 3, 254, 127, 0, - 842, 849, 5, 9, 0, 0, 843, 846, 5, 12, 0, 0, - 844, 847, 3, 254, 127, 0, 845, 847, 5, 9, 0, 0, - 846, 844, 1, 0, 0, 0, 846, 845, 1, 0, 0, 0, - 847, 849, 1, 0, 0, 0, 848, 841, 1, 0, 0, 0, - 848, 842, 1, 0, 0, 0, 848, 843, 1, 0, 0, 0, - 849, 159, 1, 0, 0, 0, 850, 851, 5, 147, 0, 0, - 851, 161, 1, 0, 0, 0, 852, 855, 3, 170, 85, 0, - 853, 855, 3, 164, 82, 0, 854, 852, 1, 0, 0, 0, - 854, 853, 1, 0, 0, 0, 855, 163, 1, 0, 0, 0, - 856, 857, 5, 16, 0, 0, 857, 858, 3, 114, 57, 0, - 858, 859, 5, 17, 0, 0, 859, 165, 1, 0, 0, 0, - 860, 863, 3, 172, 86, 0, 861, 863, 3, 168, 84, 0, - 862, 860, 1, 0, 0, 0, 862, 861, 1, 0, 0, 0, - 863, 167, 1, 0, 0, 0, 864, 865, 5, 16, 0, 0, - 865, 866, 3, 126, 63, 0, 866, 867, 5, 17, 0, 0, - 867, 169, 1, 0, 0, 0, 868, 870, 5, 2, 0, 0, - 869, 871, 3, 174, 87, 0, 870, 869, 1, 0, 0, 0, - 871, 872, 1, 0, 0, 0, 872, 870, 1, 0, 0, 0, - 872, 873, 1, 0, 0, 0, 873, 874, 1, 0, 0, 0, - 874, 875, 5, 3, 0, 0, 875, 171, 1, 0, 0, 0, - 876, 878, 5, 2, 0, 0, 877, 879, 3, 176, 88, 0, - 878, 877, 1, 0, 0, 0, 879, 880, 1, 0, 0, 0, - 880, 878, 1, 0, 0, 0, 880, 881, 1, 0, 0, 0, - 881, 882, 1, 0, 0, 0, 882, 883, 5, 3, 0, 0, - 883, 173, 1, 0, 0, 0, 884, 887, 3, 178, 89, 0, - 885, 887, 3, 162, 81, 0, 886, 884, 1, 0, 0, 0, - 886, 885, 1, 0, 0, 0, 887, 175, 1, 0, 0, 0, - 888, 891, 3, 178, 89, 0, 889, 891, 3, 166, 83, 0, - 890, 888, 1, 0, 0, 0, 890, 889, 1, 0, 0, 0, - 891, 177, 1, 0, 0, 0, 892, 895, 3, 182, 91, 0, - 893, 895, 3, 184, 92, 0, 894, 892, 1, 0, 0, 0, - 894, 893, 1, 0, 0, 0, 895, 179, 1, 0, 0, 0, - 896, 899, 3, 182, 91, 0, 897, 899, 3, 254, 127, 0, - 898, 896, 1, 0, 0, 0, 898, 897, 1, 0, 0, 0, - 899, 181, 1, 0, 0, 0, 900, 901, 7, 3, 0, 0, - 901, 183, 1, 0, 0, 0, 902, 909, 3, 254, 127, 0, - 903, 909, 3, 240, 120, 0, 904, 909, 3, 242, 121, 0, - 905, 909, 3, 250, 125, 0, 906, 909, 3, 258, 129, 0, - 907, 909, 5, 162, 0, 0, 908, 902, 1, 0, 0, 0, - 908, 903, 1, 0, 0, 0, 908, 904, 1, 0, 0, 0, - 908, 905, 1, 0, 0, 0, 908, 906, 1, 0, 0, 0, - 908, 907, 1, 0, 0, 0, 909, 185, 1, 0, 0, 0, - 910, 911, 3, 188, 94, 0, 911, 187, 1, 0, 0, 0, - 912, 917, 3, 190, 95, 0, 913, 914, 5, 18, 0, 0, - 914, 916, 3, 190, 95, 0, 915, 913, 1, 0, 0, 0, - 916, 919, 1, 0, 0, 0, 917, 915, 1, 0, 0, 0, - 917, 918, 1, 0, 0, 0, 918, 189, 1, 0, 0, 0, - 919, 917, 1, 0, 0, 0, 920, 925, 3, 192, 96, 0, - 921, 922, 5, 19, 0, 0, 922, 924, 3, 192, 96, 0, - 923, 921, 1, 0, 0, 0, 924, 927, 1, 0, 0, 0, - 925, 923, 1, 0, 0, 0, 925, 926, 1, 0, 0, 0, - 926, 191, 1, 0, 0, 0, 927, 925, 1, 0, 0, 0, - 928, 929, 3, 194, 97, 0, 929, 193, 1, 0, 0, 0, - 930, 948, 3, 196, 98, 0, 931, 932, 5, 20, 0, 0, - 932, 949, 3, 196, 98, 0, 933, 934, 5, 21, 0, 0, - 934, 949, 3, 196, 98, 0, 935, 936, 5, 22, 0, 0, - 936, 949, 3, 196, 98, 0, 937, 938, 5, 23, 0, 0, - 938, 949, 3, 196, 98, 0, 939, 940, 5, 24, 0, 0, - 940, 949, 3, 196, 98, 0, 941, 942, 5, 25, 0, 0, - 942, 949, 3, 196, 98, 0, 943, 944, 5, 77, 0, 0, - 944, 949, 3, 104, 52, 0, 945, 946, 5, 76, 0, 0, - 946, 947, 5, 77, 0, 0, 947, 949, 3, 104, 52, 0, - 948, 931, 1, 0, 0, 0, 948, 933, 1, 0, 0, 0, - 948, 935, 1, 0, 0, 0, 948, 937, 1, 0, 0, 0, - 948, 939, 1, 0, 0, 0, 948, 941, 1, 0, 0, 0, - 948, 943, 1, 0, 0, 0, 948, 945, 1, 0, 0, 0, - 948, 949, 1, 0, 0, 0, 949, 195, 1, 0, 0, 0, - 950, 951, 3, 198, 99, 0, 951, 197, 1, 0, 0, 0, - 952, 956, 3, 208, 104, 0, 953, 955, 3, 200, 100, 0, - 954, 953, 1, 0, 0, 0, 955, 958, 1, 0, 0, 0, - 956, 954, 1, 0, 0, 0, 956, 957, 1, 0, 0, 0, - 957, 199, 1, 0, 0, 0, 958, 956, 1, 0, 0, 0, - 959, 960, 5, 13, 0, 0, 960, 965, 3, 202, 101, 0, - 961, 962, 5, 26, 0, 0, 962, 965, 3, 204, 102, 0, - 963, 965, 3, 206, 103, 0, 964, 959, 1, 0, 0, 0, - 964, 961, 1, 0, 0, 0, 964, 963, 1, 0, 0, 0, - 965, 201, 1, 0, 0, 0, 966, 967, 3, 208, 104, 0, - 967, 203, 1, 0, 0, 0, 968, 969, 3, 208, 104, 0, - 969, 205, 1, 0, 0, 0, 970, 973, 3, 246, 123, 0, - 971, 973, 3, 248, 124, 0, 972, 970, 1, 0, 0, 0, - 972, 971, 1, 0, 0, 0, 973, 977, 1, 0, 0, 0, - 974, 976, 3, 210, 105, 0, 975, 974, 1, 0, 0, 0, - 976, 979, 1, 0, 0, 0, 977, 975, 1, 0, 0, 0, - 977, 978, 1, 0, 0, 0, 978, 207, 1, 0, 0, 0, - 979, 977, 1, 0, 0, 0, 980, 984, 3, 216, 108, 0, - 981, 983, 3, 210, 105, 0, 982, 981, 1, 0, 0, 0, - 983, 986, 1, 0, 0, 0, 984, 982, 1, 0, 0, 0, - 984, 985, 1, 0, 0, 0, 985, 209, 1, 0, 0, 0, - 986, 984, 1, 0, 0, 0, 987, 990, 3, 212, 106, 0, - 988, 990, 3, 214, 107, 0, 989, 987, 1, 0, 0, 0, - 989, 988, 1, 0, 0, 0, 990, 211, 1, 0, 0, 0, - 991, 992, 5, 1, 0, 0, 992, 993, 3, 216, 108, 0, - 993, 213, 1, 0, 0, 0, 994, 995, 5, 11, 0, 0, - 995, 996, 3, 216, 108, 0, 996, 215, 1, 0, 0, 0, - 997, 998, 5, 15, 0, 0, 998, 1005, 3, 218, 109, 0, - 999, 1000, 5, 13, 0, 0, 1000, 1005, 3, 218, 109, 0, - 1001, 1002, 5, 26, 0, 0, 1002, 1005, 3, 218, 109, 0, - 1003, 1005, 3, 218, 109, 0, 1004, 997, 1, 0, 0, 0, - 1004, 999, 1, 0, 0, 0, 1004, 1001, 1, 0, 0, 0, - 1004, 1003, 1, 0, 0, 0, 1005, 217, 1, 0, 0, 0, - 1006, 1014, 3, 220, 110, 0, 1007, 1014, 3, 222, 111, 0, - 1008, 1014, 3, 238, 119, 0, 1009, 1014, 3, 240, 120, 0, - 1010, 1014, 3, 242, 121, 0, 1011, 1014, 3, 250, 125, 0, - 1012, 1014, 3, 182, 91, 0, 1013, 1006, 1, 0, 0, 0, - 1013, 1007, 1, 0, 0, 0, 1013, 1008, 1, 0, 0, 0, - 1013, 1009, 1, 0, 0, 0, 1013, 1010, 1, 0, 0, 0, - 1013, 1011, 1, 0, 0, 0, 1013, 1012, 1, 0, 0, 0, - 1014, 219, 1, 0, 0, 0, 1015, 1016, 5, 2, 0, 0, - 1016, 1017, 3, 186, 93, 0, 1017, 1018, 5, 3, 0, 0, - 1018, 221, 1, 0, 0, 0, 1019, 1274, 3, 236, 118, 0, - 1020, 1021, 5, 78, 0, 0, 1021, 1022, 5, 2, 0, 0, - 1022, 1023, 3, 186, 93, 0, 1023, 1024, 5, 3, 0, 0, - 1024, 1274, 1, 0, 0, 0, 1025, 1274, 3, 226, 113, 0, - 1026, 1027, 5, 80, 0, 0, 1027, 1028, 5, 2, 0, 0, - 1028, 1029, 3, 186, 93, 0, 1029, 1030, 5, 7, 0, 0, - 1030, 1031, 3, 186, 93, 0, 1031, 1032, 5, 3, 0, 0, - 1032, 1274, 1, 0, 0, 0, 1033, 1034, 5, 81, 0, 0, - 1034, 1035, 5, 2, 0, 0, 1035, 1036, 3, 186, 93, 0, - 1036, 1037, 5, 3, 0, 0, 1037, 1274, 1, 0, 0, 0, - 1038, 1039, 5, 82, 0, 0, 1039, 1040, 5, 2, 0, 0, - 1040, 1041, 3, 182, 91, 0, 1041, 1042, 5, 3, 0, 0, - 1042, 1274, 1, 0, 0, 0, 1043, 1044, 5, 83, 0, 0, - 1044, 1045, 5, 2, 0, 0, 1045, 1046, 3, 186, 93, 0, - 1046, 1047, 5, 3, 0, 0, 1047, 1274, 1, 0, 0, 0, - 1048, 1049, 5, 84, 0, 0, 1049, 1050, 5, 2, 0, 0, - 1050, 1051, 3, 186, 93, 0, 1051, 1052, 5, 3, 0, 0, - 1052, 1274, 1, 0, 0, 0, 1053, 1059, 5, 85, 0, 0, - 1054, 1055, 5, 2, 0, 0, 1055, 1056, 3, 186, 93, 0, - 1056, 1057, 5, 3, 0, 0, 1057, 1060, 1, 0, 0, 0, - 1058, 1060, 5, 162, 0, 0, 1059, 1054, 1, 0, 0, 0, - 1059, 1058, 1, 0, 0, 0, 1060, 1274, 1, 0, 0, 0, - 1061, 1062, 5, 86, 0, 0, 1062, 1274, 5, 162, 0, 0, - 1063, 1064, 5, 87, 0, 0, 1064, 1065, 5, 2, 0, 0, - 1065, 1066, 3, 186, 93, 0, 1066, 1067, 5, 3, 0, 0, - 1067, 1274, 1, 0, 0, 0, 1068, 1069, 5, 88, 0, 0, - 1069, 1070, 5, 2, 0, 0, 1070, 1071, 3, 186, 93, 0, - 1071, 1072, 5, 3, 0, 0, 1072, 1274, 1, 0, 0, 0, - 1073, 1074, 5, 89, 0, 0, 1074, 1075, 5, 2, 0, 0, - 1075, 1076, 3, 186, 93, 0, 1076, 1077, 5, 3, 0, 0, - 1077, 1274, 1, 0, 0, 0, 1078, 1079, 5, 90, 0, 0, - 1079, 1080, 5, 2, 0, 0, 1080, 1081, 3, 186, 93, 0, - 1081, 1082, 5, 3, 0, 0, 1082, 1274, 1, 0, 0, 0, - 1083, 1084, 5, 91, 0, 0, 1084, 1274, 3, 104, 52, 0, - 1085, 1274, 3, 228, 114, 0, 1086, 1087, 5, 92, 0, 0, - 1087, 1088, 5, 2, 0, 0, 1088, 1089, 3, 186, 93, 0, - 1089, 1090, 5, 3, 0, 0, 1090, 1274, 1, 0, 0, 0, - 1091, 1274, 3, 230, 115, 0, 1092, 1093, 5, 93, 0, 0, - 1093, 1094, 5, 2, 0, 0, 1094, 1095, 3, 186, 93, 0, - 1095, 1096, 5, 3, 0, 0, 1096, 1274, 1, 0, 0, 0, - 1097, 1098, 5, 94, 0, 0, 1098, 1099, 5, 2, 0, 0, - 1099, 1100, 3, 186, 93, 0, 1100, 1101, 5, 3, 0, 0, - 1101, 1274, 1, 0, 0, 0, 1102, 1103, 5, 95, 0, 0, - 1103, 1104, 5, 2, 0, 0, 1104, 1105, 3, 186, 93, 0, - 1105, 1106, 5, 3, 0, 0, 1106, 1274, 1, 0, 0, 0, - 1107, 1108, 5, 97, 0, 0, 1108, 1109, 5, 2, 0, 0, - 1109, 1110, 3, 186, 93, 0, 1110, 1111, 5, 7, 0, 0, - 1111, 1112, 3, 186, 93, 0, 1112, 1113, 5, 3, 0, 0, - 1113, 1274, 1, 0, 0, 0, 1114, 1115, 5, 98, 0, 0, - 1115, 1116, 5, 2, 0, 0, 1116, 1117, 3, 186, 93, 0, - 1117, 1118, 5, 7, 0, 0, 1118, 1119, 3, 186, 93, 0, - 1119, 1120, 5, 3, 0, 0, 1120, 1274, 1, 0, 0, 0, - 1121, 1122, 5, 99, 0, 0, 1122, 1123, 5, 2, 0, 0, - 1123, 1124, 3, 186, 93, 0, 1124, 1125, 5, 7, 0, 0, - 1125, 1126, 3, 186, 93, 0, 1126, 1127, 5, 3, 0, 0, - 1127, 1274, 1, 0, 0, 0, 1128, 1129, 5, 100, 0, 0, - 1129, 1130, 5, 2, 0, 0, 1130, 1131, 3, 186, 93, 0, - 1131, 1132, 5, 7, 0, 0, 1132, 1133, 3, 186, 93, 0, - 1133, 1134, 5, 3, 0, 0, 1134, 1274, 1, 0, 0, 0, - 1135, 1136, 5, 101, 0, 0, 1136, 1137, 5, 2, 0, 0, - 1137, 1138, 3, 186, 93, 0, 1138, 1139, 5, 7, 0, 0, - 1139, 1140, 3, 186, 93, 0, 1140, 1141, 5, 3, 0, 0, - 1141, 1274, 1, 0, 0, 0, 1142, 1143, 5, 102, 0, 0, - 1143, 1144, 5, 2, 0, 0, 1144, 1145, 3, 186, 93, 0, - 1145, 1146, 5, 3, 0, 0, 1146, 1274, 1, 0, 0, 0, - 1147, 1148, 5, 103, 0, 0, 1148, 1149, 5, 2, 0, 0, - 1149, 1150, 3, 186, 93, 0, 1150, 1151, 5, 3, 0, 0, - 1151, 1274, 1, 0, 0, 0, 1152, 1153, 5, 104, 0, 0, - 1153, 1154, 5, 2, 0, 0, 1154, 1155, 3, 186, 93, 0, - 1155, 1156, 5, 3, 0, 0, 1156, 1274, 1, 0, 0, 0, - 1157, 1158, 5, 105, 0, 0, 1158, 1159, 5, 2, 0, 0, - 1159, 1160, 3, 186, 93, 0, 1160, 1161, 5, 3, 0, 0, - 1161, 1274, 1, 0, 0, 0, 1162, 1163, 5, 106, 0, 0, - 1163, 1164, 5, 2, 0, 0, 1164, 1165, 3, 186, 93, 0, - 1165, 1166, 5, 3, 0, 0, 1166, 1274, 1, 0, 0, 0, - 1167, 1168, 5, 107, 0, 0, 1168, 1169, 5, 2, 0, 0, - 1169, 1170, 3, 186, 93, 0, 1170, 1171, 5, 3, 0, 0, - 1171, 1274, 1, 0, 0, 0, 1172, 1173, 5, 108, 0, 0, - 1173, 1174, 5, 2, 0, 0, 1174, 1175, 3, 186, 93, 0, - 1175, 1176, 5, 3, 0, 0, 1176, 1274, 1, 0, 0, 0, - 1177, 1178, 5, 109, 0, 0, 1178, 1179, 5, 2, 0, 0, - 1179, 1180, 3, 186, 93, 0, 1180, 1181, 5, 3, 0, 0, - 1181, 1274, 1, 0, 0, 0, 1182, 1183, 5, 110, 0, 0, - 1183, 1274, 5, 162, 0, 0, 1184, 1185, 5, 111, 0, 0, - 1185, 1274, 5, 162, 0, 0, 1186, 1187, 5, 112, 0, 0, - 1187, 1274, 5, 162, 0, 0, 1188, 1189, 5, 117, 0, 0, - 1189, 1190, 5, 2, 0, 0, 1190, 1191, 3, 186, 93, 0, - 1191, 1192, 5, 3, 0, 0, 1192, 1274, 1, 0, 0, 0, - 1193, 1194, 5, 113, 0, 0, 1194, 1195, 5, 2, 0, 0, - 1195, 1196, 3, 186, 93, 0, 1196, 1197, 5, 3, 0, 0, - 1197, 1274, 1, 0, 0, 0, 1198, 1199, 5, 114, 0, 0, - 1199, 1200, 5, 2, 0, 0, 1200, 1201, 3, 186, 93, 0, - 1201, 1202, 5, 3, 0, 0, 1202, 1274, 1, 0, 0, 0, - 1203, 1204, 5, 115, 0, 0, 1204, 1205, 5, 2, 0, 0, - 1205, 1206, 3, 186, 93, 0, 1206, 1207, 5, 3, 0, 0, - 1207, 1274, 1, 0, 0, 0, 1208, 1209, 5, 116, 0, 0, - 1209, 1210, 5, 2, 0, 0, 1210, 1211, 3, 186, 93, 0, - 1211, 1212, 5, 3, 0, 0, 1212, 1274, 1, 0, 0, 0, - 1213, 1214, 5, 118, 0, 0, 1214, 1274, 3, 104, 52, 0, - 1215, 1216, 5, 119, 0, 0, 1216, 1217, 5, 2, 0, 0, - 1217, 1218, 3, 186, 93, 0, 1218, 1219, 5, 7, 0, 0, - 1219, 1220, 3, 186, 93, 0, 1220, 1221, 5, 7, 0, 0, - 1221, 1222, 3, 186, 93, 0, 1222, 1223, 5, 3, 0, 0, - 1223, 1274, 1, 0, 0, 0, 1224, 1225, 5, 120, 0, 0, - 1225, 1226, 5, 2, 0, 0, 1226, 1227, 3, 186, 93, 0, - 1227, 1228, 5, 7, 0, 0, 1228, 1229, 3, 186, 93, 0, - 1229, 1230, 5, 3, 0, 0, 1230, 1274, 1, 0, 0, 0, - 1231, 1232, 5, 121, 0, 0, 1232, 1233, 5, 2, 0, 0, - 1233, 1234, 3, 186, 93, 0, 1234, 1235, 5, 7, 0, 0, - 1235, 1236, 3, 186, 93, 0, 1236, 1237, 5, 3, 0, 0, - 1237, 1274, 1, 0, 0, 0, 1238, 1239, 5, 122, 0, 0, - 1239, 1240, 5, 2, 0, 0, 1240, 1241, 3, 186, 93, 0, - 1241, 1242, 5, 7, 0, 0, 1242, 1243, 3, 186, 93, 0, - 1243, 1244, 5, 3, 0, 0, 1244, 1274, 1, 0, 0, 0, - 1245, 1246, 5, 123, 0, 0, 1246, 1247, 5, 2, 0, 0, - 1247, 1248, 3, 186, 93, 0, 1248, 1249, 5, 3, 0, 0, - 1249, 1274, 1, 0, 0, 0, 1250, 1251, 5, 124, 0, 0, - 1251, 1252, 5, 2, 0, 0, 1252, 1253, 3, 186, 93, 0, - 1253, 1254, 5, 3, 0, 0, 1254, 1274, 1, 0, 0, 0, - 1255, 1256, 5, 125, 0, 0, 1256, 1257, 5, 2, 0, 0, - 1257, 1258, 3, 186, 93, 0, 1258, 1259, 5, 3, 0, 0, - 1259, 1274, 1, 0, 0, 0, 1260, 1261, 5, 126, 0, 0, - 1261, 1262, 5, 2, 0, 0, 1262, 1263, 3, 186, 93, 0, - 1263, 1264, 5, 3, 0, 0, 1264, 1274, 1, 0, 0, 0, - 1265, 1266, 5, 127, 0, 0, 1266, 1267, 5, 2, 0, 0, - 1267, 1268, 3, 186, 93, 0, 1268, 1269, 5, 3, 0, 0, - 1269, 1274, 1, 0, 0, 0, 1270, 1274, 3, 224, 112, 0, - 1271, 1274, 3, 232, 116, 0, 1272, 1274, 3, 234, 117, 0, - 1273, 1019, 1, 0, 0, 0, 1273, 1020, 1, 0, 0, 0, - 1273, 1025, 1, 0, 0, 0, 1273, 1026, 1, 0, 0, 0, - 1273, 1033, 1, 0, 0, 0, 1273, 1038, 1, 0, 0, 0, - 1273, 1043, 1, 0, 0, 0, 1273, 1048, 1, 0, 0, 0, - 1273, 1053, 1, 0, 0, 0, 1273, 1061, 1, 0, 0, 0, - 1273, 1063, 1, 0, 0, 0, 1273, 1068, 1, 0, 0, 0, - 1273, 1073, 1, 0, 0, 0, 1273, 1078, 1, 0, 0, 0, - 1273, 1083, 1, 0, 0, 0, 1273, 1085, 1, 0, 0, 0, - 1273, 1086, 1, 0, 0, 0, 1273, 1091, 1, 0, 0, 0, - 1273, 1092, 1, 0, 0, 0, 1273, 1097, 1, 0, 0, 0, - 1273, 1102, 1, 0, 0, 0, 1273, 1107, 1, 0, 0, 0, - 1273, 1114, 1, 0, 0, 0, 1273, 1121, 1, 0, 0, 0, - 1273, 1128, 1, 0, 0, 0, 1273, 1135, 1, 0, 0, 0, - 1273, 1142, 1, 0, 0, 0, 1273, 1147, 1, 0, 0, 0, - 1273, 1152, 1, 0, 0, 0, 1273, 1157, 1, 0, 0, 0, - 1273, 1162, 1, 0, 0, 0, 1273, 1167, 1, 0, 0, 0, - 1273, 1172, 1, 0, 0, 0, 1273, 1177, 1, 0, 0, 0, - 1273, 1182, 1, 0, 0, 0, 1273, 1184, 1, 0, 0, 0, - 1273, 1186, 1, 0, 0, 0, 1273, 1188, 1, 0, 0, 0, - 1273, 1193, 1, 0, 0, 0, 1273, 1198, 1, 0, 0, 0, - 1273, 1203, 1, 0, 0, 0, 1273, 1208, 1, 0, 0, 0, - 1273, 1213, 1, 0, 0, 0, 1273, 1215, 1, 0, 0, 0, - 1273, 1224, 1, 0, 0, 0, 1273, 1231, 1, 0, 0, 0, - 1273, 1238, 1, 0, 0, 0, 1273, 1245, 1, 0, 0, 0, - 1273, 1250, 1, 0, 0, 0, 1273, 1255, 1, 0, 0, 0, - 1273, 1260, 1, 0, 0, 0, 1273, 1265, 1, 0, 0, 0, - 1273, 1270, 1, 0, 0, 0, 1273, 1271, 1, 0, 0, 0, - 1273, 1272, 1, 0, 0, 0, 1274, 223, 1, 0, 0, 0, - 1275, 1276, 5, 128, 0, 0, 1276, 1277, 5, 2, 0, 0, - 1277, 1278, 3, 186, 93, 0, 1278, 1279, 5, 7, 0, 0, - 1279, 1282, 3, 186, 93, 0, 1280, 1281, 5, 7, 0, 0, - 1281, 1283, 3, 186, 93, 0, 1282, 1280, 1, 0, 0, 0, - 1282, 1283, 1, 0, 0, 0, 1283, 1284, 1, 0, 0, 0, - 1284, 1285, 5, 3, 0, 0, 1285, 225, 1, 0, 0, 0, - 1286, 1287, 5, 79, 0, 0, 1287, 1288, 5, 2, 0, 0, - 1288, 1289, 3, 186, 93, 0, 1289, 1290, 5, 3, 0, 0, - 1290, 227, 1, 0, 0, 0, 1291, 1292, 5, 129, 0, 0, - 1292, 1293, 5, 2, 0, 0, 1293, 1294, 3, 186, 93, 0, - 1294, 1295, 5, 7, 0, 0, 1295, 1298, 3, 186, 93, 0, - 1296, 1297, 5, 7, 0, 0, 1297, 1299, 3, 186, 93, 0, - 1298, 1296, 1, 0, 0, 0, 1298, 1299, 1, 0, 0, 0, - 1299, 1300, 1, 0, 0, 0, 1300, 1301, 5, 3, 0, 0, - 1301, 229, 1, 0, 0, 0, 1302, 1303, 5, 130, 0, 0, - 1303, 1304, 5, 2, 0, 0, 1304, 1305, 3, 186, 93, 0, - 1305, 1306, 5, 7, 0, 0, 1306, 1307, 3, 186, 93, 0, - 1307, 1308, 5, 7, 0, 0, 1308, 1311, 3, 186, 93, 0, - 1309, 1310, 5, 7, 0, 0, 1310, 1312, 3, 186, 93, 0, - 1311, 1309, 1, 0, 0, 0, 1311, 1312, 1, 0, 0, 0, - 1312, 1313, 1, 0, 0, 0, 1313, 1314, 5, 3, 0, 0, - 1314, 231, 1, 0, 0, 0, 1315, 1316, 5, 131, 0, 0, - 1316, 1317, 3, 62, 31, 0, 1317, 233, 1, 0, 0, 0, - 1318, 1319, 5, 76, 0, 0, 1319, 1320, 5, 131, 0, 0, - 1320, 1321, 3, 62, 31, 0, 1321, 235, 1, 0, 0, 0, - 1322, 1323, 5, 132, 0, 0, 1323, 1325, 5, 2, 0, 0, - 1324, 1326, 5, 33, 0, 0, 1325, 1324, 1, 0, 0, 0, - 1325, 1326, 1, 0, 0, 0, 1326, 1329, 1, 0, 0, 0, - 1327, 1330, 5, 1, 0, 0, 1328, 1330, 3, 186, 93, 0, - 1329, 1327, 1, 0, 0, 0, 1329, 1328, 1, 0, 0, 0, - 1330, 1331, 1, 0, 0, 0, 1331, 1387, 5, 3, 0, 0, - 1332, 1333, 5, 133, 0, 0, 1333, 1335, 5, 2, 0, 0, - 1334, 1336, 5, 33, 0, 0, 1335, 1334, 1, 0, 0, 0, - 1335, 1336, 1, 0, 0, 0, 1336, 1337, 1, 0, 0, 0, - 1337, 1338, 3, 186, 93, 0, 1338, 1339, 5, 3, 0, 0, - 1339, 1387, 1, 0, 0, 0, 1340, 1341, 5, 134, 0, 0, - 1341, 1343, 5, 2, 0, 0, 1342, 1344, 5, 33, 0, 0, - 1343, 1342, 1, 0, 0, 0, 1343, 1344, 1, 0, 0, 0, - 1344, 1345, 1, 0, 0, 0, 1345, 1346, 3, 186, 93, 0, - 1346, 1347, 5, 3, 0, 0, 1347, 1387, 1, 0, 0, 0, - 1348, 1349, 5, 135, 0, 0, 1349, 1351, 5, 2, 0, 0, - 1350, 1352, 5, 33, 0, 0, 1351, 1350, 1, 0, 0, 0, - 1351, 1352, 1, 0, 0, 0, 1352, 1353, 1, 0, 0, 0, - 1353, 1354, 3, 186, 93, 0, 1354, 1355, 5, 3, 0, 0, - 1355, 1387, 1, 0, 0, 0, 1356, 1357, 5, 136, 0, 0, - 1357, 1359, 5, 2, 0, 0, 1358, 1360, 5, 33, 0, 0, - 1359, 1358, 1, 0, 0, 0, 1359, 1360, 1, 0, 0, 0, - 1360, 1361, 1, 0, 0, 0, 1361, 1362, 3, 186, 93, 0, - 1362, 1363, 5, 3, 0, 0, 1363, 1387, 1, 0, 0, 0, - 1364, 1365, 5, 137, 0, 0, 1365, 1367, 5, 2, 0, 0, - 1366, 1368, 5, 33, 0, 0, 1367, 1366, 1, 0, 0, 0, - 1367, 1368, 1, 0, 0, 0, 1368, 1369, 1, 0, 0, 0, - 1369, 1370, 3, 186, 93, 0, 1370, 1371, 5, 3, 0, 0, - 1371, 1387, 1, 0, 0, 0, 1372, 1373, 5, 43, 0, 0, - 1373, 1375, 5, 2, 0, 0, 1374, 1376, 5, 33, 0, 0, - 1375, 1374, 1, 0, 0, 0, 1375, 1376, 1, 0, 0, 0, - 1376, 1377, 1, 0, 0, 0, 1377, 1382, 3, 186, 93, 0, - 1378, 1379, 5, 8, 0, 0, 1379, 1380, 5, 138, 0, 0, - 1380, 1381, 5, 20, 0, 0, 1381, 1383, 3, 252, 126, 0, - 1382, 1378, 1, 0, 0, 0, 1382, 1383, 1, 0, 0, 0, - 1383, 1384, 1, 0, 0, 0, 1384, 1385, 5, 3, 0, 0, - 1385, 1387, 1, 0, 0, 0, 1386, 1322, 1, 0, 0, 0, - 1386, 1332, 1, 0, 0, 0, 1386, 1340, 1, 0, 0, 0, - 1386, 1348, 1, 0, 0, 0, 1386, 1356, 1, 0, 0, 0, - 1386, 1364, 1, 0, 0, 0, 1386, 1372, 1, 0, 0, 0, - 1387, 237, 1, 0, 0, 0, 1388, 1390, 3, 254, 127, 0, - 1389, 1391, 3, 102, 51, 0, 1390, 1389, 1, 0, 0, 0, - 1390, 1391, 1, 0, 0, 0, 1391, 239, 1, 0, 0, 0, - 1392, 1396, 3, 252, 126, 0, 1393, 1397, 5, 145, 0, 0, - 1394, 1395, 5, 27, 0, 0, 1395, 1397, 3, 254, 127, 0, - 1396, 1393, 1, 0, 0, 0, 1396, 1394, 1, 0, 0, 0, - 1396, 1397, 1, 0, 0, 0, 1397, 241, 1, 0, 0, 0, - 1398, 1402, 3, 244, 122, 0, 1399, 1402, 3, 246, 123, 0, - 1400, 1402, 3, 248, 124, 0, 1401, 1398, 1, 0, 0, 0, - 1401, 1399, 1, 0, 0, 0, 1401, 1400, 1, 0, 0, 0, - 1402, 243, 1, 0, 0, 0, 1403, 1404, 7, 4, 0, 0, - 1404, 245, 1, 0, 0, 0, 1405, 1406, 7, 5, 0, 0, - 1406, 247, 1, 0, 0, 0, 1407, 1408, 7, 6, 0, 0, - 1408, 249, 1, 0, 0, 0, 1409, 1410, 7, 7, 0, 0, - 1410, 251, 1, 0, 0, 0, 1411, 1412, 7, 8, 0, 0, - 1412, 253, 1, 0, 0, 0, 1413, 1415, 5, 146, 0, 0, - 1414, 1413, 1, 0, 0, 0, 1414, 1415, 1, 0, 0, 0, - 1415, 1418, 1, 0, 0, 0, 1416, 1419, 3, 260, 130, 0, - 1417, 1419, 3, 256, 128, 0, 1418, 1416, 1, 0, 0, 0, - 1418, 1417, 1, 0, 0, 0, 1419, 255, 1, 0, 0, 0, - 1420, 1423, 3, 262, 131, 0, 1421, 1423, 3, 264, 132, 0, - 1422, 1420, 1, 0, 0, 0, 1422, 1421, 1, 0, 0, 0, - 1423, 257, 1, 0, 0, 0, 1424, 1425, 7, 9, 0, 0, - 1425, 259, 1, 0, 0, 0, 1426, 1427, 5, 139, 0, 0, - 1427, 261, 1, 0, 0, 0, 1428, 1429, 5, 141, 0, 0, - 1429, 263, 1, 0, 0, 0, 1430, 1431, 5, 140, 0, 0, - 1431, 265, 1, 0, 0, 0, 137, 271, 278, 280, 294, 307, - 312, 315, 319, 334, 343, 349, 353, 359, 362, 367, 371, 379, - 388, 398, 403, 406, 409, 412, 418, 426, 431, 437, 443, 448, - 454, 456, 460, 463, 467, 470, 474, 477, 481, 484, 488, 491, - 495, 498, 500, 513, 518, 520, 525, 530, 535, 540, 543, 548, - 550, 560, 571, 588, 595, 605, 609, 615, 624, 629, 636, 646, - 655, 663, 670, 675, 684, 689, 693, 700, 702, 710, 713, 721, - 725, 730, 737, 748, 751, 756, 760, 775, 782, 794, 802, 807, - 812, 824, 833, 836, 839, 846, 848, 854, 862, 872, 880, 886, - 890, 894, 898, 908, 917, 925, 948, 956, 964, 972, 977, 984, - 989, 1004, 1013, 1059, 1273, 1282, 1298, 1311, 1325, 1329, 1335, 1343, - 1351, 1359, 1367, 1375, 1382, 1386, 1390, 1396, 1401, 1414, 1418, 1422}; + 2, 131, 7, 131, 2, 132, 7, 132, 2, 133, 7, 133, + 2, 134, 7, 134, 2, 135, 7, 135, 2, 136, 7, 136, + 2, 137, 7, 137, 2, 138, 7, 138, 2, 139, 7, 139, + 2, 140, 7, 140, 2, 141, 7, 141, 2, 142, 7, 142, + 2, 143, 7, 143, 2, 144, 7, 144, 2, 145, 7, 145, + 2, 146, 7, 146, 2, 147, 7, 147, 2, 148, 7, 148, + 2, 149, 7, 149, 2, 150, 7, 150, 2, 151, 7, 151, + 2, 152, 7, 152, 2, 153, 7, 153, 2, 154, 7, 154, + 2, 155, 7, 155, 2, 156, 7, 156, 1, 0, 1, 0, + 1, 0, 1, 0, 3, 0, 319, 8, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 3, 1, 326, 8, 1, + 1, 1, 1, 1, 1, 2, 1, 2, 5, 2, 332, 8, + 2, 10, 2, 12, 2, 335, 9, 2, 1, 3, 1, 3, + 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, + 1, 5, 5, 5, 346, 8, 5, 10, 5, 12, 5, 349, + 9, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, + 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 3, 7, + 361, 8, 7, 1, 7, 4, 7, 364, 8, 7, 11, 7, + 12, 7, 365, 1, 7, 3, 7, 369, 8, 7, 1, 8, + 1, 8, 3, 8, 373, 8, 8, 1, 9, 1, 9, 1, + 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, + 11, 1, 11, 1, 11, 5, 11, 386, 8, 11, 10, 11, + 12, 11, 389, 9, 11, 1, 11, 1, 11, 1, 11, 1, + 11, 5, 11, 395, 8, 11, 10, 11, 12, 11, 398, 9, + 11, 1, 11, 1, 11, 1, 11, 3, 11, 403, 8, 11, + 1, 11, 1, 11, 3, 11, 407, 8, 11, 1, 12, 1, + 12, 4, 12, 411, 8, 12, 11, 12, 12, 12, 412, 1, + 12, 3, 12, 416, 8, 12, 1, 12, 5, 12, 419, 8, + 12, 10, 12, 12, 12, 422, 9, 12, 1, 12, 3, 12, + 425, 8, 12, 1, 12, 1, 12, 1, 13, 1, 13, 5, + 13, 431, 8, 13, 10, 13, 12, 13, 434, 9, 13, 1, + 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 3, + 14, 442, 8, 14, 1, 15, 1, 15, 1, 16, 1, 16, + 1, 16, 1, 17, 1, 17, 1, 18, 3, 18, 452, 8, + 18, 1, 18, 1, 18, 1, 19, 3, 19, 457, 8, 19, + 1, 19, 3, 19, 460, 8, 19, 1, 19, 3, 19, 463, + 8, 19, 1, 19, 3, 19, 466, 8, 19, 1, 20, 1, + 20, 4, 20, 470, 8, 20, 11, 20, 12, 20, 471, 1, + 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 3, + 21, 480, 8, 21, 1, 21, 1, 21, 1, 21, 3, 21, + 485, 8, 21, 1, 22, 1, 22, 4, 22, 489, 8, 22, + 11, 22, 12, 22, 490, 1, 23, 1, 23, 1, 24, 1, + 24, 3, 24, 497, 8, 24, 1, 24, 4, 24, 500, 8, + 24, 11, 24, 12, 24, 501, 1, 25, 1, 25, 1, 25, + 1, 25, 3, 25, 508, 8, 25, 3, 25, 510, 8, 25, + 1, 26, 1, 26, 3, 26, 514, 8, 26, 1, 26, 3, + 26, 517, 8, 26, 1, 26, 1, 26, 3, 26, 521, 8, + 26, 1, 26, 3, 26, 524, 8, 26, 1, 26, 1, 26, + 3, 26, 528, 8, 26, 1, 26, 3, 26, 531, 8, 26, + 1, 26, 1, 26, 3, 26, 535, 8, 26, 1, 26, 3, + 26, 538, 8, 26, 1, 26, 1, 26, 3, 26, 542, 8, + 26, 1, 26, 3, 26, 545, 8, 26, 1, 26, 1, 26, + 3, 26, 549, 8, 26, 1, 26, 3, 26, 552, 8, 26, + 3, 26, 554, 8, 26, 1, 27, 1, 27, 1, 27, 1, + 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, + 30, 1, 30, 3, 30, 567, 8, 30, 1, 31, 1, 31, + 1, 31, 1, 31, 3, 31, 573, 8, 31, 3, 31, 575, + 8, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, + 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, + 3, 32, 588, 8, 32, 1, 33, 1, 33, 3, 33, 592, + 8, 33, 1, 33, 1, 33, 1, 33, 3, 33, 597, 8, + 33, 1, 34, 1, 34, 3, 34, 601, 8, 34, 1, 34, + 1, 34, 1, 35, 1, 35, 3, 35, 607, 8, 35, 1, + 35, 1, 35, 1, 36, 1, 36, 3, 36, 613, 8, 36, + 1, 36, 1, 36, 1, 37, 1, 37, 3, 37, 619, 8, + 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, + 38, 3, 38, 627, 8, 38, 1, 38, 1, 38, 1, 38, + 1, 38, 1, 39, 1, 39, 3, 39, 635, 8, 39, 1, + 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, + 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, + 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 3, + 43, 655, 8, 43, 1, 43, 1, 43, 3, 43, 659, 8, + 43, 1, 43, 3, 43, 662, 8, 43, 1, 43, 5, 43, + 665, 8, 43, 10, 43, 12, 43, 668, 9, 43, 1, 43, + 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 45, + 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, + 3, 46, 683, 8, 46, 1, 47, 1, 47, 1, 47, 3, + 47, 688, 8, 47, 1, 48, 1, 48, 1, 48, 1, 49, + 1, 49, 1, 49, 1, 49, 3, 49, 697, 8, 49, 1, + 50, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, + 51, 1, 51, 1, 52, 3, 52, 708, 8, 52, 1, 52, + 1, 52, 3, 52, 712, 8, 52, 1, 52, 3, 52, 715, + 8, 52, 5, 52, 717, 8, 52, 10, 52, 12, 52, 720, + 9, 52, 1, 53, 1, 53, 1, 53, 1, 53, 3, 53, + 726, 8, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, + 54, 3, 54, 733, 8, 54, 3, 54, 735, 8, 54, 1, + 55, 1, 55, 1, 55, 3, 55, 740, 8, 55, 1, 55, + 1, 55, 1, 56, 3, 56, 745, 8, 56, 1, 56, 5, + 56, 748, 8, 56, 10, 56, 12, 56, 751, 9, 56, 1, + 57, 1, 57, 3, 57, 755, 8, 57, 1, 57, 3, 57, + 758, 8, 57, 1, 58, 1, 58, 1, 58, 3, 58, 763, + 8, 58, 3, 58, 765, 8, 58, 1, 59, 1, 59, 1, + 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 3, + 59, 775, 8, 59, 1, 60, 1, 60, 1, 60, 1, 61, + 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 3, 62, + 786, 8, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, + 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, + 64, 1, 64, 1, 64, 1, 65, 1, 65, 3, 65, 803, + 8, 65, 1, 66, 1, 66, 1, 66, 5, 66, 808, 8, + 66, 10, 66, 12, 66, 811, 9, 66, 1, 66, 1, 66, + 1, 67, 1, 67, 1, 67, 5, 67, 818, 8, 67, 10, + 67, 12, 67, 821, 9, 67, 1, 67, 3, 67, 824, 8, + 67, 1, 67, 1, 67, 5, 67, 828, 8, 67, 10, 67, + 12, 67, 831, 9, 67, 1, 67, 1, 67, 1, 68, 1, + 68, 5, 68, 837, 8, 68, 10, 68, 12, 68, 840, 9, + 68, 1, 68, 1, 68, 3, 68, 844, 8, 68, 1, 69, + 1, 69, 1, 69, 1, 69, 1, 69, 3, 69, 851, 8, + 69, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, + 71, 5, 71, 859, 8, 71, 10, 71, 12, 71, 862, 9, + 71, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, + 73, 3, 73, 870, 8, 73, 1, 74, 1, 74, 1, 74, + 1, 75, 1, 75, 1, 75, 3, 75, 878, 8, 75, 1, + 75, 1, 75, 1, 75, 5, 75, 883, 8, 75, 10, 75, + 12, 75, 886, 9, 75, 1, 75, 1, 75, 3, 75, 890, + 8, 75, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, + 5, 76, 897, 8, 76, 10, 76, 12, 76, 900, 9, 76, + 1, 76, 1, 76, 3, 76, 904, 8, 76, 1, 77, 1, + 77, 3, 77, 908, 8, 77, 1, 77, 1, 77, 1, 78, + 1, 78, 1, 78, 3, 78, 915, 8, 78, 3, 78, 917, + 8, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, + 1, 79, 3, 79, 925, 8, 79, 1, 80, 3, 80, 928, + 8, 80, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, + 1, 81, 3, 81, 936, 8, 81, 5, 81, 938, 8, 81, + 10, 81, 12, 81, 941, 9, 81, 1, 82, 1, 82, 3, + 82, 945, 8, 82, 1, 83, 1, 83, 1, 83, 5, 83, + 950, 8, 83, 10, 83, 12, 83, 953, 9, 83, 1, 84, + 1, 84, 1, 85, 1, 85, 1, 85, 1, 85, 1, 85, + 1, 85, 3, 85, 963, 8, 85, 1, 86, 3, 86, 966, + 8, 86, 1, 87, 1, 87, 1, 87, 3, 87, 971, 8, + 87, 5, 87, 973, 8, 87, 10, 87, 12, 87, 976, 9, + 87, 1, 88, 1, 88, 1, 89, 1, 89, 1, 90, 1, + 90, 1, 90, 1, 91, 1, 91, 1, 91, 1, 92, 1, + 92, 3, 92, 990, 8, 92, 1, 93, 1, 93, 1, 93, + 5, 93, 995, 8, 93, 10, 93, 12, 93, 998, 9, 93, + 1, 94, 1, 94, 1, 95, 1, 95, 1, 96, 1, 96, + 1, 96, 5, 96, 1007, 8, 96, 10, 96, 12, 96, 1010, + 9, 96, 1, 97, 1, 97, 1, 97, 5, 97, 1015, 8, + 97, 10, 97, 12, 97, 1018, 9, 97, 1, 98, 1, 98, + 3, 98, 1022, 8, 98, 1, 99, 1, 99, 1, 99, 3, + 99, 1027, 8, 99, 1, 100, 1, 100, 1, 101, 1, 101, + 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, + 3, 101, 1039, 8, 101, 1, 102, 1, 102, 1, 102, 1, + 102, 1, 102, 5, 102, 1046, 8, 102, 10, 102, 12, 102, + 1049, 9, 102, 3, 102, 1051, 8, 102, 1, 102, 3, 102, + 1054, 8, 102, 1, 103, 1, 103, 1, 103, 1, 103, 1, + 103, 3, 103, 1061, 8, 103, 3, 103, 1063, 8, 103, 1, + 104, 1, 104, 1, 105, 1, 105, 3, 105, 1069, 8, 105, + 1, 106, 1, 106, 1, 106, 1, 106, 1, 107, 1, 107, + 3, 107, 1077, 8, 107, 1, 108, 1, 108, 1, 108, 1, + 108, 1, 109, 1, 109, 4, 109, 1085, 8, 109, 11, 109, + 12, 109, 1086, 1, 109, 1, 109, 1, 110, 1, 110, 4, + 110, 1093, 8, 110, 11, 110, 12, 110, 1094, 1, 110, 1, + 110, 1, 111, 1, 111, 3, 111, 1101, 8, 111, 1, 112, + 1, 112, 3, 112, 1105, 8, 112, 1, 113, 1, 113, 3, + 113, 1109, 8, 113, 1, 114, 1, 114, 3, 114, 1113, 8, + 114, 1, 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, + 116, 1, 116, 1, 116, 3, 116, 1123, 8, 116, 1, 117, + 1, 117, 1, 118, 1, 118, 1, 118, 5, 118, 1130, 8, + 118, 10, 118, 12, 118, 1133, 9, 118, 1, 119, 1, 119, + 1, 119, 5, 119, 1138, 8, 119, 10, 119, 12, 119, 1141, + 9, 119, 1, 120, 1, 120, 1, 121, 1, 121, 1, 121, + 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, + 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, + 1, 121, 1, 121, 1, 121, 3, 121, 1163, 8, 121, 1, + 122, 1, 122, 1, 123, 1, 123, 5, 123, 1169, 8, 123, + 10, 123, 12, 123, 1172, 9, 123, 1, 124, 1, 124, 1, + 124, 1, 124, 1, 124, 3, 124, 1179, 8, 124, 1, 125, + 1, 125, 1, 126, 1, 126, 1, 127, 1, 127, 3, 127, + 1187, 8, 127, 1, 127, 5, 127, 1190, 8, 127, 10, 127, + 12, 127, 1193, 9, 127, 1, 128, 1, 128, 5, 128, 1197, + 8, 128, 10, 128, 12, 128, 1200, 9, 128, 1, 129, 1, + 129, 3, 129, 1204, 8, 129, 1, 130, 1, 130, 1, 130, + 1, 131, 1, 131, 1, 131, 1, 132, 1, 132, 1, 132, + 1, 132, 1, 132, 1, 132, 1, 132, 3, 132, 1219, 8, + 132, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, + 133, 1, 133, 3, 133, 1228, 8, 133, 1, 134, 1, 134, + 1, 134, 1, 134, 1, 135, 1, 135, 1, 135, 1, 135, + 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, + 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, + 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, + 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, + 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, + 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, + 3, 135, 1274, 8, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, + 135, 1, 135, 1, 135, 1, 135, 1, 135, 3, 135, 1488, + 8, 135, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, + 1, 136, 1, 136, 3, 136, 1497, 8, 136, 1, 136, 1, + 136, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, + 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, + 138, 3, 138, 1513, 8, 138, 1, 138, 1, 138, 1, 139, + 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, + 1, 139, 1, 139, 3, 139, 1526, 8, 139, 1, 139, 1, + 139, 1, 140, 1, 140, 1, 140, 1, 141, 1, 141, 1, + 141, 1, 141, 1, 142, 1, 142, 1, 142, 3, 142, 1540, + 8, 142, 1, 142, 1, 142, 3, 142, 1544, 8, 142, 1, + 142, 1, 142, 1, 142, 1, 142, 3, 142, 1550, 8, 142, + 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, + 3, 142, 1558, 8, 142, 1, 142, 1, 142, 1, 142, 1, + 142, 1, 142, 1, 142, 3, 142, 1566, 8, 142, 1, 142, + 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 3, 142, + 1574, 8, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, + 142, 1, 142, 3, 142, 1582, 8, 142, 1, 142, 1, 142, + 1, 142, 1, 142, 1, 142, 1, 142, 3, 142, 1590, 8, + 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 3, + 142, 1597, 8, 142, 1, 142, 1, 142, 3, 142, 1601, 8, + 142, 1, 143, 1, 143, 3, 143, 1605, 8, 143, 1, 144, + 1, 144, 1, 144, 1, 144, 3, 144, 1611, 8, 144, 1, + 145, 1, 145, 1, 145, 3, 145, 1616, 8, 145, 1, 146, + 1, 146, 1, 147, 1, 147, 1, 148, 1, 148, 1, 149, + 1, 149, 1, 150, 1, 150, 1, 151, 3, 151, 1629, 8, + 151, 1, 151, 1, 151, 3, 151, 1633, 8, 151, 1, 152, + 1, 152, 3, 152, 1637, 8, 152, 1, 153, 1, 153, 1, + 154, 1, 154, 1, 155, 1, 155, 1, 156, 1, 156, 1, + 156, 0, 0, 157, 0, 2, 4, 6, 8, 10, 12, 14, + 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, + 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, + 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, + 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, + 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, + 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, + 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, + 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, + 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, + 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, + 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, + 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, + 304, 306, 308, 310, 312, 0, 10, 1, 0, 33, 34, 1, + 0, 47, 48, 2, 0, 1, 1, 13, 14, 1, 0, 145, + 146, 1, 0, 149, 151, 1, 0, 152, 154, 1, 0, 155, + 157, 1, 0, 28, 29, 1, 0, 159, 162, 2, 0, 144, + 144, 165, 165, 1761, 0, 318, 1, 0, 0, 0, 2, 320, + 1, 0, 0, 0, 4, 333, 1, 0, 0, 0, 6, 336, + 1, 0, 0, 0, 8, 339, 1, 0, 0, 0, 10, 343, + 1, 0, 0, 0, 12, 353, 1, 0, 0, 0, 14, 358, + 1, 0, 0, 0, 16, 372, 1, 0, 0, 0, 18, 374, + 1, 0, 0, 0, 20, 378, 1, 0, 0, 0, 22, 382, + 1, 0, 0, 0, 24, 408, 1, 0, 0, 0, 26, 428, + 1, 0, 0, 0, 28, 438, 1, 0, 0, 0, 30, 443, + 1, 0, 0, 0, 32, 445, 1, 0, 0, 0, 34, 448, + 1, 0, 0, 0, 36, 451, 1, 0, 0, 0, 38, 456, + 1, 0, 0, 0, 40, 467, 1, 0, 0, 0, 42, 484, + 1, 0, 0, 0, 44, 486, 1, 0, 0, 0, 46, 492, + 1, 0, 0, 0, 48, 496, 1, 0, 0, 0, 50, 509, + 1, 0, 0, 0, 52, 553, 1, 0, 0, 0, 54, 555, + 1, 0, 0, 0, 56, 558, 1, 0, 0, 0, 58, 561, + 1, 0, 0, 0, 60, 566, 1, 0, 0, 0, 62, 568, + 1, 0, 0, 0, 64, 587, 1, 0, 0, 0, 66, 589, + 1, 0, 0, 0, 68, 598, 1, 0, 0, 0, 70, 604, + 1, 0, 0, 0, 72, 610, 1, 0, 0, 0, 74, 616, + 1, 0, 0, 0, 76, 624, 1, 0, 0, 0, 78, 632, + 1, 0, 0, 0, 80, 640, 1, 0, 0, 0, 82, 644, + 1, 0, 0, 0, 84, 648, 1, 0, 0, 0, 86, 654, + 1, 0, 0, 0, 88, 672, 1, 0, 0, 0, 90, 675, + 1, 0, 0, 0, 92, 678, 1, 0, 0, 0, 94, 687, + 1, 0, 0, 0, 96, 689, 1, 0, 0, 0, 98, 696, + 1, 0, 0, 0, 100, 698, 1, 0, 0, 0, 102, 702, + 1, 0, 0, 0, 104, 707, 1, 0, 0, 0, 106, 721, + 1, 0, 0, 0, 108, 729, 1, 0, 0, 0, 110, 736, + 1, 0, 0, 0, 112, 744, 1, 0, 0, 0, 114, 752, + 1, 0, 0, 0, 116, 759, 1, 0, 0, 0, 118, 774, + 1, 0, 0, 0, 120, 776, 1, 0, 0, 0, 122, 779, + 1, 0, 0, 0, 124, 783, 1, 0, 0, 0, 126, 790, + 1, 0, 0, 0, 128, 797, 1, 0, 0, 0, 130, 802, + 1, 0, 0, 0, 132, 804, 1, 0, 0, 0, 134, 823, + 1, 0, 0, 0, 136, 843, 1, 0, 0, 0, 138, 850, + 1, 0, 0, 0, 140, 852, 1, 0, 0, 0, 142, 855, + 1, 0, 0, 0, 144, 863, 1, 0, 0, 0, 146, 869, + 1, 0, 0, 0, 148, 871, 1, 0, 0, 0, 150, 889, + 1, 0, 0, 0, 152, 903, 1, 0, 0, 0, 154, 905, + 1, 0, 0, 0, 156, 911, 1, 0, 0, 0, 158, 924, + 1, 0, 0, 0, 160, 927, 1, 0, 0, 0, 162, 929, + 1, 0, 0, 0, 164, 944, 1, 0, 0, 0, 166, 946, + 1, 0, 0, 0, 168, 954, 1, 0, 0, 0, 170, 962, + 1, 0, 0, 0, 172, 965, 1, 0, 0, 0, 174, 967, + 1, 0, 0, 0, 176, 977, 1, 0, 0, 0, 178, 979, + 1, 0, 0, 0, 180, 981, 1, 0, 0, 0, 182, 984, + 1, 0, 0, 0, 184, 989, 1, 0, 0, 0, 186, 991, + 1, 0, 0, 0, 188, 999, 1, 0, 0, 0, 190, 1001, + 1, 0, 0, 0, 192, 1003, 1, 0, 0, 0, 194, 1011, + 1, 0, 0, 0, 196, 1019, 1, 0, 0, 0, 198, 1026, + 1, 0, 0, 0, 200, 1028, 1, 0, 0, 0, 202, 1038, + 1, 0, 0, 0, 204, 1053, 1, 0, 0, 0, 206, 1062, + 1, 0, 0, 0, 208, 1064, 1, 0, 0, 0, 210, 1068, + 1, 0, 0, 0, 212, 1070, 1, 0, 0, 0, 214, 1076, + 1, 0, 0, 0, 216, 1078, 1, 0, 0, 0, 218, 1082, + 1, 0, 0, 0, 220, 1090, 1, 0, 0, 0, 222, 1100, + 1, 0, 0, 0, 224, 1104, 1, 0, 0, 0, 226, 1108, + 1, 0, 0, 0, 228, 1112, 1, 0, 0, 0, 230, 1114, + 1, 0, 0, 0, 232, 1122, 1, 0, 0, 0, 234, 1124, + 1, 0, 0, 0, 236, 1126, 1, 0, 0, 0, 238, 1134, + 1, 0, 0, 0, 240, 1142, 1, 0, 0, 0, 242, 1144, + 1, 0, 0, 0, 244, 1164, 1, 0, 0, 0, 246, 1166, + 1, 0, 0, 0, 248, 1178, 1, 0, 0, 0, 250, 1180, + 1, 0, 0, 0, 252, 1182, 1, 0, 0, 0, 254, 1186, + 1, 0, 0, 0, 256, 1194, 1, 0, 0, 0, 258, 1203, + 1, 0, 0, 0, 260, 1205, 1, 0, 0, 0, 262, 1208, + 1, 0, 0, 0, 264, 1218, 1, 0, 0, 0, 266, 1227, + 1, 0, 0, 0, 268, 1229, 1, 0, 0, 0, 270, 1487, + 1, 0, 0, 0, 272, 1489, 1, 0, 0, 0, 274, 1500, + 1, 0, 0, 0, 276, 1505, 1, 0, 0, 0, 278, 1516, + 1, 0, 0, 0, 280, 1529, 1, 0, 0, 0, 282, 1532, + 1, 0, 0, 0, 284, 1600, 1, 0, 0, 0, 286, 1602, + 1, 0, 0, 0, 288, 1606, 1, 0, 0, 0, 290, 1615, + 1, 0, 0, 0, 292, 1617, 1, 0, 0, 0, 294, 1619, + 1, 0, 0, 0, 296, 1621, 1, 0, 0, 0, 298, 1623, + 1, 0, 0, 0, 300, 1625, 1, 0, 0, 0, 302, 1628, + 1, 0, 0, 0, 304, 1636, 1, 0, 0, 0, 306, 1638, + 1, 0, 0, 0, 308, 1640, 1, 0, 0, 0, 310, 1642, + 1, 0, 0, 0, 312, 1644, 1, 0, 0, 0, 314, 319, + 3, 2, 1, 0, 315, 316, 3, 62, 31, 0, 316, 317, + 5, 0, 0, 1, 317, 319, 1, 0, 0, 0, 318, 314, + 1, 0, 0, 0, 318, 315, 1, 0, 0, 0, 319, 1, + 1, 0, 0, 0, 320, 325, 3, 4, 2, 0, 321, 326, + 3, 10, 5, 0, 322, 326, 3, 22, 11, 0, 323, 326, + 3, 24, 12, 0, 324, 326, 3, 26, 13, 0, 325, 321, + 1, 0, 0, 0, 325, 322, 1, 0, 0, 0, 325, 323, + 1, 0, 0, 0, 325, 324, 1, 0, 0, 0, 326, 327, + 1, 0, 0, 0, 327, 328, 3, 60, 30, 0, 328, 3, + 1, 0, 0, 0, 329, 332, 3, 6, 3, 0, 330, 332, + 3, 8, 4, 0, 331, 329, 1, 0, 0, 0, 331, 330, + 1, 0, 0, 0, 332, 335, 1, 0, 0, 0, 333, 331, + 1, 0, 0, 0, 333, 334, 1, 0, 0, 0, 334, 5, + 1, 0, 0, 0, 335, 333, 1, 0, 0, 0, 336, 337, + 5, 30, 0, 0, 337, 338, 3, 308, 154, 0, 338, 7, + 1, 0, 0, 0, 339, 340, 5, 31, 0, 0, 340, 341, + 5, 142, 0, 0, 341, 342, 3, 308, 154, 0, 342, 9, + 1, 0, 0, 0, 343, 347, 3, 14, 7, 0, 344, 346, + 3, 28, 14, 0, 345, 344, 1, 0, 0, 0, 346, 349, + 1, 0, 0, 0, 347, 345, 1, 0, 0, 0, 347, 348, + 1, 0, 0, 0, 348, 350, 1, 0, 0, 0, 349, 347, + 1, 0, 0, 0, 350, 351, 3, 36, 18, 0, 351, 352, + 3, 38, 19, 0, 352, 11, 1, 0, 0, 0, 353, 354, + 3, 14, 7, 0, 354, 355, 3, 36, 18, 0, 355, 356, + 3, 38, 19, 0, 356, 357, 3, 60, 30, 0, 357, 13, + 1, 0, 0, 0, 358, 360, 5, 32, 0, 0, 359, 361, + 7, 0, 0, 0, 360, 359, 1, 0, 0, 0, 360, 361, + 1, 0, 0, 0, 361, 368, 1, 0, 0, 0, 362, 364, + 3, 16, 8, 0, 363, 362, 1, 0, 0, 0, 364, 365, + 1, 0, 0, 0, 365, 363, 1, 0, 0, 0, 365, 366, + 1, 0, 0, 0, 366, 369, 1, 0, 0, 0, 367, 369, + 5, 1, 0, 0, 368, 363, 1, 0, 0, 0, 368, 367, + 1, 0, 0, 0, 369, 15, 1, 0, 0, 0, 370, 373, + 3, 230, 115, 0, 371, 373, 3, 18, 9, 0, 372, 370, + 1, 0, 0, 0, 372, 371, 1, 0, 0, 0, 373, 17, + 1, 0, 0, 0, 374, 375, 5, 2, 0, 0, 375, 376, + 3, 20, 10, 0, 376, 377, 5, 3, 0, 0, 377, 19, + 1, 0, 0, 0, 378, 379, 3, 234, 117, 0, 379, 380, + 5, 35, 0, 0, 380, 381, 3, 230, 115, 0, 381, 21, + 1, 0, 0, 0, 382, 406, 5, 36, 0, 0, 383, 387, + 3, 154, 77, 0, 384, 386, 3, 28, 14, 0, 385, 384, + 1, 0, 0, 0, 386, 389, 1, 0, 0, 0, 387, 385, + 1, 0, 0, 0, 387, 388, 1, 0, 0, 0, 388, 390, + 1, 0, 0, 0, 389, 387, 1, 0, 0, 0, 390, 391, + 3, 36, 18, 0, 391, 392, 3, 38, 19, 0, 392, 407, + 1, 0, 0, 0, 393, 395, 3, 28, 14, 0, 394, 393, + 1, 0, 0, 0, 395, 398, 1, 0, 0, 0, 396, 394, + 1, 0, 0, 0, 396, 397, 1, 0, 0, 0, 397, 399, + 1, 0, 0, 0, 398, 396, 1, 0, 0, 0, 399, 400, + 5, 37, 0, 0, 400, 402, 5, 4, 0, 0, 401, 403, + 3, 108, 54, 0, 402, 401, 1, 0, 0, 0, 402, 403, + 1, 0, 0, 0, 403, 404, 1, 0, 0, 0, 404, 405, + 5, 5, 0, 0, 405, 407, 3, 38, 19, 0, 406, 383, + 1, 0, 0, 0, 406, 396, 1, 0, 0, 0, 407, 23, + 1, 0, 0, 0, 408, 415, 5, 38, 0, 0, 409, 411, + 3, 228, 114, 0, 410, 409, 1, 0, 0, 0, 411, 412, + 1, 0, 0, 0, 412, 410, 1, 0, 0, 0, 412, 413, + 1, 0, 0, 0, 413, 416, 1, 0, 0, 0, 414, 416, + 5, 1, 0, 0, 415, 410, 1, 0, 0, 0, 415, 414, + 1, 0, 0, 0, 416, 420, 1, 0, 0, 0, 417, 419, + 3, 28, 14, 0, 418, 417, 1, 0, 0, 0, 419, 422, + 1, 0, 0, 0, 420, 418, 1, 0, 0, 0, 420, 421, + 1, 0, 0, 0, 421, 424, 1, 0, 0, 0, 422, 420, + 1, 0, 0, 0, 423, 425, 3, 36, 18, 0, 424, 423, + 1, 0, 0, 0, 424, 425, 1, 0, 0, 0, 425, 426, + 1, 0, 0, 0, 426, 427, 3, 38, 19, 0, 427, 25, + 1, 0, 0, 0, 428, 432, 5, 39, 0, 0, 429, 431, + 3, 28, 14, 0, 430, 429, 1, 0, 0, 0, 431, 434, + 1, 0, 0, 0, 432, 430, 1, 0, 0, 0, 432, 433, + 1, 0, 0, 0, 433, 435, 1, 0, 0, 0, 434, 432, + 1, 0, 0, 0, 435, 436, 3, 36, 18, 0, 436, 437, + 3, 38, 19, 0, 437, 27, 1, 0, 0, 0, 438, 441, + 5, 40, 0, 0, 439, 442, 3, 30, 15, 0, 440, 442, + 3, 32, 16, 0, 441, 439, 1, 0, 0, 0, 441, 440, + 1, 0, 0, 0, 442, 29, 1, 0, 0, 0, 443, 444, + 3, 34, 17, 0, 444, 31, 1, 0, 0, 0, 445, 446, + 5, 41, 0, 0, 446, 447, 3, 34, 17, 0, 447, 33, + 1, 0, 0, 0, 448, 449, 3, 302, 151, 0, 449, 35, + 1, 0, 0, 0, 450, 452, 5, 37, 0, 0, 451, 450, + 1, 0, 0, 0, 451, 452, 1, 0, 0, 0, 452, 453, + 1, 0, 0, 0, 453, 454, 3, 110, 55, 0, 454, 37, + 1, 0, 0, 0, 455, 457, 3, 40, 20, 0, 456, 455, + 1, 0, 0, 0, 456, 457, 1, 0, 0, 0, 457, 459, + 1, 0, 0, 0, 458, 460, 3, 44, 22, 0, 459, 458, + 1, 0, 0, 0, 459, 460, 1, 0, 0, 0, 460, 462, + 1, 0, 0, 0, 461, 463, 3, 48, 24, 0, 462, 461, + 1, 0, 0, 0, 462, 463, 1, 0, 0, 0, 463, 465, + 1, 0, 0, 0, 464, 466, 3, 52, 26, 0, 465, 464, + 1, 0, 0, 0, 465, 466, 1, 0, 0, 0, 466, 39, + 1, 0, 0, 0, 467, 469, 5, 42, 0, 0, 468, 470, + 3, 42, 21, 0, 469, 468, 1, 0, 0, 0, 470, 471, + 1, 0, 0, 0, 471, 469, 1, 0, 0, 0, 471, 472, + 1, 0, 0, 0, 472, 41, 1, 0, 0, 0, 473, 485, + 3, 270, 135, 0, 474, 485, 3, 148, 74, 0, 475, 476, + 5, 2, 0, 0, 476, 479, 3, 234, 117, 0, 477, 478, + 5, 35, 0, 0, 478, 480, 3, 230, 115, 0, 479, 477, + 1, 0, 0, 0, 479, 480, 1, 0, 0, 0, 480, 481, + 1, 0, 0, 0, 481, 482, 5, 3, 0, 0, 482, 485, + 1, 0, 0, 0, 483, 485, 3, 230, 115, 0, 484, 473, + 1, 0, 0, 0, 484, 474, 1, 0, 0, 0, 484, 475, + 1, 0, 0, 0, 484, 483, 1, 0, 0, 0, 485, 43, + 1, 0, 0, 0, 486, 488, 5, 44, 0, 0, 487, 489, + 3, 46, 23, 0, 488, 487, 1, 0, 0, 0, 489, 490, + 1, 0, 0, 0, 490, 488, 1, 0, 0, 0, 490, 491, + 1, 0, 0, 0, 491, 45, 1, 0, 0, 0, 492, 493, + 3, 146, 73, 0, 493, 47, 1, 0, 0, 0, 494, 497, + 5, 45, 0, 0, 495, 497, 5, 46, 0, 0, 496, 494, + 1, 0, 0, 0, 496, 495, 1, 0, 0, 0, 497, 499, + 1, 0, 0, 0, 498, 500, 3, 50, 25, 0, 499, 498, + 1, 0, 0, 0, 500, 501, 1, 0, 0, 0, 501, 499, + 1, 0, 0, 0, 501, 502, 1, 0, 0, 0, 502, 49, + 1, 0, 0, 0, 503, 504, 7, 1, 0, 0, 504, 510, + 3, 268, 134, 0, 505, 508, 3, 146, 73, 0, 506, 508, + 3, 230, 115, 0, 507, 505, 1, 0, 0, 0, 507, 506, + 1, 0, 0, 0, 508, 510, 1, 0, 0, 0, 509, 503, + 1, 0, 0, 0, 509, 507, 1, 0, 0, 0, 510, 51, + 1, 0, 0, 0, 511, 513, 3, 54, 27, 0, 512, 514, + 3, 56, 28, 0, 513, 512, 1, 0, 0, 0, 513, 514, + 1, 0, 0, 0, 514, 516, 1, 0, 0, 0, 515, 517, + 3, 58, 29, 0, 516, 515, 1, 0, 0, 0, 516, 517, + 1, 0, 0, 0, 517, 554, 1, 0, 0, 0, 518, 520, + 3, 54, 27, 0, 519, 521, 3, 58, 29, 0, 520, 519, + 1, 0, 0, 0, 520, 521, 1, 0, 0, 0, 521, 523, + 1, 0, 0, 0, 522, 524, 3, 56, 28, 0, 523, 522, + 1, 0, 0, 0, 523, 524, 1, 0, 0, 0, 524, 554, + 1, 0, 0, 0, 525, 527, 3, 56, 28, 0, 526, 528, + 3, 54, 27, 0, 527, 526, 1, 0, 0, 0, 527, 528, + 1, 0, 0, 0, 528, 530, 1, 0, 0, 0, 529, 531, + 3, 58, 29, 0, 530, 529, 1, 0, 0, 0, 530, 531, + 1, 0, 0, 0, 531, 554, 1, 0, 0, 0, 532, 534, + 3, 56, 28, 0, 533, 535, 3, 58, 29, 0, 534, 533, + 1, 0, 0, 0, 534, 535, 1, 0, 0, 0, 535, 537, + 1, 0, 0, 0, 536, 538, 3, 54, 27, 0, 537, 536, + 1, 0, 0, 0, 537, 538, 1, 0, 0, 0, 538, 554, + 1, 0, 0, 0, 539, 541, 3, 58, 29, 0, 540, 542, + 3, 56, 28, 0, 541, 540, 1, 0, 0, 0, 541, 542, + 1, 0, 0, 0, 542, 544, 1, 0, 0, 0, 543, 545, + 3, 54, 27, 0, 544, 543, 1, 0, 0, 0, 544, 545, + 1, 0, 0, 0, 545, 554, 1, 0, 0, 0, 546, 548, + 3, 58, 29, 0, 547, 549, 3, 54, 27, 0, 548, 547, + 1, 0, 0, 0, 548, 549, 1, 0, 0, 0, 549, 551, + 1, 0, 0, 0, 550, 552, 3, 56, 28, 0, 551, 550, + 1, 0, 0, 0, 551, 552, 1, 0, 0, 0, 552, 554, + 1, 0, 0, 0, 553, 511, 1, 0, 0, 0, 553, 518, + 1, 0, 0, 0, 553, 525, 1, 0, 0, 0, 553, 532, + 1, 0, 0, 0, 553, 539, 1, 0, 0, 0, 553, 546, + 1, 0, 0, 0, 554, 53, 1, 0, 0, 0, 555, 556, + 5, 49, 0, 0, 556, 557, 3, 208, 104, 0, 557, 55, + 1, 0, 0, 0, 558, 559, 5, 50, 0, 0, 559, 560, + 3, 208, 104, 0, 560, 57, 1, 0, 0, 0, 561, 562, + 5, 51, 0, 0, 562, 563, 3, 208, 104, 0, 563, 59, + 1, 0, 0, 0, 564, 565, 5, 52, 0, 0, 565, 567, + 3, 130, 65, 0, 566, 564, 1, 0, 0, 0, 566, 567, + 1, 0, 0, 0, 567, 61, 1, 0, 0, 0, 568, 574, + 3, 4, 2, 0, 569, 572, 3, 64, 32, 0, 570, 571, + 5, 6, 0, 0, 571, 573, 3, 62, 31, 0, 572, 570, + 1, 0, 0, 0, 572, 573, 1, 0, 0, 0, 573, 575, + 1, 0, 0, 0, 574, 569, 1, 0, 0, 0, 574, 575, + 1, 0, 0, 0, 575, 63, 1, 0, 0, 0, 576, 588, + 3, 66, 33, 0, 577, 588, 3, 68, 34, 0, 578, 588, + 3, 70, 35, 0, 579, 588, 3, 74, 37, 0, 580, 588, + 3, 76, 38, 0, 581, 588, 3, 78, 39, 0, 582, 588, + 3, 72, 36, 0, 583, 588, 3, 80, 40, 0, 584, 588, + 3, 82, 41, 0, 585, 588, 3, 84, 42, 0, 586, 588, + 3, 86, 43, 0, 587, 576, 1, 0, 0, 0, 587, 577, + 1, 0, 0, 0, 587, 578, 1, 0, 0, 0, 587, 579, + 1, 0, 0, 0, 587, 580, 1, 0, 0, 0, 587, 581, + 1, 0, 0, 0, 587, 582, 1, 0, 0, 0, 587, 583, + 1, 0, 0, 0, 587, 584, 1, 0, 0, 0, 587, 585, + 1, 0, 0, 0, 587, 586, 1, 0, 0, 0, 588, 65, + 1, 0, 0, 0, 589, 591, 5, 53, 0, 0, 590, 592, + 5, 54, 0, 0, 591, 590, 1, 0, 0, 0, 591, 592, + 1, 0, 0, 0, 592, 593, 1, 0, 0, 0, 593, 596, + 3, 302, 151, 0, 594, 595, 5, 55, 0, 0, 595, 597, + 3, 96, 48, 0, 596, 594, 1, 0, 0, 0, 596, 597, + 1, 0, 0, 0, 597, 67, 1, 0, 0, 0, 598, 600, + 5, 56, 0, 0, 599, 601, 5, 54, 0, 0, 600, 599, + 1, 0, 0, 0, 600, 601, 1, 0, 0, 0, 601, 602, + 1, 0, 0, 0, 602, 603, 3, 98, 49, 0, 603, 69, + 1, 0, 0, 0, 604, 606, 5, 57, 0, 0, 605, 607, + 5, 54, 0, 0, 606, 605, 1, 0, 0, 0, 606, 607, + 1, 0, 0, 0, 607, 608, 1, 0, 0, 0, 608, 609, + 3, 98, 49, 0, 609, 71, 1, 0, 0, 0, 610, 612, + 5, 58, 0, 0, 611, 613, 5, 54, 0, 0, 612, 611, + 1, 0, 0, 0, 612, 613, 1, 0, 0, 0, 613, 614, + 1, 0, 0, 0, 614, 615, 3, 96, 48, 0, 615, 73, + 1, 0, 0, 0, 616, 618, 5, 59, 0, 0, 617, 619, + 5, 54, 0, 0, 618, 617, 1, 0, 0, 0, 618, 619, + 1, 0, 0, 0, 619, 620, 1, 0, 0, 0, 620, 621, + 3, 94, 47, 0, 621, 622, 5, 60, 0, 0, 622, 623, + 3, 94, 47, 0, 623, 75, 1, 0, 0, 0, 624, 626, + 5, 62, 0, 0, 625, 627, 5, 54, 0, 0, 626, 625, + 1, 0, 0, 0, 626, 627, 1, 0, 0, 0, 627, 628, + 1, 0, 0, 0, 628, 629, 3, 94, 47, 0, 629, 630, + 5, 60, 0, 0, 630, 631, 3, 94, 47, 0, 631, 77, + 1, 0, 0, 0, 632, 634, 5, 63, 0, 0, 633, 635, + 5, 54, 0, 0, 634, 633, 1, 0, 0, 0, 634, 635, + 1, 0, 0, 0, 635, 636, 1, 0, 0, 0, 636, 637, + 3, 94, 47, 0, 637, 638, 5, 60, 0, 0, 638, 639, + 3, 94, 47, 0, 639, 79, 1, 0, 0, 0, 640, 641, + 5, 64, 0, 0, 641, 642, 5, 61, 0, 0, 642, 643, + 3, 102, 51, 0, 643, 81, 1, 0, 0, 0, 644, 645, + 5, 65, 0, 0, 645, 646, 5, 61, 0, 0, 646, 647, + 3, 102, 51, 0, 647, 83, 1, 0, 0, 0, 648, 649, + 5, 65, 0, 0, 649, 650, 5, 37, 0, 0, 650, 651, + 3, 100, 50, 0, 651, 85, 1, 0, 0, 0, 652, 653, + 5, 66, 0, 0, 653, 655, 3, 302, 151, 0, 654, 652, + 1, 0, 0, 0, 654, 655, 1, 0, 0, 0, 655, 661, + 1, 0, 0, 0, 656, 658, 3, 88, 44, 0, 657, 659, + 3, 90, 45, 0, 658, 657, 1, 0, 0, 0, 658, 659, + 1, 0, 0, 0, 659, 662, 1, 0, 0, 0, 660, 662, + 3, 90, 45, 0, 661, 656, 1, 0, 0, 0, 661, 660, + 1, 0, 0, 0, 662, 666, 1, 0, 0, 0, 663, 665, + 3, 92, 46, 0, 664, 663, 1, 0, 0, 0, 665, 668, + 1, 0, 0, 0, 666, 664, 1, 0, 0, 0, 666, 667, + 1, 0, 0, 0, 667, 669, 1, 0, 0, 0, 668, 666, + 1, 0, 0, 0, 669, 670, 5, 37, 0, 0, 670, 671, + 3, 110, 55, 0, 671, 87, 1, 0, 0, 0, 672, 673, + 5, 65, 0, 0, 673, 674, 3, 100, 50, 0, 674, 89, + 1, 0, 0, 0, 675, 676, 5, 64, 0, 0, 676, 677, + 3, 100, 50, 0, 677, 91, 1, 0, 0, 0, 678, 682, + 5, 67, 0, 0, 679, 683, 5, 85, 0, 0, 680, 681, + 5, 41, 0, 0, 681, 683, 3, 302, 151, 0, 682, 679, + 1, 0, 0, 0, 682, 680, 1, 0, 0, 0, 683, 93, + 1, 0, 0, 0, 684, 688, 5, 68, 0, 0, 685, 686, + 5, 69, 0, 0, 686, 688, 3, 302, 151, 0, 687, 684, + 1, 0, 0, 0, 687, 685, 1, 0, 0, 0, 688, 95, + 1, 0, 0, 0, 689, 690, 5, 69, 0, 0, 690, 691, + 3, 302, 151, 0, 691, 97, 1, 0, 0, 0, 692, 697, + 3, 96, 48, 0, 693, 697, 5, 68, 0, 0, 694, 697, + 5, 41, 0, 0, 695, 697, 5, 70, 0, 0, 696, 692, + 1, 0, 0, 0, 696, 693, 1, 0, 0, 0, 696, 694, + 1, 0, 0, 0, 696, 695, 1, 0, 0, 0, 697, 99, + 1, 0, 0, 0, 698, 699, 5, 4, 0, 0, 699, 700, + 3, 104, 52, 0, 700, 701, 5, 5, 0, 0, 701, 101, + 1, 0, 0, 0, 702, 703, 5, 4, 0, 0, 703, 704, + 3, 104, 52, 0, 704, 705, 5, 5, 0, 0, 705, 103, + 1, 0, 0, 0, 706, 708, 3, 108, 54, 0, 707, 706, + 1, 0, 0, 0, 707, 708, 1, 0, 0, 0, 708, 718, + 1, 0, 0, 0, 709, 711, 3, 106, 53, 0, 710, 712, + 5, 7, 0, 0, 711, 710, 1, 0, 0, 0, 711, 712, + 1, 0, 0, 0, 712, 714, 1, 0, 0, 0, 713, 715, + 3, 108, 54, 0, 714, 713, 1, 0, 0, 0, 714, 715, + 1, 0, 0, 0, 715, 717, 1, 0, 0, 0, 716, 709, + 1, 0, 0, 0, 717, 720, 1, 0, 0, 0, 718, 716, + 1, 0, 0, 0, 718, 719, 1, 0, 0, 0, 719, 105, + 1, 0, 0, 0, 720, 718, 1, 0, 0, 0, 721, 722, + 5, 69, 0, 0, 722, 723, 3, 228, 114, 0, 723, 725, + 5, 4, 0, 0, 724, 726, 3, 108, 54, 0, 725, 724, + 1, 0, 0, 0, 725, 726, 1, 0, 0, 0, 726, 727, + 1, 0, 0, 0, 727, 728, 5, 5, 0, 0, 728, 107, + 1, 0, 0, 0, 729, 734, 3, 158, 79, 0, 730, 732, + 5, 7, 0, 0, 731, 733, 3, 108, 54, 0, 732, 731, + 1, 0, 0, 0, 732, 733, 1, 0, 0, 0, 733, 735, + 1, 0, 0, 0, 734, 730, 1, 0, 0, 0, 734, 735, + 1, 0, 0, 0, 735, 109, 1, 0, 0, 0, 736, 739, + 5, 4, 0, 0, 737, 740, 3, 12, 6, 0, 738, 740, + 3, 112, 56, 0, 739, 737, 1, 0, 0, 0, 739, 738, + 1, 0, 0, 0, 740, 741, 1, 0, 0, 0, 741, 742, + 5, 5, 0, 0, 742, 111, 1, 0, 0, 0, 743, 745, + 3, 116, 58, 0, 744, 743, 1, 0, 0, 0, 744, 745, + 1, 0, 0, 0, 745, 749, 1, 0, 0, 0, 746, 748, + 3, 114, 57, 0, 747, 746, 1, 0, 0, 0, 748, 751, + 1, 0, 0, 0, 749, 747, 1, 0, 0, 0, 749, 750, + 1, 0, 0, 0, 750, 113, 1, 0, 0, 0, 751, 749, + 1, 0, 0, 0, 752, 754, 3, 118, 59, 0, 753, 755, + 5, 7, 0, 0, 754, 753, 1, 0, 0, 0, 754, 755, + 1, 0, 0, 0, 755, 757, 1, 0, 0, 0, 756, 758, + 3, 116, 58, 0, 757, 756, 1, 0, 0, 0, 757, 758, + 1, 0, 0, 0, 758, 115, 1, 0, 0, 0, 759, 764, + 3, 170, 85, 0, 760, 762, 5, 7, 0, 0, 761, 763, + 3, 116, 58, 0, 762, 761, 1, 0, 0, 0, 762, 763, + 1, 0, 0, 0, 763, 765, 1, 0, 0, 0, 764, 760, + 1, 0, 0, 0, 764, 765, 1, 0, 0, 0, 765, 117, + 1, 0, 0, 0, 766, 775, 3, 142, 71, 0, 767, 775, + 3, 120, 60, 0, 768, 775, 3, 140, 70, 0, 769, 775, + 3, 122, 61, 0, 770, 775, 3, 124, 62, 0, 771, 775, + 3, 144, 72, 0, 772, 775, 3, 126, 63, 0, 773, 775, + 3, 128, 64, 0, 774, 766, 1, 0, 0, 0, 774, 767, + 1, 0, 0, 0, 774, 768, 1, 0, 0, 0, 774, 769, + 1, 0, 0, 0, 774, 770, 1, 0, 0, 0, 774, 771, + 1, 0, 0, 0, 774, 772, 1, 0, 0, 0, 774, 773, + 1, 0, 0, 0, 775, 119, 1, 0, 0, 0, 776, 777, + 5, 71, 0, 0, 777, 778, 3, 110, 55, 0, 778, 121, + 1, 0, 0, 0, 779, 780, 5, 69, 0, 0, 780, 781, + 3, 228, 114, 0, 781, 782, 3, 110, 55, 0, 782, 123, + 1, 0, 0, 0, 783, 785, 5, 72, 0, 0, 784, 786, + 5, 54, 0, 0, 785, 784, 1, 0, 0, 0, 785, 786, + 1, 0, 0, 0, 786, 787, 1, 0, 0, 0, 787, 788, + 3, 228, 114, 0, 788, 789, 3, 110, 55, 0, 789, 125, + 1, 0, 0, 0, 790, 791, 5, 73, 0, 0, 791, 792, + 5, 2, 0, 0, 792, 793, 3, 234, 117, 0, 793, 794, + 5, 35, 0, 0, 794, 795, 3, 230, 115, 0, 795, 796, + 5, 3, 0, 0, 796, 127, 1, 0, 0, 0, 797, 798, + 5, 52, 0, 0, 798, 799, 3, 130, 65, 0, 799, 129, + 1, 0, 0, 0, 800, 803, 3, 132, 66, 0, 801, 803, + 3, 134, 67, 0, 802, 800, 1, 0, 0, 0, 802, 801, + 1, 0, 0, 0, 803, 131, 1, 0, 0, 0, 804, 805, + 3, 230, 115, 0, 805, 809, 5, 4, 0, 0, 806, 808, + 3, 138, 69, 0, 807, 806, 1, 0, 0, 0, 808, 811, + 1, 0, 0, 0, 809, 807, 1, 0, 0, 0, 809, 810, + 1, 0, 0, 0, 810, 812, 1, 0, 0, 0, 811, 809, + 1, 0, 0, 0, 812, 813, 5, 5, 0, 0, 813, 133, + 1, 0, 0, 0, 814, 824, 5, 164, 0, 0, 815, 819, + 5, 2, 0, 0, 816, 818, 3, 230, 115, 0, 817, 816, + 1, 0, 0, 0, 818, 821, 1, 0, 0, 0, 819, 817, + 1, 0, 0, 0, 819, 820, 1, 0, 0, 0, 820, 822, + 1, 0, 0, 0, 821, 819, 1, 0, 0, 0, 822, 824, + 5, 3, 0, 0, 823, 814, 1, 0, 0, 0, 823, 815, + 1, 0, 0, 0, 824, 825, 1, 0, 0, 0, 825, 829, + 5, 4, 0, 0, 826, 828, 3, 136, 68, 0, 827, 826, + 1, 0, 0, 0, 828, 831, 1, 0, 0, 0, 829, 827, + 1, 0, 0, 0, 829, 830, 1, 0, 0, 0, 830, 832, + 1, 0, 0, 0, 831, 829, 1, 0, 0, 0, 832, 833, + 5, 5, 0, 0, 833, 135, 1, 0, 0, 0, 834, 838, + 5, 2, 0, 0, 835, 837, 3, 138, 69, 0, 836, 835, + 1, 0, 0, 0, 837, 840, 1, 0, 0, 0, 838, 836, + 1, 0, 0, 0, 838, 839, 1, 0, 0, 0, 839, 841, + 1, 0, 0, 0, 840, 838, 1, 0, 0, 0, 841, 844, + 5, 3, 0, 0, 842, 844, 5, 164, 0, 0, 843, 834, + 1, 0, 0, 0, 843, 842, 1, 0, 0, 0, 844, 137, + 1, 0, 0, 0, 845, 851, 3, 302, 151, 0, 846, 851, + 3, 288, 144, 0, 847, 851, 3, 290, 145, 0, 848, 851, + 3, 298, 149, 0, 849, 851, 5, 74, 0, 0, 850, 845, + 1, 0, 0, 0, 850, 846, 1, 0, 0, 0, 850, 847, + 1, 0, 0, 0, 850, 848, 1, 0, 0, 0, 850, 849, + 1, 0, 0, 0, 851, 139, 1, 0, 0, 0, 852, 853, + 5, 75, 0, 0, 853, 854, 3, 110, 55, 0, 854, 141, + 1, 0, 0, 0, 855, 860, 3, 110, 55, 0, 856, 857, + 5, 76, 0, 0, 857, 859, 3, 110, 55, 0, 858, 856, + 1, 0, 0, 0, 859, 862, 1, 0, 0, 0, 860, 858, + 1, 0, 0, 0, 860, 861, 1, 0, 0, 0, 861, 143, + 1, 0, 0, 0, 862, 860, 1, 0, 0, 0, 863, 864, + 5, 77, 0, 0, 864, 865, 3, 146, 73, 0, 865, 145, + 1, 0, 0, 0, 866, 870, 3, 268, 134, 0, 867, 870, + 3, 270, 135, 0, 868, 870, 3, 148, 74, 0, 869, 866, + 1, 0, 0, 0, 869, 867, 1, 0, 0, 0, 869, 868, + 1, 0, 0, 0, 870, 147, 1, 0, 0, 0, 871, 872, + 3, 302, 151, 0, 872, 873, 3, 150, 75, 0, 873, 149, + 1, 0, 0, 0, 874, 890, 5, 164, 0, 0, 875, 877, + 5, 2, 0, 0, 876, 878, 5, 33, 0, 0, 877, 876, + 1, 0, 0, 0, 877, 878, 1, 0, 0, 0, 878, 879, + 1, 0, 0, 0, 879, 884, 3, 234, 117, 0, 880, 881, + 5, 8, 0, 0, 881, 883, 3, 234, 117, 0, 882, 880, + 1, 0, 0, 0, 883, 886, 1, 0, 0, 0, 884, 882, + 1, 0, 0, 0, 884, 885, 1, 0, 0, 0, 885, 887, + 1, 0, 0, 0, 886, 884, 1, 0, 0, 0, 887, 888, + 5, 3, 0, 0, 888, 890, 1, 0, 0, 0, 889, 874, + 1, 0, 0, 0, 889, 875, 1, 0, 0, 0, 890, 151, + 1, 0, 0, 0, 891, 904, 5, 164, 0, 0, 892, 893, + 5, 2, 0, 0, 893, 898, 3, 234, 117, 0, 894, 895, + 5, 8, 0, 0, 895, 897, 3, 234, 117, 0, 896, 894, + 1, 0, 0, 0, 897, 900, 1, 0, 0, 0, 898, 896, + 1, 0, 0, 0, 898, 899, 1, 0, 0, 0, 899, 901, + 1, 0, 0, 0, 900, 898, 1, 0, 0, 0, 901, 902, + 5, 3, 0, 0, 902, 904, 1, 0, 0, 0, 903, 891, + 1, 0, 0, 0, 903, 892, 1, 0, 0, 0, 904, 153, + 1, 0, 0, 0, 905, 907, 5, 4, 0, 0, 906, 908, + 3, 156, 78, 0, 907, 906, 1, 0, 0, 0, 907, 908, + 1, 0, 0, 0, 908, 909, 1, 0, 0, 0, 909, 910, + 5, 5, 0, 0, 910, 155, 1, 0, 0, 0, 911, 916, + 3, 158, 79, 0, 912, 914, 5, 7, 0, 0, 913, 915, + 3, 156, 78, 0, 914, 913, 1, 0, 0, 0, 914, 915, + 1, 0, 0, 0, 915, 917, 1, 0, 0, 0, 916, 912, + 1, 0, 0, 0, 916, 917, 1, 0, 0, 0, 917, 157, + 1, 0, 0, 0, 918, 919, 3, 226, 113, 0, 919, 920, + 3, 162, 81, 0, 920, 925, 1, 0, 0, 0, 921, 922, + 3, 210, 105, 0, 922, 923, 3, 160, 80, 0, 923, 925, + 1, 0, 0, 0, 924, 918, 1, 0, 0, 0, 924, 921, + 1, 0, 0, 0, 925, 159, 1, 0, 0, 0, 926, 928, + 3, 162, 81, 0, 927, 926, 1, 0, 0, 0, 927, 928, + 1, 0, 0, 0, 928, 161, 1, 0, 0, 0, 929, 930, + 3, 164, 82, 0, 930, 939, 3, 166, 83, 0, 931, 935, + 5, 6, 0, 0, 932, 933, 3, 164, 82, 0, 933, 934, + 3, 166, 83, 0, 934, 936, 1, 0, 0, 0, 935, 932, + 1, 0, 0, 0, 935, 936, 1, 0, 0, 0, 936, 938, + 1, 0, 0, 0, 937, 931, 1, 0, 0, 0, 938, 941, + 1, 0, 0, 0, 939, 937, 1, 0, 0, 0, 939, 940, + 1, 0, 0, 0, 940, 163, 1, 0, 0, 0, 941, 939, + 1, 0, 0, 0, 942, 945, 3, 228, 114, 0, 943, 945, + 5, 9, 0, 0, 944, 942, 1, 0, 0, 0, 944, 943, + 1, 0, 0, 0, 945, 165, 1, 0, 0, 0, 946, 951, + 3, 168, 84, 0, 947, 948, 5, 8, 0, 0, 948, 950, + 3, 168, 84, 0, 949, 947, 1, 0, 0, 0, 950, 953, + 1, 0, 0, 0, 951, 949, 1, 0, 0, 0, 951, 952, + 1, 0, 0, 0, 952, 167, 1, 0, 0, 0, 953, 951, + 1, 0, 0, 0, 954, 955, 3, 222, 111, 0, 955, 169, + 1, 0, 0, 0, 956, 957, 3, 226, 113, 0, 957, 958, + 3, 174, 87, 0, 958, 963, 1, 0, 0, 0, 959, 960, + 3, 214, 107, 0, 960, 961, 3, 172, 86, 0, 961, 963, + 1, 0, 0, 0, 962, 956, 1, 0, 0, 0, 962, 959, + 1, 0, 0, 0, 963, 171, 1, 0, 0, 0, 964, 966, + 3, 174, 87, 0, 965, 964, 1, 0, 0, 0, 965, 966, + 1, 0, 0, 0, 966, 173, 1, 0, 0, 0, 967, 974, + 3, 182, 91, 0, 968, 970, 5, 6, 0, 0, 969, 971, + 3, 180, 90, 0, 970, 969, 1, 0, 0, 0, 970, 971, + 1, 0, 0, 0, 971, 973, 1, 0, 0, 0, 972, 968, + 1, 0, 0, 0, 973, 976, 1, 0, 0, 0, 974, 972, + 1, 0, 0, 0, 974, 975, 1, 0, 0, 0, 975, 175, + 1, 0, 0, 0, 976, 974, 1, 0, 0, 0, 977, 978, + 3, 190, 95, 0, 978, 177, 1, 0, 0, 0, 979, 980, + 3, 230, 115, 0, 980, 179, 1, 0, 0, 0, 981, 982, + 3, 184, 92, 0, 982, 983, 3, 166, 83, 0, 983, 181, + 1, 0, 0, 0, 984, 985, 3, 184, 92, 0, 985, 986, + 3, 186, 93, 0, 986, 183, 1, 0, 0, 0, 987, 990, + 3, 176, 88, 0, 988, 990, 3, 178, 89, 0, 989, 987, + 1, 0, 0, 0, 989, 988, 1, 0, 0, 0, 990, 185, + 1, 0, 0, 0, 991, 996, 3, 188, 94, 0, 992, 993, + 5, 8, 0, 0, 993, 995, 3, 188, 94, 0, 994, 992, + 1, 0, 0, 0, 995, 998, 1, 0, 0, 0, 996, 994, + 1, 0, 0, 0, 996, 997, 1, 0, 0, 0, 997, 187, + 1, 0, 0, 0, 998, 996, 1, 0, 0, 0, 999, 1000, + 3, 224, 112, 0, 1000, 189, 1, 0, 0, 0, 1001, 1002, + 3, 192, 96, 0, 1002, 191, 1, 0, 0, 0, 1003, 1008, + 3, 194, 97, 0, 1004, 1005, 5, 10, 0, 0, 1005, 1007, + 3, 194, 97, 0, 1006, 1004, 1, 0, 0, 0, 1007, 1010, + 1, 0, 0, 0, 1008, 1006, 1, 0, 0, 0, 1008, 1009, + 1, 0, 0, 0, 1009, 193, 1, 0, 0, 0, 1010, 1008, + 1, 0, 0, 0, 1011, 1016, 3, 198, 99, 0, 1012, 1013, + 5, 11, 0, 0, 1013, 1015, 3, 198, 99, 0, 1014, 1012, + 1, 0, 0, 0, 1015, 1018, 1, 0, 0, 0, 1016, 1014, + 1, 0, 0, 0, 1016, 1017, 1, 0, 0, 0, 1017, 195, + 1, 0, 0, 0, 1018, 1016, 1, 0, 0, 0, 1019, 1021, + 3, 202, 101, 0, 1020, 1022, 3, 200, 100, 0, 1021, 1020, + 1, 0, 0, 0, 1021, 1022, 1, 0, 0, 0, 1022, 197, + 1, 0, 0, 0, 1023, 1027, 3, 196, 98, 0, 1024, 1025, + 5, 12, 0, 0, 1025, 1027, 3, 196, 98, 0, 1026, 1023, + 1, 0, 0, 0, 1026, 1024, 1, 0, 0, 0, 1027, 199, + 1, 0, 0, 0, 1028, 1029, 7, 2, 0, 0, 1029, 201, + 1, 0, 0, 0, 1030, 1039, 3, 302, 151, 0, 1031, 1039, + 5, 9, 0, 0, 1032, 1033, 5, 15, 0, 0, 1033, 1039, + 3, 204, 102, 0, 1034, 1035, 5, 2, 0, 0, 1035, 1036, + 3, 190, 95, 0, 1036, 1037, 5, 3, 0, 0, 1037, 1039, + 1, 0, 0, 0, 1038, 1030, 1, 0, 0, 0, 1038, 1031, + 1, 0, 0, 0, 1038, 1032, 1, 0, 0, 0, 1038, 1034, + 1, 0, 0, 0, 1039, 203, 1, 0, 0, 0, 1040, 1054, + 3, 206, 103, 0, 1041, 1050, 5, 2, 0, 0, 1042, 1047, + 3, 206, 103, 0, 1043, 1044, 5, 10, 0, 0, 1044, 1046, + 3, 206, 103, 0, 1045, 1043, 1, 0, 0, 0, 1046, 1049, + 1, 0, 0, 0, 1047, 1045, 1, 0, 0, 0, 1047, 1048, + 1, 0, 0, 0, 1048, 1051, 1, 0, 0, 0, 1049, 1047, + 1, 0, 0, 0, 1050, 1042, 1, 0, 0, 0, 1050, 1051, + 1, 0, 0, 0, 1051, 1052, 1, 0, 0, 0, 1052, 1054, + 5, 3, 0, 0, 1053, 1040, 1, 0, 0, 0, 1053, 1041, + 1, 0, 0, 0, 1054, 205, 1, 0, 0, 0, 1055, 1063, + 3, 302, 151, 0, 1056, 1063, 5, 9, 0, 0, 1057, 1060, + 5, 12, 0, 0, 1058, 1061, 3, 302, 151, 0, 1059, 1061, + 5, 9, 0, 0, 1060, 1058, 1, 0, 0, 0, 1060, 1059, + 1, 0, 0, 0, 1061, 1063, 1, 0, 0, 0, 1062, 1055, + 1, 0, 0, 0, 1062, 1056, 1, 0, 0, 0, 1062, 1057, + 1, 0, 0, 0, 1063, 207, 1, 0, 0, 0, 1064, 1065, + 5, 149, 0, 0, 1065, 209, 1, 0, 0, 0, 1066, 1069, + 3, 218, 109, 0, 1067, 1069, 3, 212, 106, 0, 1068, 1066, + 1, 0, 0, 0, 1068, 1067, 1, 0, 0, 0, 1069, 211, + 1, 0, 0, 0, 1070, 1071, 5, 16, 0, 0, 1071, 1072, + 3, 162, 81, 0, 1072, 1073, 5, 17, 0, 0, 1073, 213, + 1, 0, 0, 0, 1074, 1077, 3, 220, 110, 0, 1075, 1077, + 3, 216, 108, 0, 1076, 1074, 1, 0, 0, 0, 1076, 1075, + 1, 0, 0, 0, 1077, 215, 1, 0, 0, 0, 1078, 1079, + 5, 16, 0, 0, 1079, 1080, 3, 174, 87, 0, 1080, 1081, + 5, 17, 0, 0, 1081, 217, 1, 0, 0, 0, 1082, 1084, + 5, 2, 0, 0, 1083, 1085, 3, 222, 111, 0, 1084, 1083, + 1, 0, 0, 0, 1085, 1086, 1, 0, 0, 0, 1086, 1084, + 1, 0, 0, 0, 1086, 1087, 1, 0, 0, 0, 1087, 1088, + 1, 0, 0, 0, 1088, 1089, 5, 3, 0, 0, 1089, 219, + 1, 0, 0, 0, 1090, 1092, 5, 2, 0, 0, 1091, 1093, + 3, 224, 112, 0, 1092, 1091, 1, 0, 0, 0, 1093, 1094, + 1, 0, 0, 0, 1094, 1092, 1, 0, 0, 0, 1094, 1095, + 1, 0, 0, 0, 1095, 1096, 1, 0, 0, 0, 1096, 1097, + 5, 3, 0, 0, 1097, 221, 1, 0, 0, 0, 1098, 1101, + 3, 226, 113, 0, 1099, 1101, 3, 210, 105, 0, 1100, 1098, + 1, 0, 0, 0, 1100, 1099, 1, 0, 0, 0, 1101, 223, + 1, 0, 0, 0, 1102, 1105, 3, 226, 113, 0, 1103, 1105, + 3, 214, 107, 0, 1104, 1102, 1, 0, 0, 0, 1104, 1103, + 1, 0, 0, 0, 1105, 225, 1, 0, 0, 0, 1106, 1109, + 3, 230, 115, 0, 1107, 1109, 3, 232, 116, 0, 1108, 1106, + 1, 0, 0, 0, 1108, 1107, 1, 0, 0, 0, 1109, 227, + 1, 0, 0, 0, 1110, 1113, 3, 230, 115, 0, 1111, 1113, + 3, 302, 151, 0, 1112, 1110, 1, 0, 0, 0, 1112, 1111, + 1, 0, 0, 0, 1113, 229, 1, 0, 0, 0, 1114, 1115, + 7, 3, 0, 0, 1115, 231, 1, 0, 0, 0, 1116, 1123, + 3, 302, 151, 0, 1117, 1123, 3, 288, 144, 0, 1118, 1123, + 3, 290, 145, 0, 1119, 1123, 3, 298, 149, 0, 1120, 1123, + 3, 306, 153, 0, 1121, 1123, 5, 164, 0, 0, 1122, 1116, + 1, 0, 0, 0, 1122, 1117, 1, 0, 0, 0, 1122, 1118, + 1, 0, 0, 0, 1122, 1119, 1, 0, 0, 0, 1122, 1120, + 1, 0, 0, 0, 1122, 1121, 1, 0, 0, 0, 1123, 233, + 1, 0, 0, 0, 1124, 1125, 3, 236, 118, 0, 1125, 235, + 1, 0, 0, 0, 1126, 1131, 3, 238, 119, 0, 1127, 1128, + 5, 18, 0, 0, 1128, 1130, 3, 238, 119, 0, 1129, 1127, + 1, 0, 0, 0, 1130, 1133, 1, 0, 0, 0, 1131, 1129, + 1, 0, 0, 0, 1131, 1132, 1, 0, 0, 0, 1132, 237, + 1, 0, 0, 0, 1133, 1131, 1, 0, 0, 0, 1134, 1139, + 3, 240, 120, 0, 1135, 1136, 5, 19, 0, 0, 1136, 1138, + 3, 240, 120, 0, 1137, 1135, 1, 0, 0, 0, 1138, 1141, + 1, 0, 0, 0, 1139, 1137, 1, 0, 0, 0, 1139, 1140, + 1, 0, 0, 0, 1140, 239, 1, 0, 0, 0, 1141, 1139, + 1, 0, 0, 0, 1142, 1143, 3, 242, 121, 0, 1143, 241, + 1, 0, 0, 0, 1144, 1162, 3, 244, 122, 0, 1145, 1146, + 5, 20, 0, 0, 1146, 1163, 3, 244, 122, 0, 1147, 1148, + 5, 21, 0, 0, 1148, 1163, 3, 244, 122, 0, 1149, 1150, + 5, 22, 0, 0, 1150, 1163, 3, 244, 122, 0, 1151, 1152, + 5, 23, 0, 0, 1152, 1163, 3, 244, 122, 0, 1153, 1154, + 5, 24, 0, 0, 1154, 1163, 3, 244, 122, 0, 1155, 1156, + 5, 25, 0, 0, 1156, 1163, 3, 244, 122, 0, 1157, 1158, + 5, 79, 0, 0, 1158, 1163, 3, 152, 76, 0, 1159, 1160, + 5, 78, 0, 0, 1160, 1161, 5, 79, 0, 0, 1161, 1163, + 3, 152, 76, 0, 1162, 1145, 1, 0, 0, 0, 1162, 1147, + 1, 0, 0, 0, 1162, 1149, 1, 0, 0, 0, 1162, 1151, + 1, 0, 0, 0, 1162, 1153, 1, 0, 0, 0, 1162, 1155, + 1, 0, 0, 0, 1162, 1157, 1, 0, 0, 0, 1162, 1159, + 1, 0, 0, 0, 1162, 1163, 1, 0, 0, 0, 1163, 243, + 1, 0, 0, 0, 1164, 1165, 3, 246, 123, 0, 1165, 245, + 1, 0, 0, 0, 1166, 1170, 3, 256, 128, 0, 1167, 1169, + 3, 248, 124, 0, 1168, 1167, 1, 0, 0, 0, 1169, 1172, + 1, 0, 0, 0, 1170, 1168, 1, 0, 0, 0, 1170, 1171, + 1, 0, 0, 0, 1171, 247, 1, 0, 0, 0, 1172, 1170, + 1, 0, 0, 0, 1173, 1174, 5, 13, 0, 0, 1174, 1179, + 3, 250, 125, 0, 1175, 1176, 5, 26, 0, 0, 1176, 1179, + 3, 252, 126, 0, 1177, 1179, 3, 254, 127, 0, 1178, 1173, + 1, 0, 0, 0, 1178, 1175, 1, 0, 0, 0, 1178, 1177, + 1, 0, 0, 0, 1179, 249, 1, 0, 0, 0, 1180, 1181, + 3, 256, 128, 0, 1181, 251, 1, 0, 0, 0, 1182, 1183, + 3, 256, 128, 0, 1183, 253, 1, 0, 0, 0, 1184, 1187, + 3, 294, 147, 0, 1185, 1187, 3, 296, 148, 0, 1186, 1184, + 1, 0, 0, 0, 1186, 1185, 1, 0, 0, 0, 1187, 1191, + 1, 0, 0, 0, 1188, 1190, 3, 258, 129, 0, 1189, 1188, + 1, 0, 0, 0, 1190, 1193, 1, 0, 0, 0, 1191, 1189, + 1, 0, 0, 0, 1191, 1192, 1, 0, 0, 0, 1192, 255, + 1, 0, 0, 0, 1193, 1191, 1, 0, 0, 0, 1194, 1198, + 3, 264, 132, 0, 1195, 1197, 3, 258, 129, 0, 1196, 1195, + 1, 0, 0, 0, 1197, 1200, 1, 0, 0, 0, 1198, 1196, + 1, 0, 0, 0, 1198, 1199, 1, 0, 0, 0, 1199, 257, + 1, 0, 0, 0, 1200, 1198, 1, 0, 0, 0, 1201, 1204, + 3, 260, 130, 0, 1202, 1204, 3, 262, 131, 0, 1203, 1201, + 1, 0, 0, 0, 1203, 1202, 1, 0, 0, 0, 1204, 259, + 1, 0, 0, 0, 1205, 1206, 5, 1, 0, 0, 1206, 1207, + 3, 264, 132, 0, 1207, 261, 1, 0, 0, 0, 1208, 1209, + 5, 11, 0, 0, 1209, 1210, 3, 264, 132, 0, 1210, 263, + 1, 0, 0, 0, 1211, 1212, 5, 15, 0, 0, 1212, 1219, + 3, 266, 133, 0, 1213, 1214, 5, 13, 0, 0, 1214, 1219, + 3, 266, 133, 0, 1215, 1216, 5, 26, 0, 0, 1216, 1219, + 3, 266, 133, 0, 1217, 1219, 3, 266, 133, 0, 1218, 1211, + 1, 0, 0, 0, 1218, 1213, 1, 0, 0, 0, 1218, 1215, + 1, 0, 0, 0, 1218, 1217, 1, 0, 0, 0, 1219, 265, + 1, 0, 0, 0, 1220, 1228, 3, 268, 134, 0, 1221, 1228, + 3, 270, 135, 0, 1222, 1228, 3, 286, 143, 0, 1223, 1228, + 3, 288, 144, 0, 1224, 1228, 3, 290, 145, 0, 1225, 1228, + 3, 298, 149, 0, 1226, 1228, 3, 230, 115, 0, 1227, 1220, + 1, 0, 0, 0, 1227, 1221, 1, 0, 0, 0, 1227, 1222, + 1, 0, 0, 0, 1227, 1223, 1, 0, 0, 0, 1227, 1224, + 1, 0, 0, 0, 1227, 1225, 1, 0, 0, 0, 1227, 1226, + 1, 0, 0, 0, 1228, 267, 1, 0, 0, 0, 1229, 1230, + 5, 2, 0, 0, 1230, 1231, 3, 234, 117, 0, 1231, 1232, + 5, 3, 0, 0, 1232, 269, 1, 0, 0, 0, 1233, 1488, + 3, 284, 142, 0, 1234, 1235, 5, 80, 0, 0, 1235, 1236, + 5, 2, 0, 0, 1236, 1237, 3, 234, 117, 0, 1237, 1238, + 5, 3, 0, 0, 1238, 1488, 1, 0, 0, 0, 1239, 1488, + 3, 274, 137, 0, 1240, 1241, 5, 82, 0, 0, 1241, 1242, + 5, 2, 0, 0, 1242, 1243, 3, 234, 117, 0, 1243, 1244, + 5, 8, 0, 0, 1244, 1245, 3, 234, 117, 0, 1245, 1246, + 5, 3, 0, 0, 1246, 1488, 1, 0, 0, 0, 1247, 1248, + 5, 83, 0, 0, 1248, 1249, 5, 2, 0, 0, 1249, 1250, + 3, 234, 117, 0, 1250, 1251, 5, 3, 0, 0, 1251, 1488, + 1, 0, 0, 0, 1252, 1253, 5, 84, 0, 0, 1253, 1254, + 5, 2, 0, 0, 1254, 1255, 3, 230, 115, 0, 1255, 1256, + 5, 3, 0, 0, 1256, 1488, 1, 0, 0, 0, 1257, 1258, + 5, 85, 0, 0, 1258, 1259, 5, 2, 0, 0, 1259, 1260, + 3, 234, 117, 0, 1260, 1261, 5, 3, 0, 0, 1261, 1488, + 1, 0, 0, 0, 1262, 1263, 5, 86, 0, 0, 1263, 1264, + 5, 2, 0, 0, 1264, 1265, 3, 234, 117, 0, 1265, 1266, + 5, 3, 0, 0, 1266, 1488, 1, 0, 0, 0, 1267, 1273, + 5, 87, 0, 0, 1268, 1269, 5, 2, 0, 0, 1269, 1270, + 3, 234, 117, 0, 1270, 1271, 5, 3, 0, 0, 1271, 1274, + 1, 0, 0, 0, 1272, 1274, 5, 164, 0, 0, 1273, 1268, + 1, 0, 0, 0, 1273, 1272, 1, 0, 0, 0, 1274, 1488, + 1, 0, 0, 0, 1275, 1276, 5, 88, 0, 0, 1276, 1488, + 5, 164, 0, 0, 1277, 1278, 5, 89, 0, 0, 1278, 1279, + 5, 2, 0, 0, 1279, 1280, 3, 234, 117, 0, 1280, 1281, + 5, 3, 0, 0, 1281, 1488, 1, 0, 0, 0, 1282, 1283, + 5, 90, 0, 0, 1283, 1284, 5, 2, 0, 0, 1284, 1285, + 3, 234, 117, 0, 1285, 1286, 5, 3, 0, 0, 1286, 1488, + 1, 0, 0, 0, 1287, 1288, 5, 91, 0, 0, 1288, 1289, + 5, 2, 0, 0, 1289, 1290, 3, 234, 117, 0, 1290, 1291, + 5, 3, 0, 0, 1291, 1488, 1, 0, 0, 0, 1292, 1293, + 5, 92, 0, 0, 1293, 1294, 5, 2, 0, 0, 1294, 1295, + 3, 234, 117, 0, 1295, 1296, 5, 3, 0, 0, 1296, 1488, + 1, 0, 0, 0, 1297, 1298, 5, 93, 0, 0, 1298, 1488, + 3, 152, 76, 0, 1299, 1488, 3, 276, 138, 0, 1300, 1301, + 5, 94, 0, 0, 1301, 1302, 5, 2, 0, 0, 1302, 1303, + 3, 234, 117, 0, 1303, 1304, 5, 3, 0, 0, 1304, 1488, + 1, 0, 0, 0, 1305, 1488, 3, 278, 139, 0, 1306, 1307, + 5, 95, 0, 0, 1307, 1308, 5, 2, 0, 0, 1308, 1309, + 3, 234, 117, 0, 1309, 1310, 5, 3, 0, 0, 1310, 1488, + 1, 0, 0, 0, 1311, 1312, 5, 96, 0, 0, 1312, 1313, + 5, 2, 0, 0, 1313, 1314, 3, 234, 117, 0, 1314, 1315, + 5, 3, 0, 0, 1315, 1488, 1, 0, 0, 0, 1316, 1317, + 5, 97, 0, 0, 1317, 1318, 5, 2, 0, 0, 1318, 1319, + 3, 234, 117, 0, 1319, 1320, 5, 3, 0, 0, 1320, 1488, + 1, 0, 0, 0, 1321, 1322, 5, 99, 0, 0, 1322, 1323, + 5, 2, 0, 0, 1323, 1324, 3, 234, 117, 0, 1324, 1325, + 5, 8, 0, 0, 1325, 1326, 3, 234, 117, 0, 1326, 1327, + 5, 3, 0, 0, 1327, 1488, 1, 0, 0, 0, 1328, 1329, + 5, 100, 0, 0, 1329, 1330, 5, 2, 0, 0, 1330, 1331, + 3, 234, 117, 0, 1331, 1332, 5, 8, 0, 0, 1332, 1333, + 3, 234, 117, 0, 1333, 1334, 5, 3, 0, 0, 1334, 1488, + 1, 0, 0, 0, 1335, 1336, 5, 101, 0, 0, 1336, 1337, + 5, 2, 0, 0, 1337, 1338, 3, 234, 117, 0, 1338, 1339, + 5, 8, 0, 0, 1339, 1340, 3, 234, 117, 0, 1340, 1341, + 5, 3, 0, 0, 1341, 1488, 1, 0, 0, 0, 1342, 1343, + 5, 102, 0, 0, 1343, 1344, 5, 2, 0, 0, 1344, 1345, + 3, 234, 117, 0, 1345, 1346, 5, 8, 0, 0, 1346, 1347, + 3, 234, 117, 0, 1347, 1348, 5, 3, 0, 0, 1348, 1488, + 1, 0, 0, 0, 1349, 1350, 5, 103, 0, 0, 1350, 1351, + 5, 2, 0, 0, 1351, 1352, 3, 234, 117, 0, 1352, 1353, + 5, 8, 0, 0, 1353, 1354, 3, 234, 117, 0, 1354, 1355, + 5, 3, 0, 0, 1355, 1488, 1, 0, 0, 0, 1356, 1357, + 5, 104, 0, 0, 1357, 1358, 5, 2, 0, 0, 1358, 1359, + 3, 234, 117, 0, 1359, 1360, 5, 3, 0, 0, 1360, 1488, + 1, 0, 0, 0, 1361, 1362, 5, 105, 0, 0, 1362, 1363, + 5, 2, 0, 0, 1363, 1364, 3, 234, 117, 0, 1364, 1365, + 5, 3, 0, 0, 1365, 1488, 1, 0, 0, 0, 1366, 1367, + 5, 106, 0, 0, 1367, 1368, 5, 2, 0, 0, 1368, 1369, + 3, 234, 117, 0, 1369, 1370, 5, 3, 0, 0, 1370, 1488, + 1, 0, 0, 0, 1371, 1372, 5, 107, 0, 0, 1372, 1373, + 5, 2, 0, 0, 1373, 1374, 3, 234, 117, 0, 1374, 1375, + 5, 3, 0, 0, 1375, 1488, 1, 0, 0, 0, 1376, 1377, + 5, 108, 0, 0, 1377, 1378, 5, 2, 0, 0, 1378, 1379, + 3, 234, 117, 0, 1379, 1380, 5, 3, 0, 0, 1380, 1488, + 1, 0, 0, 0, 1381, 1382, 5, 109, 0, 0, 1382, 1383, + 5, 2, 0, 0, 1383, 1384, 3, 234, 117, 0, 1384, 1385, + 5, 3, 0, 0, 1385, 1488, 1, 0, 0, 0, 1386, 1387, + 5, 110, 0, 0, 1387, 1388, 5, 2, 0, 0, 1388, 1389, + 3, 234, 117, 0, 1389, 1390, 5, 3, 0, 0, 1390, 1488, + 1, 0, 0, 0, 1391, 1392, 5, 111, 0, 0, 1392, 1393, + 5, 2, 0, 0, 1393, 1394, 3, 234, 117, 0, 1394, 1395, + 5, 3, 0, 0, 1395, 1488, 1, 0, 0, 0, 1396, 1397, + 5, 112, 0, 0, 1397, 1488, 5, 164, 0, 0, 1398, 1399, + 5, 113, 0, 0, 1399, 1488, 5, 164, 0, 0, 1400, 1401, + 5, 114, 0, 0, 1401, 1488, 5, 164, 0, 0, 1402, 1403, + 5, 119, 0, 0, 1403, 1404, 5, 2, 0, 0, 1404, 1405, + 3, 234, 117, 0, 1405, 1406, 5, 3, 0, 0, 1406, 1488, + 1, 0, 0, 0, 1407, 1408, 5, 115, 0, 0, 1408, 1409, + 5, 2, 0, 0, 1409, 1410, 3, 234, 117, 0, 1410, 1411, + 5, 3, 0, 0, 1411, 1488, 1, 0, 0, 0, 1412, 1413, + 5, 116, 0, 0, 1413, 1414, 5, 2, 0, 0, 1414, 1415, + 3, 234, 117, 0, 1415, 1416, 5, 3, 0, 0, 1416, 1488, + 1, 0, 0, 0, 1417, 1418, 5, 117, 0, 0, 1418, 1419, + 5, 2, 0, 0, 1419, 1420, 3, 234, 117, 0, 1420, 1421, + 5, 3, 0, 0, 1421, 1488, 1, 0, 0, 0, 1422, 1423, + 5, 118, 0, 0, 1423, 1424, 5, 2, 0, 0, 1424, 1425, + 3, 234, 117, 0, 1425, 1426, 5, 3, 0, 0, 1426, 1488, + 1, 0, 0, 0, 1427, 1428, 5, 120, 0, 0, 1428, 1488, + 3, 152, 76, 0, 1429, 1430, 5, 121, 0, 0, 1430, 1431, + 5, 2, 0, 0, 1431, 1432, 3, 234, 117, 0, 1432, 1433, + 5, 8, 0, 0, 1433, 1434, 3, 234, 117, 0, 1434, 1435, + 5, 8, 0, 0, 1435, 1436, 3, 234, 117, 0, 1436, 1437, + 5, 3, 0, 0, 1437, 1488, 1, 0, 0, 0, 1438, 1439, + 5, 122, 0, 0, 1439, 1440, 5, 2, 0, 0, 1440, 1441, + 3, 234, 117, 0, 1441, 1442, 5, 8, 0, 0, 1442, 1443, + 3, 234, 117, 0, 1443, 1444, 5, 3, 0, 0, 1444, 1488, + 1, 0, 0, 0, 1445, 1446, 5, 123, 0, 0, 1446, 1447, + 5, 2, 0, 0, 1447, 1448, 3, 234, 117, 0, 1448, 1449, + 5, 8, 0, 0, 1449, 1450, 3, 234, 117, 0, 1450, 1451, + 5, 3, 0, 0, 1451, 1488, 1, 0, 0, 0, 1452, 1453, + 5, 124, 0, 0, 1453, 1454, 5, 2, 0, 0, 1454, 1455, + 3, 234, 117, 0, 1455, 1456, 5, 8, 0, 0, 1456, 1457, + 3, 234, 117, 0, 1457, 1458, 5, 3, 0, 0, 1458, 1488, + 1, 0, 0, 0, 1459, 1460, 5, 125, 0, 0, 1460, 1461, + 5, 2, 0, 0, 1461, 1462, 3, 234, 117, 0, 1462, 1463, + 5, 3, 0, 0, 1463, 1488, 1, 0, 0, 0, 1464, 1465, + 5, 126, 0, 0, 1465, 1466, 5, 2, 0, 0, 1466, 1467, + 3, 234, 117, 0, 1467, 1468, 5, 3, 0, 0, 1468, 1488, + 1, 0, 0, 0, 1469, 1470, 5, 127, 0, 0, 1470, 1471, + 5, 2, 0, 0, 1471, 1472, 3, 234, 117, 0, 1472, 1473, + 5, 3, 0, 0, 1473, 1488, 1, 0, 0, 0, 1474, 1475, + 5, 128, 0, 0, 1475, 1476, 5, 2, 0, 0, 1476, 1477, + 3, 234, 117, 0, 1477, 1478, 5, 3, 0, 0, 1478, 1488, + 1, 0, 0, 0, 1479, 1480, 5, 129, 0, 0, 1480, 1481, + 5, 2, 0, 0, 1481, 1482, 3, 234, 117, 0, 1482, 1483, + 5, 3, 0, 0, 1483, 1488, 1, 0, 0, 0, 1484, 1488, + 3, 272, 136, 0, 1485, 1488, 3, 280, 140, 0, 1486, 1488, + 3, 282, 141, 0, 1487, 1233, 1, 0, 0, 0, 1487, 1234, + 1, 0, 0, 0, 1487, 1239, 1, 0, 0, 0, 1487, 1240, + 1, 0, 0, 0, 1487, 1247, 1, 0, 0, 0, 1487, 1252, + 1, 0, 0, 0, 1487, 1257, 1, 0, 0, 0, 1487, 1262, + 1, 0, 0, 0, 1487, 1267, 1, 0, 0, 0, 1487, 1275, + 1, 0, 0, 0, 1487, 1277, 1, 0, 0, 0, 1487, 1282, + 1, 0, 0, 0, 1487, 1287, 1, 0, 0, 0, 1487, 1292, + 1, 0, 0, 0, 1487, 1297, 1, 0, 0, 0, 1487, 1299, + 1, 0, 0, 0, 1487, 1300, 1, 0, 0, 0, 1487, 1305, + 1, 0, 0, 0, 1487, 1306, 1, 0, 0, 0, 1487, 1311, + 1, 0, 0, 0, 1487, 1316, 1, 0, 0, 0, 1487, 1321, + 1, 0, 0, 0, 1487, 1328, 1, 0, 0, 0, 1487, 1335, + 1, 0, 0, 0, 1487, 1342, 1, 0, 0, 0, 1487, 1349, + 1, 0, 0, 0, 1487, 1356, 1, 0, 0, 0, 1487, 1361, + 1, 0, 0, 0, 1487, 1366, 1, 0, 0, 0, 1487, 1371, + 1, 0, 0, 0, 1487, 1376, 1, 0, 0, 0, 1487, 1381, + 1, 0, 0, 0, 1487, 1386, 1, 0, 0, 0, 1487, 1391, + 1, 0, 0, 0, 1487, 1396, 1, 0, 0, 0, 1487, 1398, + 1, 0, 0, 0, 1487, 1400, 1, 0, 0, 0, 1487, 1402, + 1, 0, 0, 0, 1487, 1407, 1, 0, 0, 0, 1487, 1412, + 1, 0, 0, 0, 1487, 1417, 1, 0, 0, 0, 1487, 1422, + 1, 0, 0, 0, 1487, 1427, 1, 0, 0, 0, 1487, 1429, + 1, 0, 0, 0, 1487, 1438, 1, 0, 0, 0, 1487, 1445, + 1, 0, 0, 0, 1487, 1452, 1, 0, 0, 0, 1487, 1459, + 1, 0, 0, 0, 1487, 1464, 1, 0, 0, 0, 1487, 1469, + 1, 0, 0, 0, 1487, 1474, 1, 0, 0, 0, 1487, 1479, + 1, 0, 0, 0, 1487, 1484, 1, 0, 0, 0, 1487, 1485, + 1, 0, 0, 0, 1487, 1486, 1, 0, 0, 0, 1488, 271, + 1, 0, 0, 0, 1489, 1490, 5, 130, 0, 0, 1490, 1491, + 5, 2, 0, 0, 1491, 1492, 3, 234, 117, 0, 1492, 1493, + 5, 8, 0, 0, 1493, 1496, 3, 234, 117, 0, 1494, 1495, + 5, 8, 0, 0, 1495, 1497, 3, 234, 117, 0, 1496, 1494, + 1, 0, 0, 0, 1496, 1497, 1, 0, 0, 0, 1497, 1498, + 1, 0, 0, 0, 1498, 1499, 5, 3, 0, 0, 1499, 273, + 1, 0, 0, 0, 1500, 1501, 5, 81, 0, 0, 1501, 1502, + 5, 2, 0, 0, 1502, 1503, 3, 234, 117, 0, 1503, 1504, + 5, 3, 0, 0, 1504, 275, 1, 0, 0, 0, 1505, 1506, + 5, 131, 0, 0, 1506, 1507, 5, 2, 0, 0, 1507, 1508, + 3, 234, 117, 0, 1508, 1509, 5, 8, 0, 0, 1509, 1512, + 3, 234, 117, 0, 1510, 1511, 5, 8, 0, 0, 1511, 1513, + 3, 234, 117, 0, 1512, 1510, 1, 0, 0, 0, 1512, 1513, + 1, 0, 0, 0, 1513, 1514, 1, 0, 0, 0, 1514, 1515, + 5, 3, 0, 0, 1515, 277, 1, 0, 0, 0, 1516, 1517, + 5, 132, 0, 0, 1517, 1518, 5, 2, 0, 0, 1518, 1519, + 3, 234, 117, 0, 1519, 1520, 5, 8, 0, 0, 1520, 1521, + 3, 234, 117, 0, 1521, 1522, 5, 8, 0, 0, 1522, 1525, + 3, 234, 117, 0, 1523, 1524, 5, 8, 0, 0, 1524, 1526, + 3, 234, 117, 0, 1525, 1523, 1, 0, 0, 0, 1525, 1526, + 1, 0, 0, 0, 1526, 1527, 1, 0, 0, 0, 1527, 1528, + 5, 3, 0, 0, 1528, 279, 1, 0, 0, 0, 1529, 1530, + 5, 133, 0, 0, 1530, 1531, 3, 110, 55, 0, 1531, 281, + 1, 0, 0, 0, 1532, 1533, 5, 78, 0, 0, 1533, 1534, + 5, 133, 0, 0, 1534, 1535, 3, 110, 55, 0, 1535, 283, + 1, 0, 0, 0, 1536, 1537, 5, 134, 0, 0, 1537, 1539, + 5, 2, 0, 0, 1538, 1540, 5, 33, 0, 0, 1539, 1538, + 1, 0, 0, 0, 1539, 1540, 1, 0, 0, 0, 1540, 1543, + 1, 0, 0, 0, 1541, 1544, 5, 1, 0, 0, 1542, 1544, + 3, 234, 117, 0, 1543, 1541, 1, 0, 0, 0, 1543, 1542, + 1, 0, 0, 0, 1544, 1545, 1, 0, 0, 0, 1545, 1601, + 5, 3, 0, 0, 1546, 1547, 5, 135, 0, 0, 1547, 1549, + 5, 2, 0, 0, 1548, 1550, 5, 33, 0, 0, 1549, 1548, + 1, 0, 0, 0, 1549, 1550, 1, 0, 0, 0, 1550, 1551, + 1, 0, 0, 0, 1551, 1552, 3, 234, 117, 0, 1552, 1553, + 5, 3, 0, 0, 1553, 1601, 1, 0, 0, 0, 1554, 1555, + 5, 136, 0, 0, 1555, 1557, 5, 2, 0, 0, 1556, 1558, + 5, 33, 0, 0, 1557, 1556, 1, 0, 0, 0, 1557, 1558, + 1, 0, 0, 0, 1558, 1559, 1, 0, 0, 0, 1559, 1560, + 3, 234, 117, 0, 1560, 1561, 5, 3, 0, 0, 1561, 1601, + 1, 0, 0, 0, 1562, 1563, 5, 137, 0, 0, 1563, 1565, + 5, 2, 0, 0, 1564, 1566, 5, 33, 0, 0, 1565, 1564, + 1, 0, 0, 0, 1565, 1566, 1, 0, 0, 0, 1566, 1567, + 1, 0, 0, 0, 1567, 1568, 3, 234, 117, 0, 1568, 1569, + 5, 3, 0, 0, 1569, 1601, 1, 0, 0, 0, 1570, 1571, + 5, 138, 0, 0, 1571, 1573, 5, 2, 0, 0, 1572, 1574, + 5, 33, 0, 0, 1573, 1572, 1, 0, 0, 0, 1573, 1574, + 1, 0, 0, 0, 1574, 1575, 1, 0, 0, 0, 1575, 1576, + 3, 234, 117, 0, 1576, 1577, 5, 3, 0, 0, 1577, 1601, + 1, 0, 0, 0, 1578, 1579, 5, 139, 0, 0, 1579, 1581, + 5, 2, 0, 0, 1580, 1582, 5, 33, 0, 0, 1581, 1580, + 1, 0, 0, 0, 1581, 1582, 1, 0, 0, 0, 1582, 1583, + 1, 0, 0, 0, 1583, 1584, 3, 234, 117, 0, 1584, 1585, + 5, 3, 0, 0, 1585, 1601, 1, 0, 0, 0, 1586, 1587, + 5, 43, 0, 0, 1587, 1589, 5, 2, 0, 0, 1588, 1590, + 5, 33, 0, 0, 1589, 1588, 1, 0, 0, 0, 1589, 1590, + 1, 0, 0, 0, 1590, 1591, 1, 0, 0, 0, 1591, 1596, + 3, 234, 117, 0, 1592, 1593, 5, 6, 0, 0, 1593, 1594, + 5, 140, 0, 0, 1594, 1595, 5, 20, 0, 0, 1595, 1597, + 3, 300, 150, 0, 1596, 1592, 1, 0, 0, 0, 1596, 1597, + 1, 0, 0, 0, 1597, 1598, 1, 0, 0, 0, 1598, 1599, + 5, 3, 0, 0, 1599, 1601, 1, 0, 0, 0, 1600, 1536, + 1, 0, 0, 0, 1600, 1546, 1, 0, 0, 0, 1600, 1554, + 1, 0, 0, 0, 1600, 1562, 1, 0, 0, 0, 1600, 1570, + 1, 0, 0, 0, 1600, 1578, 1, 0, 0, 0, 1600, 1586, + 1, 0, 0, 0, 1601, 285, 1, 0, 0, 0, 1602, 1604, + 3, 302, 151, 0, 1603, 1605, 3, 150, 75, 0, 1604, 1603, + 1, 0, 0, 0, 1604, 1605, 1, 0, 0, 0, 1605, 287, + 1, 0, 0, 0, 1606, 1610, 3, 300, 150, 0, 1607, 1611, + 5, 147, 0, 0, 1608, 1609, 5, 27, 0, 0, 1609, 1611, + 3, 302, 151, 0, 1610, 1607, 1, 0, 0, 0, 1610, 1608, + 1, 0, 0, 0, 1610, 1611, 1, 0, 0, 0, 1611, 289, + 1, 0, 0, 0, 1612, 1616, 3, 292, 146, 0, 1613, 1616, + 3, 294, 147, 0, 1614, 1616, 3, 296, 148, 0, 1615, 1612, + 1, 0, 0, 0, 1615, 1613, 1, 0, 0, 0, 1615, 1614, + 1, 0, 0, 0, 1616, 291, 1, 0, 0, 0, 1617, 1618, + 7, 4, 0, 0, 1618, 293, 1, 0, 0, 0, 1619, 1620, + 7, 5, 0, 0, 1620, 295, 1, 0, 0, 0, 1621, 1622, + 7, 6, 0, 0, 1622, 297, 1, 0, 0, 0, 1623, 1624, + 7, 7, 0, 0, 1624, 299, 1, 0, 0, 0, 1625, 1626, + 7, 8, 0, 0, 1626, 301, 1, 0, 0, 0, 1627, 1629, + 5, 148, 0, 0, 1628, 1627, 1, 0, 0, 0, 1628, 1629, + 1, 0, 0, 0, 1629, 1632, 1, 0, 0, 0, 1630, 1633, + 3, 308, 154, 0, 1631, 1633, 3, 304, 152, 0, 1632, 1630, + 1, 0, 0, 0, 1632, 1631, 1, 0, 0, 0, 1633, 303, + 1, 0, 0, 0, 1634, 1637, 3, 310, 155, 0, 1635, 1637, + 3, 312, 156, 0, 1636, 1634, 1, 0, 0, 0, 1636, 1635, + 1, 0, 0, 0, 1637, 305, 1, 0, 0, 0, 1638, 1639, + 7, 9, 0, 0, 1639, 307, 1, 0, 0, 0, 1640, 1641, + 5, 141, 0, 0, 1641, 309, 1, 0, 0, 0, 1642, 1643, + 5, 143, 0, 0, 1643, 311, 1, 0, 0, 0, 1644, 1645, + 5, 142, 0, 0, 1645, 313, 1, 0, 0, 0, 161, 318, + 325, 331, 333, 347, 360, 365, 368, 372, 387, 396, 402, 406, + 412, 415, 420, 424, 432, 441, 451, 456, 459, 462, 465, 471, + 479, 484, 490, 496, 501, 507, 509, 513, 516, 520, 523, 527, + 530, 534, 537, 541, 544, 548, 551, 553, 566, 572, 574, 587, + 591, 596, 600, 606, 612, 618, 626, 634, 654, 658, 661, 666, + 682, 687, 696, 707, 711, 714, 718, 725, 732, 734, 739, 744, + 749, 754, 757, 762, 764, 774, 785, 802, 809, 819, 823, 829, + 838, 843, 850, 860, 869, 877, 884, 889, 898, 903, 907, 914, + 916, 924, 927, 935, 939, 944, 951, 962, 965, 970, 974, 989, + 996, 1008, 1016, 1021, 1026, 1038, 1047, 1050, 1053, 1060, 1062, 1068, + 1076, 1086, 1094, 1100, 1104, 1108, 1112, 1122, 1131, 1139, 1162, 1170, + 1178, 1186, 1191, 1198, 1203, 1218, 1227, 1273, 1487, 1496, 1512, 1525, + 1539, 1543, 1549, 1557, 1565, 1573, 1581, 1589, 1596, 1600, 1604, 1610, + 1615, 1628, 1632, 1636}; staticData->serializedATN = antlr4::atn::SerializedATNView( serializedATNSegment, sizeof(serializedATNSegment) / sizeof(serializedATNSegment[0])); @@ -1461,6 +1642,98 @@ antlr4::atn::SerializedATNView SparqlAutomaticParser::getSerializedATN() const { return sparqlautomaticParserStaticData->serializedATN; } +//----------------- QueryOrUpdateContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::QueryOrUpdateContext::QueryOrUpdateContext( + ParserRuleContext* parent, size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +SparqlAutomaticParser::QueryContext* +SparqlAutomaticParser::QueryOrUpdateContext::query() { + return getRuleContext(0); +} + +SparqlAutomaticParser::UpdateContext* +SparqlAutomaticParser::QueryOrUpdateContext::update() { + return getRuleContext(0); +} + +tree::TerminalNode* SparqlAutomaticParser::QueryOrUpdateContext::EOF() { + return getToken(SparqlAutomaticParser::EOF, 0); +} + +size_t SparqlAutomaticParser::QueryOrUpdateContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleQueryOrUpdate; +} + +void SparqlAutomaticParser::QueryOrUpdateContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterQueryOrUpdate(this); +} + +void SparqlAutomaticParser::QueryOrUpdateContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitQueryOrUpdate(this); +} + +std::any SparqlAutomaticParser::QueryOrUpdateContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitQueryOrUpdate(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::QueryOrUpdateContext* +SparqlAutomaticParser::queryOrUpdate() { + QueryOrUpdateContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 0, SparqlAutomaticParser::RuleQueryOrUpdate); + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + setState(318); + _errHandler->sync(this); + switch (getInterpreter()->adaptivePredict( + _input, 0, _ctx)) { + case 1: { + enterOuterAlt(_localctx, 1); + setState(314); + query(); + break; + } + + case 2: { + enterOuterAlt(_localctx, 2); + setState(315); + update(); + setState(316); + match(SparqlAutomaticParser::EOF); + break; + } + + default: + break; + } + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + //----------------- QueryContext //------------------------------------------------------------------ @@ -1478,10 +1751,6 @@ SparqlAutomaticParser::QueryContext::valuesClause() { return getRuleContext(0); } -tree::TerminalNode* SparqlAutomaticParser::QueryContext::EOF() { - return getToken(SparqlAutomaticParser::EOF, 0); -} - SparqlAutomaticParser::SelectQueryContext* SparqlAutomaticParser::QueryContext::selectQuery() { return getRuleContext(0); @@ -1529,7 +1798,7 @@ std::any SparqlAutomaticParser::QueryContext::accept( SparqlAutomaticParser::QueryContext* SparqlAutomaticParser::query() { QueryContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 0, SparqlAutomaticParser::RuleQuery); + enterRule(_localctx, 2, SparqlAutomaticParser::RuleQuery); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -1540,31 +1809,31 @@ SparqlAutomaticParser::QueryContext* SparqlAutomaticParser::query() { }); try { enterOuterAlt(_localctx, 1); - setState(266); + setState(320); prologue(); - setState(271); + setState(325); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::SELECT: { - setState(267); + setState(321); selectQuery(); break; } case SparqlAutomaticParser::CONSTRUCT: { - setState(268); + setState(322); constructQuery(); break; } case SparqlAutomaticParser::DESCRIBE: { - setState(269); + setState(323); describeQuery(); break; } case SparqlAutomaticParser::ASK: { - setState(270); + setState(324); askQuery(); break; } @@ -1572,10 +1841,8 @@ SparqlAutomaticParser::QueryContext* SparqlAutomaticParser::query() { default: throw NoViableAltException(this); } - setState(273); + setState(327); valuesClause(); - setState(274); - match(SparqlAutomaticParser::EOF); } catch (RecognitionException& e) { _errHandler->reportError(this, e); @@ -1640,7 +1907,7 @@ std::any SparqlAutomaticParser::PrologueContext::accept( SparqlAutomaticParser::PrologueContext* SparqlAutomaticParser::prologue() { PrologueContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 2, SparqlAutomaticParser::RulePrologue); + enterRule(_localctx, 4, SparqlAutomaticParser::RulePrologue); size_t _la = 0; #if __cplusplus > 201703L @@ -1652,23 +1919,23 @@ SparqlAutomaticParser::PrologueContext* SparqlAutomaticParser::prologue() { }); try { enterOuterAlt(_localctx, 1); - setState(280); + setState(333); _errHandler->sync(this); _la = _input->LA(1); while (_la == SparqlAutomaticParser::BASE || _la == SparqlAutomaticParser::PREFIX) { - setState(278); + setState(331); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::BASE: { - setState(276); + setState(329); baseDecl(); break; } case SparqlAutomaticParser::PREFIX: { - setState(277); + setState(330); prefixDecl(); break; } @@ -1676,7 +1943,7 @@ SparqlAutomaticParser::PrologueContext* SparqlAutomaticParser::prologue() { default: throw NoViableAltException(this); } - setState(282); + setState(335); _errHandler->sync(this); _la = _input->LA(1); } @@ -1733,7 +2000,7 @@ std::any SparqlAutomaticParser::BaseDeclContext::accept( SparqlAutomaticParser::BaseDeclContext* SparqlAutomaticParser::baseDecl() { BaseDeclContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 4, SparqlAutomaticParser::RuleBaseDecl); + enterRule(_localctx, 6, SparqlAutomaticParser::RuleBaseDecl); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -1744,9 +2011,9 @@ SparqlAutomaticParser::BaseDeclContext* SparqlAutomaticParser::baseDecl() { }); try { enterOuterAlt(_localctx, 1); - setState(283); + setState(336); match(SparqlAutomaticParser::BASE); - setState(284); + setState(337); iriref(); } catch (RecognitionException& e) { @@ -1805,7 +2072,7 @@ std::any SparqlAutomaticParser::PrefixDeclContext::accept( SparqlAutomaticParser::PrefixDeclContext* SparqlAutomaticParser::prefixDecl() { PrefixDeclContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 6, SparqlAutomaticParser::RulePrefixDecl); + enterRule(_localctx, 8, SparqlAutomaticParser::RulePrefixDecl); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -1816,11 +2083,11 @@ SparqlAutomaticParser::PrefixDeclContext* SparqlAutomaticParser::prefixDecl() { }); try { enterOuterAlt(_localctx, 1); - setState(286); + setState(339); match(SparqlAutomaticParser::PREFIX); - setState(287); + setState(340); match(SparqlAutomaticParser::PNAME_NS); - setState(288); + setState(341); iriref(); } catch (RecognitionException& e) { @@ -1892,7 +2159,7 @@ SparqlAutomaticParser::SelectQueryContext* SparqlAutomaticParser::selectQuery() { SelectQueryContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 8, SparqlAutomaticParser::RuleSelectQuery); + enterRule(_localctx, 10, SparqlAutomaticParser::RuleSelectQuery); size_t _la = 0; #if __cplusplus > 201703L @@ -1904,21 +2171,21 @@ SparqlAutomaticParser::selectQuery() { }); try { enterOuterAlt(_localctx, 1); - setState(290); + setState(343); selectClause(); - setState(294); + setState(347); _errHandler->sync(this); _la = _input->LA(1); while (_la == SparqlAutomaticParser::FROM) { - setState(291); + setState(344); datasetClause(); - setState(296); + setState(349); _errHandler->sync(this); _la = _input->LA(1); } - setState(297); + setState(350); whereClause(); - setState(298); + setState(351); solutionModifier(); } catch (RecognitionException& e) { @@ -1984,7 +2251,7 @@ std::any SparqlAutomaticParser::SubSelectContext::accept( SparqlAutomaticParser::SubSelectContext* SparqlAutomaticParser::subSelect() { SubSelectContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 10, SparqlAutomaticParser::RuleSubSelect); + enterRule(_localctx, 12, SparqlAutomaticParser::RuleSubSelect); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -1995,13 +2262,13 @@ SparqlAutomaticParser::SubSelectContext* SparqlAutomaticParser::subSelect() { }); try { enterOuterAlt(_localctx, 1); - setState(300); + setState(353); selectClause(); - setState(301); + setState(354); whereClause(); - setState(302); + setState(355); solutionModifier(); - setState(303); + setState(356); valuesClause(); } catch (RecognitionException& e) { @@ -2070,7 +2337,7 @@ SparqlAutomaticParser::SelectClauseContext* SparqlAutomaticParser::selectClause() { SelectClauseContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 12, SparqlAutomaticParser::RuleSelectClause); + enterRule(_localctx, 14, SparqlAutomaticParser::RuleSelectClause); size_t _la = 0; #if __cplusplus > 201703L @@ -2082,16 +2349,16 @@ SparqlAutomaticParser::selectClause() { }); try { enterOuterAlt(_localctx, 1); - setState(305); + setState(358); match(SparqlAutomaticParser::SELECT); - setState(307); + setState(360); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::DISTINCT || _la == SparqlAutomaticParser::REDUCED) { - setState(306); + setState(359); _la = _input->LA(1); if (!(_la == SparqlAutomaticParser::DISTINCT @@ -2102,19 +2369,19 @@ SparqlAutomaticParser::selectClause() { consume(); } } - setState(315); + setState(368); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__1: case SparqlAutomaticParser::VAR1: case SparqlAutomaticParser::VAR2: { - setState(310); + setState(363); _errHandler->sync(this); _la = _input->LA(1); do { - setState(309); + setState(362); varOrAlias(); - setState(312); + setState(365); _errHandler->sync(this); _la = _input->LA(1); } while (_la == SparqlAutomaticParser::T__1 || @@ -2125,7 +2392,7 @@ SparqlAutomaticParser::selectClause() { } case SparqlAutomaticParser::T__0: { - setState(314); + setState(367); antlrcpp::downCast(_localctx)->asterisk = match(SparqlAutomaticParser::T__0); break; @@ -2188,7 +2455,7 @@ std::any SparqlAutomaticParser::VarOrAliasContext::accept( SparqlAutomaticParser::VarOrAliasContext* SparqlAutomaticParser::varOrAlias() { VarOrAliasContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 14, SparqlAutomaticParser::RuleVarOrAlias); + enterRule(_localctx, 16, SparqlAutomaticParser::RuleVarOrAlias); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -2198,20 +2465,20 @@ SparqlAutomaticParser::VarOrAliasContext* SparqlAutomaticParser::varOrAlias() { exitRule(); }); try { - setState(319); + setState(372); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::VAR1: case SparqlAutomaticParser::VAR2: { enterOuterAlt(_localctx, 1); - setState(317); + setState(370); var(); break; } case SparqlAutomaticParser::T__1: { enterOuterAlt(_localctx, 2); - setState(318); + setState(371); alias(); break; } @@ -2268,7 +2535,7 @@ std::any SparqlAutomaticParser::AliasContext::accept( SparqlAutomaticParser::AliasContext* SparqlAutomaticParser::alias() { AliasContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 16, SparqlAutomaticParser::RuleAlias); + enterRule(_localctx, 18, SparqlAutomaticParser::RuleAlias); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -2279,11 +2546,11 @@ SparqlAutomaticParser::AliasContext* SparqlAutomaticParser::alias() { }); try { enterOuterAlt(_localctx, 1); - setState(321); + setState(374); match(SparqlAutomaticParser::T__1); - setState(322); + setState(375); aliasWithoutBrackets(); - setState(323); + setState(376); match(SparqlAutomaticParser::T__2); } catch (RecognitionException& e) { @@ -2346,7 +2613,7 @@ SparqlAutomaticParser::AliasWithoutBracketsContext* SparqlAutomaticParser::aliasWithoutBrackets() { AliasWithoutBracketsContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 18, SparqlAutomaticParser::RuleAliasWithoutBrackets); + enterRule(_localctx, 20, SparqlAutomaticParser::RuleAliasWithoutBrackets); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -2357,11 +2624,11 @@ SparqlAutomaticParser::aliasWithoutBrackets() { }); try { enterOuterAlt(_localctx, 1); - setState(325); + setState(378); expression(); - setState(326); + setState(379); match(SparqlAutomaticParser::AS); - setState(327); + setState(380); var(); } catch (RecognitionException& e) { @@ -2446,7 +2713,7 @@ SparqlAutomaticParser::ConstructQueryContext* SparqlAutomaticParser::constructQuery() { ConstructQueryContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 20, SparqlAutomaticParser::RuleConstructQuery); + enterRule(_localctx, 22, SparqlAutomaticParser::RuleConstructQuery); size_t _la = 0; #if __cplusplus > 201703L @@ -2458,60 +2725,60 @@ SparqlAutomaticParser::constructQuery() { }); try { enterOuterAlt(_localctx, 1); - setState(329); + setState(382); match(SparqlAutomaticParser::CONSTRUCT); - setState(353); + setState(406); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__3: { - setState(330); + setState(383); constructTemplate(); - setState(334); + setState(387); _errHandler->sync(this); _la = _input->LA(1); while (_la == SparqlAutomaticParser::FROM) { - setState(331); + setState(384); datasetClause(); - setState(336); + setState(389); _errHandler->sync(this); _la = _input->LA(1); } - setState(337); + setState(390); whereClause(); - setState(338); + setState(391); solutionModifier(); break; } case SparqlAutomaticParser::WHERE: case SparqlAutomaticParser::FROM: { - setState(343); + setState(396); _errHandler->sync(this); _la = _input->LA(1); while (_la == SparqlAutomaticParser::FROM) { - setState(340); + setState(393); datasetClause(); - setState(345); + setState(398); _errHandler->sync(this); _la = _input->LA(1); } - setState(346); + setState(399); match(SparqlAutomaticParser::WHERE); - setState(347); + setState(400); match(SparqlAutomaticParser::T__3); - setState(349); + setState(402); _errHandler->sync(this); _la = _input->LA(1); if (((_la & ~0x3fULL) == 0) && ((1ULL << _la) & 805371908) != 0 || - (((_la - 139) & ~0x3fULL) == 0) && - ((1ULL << (_la - 139)) & 29228991) != 0) { - setState(348); + (((_la - 141) & ~0x3fULL) == 0) && + ((1ULL << (_la - 141)) & 29228991) != 0) { + setState(401); triplesTemplate(); } - setState(351); + setState(404); match(SparqlAutomaticParser::T__4); - setState(352); + setState(405); solutionModifier(); break; } @@ -2598,7 +2865,7 @@ SparqlAutomaticParser::DescribeQueryContext* SparqlAutomaticParser::describeQuery() { DescribeQueryContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 22, SparqlAutomaticParser::RuleDescribeQuery); + enterRule(_localctx, 24, SparqlAutomaticParser::RuleDescribeQuery); size_t _la = 0; #if __cplusplus > 201703L @@ -2610,9 +2877,9 @@ SparqlAutomaticParser::describeQuery() { }); try { enterOuterAlt(_localctx, 1); - setState(355); + setState(408); match(SparqlAutomaticParser::DESCRIBE); - setState(362); + setState(415); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::IRI_REF: @@ -2621,22 +2888,22 @@ SparqlAutomaticParser::describeQuery() { case SparqlAutomaticParser::VAR1: case SparqlAutomaticParser::VAR2: case SparqlAutomaticParser::PREFIX_LANGTAG: { - setState(357); + setState(410); _errHandler->sync(this); _la = _input->LA(1); do { - setState(356); + setState(409); varOrIri(); - setState(359); + setState(412); _errHandler->sync(this); _la = _input->LA(1); - } while ((((_la - 139) & ~0x3fULL) == 0) && - ((1ULL << (_la - 139)) & 183) != 0); + } while ((((_la - 141) & ~0x3fULL) == 0) && + ((1ULL << (_la - 141)) & 183) != 0); break; } case SparqlAutomaticParser::T__0: { - setState(361); + setState(414); match(SparqlAutomaticParser::T__0); break; } @@ -2644,27 +2911,27 @@ SparqlAutomaticParser::describeQuery() { default: throw NoViableAltException(this); } - setState(367); + setState(420); _errHandler->sync(this); _la = _input->LA(1); while (_la == SparqlAutomaticParser::FROM) { - setState(364); + setState(417); datasetClause(); - setState(369); + setState(422); _errHandler->sync(this); _la = _input->LA(1); } - setState(371); + setState(424); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::T__3 || _la == SparqlAutomaticParser::WHERE) { - setState(370); + setState(423); whereClause(); } - setState(373); + setState(426); solutionModifier(); } catch (RecognitionException& e) { @@ -2734,7 +3001,7 @@ std::any SparqlAutomaticParser::AskQueryContext::accept( SparqlAutomaticParser::AskQueryContext* SparqlAutomaticParser::askQuery() { AskQueryContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 24, SparqlAutomaticParser::RuleAskQuery); + enterRule(_localctx, 26, SparqlAutomaticParser::RuleAskQuery); size_t _la = 0; #if __cplusplus > 201703L @@ -2746,21 +3013,21 @@ SparqlAutomaticParser::AskQueryContext* SparqlAutomaticParser::askQuery() { }); try { enterOuterAlt(_localctx, 1); - setState(375); + setState(428); match(SparqlAutomaticParser::ASK); - setState(379); + setState(432); _errHandler->sync(this); _la = _input->LA(1); while (_la == SparqlAutomaticParser::FROM) { - setState(376); + setState(429); datasetClause(); - setState(381); + setState(434); _errHandler->sync(this); _la = _input->LA(1); } - setState(382); + setState(435); whereClause(); - setState(383); + setState(436); solutionModifier(); } catch (RecognitionException& e) { @@ -2821,7 +3088,7 @@ SparqlAutomaticParser::DatasetClauseContext* SparqlAutomaticParser::datasetClause() { DatasetClauseContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 26, SparqlAutomaticParser::RuleDatasetClause); + enterRule(_localctx, 28, SparqlAutomaticParser::RuleDatasetClause); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -2832,22 +3099,22 @@ SparqlAutomaticParser::datasetClause() { }); try { enterOuterAlt(_localctx, 1); - setState(385); + setState(438); match(SparqlAutomaticParser::FROM); - setState(388); + setState(441); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::IRI_REF: case SparqlAutomaticParser::PNAME_NS: case SparqlAutomaticParser::PNAME_LN: case SparqlAutomaticParser::PREFIX_LANGTAG: { - setState(386); + setState(439); defaultGraphClause(); break; } case SparqlAutomaticParser::NAMED: { - setState(387); + setState(440); namedGraphClause(); break; } @@ -2905,7 +3172,7 @@ SparqlAutomaticParser::DefaultGraphClauseContext* SparqlAutomaticParser::defaultGraphClause() { DefaultGraphClauseContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 28, SparqlAutomaticParser::RuleDefaultGraphClause); + enterRule(_localctx, 30, SparqlAutomaticParser::RuleDefaultGraphClause); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -2916,7 +3183,7 @@ SparqlAutomaticParser::defaultGraphClause() { }); try { enterOuterAlt(_localctx, 1); - setState(390); + setState(443); sourceSelector(); } catch (RecognitionException& e) { @@ -2972,7 +3239,7 @@ SparqlAutomaticParser::NamedGraphClauseContext* SparqlAutomaticParser::namedGraphClause() { NamedGraphClauseContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 30, SparqlAutomaticParser::RuleNamedGraphClause); + enterRule(_localctx, 32, SparqlAutomaticParser::RuleNamedGraphClause); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -2983,9 +3250,9 @@ SparqlAutomaticParser::namedGraphClause() { }); try { enterOuterAlt(_localctx, 1); - setState(392); + setState(445); match(SparqlAutomaticParser::NAMED); - setState(393); + setState(446); sourceSelector(); } catch (RecognitionException& e) { @@ -3037,7 +3304,7 @@ SparqlAutomaticParser::SourceSelectorContext* SparqlAutomaticParser::sourceSelector() { SourceSelectorContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 32, SparqlAutomaticParser::RuleSourceSelector); + enterRule(_localctx, 34, SparqlAutomaticParser::RuleSourceSelector); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -3048,7 +3315,7 @@ SparqlAutomaticParser::sourceSelector() { }); try { enterOuterAlt(_localctx, 1); - setState(395); + setState(448); iri(); } catch (RecognitionException& e) { @@ -3104,7 +3371,7 @@ SparqlAutomaticParser::WhereClauseContext* SparqlAutomaticParser::whereClause() { WhereClauseContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 34, SparqlAutomaticParser::RuleWhereClause); + enterRule(_localctx, 36, SparqlAutomaticParser::RuleWhereClause); size_t _la = 0; #if __cplusplus > 201703L @@ -3116,15 +3383,15 @@ SparqlAutomaticParser::whereClause() { }); try { enterOuterAlt(_localctx, 1); - setState(398); + setState(451); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::WHERE) { - setState(397); + setState(450); match(SparqlAutomaticParser::WHERE); } - setState(400); + setState(453); groupGraphPattern(); } catch (RecognitionException& e) { @@ -3191,7 +3458,7 @@ SparqlAutomaticParser::SolutionModifierContext* SparqlAutomaticParser::solutionModifier() { SolutionModifierContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 36, SparqlAutomaticParser::RuleSolutionModifier); + enterRule(_localctx, 38, SparqlAutomaticParser::RuleSolutionModifier); size_t _la = 0; #if __cplusplus > 201703L @@ -3203,38 +3470,38 @@ SparqlAutomaticParser::solutionModifier() { }); try { enterOuterAlt(_localctx, 1); - setState(403); + setState(456); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::GROUPBY) { - setState(402); + setState(455); groupClause(); } - setState(406); + setState(459); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::HAVING) { - setState(405); + setState(458); havingClause(); } - setState(409); + setState(462); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::ORDERBY || _la == SparqlAutomaticParser::INTERNALSORTBY) { - setState(408); + setState(461); orderClause(); } - setState(412); + setState(465); _errHandler->sync(this); _la = _input->LA(1); if (((_la & ~0x3fULL) == 0) && ((1ULL << _la) & 3940649673949184) != 0) { - setState(411); + setState(464); limitOffsetClauses(); } @@ -3296,7 +3563,7 @@ SparqlAutomaticParser::GroupClauseContext* SparqlAutomaticParser::groupClause() { GroupClauseContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 38, SparqlAutomaticParser::RuleGroupClause); + enterRule(_localctx, 40, SparqlAutomaticParser::RuleGroupClause); size_t _la = 0; #if __cplusplus > 201703L @@ -3308,24 +3575,24 @@ SparqlAutomaticParser::groupClause() { }); try { enterOuterAlt(_localctx, 1); - setState(414); + setState(467); match(SparqlAutomaticParser::GROUPBY); - setState(416); + setState(469); _errHandler->sync(this); _la = _input->LA(1); do { - setState(415); + setState(468); groupCondition(); - setState(418); + setState(471); _errHandler->sync(this); _la = _input->LA(1); } while (_la == SparqlAutomaticParser::T__1 || _la == SparqlAutomaticParser::GROUP_CONCAT || - (((_la - 76) & ~0x3fULL) == 0) && - ((1ULL << (_la - 76)) & -4611686018428436483) != 0 || - (((_la - 140) & ~0x3fULL) == 0) && - ((1ULL << (_la - 140)) & 91) != 0); + (((_la - 78) & ~0x3fULL) == 0) && + ((1ULL << (_la - 78)) & -4611686018428436483) != 0 || + (((_la - 142) & ~0x3fULL) == 0) && + ((1ULL << (_la - 142)) & 91) != 0); } catch (RecognitionException& e) { _errHandler->reportError(this, e); @@ -3395,7 +3662,7 @@ SparqlAutomaticParser::GroupConditionContext* SparqlAutomaticParser::groupCondition() { GroupConditionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 40, SparqlAutomaticParser::RuleGroupCondition); + enterRule(_localctx, 42, SparqlAutomaticParser::RuleGroupCondition); size_t _la = 0; #if __cplusplus > 201703L @@ -3406,7 +3673,7 @@ SparqlAutomaticParser::groupCondition() { exitRule(); }); try { - setState(431); + setState(484); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::GROUP_CONCAT: @@ -3471,7 +3738,7 @@ SparqlAutomaticParser::groupCondition() { case SparqlAutomaticParser::AVG: case SparqlAutomaticParser::SAMPLE: { enterOuterAlt(_localctx, 1); - setState(420); + setState(473); builtInCall(); break; } @@ -3481,28 +3748,28 @@ SparqlAutomaticParser::groupCondition() { case SparqlAutomaticParser::PNAME_LN: case SparqlAutomaticParser::PREFIX_LANGTAG: { enterOuterAlt(_localctx, 2); - setState(421); + setState(474); functionCall(); break; } case SparqlAutomaticParser::T__1: { enterOuterAlt(_localctx, 3); - setState(422); + setState(475); match(SparqlAutomaticParser::T__1); - setState(423); + setState(476); expression(); - setState(426); + setState(479); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::AS) { - setState(424); + setState(477); match(SparqlAutomaticParser::AS); - setState(425); + setState(478); var(); } - setState(428); + setState(481); match(SparqlAutomaticParser::T__2); break; } @@ -3510,7 +3777,7 @@ SparqlAutomaticParser::groupCondition() { case SparqlAutomaticParser::VAR1: case SparqlAutomaticParser::VAR2: { enterOuterAlt(_localctx, 4); - setState(430); + setState(483); var(); break; } @@ -3577,7 +3844,7 @@ SparqlAutomaticParser::HavingClauseContext* SparqlAutomaticParser::havingClause() { HavingClauseContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 42, SparqlAutomaticParser::RuleHavingClause); + enterRule(_localctx, 44, SparqlAutomaticParser::RuleHavingClause); size_t _la = 0; #if __cplusplus > 201703L @@ -3589,24 +3856,24 @@ SparqlAutomaticParser::havingClause() { }); try { enterOuterAlt(_localctx, 1); - setState(433); + setState(486); match(SparqlAutomaticParser::HAVING); - setState(435); + setState(488); _errHandler->sync(this); _la = _input->LA(1); do { - setState(434); + setState(487); havingCondition(); - setState(437); + setState(490); _errHandler->sync(this); _la = _input->LA(1); } while (_la == SparqlAutomaticParser::T__1 || _la == SparqlAutomaticParser::GROUP_CONCAT || - (((_la - 76) & ~0x3fULL) == 0) && - ((1ULL << (_la - 76)) & -4611686018428436483) != 0 || - (((_la - 140) & ~0x3fULL) == 0) && - ((1ULL << (_la - 140)) & 67) != 0); + (((_la - 78) & ~0x3fULL) == 0) && + ((1ULL << (_la - 78)) & -4611686018428436483) != 0 || + (((_la - 142) & ~0x3fULL) == 0) && + ((1ULL << (_la - 142)) & 67) != 0); } catch (RecognitionException& e) { _errHandler->reportError(this, e); @@ -3657,7 +3924,7 @@ SparqlAutomaticParser::HavingConditionContext* SparqlAutomaticParser::havingCondition() { HavingConditionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 44, SparqlAutomaticParser::RuleHavingCondition); + enterRule(_localctx, 46, SparqlAutomaticParser::RuleHavingCondition); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -3668,7 +3935,7 @@ SparqlAutomaticParser::havingCondition() { }); try { enterOuterAlt(_localctx, 1); - setState(439); + setState(492); constraint(); } catch (RecognitionException& e) { @@ -3734,7 +4001,7 @@ SparqlAutomaticParser::OrderClauseContext* SparqlAutomaticParser::orderClause() { OrderClauseContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 46, SparqlAutomaticParser::RuleOrderClause); + enterRule(_localctx, 48, SparqlAutomaticParser::RuleOrderClause); size_t _la = 0; #if __cplusplus > 201703L @@ -3746,18 +4013,18 @@ SparqlAutomaticParser::orderClause() { }); try { enterOuterAlt(_localctx, 1); - setState(443); + setState(496); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::ORDERBY: { - setState(441); + setState(494); antlrcpp::downCast(_localctx)->orderBy = match(SparqlAutomaticParser::ORDERBY); break; } case SparqlAutomaticParser::INTERNALSORTBY: { - setState(442); + setState(495); antlrcpp::downCast(_localctx)->internalSortBy = match(SparqlAutomaticParser::INTERNALSORTBY); break; @@ -3766,20 +4033,20 @@ SparqlAutomaticParser::orderClause() { default: throw NoViableAltException(this); } - setState(446); + setState(499); _errHandler->sync(this); _la = _input->LA(1); do { - setState(445); + setState(498); orderCondition(); - setState(448); + setState(501); _errHandler->sync(this); _la = _input->LA(1); } while ( ((_la & ~0x3fULL) == 0) && ((1ULL << _la) & 431008558088196) != 0 || - (((_la - 76) & ~0x3fULL) == 0) && - ((1ULL << (_la - 76)) & -4611686018428436483) != 0 || - (((_la - 140) & ~0x3fULL) == 0) && ((1ULL << (_la - 140)) & 91) != 0); + (((_la - 78) & ~0x3fULL) == 0) && + ((1ULL << (_la - 78)) & -4611686018428436483) != 0 || + (((_la - 142) & ~0x3fULL) == 0) && ((1ULL << (_la - 142)) & 91) != 0); } catch (RecognitionException& e) { _errHandler->reportError(this, e); @@ -3848,7 +4115,7 @@ SparqlAutomaticParser::OrderConditionContext* SparqlAutomaticParser::orderCondition() { OrderConditionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 48, SparqlAutomaticParser::RuleOrderCondition); + enterRule(_localctx, 50, SparqlAutomaticParser::RuleOrderCondition); size_t _la = 0; #if __cplusplus > 201703L @@ -3859,13 +4126,13 @@ SparqlAutomaticParser::orderCondition() { exitRule(); }); try { - setState(456); + setState(509); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::ASC: case SparqlAutomaticParser::DESC: { enterOuterAlt(_localctx, 1); - setState(450); + setState(503); _la = _input->LA(1); if (!(_la == SparqlAutomaticParser::ASC @@ -3875,7 +4142,7 @@ SparqlAutomaticParser::orderCondition() { _errHandler->reportMatch(this); consume(); } - setState(451); + setState(504); brackettedExpression(); break; } @@ -3949,7 +4216,7 @@ SparqlAutomaticParser::orderCondition() { case SparqlAutomaticParser::VAR2: case SparqlAutomaticParser::PREFIX_LANGTAG: { enterOuterAlt(_localctx, 2); - setState(454); + setState(507); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__1: @@ -4018,14 +4285,14 @@ SparqlAutomaticParser::orderCondition() { case SparqlAutomaticParser::PNAME_NS: case SparqlAutomaticParser::PNAME_LN: case SparqlAutomaticParser::PREFIX_LANGTAG: { - setState(452); + setState(505); constraint(); break; } case SparqlAutomaticParser::VAR1: case SparqlAutomaticParser::VAR2: { - setState(453); + setState(506); var(); break; } @@ -4099,7 +4366,7 @@ SparqlAutomaticParser::LimitOffsetClausesContext* SparqlAutomaticParser::limitOffsetClauses() { LimitOffsetClausesContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 50, SparqlAutomaticParser::RuleLimitOffsetClauses); + enterRule(_localctx, 52, SparqlAutomaticParser::RuleLimitOffsetClauses); size_t _la = 0; #if __cplusplus > 201703L @@ -4110,28 +4377,28 @@ SparqlAutomaticParser::limitOffsetClauses() { exitRule(); }); try { - setState(500); + setState(553); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict( - _input, 43, _ctx)) { + _input, 44, _ctx)) { case 1: { enterOuterAlt(_localctx, 1); - setState(458); + setState(511); limitClause(); - setState(460); + setState(513); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::OFFSET) { - setState(459); + setState(512); offsetClause(); } - setState(463); + setState(516); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::TEXTLIMIT) { - setState(462); + setState(515); textLimitClause(); } break; @@ -4139,22 +4406,22 @@ SparqlAutomaticParser::limitOffsetClauses() { case 2: { enterOuterAlt(_localctx, 2); - setState(465); + setState(518); limitClause(); - setState(467); + setState(520); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::TEXTLIMIT) { - setState(466); + setState(519); textLimitClause(); } - setState(470); + setState(523); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::OFFSET) { - setState(469); + setState(522); offsetClause(); } break; @@ -4162,22 +4429,22 @@ SparqlAutomaticParser::limitOffsetClauses() { case 3: { enterOuterAlt(_localctx, 3); - setState(472); + setState(525); offsetClause(); - setState(474); + setState(527); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::LIMIT) { - setState(473); + setState(526); limitClause(); } - setState(477); + setState(530); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::TEXTLIMIT) { - setState(476); + setState(529); textLimitClause(); } break; @@ -4185,22 +4452,22 @@ SparqlAutomaticParser::limitOffsetClauses() { case 4: { enterOuterAlt(_localctx, 4); - setState(479); + setState(532); offsetClause(); - setState(481); + setState(534); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::TEXTLIMIT) { - setState(480); + setState(533); textLimitClause(); } - setState(484); + setState(537); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::LIMIT) { - setState(483); + setState(536); limitClause(); } break; @@ -4208,22 +4475,22 @@ SparqlAutomaticParser::limitOffsetClauses() { case 5: { enterOuterAlt(_localctx, 5); - setState(486); + setState(539); textLimitClause(); - setState(488); + setState(541); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::OFFSET) { - setState(487); + setState(540); offsetClause(); } - setState(491); + setState(544); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::LIMIT) { - setState(490); + setState(543); limitClause(); } break; @@ -4231,22 +4498,22 @@ SparqlAutomaticParser::limitOffsetClauses() { case 6: { enterOuterAlt(_localctx, 6); - setState(493); + setState(546); textLimitClause(); - setState(495); + setState(548); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::LIMIT) { - setState(494); + setState(547); limitClause(); } - setState(498); + setState(551); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::OFFSET) { - setState(497); + setState(550); offsetClause(); } break; @@ -4305,11 +4572,2060 @@ std::any SparqlAutomaticParser::LimitClauseContext::accept( return visitor->visitChildren(this); } -SparqlAutomaticParser::LimitClauseContext* -SparqlAutomaticParser::limitClause() { - LimitClauseContext* _localctx = - _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 52, SparqlAutomaticParser::RuleLimitClause); +SparqlAutomaticParser::LimitClauseContext* +SparqlAutomaticParser::limitClause() { + LimitClauseContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 54, SparqlAutomaticParser::RuleLimitClause); + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(555); + match(SparqlAutomaticParser::LIMIT); + setState(556); + integer(); + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- OffsetClauseContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::OffsetClauseContext::OffsetClauseContext( + ParserRuleContext* parent, size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +tree::TerminalNode* SparqlAutomaticParser::OffsetClauseContext::OFFSET() { + return getToken(SparqlAutomaticParser::OFFSET, 0); +} + +SparqlAutomaticParser::IntegerContext* +SparqlAutomaticParser::OffsetClauseContext::integer() { + return getRuleContext(0); +} + +size_t SparqlAutomaticParser::OffsetClauseContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleOffsetClause; +} + +void SparqlAutomaticParser::OffsetClauseContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterOffsetClause(this); +} + +void SparqlAutomaticParser::OffsetClauseContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitOffsetClause(this); +} + +std::any SparqlAutomaticParser::OffsetClauseContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitOffsetClause(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::OffsetClauseContext* +SparqlAutomaticParser::offsetClause() { + OffsetClauseContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 56, SparqlAutomaticParser::RuleOffsetClause); + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(558); + match(SparqlAutomaticParser::OFFSET); + setState(559); + integer(); + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- TextLimitClauseContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::TextLimitClauseContext::TextLimitClauseContext( + ParserRuleContext* parent, size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +tree::TerminalNode* SparqlAutomaticParser::TextLimitClauseContext::TEXTLIMIT() { + return getToken(SparqlAutomaticParser::TEXTLIMIT, 0); +} + +SparqlAutomaticParser::IntegerContext* +SparqlAutomaticParser::TextLimitClauseContext::integer() { + return getRuleContext(0); +} + +size_t SparqlAutomaticParser::TextLimitClauseContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleTextLimitClause; +} + +void SparqlAutomaticParser::TextLimitClauseContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterTextLimitClause(this); +} + +void SparqlAutomaticParser::TextLimitClauseContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitTextLimitClause(this); +} + +std::any SparqlAutomaticParser::TextLimitClauseContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitTextLimitClause(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::TextLimitClauseContext* +SparqlAutomaticParser::textLimitClause() { + TextLimitClauseContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 58, SparqlAutomaticParser::RuleTextLimitClause); + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(561); + match(SparqlAutomaticParser::TEXTLIMIT); + setState(562); + integer(); + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- ValuesClauseContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::ValuesClauseContext::ValuesClauseContext( + ParserRuleContext* parent, size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +tree::TerminalNode* SparqlAutomaticParser::ValuesClauseContext::VALUES() { + return getToken(SparqlAutomaticParser::VALUES, 0); +} + +SparqlAutomaticParser::DataBlockContext* +SparqlAutomaticParser::ValuesClauseContext::dataBlock() { + return getRuleContext(0); +} + +size_t SparqlAutomaticParser::ValuesClauseContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleValuesClause; +} + +void SparqlAutomaticParser::ValuesClauseContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterValuesClause(this); +} + +void SparqlAutomaticParser::ValuesClauseContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitValuesClause(this); +} + +std::any SparqlAutomaticParser::ValuesClauseContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitValuesClause(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::ValuesClauseContext* +SparqlAutomaticParser::valuesClause() { + ValuesClauseContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 60, SparqlAutomaticParser::RuleValuesClause); + size_t _la = 0; + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(566); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == SparqlAutomaticParser::VALUES) { + setState(564); + match(SparqlAutomaticParser::VALUES); + setState(565); + dataBlock(); + } + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- UpdateContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::UpdateContext::UpdateContext(ParserRuleContext* parent, + size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +SparqlAutomaticParser::PrologueContext* +SparqlAutomaticParser::UpdateContext::prologue() { + return getRuleContext(0); +} + +SparqlAutomaticParser::Update1Context* +SparqlAutomaticParser::UpdateContext::update1() { + return getRuleContext(0); +} + +SparqlAutomaticParser::UpdateContext* +SparqlAutomaticParser::UpdateContext::update() { + return getRuleContext(0); +} + +size_t SparqlAutomaticParser::UpdateContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleUpdate; +} + +void SparqlAutomaticParser::UpdateContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterUpdate(this); +} + +void SparqlAutomaticParser::UpdateContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitUpdate(this); +} + +std::any SparqlAutomaticParser::UpdateContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitUpdate(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::UpdateContext* SparqlAutomaticParser::update() { + UpdateContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 62, SparqlAutomaticParser::RuleUpdate); + size_t _la = 0; + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(568); + prologue(); + setState(574); + _errHandler->sync(this); + + _la = _input->LA(1); + if ((((_la - 53) & ~0x3fULL) == 0) && ((1ULL << (_la - 53)) & 15993) != 0) { + setState(569); + update1(); + setState(572); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == SparqlAutomaticParser::T__5) { + setState(570); + match(SparqlAutomaticParser::T__5); + setState(571); + update(); + } + } + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- Update1Context +//------------------------------------------------------------------ + +SparqlAutomaticParser::Update1Context::Update1Context(ParserRuleContext* parent, + size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +SparqlAutomaticParser::LoadContext* +SparqlAutomaticParser::Update1Context::load() { + return getRuleContext(0); +} + +SparqlAutomaticParser::ClearContext* +SparqlAutomaticParser::Update1Context::clear() { + return getRuleContext(0); +} + +SparqlAutomaticParser::DropContext* +SparqlAutomaticParser::Update1Context::drop() { + return getRuleContext(0); +} + +SparqlAutomaticParser::AddContext* +SparqlAutomaticParser::Update1Context::add() { + return getRuleContext(0); +} + +SparqlAutomaticParser::MoveContext* +SparqlAutomaticParser::Update1Context::move() { + return getRuleContext(0); +} + +SparqlAutomaticParser::CopyContext* +SparqlAutomaticParser::Update1Context::copy() { + return getRuleContext(0); +} + +SparqlAutomaticParser::CreateContext* +SparqlAutomaticParser::Update1Context::create() { + return getRuleContext(0); +} + +SparqlAutomaticParser::InsertDataContext* +SparqlAutomaticParser::Update1Context::insertData() { + return getRuleContext(0); +} + +SparqlAutomaticParser::DeleteDataContext* +SparqlAutomaticParser::Update1Context::deleteData() { + return getRuleContext(0); +} + +SparqlAutomaticParser::DeleteWhereContext* +SparqlAutomaticParser::Update1Context::deleteWhere() { + return getRuleContext(0); +} + +SparqlAutomaticParser::ModifyContext* +SparqlAutomaticParser::Update1Context::modify() { + return getRuleContext(0); +} + +size_t SparqlAutomaticParser::Update1Context::getRuleIndex() const { + return SparqlAutomaticParser::RuleUpdate1; +} + +void SparqlAutomaticParser::Update1Context::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterUpdate1(this); +} + +void SparqlAutomaticParser::Update1Context::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitUpdate1(this); +} + +std::any SparqlAutomaticParser::Update1Context::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitUpdate1(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::Update1Context* SparqlAutomaticParser::update1() { + Update1Context* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 64, SparqlAutomaticParser::RuleUpdate1); + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + setState(587); + _errHandler->sync(this); + switch (getInterpreter()->adaptivePredict( + _input, 48, _ctx)) { + case 1: { + enterOuterAlt(_localctx, 1); + setState(576); + load(); + break; + } + + case 2: { + enterOuterAlt(_localctx, 2); + setState(577); + clear(); + break; + } + + case 3: { + enterOuterAlt(_localctx, 3); + setState(578); + drop(); + break; + } + + case 4: { + enterOuterAlt(_localctx, 4); + setState(579); + add(); + break; + } + + case 5: { + enterOuterAlt(_localctx, 5); + setState(580); + move(); + break; + } + + case 6: { + enterOuterAlt(_localctx, 6); + setState(581); + copy(); + break; + } + + case 7: { + enterOuterAlt(_localctx, 7); + setState(582); + create(); + break; + } + + case 8: { + enterOuterAlt(_localctx, 8); + setState(583); + insertData(); + break; + } + + case 9: { + enterOuterAlt(_localctx, 9); + setState(584); + deleteData(); + break; + } + + case 10: { + enterOuterAlt(_localctx, 10); + setState(585); + deleteWhere(); + break; + } + + case 11: { + enterOuterAlt(_localctx, 11); + setState(586); + modify(); + break; + } + + default: + break; + } + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- LoadContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::LoadContext::LoadContext(ParserRuleContext* parent, + size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +tree::TerminalNode* SparqlAutomaticParser::LoadContext::LOAD() { + return getToken(SparqlAutomaticParser::LOAD, 0); +} + +SparqlAutomaticParser::IriContext* SparqlAutomaticParser::LoadContext::iri() { + return getRuleContext(0); +} + +tree::TerminalNode* SparqlAutomaticParser::LoadContext::SILENT() { + return getToken(SparqlAutomaticParser::SILENT, 0); +} + +tree::TerminalNode* SparqlAutomaticParser::LoadContext::INTO() { + return getToken(SparqlAutomaticParser::INTO, 0); +} + +SparqlAutomaticParser::GraphRefContext* +SparqlAutomaticParser::LoadContext::graphRef() { + return getRuleContext(0); +} + +size_t SparqlAutomaticParser::LoadContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleLoad; +} + +void SparqlAutomaticParser::LoadContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterLoad(this); +} + +void SparqlAutomaticParser::LoadContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitLoad(this); +} + +std::any SparqlAutomaticParser::LoadContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitLoad(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::LoadContext* SparqlAutomaticParser::load() { + LoadContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 66, SparqlAutomaticParser::RuleLoad); + size_t _la = 0; + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(589); + match(SparqlAutomaticParser::LOAD); + setState(591); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == SparqlAutomaticParser::SILENT) { + setState(590); + match(SparqlAutomaticParser::SILENT); + } + setState(593); + iri(); + setState(596); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == SparqlAutomaticParser::INTO) { + setState(594); + match(SparqlAutomaticParser::INTO); + setState(595); + graphRef(); + } + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- ClearContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::ClearContext::ClearContext(ParserRuleContext* parent, + size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +tree::TerminalNode* SparqlAutomaticParser::ClearContext::CLEAR() { + return getToken(SparqlAutomaticParser::CLEAR, 0); +} + +SparqlAutomaticParser::GraphRefAllContext* +SparqlAutomaticParser::ClearContext::graphRefAll() { + return getRuleContext(0); +} + +tree::TerminalNode* SparqlAutomaticParser::ClearContext::SILENT() { + return getToken(SparqlAutomaticParser::SILENT, 0); +} + +size_t SparqlAutomaticParser::ClearContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleClear; +} + +void SparqlAutomaticParser::ClearContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterClear(this); +} + +void SparqlAutomaticParser::ClearContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitClear(this); +} + +std::any SparqlAutomaticParser::ClearContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitClear(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::ClearContext* SparqlAutomaticParser::clear() { + ClearContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 68, SparqlAutomaticParser::RuleClear); + size_t _la = 0; + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(598); + match(SparqlAutomaticParser::CLEAR); + setState(600); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == SparqlAutomaticParser::SILENT) { + setState(599); + match(SparqlAutomaticParser::SILENT); + } + setState(602); + graphRefAll(); + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- DropContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::DropContext::DropContext(ParserRuleContext* parent, + size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +tree::TerminalNode* SparqlAutomaticParser::DropContext::DROP() { + return getToken(SparqlAutomaticParser::DROP, 0); +} + +SparqlAutomaticParser::GraphRefAllContext* +SparqlAutomaticParser::DropContext::graphRefAll() { + return getRuleContext(0); +} + +tree::TerminalNode* SparqlAutomaticParser::DropContext::SILENT() { + return getToken(SparqlAutomaticParser::SILENT, 0); +} + +size_t SparqlAutomaticParser::DropContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleDrop; +} + +void SparqlAutomaticParser::DropContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterDrop(this); +} + +void SparqlAutomaticParser::DropContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitDrop(this); +} + +std::any SparqlAutomaticParser::DropContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitDrop(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::DropContext* SparqlAutomaticParser::drop() { + DropContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 70, SparqlAutomaticParser::RuleDrop); + size_t _la = 0; + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(604); + match(SparqlAutomaticParser::DROP); + setState(606); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == SparqlAutomaticParser::SILENT) { + setState(605); + match(SparqlAutomaticParser::SILENT); + } + setState(608); + graphRefAll(); + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- CreateContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::CreateContext::CreateContext(ParserRuleContext* parent, + size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +tree::TerminalNode* SparqlAutomaticParser::CreateContext::CREATE() { + return getToken(SparqlAutomaticParser::CREATE, 0); +} + +SparqlAutomaticParser::GraphRefContext* +SparqlAutomaticParser::CreateContext::graphRef() { + return getRuleContext(0); +} + +tree::TerminalNode* SparqlAutomaticParser::CreateContext::SILENT() { + return getToken(SparqlAutomaticParser::SILENT, 0); +} + +size_t SparqlAutomaticParser::CreateContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleCreate; +} + +void SparqlAutomaticParser::CreateContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterCreate(this); +} + +void SparqlAutomaticParser::CreateContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitCreate(this); +} + +std::any SparqlAutomaticParser::CreateContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitCreate(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::CreateContext* SparqlAutomaticParser::create() { + CreateContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 72, SparqlAutomaticParser::RuleCreate); + size_t _la = 0; + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(610); + match(SparqlAutomaticParser::CREATE); + setState(612); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == SparqlAutomaticParser::SILENT) { + setState(611); + match(SparqlAutomaticParser::SILENT); + } + setState(614); + graphRef(); + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- AddContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::AddContext::AddContext(ParserRuleContext* parent, + size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +tree::TerminalNode* SparqlAutomaticParser::AddContext::ADD() { + return getToken(SparqlAutomaticParser::ADD, 0); +} + +std::vector +SparqlAutomaticParser::AddContext::graphOrDefault() { + return getRuleContexts(); +} + +SparqlAutomaticParser::GraphOrDefaultContext* +SparqlAutomaticParser::AddContext::graphOrDefault(size_t i) { + return getRuleContext(i); +} + +tree::TerminalNode* SparqlAutomaticParser::AddContext::TO() { + return getToken(SparqlAutomaticParser::TO, 0); +} + +tree::TerminalNode* SparqlAutomaticParser::AddContext::SILENT() { + return getToken(SparqlAutomaticParser::SILENT, 0); +} + +size_t SparqlAutomaticParser::AddContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleAdd; +} + +void SparqlAutomaticParser::AddContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterAdd(this); +} + +void SparqlAutomaticParser::AddContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitAdd(this); +} + +std::any SparqlAutomaticParser::AddContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitAdd(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::AddContext* SparqlAutomaticParser::add() { + AddContext* _localctx = _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 74, SparqlAutomaticParser::RuleAdd); + size_t _la = 0; + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(616); + match(SparqlAutomaticParser::ADD); + setState(618); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == SparqlAutomaticParser::SILENT) { + setState(617); + match(SparqlAutomaticParser::SILENT); + } + setState(620); + graphOrDefault(); + setState(621); + match(SparqlAutomaticParser::TO); + setState(622); + graphOrDefault(); + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- MoveContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::MoveContext::MoveContext(ParserRuleContext* parent, + size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +tree::TerminalNode* SparqlAutomaticParser::MoveContext::MOVE() { + return getToken(SparqlAutomaticParser::MOVE, 0); +} + +std::vector +SparqlAutomaticParser::MoveContext::graphOrDefault() { + return getRuleContexts(); +} + +SparqlAutomaticParser::GraphOrDefaultContext* +SparqlAutomaticParser::MoveContext::graphOrDefault(size_t i) { + return getRuleContext(i); +} + +tree::TerminalNode* SparqlAutomaticParser::MoveContext::TO() { + return getToken(SparqlAutomaticParser::TO, 0); +} + +tree::TerminalNode* SparqlAutomaticParser::MoveContext::SILENT() { + return getToken(SparqlAutomaticParser::SILENT, 0); +} + +size_t SparqlAutomaticParser::MoveContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleMove; +} + +void SparqlAutomaticParser::MoveContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterMove(this); +} + +void SparqlAutomaticParser::MoveContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitMove(this); +} + +std::any SparqlAutomaticParser::MoveContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitMove(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::MoveContext* SparqlAutomaticParser::move() { + MoveContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 76, SparqlAutomaticParser::RuleMove); + size_t _la = 0; + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(624); + match(SparqlAutomaticParser::MOVE); + setState(626); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == SparqlAutomaticParser::SILENT) { + setState(625); + match(SparqlAutomaticParser::SILENT); + } + setState(628); + graphOrDefault(); + setState(629); + match(SparqlAutomaticParser::TO); + setState(630); + graphOrDefault(); + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- CopyContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::CopyContext::CopyContext(ParserRuleContext* parent, + size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +tree::TerminalNode* SparqlAutomaticParser::CopyContext::COPY() { + return getToken(SparqlAutomaticParser::COPY, 0); +} + +std::vector +SparqlAutomaticParser::CopyContext::graphOrDefault() { + return getRuleContexts(); +} + +SparqlAutomaticParser::GraphOrDefaultContext* +SparqlAutomaticParser::CopyContext::graphOrDefault(size_t i) { + return getRuleContext(i); +} + +tree::TerminalNode* SparqlAutomaticParser::CopyContext::TO() { + return getToken(SparqlAutomaticParser::TO, 0); +} + +tree::TerminalNode* SparqlAutomaticParser::CopyContext::SILENT() { + return getToken(SparqlAutomaticParser::SILENT, 0); +} + +size_t SparqlAutomaticParser::CopyContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleCopy; +} + +void SparqlAutomaticParser::CopyContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterCopy(this); +} + +void SparqlAutomaticParser::CopyContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitCopy(this); +} + +std::any SparqlAutomaticParser::CopyContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitCopy(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::CopyContext* SparqlAutomaticParser::copy() { + CopyContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 78, SparqlAutomaticParser::RuleCopy); + size_t _la = 0; + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(632); + match(SparqlAutomaticParser::COPY); + setState(634); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == SparqlAutomaticParser::SILENT) { + setState(633); + match(SparqlAutomaticParser::SILENT); + } + setState(636); + graphOrDefault(); + setState(637); + match(SparqlAutomaticParser::TO); + setState(638); + graphOrDefault(); + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- InsertDataContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::InsertDataContext::InsertDataContext( + ParserRuleContext* parent, size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +tree::TerminalNode* SparqlAutomaticParser::InsertDataContext::INSERT() { + return getToken(SparqlAutomaticParser::INSERT, 0); +} + +tree::TerminalNode* SparqlAutomaticParser::InsertDataContext::DATA() { + return getToken(SparqlAutomaticParser::DATA, 0); +} + +SparqlAutomaticParser::QuadDataContext* +SparqlAutomaticParser::InsertDataContext::quadData() { + return getRuleContext(0); +} + +size_t SparqlAutomaticParser::InsertDataContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleInsertData; +} + +void SparqlAutomaticParser::InsertDataContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterInsertData(this); +} + +void SparqlAutomaticParser::InsertDataContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitInsertData(this); +} + +std::any SparqlAutomaticParser::InsertDataContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitInsertData(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::InsertDataContext* SparqlAutomaticParser::insertData() { + InsertDataContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 80, SparqlAutomaticParser::RuleInsertData); + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(640); + match(SparqlAutomaticParser::INSERT); + setState(641); + match(SparqlAutomaticParser::DATA); + setState(642); + quadData(); + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- DeleteDataContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::DeleteDataContext::DeleteDataContext( + ParserRuleContext* parent, size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +tree::TerminalNode* SparqlAutomaticParser::DeleteDataContext::DELETE() { + return getToken(SparqlAutomaticParser::DELETE, 0); +} + +tree::TerminalNode* SparqlAutomaticParser::DeleteDataContext::DATA() { + return getToken(SparqlAutomaticParser::DATA, 0); +} + +SparqlAutomaticParser::QuadDataContext* +SparqlAutomaticParser::DeleteDataContext::quadData() { + return getRuleContext(0); +} + +size_t SparqlAutomaticParser::DeleteDataContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleDeleteData; +} + +void SparqlAutomaticParser::DeleteDataContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterDeleteData(this); +} + +void SparqlAutomaticParser::DeleteDataContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitDeleteData(this); +} + +std::any SparqlAutomaticParser::DeleteDataContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitDeleteData(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::DeleteDataContext* SparqlAutomaticParser::deleteData() { + DeleteDataContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 82, SparqlAutomaticParser::RuleDeleteData); + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(644); + match(SparqlAutomaticParser::DELETE); + setState(645); + match(SparqlAutomaticParser::DATA); + setState(646); + quadData(); + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- DeleteWhereContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::DeleteWhereContext::DeleteWhereContext( + ParserRuleContext* parent, size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +tree::TerminalNode* SparqlAutomaticParser::DeleteWhereContext::DELETE() { + return getToken(SparqlAutomaticParser::DELETE, 0); +} + +tree::TerminalNode* SparqlAutomaticParser::DeleteWhereContext::WHERE() { + return getToken(SparqlAutomaticParser::WHERE, 0); +} + +SparqlAutomaticParser::QuadPatternContext* +SparqlAutomaticParser::DeleteWhereContext::quadPattern() { + return getRuleContext(0); +} + +size_t SparqlAutomaticParser::DeleteWhereContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleDeleteWhere; +} + +void SparqlAutomaticParser::DeleteWhereContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterDeleteWhere(this); +} + +void SparqlAutomaticParser::DeleteWhereContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitDeleteWhere(this); +} + +std::any SparqlAutomaticParser::DeleteWhereContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitDeleteWhere(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::DeleteWhereContext* +SparqlAutomaticParser::deleteWhere() { + DeleteWhereContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 84, SparqlAutomaticParser::RuleDeleteWhere); + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(648); + match(SparqlAutomaticParser::DELETE); + setState(649); + match(SparqlAutomaticParser::WHERE); + setState(650); + quadPattern(); + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- ModifyContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::ModifyContext::ModifyContext(ParserRuleContext* parent, + size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +tree::TerminalNode* SparqlAutomaticParser::ModifyContext::WHERE() { + return getToken(SparqlAutomaticParser::WHERE, 0); +} + +SparqlAutomaticParser::GroupGraphPatternContext* +SparqlAutomaticParser::ModifyContext::groupGraphPattern() { + return getRuleContext(0); +} + +SparqlAutomaticParser::DeleteClauseContext* +SparqlAutomaticParser::ModifyContext::deleteClause() { + return getRuleContext(0); +} + +SparqlAutomaticParser::InsertClauseContext* +SparqlAutomaticParser::ModifyContext::insertClause() { + return getRuleContext(0); +} + +tree::TerminalNode* SparqlAutomaticParser::ModifyContext::WITH() { + return getToken(SparqlAutomaticParser::WITH, 0); +} + +SparqlAutomaticParser::IriContext* SparqlAutomaticParser::ModifyContext::iri() { + return getRuleContext(0); +} + +std::vector +SparqlAutomaticParser::ModifyContext::usingClause() { + return getRuleContexts(); +} + +SparqlAutomaticParser::UsingClauseContext* +SparqlAutomaticParser::ModifyContext::usingClause(size_t i) { + return getRuleContext(i); +} + +size_t SparqlAutomaticParser::ModifyContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleModify; +} + +void SparqlAutomaticParser::ModifyContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterModify(this); +} + +void SparqlAutomaticParser::ModifyContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitModify(this); +} + +std::any SparqlAutomaticParser::ModifyContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitModify(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::ModifyContext* SparqlAutomaticParser::modify() { + ModifyContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 86, SparqlAutomaticParser::RuleModify); + size_t _la = 0; + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(654); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == SparqlAutomaticParser::WITH) { + setState(652); + match(SparqlAutomaticParser::WITH); + setState(653); + iri(); + } + setState(661); + _errHandler->sync(this); + switch (_input->LA(1)) { + case SparqlAutomaticParser::DELETE: { + setState(656); + deleteClause(); + setState(658); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == SparqlAutomaticParser::INSERT) { + setState(657); + insertClause(); + } + break; + } + + case SparqlAutomaticParser::INSERT: { + setState(660); + insertClause(); + break; + } + + default: + throw NoViableAltException(this); + } + setState(666); + _errHandler->sync(this); + _la = _input->LA(1); + while (_la == SparqlAutomaticParser::USING) { + setState(663); + usingClause(); + setState(668); + _errHandler->sync(this); + _la = _input->LA(1); + } + setState(669); + match(SparqlAutomaticParser::WHERE); + setState(670); + groupGraphPattern(); + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- DeleteClauseContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::DeleteClauseContext::DeleteClauseContext( + ParserRuleContext* parent, size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +tree::TerminalNode* SparqlAutomaticParser::DeleteClauseContext::DELETE() { + return getToken(SparqlAutomaticParser::DELETE, 0); +} + +SparqlAutomaticParser::QuadPatternContext* +SparqlAutomaticParser::DeleteClauseContext::quadPattern() { + return getRuleContext(0); +} + +size_t SparqlAutomaticParser::DeleteClauseContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleDeleteClause; +} + +void SparqlAutomaticParser::DeleteClauseContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterDeleteClause(this); +} + +void SparqlAutomaticParser::DeleteClauseContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitDeleteClause(this); +} + +std::any SparqlAutomaticParser::DeleteClauseContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitDeleteClause(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::DeleteClauseContext* +SparqlAutomaticParser::deleteClause() { + DeleteClauseContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 88, SparqlAutomaticParser::RuleDeleteClause); + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(672); + match(SparqlAutomaticParser::DELETE); + setState(673); + quadPattern(); + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- InsertClauseContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::InsertClauseContext::InsertClauseContext( + ParserRuleContext* parent, size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +tree::TerminalNode* SparqlAutomaticParser::InsertClauseContext::INSERT() { + return getToken(SparqlAutomaticParser::INSERT, 0); +} + +SparqlAutomaticParser::QuadPatternContext* +SparqlAutomaticParser::InsertClauseContext::quadPattern() { + return getRuleContext(0); +} + +size_t SparqlAutomaticParser::InsertClauseContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleInsertClause; +} + +void SparqlAutomaticParser::InsertClauseContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterInsertClause(this); +} + +void SparqlAutomaticParser::InsertClauseContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitInsertClause(this); +} + +std::any SparqlAutomaticParser::InsertClauseContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitInsertClause(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::InsertClauseContext* +SparqlAutomaticParser::insertClause() { + InsertClauseContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 90, SparqlAutomaticParser::RuleInsertClause); + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(675); + match(SparqlAutomaticParser::INSERT); + setState(676); + quadPattern(); + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- UsingClauseContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::UsingClauseContext::UsingClauseContext( + ParserRuleContext* parent, size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +tree::TerminalNode* SparqlAutomaticParser::UsingClauseContext::USING() { + return getToken(SparqlAutomaticParser::USING, 0); +} + +tree::TerminalNode* SparqlAutomaticParser::UsingClauseContext::IRI() { + return getToken(SparqlAutomaticParser::IRI, 0); +} + +tree::TerminalNode* SparqlAutomaticParser::UsingClauseContext::NAMED() { + return getToken(SparqlAutomaticParser::NAMED, 0); +} + +SparqlAutomaticParser::IriContext* +SparqlAutomaticParser::UsingClauseContext::iri() { + return getRuleContext(0); +} + +size_t SparqlAutomaticParser::UsingClauseContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleUsingClause; +} + +void SparqlAutomaticParser::UsingClauseContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterUsingClause(this); +} + +void SparqlAutomaticParser::UsingClauseContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitUsingClause(this); +} + +std::any SparqlAutomaticParser::UsingClauseContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitUsingClause(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::UsingClauseContext* +SparqlAutomaticParser::usingClause() { + UsingClauseContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 92, SparqlAutomaticParser::RuleUsingClause); + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(678); + match(SparqlAutomaticParser::USING); + setState(682); + _errHandler->sync(this); + switch (_input->LA(1)) { + case SparqlAutomaticParser::IRI: { + setState(679); + match(SparqlAutomaticParser::IRI); + break; + } + + case SparqlAutomaticParser::NAMED: { + setState(680); + match(SparqlAutomaticParser::NAMED); + setState(681); + iri(); + break; + } + + default: + throw NoViableAltException(this); + } + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- GraphOrDefaultContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::GraphOrDefaultContext::GraphOrDefaultContext( + ParserRuleContext* parent, size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +tree::TerminalNode* SparqlAutomaticParser::GraphOrDefaultContext::DEFAULT() { + return getToken(SparqlAutomaticParser::DEFAULT, 0); +} + +tree::TerminalNode* SparqlAutomaticParser::GraphOrDefaultContext::GRAPH() { + return getToken(SparqlAutomaticParser::GRAPH, 0); +} + +SparqlAutomaticParser::IriContext* +SparqlAutomaticParser::GraphOrDefaultContext::iri() { + return getRuleContext(0); +} + +size_t SparqlAutomaticParser::GraphOrDefaultContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleGraphOrDefault; +} + +void SparqlAutomaticParser::GraphOrDefaultContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterGraphOrDefault(this); +} + +void SparqlAutomaticParser::GraphOrDefaultContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitGraphOrDefault(this); +} + +std::any SparqlAutomaticParser::GraphOrDefaultContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitGraphOrDefault(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::GraphOrDefaultContext* +SparqlAutomaticParser::graphOrDefault() { + GraphOrDefaultContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 94, SparqlAutomaticParser::RuleGraphOrDefault); + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + setState(687); + _errHandler->sync(this); + switch (_input->LA(1)) { + case SparqlAutomaticParser::DEFAULT: { + enterOuterAlt(_localctx, 1); + setState(684); + match(SparqlAutomaticParser::DEFAULT); + break; + } + + case SparqlAutomaticParser::GRAPH: { + enterOuterAlt(_localctx, 2); + setState(685); + match(SparqlAutomaticParser::GRAPH); + setState(686); + iri(); + break; + } + + default: + throw NoViableAltException(this); + } + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- GraphRefContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::GraphRefContext::GraphRefContext( + ParserRuleContext* parent, size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +tree::TerminalNode* SparqlAutomaticParser::GraphRefContext::GRAPH() { + return getToken(SparqlAutomaticParser::GRAPH, 0); +} + +SparqlAutomaticParser::IriContext* +SparqlAutomaticParser::GraphRefContext::iri() { + return getRuleContext(0); +} + +size_t SparqlAutomaticParser::GraphRefContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleGraphRef; +} + +void SparqlAutomaticParser::GraphRefContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterGraphRef(this); +} + +void SparqlAutomaticParser::GraphRefContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitGraphRef(this); +} + +std::any SparqlAutomaticParser::GraphRefContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitGraphRef(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::GraphRefContext* SparqlAutomaticParser::graphRef() { + GraphRefContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 96, SparqlAutomaticParser::RuleGraphRef); + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(689); + match(SparqlAutomaticParser::GRAPH); + setState(690); + iri(); + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- GraphRefAllContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::GraphRefAllContext::GraphRefAllContext( + ParserRuleContext* parent, size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +SparqlAutomaticParser::GraphRefContext* +SparqlAutomaticParser::GraphRefAllContext::graphRef() { + return getRuleContext(0); +} + +tree::TerminalNode* SparqlAutomaticParser::GraphRefAllContext::DEFAULT() { + return getToken(SparqlAutomaticParser::DEFAULT, 0); +} + +tree::TerminalNode* SparqlAutomaticParser::GraphRefAllContext::NAMED() { + return getToken(SparqlAutomaticParser::NAMED, 0); +} + +tree::TerminalNode* SparqlAutomaticParser::GraphRefAllContext::ALL() { + return getToken(SparqlAutomaticParser::ALL, 0); +} + +size_t SparqlAutomaticParser::GraphRefAllContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleGraphRefAll; +} + +void SparqlAutomaticParser::GraphRefAllContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterGraphRefAll(this); +} + +void SparqlAutomaticParser::GraphRefAllContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitGraphRefAll(this); +} + +std::any SparqlAutomaticParser::GraphRefAllContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitGraphRefAll(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::GraphRefAllContext* +SparqlAutomaticParser::graphRefAll() { + GraphRefAllContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 98, SparqlAutomaticParser::RuleGraphRefAll); + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + setState(696); + _errHandler->sync(this); + switch (_input->LA(1)) { + case SparqlAutomaticParser::GRAPH: { + enterOuterAlt(_localctx, 1); + setState(692); + graphRef(); + break; + } + + case SparqlAutomaticParser::DEFAULT: { + enterOuterAlt(_localctx, 2); + setState(693); + match(SparqlAutomaticParser::DEFAULT); + break; + } + + case SparqlAutomaticParser::NAMED: { + enterOuterAlt(_localctx, 3); + setState(694); + match(SparqlAutomaticParser::NAMED); + break; + } + + case SparqlAutomaticParser::ALL: { + enterOuterAlt(_localctx, 4); + setState(695); + match(SparqlAutomaticParser::ALL); + break; + } + + default: + throw NoViableAltException(this); + } + + } catch (RecognitionException& e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- QuadPatternContext +//------------------------------------------------------------------ + +SparqlAutomaticParser::QuadPatternContext::QuadPatternContext( + ParserRuleContext* parent, size_t invokingState) + : ParserRuleContext(parent, invokingState) {} + +SparqlAutomaticParser::QuadsContext* +SparqlAutomaticParser::QuadPatternContext::quads() { + return getRuleContext(0); +} + +size_t SparqlAutomaticParser::QuadPatternContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleQuadPattern; +} + +void SparqlAutomaticParser::QuadPatternContext::enterRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->enterQuadPattern(this); +} + +void SparqlAutomaticParser::QuadPatternContext::exitRule( + tree::ParseTreeListener* listener) { + auto parserListener = dynamic_cast(listener); + if (parserListener != nullptr) parserListener->exitQuadPattern(this); +} + +std::any SparqlAutomaticParser::QuadPatternContext::accept( + tree::ParseTreeVisitor* visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitQuadPattern(this); + else + return visitor->visitChildren(this); +} + +SparqlAutomaticParser::QuadPatternContext* +SparqlAutomaticParser::quadPattern() { + QuadPatternContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 100, SparqlAutomaticParser::RuleQuadPattern); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -4320,10 +6636,12 @@ SparqlAutomaticParser::limitClause() { }); try { enterOuterAlt(_localctx, 1); - setState(502); - match(SparqlAutomaticParser::LIMIT); - setState(503); - integer(); + setState(698); + match(SparqlAutomaticParser::T__3); + setState(699); + quads(); + setState(700); + match(SparqlAutomaticParser::T__4); } catch (RecognitionException& e) { _errHandler->reportError(this, e); @@ -4334,51 +6652,46 @@ SparqlAutomaticParser::limitClause() { return _localctx; } -//----------------- OffsetClauseContext +//----------------- QuadDataContext //------------------------------------------------------------------ -SparqlAutomaticParser::OffsetClauseContext::OffsetClauseContext( +SparqlAutomaticParser::QuadDataContext::QuadDataContext( ParserRuleContext* parent, size_t invokingState) : ParserRuleContext(parent, invokingState) {} -tree::TerminalNode* SparqlAutomaticParser::OffsetClauseContext::OFFSET() { - return getToken(SparqlAutomaticParser::OFFSET, 0); -} - -SparqlAutomaticParser::IntegerContext* -SparqlAutomaticParser::OffsetClauseContext::integer() { - return getRuleContext(0); +SparqlAutomaticParser::QuadsContext* +SparqlAutomaticParser::QuadDataContext::quads() { + return getRuleContext(0); } -size_t SparqlAutomaticParser::OffsetClauseContext::getRuleIndex() const { - return SparqlAutomaticParser::RuleOffsetClause; +size_t SparqlAutomaticParser::QuadDataContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleQuadData; } -void SparqlAutomaticParser::OffsetClauseContext::enterRule( +void SparqlAutomaticParser::QuadDataContext::enterRule( tree::ParseTreeListener* listener) { auto parserListener = dynamic_cast(listener); - if (parserListener != nullptr) parserListener->enterOffsetClause(this); + if (parserListener != nullptr) parserListener->enterQuadData(this); } -void SparqlAutomaticParser::OffsetClauseContext::exitRule( +void SparqlAutomaticParser::QuadDataContext::exitRule( tree::ParseTreeListener* listener) { auto parserListener = dynamic_cast(listener); - if (parserListener != nullptr) parserListener->exitOffsetClause(this); + if (parserListener != nullptr) parserListener->exitQuadData(this); } -std::any SparqlAutomaticParser::OffsetClauseContext::accept( +std::any SparqlAutomaticParser::QuadDataContext::accept( tree::ParseTreeVisitor* visitor) { if (auto parserVisitor = dynamic_cast(visitor)) - return parserVisitor->visitOffsetClause(this); + return parserVisitor->visitQuadData(this); else return visitor->visitChildren(this); } -SparqlAutomaticParser::OffsetClauseContext* -SparqlAutomaticParser::offsetClause() { - OffsetClauseContext* _localctx = - _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 54, SparqlAutomaticParser::RuleOffsetClause); +SparqlAutomaticParser::QuadDataContext* SparqlAutomaticParser::quadData() { + QuadDataContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 102, SparqlAutomaticParser::RuleQuadData); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -4389,10 +6702,12 @@ SparqlAutomaticParser::offsetClause() { }); try { enterOuterAlt(_localctx, 1); - setState(505); - match(SparqlAutomaticParser::OFFSET); - setState(506); - integer(); + setState(702); + match(SparqlAutomaticParser::T__3); + setState(703); + quads(); + setState(704); + match(SparqlAutomaticParser::T__4); } catch (RecognitionException& e) { _errHandler->reportError(this, e); @@ -4403,51 +6718,62 @@ SparqlAutomaticParser::offsetClause() { return _localctx; } -//----------------- TextLimitClauseContext +//----------------- QuadsContext //------------------------------------------------------------------ -SparqlAutomaticParser::TextLimitClauseContext::TextLimitClauseContext( - ParserRuleContext* parent, size_t invokingState) +SparqlAutomaticParser::QuadsContext::QuadsContext(ParserRuleContext* parent, + size_t invokingState) : ParserRuleContext(parent, invokingState) {} -tree::TerminalNode* SparqlAutomaticParser::TextLimitClauseContext::TEXTLIMIT() { - return getToken(SparqlAutomaticParser::TEXTLIMIT, 0); +std::vector +SparqlAutomaticParser::QuadsContext::triplesTemplate() { + return getRuleContexts(); } -SparqlAutomaticParser::IntegerContext* -SparqlAutomaticParser::TextLimitClauseContext::integer() { - return getRuleContext(0); +SparqlAutomaticParser::TriplesTemplateContext* +SparqlAutomaticParser::QuadsContext::triplesTemplate(size_t i) { + return getRuleContext(i); } -size_t SparqlAutomaticParser::TextLimitClauseContext::getRuleIndex() const { - return SparqlAutomaticParser::RuleTextLimitClause; +std::vector +SparqlAutomaticParser::QuadsContext::quadsNotTriples() { + return getRuleContexts(); } -void SparqlAutomaticParser::TextLimitClauseContext::enterRule( +SparqlAutomaticParser::QuadsNotTriplesContext* +SparqlAutomaticParser::QuadsContext::quadsNotTriples(size_t i) { + return getRuleContext(i); +} + +size_t SparqlAutomaticParser::QuadsContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleQuads; +} + +void SparqlAutomaticParser::QuadsContext::enterRule( tree::ParseTreeListener* listener) { auto parserListener = dynamic_cast(listener); - if (parserListener != nullptr) parserListener->enterTextLimitClause(this); + if (parserListener != nullptr) parserListener->enterQuads(this); } -void SparqlAutomaticParser::TextLimitClauseContext::exitRule( +void SparqlAutomaticParser::QuadsContext::exitRule( tree::ParseTreeListener* listener) { auto parserListener = dynamic_cast(listener); - if (parserListener != nullptr) parserListener->exitTextLimitClause(this); + if (parserListener != nullptr) parserListener->exitQuads(this); } -std::any SparqlAutomaticParser::TextLimitClauseContext::accept( +std::any SparqlAutomaticParser::QuadsContext::accept( tree::ParseTreeVisitor* visitor) { if (auto parserVisitor = dynamic_cast(visitor)) - return parserVisitor->visitTextLimitClause(this); + return parserVisitor->visitQuads(this); else return visitor->visitChildren(this); } -SparqlAutomaticParser::TextLimitClauseContext* -SparqlAutomaticParser::textLimitClause() { - TextLimitClauseContext* _localctx = - _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 56, SparqlAutomaticParser::RuleTextLimitClause); +SparqlAutomaticParser::QuadsContext* SparqlAutomaticParser::quads() { + QuadsContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 104, SparqlAutomaticParser::RuleQuads); + size_t _la = 0; #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -4458,10 +6784,44 @@ SparqlAutomaticParser::textLimitClause() { }); try { enterOuterAlt(_localctx, 1); - setState(508); - match(SparqlAutomaticParser::TEXTLIMIT); - setState(509); - integer(); + setState(707); + _errHandler->sync(this); + + _la = _input->LA(1); + if (((_la & ~0x3fULL) == 0) && ((1ULL << _la) & 805371908) != 0 || + (((_la - 141) & ~0x3fULL) == 0) && + ((1ULL << (_la - 141)) & 29228991) != 0) { + setState(706); + triplesTemplate(); + } + setState(718); + _errHandler->sync(this); + _la = _input->LA(1); + while (_la == SparqlAutomaticParser::GRAPH) { + setState(709); + quadsNotTriples(); + setState(711); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == SparqlAutomaticParser::T__6) { + setState(710); + match(SparqlAutomaticParser::T__6); + } + setState(714); + _errHandler->sync(this); + + _la = _input->LA(1); + if (((_la & ~0x3fULL) == 0) && ((1ULL << _la) & 805371908) != 0 || + (((_la - 141) & ~0x3fULL) == 0) && + ((1ULL << (_la - 141)) & 29228991) != 0) { + setState(713); + triplesTemplate(); + } + setState(720); + _errHandler->sync(this); + _la = _input->LA(1); + } } catch (RecognitionException& e) { _errHandler->reportError(this, e); @@ -4472,51 +6832,56 @@ SparqlAutomaticParser::textLimitClause() { return _localctx; } -//----------------- ValuesClauseContext +//----------------- QuadsNotTriplesContext //------------------------------------------------------------------ -SparqlAutomaticParser::ValuesClauseContext::ValuesClauseContext( +SparqlAutomaticParser::QuadsNotTriplesContext::QuadsNotTriplesContext( ParserRuleContext* parent, size_t invokingState) : ParserRuleContext(parent, invokingState) {} -tree::TerminalNode* SparqlAutomaticParser::ValuesClauseContext::VALUES() { - return getToken(SparqlAutomaticParser::VALUES, 0); +tree::TerminalNode* SparqlAutomaticParser::QuadsNotTriplesContext::GRAPH() { + return getToken(SparqlAutomaticParser::GRAPH, 0); } -SparqlAutomaticParser::DataBlockContext* -SparqlAutomaticParser::ValuesClauseContext::dataBlock() { - return getRuleContext(0); +SparqlAutomaticParser::VarOrIriContext* +SparqlAutomaticParser::QuadsNotTriplesContext::varOrIri() { + return getRuleContext(0); } -size_t SparqlAutomaticParser::ValuesClauseContext::getRuleIndex() const { - return SparqlAutomaticParser::RuleValuesClause; +SparqlAutomaticParser::TriplesTemplateContext* +SparqlAutomaticParser::QuadsNotTriplesContext::triplesTemplate() { + return getRuleContext(0); } -void SparqlAutomaticParser::ValuesClauseContext::enterRule( +size_t SparqlAutomaticParser::QuadsNotTriplesContext::getRuleIndex() const { + return SparqlAutomaticParser::RuleQuadsNotTriples; +} + +void SparqlAutomaticParser::QuadsNotTriplesContext::enterRule( tree::ParseTreeListener* listener) { auto parserListener = dynamic_cast(listener); - if (parserListener != nullptr) parserListener->enterValuesClause(this); + if (parserListener != nullptr) parserListener->enterQuadsNotTriples(this); } -void SparqlAutomaticParser::ValuesClauseContext::exitRule( +void SparqlAutomaticParser::QuadsNotTriplesContext::exitRule( tree::ParseTreeListener* listener) { auto parserListener = dynamic_cast(listener); - if (parserListener != nullptr) parserListener->exitValuesClause(this); + if (parserListener != nullptr) parserListener->exitQuadsNotTriples(this); } -std::any SparqlAutomaticParser::ValuesClauseContext::accept( +std::any SparqlAutomaticParser::QuadsNotTriplesContext::accept( tree::ParseTreeVisitor* visitor) { if (auto parserVisitor = dynamic_cast(visitor)) - return parserVisitor->visitValuesClause(this); + return parserVisitor->visitQuadsNotTriples(this); else return visitor->visitChildren(this); } -SparqlAutomaticParser::ValuesClauseContext* -SparqlAutomaticParser::valuesClause() { - ValuesClauseContext* _localctx = - _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 58, SparqlAutomaticParser::RuleValuesClause); +SparqlAutomaticParser::QuadsNotTriplesContext* +SparqlAutomaticParser::quadsNotTriples() { + QuadsNotTriplesContext* _localctx = + _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 106, SparqlAutomaticParser::RuleQuadsNotTriples); size_t _la = 0; #if __cplusplus > 201703L @@ -4528,16 +6893,24 @@ SparqlAutomaticParser::valuesClause() { }); try { enterOuterAlt(_localctx, 1); - setState(513); + setState(721); + match(SparqlAutomaticParser::GRAPH); + setState(722); + varOrIri(); + setState(723); + match(SparqlAutomaticParser::T__3); + setState(725); _errHandler->sync(this); _la = _input->LA(1); - if (_la == SparqlAutomaticParser::VALUES) { - setState(511); - match(SparqlAutomaticParser::VALUES); - setState(512); - dataBlock(); + if (((_la & ~0x3fULL) == 0) && ((1ULL << _la) & 805371908) != 0 || + (((_la - 141) & ~0x3fULL) == 0) && + ((1ULL << (_la - 141)) & 29228991) != 0) { + setState(724); + triplesTemplate(); } + setState(727); + match(SparqlAutomaticParser::T__4); } catch (RecognitionException& e) { _errHandler->reportError(this, e); @@ -4593,7 +6966,7 @@ SparqlAutomaticParser::TriplesTemplateContext* SparqlAutomaticParser::triplesTemplate() { TriplesTemplateContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 60, SparqlAutomaticParser::RuleTriplesTemplate); + enterRule(_localctx, 108, SparqlAutomaticParser::RuleTriplesTemplate); size_t _la = 0; #if __cplusplus > 201703L @@ -4605,23 +6978,23 @@ SparqlAutomaticParser::triplesTemplate() { }); try { enterOuterAlt(_localctx, 1); - setState(515); + setState(729); triplesSameSubject(); - setState(520); + setState(734); _errHandler->sync(this); _la = _input->LA(1); - if (_la == SparqlAutomaticParser::T__5) { - setState(516); - match(SparqlAutomaticParser::T__5); - setState(518); + if (_la == SparqlAutomaticParser::T__6) { + setState(730); + match(SparqlAutomaticParser::T__6); + setState(732); _errHandler->sync(this); _la = _input->LA(1); if (((_la & ~0x3fULL) == 0) && ((1ULL << _la) & 805371908) != 0 || - (((_la - 139) & ~0x3fULL) == 0) && - ((1ULL << (_la - 139)) & 29228991) != 0) { - setState(517); + (((_la - 141) & ~0x3fULL) == 0) && + ((1ULL << (_la - 141)) & 29228991) != 0) { + setState(731); triplesTemplate(); } } @@ -4680,7 +7053,7 @@ SparqlAutomaticParser::GroupGraphPatternContext* SparqlAutomaticParser::groupGraphPattern() { GroupGraphPatternContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 62, SparqlAutomaticParser::RuleGroupGraphPattern); + enterRule(_localctx, 110, SparqlAutomaticParser::RuleGroupGraphPattern); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -4691,13 +7064,13 @@ SparqlAutomaticParser::groupGraphPattern() { }); try { enterOuterAlt(_localctx, 1); - setState(522); + setState(736); match(SparqlAutomaticParser::T__3); - setState(525); + setState(739); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::SELECT: { - setState(523); + setState(737); subSelect(); break; } @@ -4737,7 +7110,7 @@ SparqlAutomaticParser::groupGraphPattern() { case SparqlAutomaticParser::STRING_LITERAL_LONG2: case SparqlAutomaticParser::NIL: case SparqlAutomaticParser::ANON: { - setState(524); + setState(738); groupGraphPatternSub(); break; } @@ -4745,7 +7118,7 @@ SparqlAutomaticParser::groupGraphPattern() { default: throw NoViableAltException(this); } - setState(527); + setState(741); match(SparqlAutomaticParser::T__4); } catch (RecognitionException& e) { @@ -4814,7 +7187,7 @@ SparqlAutomaticParser::GroupGraphPatternSubContext* SparqlAutomaticParser::groupGraphPatternSub() { GroupGraphPatternSubContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 64, SparqlAutomaticParser::RuleGroupGraphPatternSub); + enterRule(_localctx, 112, SparqlAutomaticParser::RuleGroupGraphPatternSub); size_t _la = 0; #if __cplusplus > 201703L @@ -4826,27 +7199,27 @@ SparqlAutomaticParser::groupGraphPatternSub() { }); try { enterOuterAlt(_localctx, 1); - setState(530); + setState(744); _errHandler->sync(this); _la = _input->LA(1); if (((_la & ~0x3fULL) == 0) && ((1ULL << _la) & 805371908) != 0 || - (((_la - 139) & ~0x3fULL) == 0) && - ((1ULL << (_la - 139)) & 29228991) != 0) { - setState(529); + (((_la - 141) & ~0x3fULL) == 0) && + ((1ULL << (_la - 141)) & 29228991) != 0) { + setState(743); triplesBlock(); } - setState(535); + setState(749); _errHandler->sync(this); _la = _input->LA(1); while (_la == SparqlAutomaticParser::T__3 || _la == SparqlAutomaticParser::VALUES || - (((_la - 67) & ~0x3fULL) == 0) && - ((1ULL << (_la - 67)) & 349) != 0) { - setState(532); + (((_la - 69) & ~0x3fULL) == 0) && + ((1ULL << (_la - 69)) & 349) != 0) { + setState(746); graphPatternNotTriplesAndMaybeTriples(); - setState(537); + setState(751); _errHandler->sync(this); _la = _input->LA(1); } @@ -4912,7 +7285,7 @@ SparqlAutomaticParser::graphPatternNotTriplesAndMaybeTriples() { GraphPatternNotTriplesAndMaybeTriplesContext* _localctx = _tracker.createInstance( _ctx, getState()); - enterRule(_localctx, 66, + enterRule(_localctx, 114, SparqlAutomaticParser::RuleGraphPatternNotTriplesAndMaybeTriples); size_t _la = 0; @@ -4925,24 +7298,24 @@ SparqlAutomaticParser::graphPatternNotTriplesAndMaybeTriples() { }); try { enterOuterAlt(_localctx, 1); - setState(538); + setState(752); graphPatternNotTriples(); - setState(540); + setState(754); _errHandler->sync(this); _la = _input->LA(1); - if (_la == SparqlAutomaticParser::T__5) { - setState(539); - match(SparqlAutomaticParser::T__5); + if (_la == SparqlAutomaticParser::T__6) { + setState(753); + match(SparqlAutomaticParser::T__6); } - setState(543); + setState(757); _errHandler->sync(this); _la = _input->LA(1); if (((_la & ~0x3fULL) == 0) && ((1ULL << _la) & 805371908) != 0 || - (((_la - 139) & ~0x3fULL) == 0) && - ((1ULL << (_la - 139)) & 29228991) != 0) { - setState(542); + (((_la - 141) & ~0x3fULL) == 0) && + ((1ULL << (_la - 141)) & 29228991) != 0) { + setState(756); triplesBlock(); } @@ -5001,7 +7374,7 @@ SparqlAutomaticParser::TriplesBlockContext* SparqlAutomaticParser::triplesBlock() { TriplesBlockContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 68, SparqlAutomaticParser::RuleTriplesBlock); + enterRule(_localctx, 116, SparqlAutomaticParser::RuleTriplesBlock); size_t _la = 0; #if __cplusplus > 201703L @@ -5013,23 +7386,23 @@ SparqlAutomaticParser::triplesBlock() { }); try { enterOuterAlt(_localctx, 1); - setState(545); + setState(759); triplesSameSubjectPath(); - setState(550); + setState(764); _errHandler->sync(this); _la = _input->LA(1); - if (_la == SparqlAutomaticParser::T__5) { - setState(546); - match(SparqlAutomaticParser::T__5); - setState(548); + if (_la == SparqlAutomaticParser::T__6) { + setState(760); + match(SparqlAutomaticParser::T__6); + setState(762); _errHandler->sync(this); _la = _input->LA(1); if (((_la & ~0x3fULL) == 0) && ((1ULL << _la) & 805371908) != 0 || - (((_la - 139) & ~0x3fULL) == 0) && - ((1ULL << (_la - 139)) & 29228991) != 0) { - setState(547); + (((_la - 141) & ~0x3fULL) == 0) && + ((1ULL << (_la - 141)) & 29228991) != 0) { + setState(761); triplesBlock(); } } @@ -5123,7 +7496,7 @@ SparqlAutomaticParser::GraphPatternNotTriplesContext* SparqlAutomaticParser::graphPatternNotTriples() { GraphPatternNotTriplesContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 70, SparqlAutomaticParser::RuleGraphPatternNotTriples); + enterRule(_localctx, 118, SparqlAutomaticParser::RuleGraphPatternNotTriples); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -5133,61 +7506,61 @@ SparqlAutomaticParser::graphPatternNotTriples() { exitRule(); }); try { - setState(560); + setState(774); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__3: { enterOuterAlt(_localctx, 1); - setState(552); + setState(766); groupOrUnionGraphPattern(); break; } case SparqlAutomaticParser::OPTIONAL: { enterOuterAlt(_localctx, 2); - setState(553); + setState(767); optionalGraphPattern(); break; } case SparqlAutomaticParser::MINUS: { enterOuterAlt(_localctx, 3); - setState(554); + setState(768); minusGraphPattern(); break; } case SparqlAutomaticParser::GRAPH: { enterOuterAlt(_localctx, 4); - setState(555); + setState(769); graphGraphPattern(); break; } case SparqlAutomaticParser::SERVICE: { enterOuterAlt(_localctx, 5); - setState(556); + setState(770); serviceGraphPattern(); break; } case SparqlAutomaticParser::FILTER: { enterOuterAlt(_localctx, 6); - setState(557); + setState(771); filterR(); break; } case SparqlAutomaticParser::BIND: { enterOuterAlt(_localctx, 7); - setState(558); + setState(772); bind(); break; } case SparqlAutomaticParser::VALUES: { enterOuterAlt(_localctx, 8); - setState(559); + setState(773); inlineData(); break; } @@ -5252,7 +7625,7 @@ SparqlAutomaticParser::OptionalGraphPatternContext* SparqlAutomaticParser::optionalGraphPattern() { OptionalGraphPatternContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 72, SparqlAutomaticParser::RuleOptionalGraphPattern); + enterRule(_localctx, 120, SparqlAutomaticParser::RuleOptionalGraphPattern); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -5263,9 +7636,9 @@ SparqlAutomaticParser::optionalGraphPattern() { }); try { enterOuterAlt(_localctx, 1); - setState(562); + setState(776); match(SparqlAutomaticParser::OPTIONAL); - setState(563); + setState(777); groupGraphPattern(); } catch (RecognitionException& e) { @@ -5326,7 +7699,7 @@ SparqlAutomaticParser::GraphGraphPatternContext* SparqlAutomaticParser::graphGraphPattern() { GraphGraphPatternContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 74, SparqlAutomaticParser::RuleGraphGraphPattern); + enterRule(_localctx, 122, SparqlAutomaticParser::RuleGraphGraphPattern); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -5337,11 +7710,11 @@ SparqlAutomaticParser::graphGraphPattern() { }); try { enterOuterAlt(_localctx, 1); - setState(565); + setState(779); match(SparqlAutomaticParser::GRAPH); - setState(566); + setState(780); varOrIri(); - setState(567); + setState(781); groupGraphPattern(); } catch (RecognitionException& e) { @@ -5408,7 +7781,7 @@ SparqlAutomaticParser::ServiceGraphPatternContext* SparqlAutomaticParser::serviceGraphPattern() { ServiceGraphPatternContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 76, SparqlAutomaticParser::RuleServiceGraphPattern); + enterRule(_localctx, 124, SparqlAutomaticParser::RuleServiceGraphPattern); size_t _la = 0; #if __cplusplus > 201703L @@ -5420,19 +7793,19 @@ SparqlAutomaticParser::serviceGraphPattern() { }); try { enterOuterAlt(_localctx, 1); - setState(569); + setState(783); match(SparqlAutomaticParser::SERVICE); - setState(571); + setState(785); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::SILENT) { - setState(570); + setState(784); match(SparqlAutomaticParser::SILENT); } - setState(573); + setState(787); varOrIri(); - setState(574); + setState(788); groupGraphPattern(); } catch (RecognitionException& e) { @@ -5495,7 +7868,7 @@ std::any SparqlAutomaticParser::BindContext::accept( SparqlAutomaticParser::BindContext* SparqlAutomaticParser::bind() { BindContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 78, SparqlAutomaticParser::RuleBind); + enterRule(_localctx, 126, SparqlAutomaticParser::RuleBind); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -5506,17 +7879,17 @@ SparqlAutomaticParser::BindContext* SparqlAutomaticParser::bind() { }); try { enterOuterAlt(_localctx, 1); - setState(576); + setState(790); match(SparqlAutomaticParser::BIND); - setState(577); + setState(791); match(SparqlAutomaticParser::T__1); - setState(578); + setState(792); expression(); - setState(579); + setState(793); match(SparqlAutomaticParser::AS); - setState(580); + setState(794); var(); - setState(581); + setState(795); match(SparqlAutomaticParser::T__2); } catch (RecognitionException& e) { @@ -5571,7 +7944,7 @@ std::any SparqlAutomaticParser::InlineDataContext::accept( SparqlAutomaticParser::InlineDataContext* SparqlAutomaticParser::inlineData() { InlineDataContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 80, SparqlAutomaticParser::RuleInlineData); + enterRule(_localctx, 128, SparqlAutomaticParser::RuleInlineData); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -5582,9 +7955,9 @@ SparqlAutomaticParser::InlineDataContext* SparqlAutomaticParser::inlineData() { }); try { enterOuterAlt(_localctx, 1); - setState(583); + setState(797); match(SparqlAutomaticParser::VALUES); - setState(584); + setState(798); dataBlock(); } catch (RecognitionException& e) { @@ -5640,7 +8013,7 @@ std::any SparqlAutomaticParser::DataBlockContext::accept( SparqlAutomaticParser::DataBlockContext* SparqlAutomaticParser::dataBlock() { DataBlockContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 82, SparqlAutomaticParser::RuleDataBlock); + enterRule(_localctx, 130, SparqlAutomaticParser::RuleDataBlock); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -5650,13 +8023,13 @@ SparqlAutomaticParser::DataBlockContext* SparqlAutomaticParser::dataBlock() { exitRule(); }); try { - setState(588); + setState(802); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::VAR1: case SparqlAutomaticParser::VAR2: { enterOuterAlt(_localctx, 1); - setState(586); + setState(800); inlineDataOneVar(); break; } @@ -5664,7 +8037,7 @@ SparqlAutomaticParser::DataBlockContext* SparqlAutomaticParser::dataBlock() { case SparqlAutomaticParser::T__1: case SparqlAutomaticParser::NIL: { enterOuterAlt(_localctx, 2); - setState(587); + setState(801); inlineDataFull(); break; } @@ -5732,7 +8105,7 @@ SparqlAutomaticParser::InlineDataOneVarContext* SparqlAutomaticParser::inlineDataOneVar() { InlineDataOneVarContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 84, SparqlAutomaticParser::RuleInlineDataOneVar); + enterRule(_localctx, 132, SparqlAutomaticParser::RuleInlineDataOneVar); size_t _la = 0; #if __cplusplus > 201703L @@ -5744,24 +8117,24 @@ SparqlAutomaticParser::inlineDataOneVar() { }); try { enterOuterAlt(_localctx, 1); - setState(590); + setState(804); var(); - setState(591); + setState(805); match(SparqlAutomaticParser::T__3); - setState(595); + setState(809); _errHandler->sync(this); _la = _input->LA(1); while ((((_la - 28) & ~0x3fULL) == 0) && - ((1ULL << (_la - 28)) & 17592186044419) != 0 || - (((_la - 139) & ~0x3fULL) == 0) && - ((1ULL << (_la - 139)) & 4063111) != 0) { - setState(592); + ((1ULL << (_la - 28)) & 70368744177667) != 0 || + (((_la - 141) & ~0x3fULL) == 0) && + ((1ULL << (_la - 141)) & 4063111) != 0) { + setState(806); dataBlockValue(); - setState(597); + setState(811); _errHandler->sync(this); _la = _input->LA(1); } - setState(598); + setState(812); match(SparqlAutomaticParser::T__4); } catch (RecognitionException& e) { @@ -5832,7 +8205,7 @@ SparqlAutomaticParser::InlineDataFullContext* SparqlAutomaticParser::inlineDataFull() { InlineDataFullContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 86, SparqlAutomaticParser::RuleInlineDataFull); + enterRule(_localctx, 134, SparqlAutomaticParser::RuleInlineDataFull); size_t _la = 0; #if __cplusplus > 201703L @@ -5844,31 +8217,31 @@ SparqlAutomaticParser::inlineDataFull() { }); try { enterOuterAlt(_localctx, 1); - setState(609); + setState(823); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::NIL: { - setState(600); + setState(814); match(SparqlAutomaticParser::NIL); break; } case SparqlAutomaticParser::T__1: { - setState(601); + setState(815); match(SparqlAutomaticParser::T__1); - setState(605); + setState(819); _errHandler->sync(this); _la = _input->LA(1); while (_la == SparqlAutomaticParser::VAR1 || _la == SparqlAutomaticParser::VAR2) { - setState(602); + setState(816); var(); - setState(607); + setState(821); _errHandler->sync(this); _la = _input->LA(1); } - setState(608); + setState(822); match(SparqlAutomaticParser::T__2); break; } @@ -5876,20 +8249,20 @@ SparqlAutomaticParser::inlineDataFull() { default: throw NoViableAltException(this); } - setState(611); + setState(825); match(SparqlAutomaticParser::T__3); - setState(615); + setState(829); _errHandler->sync(this); _la = _input->LA(1); while (_la == SparqlAutomaticParser::T__1 || _la == SparqlAutomaticParser::NIL) { - setState(612); + setState(826); dataBlockSingle(); - setState(617); + setState(831); _errHandler->sync(this); _la = _input->LA(1); } - setState(618); + setState(832); match(SparqlAutomaticParser::T__4); } catch (RecognitionException& e) { @@ -5950,7 +8323,7 @@ SparqlAutomaticParser::DataBlockSingleContext* SparqlAutomaticParser::dataBlockSingle() { DataBlockSingleContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 88, SparqlAutomaticParser::RuleDataBlockSingle); + enterRule(_localctx, 136, SparqlAutomaticParser::RuleDataBlockSingle); size_t _la = 0; #if __cplusplus > 201703L @@ -5962,32 +8335,32 @@ SparqlAutomaticParser::dataBlockSingle() { }); try { enterOuterAlt(_localctx, 1); - setState(629); + setState(843); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__1: { - setState(620); + setState(834); match(SparqlAutomaticParser::T__1); - setState(624); + setState(838); _errHandler->sync(this); _la = _input->LA(1); while ((((_la - 28) & ~0x3fULL) == 0) && - ((1ULL << (_la - 28)) & 17592186044419) != 0 || - (((_la - 139) & ~0x3fULL) == 0) && - ((1ULL << (_la - 139)) & 4063111) != 0) { - setState(621); + ((1ULL << (_la - 28)) & 70368744177667) != 0 || + (((_la - 141) & ~0x3fULL) == 0) && + ((1ULL << (_la - 141)) & 4063111) != 0) { + setState(835); dataBlockValue(); - setState(626); + setState(840); _errHandler->sync(this); _la = _input->LA(1); } - setState(627); + setState(841); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::NIL: { - setState(628); + setState(842); match(SparqlAutomaticParser::NIL); break; } @@ -6064,7 +8437,7 @@ SparqlAutomaticParser::DataBlockValueContext* SparqlAutomaticParser::dataBlockValue() { DataBlockValueContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 90, SparqlAutomaticParser::RuleDataBlockValue); + enterRule(_localctx, 138, SparqlAutomaticParser::RuleDataBlockValue); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -6074,7 +8447,7 @@ SparqlAutomaticParser::dataBlockValue() { exitRule(); }); try { - setState(636); + setState(850); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::IRI_REF: @@ -6082,7 +8455,7 @@ SparqlAutomaticParser::dataBlockValue() { case SparqlAutomaticParser::PNAME_LN: case SparqlAutomaticParser::PREFIX_LANGTAG: { enterOuterAlt(_localctx, 1); - setState(631); + setState(845); iri(); break; } @@ -6092,7 +8465,7 @@ SparqlAutomaticParser::dataBlockValue() { case SparqlAutomaticParser::STRING_LITERAL_LONG1: case SparqlAutomaticParser::STRING_LITERAL_LONG2: { enterOuterAlt(_localctx, 2); - setState(632); + setState(846); rdfLiteral(); break; } @@ -6107,7 +8480,7 @@ SparqlAutomaticParser::dataBlockValue() { case SparqlAutomaticParser::DECIMAL_NEGATIVE: case SparqlAutomaticParser::DOUBLE_NEGATIVE: { enterOuterAlt(_localctx, 3); - setState(633); + setState(847); numericLiteral(); break; } @@ -6115,14 +8488,14 @@ SparqlAutomaticParser::dataBlockValue() { case SparqlAutomaticParser::T__27: case SparqlAutomaticParser::T__28: { enterOuterAlt(_localctx, 4); - setState(634); + setState(848); booleanLiteral(); break; } case SparqlAutomaticParser::UNDEF: { enterOuterAlt(_localctx, 5); - setState(635); + setState(849); match(SparqlAutomaticParser::UNDEF); break; } @@ -6184,7 +8557,7 @@ SparqlAutomaticParser::MinusGraphPatternContext* SparqlAutomaticParser::minusGraphPattern() { MinusGraphPatternContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 92, SparqlAutomaticParser::RuleMinusGraphPattern); + enterRule(_localctx, 140, SparqlAutomaticParser::RuleMinusGraphPattern); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -6195,9 +8568,9 @@ SparqlAutomaticParser::minusGraphPattern() { }); try { enterOuterAlt(_localctx, 1); - setState(638); + setState(852); match(SparqlAutomaticParser::MINUS); - setState(639); + setState(853); groupGraphPattern(); } catch (RecognitionException& e) { @@ -6270,7 +8643,8 @@ SparqlAutomaticParser::groupOrUnionGraphPattern() { GroupOrUnionGraphPatternContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 94, SparqlAutomaticParser::RuleGroupOrUnionGraphPattern); + enterRule(_localctx, 142, + SparqlAutomaticParser::RuleGroupOrUnionGraphPattern); size_t _la = 0; #if __cplusplus > 201703L @@ -6282,17 +8656,17 @@ SparqlAutomaticParser::groupOrUnionGraphPattern() { }); try { enterOuterAlt(_localctx, 1); - setState(641); + setState(855); groupGraphPattern(); - setState(646); + setState(860); _errHandler->sync(this); _la = _input->LA(1); while (_la == SparqlAutomaticParser::UNION) { - setState(642); + setState(856); match(SparqlAutomaticParser::UNION); - setState(643); + setState(857); groupGraphPattern(); - setState(648); + setState(862); _errHandler->sync(this); _la = _input->LA(1); } @@ -6349,7 +8723,7 @@ std::any SparqlAutomaticParser::FilterRContext::accept( SparqlAutomaticParser::FilterRContext* SparqlAutomaticParser::filterR() { FilterRContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 96, SparqlAutomaticParser::RuleFilterR); + enterRule(_localctx, 144, SparqlAutomaticParser::RuleFilterR); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -6360,9 +8734,9 @@ SparqlAutomaticParser::FilterRContext* SparqlAutomaticParser::filterR() { }); try { enterOuterAlt(_localctx, 1); - setState(649); + setState(863); match(SparqlAutomaticParser::FILTER); - setState(650); + setState(864); constraint(); } catch (RecognitionException& e) { @@ -6423,7 +8797,7 @@ std::any SparqlAutomaticParser::ConstraintContext::accept( SparqlAutomaticParser::ConstraintContext* SparqlAutomaticParser::constraint() { ConstraintContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 98, SparqlAutomaticParser::RuleConstraint); + enterRule(_localctx, 146, SparqlAutomaticParser::RuleConstraint); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -6433,12 +8807,12 @@ SparqlAutomaticParser::ConstraintContext* SparqlAutomaticParser::constraint() { exitRule(); }); try { - setState(655); + setState(869); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__1: { enterOuterAlt(_localctx, 1); - setState(652); + setState(866); brackettedExpression(); break; } @@ -6505,7 +8879,7 @@ SparqlAutomaticParser::ConstraintContext* SparqlAutomaticParser::constraint() { case SparqlAutomaticParser::AVG: case SparqlAutomaticParser::SAMPLE: { enterOuterAlt(_localctx, 2); - setState(653); + setState(867); builtInCall(); break; } @@ -6515,7 +8889,7 @@ SparqlAutomaticParser::ConstraintContext* SparqlAutomaticParser::constraint() { case SparqlAutomaticParser::PNAME_LN: case SparqlAutomaticParser::PREFIX_LANGTAG: { enterOuterAlt(_localctx, 3); - setState(654); + setState(868); functionCall(); break; } @@ -6578,7 +8952,7 @@ SparqlAutomaticParser::FunctionCallContext* SparqlAutomaticParser::functionCall() { FunctionCallContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 100, SparqlAutomaticParser::RuleFunctionCall); + enterRule(_localctx, 148, SparqlAutomaticParser::RuleFunctionCall); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -6589,9 +8963,9 @@ SparqlAutomaticParser::functionCall() { }); try { enterOuterAlt(_localctx, 1); - setState(657); + setState(871); iri(); - setState(658); + setState(872); argList(); } catch (RecognitionException& e) { @@ -6655,7 +9029,7 @@ std::any SparqlAutomaticParser::ArgListContext::accept( SparqlAutomaticParser::ArgListContext* SparqlAutomaticParser::argList() { ArgListContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 102, SparqlAutomaticParser::RuleArgList); + enterRule(_localctx, 150, SparqlAutomaticParser::RuleArgList); size_t _la = 0; #if __cplusplus > 201703L @@ -6666,43 +9040,43 @@ SparqlAutomaticParser::ArgListContext* SparqlAutomaticParser::argList() { exitRule(); }); try { - setState(675); + setState(889); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::NIL: { enterOuterAlt(_localctx, 1); - setState(660); + setState(874); match(SparqlAutomaticParser::NIL); break; } case SparqlAutomaticParser::T__1: { enterOuterAlt(_localctx, 2); - setState(661); + setState(875); match(SparqlAutomaticParser::T__1); - setState(663); + setState(877); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::DISTINCT) { - setState(662); + setState(876); match(SparqlAutomaticParser::DISTINCT); } - setState(665); + setState(879); expression(); - setState(670); + setState(884); _errHandler->sync(this); _la = _input->LA(1); - while (_la == SparqlAutomaticParser::T__6) { - setState(666); - match(SparqlAutomaticParser::T__6); - setState(667); + while (_la == SparqlAutomaticParser::T__7) { + setState(880); + match(SparqlAutomaticParser::T__7); + setState(881); expression(); - setState(672); + setState(886); _errHandler->sync(this); _la = _input->LA(1); } - setState(673); + setState(887); match(SparqlAutomaticParser::T__2); break; } @@ -6769,7 +9143,7 @@ SparqlAutomaticParser::ExpressionListContext* SparqlAutomaticParser::expressionList() { ExpressionListContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 104, SparqlAutomaticParser::RuleExpressionList); + enterRule(_localctx, 152, SparqlAutomaticParser::RuleExpressionList); size_t _la = 0; #if __cplusplus > 201703L @@ -6780,35 +9154,35 @@ SparqlAutomaticParser::expressionList() { exitRule(); }); try { - setState(689); + setState(903); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::NIL: { enterOuterAlt(_localctx, 1); - setState(677); + setState(891); match(SparqlAutomaticParser::NIL); break; } case SparqlAutomaticParser::T__1: { enterOuterAlt(_localctx, 2); - setState(678); + setState(892); match(SparqlAutomaticParser::T__1); - setState(679); + setState(893); expression(); - setState(684); + setState(898); _errHandler->sync(this); _la = _input->LA(1); - while (_la == SparqlAutomaticParser::T__6) { - setState(680); - match(SparqlAutomaticParser::T__6); - setState(681); + while (_la == SparqlAutomaticParser::T__7) { + setState(894); + match(SparqlAutomaticParser::T__7); + setState(895); expression(); - setState(686); + setState(900); _errHandler->sync(this); _la = _input->LA(1); } - setState(687); + setState(901); match(SparqlAutomaticParser::T__2); break; } @@ -6866,7 +9240,7 @@ SparqlAutomaticParser::ConstructTemplateContext* SparqlAutomaticParser::constructTemplate() { ConstructTemplateContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 106, SparqlAutomaticParser::RuleConstructTemplate); + enterRule(_localctx, 154, SparqlAutomaticParser::RuleConstructTemplate); size_t _la = 0; #if __cplusplus > 201703L @@ -6878,19 +9252,19 @@ SparqlAutomaticParser::constructTemplate() { }); try { enterOuterAlt(_localctx, 1); - setState(691); + setState(905); match(SparqlAutomaticParser::T__3); - setState(693); + setState(907); _errHandler->sync(this); _la = _input->LA(1); if (((_la & ~0x3fULL) == 0) && ((1ULL << _la) & 805371908) != 0 || - (((_la - 139) & ~0x3fULL) == 0) && - ((1ULL << (_la - 139)) & 29228991) != 0) { - setState(692); + (((_la - 141) & ~0x3fULL) == 0) && + ((1ULL << (_la - 141)) & 29228991) != 0) { + setState(906); constructTriples(); } - setState(695); + setState(909); match(SparqlAutomaticParser::T__4); } catch (RecognitionException& e) { @@ -6947,7 +9321,7 @@ SparqlAutomaticParser::ConstructTriplesContext* SparqlAutomaticParser::constructTriples() { ConstructTriplesContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 108, SparqlAutomaticParser::RuleConstructTriples); + enterRule(_localctx, 156, SparqlAutomaticParser::RuleConstructTriples); size_t _la = 0; #if __cplusplus > 201703L @@ -6959,23 +9333,23 @@ SparqlAutomaticParser::constructTriples() { }); try { enterOuterAlt(_localctx, 1); - setState(697); + setState(911); triplesSameSubject(); - setState(702); + setState(916); _errHandler->sync(this); _la = _input->LA(1); - if (_la == SparqlAutomaticParser::T__5) { - setState(698); - match(SparqlAutomaticParser::T__5); - setState(700); + if (_la == SparqlAutomaticParser::T__6) { + setState(912); + match(SparqlAutomaticParser::T__6); + setState(914); _errHandler->sync(this); _la = _input->LA(1); if (((_la & ~0x3fULL) == 0) && ((1ULL << _la) & 805371908) != 0 || - (((_la - 139) & ~0x3fULL) == 0) && - ((1ULL << (_la - 139)) & 29228991) != 0) { - setState(699); + (((_la - 141) & ~0x3fULL) == 0) && + ((1ULL << (_la - 141)) & 29228991) != 0) { + setState(913); constructTriples(); } } @@ -7044,7 +9418,7 @@ SparqlAutomaticParser::TriplesSameSubjectContext* SparqlAutomaticParser::triplesSameSubject() { TriplesSameSubjectContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 110, SparqlAutomaticParser::RuleTriplesSameSubject); + enterRule(_localctx, 158, SparqlAutomaticParser::RuleTriplesSameSubject); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -7054,7 +9428,7 @@ SparqlAutomaticParser::triplesSameSubject() { exitRule(); }); try { - setState(710); + setState(924); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__27: @@ -7082,9 +9456,9 @@ SparqlAutomaticParser::triplesSameSubject() { case SparqlAutomaticParser::NIL: case SparqlAutomaticParser::ANON: { enterOuterAlt(_localctx, 1); - setState(704); + setState(918); varOrTerm(); - setState(705); + setState(919); propertyListNotEmpty(); break; } @@ -7092,9 +9466,9 @@ SparqlAutomaticParser::triplesSameSubject() { case SparqlAutomaticParser::T__1: case SparqlAutomaticParser::T__15: { enterOuterAlt(_localctx, 2); - setState(707); + setState(921); triplesNode(); - setState(708); + setState(922); propertyList(); break; } @@ -7152,7 +9526,7 @@ SparqlAutomaticParser::PropertyListContext* SparqlAutomaticParser::propertyList() { PropertyListContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 112, SparqlAutomaticParser::RulePropertyList); + enterRule(_localctx, 160, SparqlAutomaticParser::RulePropertyList); size_t _la = 0; #if __cplusplus > 201703L @@ -7164,13 +9538,13 @@ SparqlAutomaticParser::propertyList() { }); try { enterOuterAlt(_localctx, 1); - setState(713); + setState(927); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::T__8 || - (((_la - 139) & ~0x3fULL) == 0) && ((1ULL << (_la - 139)) & 183) != 0) { - setState(712); + (((_la - 141) & ~0x3fULL) == 0) && ((1ULL << (_la - 141)) & 183) != 0) { + setState(926); propertyListNotEmpty(); } @@ -7240,7 +9614,7 @@ SparqlAutomaticParser::PropertyListNotEmptyContext* SparqlAutomaticParser::propertyListNotEmpty() { PropertyListNotEmptyContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 114, SparqlAutomaticParser::RulePropertyListNotEmpty); + enterRule(_localctx, 162, SparqlAutomaticParser::RulePropertyListNotEmpty); size_t _la = 0; #if __cplusplus > 201703L @@ -7252,29 +9626,29 @@ SparqlAutomaticParser::propertyListNotEmpty() { }); try { enterOuterAlt(_localctx, 1); - setState(715); + setState(929); verb(); - setState(716); + setState(930); objectList(); - setState(725); + setState(939); _errHandler->sync(this); _la = _input->LA(1); - while (_la == SparqlAutomaticParser::T__7) { - setState(717); - match(SparqlAutomaticParser::T__7); - setState(721); + while (_la == SparqlAutomaticParser::T__5) { + setState(931); + match(SparqlAutomaticParser::T__5); + setState(935); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::T__8 || - (((_la - 139) & ~0x3fULL) == 0) && - ((1ULL << (_la - 139)) & 183) != 0) { - setState(718); + (((_la - 141) & ~0x3fULL) == 0) && + ((1ULL << (_la - 141)) & 183) != 0) { + setState(932); verb(); - setState(719); + setState(933); objectList(); } - setState(727); + setState(941); _errHandler->sync(this); _la = _input->LA(1); } @@ -7327,7 +9701,7 @@ std::any SparqlAutomaticParser::VerbContext::accept( SparqlAutomaticParser::VerbContext* SparqlAutomaticParser::verb() { VerbContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 116, SparqlAutomaticParser::RuleVerb); + enterRule(_localctx, 164, SparqlAutomaticParser::RuleVerb); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -7337,7 +9711,7 @@ SparqlAutomaticParser::VerbContext* SparqlAutomaticParser::verb() { exitRule(); }); try { - setState(730); + setState(944); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::IRI_REF: @@ -7347,14 +9721,14 @@ SparqlAutomaticParser::VerbContext* SparqlAutomaticParser::verb() { case SparqlAutomaticParser::VAR2: case SparqlAutomaticParser::PREFIX_LANGTAG: { enterOuterAlt(_localctx, 1); - setState(728); + setState(942); varOrIri(); break; } case SparqlAutomaticParser::T__8: { enterOuterAlt(_localctx, 2); - setState(729); + setState(943); match(SparqlAutomaticParser::T__8); break; } @@ -7416,7 +9790,7 @@ std::any SparqlAutomaticParser::ObjectListContext::accept( SparqlAutomaticParser::ObjectListContext* SparqlAutomaticParser::objectList() { ObjectListContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 118, SparqlAutomaticParser::RuleObjectList); + enterRule(_localctx, 166, SparqlAutomaticParser::RuleObjectList); size_t _la = 0; #if __cplusplus > 201703L @@ -7428,17 +9802,17 @@ SparqlAutomaticParser::ObjectListContext* SparqlAutomaticParser::objectList() { }); try { enterOuterAlt(_localctx, 1); - setState(732); + setState(946); objectR(); - setState(737); + setState(951); _errHandler->sync(this); _la = _input->LA(1); - while (_la == SparqlAutomaticParser::T__6) { - setState(733); - match(SparqlAutomaticParser::T__6); - setState(734); + while (_la == SparqlAutomaticParser::T__7) { + setState(947); + match(SparqlAutomaticParser::T__7); + setState(948); objectR(); - setState(739); + setState(953); _errHandler->sync(this); _la = _input->LA(1); } @@ -7491,7 +9865,7 @@ std::any SparqlAutomaticParser::ObjectRContext::accept( SparqlAutomaticParser::ObjectRContext* SparqlAutomaticParser::objectR() { ObjectRContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 120, SparqlAutomaticParser::RuleObjectR); + enterRule(_localctx, 168, SparqlAutomaticParser::RuleObjectR); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -7502,7 +9876,7 @@ SparqlAutomaticParser::ObjectRContext* SparqlAutomaticParser::objectR() { }); try { enterOuterAlt(_localctx, 1); - setState(740); + setState(954); graphNode(); } catch (RecognitionException& e) { @@ -7574,7 +9948,7 @@ SparqlAutomaticParser::TriplesSameSubjectPathContext* SparqlAutomaticParser::triplesSameSubjectPath() { TriplesSameSubjectPathContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 122, SparqlAutomaticParser::RuleTriplesSameSubjectPath); + enterRule(_localctx, 170, SparqlAutomaticParser::RuleTriplesSameSubjectPath); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -7584,7 +9958,7 @@ SparqlAutomaticParser::triplesSameSubjectPath() { exitRule(); }); try { - setState(748); + setState(962); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__27: @@ -7612,9 +9986,9 @@ SparqlAutomaticParser::triplesSameSubjectPath() { case SparqlAutomaticParser::NIL: case SparqlAutomaticParser::ANON: { enterOuterAlt(_localctx, 1); - setState(742); + setState(956); varOrTerm(); - setState(743); + setState(957); propertyListPathNotEmpty(); break; } @@ -7622,9 +9996,9 @@ SparqlAutomaticParser::triplesSameSubjectPath() { case SparqlAutomaticParser::T__1: case SparqlAutomaticParser::T__15: { enterOuterAlt(_localctx, 2); - setState(745); + setState(959); triplesNodePath(); - setState(746); + setState(960); propertyListPath(); break; } @@ -7683,7 +10057,7 @@ SparqlAutomaticParser::PropertyListPathContext* SparqlAutomaticParser::propertyListPath() { PropertyListPathContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 124, SparqlAutomaticParser::RulePropertyListPath); + enterRule(_localctx, 172, SparqlAutomaticParser::RulePropertyListPath); size_t _la = 0; #if __cplusplus > 201703L @@ -7695,13 +10069,13 @@ SparqlAutomaticParser::propertyListPath() { }); try { enterOuterAlt(_localctx, 1); - setState(751); + setState(965); _errHandler->sync(this); _la = _input->LA(1); if (((_la & ~0x3fULL) == 0) && ((1ULL << _la) & 37380) != 0 || - (((_la - 139) & ~0x3fULL) == 0) && ((1ULL << (_la - 139)) & 183) != 0) { - setState(750); + (((_la - 141) & ~0x3fULL) == 0) && ((1ULL << (_la - 141)) & 183) != 0) { + setState(964); propertyListPathNotEmpty(); } @@ -7770,7 +10144,7 @@ SparqlAutomaticParser::propertyListPathNotEmpty() { PropertyListPathNotEmptyContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 126, + enterRule(_localctx, 174, SparqlAutomaticParser::RulePropertyListPathNotEmpty); size_t _la = 0; @@ -7783,25 +10157,25 @@ SparqlAutomaticParser::propertyListPathNotEmpty() { }); try { enterOuterAlt(_localctx, 1); - setState(753); + setState(967); tupleWithPath(); - setState(760); + setState(974); _errHandler->sync(this); _la = _input->LA(1); - while (_la == SparqlAutomaticParser::T__7) { - setState(754); - match(SparqlAutomaticParser::T__7); - setState(756); + while (_la == SparqlAutomaticParser::T__5) { + setState(968); + match(SparqlAutomaticParser::T__5); + setState(970); _errHandler->sync(this); _la = _input->LA(1); if (((_la & ~0x3fULL) == 0) && ((1ULL << _la) & 37380) != 0 || - (((_la - 139) & ~0x3fULL) == 0) && - ((1ULL << (_la - 139)) & 183) != 0) { - setState(755); + (((_la - 141) & ~0x3fULL) == 0) && + ((1ULL << (_la - 141)) & 183) != 0) { + setState(969); tupleWithoutPath(); } - setState(762); + setState(976); _errHandler->sync(this); _la = _input->LA(1); } @@ -7854,7 +10228,7 @@ std::any SparqlAutomaticParser::VerbPathContext::accept( SparqlAutomaticParser::VerbPathContext* SparqlAutomaticParser::verbPath() { VerbPathContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 128, SparqlAutomaticParser::RuleVerbPath); + enterRule(_localctx, 176, SparqlAutomaticParser::RuleVerbPath); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -7865,7 +10239,7 @@ SparqlAutomaticParser::VerbPathContext* SparqlAutomaticParser::verbPath() { }); try { enterOuterAlt(_localctx, 1); - setState(763); + setState(977); path(); } catch (RecognitionException& e) { @@ -7916,7 +10290,7 @@ std::any SparqlAutomaticParser::VerbSimpleContext::accept( SparqlAutomaticParser::VerbSimpleContext* SparqlAutomaticParser::verbSimple() { VerbSimpleContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 130, SparqlAutomaticParser::RuleVerbSimple); + enterRule(_localctx, 178, SparqlAutomaticParser::RuleVerbSimple); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -7927,7 +10301,7 @@ SparqlAutomaticParser::VerbSimpleContext* SparqlAutomaticParser::verbSimple() { }); try { enterOuterAlt(_localctx, 1); - setState(765); + setState(979); var(); } catch (RecognitionException& e) { @@ -7984,7 +10358,7 @@ SparqlAutomaticParser::TupleWithoutPathContext* SparqlAutomaticParser::tupleWithoutPath() { TupleWithoutPathContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 132, SparqlAutomaticParser::RuleTupleWithoutPath); + enterRule(_localctx, 180, SparqlAutomaticParser::RuleTupleWithoutPath); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -7995,9 +10369,9 @@ SparqlAutomaticParser::tupleWithoutPath() { }); try { enterOuterAlt(_localctx, 1); - setState(767); + setState(981); verbPathOrSimple(); - setState(768); + setState(982); objectList(); } catch (RecognitionException& e) { @@ -8054,7 +10428,7 @@ SparqlAutomaticParser::TupleWithPathContext* SparqlAutomaticParser::tupleWithPath() { TupleWithPathContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 134, SparqlAutomaticParser::RuleTupleWithPath); + enterRule(_localctx, 182, SparqlAutomaticParser::RuleTupleWithPath); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -8065,9 +10439,9 @@ SparqlAutomaticParser::tupleWithPath() { }); try { enterOuterAlt(_localctx, 1); - setState(770); + setState(984); verbPathOrSimple(); - setState(771); + setState(985); objectListPath(); } catch (RecognitionException& e) { @@ -8124,7 +10498,7 @@ SparqlAutomaticParser::VerbPathOrSimpleContext* SparqlAutomaticParser::verbPathOrSimple() { VerbPathOrSimpleContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 136, SparqlAutomaticParser::RuleVerbPathOrSimple); + enterRule(_localctx, 184, SparqlAutomaticParser::RuleVerbPathOrSimple); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -8135,7 +10509,7 @@ SparqlAutomaticParser::verbPathOrSimple() { }); try { enterOuterAlt(_localctx, 1); - setState(775); + setState(989); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__1: @@ -8146,14 +10520,14 @@ SparqlAutomaticParser::verbPathOrSimple() { case SparqlAutomaticParser::PNAME_NS: case SparqlAutomaticParser::PNAME_LN: case SparqlAutomaticParser::PREFIX_LANGTAG: { - setState(773); + setState(987); verbPath(); break; } case SparqlAutomaticParser::VAR1: case SparqlAutomaticParser::VAR2: { - setState(774); + setState(988); verbSimple(); break; } @@ -8216,7 +10590,7 @@ SparqlAutomaticParser::ObjectListPathContext* SparqlAutomaticParser::objectListPath() { ObjectListPathContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 138, SparqlAutomaticParser::RuleObjectListPath); + enterRule(_localctx, 186, SparqlAutomaticParser::RuleObjectListPath); size_t _la = 0; #if __cplusplus > 201703L @@ -8228,17 +10602,17 @@ SparqlAutomaticParser::objectListPath() { }); try { enterOuterAlt(_localctx, 1); - setState(777); + setState(991); objectPath(); - setState(782); + setState(996); _errHandler->sync(this); _la = _input->LA(1); - while (_la == SparqlAutomaticParser::T__6) { - setState(778); - match(SparqlAutomaticParser::T__6); - setState(779); + while (_la == SparqlAutomaticParser::T__7) { + setState(992); + match(SparqlAutomaticParser::T__7); + setState(993); objectPath(); - setState(784); + setState(998); _errHandler->sync(this); _la = _input->LA(1); } @@ -8291,7 +10665,7 @@ std::any SparqlAutomaticParser::ObjectPathContext::accept( SparqlAutomaticParser::ObjectPathContext* SparqlAutomaticParser::objectPath() { ObjectPathContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 140, SparqlAutomaticParser::RuleObjectPath); + enterRule(_localctx, 188, SparqlAutomaticParser::RuleObjectPath); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -8302,7 +10676,7 @@ SparqlAutomaticParser::ObjectPathContext* SparqlAutomaticParser::objectPath() { }); try { enterOuterAlt(_localctx, 1); - setState(785); + setState(999); graphNodePath(); } catch (RecognitionException& e) { @@ -8353,7 +10727,7 @@ std::any SparqlAutomaticParser::PathContext::accept( SparqlAutomaticParser::PathContext* SparqlAutomaticParser::path() { PathContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 142, SparqlAutomaticParser::RulePath); + enterRule(_localctx, 190, SparqlAutomaticParser::RulePath); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -8364,7 +10738,7 @@ SparqlAutomaticParser::PathContext* SparqlAutomaticParser::path() { }); try { enterOuterAlt(_localctx, 1); - setState(787); + setState(1001); pathAlternative(); } catch (RecognitionException& e) { @@ -8421,7 +10795,7 @@ SparqlAutomaticParser::PathAlternativeContext* SparqlAutomaticParser::pathAlternative() { PathAlternativeContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 144, SparqlAutomaticParser::RulePathAlternative); + enterRule(_localctx, 192, SparqlAutomaticParser::RulePathAlternative); size_t _la = 0; #if __cplusplus > 201703L @@ -8433,17 +10807,17 @@ SparqlAutomaticParser::pathAlternative() { }); try { enterOuterAlt(_localctx, 1); - setState(789); + setState(1003); pathSequence(); - setState(794); + setState(1008); _errHandler->sync(this); _la = _input->LA(1); while (_la == SparqlAutomaticParser::T__9) { - setState(790); + setState(1004); match(SparqlAutomaticParser::T__9); - setState(791); + setState(1005); pathSequence(); - setState(796); + setState(1010); _errHandler->sync(this); _la = _input->LA(1); } @@ -8502,7 +10876,7 @@ SparqlAutomaticParser::PathSequenceContext* SparqlAutomaticParser::pathSequence() { PathSequenceContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 146, SparqlAutomaticParser::RulePathSequence); + enterRule(_localctx, 194, SparqlAutomaticParser::RulePathSequence); size_t _la = 0; #if __cplusplus > 201703L @@ -8514,17 +10888,17 @@ SparqlAutomaticParser::pathSequence() { }); try { enterOuterAlt(_localctx, 1); - setState(797); + setState(1011); pathEltOrInverse(); - setState(802); + setState(1016); _errHandler->sync(this); _la = _input->LA(1); while (_la == SparqlAutomaticParser::T__10) { - setState(798); + setState(1012); match(SparqlAutomaticParser::T__10); - setState(799); + setState(1013); pathEltOrInverse(); - setState(804); + setState(1018); _errHandler->sync(this); _la = _input->LA(1); } @@ -8582,7 +10956,7 @@ std::any SparqlAutomaticParser::PathEltContext::accept( SparqlAutomaticParser::PathEltContext* SparqlAutomaticParser::pathElt() { PathEltContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 148, SparqlAutomaticParser::RulePathElt); + enterRule(_localctx, 196, SparqlAutomaticParser::RulePathElt); size_t _la = 0; #if __cplusplus > 201703L @@ -8594,14 +10968,14 @@ SparqlAutomaticParser::PathEltContext* SparqlAutomaticParser::pathElt() { }); try { enterOuterAlt(_localctx, 1); - setState(805); + setState(1019); pathPrimary(); - setState(807); + setState(1021); _errHandler->sync(this); _la = _input->LA(1); if (((_la & ~0x3fULL) == 0) && ((1ULL << _la) & 24578) != 0) { - setState(806); + setState(1020); pathMod(); } @@ -8654,7 +11028,7 @@ SparqlAutomaticParser::PathEltOrInverseContext* SparqlAutomaticParser::pathEltOrInverse() { PathEltOrInverseContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 150, SparqlAutomaticParser::RulePathEltOrInverse); + enterRule(_localctx, 198, SparqlAutomaticParser::RulePathEltOrInverse); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -8664,7 +11038,7 @@ SparqlAutomaticParser::pathEltOrInverse() { exitRule(); }); try { - setState(812); + setState(1026); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__1: @@ -8675,17 +11049,17 @@ SparqlAutomaticParser::pathEltOrInverse() { case SparqlAutomaticParser::PNAME_LN: case SparqlAutomaticParser::PREFIX_LANGTAG: { enterOuterAlt(_localctx, 1); - setState(809); + setState(1023); pathElt(); break; } case SparqlAutomaticParser::T__11: { enterOuterAlt(_localctx, 2); - setState(810); + setState(1024); antlrcpp::downCast(_localctx) ->negationOperator = match(SparqlAutomaticParser::T__11); - setState(811); + setState(1025); pathElt(); break; } @@ -8737,7 +11111,7 @@ std::any SparqlAutomaticParser::PathModContext::accept( SparqlAutomaticParser::PathModContext* SparqlAutomaticParser::pathMod() { PathModContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 152, SparqlAutomaticParser::RulePathMod); + enterRule(_localctx, 200, SparqlAutomaticParser::RulePathMod); size_t _la = 0; #if __cplusplus > 201703L @@ -8749,7 +11123,7 @@ SparqlAutomaticParser::PathModContext* SparqlAutomaticParser::pathMod() { }); try { enterOuterAlt(_localctx, 1); - setState(814); + setState(1028); _la = _input->LA(1); if (!(((_la & ~0x3fULL) == 0) && ((1ULL << _la) & 24578) != 0)) { _errHandler->recoverInline(this); @@ -8818,7 +11192,7 @@ SparqlAutomaticParser::PathPrimaryContext* SparqlAutomaticParser::pathPrimary() { PathPrimaryContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 154, SparqlAutomaticParser::RulePathPrimary); + enterRule(_localctx, 202, SparqlAutomaticParser::RulePathPrimary); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -8828,7 +11202,7 @@ SparqlAutomaticParser::pathPrimary() { exitRule(); }); try { - setState(824); + setState(1038); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::IRI_REF: @@ -8836,34 +11210,34 @@ SparqlAutomaticParser::pathPrimary() { case SparqlAutomaticParser::PNAME_LN: case SparqlAutomaticParser::PREFIX_LANGTAG: { enterOuterAlt(_localctx, 1); - setState(816); + setState(1030); iri(); break; } case SparqlAutomaticParser::T__8: { enterOuterAlt(_localctx, 2); - setState(817); + setState(1031); match(SparqlAutomaticParser::T__8); break; } case SparqlAutomaticParser::T__14: { enterOuterAlt(_localctx, 3); - setState(818); + setState(1032); match(SparqlAutomaticParser::T__14); - setState(819); + setState(1033); pathNegatedPropertySet(); break; } case SparqlAutomaticParser::T__1: { enterOuterAlt(_localctx, 4); - setState(820); + setState(1034); match(SparqlAutomaticParser::T__1); - setState(821); + setState(1035); path(); - setState(822); + setState(1036); match(SparqlAutomaticParser::T__2); break; } @@ -8931,7 +11305,7 @@ SparqlAutomaticParser::PathNegatedPropertySetContext* SparqlAutomaticParser::pathNegatedPropertySet() { PathNegatedPropertySetContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 156, SparqlAutomaticParser::RulePathNegatedPropertySet); + enterRule(_localctx, 204, SparqlAutomaticParser::RulePathNegatedPropertySet); size_t _la = 0; #if __cplusplus > 201703L @@ -8942,7 +11316,7 @@ SparqlAutomaticParser::pathNegatedPropertySet() { exitRule(); }); try { - setState(839); + setState(1053); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__8: @@ -8952,40 +11326,40 @@ SparqlAutomaticParser::pathNegatedPropertySet() { case SparqlAutomaticParser::PNAME_LN: case SparqlAutomaticParser::PREFIX_LANGTAG: { enterOuterAlt(_localctx, 1); - setState(826); + setState(1040); pathOneInPropertySet(); break; } case SparqlAutomaticParser::T__1: { enterOuterAlt(_localctx, 2); - setState(827); + setState(1041); match(SparqlAutomaticParser::T__1); - setState(836); + setState(1050); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::T__8 || _la == SparqlAutomaticParser::T__11 || - (((_la - 139) & ~0x3fULL) == 0) && - ((1ULL << (_la - 139)) & 135) != 0) { - setState(828); + (((_la - 141) & ~0x3fULL) == 0) && + ((1ULL << (_la - 141)) & 135) != 0) { + setState(1042); pathOneInPropertySet(); - setState(833); + setState(1047); _errHandler->sync(this); _la = _input->LA(1); while (_la == SparqlAutomaticParser::T__9) { - setState(829); + setState(1043); match(SparqlAutomaticParser::T__9); - setState(830); + setState(1044); pathOneInPropertySet(); - setState(835); + setState(1049); _errHandler->sync(this); _la = _input->LA(1); } } - setState(838); + setState(1052); match(SparqlAutomaticParser::T__2); break; } @@ -9045,7 +11419,7 @@ SparqlAutomaticParser::PathOneInPropertySetContext* SparqlAutomaticParser::pathOneInPropertySet() { PathOneInPropertySetContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 158, SparqlAutomaticParser::RulePathOneInPropertySet); + enterRule(_localctx, 206, SparqlAutomaticParser::RulePathOneInPropertySet); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -9055,7 +11429,7 @@ SparqlAutomaticParser::pathOneInPropertySet() { exitRule(); }); try { - setState(848); + setState(1062); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::IRI_REF: @@ -9063,36 +11437,36 @@ SparqlAutomaticParser::pathOneInPropertySet() { case SparqlAutomaticParser::PNAME_LN: case SparqlAutomaticParser::PREFIX_LANGTAG: { enterOuterAlt(_localctx, 1); - setState(841); + setState(1055); iri(); break; } case SparqlAutomaticParser::T__8: { enterOuterAlt(_localctx, 2); - setState(842); + setState(1056); match(SparqlAutomaticParser::T__8); break; } case SparqlAutomaticParser::T__11: { enterOuterAlt(_localctx, 3); - setState(843); + setState(1057); match(SparqlAutomaticParser::T__11); - setState(846); + setState(1060); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::IRI_REF: case SparqlAutomaticParser::PNAME_NS: case SparqlAutomaticParser::PNAME_LN: case SparqlAutomaticParser::PREFIX_LANGTAG: { - setState(844); + setState(1058); iri(); break; } case SparqlAutomaticParser::T__8: { - setState(845); + setState(1059); match(SparqlAutomaticParser::T__8); break; } @@ -9154,7 +11528,7 @@ std::any SparqlAutomaticParser::IntegerContext::accept( SparqlAutomaticParser::IntegerContext* SparqlAutomaticParser::integer() { IntegerContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 160, SparqlAutomaticParser::RuleInteger); + enterRule(_localctx, 208, SparqlAutomaticParser::RuleInteger); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -9165,7 +11539,7 @@ SparqlAutomaticParser::IntegerContext* SparqlAutomaticParser::integer() { }); try { enterOuterAlt(_localctx, 1); - setState(850); + setState(1064); match(SparqlAutomaticParser::INTEGER); } catch (RecognitionException& e) { @@ -9222,7 +11596,7 @@ SparqlAutomaticParser::TriplesNodeContext* SparqlAutomaticParser::triplesNode() { TriplesNodeContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 162, SparqlAutomaticParser::RuleTriplesNode); + enterRule(_localctx, 210, SparqlAutomaticParser::RuleTriplesNode); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -9232,19 +11606,19 @@ SparqlAutomaticParser::triplesNode() { exitRule(); }); try { - setState(854); + setState(1068); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__1: { enterOuterAlt(_localctx, 1); - setState(852); + setState(1066); collection(); break; } case SparqlAutomaticParser::T__15: { enterOuterAlt(_localctx, 2); - setState(853); + setState(1067); blankNodePropertyList(); break; } @@ -9306,7 +11680,7 @@ SparqlAutomaticParser::BlankNodePropertyListContext* SparqlAutomaticParser::blankNodePropertyList() { BlankNodePropertyListContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 164, SparqlAutomaticParser::RuleBlankNodePropertyList); + enterRule(_localctx, 212, SparqlAutomaticParser::RuleBlankNodePropertyList); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -9317,11 +11691,11 @@ SparqlAutomaticParser::blankNodePropertyList() { }); try { enterOuterAlt(_localctx, 1); - setState(856); + setState(1070); match(SparqlAutomaticParser::T__15); - setState(857); + setState(1071); propertyListNotEmpty(); - setState(858); + setState(1072); match(SparqlAutomaticParser::T__16); } catch (RecognitionException& e) { @@ -9379,7 +11753,7 @@ SparqlAutomaticParser::TriplesNodePathContext* SparqlAutomaticParser::triplesNodePath() { TriplesNodePathContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 166, SparqlAutomaticParser::RuleTriplesNodePath); + enterRule(_localctx, 214, SparqlAutomaticParser::RuleTriplesNodePath); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -9389,19 +11763,19 @@ SparqlAutomaticParser::triplesNodePath() { exitRule(); }); try { - setState(862); + setState(1076); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__1: { enterOuterAlt(_localctx, 1); - setState(860); + setState(1074); collectionPath(); break; } case SparqlAutomaticParser::T__15: { enterOuterAlt(_localctx, 2); - setState(861); + setState(1075); blankNodePropertyListPath(); break; } @@ -9465,7 +11839,7 @@ SparqlAutomaticParser::blankNodePropertyListPath() { BlankNodePropertyListPathContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 168, + enterRule(_localctx, 216, SparqlAutomaticParser::RuleBlankNodePropertyListPath); #if __cplusplus > 201703L @@ -9477,11 +11851,11 @@ SparqlAutomaticParser::blankNodePropertyListPath() { }); try { enterOuterAlt(_localctx, 1); - setState(864); + setState(1078); match(SparqlAutomaticParser::T__15); - setState(865); + setState(1079); propertyListPathNotEmpty(); - setState(866); + setState(1080); match(SparqlAutomaticParser::T__16); } catch (RecognitionException& e) { @@ -9537,7 +11911,7 @@ std::any SparqlAutomaticParser::CollectionContext::accept( SparqlAutomaticParser::CollectionContext* SparqlAutomaticParser::collection() { CollectionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 170, SparqlAutomaticParser::RuleCollection); + enterRule(_localctx, 218, SparqlAutomaticParser::RuleCollection); size_t _la = 0; #if __cplusplus > 201703L @@ -9549,21 +11923,21 @@ SparqlAutomaticParser::CollectionContext* SparqlAutomaticParser::collection() { }); try { enterOuterAlt(_localctx, 1); - setState(868); + setState(1082); match(SparqlAutomaticParser::T__1); - setState(870); + setState(1084); _errHandler->sync(this); _la = _input->LA(1); do { - setState(869); + setState(1083); graphNode(); - setState(872); + setState(1086); _errHandler->sync(this); _la = _input->LA(1); } while (((_la & ~0x3fULL) == 0) && ((1ULL << _la) & 805371908) != 0 || - (((_la - 139) & ~0x3fULL) == 0) && - ((1ULL << (_la - 139)) & 29228991) != 0); - setState(874); + (((_la - 141) & ~0x3fULL) == 0) && + ((1ULL << (_la - 141)) & 29228991) != 0); + setState(1088); match(SparqlAutomaticParser::T__2); } catch (RecognitionException& e) { @@ -9620,7 +11994,7 @@ SparqlAutomaticParser::CollectionPathContext* SparqlAutomaticParser::collectionPath() { CollectionPathContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 172, SparqlAutomaticParser::RuleCollectionPath); + enterRule(_localctx, 220, SparqlAutomaticParser::RuleCollectionPath); size_t _la = 0; #if __cplusplus > 201703L @@ -9632,21 +12006,21 @@ SparqlAutomaticParser::collectionPath() { }); try { enterOuterAlt(_localctx, 1); - setState(876); + setState(1090); match(SparqlAutomaticParser::T__1); - setState(878); + setState(1092); _errHandler->sync(this); _la = _input->LA(1); do { - setState(877); + setState(1091); graphNodePath(); - setState(880); + setState(1094); _errHandler->sync(this); _la = _input->LA(1); } while (((_la & ~0x3fULL) == 0) && ((1ULL << _la) & 805371908) != 0 || - (((_la - 139) & ~0x3fULL) == 0) && - ((1ULL << (_la - 139)) & 29228991) != 0); - setState(882); + (((_la - 141) & ~0x3fULL) == 0) && + ((1ULL << (_la - 141)) & 29228991) != 0); + setState(1096); match(SparqlAutomaticParser::T__2); } catch (RecognitionException& e) { @@ -9702,7 +12076,7 @@ std::any SparqlAutomaticParser::GraphNodeContext::accept( SparqlAutomaticParser::GraphNodeContext* SparqlAutomaticParser::graphNode() { GraphNodeContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 174, SparqlAutomaticParser::RuleGraphNode); + enterRule(_localctx, 222, SparqlAutomaticParser::RuleGraphNode); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -9712,7 +12086,7 @@ SparqlAutomaticParser::GraphNodeContext* SparqlAutomaticParser::graphNode() { exitRule(); }); try { - setState(886); + setState(1100); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__27: @@ -9740,7 +12114,7 @@ SparqlAutomaticParser::GraphNodeContext* SparqlAutomaticParser::graphNode() { case SparqlAutomaticParser::NIL: case SparqlAutomaticParser::ANON: { enterOuterAlt(_localctx, 1); - setState(884); + setState(1098); varOrTerm(); break; } @@ -9748,7 +12122,7 @@ SparqlAutomaticParser::GraphNodeContext* SparqlAutomaticParser::graphNode() { case SparqlAutomaticParser::T__1: case SparqlAutomaticParser::T__15: { enterOuterAlt(_localctx, 2); - setState(885); + setState(1099); triplesNode(); break; } @@ -9811,7 +12185,7 @@ SparqlAutomaticParser::GraphNodePathContext* SparqlAutomaticParser::graphNodePath() { GraphNodePathContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 176, SparqlAutomaticParser::RuleGraphNodePath); + enterRule(_localctx, 224, SparqlAutomaticParser::RuleGraphNodePath); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -9821,7 +12195,7 @@ SparqlAutomaticParser::graphNodePath() { exitRule(); }); try { - setState(890); + setState(1104); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__27: @@ -9849,7 +12223,7 @@ SparqlAutomaticParser::graphNodePath() { case SparqlAutomaticParser::NIL: case SparqlAutomaticParser::ANON: { enterOuterAlt(_localctx, 1); - setState(888); + setState(1102); varOrTerm(); break; } @@ -9857,7 +12231,7 @@ SparqlAutomaticParser::graphNodePath() { case SparqlAutomaticParser::T__1: case SparqlAutomaticParser::T__15: { enterOuterAlt(_localctx, 2); - setState(889); + setState(1103); triplesNodePath(); break; } @@ -9919,7 +12293,7 @@ std::any SparqlAutomaticParser::VarOrTermContext::accept( SparqlAutomaticParser::VarOrTermContext* SparqlAutomaticParser::varOrTerm() { VarOrTermContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 178, SparqlAutomaticParser::RuleVarOrTerm); + enterRule(_localctx, 226, SparqlAutomaticParser::RuleVarOrTerm); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -9929,13 +12303,13 @@ SparqlAutomaticParser::VarOrTermContext* SparqlAutomaticParser::varOrTerm() { exitRule(); }); try { - setState(894); + setState(1108); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::VAR1: case SparqlAutomaticParser::VAR2: { enterOuterAlt(_localctx, 1); - setState(892); + setState(1106); var(); break; } @@ -9963,7 +12337,7 @@ SparqlAutomaticParser::VarOrTermContext* SparqlAutomaticParser::varOrTerm() { case SparqlAutomaticParser::NIL: case SparqlAutomaticParser::ANON: { enterOuterAlt(_localctx, 2); - setState(893); + setState(1107); graphTerm(); break; } @@ -10025,7 +12399,7 @@ std::any SparqlAutomaticParser::VarOrIriContext::accept( SparqlAutomaticParser::VarOrIriContext* SparqlAutomaticParser::varOrIri() { VarOrIriContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 180, SparqlAutomaticParser::RuleVarOrIri); + enterRule(_localctx, 228, SparqlAutomaticParser::RuleVarOrIri); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -10035,13 +12409,13 @@ SparqlAutomaticParser::VarOrIriContext* SparqlAutomaticParser::varOrIri() { exitRule(); }); try { - setState(898); + setState(1112); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::VAR1: case SparqlAutomaticParser::VAR2: { enterOuterAlt(_localctx, 1); - setState(896); + setState(1110); var(); break; } @@ -10051,7 +12425,7 @@ SparqlAutomaticParser::VarOrIriContext* SparqlAutomaticParser::varOrIri() { case SparqlAutomaticParser::PNAME_LN: case SparqlAutomaticParser::PREFIX_LANGTAG: { enterOuterAlt(_localctx, 2); - setState(897); + setState(1111); iri(); break; } @@ -10110,7 +12484,7 @@ std::any SparqlAutomaticParser::VarContext::accept( SparqlAutomaticParser::VarContext* SparqlAutomaticParser::var() { VarContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 182, SparqlAutomaticParser::RuleVar); + enterRule(_localctx, 230, SparqlAutomaticParser::RuleVar); size_t _la = 0; #if __cplusplus > 201703L @@ -10122,7 +12496,7 @@ SparqlAutomaticParser::VarContext* SparqlAutomaticParser::var() { }); try { enterOuterAlt(_localctx, 1); - setState(900); + setState(1114); _la = _input->LA(1); if (!(_la == SparqlAutomaticParser::VAR1 @@ -10205,7 +12579,7 @@ std::any SparqlAutomaticParser::GraphTermContext::accept( SparqlAutomaticParser::GraphTermContext* SparqlAutomaticParser::graphTerm() { GraphTermContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 184, SparqlAutomaticParser::RuleGraphTerm); + enterRule(_localctx, 232, SparqlAutomaticParser::RuleGraphTerm); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -10215,7 +12589,7 @@ SparqlAutomaticParser::GraphTermContext* SparqlAutomaticParser::graphTerm() { exitRule(); }); try { - setState(908); + setState(1122); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::IRI_REF: @@ -10223,7 +12597,7 @@ SparqlAutomaticParser::GraphTermContext* SparqlAutomaticParser::graphTerm() { case SparqlAutomaticParser::PNAME_LN: case SparqlAutomaticParser::PREFIX_LANGTAG: { enterOuterAlt(_localctx, 1); - setState(902); + setState(1116); iri(); break; } @@ -10233,7 +12607,7 @@ SparqlAutomaticParser::GraphTermContext* SparqlAutomaticParser::graphTerm() { case SparqlAutomaticParser::STRING_LITERAL_LONG1: case SparqlAutomaticParser::STRING_LITERAL_LONG2: { enterOuterAlt(_localctx, 2); - setState(903); + setState(1117); rdfLiteral(); break; } @@ -10248,7 +12622,7 @@ SparqlAutomaticParser::GraphTermContext* SparqlAutomaticParser::graphTerm() { case SparqlAutomaticParser::DECIMAL_NEGATIVE: case SparqlAutomaticParser::DOUBLE_NEGATIVE: { enterOuterAlt(_localctx, 3); - setState(904); + setState(1118); numericLiteral(); break; } @@ -10256,7 +12630,7 @@ SparqlAutomaticParser::GraphTermContext* SparqlAutomaticParser::graphTerm() { case SparqlAutomaticParser::T__27: case SparqlAutomaticParser::T__28: { enterOuterAlt(_localctx, 4); - setState(905); + setState(1119); booleanLiteral(); break; } @@ -10264,14 +12638,14 @@ SparqlAutomaticParser::GraphTermContext* SparqlAutomaticParser::graphTerm() { case SparqlAutomaticParser::BLANK_NODE_LABEL: case SparqlAutomaticParser::ANON: { enterOuterAlt(_localctx, 5); - setState(906); + setState(1120); blankNode(); break; } case SparqlAutomaticParser::NIL: { enterOuterAlt(_localctx, 6); - setState(907); + setState(1121); match(SparqlAutomaticParser::NIL); break; } @@ -10329,7 +12703,7 @@ std::any SparqlAutomaticParser::ExpressionContext::accept( SparqlAutomaticParser::ExpressionContext* SparqlAutomaticParser::expression() { ExpressionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 186, SparqlAutomaticParser::RuleExpression); + enterRule(_localctx, 234, SparqlAutomaticParser::RuleExpression); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -10340,7 +12714,7 @@ SparqlAutomaticParser::ExpressionContext* SparqlAutomaticParser::expression() { }); try { enterOuterAlt(_localctx, 1); - setState(910); + setState(1124); conditionalOrExpression(); } catch (RecognitionException& e) { @@ -10405,7 +12779,7 @@ SparqlAutomaticParser::ConditionalOrExpressionContext* SparqlAutomaticParser::conditionalOrExpression() { ConditionalOrExpressionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 188, SparqlAutomaticParser::RuleConditionalOrExpression); + enterRule(_localctx, 236, SparqlAutomaticParser::RuleConditionalOrExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -10417,17 +12791,17 @@ SparqlAutomaticParser::conditionalOrExpression() { }); try { enterOuterAlt(_localctx, 1); - setState(912); + setState(1126); conditionalAndExpression(); - setState(917); + setState(1131); _errHandler->sync(this); _la = _input->LA(1); while (_la == SparqlAutomaticParser::T__17) { - setState(913); + setState(1127); match(SparqlAutomaticParser::T__17); - setState(914); + setState(1128); conditionalAndExpression(); - setState(919); + setState(1133); _errHandler->sync(this); _la = _input->LA(1); } @@ -10491,7 +12865,7 @@ SparqlAutomaticParser::conditionalAndExpression() { ConditionalAndExpressionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 190, + enterRule(_localctx, 238, SparqlAutomaticParser::RuleConditionalAndExpression); size_t _la = 0; @@ -10504,17 +12878,17 @@ SparqlAutomaticParser::conditionalAndExpression() { }); try { enterOuterAlt(_localctx, 1); - setState(920); + setState(1134); valueLogical(); - setState(925); + setState(1139); _errHandler->sync(this); _la = _input->LA(1); while (_la == SparqlAutomaticParser::T__18) { - setState(921); + setState(1135); match(SparqlAutomaticParser::T__18); - setState(922); + setState(1136); valueLogical(); - setState(927); + setState(1141); _errHandler->sync(this); _la = _input->LA(1); } @@ -10568,7 +12942,7 @@ SparqlAutomaticParser::ValueLogicalContext* SparqlAutomaticParser::valueLogical() { ValueLogicalContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 192, SparqlAutomaticParser::RuleValueLogical); + enterRule(_localctx, 240, SparqlAutomaticParser::RuleValueLogical); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -10579,7 +12953,7 @@ SparqlAutomaticParser::valueLogical() { }); try { enterOuterAlt(_localctx, 1); - setState(928); + setState(1142); relationalExpression(); } catch (RecognitionException& e) { @@ -10652,7 +13026,7 @@ SparqlAutomaticParser::RelationalExpressionContext* SparqlAutomaticParser::relationalExpression() { RelationalExpressionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 194, SparqlAutomaticParser::RuleRelationalExpression); + enterRule(_localctx, 242, SparqlAutomaticParser::RuleRelationalExpression); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -10663,79 +13037,79 @@ SparqlAutomaticParser::relationalExpression() { }); try { enterOuterAlt(_localctx, 1); - setState(930); + setState(1144); numericExpression(); - setState(948); + setState(1162); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__19: { - setState(931); + setState(1145); match(SparqlAutomaticParser::T__19); - setState(932); + setState(1146); numericExpression(); break; } case SparqlAutomaticParser::T__20: { - setState(933); + setState(1147); match(SparqlAutomaticParser::T__20); - setState(934); + setState(1148); numericExpression(); break; } case SparqlAutomaticParser::T__21: { - setState(935); + setState(1149); match(SparqlAutomaticParser::T__21); - setState(936); + setState(1150); numericExpression(); break; } case SparqlAutomaticParser::T__22: { - setState(937); + setState(1151); match(SparqlAutomaticParser::T__22); - setState(938); + setState(1152); numericExpression(); break; } case SparqlAutomaticParser::T__23: { - setState(939); + setState(1153); match(SparqlAutomaticParser::T__23); - setState(940); + setState(1154); numericExpression(); break; } case SparqlAutomaticParser::T__24: { - setState(941); + setState(1155); match(SparqlAutomaticParser::T__24); - setState(942); + setState(1156); numericExpression(); break; } case SparqlAutomaticParser::IN: { - setState(943); + setState(1157); match(SparqlAutomaticParser::IN); - setState(944); + setState(1158); expressionList(); break; } case SparqlAutomaticParser::NOT: { - setState(945); + setState(1159); match(SparqlAutomaticParser::NOT); - setState(946); + setState(1160); match(SparqlAutomaticParser::IN); - setState(947); + setState(1161); expressionList(); break; } case SparqlAutomaticParser::T__2: - case SparqlAutomaticParser::T__6: + case SparqlAutomaticParser::T__5: case SparqlAutomaticParser::T__7: case SparqlAutomaticParser::T__17: case SparqlAutomaticParser::T__18: @@ -10796,7 +13170,7 @@ SparqlAutomaticParser::NumericExpressionContext* SparqlAutomaticParser::numericExpression() { NumericExpressionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 196, SparqlAutomaticParser::RuleNumericExpression); + enterRule(_localctx, 244, SparqlAutomaticParser::RuleNumericExpression); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -10807,7 +13181,7 @@ SparqlAutomaticParser::numericExpression() { }); try { enterOuterAlt(_localctx, 1); - setState(950); + setState(1164); additiveExpression(); } catch (RecognitionException& e) { @@ -10874,7 +13248,7 @@ SparqlAutomaticParser::AdditiveExpressionContext* SparqlAutomaticParser::additiveExpression() { AdditiveExpressionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 198, SparqlAutomaticParser::RuleAdditiveExpression); + enterRule(_localctx, 246, SparqlAutomaticParser::RuleAdditiveExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -10886,19 +13260,19 @@ SparqlAutomaticParser::additiveExpression() { }); try { enterOuterAlt(_localctx, 1); - setState(952); + setState(1166); multiplicativeExpression(); - setState(956); + setState(1170); _errHandler->sync(this); _la = _input->LA(1); while (_la == SparqlAutomaticParser::T__12 || _la == SparqlAutomaticParser::T__25 || - (((_la - 150) & ~0x3fULL) == 0) && - ((1ULL << (_la - 150)) & 63) != 0) { - setState(953); + (((_la - 152) & ~0x3fULL) == 0) && + ((1ULL << (_la - 152)) & 63) != 0) { + setState(1167); multiplicativeExpressionWithSign(); - setState(958); + setState(1172); _errHandler->sync(this); _la = _input->LA(1); } @@ -10971,7 +13345,7 @@ SparqlAutomaticParser::multiplicativeExpressionWithSign() { MultiplicativeExpressionWithSignContext* _localctx = _tracker.createInstance( _ctx, getState()); - enterRule(_localctx, 200, + enterRule(_localctx, 248, SparqlAutomaticParser::RuleMultiplicativeExpressionWithSign); #if __cplusplus > 201703L @@ -10982,23 +13356,23 @@ SparqlAutomaticParser::multiplicativeExpressionWithSign() { exitRule(); }); try { - setState(964); + setState(1178); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__12: { enterOuterAlt(_localctx, 1); - setState(959); + setState(1173); match(SparqlAutomaticParser::T__12); - setState(960); + setState(1174); plusSubexpression(); break; } case SparqlAutomaticParser::T__25: { enterOuterAlt(_localctx, 2); - setState(961); + setState(1175); match(SparqlAutomaticParser::T__25); - setState(962); + setState(1176); minusSubexpression(); break; } @@ -11010,7 +13384,7 @@ SparqlAutomaticParser::multiplicativeExpressionWithSign() { case SparqlAutomaticParser::DECIMAL_NEGATIVE: case SparqlAutomaticParser::DOUBLE_NEGATIVE: { enterOuterAlt(_localctx, 3); - setState(963); + setState(1177); multiplicativeExpressionWithLeadingSignButNoSpace(); break; } @@ -11069,7 +13443,7 @@ SparqlAutomaticParser::PlusSubexpressionContext* SparqlAutomaticParser::plusSubexpression() { PlusSubexpressionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 202, SparqlAutomaticParser::RulePlusSubexpression); + enterRule(_localctx, 250, SparqlAutomaticParser::RulePlusSubexpression); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -11080,7 +13454,7 @@ SparqlAutomaticParser::plusSubexpression() { }); try { enterOuterAlt(_localctx, 1); - setState(966); + setState(1180); multiplicativeExpression(); } catch (RecognitionException& e) { @@ -11133,7 +13507,7 @@ SparqlAutomaticParser::MinusSubexpressionContext* SparqlAutomaticParser::minusSubexpression() { MinusSubexpressionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 204, SparqlAutomaticParser::RuleMinusSubexpression); + enterRule(_localctx, 252, SparqlAutomaticParser::RuleMinusSubexpression); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -11144,7 +13518,7 @@ SparqlAutomaticParser::minusSubexpression() { }); try { enterOuterAlt(_localctx, 1); - setState(968); + setState(1182); multiplicativeExpression(); } catch (RecognitionException& e) { @@ -11235,7 +13609,7 @@ SparqlAutomaticParser::multiplicativeExpressionWithLeadingSignButNoSpace() { _tracker.createInstance< MultiplicativeExpressionWithLeadingSignButNoSpaceContext>(_ctx, getState()); - enterRule(_localctx, 206, + enterRule(_localctx, 254, SparqlAutomaticParser:: RuleMultiplicativeExpressionWithLeadingSignButNoSpace); size_t _la = 0; @@ -11249,13 +13623,13 @@ SparqlAutomaticParser::multiplicativeExpressionWithLeadingSignButNoSpace() { }); try { enterOuterAlt(_localctx, 1); - setState(972); + setState(1186); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::INTEGER_POSITIVE: case SparqlAutomaticParser::DECIMAL_POSITIVE: case SparqlAutomaticParser::DOUBLE_POSITIVE: { - setState(970); + setState(1184); numericLiteralPositive(); break; } @@ -11263,7 +13637,7 @@ SparqlAutomaticParser::multiplicativeExpressionWithLeadingSignButNoSpace() { case SparqlAutomaticParser::INTEGER_NEGATIVE: case SparqlAutomaticParser::DECIMAL_NEGATIVE: case SparqlAutomaticParser::DOUBLE_NEGATIVE: { - setState(971); + setState(1185); numericLiteralNegative(); break; } @@ -11271,15 +13645,15 @@ SparqlAutomaticParser::multiplicativeExpressionWithLeadingSignButNoSpace() { default: throw NoViableAltException(this); } - setState(977); + setState(1191); _errHandler->sync(this); _la = _input->LA(1); while (_la == SparqlAutomaticParser::T__0 || _la == SparqlAutomaticParser::T__10) { - setState(974); + setState(1188); multiplyOrDivideExpression(); - setState(979); + setState(1193); _errHandler->sync(this); _la = _input->LA(1); } @@ -11352,7 +13726,7 @@ SparqlAutomaticParser::multiplicativeExpression() { MultiplicativeExpressionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 208, + enterRule(_localctx, 256, SparqlAutomaticParser::RuleMultiplicativeExpression); size_t _la = 0; @@ -11365,17 +13739,17 @@ SparqlAutomaticParser::multiplicativeExpression() { }); try { enterOuterAlt(_localctx, 1); - setState(980); + setState(1194); unaryExpression(); - setState(984); + setState(1198); _errHandler->sync(this); _la = _input->LA(1); while (_la == SparqlAutomaticParser::T__0 || _la == SparqlAutomaticParser::T__10) { - setState(981); + setState(1195); multiplyOrDivideExpression(); - setState(986); + setState(1200); _errHandler->sync(this); _la = _input->LA(1); } @@ -11439,7 +13813,7 @@ SparqlAutomaticParser::multiplyOrDivideExpression() { MultiplyOrDivideExpressionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 210, + enterRule(_localctx, 258, SparqlAutomaticParser::RuleMultiplyOrDivideExpression); #if __cplusplus > 201703L @@ -11450,19 +13824,19 @@ SparqlAutomaticParser::multiplyOrDivideExpression() { exitRule(); }); try { - setState(989); + setState(1203); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__0: { enterOuterAlt(_localctx, 1); - setState(987); + setState(1201); multiplyExpression(); break; } case SparqlAutomaticParser::T__10: { enterOuterAlt(_localctx, 2); - setState(988); + setState(1202); divideExpression(); break; } @@ -11520,7 +13894,7 @@ SparqlAutomaticParser::MultiplyExpressionContext* SparqlAutomaticParser::multiplyExpression() { MultiplyExpressionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 212, SparqlAutomaticParser::RuleMultiplyExpression); + enterRule(_localctx, 260, SparqlAutomaticParser::RuleMultiplyExpression); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -11531,9 +13905,9 @@ SparqlAutomaticParser::multiplyExpression() { }); try { enterOuterAlt(_localctx, 1); - setState(991); + setState(1205); match(SparqlAutomaticParser::T__0); - setState(992); + setState(1206); unaryExpression(); } catch (RecognitionException& e) { @@ -11585,7 +13959,7 @@ SparqlAutomaticParser::DivideExpressionContext* SparqlAutomaticParser::divideExpression() { DivideExpressionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 214, SparqlAutomaticParser::RuleDivideExpression); + enterRule(_localctx, 262, SparqlAutomaticParser::RuleDivideExpression); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -11596,9 +13970,9 @@ SparqlAutomaticParser::divideExpression() { }); try { enterOuterAlt(_localctx, 1); - setState(994); + setState(1208); match(SparqlAutomaticParser::T__10); - setState(995); + setState(1209); unaryExpression(); } catch (RecognitionException& e) { @@ -11650,7 +14024,7 @@ SparqlAutomaticParser::UnaryExpressionContext* SparqlAutomaticParser::unaryExpression() { UnaryExpressionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 216, SparqlAutomaticParser::RuleUnaryExpression); + enterRule(_localctx, 264, SparqlAutomaticParser::RuleUnaryExpression); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -11660,32 +14034,32 @@ SparqlAutomaticParser::unaryExpression() { exitRule(); }); try { - setState(1004); + setState(1218); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__14: { enterOuterAlt(_localctx, 1); - setState(997); + setState(1211); match(SparqlAutomaticParser::T__14); - setState(998); + setState(1212); primaryExpression(); break; } case SparqlAutomaticParser::T__12: { enterOuterAlt(_localctx, 2); - setState(999); + setState(1213); match(SparqlAutomaticParser::T__12); - setState(1000); + setState(1214); primaryExpression(); break; } case SparqlAutomaticParser::T__25: { enterOuterAlt(_localctx, 3); - setState(1001); + setState(1215); match(SparqlAutomaticParser::T__25); - setState(1002); + setState(1216); primaryExpression(); break; } @@ -11774,7 +14148,7 @@ SparqlAutomaticParser::unaryExpression() { case SparqlAutomaticParser::STRING_LITERAL_LONG1: case SparqlAutomaticParser::STRING_LITERAL_LONG2: { enterOuterAlt(_localctx, 4); - setState(1003); + setState(1217); primaryExpression(); break; } @@ -11862,7 +14236,7 @@ SparqlAutomaticParser::PrimaryExpressionContext* SparqlAutomaticParser::primaryExpression() { PrimaryExpressionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 218, SparqlAutomaticParser::RulePrimaryExpression); + enterRule(_localctx, 266, SparqlAutomaticParser::RulePrimaryExpression); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -11872,12 +14246,12 @@ SparqlAutomaticParser::primaryExpression() { exitRule(); }); try { - setState(1013); + setState(1227); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__1: { enterOuterAlt(_localctx, 1); - setState(1006); + setState(1220); brackettedExpression(); break; } @@ -11944,7 +14318,7 @@ SparqlAutomaticParser::primaryExpression() { case SparqlAutomaticParser::AVG: case SparqlAutomaticParser::SAMPLE: { enterOuterAlt(_localctx, 2); - setState(1007); + setState(1221); builtInCall(); break; } @@ -11954,7 +14328,7 @@ SparqlAutomaticParser::primaryExpression() { case SparqlAutomaticParser::PNAME_LN: case SparqlAutomaticParser::PREFIX_LANGTAG: { enterOuterAlt(_localctx, 3); - setState(1008); + setState(1222); iriOrFunction(); break; } @@ -11964,7 +14338,7 @@ SparqlAutomaticParser::primaryExpression() { case SparqlAutomaticParser::STRING_LITERAL_LONG1: case SparqlAutomaticParser::STRING_LITERAL_LONG2: { enterOuterAlt(_localctx, 4); - setState(1009); + setState(1223); rdfLiteral(); break; } @@ -11979,7 +14353,7 @@ SparqlAutomaticParser::primaryExpression() { case SparqlAutomaticParser::DECIMAL_NEGATIVE: case SparqlAutomaticParser::DOUBLE_NEGATIVE: { enterOuterAlt(_localctx, 5); - setState(1010); + setState(1224); numericLiteral(); break; } @@ -11987,7 +14361,7 @@ SparqlAutomaticParser::primaryExpression() { case SparqlAutomaticParser::T__27: case SparqlAutomaticParser::T__28: { enterOuterAlt(_localctx, 6); - setState(1011); + setState(1225); booleanLiteral(); break; } @@ -11995,7 +14369,7 @@ SparqlAutomaticParser::primaryExpression() { case SparqlAutomaticParser::VAR1: case SparqlAutomaticParser::VAR2: { enterOuterAlt(_localctx, 7); - setState(1012); + setState(1226); var(); break; } @@ -12055,7 +14429,7 @@ SparqlAutomaticParser::BrackettedExpressionContext* SparqlAutomaticParser::brackettedExpression() { BrackettedExpressionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 220, SparqlAutomaticParser::RuleBrackettedExpression); + enterRule(_localctx, 268, SparqlAutomaticParser::RuleBrackettedExpression); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -12066,11 +14440,11 @@ SparqlAutomaticParser::brackettedExpression() { }); try { enterOuterAlt(_localctx, 1); - setState(1015); + setState(1229); match(SparqlAutomaticParser::T__1); - setState(1016); + setState(1230); expression(); - setState(1017); + setState(1231); match(SparqlAutomaticParser::T__2); } catch (RecognitionException& e) { @@ -12369,7 +14743,7 @@ SparqlAutomaticParser::BuiltInCallContext* SparqlAutomaticParser::builtInCall() { BuiltInCallContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 222, SparqlAutomaticParser::RuleBuiltInCall); + enterRule(_localctx, 270, SparqlAutomaticParser::RuleBuiltInCall); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -12379,7 +14753,7 @@ SparqlAutomaticParser::builtInCall() { exitRule(); }); try { - setState(1273); + setState(1487); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::GROUP_CONCAT: @@ -12390,119 +14764,119 @@ SparqlAutomaticParser::builtInCall() { case SparqlAutomaticParser::AVG: case SparqlAutomaticParser::SAMPLE: { enterOuterAlt(_localctx, 1); - setState(1019); + setState(1233); aggregate(); break; } case SparqlAutomaticParser::STR: { enterOuterAlt(_localctx, 2); - setState(1020); + setState(1234); match(SparqlAutomaticParser::STR); - setState(1021); + setState(1235); match(SparqlAutomaticParser::T__1); - setState(1022); + setState(1236); expression(); - setState(1023); + setState(1237); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::LANG: { enterOuterAlt(_localctx, 3); - setState(1025); + setState(1239); langExpression(); break; } case SparqlAutomaticParser::LANGMATCHES: { enterOuterAlt(_localctx, 4); - setState(1026); + setState(1240); match(SparqlAutomaticParser::LANGMATCHES); - setState(1027); + setState(1241); match(SparqlAutomaticParser::T__1); - setState(1028); + setState(1242); expression(); - setState(1029); - match(SparqlAutomaticParser::T__6); - setState(1030); + setState(1243); + match(SparqlAutomaticParser::T__7); + setState(1244); expression(); - setState(1031); + setState(1245); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::DATATYPE: { enterOuterAlt(_localctx, 5); - setState(1033); + setState(1247); match(SparqlAutomaticParser::DATATYPE); - setState(1034); + setState(1248); match(SparqlAutomaticParser::T__1); - setState(1035); + setState(1249); expression(); - setState(1036); + setState(1250); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::BOUND: { enterOuterAlt(_localctx, 6); - setState(1038); + setState(1252); match(SparqlAutomaticParser::BOUND); - setState(1039); + setState(1253); match(SparqlAutomaticParser::T__1); - setState(1040); + setState(1254); var(); - setState(1041); + setState(1255); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::IRI: { enterOuterAlt(_localctx, 7); - setState(1043); + setState(1257); match(SparqlAutomaticParser::IRI); - setState(1044); + setState(1258); match(SparqlAutomaticParser::T__1); - setState(1045); + setState(1259); expression(); - setState(1046); + setState(1260); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::URI: { enterOuterAlt(_localctx, 8); - setState(1048); + setState(1262); match(SparqlAutomaticParser::URI); - setState(1049); + setState(1263); match(SparqlAutomaticParser::T__1); - setState(1050); + setState(1264); expression(); - setState(1051); + setState(1265); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::BNODE: { enterOuterAlt(_localctx, 9); - setState(1053); + setState(1267); match(SparqlAutomaticParser::BNODE); - setState(1059); + setState(1273); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__1: { - setState(1054); + setState(1268); match(SparqlAutomaticParser::T__1); - setState(1055); + setState(1269); expression(); - setState(1056); + setState(1270); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::NIL: { - setState(1058); + setState(1272); match(SparqlAutomaticParser::NIL); break; } @@ -12515,584 +14889,584 @@ SparqlAutomaticParser::builtInCall() { case SparqlAutomaticParser::RAND: { enterOuterAlt(_localctx, 10); - setState(1061); + setState(1275); match(SparqlAutomaticParser::RAND); - setState(1062); + setState(1276); match(SparqlAutomaticParser::NIL); break; } case SparqlAutomaticParser::ABS: { enterOuterAlt(_localctx, 11); - setState(1063); + setState(1277); match(SparqlAutomaticParser::ABS); - setState(1064); + setState(1278); match(SparqlAutomaticParser::T__1); - setState(1065); + setState(1279); expression(); - setState(1066); + setState(1280); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::CEIL: { enterOuterAlt(_localctx, 12); - setState(1068); + setState(1282); match(SparqlAutomaticParser::CEIL); - setState(1069); + setState(1283); match(SparqlAutomaticParser::T__1); - setState(1070); + setState(1284); expression(); - setState(1071); + setState(1285); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::FLOOR: { enterOuterAlt(_localctx, 13); - setState(1073); + setState(1287); match(SparqlAutomaticParser::FLOOR); - setState(1074); + setState(1288); match(SparqlAutomaticParser::T__1); - setState(1075); + setState(1289); expression(); - setState(1076); + setState(1290); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::ROUND: { enterOuterAlt(_localctx, 14); - setState(1078); + setState(1292); match(SparqlAutomaticParser::ROUND); - setState(1079); + setState(1293); match(SparqlAutomaticParser::T__1); - setState(1080); + setState(1294); expression(); - setState(1081); + setState(1295); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::CONCAT: { enterOuterAlt(_localctx, 15); - setState(1083); + setState(1297); match(SparqlAutomaticParser::CONCAT); - setState(1084); + setState(1298); expressionList(); break; } case SparqlAutomaticParser::SUBSTR: { enterOuterAlt(_localctx, 16); - setState(1085); + setState(1299); substringExpression(); break; } case SparqlAutomaticParser::STRLEN: { enterOuterAlt(_localctx, 17); - setState(1086); + setState(1300); match(SparqlAutomaticParser::STRLEN); - setState(1087); + setState(1301); match(SparqlAutomaticParser::T__1); - setState(1088); + setState(1302); expression(); - setState(1089); + setState(1303); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::REPLACE: { enterOuterAlt(_localctx, 18); - setState(1091); + setState(1305); strReplaceExpression(); break; } case SparqlAutomaticParser::UCASE: { enterOuterAlt(_localctx, 19); - setState(1092); + setState(1306); match(SparqlAutomaticParser::UCASE); - setState(1093); + setState(1307); match(SparqlAutomaticParser::T__1); - setState(1094); + setState(1308); expression(); - setState(1095); + setState(1309); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::LCASE: { enterOuterAlt(_localctx, 20); - setState(1097); + setState(1311); match(SparqlAutomaticParser::LCASE); - setState(1098); + setState(1312); match(SparqlAutomaticParser::T__1); - setState(1099); + setState(1313); expression(); - setState(1100); + setState(1314); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::ENCODE_FOR_URI: { enterOuterAlt(_localctx, 21); - setState(1102); + setState(1316); match(SparqlAutomaticParser::ENCODE_FOR_URI); - setState(1103); + setState(1317); match(SparqlAutomaticParser::T__1); - setState(1104); + setState(1318); expression(); - setState(1105); + setState(1319); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::CONTAINS: { enterOuterAlt(_localctx, 22); - setState(1107); + setState(1321); match(SparqlAutomaticParser::CONTAINS); - setState(1108); + setState(1322); match(SparqlAutomaticParser::T__1); - setState(1109); + setState(1323); expression(); - setState(1110); - match(SparqlAutomaticParser::T__6); - setState(1111); + setState(1324); + match(SparqlAutomaticParser::T__7); + setState(1325); expression(); - setState(1112); + setState(1326); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::STRSTARTS: { enterOuterAlt(_localctx, 23); - setState(1114); + setState(1328); match(SparqlAutomaticParser::STRSTARTS); - setState(1115); + setState(1329); match(SparqlAutomaticParser::T__1); - setState(1116); + setState(1330); expression(); - setState(1117); - match(SparqlAutomaticParser::T__6); - setState(1118); + setState(1331); + match(SparqlAutomaticParser::T__7); + setState(1332); expression(); - setState(1119); + setState(1333); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::STRENDS: { enterOuterAlt(_localctx, 24); - setState(1121); + setState(1335); match(SparqlAutomaticParser::STRENDS); - setState(1122); + setState(1336); match(SparqlAutomaticParser::T__1); - setState(1123); + setState(1337); expression(); - setState(1124); - match(SparqlAutomaticParser::T__6); - setState(1125); + setState(1338); + match(SparqlAutomaticParser::T__7); + setState(1339); expression(); - setState(1126); + setState(1340); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::STRBEFORE: { enterOuterAlt(_localctx, 25); - setState(1128); + setState(1342); match(SparqlAutomaticParser::STRBEFORE); - setState(1129); + setState(1343); match(SparqlAutomaticParser::T__1); - setState(1130); + setState(1344); expression(); - setState(1131); - match(SparqlAutomaticParser::T__6); - setState(1132); + setState(1345); + match(SparqlAutomaticParser::T__7); + setState(1346); expression(); - setState(1133); + setState(1347); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::STRAFTER: { enterOuterAlt(_localctx, 26); - setState(1135); + setState(1349); match(SparqlAutomaticParser::STRAFTER); - setState(1136); + setState(1350); match(SparqlAutomaticParser::T__1); - setState(1137); + setState(1351); expression(); - setState(1138); - match(SparqlAutomaticParser::T__6); - setState(1139); + setState(1352); + match(SparqlAutomaticParser::T__7); + setState(1353); expression(); - setState(1140); + setState(1354); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::YEAR: { enterOuterAlt(_localctx, 27); - setState(1142); + setState(1356); match(SparqlAutomaticParser::YEAR); - setState(1143); + setState(1357); match(SparqlAutomaticParser::T__1); - setState(1144); + setState(1358); expression(); - setState(1145); + setState(1359); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::MONTH: { enterOuterAlt(_localctx, 28); - setState(1147); + setState(1361); match(SparqlAutomaticParser::MONTH); - setState(1148); + setState(1362); match(SparqlAutomaticParser::T__1); - setState(1149); + setState(1363); expression(); - setState(1150); + setState(1364); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::DAY: { enterOuterAlt(_localctx, 29); - setState(1152); + setState(1366); match(SparqlAutomaticParser::DAY); - setState(1153); + setState(1367); match(SparqlAutomaticParser::T__1); - setState(1154); + setState(1368); expression(); - setState(1155); + setState(1369); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::HOURS: { enterOuterAlt(_localctx, 30); - setState(1157); + setState(1371); match(SparqlAutomaticParser::HOURS); - setState(1158); + setState(1372); match(SparqlAutomaticParser::T__1); - setState(1159); + setState(1373); expression(); - setState(1160); + setState(1374); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::MINUTES: { enterOuterAlt(_localctx, 31); - setState(1162); + setState(1376); match(SparqlAutomaticParser::MINUTES); - setState(1163); + setState(1377); match(SparqlAutomaticParser::T__1); - setState(1164); + setState(1378); expression(); - setState(1165); + setState(1379); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::SECONDS: { enterOuterAlt(_localctx, 32); - setState(1167); + setState(1381); match(SparqlAutomaticParser::SECONDS); - setState(1168); + setState(1382); match(SparqlAutomaticParser::T__1); - setState(1169); + setState(1383); expression(); - setState(1170); + setState(1384); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::TIMEZONE: { enterOuterAlt(_localctx, 33); - setState(1172); + setState(1386); match(SparqlAutomaticParser::TIMEZONE); - setState(1173); + setState(1387); match(SparqlAutomaticParser::T__1); - setState(1174); + setState(1388); expression(); - setState(1175); + setState(1389); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::TZ: { enterOuterAlt(_localctx, 34); - setState(1177); + setState(1391); match(SparqlAutomaticParser::TZ); - setState(1178); + setState(1392); match(SparqlAutomaticParser::T__1); - setState(1179); + setState(1393); expression(); - setState(1180); + setState(1394); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::NOW: { enterOuterAlt(_localctx, 35); - setState(1182); + setState(1396); match(SparqlAutomaticParser::NOW); - setState(1183); + setState(1397); match(SparqlAutomaticParser::NIL); break; } case SparqlAutomaticParser::UUID: { enterOuterAlt(_localctx, 36); - setState(1184); + setState(1398); match(SparqlAutomaticParser::UUID); - setState(1185); + setState(1399); match(SparqlAutomaticParser::NIL); break; } case SparqlAutomaticParser::STRUUID: { enterOuterAlt(_localctx, 37); - setState(1186); + setState(1400); match(SparqlAutomaticParser::STRUUID); - setState(1187); + setState(1401); match(SparqlAutomaticParser::NIL); break; } case SparqlAutomaticParser::MD5: { enterOuterAlt(_localctx, 38); - setState(1188); + setState(1402); match(SparqlAutomaticParser::MD5); - setState(1189); + setState(1403); match(SparqlAutomaticParser::T__1); - setState(1190); + setState(1404); expression(); - setState(1191); + setState(1405); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::SHA1: { enterOuterAlt(_localctx, 39); - setState(1193); + setState(1407); match(SparqlAutomaticParser::SHA1); - setState(1194); + setState(1408); match(SparqlAutomaticParser::T__1); - setState(1195); + setState(1409); expression(); - setState(1196); + setState(1410); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::SHA256: { enterOuterAlt(_localctx, 40); - setState(1198); + setState(1412); match(SparqlAutomaticParser::SHA256); - setState(1199); + setState(1413); match(SparqlAutomaticParser::T__1); - setState(1200); + setState(1414); expression(); - setState(1201); + setState(1415); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::SHA384: { enterOuterAlt(_localctx, 41); - setState(1203); + setState(1417); match(SparqlAutomaticParser::SHA384); - setState(1204); + setState(1418); match(SparqlAutomaticParser::T__1); - setState(1205); + setState(1419); expression(); - setState(1206); + setState(1420); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::SHA512: { enterOuterAlt(_localctx, 42); - setState(1208); + setState(1422); match(SparqlAutomaticParser::SHA512); - setState(1209); + setState(1423); match(SparqlAutomaticParser::T__1); - setState(1210); + setState(1424); expression(); - setState(1211); + setState(1425); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::COALESCE: { enterOuterAlt(_localctx, 43); - setState(1213); + setState(1427); match(SparqlAutomaticParser::COALESCE); - setState(1214); + setState(1428); expressionList(); break; } case SparqlAutomaticParser::IF: { enterOuterAlt(_localctx, 44); - setState(1215); + setState(1429); match(SparqlAutomaticParser::IF); - setState(1216); + setState(1430); match(SparqlAutomaticParser::T__1); - setState(1217); + setState(1431); expression(); - setState(1218); - match(SparqlAutomaticParser::T__6); - setState(1219); + setState(1432); + match(SparqlAutomaticParser::T__7); + setState(1433); expression(); - setState(1220); - match(SparqlAutomaticParser::T__6); - setState(1221); + setState(1434); + match(SparqlAutomaticParser::T__7); + setState(1435); expression(); - setState(1222); + setState(1436); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::STRLANG: { enterOuterAlt(_localctx, 45); - setState(1224); + setState(1438); match(SparqlAutomaticParser::STRLANG); - setState(1225); + setState(1439); match(SparqlAutomaticParser::T__1); - setState(1226); + setState(1440); expression(); - setState(1227); - match(SparqlAutomaticParser::T__6); - setState(1228); + setState(1441); + match(SparqlAutomaticParser::T__7); + setState(1442); expression(); - setState(1229); + setState(1443); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::STRDT: { enterOuterAlt(_localctx, 46); - setState(1231); + setState(1445); match(SparqlAutomaticParser::STRDT); - setState(1232); + setState(1446); match(SparqlAutomaticParser::T__1); - setState(1233); + setState(1447); expression(); - setState(1234); - match(SparqlAutomaticParser::T__6); - setState(1235); + setState(1448); + match(SparqlAutomaticParser::T__7); + setState(1449); expression(); - setState(1236); + setState(1450); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::SAMETERM: { enterOuterAlt(_localctx, 47); - setState(1238); + setState(1452); match(SparqlAutomaticParser::SAMETERM); - setState(1239); + setState(1453); match(SparqlAutomaticParser::T__1); - setState(1240); + setState(1454); expression(); - setState(1241); - match(SparqlAutomaticParser::T__6); - setState(1242); + setState(1455); + match(SparqlAutomaticParser::T__7); + setState(1456); expression(); - setState(1243); + setState(1457); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::ISIRI: { enterOuterAlt(_localctx, 48); - setState(1245); + setState(1459); match(SparqlAutomaticParser::ISIRI); - setState(1246); + setState(1460); match(SparqlAutomaticParser::T__1); - setState(1247); + setState(1461); expression(); - setState(1248); + setState(1462); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::ISURI: { enterOuterAlt(_localctx, 49); - setState(1250); + setState(1464); match(SparqlAutomaticParser::ISURI); - setState(1251); + setState(1465); match(SparqlAutomaticParser::T__1); - setState(1252); + setState(1466); expression(); - setState(1253); + setState(1467); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::ISBLANK: { enterOuterAlt(_localctx, 50); - setState(1255); + setState(1469); match(SparqlAutomaticParser::ISBLANK); - setState(1256); + setState(1470); match(SparqlAutomaticParser::T__1); - setState(1257); + setState(1471); expression(); - setState(1258); + setState(1472); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::ISLITERAL: { enterOuterAlt(_localctx, 51); - setState(1260); + setState(1474); match(SparqlAutomaticParser::ISLITERAL); - setState(1261); + setState(1475); match(SparqlAutomaticParser::T__1); - setState(1262); + setState(1476); expression(); - setState(1263); + setState(1477); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::ISNUMERIC: { enterOuterAlt(_localctx, 52); - setState(1265); + setState(1479); match(SparqlAutomaticParser::ISNUMERIC); - setState(1266); + setState(1480); match(SparqlAutomaticParser::T__1); - setState(1267); + setState(1481); expression(); - setState(1268); + setState(1482); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::REGEX: { enterOuterAlt(_localctx, 53); - setState(1270); + setState(1484); regexExpression(); break; } case SparqlAutomaticParser::EXISTS: { enterOuterAlt(_localctx, 54); - setState(1271); + setState(1485); existsFunc(); break; } case SparqlAutomaticParser::NOT: { enterOuterAlt(_localctx, 55); - setState(1272); + setState(1486); notExistsFunc(); break; } @@ -13159,7 +15533,7 @@ SparqlAutomaticParser::RegexExpressionContext* SparqlAutomaticParser::regexExpression() { RegexExpressionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 224, SparqlAutomaticParser::RuleRegexExpression); + enterRule(_localctx, 272, SparqlAutomaticParser::RuleRegexExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -13171,27 +15545,27 @@ SparqlAutomaticParser::regexExpression() { }); try { enterOuterAlt(_localctx, 1); - setState(1275); + setState(1489); match(SparqlAutomaticParser::REGEX); - setState(1276); + setState(1490); match(SparqlAutomaticParser::T__1); - setState(1277); + setState(1491); expression(); - setState(1278); - match(SparqlAutomaticParser::T__6); - setState(1279); + setState(1492); + match(SparqlAutomaticParser::T__7); + setState(1493); expression(); - setState(1282); + setState(1496); _errHandler->sync(this); _la = _input->LA(1); - if (_la == SparqlAutomaticParser::T__6) { - setState(1280); - match(SparqlAutomaticParser::T__6); - setState(1281); + if (_la == SparqlAutomaticParser::T__7) { + setState(1494); + match(SparqlAutomaticParser::T__7); + setState(1495); expression(); } - setState(1284); + setState(1498); match(SparqlAutomaticParser::T__2); } catch (RecognitionException& e) { @@ -13247,7 +15621,7 @@ SparqlAutomaticParser::LangExpressionContext* SparqlAutomaticParser::langExpression() { LangExpressionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 226, SparqlAutomaticParser::RuleLangExpression); + enterRule(_localctx, 274, SparqlAutomaticParser::RuleLangExpression); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -13258,13 +15632,13 @@ SparqlAutomaticParser::langExpression() { }); try { enterOuterAlt(_localctx, 1); - setState(1286); + setState(1500); match(SparqlAutomaticParser::LANG); - setState(1287); + setState(1501); match(SparqlAutomaticParser::T__1); - setState(1288); + setState(1502); expression(); - setState(1289); + setState(1503); match(SparqlAutomaticParser::T__2); } catch (RecognitionException& e) { @@ -13326,7 +15700,7 @@ SparqlAutomaticParser::SubstringExpressionContext* SparqlAutomaticParser::substringExpression() { SubstringExpressionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 228, SparqlAutomaticParser::RuleSubstringExpression); + enterRule(_localctx, 276, SparqlAutomaticParser::RuleSubstringExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -13338,27 +15712,27 @@ SparqlAutomaticParser::substringExpression() { }); try { enterOuterAlt(_localctx, 1); - setState(1291); + setState(1505); match(SparqlAutomaticParser::SUBSTR); - setState(1292); + setState(1506); match(SparqlAutomaticParser::T__1); - setState(1293); + setState(1507); expression(); - setState(1294); - match(SparqlAutomaticParser::T__6); - setState(1295); + setState(1508); + match(SparqlAutomaticParser::T__7); + setState(1509); expression(); - setState(1298); + setState(1512); _errHandler->sync(this); _la = _input->LA(1); - if (_la == SparqlAutomaticParser::T__6) { - setState(1296); - match(SparqlAutomaticParser::T__6); - setState(1297); + if (_la == SparqlAutomaticParser::T__7) { + setState(1510); + match(SparqlAutomaticParser::T__7); + setState(1511); expression(); } - setState(1300); + setState(1514); match(SparqlAutomaticParser::T__2); } catch (RecognitionException& e) { @@ -13422,7 +15796,7 @@ SparqlAutomaticParser::StrReplaceExpressionContext* SparqlAutomaticParser::strReplaceExpression() { StrReplaceExpressionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 230, SparqlAutomaticParser::RuleStrReplaceExpression); + enterRule(_localctx, 278, SparqlAutomaticParser::RuleStrReplaceExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -13434,31 +15808,31 @@ SparqlAutomaticParser::strReplaceExpression() { }); try { enterOuterAlt(_localctx, 1); - setState(1302); + setState(1516); match(SparqlAutomaticParser::REPLACE); - setState(1303); + setState(1517); match(SparqlAutomaticParser::T__1); - setState(1304); + setState(1518); expression(); - setState(1305); - match(SparqlAutomaticParser::T__6); - setState(1306); + setState(1519); + match(SparqlAutomaticParser::T__7); + setState(1520); expression(); - setState(1307); - match(SparqlAutomaticParser::T__6); - setState(1308); + setState(1521); + match(SparqlAutomaticParser::T__7); + setState(1522); expression(); - setState(1311); + setState(1525); _errHandler->sync(this); _la = _input->LA(1); - if (_la == SparqlAutomaticParser::T__6) { - setState(1309); - match(SparqlAutomaticParser::T__6); - setState(1310); + if (_la == SparqlAutomaticParser::T__7) { + setState(1523); + match(SparqlAutomaticParser::T__7); + setState(1524); expression(); } - setState(1313); + setState(1527); match(SparqlAutomaticParser::T__2); } catch (RecognitionException& e) { @@ -13513,7 +15887,7 @@ std::any SparqlAutomaticParser::ExistsFuncContext::accept( SparqlAutomaticParser::ExistsFuncContext* SparqlAutomaticParser::existsFunc() { ExistsFuncContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 232, SparqlAutomaticParser::RuleExistsFunc); + enterRule(_localctx, 280, SparqlAutomaticParser::RuleExistsFunc); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -13524,9 +15898,9 @@ SparqlAutomaticParser::ExistsFuncContext* SparqlAutomaticParser::existsFunc() { }); try { enterOuterAlt(_localctx, 1); - setState(1315); + setState(1529); match(SparqlAutomaticParser::EXISTS); - setState(1316); + setState(1530); groupGraphPattern(); } catch (RecognitionException& e) { @@ -13586,7 +15960,7 @@ SparqlAutomaticParser::NotExistsFuncContext* SparqlAutomaticParser::notExistsFunc() { NotExistsFuncContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 234, SparqlAutomaticParser::RuleNotExistsFunc); + enterRule(_localctx, 282, SparqlAutomaticParser::RuleNotExistsFunc); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -13597,11 +15971,11 @@ SparqlAutomaticParser::notExistsFunc() { }); try { enterOuterAlt(_localctx, 1); - setState(1318); + setState(1532); match(SparqlAutomaticParser::NOT); - setState(1319); + setState(1533); match(SparqlAutomaticParser::EXISTS); - setState(1320); + setState(1534); groupGraphPattern(); } catch (RecognitionException& e) { @@ -13693,7 +16067,7 @@ std::any SparqlAutomaticParser::AggregateContext::accept( SparqlAutomaticParser::AggregateContext* SparqlAutomaticParser::aggregate() { AggregateContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 236, SparqlAutomaticParser::RuleAggregate); + enterRule(_localctx, 284, SparqlAutomaticParser::RuleAggregate); size_t _la = 0; #if __cplusplus > 201703L @@ -13704,28 +16078,28 @@ SparqlAutomaticParser::AggregateContext* SparqlAutomaticParser::aggregate() { exitRule(); }); try { - setState(1386); + setState(1600); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::COUNT: { enterOuterAlt(_localctx, 1); - setState(1322); + setState(1536); match(SparqlAutomaticParser::COUNT); - setState(1323); + setState(1537); match(SparqlAutomaticParser::T__1); - setState(1325); + setState(1539); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::DISTINCT) { - setState(1324); + setState(1538); match(SparqlAutomaticParser::DISTINCT); } - setState(1329); + setState(1543); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::T__0: { - setState(1327); + setState(1541); match(SparqlAutomaticParser::T__0); break; } @@ -13816,7 +16190,7 @@ SparqlAutomaticParser::AggregateContext* SparqlAutomaticParser::aggregate() { case SparqlAutomaticParser::STRING_LITERAL2: case SparqlAutomaticParser::STRING_LITERAL_LONG1: case SparqlAutomaticParser::STRING_LITERAL_LONG2: { - setState(1328); + setState(1542); expression(); break; } @@ -13824,147 +16198,147 @@ SparqlAutomaticParser::AggregateContext* SparqlAutomaticParser::aggregate() { default: throw NoViableAltException(this); } - setState(1331); + setState(1545); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::SUM: { enterOuterAlt(_localctx, 2); - setState(1332); + setState(1546); match(SparqlAutomaticParser::SUM); - setState(1333); + setState(1547); match(SparqlAutomaticParser::T__1); - setState(1335); + setState(1549); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::DISTINCT) { - setState(1334); + setState(1548); match(SparqlAutomaticParser::DISTINCT); } - setState(1337); + setState(1551); expression(); - setState(1338); + setState(1552); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::MIN: { enterOuterAlt(_localctx, 3); - setState(1340); + setState(1554); match(SparqlAutomaticParser::MIN); - setState(1341); + setState(1555); match(SparqlAutomaticParser::T__1); - setState(1343); + setState(1557); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::DISTINCT) { - setState(1342); + setState(1556); match(SparqlAutomaticParser::DISTINCT); } - setState(1345); + setState(1559); expression(); - setState(1346); + setState(1560); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::MAX: { enterOuterAlt(_localctx, 4); - setState(1348); + setState(1562); match(SparqlAutomaticParser::MAX); - setState(1349); + setState(1563); match(SparqlAutomaticParser::T__1); - setState(1351); + setState(1565); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::DISTINCT) { - setState(1350); + setState(1564); match(SparqlAutomaticParser::DISTINCT); } - setState(1353); + setState(1567); expression(); - setState(1354); + setState(1568); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::AVG: { enterOuterAlt(_localctx, 5); - setState(1356); + setState(1570); match(SparqlAutomaticParser::AVG); - setState(1357); + setState(1571); match(SparqlAutomaticParser::T__1); - setState(1359); + setState(1573); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::DISTINCT) { - setState(1358); + setState(1572); match(SparqlAutomaticParser::DISTINCT); } - setState(1361); + setState(1575); expression(); - setState(1362); + setState(1576); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::SAMPLE: { enterOuterAlt(_localctx, 6); - setState(1364); + setState(1578); match(SparqlAutomaticParser::SAMPLE); - setState(1365); + setState(1579); match(SparqlAutomaticParser::T__1); - setState(1367); + setState(1581); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::DISTINCT) { - setState(1366); + setState(1580); match(SparqlAutomaticParser::DISTINCT); } - setState(1369); + setState(1583); expression(); - setState(1370); + setState(1584); match(SparqlAutomaticParser::T__2); break; } case SparqlAutomaticParser::GROUP_CONCAT: { enterOuterAlt(_localctx, 7); - setState(1372); + setState(1586); match(SparqlAutomaticParser::GROUP_CONCAT); - setState(1373); + setState(1587); match(SparqlAutomaticParser::T__1); - setState(1375); + setState(1589); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::DISTINCT) { - setState(1374); + setState(1588); match(SparqlAutomaticParser::DISTINCT); } - setState(1377); + setState(1591); expression(); - setState(1382); + setState(1596); _errHandler->sync(this); _la = _input->LA(1); - if (_la == SparqlAutomaticParser::T__7) { - setState(1378); - match(SparqlAutomaticParser::T__7); - setState(1379); + if (_la == SparqlAutomaticParser::T__5) { + setState(1592); + match(SparqlAutomaticParser::T__5); + setState(1593); match(SparqlAutomaticParser::SEPARATOR); - setState(1380); + setState(1594); match(SparqlAutomaticParser::T__19); - setState(1381); + setState(1595); string(); } - setState(1384); + setState(1598); match(SparqlAutomaticParser::T__2); break; } @@ -14027,7 +16401,7 @@ SparqlAutomaticParser::IriOrFunctionContext* SparqlAutomaticParser::iriOrFunction() { IriOrFunctionContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 238, SparqlAutomaticParser::RuleIriOrFunction); + enterRule(_localctx, 286, SparqlAutomaticParser::RuleIriOrFunction); size_t _la = 0; #if __cplusplus > 201703L @@ -14039,15 +16413,15 @@ SparqlAutomaticParser::iriOrFunction() { }); try { enterOuterAlt(_localctx, 1); - setState(1388); + setState(1602); iri(); - setState(1390); + setState(1604); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::T__1 || _la == SparqlAutomaticParser::NIL) { - setState(1389); + setState(1603); argList(); } @@ -14108,7 +16482,7 @@ std::any SparqlAutomaticParser::RdfLiteralContext::accept( SparqlAutomaticParser::RdfLiteralContext* SparqlAutomaticParser::rdfLiteral() { RdfLiteralContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 240, SparqlAutomaticParser::RuleRdfLiteral); + enterRule(_localctx, 288, SparqlAutomaticParser::RuleRdfLiteral); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -14119,21 +16493,21 @@ SparqlAutomaticParser::RdfLiteralContext* SparqlAutomaticParser::rdfLiteral() { }); try { enterOuterAlt(_localctx, 1); - setState(1392); + setState(1606); string(); - setState(1396); + setState(1610); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::LANGTAG: { - setState(1393); + setState(1607); match(SparqlAutomaticParser::LANGTAG); break; } case SparqlAutomaticParser::T__26: { - setState(1394); + setState(1608); match(SparqlAutomaticParser::T__26); - setState(1395); + setState(1609); iri(); break; } @@ -14266,7 +16640,7 @@ SparqlAutomaticParser::NumericLiteralContext* SparqlAutomaticParser::numericLiteral() { NumericLiteralContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 242, SparqlAutomaticParser::RuleNumericLiteral); + enterRule(_localctx, 290, SparqlAutomaticParser::RuleNumericLiteral); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -14276,14 +16650,14 @@ SparqlAutomaticParser::numericLiteral() { exitRule(); }); try { - setState(1401); + setState(1615); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::INTEGER: case SparqlAutomaticParser::DECIMAL: case SparqlAutomaticParser::DOUBLE: { enterOuterAlt(_localctx, 1); - setState(1398); + setState(1612); numericLiteralUnsigned(); break; } @@ -14292,7 +16666,7 @@ SparqlAutomaticParser::numericLiteral() { case SparqlAutomaticParser::DECIMAL_POSITIVE: case SparqlAutomaticParser::DOUBLE_POSITIVE: { enterOuterAlt(_localctx, 2); - setState(1399); + setState(1613); numericLiteralPositive(); break; } @@ -14301,7 +16675,7 @@ SparqlAutomaticParser::numericLiteral() { case SparqlAutomaticParser::DECIMAL_NEGATIVE: case SparqlAutomaticParser::DOUBLE_NEGATIVE: { enterOuterAlt(_localctx, 3); - setState(1400); + setState(1614); numericLiteralNegative(); break; } @@ -14373,7 +16747,7 @@ SparqlAutomaticParser::NumericLiteralUnsignedContext* SparqlAutomaticParser::numericLiteralUnsigned() { NumericLiteralUnsignedContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 244, SparqlAutomaticParser::RuleNumericLiteralUnsigned); + enterRule(_localctx, 292, SparqlAutomaticParser::RuleNumericLiteralUnsigned); size_t _la = 0; #if __cplusplus > 201703L @@ -14385,10 +16759,10 @@ SparqlAutomaticParser::numericLiteralUnsigned() { }); try { enterOuterAlt(_localctx, 1); - setState(1403); + setState(1617); _la = _input->LA(1); - if (!((((_la - 147) & ~0x3fULL) == 0) && - ((1ULL << (_la - 147)) & 7) != 0)) { + if (!((((_la - 149) & ~0x3fULL) == 0) && + ((1ULL << (_la - 149)) & 7) != 0)) { _errHandler->recoverInline(this); } else { _errHandler->reportMatch(this); @@ -14458,7 +16832,7 @@ SparqlAutomaticParser::NumericLiteralPositiveContext* SparqlAutomaticParser::numericLiteralPositive() { NumericLiteralPositiveContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 246, SparqlAutomaticParser::RuleNumericLiteralPositive); + enterRule(_localctx, 294, SparqlAutomaticParser::RuleNumericLiteralPositive); size_t _la = 0; #if __cplusplus > 201703L @@ -14470,10 +16844,10 @@ SparqlAutomaticParser::numericLiteralPositive() { }); try { enterOuterAlt(_localctx, 1); - setState(1405); + setState(1619); _la = _input->LA(1); - if (!((((_la - 150) & ~0x3fULL) == 0) && - ((1ULL << (_la - 150)) & 7) != 0)) { + if (!((((_la - 152) & ~0x3fULL) == 0) && + ((1ULL << (_la - 152)) & 7) != 0)) { _errHandler->recoverInline(this); } else { _errHandler->reportMatch(this); @@ -14543,7 +16917,7 @@ SparqlAutomaticParser::NumericLiteralNegativeContext* SparqlAutomaticParser::numericLiteralNegative() { NumericLiteralNegativeContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 248, SparqlAutomaticParser::RuleNumericLiteralNegative); + enterRule(_localctx, 296, SparqlAutomaticParser::RuleNumericLiteralNegative); size_t _la = 0; #if __cplusplus > 201703L @@ -14555,10 +16929,10 @@ SparqlAutomaticParser::numericLiteralNegative() { }); try { enterOuterAlt(_localctx, 1); - setState(1407); + setState(1621); _la = _input->LA(1); - if (!((((_la - 153) & ~0x3fULL) == 0) && - ((1ULL << (_la - 153)) & 7) != 0)) { + if (!((((_la - 155) & ~0x3fULL) == 0) && + ((1ULL << (_la - 155)) & 7) != 0)) { _errHandler->recoverInline(this); } else { _errHandler->reportMatch(this); @@ -14609,7 +16983,7 @@ SparqlAutomaticParser::BooleanLiteralContext* SparqlAutomaticParser::booleanLiteral() { BooleanLiteralContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 250, SparqlAutomaticParser::RuleBooleanLiteral); + enterRule(_localctx, 298, SparqlAutomaticParser::RuleBooleanLiteral); size_t _la = 0; #if __cplusplus > 201703L @@ -14621,7 +16995,7 @@ SparqlAutomaticParser::booleanLiteral() { }); try { enterOuterAlt(_localctx, 1); - setState(1409); + setState(1623); _la = _input->LA(1); if (!(_la == SparqlAutomaticParser::T__27 @@ -14693,7 +17067,7 @@ std::any SparqlAutomaticParser::StringContext::accept( SparqlAutomaticParser::StringContext* SparqlAutomaticParser::string() { StringContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 252, SparqlAutomaticParser::RuleString); + enterRule(_localctx, 300, SparqlAutomaticParser::RuleString); size_t _la = 0; #if __cplusplus > 201703L @@ -14705,10 +17079,10 @@ SparqlAutomaticParser::StringContext* SparqlAutomaticParser::string() { }); try { enterOuterAlt(_localctx, 1); - setState(1411); + setState(1625); _la = _input->LA(1); - if (!((((_la - 157) & ~0x3fULL) == 0) && - ((1ULL << (_la - 157)) & 15) != 0)) { + if (!((((_la - 159) & ~0x3fULL) == 0) && + ((1ULL << (_la - 159)) & 15) != 0)) { _errHandler->recoverInline(this); } else { _errHandler->reportMatch(this); @@ -14771,7 +17145,7 @@ std::any SparqlAutomaticParser::IriContext::accept( SparqlAutomaticParser::IriContext* SparqlAutomaticParser::iri() { IriContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 254, SparqlAutomaticParser::RuleIri); + enterRule(_localctx, 302, SparqlAutomaticParser::RuleIri); size_t _la = 0; #if __cplusplus > 201703L @@ -14783,26 +17157,26 @@ SparqlAutomaticParser::IriContext* SparqlAutomaticParser::iri() { }); try { enterOuterAlt(_localctx, 1); - setState(1414); + setState(1628); _errHandler->sync(this); _la = _input->LA(1); if (_la == SparqlAutomaticParser::PREFIX_LANGTAG) { - setState(1413); + setState(1627); match(SparqlAutomaticParser::PREFIX_LANGTAG); } - setState(1418); + setState(1632); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::IRI_REF: { - setState(1416); + setState(1630); iriref(); break; } case SparqlAutomaticParser::PNAME_NS: case SparqlAutomaticParser::PNAME_LN: { - setState(1417); + setState(1631); prefixedName(); break; } @@ -14865,7 +17239,7 @@ SparqlAutomaticParser::PrefixedNameContext* SparqlAutomaticParser::prefixedName() { PrefixedNameContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 256, SparqlAutomaticParser::RulePrefixedName); + enterRule(_localctx, 304, SparqlAutomaticParser::RulePrefixedName); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -14875,19 +17249,19 @@ SparqlAutomaticParser::prefixedName() { exitRule(); }); try { - setState(1422); + setState(1636); _errHandler->sync(this); switch (_input->LA(1)) { case SparqlAutomaticParser::PNAME_LN: { enterOuterAlt(_localctx, 1); - setState(1420); + setState(1634); pnameLn(); break; } case SparqlAutomaticParser::PNAME_NS: { enterOuterAlt(_localctx, 2); - setState(1421); + setState(1635); pnameNs(); break; } @@ -14948,7 +17322,7 @@ std::any SparqlAutomaticParser::BlankNodeContext::accept( SparqlAutomaticParser::BlankNodeContext* SparqlAutomaticParser::blankNode() { BlankNodeContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 258, SparqlAutomaticParser::RuleBlankNode); + enterRule(_localctx, 306, SparqlAutomaticParser::RuleBlankNode); size_t _la = 0; #if __cplusplus > 201703L @@ -14960,7 +17334,7 @@ SparqlAutomaticParser::BlankNodeContext* SparqlAutomaticParser::blankNode() { }); try { enterOuterAlt(_localctx, 1); - setState(1424); + setState(1638); _la = _input->LA(1); if (!(_la == SparqlAutomaticParser::BLANK_NODE_LABEL @@ -15018,7 +17392,7 @@ std::any SparqlAutomaticParser::IrirefContext::accept( SparqlAutomaticParser::IrirefContext* SparqlAutomaticParser::iriref() { IrirefContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 260, SparqlAutomaticParser::RuleIriref); + enterRule(_localctx, 308, SparqlAutomaticParser::RuleIriref); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -15029,7 +17403,7 @@ SparqlAutomaticParser::IrirefContext* SparqlAutomaticParser::iriref() { }); try { enterOuterAlt(_localctx, 1); - setState(1426); + setState(1640); match(SparqlAutomaticParser::IRI_REF); } catch (RecognitionException& e) { @@ -15079,7 +17453,7 @@ std::any SparqlAutomaticParser::PnameLnContext::accept( SparqlAutomaticParser::PnameLnContext* SparqlAutomaticParser::pnameLn() { PnameLnContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 262, SparqlAutomaticParser::RulePnameLn); + enterRule(_localctx, 310, SparqlAutomaticParser::RulePnameLn); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -15090,7 +17464,7 @@ SparqlAutomaticParser::PnameLnContext* SparqlAutomaticParser::pnameLn() { }); try { enterOuterAlt(_localctx, 1); - setState(1428); + setState(1642); match(SparqlAutomaticParser::PNAME_LN); } catch (RecognitionException& e) { @@ -15140,7 +17514,7 @@ std::any SparqlAutomaticParser::PnameNsContext::accept( SparqlAutomaticParser::PnameNsContext* SparqlAutomaticParser::pnameNs() { PnameNsContext* _localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 264, SparqlAutomaticParser::RulePnameNs); + enterRule(_localctx, 312, SparqlAutomaticParser::RulePnameNs); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -15151,7 +17525,7 @@ SparqlAutomaticParser::PnameNsContext* SparqlAutomaticParser::pnameNs() { }); try { enterOuterAlt(_localctx, 1); - setState(1430); + setState(1644); match(SparqlAutomaticParser::PNAME_NS); } catch (RecognitionException& e) { diff --git a/src/parser/sparqlParser/generated/SparqlAutomaticParser.h b/src/parser/sparqlParser/generated/SparqlAutomaticParser.h index 76eaebb1c2..c6f5215404 100644 --- a/src/parser/sparqlParser/generated/SparqlAutomaticParser.h +++ b/src/parser/sparqlParser/generated/SparqlAutomaticParser.h @@ -62,261 +62,287 @@ class SparqlAutomaticParser : public antlr4::Parser { VALUES = 52, LOAD = 53, SILENT = 54, - CLEAR = 55, - DROP = 56, - CREATE = 57, - ADD = 58, - DATA = 59, - MOVE = 60, - COPY = 61, - INSERT = 62, - DELETE = 63, - WITH = 64, - USING = 65, - DEFAULT = 66, - GRAPH = 67, - ALL = 68, - OPTIONAL = 69, - SERVICE = 70, - BIND = 71, - UNDEF = 72, - MINUS = 73, - UNION = 74, - FILTER = 75, - NOT = 76, - IN = 77, - STR = 78, - LANG = 79, - LANGMATCHES = 80, - DATATYPE = 81, - BOUND = 82, - IRI = 83, - URI = 84, - BNODE = 85, - RAND = 86, - ABS = 87, - CEIL = 88, - FLOOR = 89, - ROUND = 90, - CONCAT = 91, - STRLEN = 92, - UCASE = 93, - LCASE = 94, - ENCODE_FOR_URI = 95, - FOR = 96, - CONTAINS = 97, - STRSTARTS = 98, - STRENDS = 99, - STRBEFORE = 100, - STRAFTER = 101, - YEAR = 102, - MONTH = 103, - DAY = 104, - HOURS = 105, - MINUTES = 106, - SECONDS = 107, - TIMEZONE = 108, - TZ = 109, - NOW = 110, - UUID = 111, - STRUUID = 112, - SHA1 = 113, - SHA256 = 114, - SHA384 = 115, - SHA512 = 116, - MD5 = 117, - COALESCE = 118, - IF = 119, - STRLANG = 120, - STRDT = 121, - SAMETERM = 122, - ISIRI = 123, - ISURI = 124, - ISBLANK = 125, - ISLITERAL = 126, - ISNUMERIC = 127, - REGEX = 128, - SUBSTR = 129, - REPLACE = 130, - EXISTS = 131, - COUNT = 132, - SUM = 133, - MIN = 134, - MAX = 135, - AVG = 136, - SAMPLE = 137, - SEPARATOR = 138, - IRI_REF = 139, - PNAME_NS = 140, - PNAME_LN = 141, - BLANK_NODE_LABEL = 142, - VAR1 = 143, - VAR2 = 144, - LANGTAG = 145, - PREFIX_LANGTAG = 146, - INTEGER = 147, - DECIMAL = 148, - DOUBLE = 149, - INTEGER_POSITIVE = 150, - DECIMAL_POSITIVE = 151, - DOUBLE_POSITIVE = 152, - INTEGER_NEGATIVE = 153, - DECIMAL_NEGATIVE = 154, - DOUBLE_NEGATIVE = 155, - EXPONENT = 156, - STRING_LITERAL1 = 157, - STRING_LITERAL2 = 158, - STRING_LITERAL_LONG1 = 159, - STRING_LITERAL_LONG2 = 160, - ECHAR = 161, - NIL = 162, - ANON = 163, - PN_CHARS_U = 164, - VARNAME = 165, - PN_PREFIX = 166, - PN_LOCAL = 167, - PLX = 168, - PERCENT = 169, - HEX = 170, - PN_LOCAL_ESC = 171, - WS = 172, - COMMENTS = 173 + INTO = 55, + CLEAR = 56, + DROP = 57, + CREATE = 58, + ADD = 59, + TO = 60, + DATA = 61, + MOVE = 62, + COPY = 63, + INSERT = 64, + DELETE = 65, + WITH = 66, + USING = 67, + DEFAULT = 68, + GRAPH = 69, + ALL = 70, + OPTIONAL = 71, + SERVICE = 72, + BIND = 73, + UNDEF = 74, + MINUS = 75, + UNION = 76, + FILTER = 77, + NOT = 78, + IN = 79, + STR = 80, + LANG = 81, + LANGMATCHES = 82, + DATATYPE = 83, + BOUND = 84, + IRI = 85, + URI = 86, + BNODE = 87, + RAND = 88, + ABS = 89, + CEIL = 90, + FLOOR = 91, + ROUND = 92, + CONCAT = 93, + STRLEN = 94, + UCASE = 95, + LCASE = 96, + ENCODE_FOR_URI = 97, + FOR = 98, + CONTAINS = 99, + STRSTARTS = 100, + STRENDS = 101, + STRBEFORE = 102, + STRAFTER = 103, + YEAR = 104, + MONTH = 105, + DAY = 106, + HOURS = 107, + MINUTES = 108, + SECONDS = 109, + TIMEZONE = 110, + TZ = 111, + NOW = 112, + UUID = 113, + STRUUID = 114, + SHA1 = 115, + SHA256 = 116, + SHA384 = 117, + SHA512 = 118, + MD5 = 119, + COALESCE = 120, + IF = 121, + STRLANG = 122, + STRDT = 123, + SAMETERM = 124, + ISIRI = 125, + ISURI = 126, + ISBLANK = 127, + ISLITERAL = 128, + ISNUMERIC = 129, + REGEX = 130, + SUBSTR = 131, + REPLACE = 132, + EXISTS = 133, + COUNT = 134, + SUM = 135, + MIN = 136, + MAX = 137, + AVG = 138, + SAMPLE = 139, + SEPARATOR = 140, + IRI_REF = 141, + PNAME_NS = 142, + PNAME_LN = 143, + BLANK_NODE_LABEL = 144, + VAR1 = 145, + VAR2 = 146, + LANGTAG = 147, + PREFIX_LANGTAG = 148, + INTEGER = 149, + DECIMAL = 150, + DOUBLE = 151, + INTEGER_POSITIVE = 152, + DECIMAL_POSITIVE = 153, + DOUBLE_POSITIVE = 154, + INTEGER_NEGATIVE = 155, + DECIMAL_NEGATIVE = 156, + DOUBLE_NEGATIVE = 157, + EXPONENT = 158, + STRING_LITERAL1 = 159, + STRING_LITERAL2 = 160, + STRING_LITERAL_LONG1 = 161, + STRING_LITERAL_LONG2 = 162, + ECHAR = 163, + NIL = 164, + ANON = 165, + PN_CHARS_U = 166, + VARNAME = 167, + PN_PREFIX = 168, + PN_LOCAL = 169, + PLX = 170, + PERCENT = 171, + HEX = 172, + PN_LOCAL_ESC = 173, + WS = 174, + COMMENTS = 175 }; enum { - RuleQuery = 0, - RulePrologue = 1, - RuleBaseDecl = 2, - RulePrefixDecl = 3, - RuleSelectQuery = 4, - RuleSubSelect = 5, - RuleSelectClause = 6, - RuleVarOrAlias = 7, - RuleAlias = 8, - RuleAliasWithoutBrackets = 9, - RuleConstructQuery = 10, - RuleDescribeQuery = 11, - RuleAskQuery = 12, - RuleDatasetClause = 13, - RuleDefaultGraphClause = 14, - RuleNamedGraphClause = 15, - RuleSourceSelector = 16, - RuleWhereClause = 17, - RuleSolutionModifier = 18, - RuleGroupClause = 19, - RuleGroupCondition = 20, - RuleHavingClause = 21, - RuleHavingCondition = 22, - RuleOrderClause = 23, - RuleOrderCondition = 24, - RuleLimitOffsetClauses = 25, - RuleLimitClause = 26, - RuleOffsetClause = 27, - RuleTextLimitClause = 28, - RuleValuesClause = 29, - RuleTriplesTemplate = 30, - RuleGroupGraphPattern = 31, - RuleGroupGraphPatternSub = 32, - RuleGraphPatternNotTriplesAndMaybeTriples = 33, - RuleTriplesBlock = 34, - RuleGraphPatternNotTriples = 35, - RuleOptionalGraphPattern = 36, - RuleGraphGraphPattern = 37, - RuleServiceGraphPattern = 38, - RuleBind = 39, - RuleInlineData = 40, - RuleDataBlock = 41, - RuleInlineDataOneVar = 42, - RuleInlineDataFull = 43, - RuleDataBlockSingle = 44, - RuleDataBlockValue = 45, - RuleMinusGraphPattern = 46, - RuleGroupOrUnionGraphPattern = 47, - RuleFilterR = 48, - RuleConstraint = 49, - RuleFunctionCall = 50, - RuleArgList = 51, - RuleExpressionList = 52, - RuleConstructTemplate = 53, - RuleConstructTriples = 54, - RuleTriplesSameSubject = 55, - RulePropertyList = 56, - RulePropertyListNotEmpty = 57, - RuleVerb = 58, - RuleObjectList = 59, - RuleObjectR = 60, - RuleTriplesSameSubjectPath = 61, - RulePropertyListPath = 62, - RulePropertyListPathNotEmpty = 63, - RuleVerbPath = 64, - RuleVerbSimple = 65, - RuleTupleWithoutPath = 66, - RuleTupleWithPath = 67, - RuleVerbPathOrSimple = 68, - RuleObjectListPath = 69, - RuleObjectPath = 70, - RulePath = 71, - RulePathAlternative = 72, - RulePathSequence = 73, - RulePathElt = 74, - RulePathEltOrInverse = 75, - RulePathMod = 76, - RulePathPrimary = 77, - RulePathNegatedPropertySet = 78, - RulePathOneInPropertySet = 79, - RuleInteger = 80, - RuleTriplesNode = 81, - RuleBlankNodePropertyList = 82, - RuleTriplesNodePath = 83, - RuleBlankNodePropertyListPath = 84, - RuleCollection = 85, - RuleCollectionPath = 86, - RuleGraphNode = 87, - RuleGraphNodePath = 88, - RuleVarOrTerm = 89, - RuleVarOrIri = 90, - RuleVar = 91, - RuleGraphTerm = 92, - RuleExpression = 93, - RuleConditionalOrExpression = 94, - RuleConditionalAndExpression = 95, - RuleValueLogical = 96, - RuleRelationalExpression = 97, - RuleNumericExpression = 98, - RuleAdditiveExpression = 99, - RuleMultiplicativeExpressionWithSign = 100, - RulePlusSubexpression = 101, - RuleMinusSubexpression = 102, - RuleMultiplicativeExpressionWithLeadingSignButNoSpace = 103, - RuleMultiplicativeExpression = 104, - RuleMultiplyOrDivideExpression = 105, - RuleMultiplyExpression = 106, - RuleDivideExpression = 107, - RuleUnaryExpression = 108, - RulePrimaryExpression = 109, - RuleBrackettedExpression = 110, - RuleBuiltInCall = 111, - RuleRegexExpression = 112, - RuleLangExpression = 113, - RuleSubstringExpression = 114, - RuleStrReplaceExpression = 115, - RuleExistsFunc = 116, - RuleNotExistsFunc = 117, - RuleAggregate = 118, - RuleIriOrFunction = 119, - RuleRdfLiteral = 120, - RuleNumericLiteral = 121, - RuleNumericLiteralUnsigned = 122, - RuleNumericLiteralPositive = 123, - RuleNumericLiteralNegative = 124, - RuleBooleanLiteral = 125, - RuleString = 126, - RuleIri = 127, - RulePrefixedName = 128, - RuleBlankNode = 129, - RuleIriref = 130, - RulePnameLn = 131, - RulePnameNs = 132 + RuleQueryOrUpdate = 0, + RuleQuery = 1, + RulePrologue = 2, + RuleBaseDecl = 3, + RulePrefixDecl = 4, + RuleSelectQuery = 5, + RuleSubSelect = 6, + RuleSelectClause = 7, + RuleVarOrAlias = 8, + RuleAlias = 9, + RuleAliasWithoutBrackets = 10, + RuleConstructQuery = 11, + RuleDescribeQuery = 12, + RuleAskQuery = 13, + RuleDatasetClause = 14, + RuleDefaultGraphClause = 15, + RuleNamedGraphClause = 16, + RuleSourceSelector = 17, + RuleWhereClause = 18, + RuleSolutionModifier = 19, + RuleGroupClause = 20, + RuleGroupCondition = 21, + RuleHavingClause = 22, + RuleHavingCondition = 23, + RuleOrderClause = 24, + RuleOrderCondition = 25, + RuleLimitOffsetClauses = 26, + RuleLimitClause = 27, + RuleOffsetClause = 28, + RuleTextLimitClause = 29, + RuleValuesClause = 30, + RuleUpdate = 31, + RuleUpdate1 = 32, + RuleLoad = 33, + RuleClear = 34, + RuleDrop = 35, + RuleCreate = 36, + RuleAdd = 37, + RuleMove = 38, + RuleCopy = 39, + RuleInsertData = 40, + RuleDeleteData = 41, + RuleDeleteWhere = 42, + RuleModify = 43, + RuleDeleteClause = 44, + RuleInsertClause = 45, + RuleUsingClause = 46, + RuleGraphOrDefault = 47, + RuleGraphRef = 48, + RuleGraphRefAll = 49, + RuleQuadPattern = 50, + RuleQuadData = 51, + RuleQuads = 52, + RuleQuadsNotTriples = 53, + RuleTriplesTemplate = 54, + RuleGroupGraphPattern = 55, + RuleGroupGraphPatternSub = 56, + RuleGraphPatternNotTriplesAndMaybeTriples = 57, + RuleTriplesBlock = 58, + RuleGraphPatternNotTriples = 59, + RuleOptionalGraphPattern = 60, + RuleGraphGraphPattern = 61, + RuleServiceGraphPattern = 62, + RuleBind = 63, + RuleInlineData = 64, + RuleDataBlock = 65, + RuleInlineDataOneVar = 66, + RuleInlineDataFull = 67, + RuleDataBlockSingle = 68, + RuleDataBlockValue = 69, + RuleMinusGraphPattern = 70, + RuleGroupOrUnionGraphPattern = 71, + RuleFilterR = 72, + RuleConstraint = 73, + RuleFunctionCall = 74, + RuleArgList = 75, + RuleExpressionList = 76, + RuleConstructTemplate = 77, + RuleConstructTriples = 78, + RuleTriplesSameSubject = 79, + RulePropertyList = 80, + RulePropertyListNotEmpty = 81, + RuleVerb = 82, + RuleObjectList = 83, + RuleObjectR = 84, + RuleTriplesSameSubjectPath = 85, + RulePropertyListPath = 86, + RulePropertyListPathNotEmpty = 87, + RuleVerbPath = 88, + RuleVerbSimple = 89, + RuleTupleWithoutPath = 90, + RuleTupleWithPath = 91, + RuleVerbPathOrSimple = 92, + RuleObjectListPath = 93, + RuleObjectPath = 94, + RulePath = 95, + RulePathAlternative = 96, + RulePathSequence = 97, + RulePathElt = 98, + RulePathEltOrInverse = 99, + RulePathMod = 100, + RulePathPrimary = 101, + RulePathNegatedPropertySet = 102, + RulePathOneInPropertySet = 103, + RuleInteger = 104, + RuleTriplesNode = 105, + RuleBlankNodePropertyList = 106, + RuleTriplesNodePath = 107, + RuleBlankNodePropertyListPath = 108, + RuleCollection = 109, + RuleCollectionPath = 110, + RuleGraphNode = 111, + RuleGraphNodePath = 112, + RuleVarOrTerm = 113, + RuleVarOrIri = 114, + RuleVar = 115, + RuleGraphTerm = 116, + RuleExpression = 117, + RuleConditionalOrExpression = 118, + RuleConditionalAndExpression = 119, + RuleValueLogical = 120, + RuleRelationalExpression = 121, + RuleNumericExpression = 122, + RuleAdditiveExpression = 123, + RuleMultiplicativeExpressionWithSign = 124, + RulePlusSubexpression = 125, + RuleMinusSubexpression = 126, + RuleMultiplicativeExpressionWithLeadingSignButNoSpace = 127, + RuleMultiplicativeExpression = 128, + RuleMultiplyOrDivideExpression = 129, + RuleMultiplyExpression = 130, + RuleDivideExpression = 131, + RuleUnaryExpression = 132, + RulePrimaryExpression = 133, + RuleBrackettedExpression = 134, + RuleBuiltInCall = 135, + RuleRegexExpression = 136, + RuleLangExpression = 137, + RuleSubstringExpression = 138, + RuleStrReplaceExpression = 139, + RuleExistsFunc = 140, + RuleNotExistsFunc = 141, + RuleAggregate = 142, + RuleIriOrFunction = 143, + RuleRdfLiteral = 144, + RuleNumericLiteral = 145, + RuleNumericLiteralUnsigned = 146, + RuleNumericLiteralPositive = 147, + RuleNumericLiteralNegative = 148, + RuleBooleanLiteral = 149, + RuleString = 150, + RuleIri = 151, + RulePrefixedName = 152, + RuleBlankNode = 153, + RuleIriref = 154, + RulePnameLn = 155, + RulePnameNs = 156 }; explicit SparqlAutomaticParser(antlr4::TokenStream* input); @@ -336,6 +362,7 @@ class SparqlAutomaticParser : public antlr4::Parser { antlr4::atn::SerializedATNView getSerializedATN() const override; + class QueryOrUpdateContext; class QueryContext; class PrologueContext; class BaseDeclContext; @@ -366,6 +393,29 @@ class SparqlAutomaticParser : public antlr4::Parser { class OffsetClauseContext; class TextLimitClauseContext; class ValuesClauseContext; + class UpdateContext; + class Update1Context; + class LoadContext; + class ClearContext; + class DropContext; + class CreateContext; + class AddContext; + class MoveContext; + class CopyContext; + class InsertDataContext; + class DeleteDataContext; + class DeleteWhereContext; + class ModifyContext; + class DeleteClauseContext; + class InsertClauseContext; + class UsingClauseContext; + class GraphOrDefaultContext; + class GraphRefContext; + class GraphRefAllContext; + class QuadPatternContext; + class QuadDataContext; + class QuadsContext; + class QuadsNotTriplesContext; class TriplesTemplateContext; class GroupGraphPatternContext; class GroupGraphPatternSubContext; @@ -470,13 +520,29 @@ class SparqlAutomaticParser : public antlr4::Parser { class PnameLnContext; class PnameNsContext; + class QueryOrUpdateContext : public antlr4::ParserRuleContext { + public: + QueryOrUpdateContext(antlr4::ParserRuleContext* parent, + size_t invokingState); + virtual size_t getRuleIndex() const override; + QueryContext* query(); + UpdateContext* update(); + antlr4::tree::TerminalNode* EOF(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + QueryOrUpdateContext* queryOrUpdate(); + class QueryContext : public antlr4::ParserRuleContext { public: QueryContext(antlr4::ParserRuleContext* parent, size_t invokingState); virtual size_t getRuleIndex() const override; PrologueContext* prologue(); ValuesClauseContext* valuesClause(); - antlr4::tree::TerminalNode* EOF(); SelectQueryContext* selectQuery(); ConstructQueryContext* constructQuery(); DescribeQueryContext* describeQuery(); @@ -981,6 +1047,395 @@ class SparqlAutomaticParser : public antlr4::Parser { ValuesClauseContext* valuesClause(); + class UpdateContext : public antlr4::ParserRuleContext { + public: + UpdateContext(antlr4::ParserRuleContext* parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + PrologueContext* prologue(); + Update1Context* update1(); + UpdateContext* update(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + UpdateContext* update(); + + class Update1Context : public antlr4::ParserRuleContext { + public: + Update1Context(antlr4::ParserRuleContext* parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + LoadContext* load(); + ClearContext* clear(); + DropContext* drop(); + AddContext* add(); + MoveContext* move(); + CopyContext* copy(); + CreateContext* create(); + InsertDataContext* insertData(); + DeleteDataContext* deleteData(); + DeleteWhereContext* deleteWhere(); + ModifyContext* modify(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + Update1Context* update1(); + + class LoadContext : public antlr4::ParserRuleContext { + public: + LoadContext(antlr4::ParserRuleContext* parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + antlr4::tree::TerminalNode* LOAD(); + IriContext* iri(); + antlr4::tree::TerminalNode* SILENT(); + antlr4::tree::TerminalNode* INTO(); + GraphRefContext* graphRef(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + LoadContext* load(); + + class ClearContext : public antlr4::ParserRuleContext { + public: + ClearContext(antlr4::ParserRuleContext* parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + antlr4::tree::TerminalNode* CLEAR(); + GraphRefAllContext* graphRefAll(); + antlr4::tree::TerminalNode* SILENT(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + ClearContext* clear(); + + class DropContext : public antlr4::ParserRuleContext { + public: + DropContext(antlr4::ParserRuleContext* parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + antlr4::tree::TerminalNode* DROP(); + GraphRefAllContext* graphRefAll(); + antlr4::tree::TerminalNode* SILENT(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + DropContext* drop(); + + class CreateContext : public antlr4::ParserRuleContext { + public: + CreateContext(antlr4::ParserRuleContext* parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + antlr4::tree::TerminalNode* CREATE(); + GraphRefContext* graphRef(); + antlr4::tree::TerminalNode* SILENT(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + CreateContext* create(); + + class AddContext : public antlr4::ParserRuleContext { + public: + AddContext(antlr4::ParserRuleContext* parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + antlr4::tree::TerminalNode* ADD(); + std::vector graphOrDefault(); + GraphOrDefaultContext* graphOrDefault(size_t i); + antlr4::tree::TerminalNode* TO(); + antlr4::tree::TerminalNode* SILENT(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + AddContext* add(); + + class MoveContext : public antlr4::ParserRuleContext { + public: + MoveContext(antlr4::ParserRuleContext* parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + antlr4::tree::TerminalNode* MOVE(); + std::vector graphOrDefault(); + GraphOrDefaultContext* graphOrDefault(size_t i); + antlr4::tree::TerminalNode* TO(); + antlr4::tree::TerminalNode* SILENT(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + MoveContext* move(); + + class CopyContext : public antlr4::ParserRuleContext { + public: + CopyContext(antlr4::ParserRuleContext* parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + antlr4::tree::TerminalNode* COPY(); + std::vector graphOrDefault(); + GraphOrDefaultContext* graphOrDefault(size_t i); + antlr4::tree::TerminalNode* TO(); + antlr4::tree::TerminalNode* SILENT(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + CopyContext* copy(); + + class InsertDataContext : public antlr4::ParserRuleContext { + public: + InsertDataContext(antlr4::ParserRuleContext* parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + antlr4::tree::TerminalNode* INSERT(); + antlr4::tree::TerminalNode* DATA(); + QuadDataContext* quadData(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + InsertDataContext* insertData(); + + class DeleteDataContext : public antlr4::ParserRuleContext { + public: + DeleteDataContext(antlr4::ParserRuleContext* parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + antlr4::tree::TerminalNode* DELETE(); + antlr4::tree::TerminalNode* DATA(); + QuadDataContext* quadData(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + DeleteDataContext* deleteData(); + + class DeleteWhereContext : public antlr4::ParserRuleContext { + public: + DeleteWhereContext(antlr4::ParserRuleContext* parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + antlr4::tree::TerminalNode* DELETE(); + antlr4::tree::TerminalNode* WHERE(); + QuadPatternContext* quadPattern(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + DeleteWhereContext* deleteWhere(); + + class ModifyContext : public antlr4::ParserRuleContext { + public: + ModifyContext(antlr4::ParserRuleContext* parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + antlr4::tree::TerminalNode* WHERE(); + GroupGraphPatternContext* groupGraphPattern(); + DeleteClauseContext* deleteClause(); + InsertClauseContext* insertClause(); + antlr4::tree::TerminalNode* WITH(); + IriContext* iri(); + std::vector usingClause(); + UsingClauseContext* usingClause(size_t i); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + ModifyContext* modify(); + + class DeleteClauseContext : public antlr4::ParserRuleContext { + public: + DeleteClauseContext(antlr4::ParserRuleContext* parent, + size_t invokingState); + virtual size_t getRuleIndex() const override; + antlr4::tree::TerminalNode* DELETE(); + QuadPatternContext* quadPattern(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + DeleteClauseContext* deleteClause(); + + class InsertClauseContext : public antlr4::ParserRuleContext { + public: + InsertClauseContext(antlr4::ParserRuleContext* parent, + size_t invokingState); + virtual size_t getRuleIndex() const override; + antlr4::tree::TerminalNode* INSERT(); + QuadPatternContext* quadPattern(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + InsertClauseContext* insertClause(); + + class UsingClauseContext : public antlr4::ParserRuleContext { + public: + UsingClauseContext(antlr4::ParserRuleContext* parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + antlr4::tree::TerminalNode* USING(); + antlr4::tree::TerminalNode* IRI(); + antlr4::tree::TerminalNode* NAMED(); + IriContext* iri(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + UsingClauseContext* usingClause(); + + class GraphOrDefaultContext : public antlr4::ParserRuleContext { + public: + GraphOrDefaultContext(antlr4::ParserRuleContext* parent, + size_t invokingState); + virtual size_t getRuleIndex() const override; + antlr4::tree::TerminalNode* DEFAULT(); + antlr4::tree::TerminalNode* GRAPH(); + IriContext* iri(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + GraphOrDefaultContext* graphOrDefault(); + + class GraphRefContext : public antlr4::ParserRuleContext { + public: + GraphRefContext(antlr4::ParserRuleContext* parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + antlr4::tree::TerminalNode* GRAPH(); + IriContext* iri(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + GraphRefContext* graphRef(); + + class GraphRefAllContext : public antlr4::ParserRuleContext { + public: + GraphRefAllContext(antlr4::ParserRuleContext* parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + GraphRefContext* graphRef(); + antlr4::tree::TerminalNode* DEFAULT(); + antlr4::tree::TerminalNode* NAMED(); + antlr4::tree::TerminalNode* ALL(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + GraphRefAllContext* graphRefAll(); + + class QuadPatternContext : public antlr4::ParserRuleContext { + public: + QuadPatternContext(antlr4::ParserRuleContext* parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + QuadsContext* quads(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + QuadPatternContext* quadPattern(); + + class QuadDataContext : public antlr4::ParserRuleContext { + public: + QuadDataContext(antlr4::ParserRuleContext* parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + QuadsContext* quads(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + QuadDataContext* quadData(); + + class QuadsContext : public antlr4::ParserRuleContext { + public: + QuadsContext(antlr4::ParserRuleContext* parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + std::vector triplesTemplate(); + TriplesTemplateContext* triplesTemplate(size_t i); + std::vector quadsNotTriples(); + QuadsNotTriplesContext* quadsNotTriples(size_t i); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + QuadsContext* quads(); + + class QuadsNotTriplesContext : public antlr4::ParserRuleContext { + public: + QuadsNotTriplesContext(antlr4::ParserRuleContext* parent, + size_t invokingState); + virtual size_t getRuleIndex() const override; + antlr4::tree::TerminalNode* GRAPH(); + VarOrIriContext* varOrIri(); + TriplesTemplateContext* triplesTemplate(); + + virtual void enterRule(antlr4::tree::ParseTreeListener* listener) override; + virtual void exitRule(antlr4::tree::ParseTreeListener* listener) override; + + virtual std::any accept(antlr4::tree::ParseTreeVisitor* visitor) override; + }; + + QuadsNotTriplesContext* quadsNotTriples(); + class TriplesTemplateContext : public antlr4::ParserRuleContext { public: TriplesTemplateContext(antlr4::ParserRuleContext* parent, diff --git a/src/parser/sparqlParser/generated/SparqlAutomaticVisitor.h b/src/parser/sparqlParser/generated/SparqlAutomaticVisitor.h index 00229cb010..338b434ebe 100644 --- a/src/parser/sparqlParser/generated/SparqlAutomaticVisitor.h +++ b/src/parser/sparqlParser/generated/SparqlAutomaticVisitor.h @@ -15,6 +15,9 @@ class SparqlAutomaticVisitor : public antlr4::tree::AbstractParseTreeVisitor { /** * Visit parse trees produced by SparqlAutomaticParser. */ + virtual std::any visitQueryOrUpdate( + SparqlAutomaticParser::QueryOrUpdateContext* context) = 0; + virtual std::any visitQuery(SparqlAutomaticParser::QueryContext* context) = 0; virtual std::any visitPrologue( @@ -103,6 +106,68 @@ class SparqlAutomaticVisitor : public antlr4::tree::AbstractParseTreeVisitor { virtual std::any visitValuesClause( SparqlAutomaticParser::ValuesClauseContext* context) = 0; + virtual std::any visitUpdate( + SparqlAutomaticParser::UpdateContext* context) = 0; + + virtual std::any visitUpdate1( + SparqlAutomaticParser::Update1Context* context) = 0; + + virtual std::any visitLoad(SparqlAutomaticParser::LoadContext* context) = 0; + + virtual std::any visitClear(SparqlAutomaticParser::ClearContext* context) = 0; + + virtual std::any visitDrop(SparqlAutomaticParser::DropContext* context) = 0; + + virtual std::any visitCreate( + SparqlAutomaticParser::CreateContext* context) = 0; + + virtual std::any visitAdd(SparqlAutomaticParser::AddContext* context) = 0; + + virtual std::any visitMove(SparqlAutomaticParser::MoveContext* context) = 0; + + virtual std::any visitCopy(SparqlAutomaticParser::CopyContext* context) = 0; + + virtual std::any visitInsertData( + SparqlAutomaticParser::InsertDataContext* context) = 0; + + virtual std::any visitDeleteData( + SparqlAutomaticParser::DeleteDataContext* context) = 0; + + virtual std::any visitDeleteWhere( + SparqlAutomaticParser::DeleteWhereContext* context) = 0; + + virtual std::any visitModify( + SparqlAutomaticParser::ModifyContext* context) = 0; + + virtual std::any visitDeleteClause( + SparqlAutomaticParser::DeleteClauseContext* context) = 0; + + virtual std::any visitInsertClause( + SparqlAutomaticParser::InsertClauseContext* context) = 0; + + virtual std::any visitUsingClause( + SparqlAutomaticParser::UsingClauseContext* context) = 0; + + virtual std::any visitGraphOrDefault( + SparqlAutomaticParser::GraphOrDefaultContext* context) = 0; + + virtual std::any visitGraphRef( + SparqlAutomaticParser::GraphRefContext* context) = 0; + + virtual std::any visitGraphRefAll( + SparqlAutomaticParser::GraphRefAllContext* context) = 0; + + virtual std::any visitQuadPattern( + SparqlAutomaticParser::QuadPatternContext* context) = 0; + + virtual std::any visitQuadData( + SparqlAutomaticParser::QuadDataContext* context) = 0; + + virtual std::any visitQuads(SparqlAutomaticParser::QuadsContext* context) = 0; + + virtual std::any visitQuadsNotTriples( + SparqlAutomaticParser::QuadsNotTriplesContext* context) = 0; + virtual std::any visitTriplesTemplate( SparqlAutomaticParser::TriplesTemplateContext* context) = 0; diff --git a/src/util/AsyncStream.h b/src/util/AsyncStream.h index e5a0c281c9..b5d664d926 100644 --- a/src/util/AsyncStream.h +++ b/src/util/AsyncStream.h @@ -45,8 +45,8 @@ cppcoro::generator runStreamAsync( queue.finish(); }}; - // Only rethrow an exception from the `thread` if no exception occured in this - // thread to avoid crashes because of multiple active exceptions. + // Only rethrow an exception from the `thread` if no exception occurred in + // this thread to avoid crashes because of multiple active exceptions. auto cleanup = ad_utility::makeOnDestructionDontThrowDuringStackUnwinding( [&queue, &thread, &exception] { queue.finish(); diff --git a/src/util/Cache.h b/src/util/Cache.h index 648e3315d8..1c7eb5923c 100644 --- a/src/util/Cache.h +++ b/src/util/Cache.h @@ -478,7 +478,7 @@ class TreeBasedLRUCache }; /// typedef for the simple name LRUCache that is fixed to one of the possible -/// implementations at compiletime +/// implementations at compile time #ifdef _QLEVER_USE_TREE_BASED_CACHE template ValueSizeGetter> using LRUCache = TreeBasedLRUCache; diff --git a/src/util/CancellationHandle.h b/src/util/CancellationHandle.h index c928772eca..0e62a01c61 100644 --- a/src/util/CancellationHandle.h +++ b/src/util/CancellationHandle.h @@ -64,7 +64,7 @@ AD_ALWAYS_INLINE constexpr bool isCancelled( /// Helper struct to allow to conditionally compile fields into a class. struct Empty { - // Ignore potential assigment + // Ignore potential assignment template explicit Empty(const Args&...) {} }; diff --git a/src/util/ConfigManager/ConfigManager.cpp b/src/util/ConfigManager/ConfigManager.cpp index a4b7ab2813..12d7db1313 100644 --- a/src/util/ConfigManager/ConfigManager.cpp +++ b/src/util/ConfigManager/ConfigManager.cpp @@ -298,7 +298,7 @@ std::string ConfigManager::createJsonPointerString( std::ostringstream pointerString; // We don't use a `lazyStrJoin` here, so that an empty `keys` produces an - // emptry string. + // empty string. std::ranges::for_each( keys, [&escapeSpecialCharacters, &pointerString](std::string_view key) { pointerString << "/" << escapeSpecialCharacters(key); @@ -386,7 +386,7 @@ void ConfigManager::verifyPath(const std::vector& path) const { `some/options/optionA` in json pointer terms, but in string terms, because `"option"` is a prefix of `"options"`. - This can be fixed, by adding the seperator `/` at the end of both + This can be fixed, by adding the separator `/` at the end of both string representation. Because the symbol `/` is not allowed in `xi`, for `any i in [0, N]`, but must be between them, it forces all the `xi` and `yi` to be equal. diff --git a/src/util/ConfigManager/ConfigManager.h b/src/util/ConfigManager/ConfigManager.h index 9c9ddacbdd..63d44eed04 100644 --- a/src/util/ConfigManager/ConfigManager.h +++ b/src/util/ConfigManager/ConfigManager.h @@ -44,7 +44,7 @@ class ConfigManager { Our hash map always saves either a configuration option, or a sub manager (another `ConfigManager`). - This class makes the handeling more explicit and allows for more information + This class makes the handling more explicit and allows for more information to be saved alongside the configuration options and sub managers. For example: The order, in which they were created. */ @@ -285,13 +285,13 @@ class ConfigManager { /* @brief Returns a string containing a json configuration and, optionally, the - string representations of all added configuration options, togehter with the + string representations of all added configuration options, together with the validator invariants. @param detailed Iff false, only print the json configuration. Otherwise, print the json configuration, followed by the string representations of all added configuration options, which contain more detailed information about the - configuration options, togehter with the validator invariants + configuration options, together with the validator invariants */ std::string printConfigurationDoc(bool detailed) const; @@ -309,7 +309,7 @@ class ConfigManager { get thrown, if the `validatorFunction` returns false. @param validatorDescriptor A description of the invariant, that `validatorFunction` imposes. - @param configOptionsToBeChecked Proxies for the configuration options, whos + @param configOptionsToBeChecked Proxies for the configuration options, whose values will be passed to the validator function as function arguments. Will keep the same order. */ @@ -552,7 +552,7 @@ class ConfigManager { /* We can't just create a `ConfigOption` variable, pass it and return it, because the hash map has ownership of the newly added `ConfigOption`. - Which was transfered via creating a new internal `ConfigOption` with move + Which was transferred via creating a new internal `ConfigOption` with move constructors. Which would mean, that our local `ConfigOption` isn't the `ConfigOption` we want to return a reference to. diff --git a/src/util/ConfigManager/ConfigOption.cpp b/src/util/ConfigManager/ConfigOption.cpp index 42984f3d4d..26249649f7 100644 --- a/src/util/ConfigManager/ConfigOption.cpp +++ b/src/util/ConfigManager/ConfigOption.cpp @@ -70,7 +70,7 @@ bool ConfigOption::wasSet() const { void ConfigOption::setValueWithJson(const nlohmann::json& json) { // TODO Use "deducing this" for simpler recursive lambdas. /* - Manually checks, if the json represents one of the possibilites of + Manually checks, if the json represents one of the possibilities of `AvailableTypes`. */ auto isValueTypeSubType = [](const nlohmann::json& j, diff --git a/src/util/ConfigManager/ConfigOption.h b/src/util/ConfigManager/ConfigOption.h index b2abed3793..f80fd5183f 100644 --- a/src/util/ConfigManager/ConfigOption.h +++ b/src/util/ConfigManager/ConfigOption.h @@ -42,7 +42,7 @@ class ConfigOption { private: /* - Holds the type dependant data of the class, because the class is not a + Holds the type dependent data of the class, because the class is not a templated class, but sometimes behaves like one. */ template diff --git a/src/util/ConfigManager/Validator.h b/src/util/ConfigManager/Validator.h index f0d68cfad8..8400332b31 100644 --- a/src/util/ConfigManager/Validator.h +++ b/src/util/ConfigManager/Validator.h @@ -30,7 +30,7 @@ concept ValidatorFunction = RegularInvocableWithSimilarReturnType; // Simple struct, that holds an error message. For use as the return type of -// invocable object, that fullfill `ExceptionValidator`. +// invocable object, that fulfill `ExceptionValidator`. struct ErrorMessage { private: std::string message_; @@ -100,7 +100,7 @@ class ConfigOptionValidatorManager { */ std::function wrappedValidatorFunction_; - // A descripton of the invariant, this validator imposes. + // A description of the invariant, this validator imposes. std::string descriptor_; // Pointer to the `configOption`, that will be checked. diff --git a/src/util/ConstexprUtils.h b/src/util/ConstexprUtils.h index d53745ee28..90b40e6ab8 100644 --- a/src/util/ConstexprUtils.h +++ b/src/util/ConstexprUtils.h @@ -18,7 +18,7 @@ namespace ad_utility { // Compute `base ^ exponent` where `^` denotes exponentiation. This is consteval // because for all runtime calls, a better optimized algorithm from the standard // library should be chosen. -// TODO why can't this be consteval when the result is boudn to a +// TODO why can't this be consteval when the result is bound to a // `constexpr` variable? constexpr auto pow(auto base, int exponent) { if (exponent < 0) { diff --git a/src/util/CopyableUniquePtr.h b/src/util/CopyableUniquePtr.h index 08e37f7bf1..f3cc4cbe2f 100644 --- a/src/util/CopyableUniquePtr.h +++ b/src/util/CopyableUniquePtr.h @@ -14,8 +14,8 @@ namespace ad_utility { /* -A version of `std::unique_ptr` with a copy assigment operator and a copy -constructor, which both copy the dereferenced pointer to create a new instace +A version of `std::unique_ptr` with a copy assignment operator and a copy +constructor, which both copy the dereferenced pointer to create a new instance of the object for the `unique_ptr`. Currently not written with support for dynamically-allocated array of objects in mind, so that may not work. diff --git a/src/util/CryptographicHashUtils.h b/src/util/CryptographicHashUtils.h new file mode 100644 index 0000000000..90094d355a --- /dev/null +++ b/src/util/CryptographicHashUtils.h @@ -0,0 +1,58 @@ +// Copyright 2024, University of Freiburg, +// Chair of Algorithms and Data Structures +// Author: Hannes Baumann + +#pragma once + +#include +#include +#include +#include + +#include +#include + +namespace ad_utility { +// `hashImpl` is a templated lambda function which returns for given input +// string the respective hash (hex) by applying the `HashEvpFunc` +// function from openssl over the provided `openssl/evp.h` high level interface. +template +inline constexpr auto hashImpl = + [](const std::string_view& str) -> std::vector { + EVP_MD_CTX* ctx = EVP_MD_CTX_new(); + auto md = HashEvpFunc(); + std::vector hexHash(DigestLength); + EVP_DigestInit_ex(ctx, md, nullptr); + EVP_DigestUpdate(ctx, str.data(), str.length()); + EVP_DigestFinal(ctx, hexHash.data(), nullptr); + EVP_MD_CTX_free(ctx); + return hexHash; +}; + +// lambda function which enables conversion of hash value to +// hex hash string (`std::string`) with `absl` library. +inline constexpr auto hexFormatter = [](std::string* out, char c) { + return absl::AlphaNumFormatter()(out, absl::Hex(c, absl::kZeroPad2)); +}; + +// `HashMd5` takes an argument of type `std::string_view` and provides +// a Hex value by applying `EVP_md5()` from the openssl library as a result. +constexpr auto hashMd5 = hashImpl<&EVP_md5, MD5_DIGEST_LENGTH>; + +// `HashSha1` takes an argument of type `std::string_view` and provides +// a Hex by applying `EVP_sha1()` from the openssl library as a result. +constexpr auto hashSha1 = hashImpl<&EVP_sha1, SHA_DIGEST_LENGTH>; + +// `HashSha256` takes an argument of type `std::string_view` and provides +// a Hex by applying `EVP_sha256()` from the openssl library as a result. +constexpr auto hashSha256 = hashImpl<&EVP_sha256, SHA256_DIGEST_LENGTH>; + +// `HashSha384` takes an argument of type `std::string_view` and provides +// a Hex by applying `EVP_sha384()` from the openssl library as a result. +constexpr auto hashSha384 = hashImpl<&EVP_sha384, SHA384_DIGEST_LENGTH>; + +// `HashSha512` takes an argument of type `std::string_view` and provides +// a Hex by applying `EVP_sha512()` from the openssl library as a result. +constexpr auto hashSha512 = hashImpl<&EVP_sha512, SHA512_DIGEST_LENGTH>; + +} // namespace ad_utility diff --git a/src/util/Date.cpp b/src/util/Date.cpp index afc5e078b1..d5e821a112 100644 --- a/src/util/Date.cpp +++ b/src/util/Date.cpp @@ -281,3 +281,12 @@ std::optional DateOrLargeYear::getDay() const { return 1; } } + +// _____________________________________________________________________- +std::string DateOrLargeYear::getStrTimezone() const { + if (isDate()) { + return getDateUnchecked().formatTimeZone(); + } else { + return ""; + } +} diff --git a/src/util/Date.h b/src/util/Date.h index 89e2d0db4f..51f0ac7c78 100644 --- a/src/util/Date.h +++ b/src/util/Date.h @@ -192,7 +192,7 @@ class Date { /// Convert a `uint64_t` to a `Date`. This is only valid if the `uint64_t` was /// obtained via a call to `Date::toBits()`. This just casts the underlying - /// representaion. + /// representation. static constexpr Date fromBits(uint64_t bytes) { return std::bit_cast(bytes); } @@ -396,6 +396,11 @@ class DateOrLargeYear { // Similar to `getMonth`, but get the day. std::optional getDay() const; + // Get the timezone if there is an underlying complete `Date` w.r.t. this + // DateOrLargeYear object. This implementation is necessary for the + // `tz()`-function. + std::string getStrTimezone() const; + Type getType() const { return static_cast(ad_utility::bitMaskForLowerBits(numTypeBits) & bits_); @@ -408,7 +413,7 @@ class DateOrLargeYear { // format used by Wikidata). std::pair toStringAndType() const; - // The bitwise comparison also correpsonds to the semantic ordering of years + // The bitwise comparison also corresponds to the semantic ordering of years // and dates. auto operator<=>(const DateOrLargeYear&) const = default; diff --git a/src/util/Exception.h b/src/util/Exception.h index 18278c75d7..a317a02350 100644 --- a/src/util/Exception.h +++ b/src/util/Exception.h @@ -102,7 +102,7 @@ std::string getMessageImpl( } // Helper function used to format the arguments passed to `AD_CONTRACT_CHECK` -// etc. Return "" followed by +// etc. Return "" followed by // a full stop and space if there is at least one message. std::string concatMessages(auto&&... messages) { if constexpr (sizeof...(messages) == 0) { diff --git a/src/util/File.h b/src/util/File.h index b895c01d84..cde77a4aaf 100644 --- a/src/util/File.h +++ b/src/util/File.h @@ -222,7 +222,7 @@ Stream makeFilestream(const std::filesystem::path& path, auto&&... args) { } // namespace detail // Open and return a std::ifstream from a given filename and optional -// additionals `args`. Throw an exception stating the filename and the absolute +// additional `args`. Throw an exception stating the filename and the absolute // path when the file can't be opened. std::ifstream makeIfstream(const std::filesystem::path& path, auto&&... args) { return detail::makeFilestream(path, AD_FWD(args)...); diff --git a/src/util/JoinAlgorithms/JoinAlgorithms.h b/src/util/JoinAlgorithms/JoinAlgorithms.h index 12e39859f4..5b3e9de8d9 100644 --- a/src/util/JoinAlgorithms/JoinAlgorithms.h +++ b/src/util/JoinAlgorithms/JoinAlgorithms.h @@ -158,7 +158,7 @@ template (const T& row) { if constexpr (isSimilar && @@ -662,7 +662,7 @@ class BlockAndSubrange { // A helper struct for the zipper join on blocks algorithm (see below). It // combines the current iterator, then end iterator, the relevant projection to -// obtain the input to the comparsion, and a buffer for blocks that are +// obtain the input to the comparison, and a buffer for blocks that are // currently required by the join algorithm for one side of the join. template struct JoinSide { diff --git a/src/util/MemorySize/MemorySize.h b/src/util/MemorySize/MemorySize.h index 7fe86be8ad..59d7e47a19 100644 --- a/src/util/MemorySize/MemorySize.h +++ b/src/util/MemorySize/MemorySize.h @@ -66,7 +66,7 @@ class MemorySize { /* Factory functions for creating an instance of this class with the wanted - memory size saved internally. Always requries the exact memory size unit and + memory size saved internally. Always requires the exact memory size unit and size wanted. */ template @@ -175,7 +175,7 @@ constexpr ConstexprMap numBytesPerUnit( /* Helper function for dividing two instances of `size_t`. Needed, because there is no `std` division function, that takes unconverted -`size_t`.This tends to lead to error and unprecise results. This function +`size_t`.This tends to lead to error and imprecise results. This function however, should be about as precise as possible, when having the return type `double`. */ @@ -222,7 +222,7 @@ template constexpr size_t convertMemoryUnitsToBytes(const T amountOfUnits, std::string_view unitName) { if constexpr (std::is_signed_v) { - // Negativ values makes no sense. + // Negative values makes no sense. AD_CONTRACT_CHECK(amountOfUnits >= 0); } @@ -267,7 +267,7 @@ multiplied/divied with. `MemorySize` records. It will be given the amount of bytes in `m`, followed by `c` for this calculation. Both will either have been cast to `size_t`, or `double.` Note, that the rounding and casting to `size_t` for floating point -return types will be automaticly done, and can be ignored by `func`. +return types will be automatically done, and can be ignored by `func`. */ template requires std::invocable || @@ -289,7 +289,7 @@ constexpr MemorySize magicImplForDivAndMul(const MemorySize& m, const T c, template constexpr MemorySize MemorySize::bytes(T numBytes) { if constexpr (std::is_signed_v) { - // Doesn't make much sense to a negativ amount of memory. + // Doesn't make much sense to a negative amount of memory. AD_CONTRACT_CHECK(numBytes >= 0); } diff --git a/src/util/MmapVector.h b/src/util/MmapVector.h index 9f99af080e..447f219834 100644 --- a/src/util/MmapVector.h +++ b/src/util/MmapVector.h @@ -161,13 +161,13 @@ class MmapVector { } // create Array of given size fill with default value - // file contents will be overriden if existing! + // file contents will be overridden if existing! // allows read and write access void open(size_t size, const T& defaultValue, string filename, AccessPattern pattern = AccessPattern::None); - // create unititialized array of given size at path specified by filename - // file will be created or overriden! + // create uninitialized array of given size at path specified by filename + // file will be created or overridden! // allows read and write access void open(size_t size, string filename, AccessPattern pattern = AccessPattern::None); @@ -305,7 +305,7 @@ class MmapVectorView : private MmapVector { // ____________________________________________________ size_t size() const { return MmapVector::size(); } - // default constructor, leaves an unitialized vector that will throw until a + // default constructor, leaves an uninitialized vector that will throw until a // valid call to open() MmapVectorView() = default; @@ -342,8 +342,8 @@ class MmapVectorView : private MmapVector { open(filename, pattern); } - // explicitly close the vector to an unitialized state and free the associated - // ressources + // explicitly close the vector to an uninitialized state and free the + // associated resources void close(); // destructor diff --git a/src/util/MmapVectorImpl.h b/src/util/MmapVectorImpl.h index 79dc53a698..8584cb9b17 100644 --- a/src/util/MmapVectorImpl.h +++ b/src/util/MmapVectorImpl.h @@ -82,7 +82,7 @@ template void MmapVector::mapForReading() { // open to get valid file descriptor int orig_fd = ::open(_filename.c_str(), O_RDONLY); - // TODO: check if MAP_SHARED is necessary/usefule + // TODO: check if MAP_SHARED is necessary/useful void* ptr = mmap(nullptr, _bytesize, PROT_READ, MAP_SHARED, orig_fd, 0); AD_CONTRACT_CHECK(ptr != MAP_FAILED); diff --git a/src/util/PriorityQueue.h b/src/util/PriorityQueue.h index 0a4dd08af5..bbf4359be6 100644 --- a/src/util/PriorityQueue.h +++ b/src/util/PriorityQueue.h @@ -153,7 +153,7 @@ class TreeBasedPQ { /** * Update the key of a value in the HeapBasedPQ * @param newKey - * @param handle inout parameter, will be changed to be a valid handle after + * @param handle in/out parameter, will be changed to be a valid handle after * the operation has finished. * @throws NotInPQException if the handle does not point into the PQ (because * of pop or erase operations) @@ -241,7 +241,7 @@ class HeapBasedPQ { const Value& value() const { return mData->mValue; } Value& value() { return mData->mValue; } - // was the value asociated with this handle already deleted because of an + // was the value associated with this handle already deleted because of an // erase operation bool isValid() const { return (mData->mScore).index() == 1; }; @@ -370,7 +370,7 @@ class HeapBasedPQ { * associated with the handle * * @param newKey - * @param handle Inout parameter: Updated s.t. it stays valid. + * @param handle in/out parameter: Updated s.t. it stays valid. * @throws NotInPQException if the handle does not point into the PQ (because * of pop or erase operations) */ diff --git a/src/util/Random.h b/src/util/Random.h index e795efc7c0..0be93b0f81 100644 --- a/src/util/Random.h +++ b/src/util/Random.h @@ -8,6 +8,8 @@ #include #include +#include +#include #include #include #include @@ -104,6 +106,20 @@ class RandomDoubleGenerator { std::uniform_real_distribution _distribution; }; +// GENERATE UUID +class UuidGenerator { + public: + explicit UuidGenerator( + RandomSeed seed = RandomSeed::make(std::random_device{}())) + : randomEngine_{seed.get()}, gen_(randomEngine_) {} + + std::string operator()() { return boost::uuids::to_string(gen_()); } + + private: + std::mt19937_64 randomEngine_; + boost::uuids::basic_random_generator gen_; +}; + /// Randomly shuffle range denoted by `[begin, end)` template void randomShuffle(RandomIt begin, RandomIt end, diff --git a/src/util/Serializer/Serializer.h b/src/util/Serializer/Serializer.h index b66a49d94b..574604ed90 100644 --- a/src/util/Serializer/Serializer.h +++ b/src/util/Serializer/Serializer.h @@ -144,7 +144,7 @@ static constexpr bool SerializerMatchesConstness = requires(Constraint) void serialize(S& serializer, T&& arg) /// Similar to `AD_SERIALIZE_FUNCTION_WITH_CONSTRAINT` but only for -/// `WriteSerializer`s. For an exmple usage see `SerializeVector.h` +/// `WriteSerializer`s. For an example usage see `SerializeVector.h` #define AD_SERIALIZE_FUNCTION_WITH_CONSTRAINT_WRITE(Constraint) \ template \ requires(Constraint) void serialize(S& serializer, T&& arg) diff --git a/src/util/Simple8bCode.h b/src/util/Simple8bCode.h index 2a97848b8e..ff13bfb8e9 100644 --- a/src/util/Simple8bCode.h +++ b/src/util/Simple8bCode.h @@ -127,7 +127,7 @@ class Simple8bCode { } // Check that the max value (60 bit) is not exceeded. // I put it here to same some for this check, otherwise we must - // for each elements in hte plaintext do this check. + // for each elements in the plaintext do this check. assert(get(nofElementsEncoded + nofItemsInWord) <= 0x0FFFFFFFFFFFFFFF); } } diff --git a/src/util/StringUtils.cpp b/src/util/StringUtils.cpp index 8d6518abfd..9ccfbb7a7d 100644 --- a/src/util/StringUtils.cpp +++ b/src/util/StringUtils.cpp @@ -5,6 +5,9 @@ #include "util/StringUtils.h" +#include +#include + namespace ad_utility { // ____________________________________________________________________________ string_view commonPrefix(string_view a, const string_view b) { @@ -39,6 +42,11 @@ string getUppercase(const string& orig) { return retVal; } +// ____________________________________________________________________________ +bool strIsLangTag(const string& input) { + return ctre::match<"[a-zA-Z]+(-[a-zA-Z0-9]+)*">(input); +} + // ___________________________________________________________________________ std::pair getUTF8Prefix(std::string_view sv, size_t prefixLength) { @@ -147,7 +155,7 @@ size_t findLiteralEnd(const std::string_view input, } } - // if we have found any unescaped occurence of literalEnd, return the last + // if we have found any unescaped occurrence of literalEnd, return the last // of these positions if (lastFoundPos != size_t(-1)) { return lastFoundPos; diff --git a/src/util/StringUtils.h b/src/util/StringUtils.h index 7c0a49e2bd..0ee68289c6 100644 --- a/src/util/StringUtils.h +++ b/src/util/StringUtils.h @@ -4,28 +4,13 @@ #pragma once -#include #include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include + #include #include "util/Algorithm.h" #include "util/Concepts.h" #include "util/CtreHelpers.h" -#include "util/Exception.h" -#include "util/Forward.h" -#include "util/TypeTraits.h" using std::string; using std::string_view; @@ -43,6 +28,10 @@ string getLowercase(const string& orig); string getUppercase(const string& orig); +// Check if the given string `language tag` is `BPC47` conform. +// Use the ICU library (unicode/uloc.h) for this procedure. +bool strIsLangTag(const string& strLangTag); + /* * @brief convert a UTF-8 String to lowercase according to the held locale * @param s UTF-8 encoded string @@ -105,7 +94,7 @@ size_t findLiteralEnd(std::string_view input, std::string_view literalEnd); @brief Add elements of the range to a stream, with the `separator` between the elements. -@tparam Range An input range, whos dereferenced iterators can be inserted into +@tparam Range An input range, whose dereferenced iterators can be inserted into streams. @param separator Will be put between each of the string representations @@ -202,7 +191,7 @@ void lazyStrJoin(std::ostream* stream, Range&& r, std::string_view separator) { return; } - // Add the first entry without a seperator. + // Add the first entry without a separator. *stream << *begin; // Add the remaining entries. @@ -270,7 +259,7 @@ std::string insertThousandSeparator(const std::string_view str, /* For walking over the string view. Our initialization value skips the leading digits, so that only the digits - remain, where we have to put the seperator in front of every three chars. + remain, where we have to put the separator in front of every three chars. */ size_t currentIdx{s.length() % 3 == 0 ? 3 : s.length() % 3}; ostream << s.substr(0, currentIdx); diff --git a/src/util/SuppressWarnings.h b/src/util/SuppressWarnings.h index fd128d7fea..1f90b85c97 100644 --- a/src/util/SuppressWarnings.h +++ b/src/util/SuppressWarnings.h @@ -12,7 +12,7 @@ // really sure that the suppressed warnings are false positives and that there // is no feasible way to avoid them. -// Macros to disable and reenable certain warnings on GCC13. Currently some +// Macros to disable and re-enable certain warnings on GCC13. Currently some // (valid) uses of `std::sort` trigger a false positive `-Warray-bounds` // warning. It is important that there is a corresponding `ENABLE_...` macro // issued for every `DISABLE_...` macro. diff --git a/src/util/Synchronized.h b/src/util/Synchronized.h index 04c08dcd6a..d699e612ca 100644 --- a/src/util/Synchronized.h +++ b/src/util/Synchronized.h @@ -107,7 +107,7 @@ class Synchronized { * type, return the result. * * Note that return type deduction is done via auto which means, - * that no references are passed out. This happens deliberatly as + * that no references are passed out. This happens deliberately as * passing out references to the underlying type would ignore the locking. */ template @@ -146,7 +146,7 @@ class Synchronized { * return the result. * * Note that return type deduction is done via auto which means, - * that no references are passed out. This happens deliberatly as + * that no references are passed out. This happens deliberately as * passing out references to the underlying type would ignore the locking. * Only supported if the mutex allows shared locking and the * function type F only treats its object as const. diff --git a/src/util/TaskQueue.h b/src/util/TaskQueue.h index 40d6f80c5e..878f13c70e 100644 --- a/src/util/TaskQueue.h +++ b/src/util/TaskQueue.h @@ -58,7 +58,7 @@ class TaskQueue { /// "pusher" is faster for many tasks, the queue will grow too large to fit /// into memory. The task queue will work optimally, when on the average the /// workers are at least as fast as the "pusher", but the pusher is faster - /// sometimes (which the queue can then accomodate). + /// sometimes (which the queue can then accommodate). TaskQueue(size_t maxQueueSize, size_t numThreads, std::string name = "") : queueMaxSize_{maxQueueSize}, name_{std::move(name)} { AD_CONTRACT_CHECK(queueMaxSize_ > 0); diff --git a/src/util/TupleForEach.h b/src/util/TupleForEach.h index 96910cd00a..a0fef421cb 100644 --- a/src/util/TupleForEach.h +++ b/src/util/TupleForEach.h @@ -16,7 +16,7 @@ void forEachInTuple(Tuple&& tuple, Function&& function) { std::apply(forEachInParamPack, std::forward(tuple)); } -/// Apply the `function` to each element of the `tuple`. Retur an `array` of +/// Apply the `function` to each element of the `tuple`. Return an `array` of /// the results. The function is applied on the tuple elements sequentially /// from left to right. /// \param tuple must be a std::tuple<...>. diff --git a/src/util/TupleHelpers.h b/src/util/TupleHelpers.h index 90a37e94f2..675d031af5 100644 --- a/src/util/TupleHelpers.h +++ b/src/util/TupleHelpers.h @@ -44,7 +44,7 @@ auto setupTupleFromCallable(F&& f) { * toUniquePtrTuple(int(3), std::string("foo")) == * std::tuple(std::make_unique(3), std::make_unique("foo")) It * can take an arbitrary positive number of arguments. Currently this template - * is linearly expanded, if this becomes a bottleneck at compiletime (e.g. for + * is linearly expanded, if this becomes a bottleneck at compile time (e.g. for * very long parameter packs) we could do something more intelligent. * @return std::tuple(std::make_unique(std::forward(l), * std::make_unique {}; /// The concept is fulfilled iff `T` is an instantiation of `TemplatedType`. /// Examples: /// -/// isInstantiation> == true; -/// isInstantiation&> == false; +/// isInstantiation, std::vector> == true; +/// isInstantiation&, std::vector> == false; template typename TemplatedType> concept isInstantiation = detail::IsInstantiationOf::template Instantiation::value; @@ -115,7 +115,7 @@ constexpr static bool isArray = false; template constexpr static bool isArray> = true; -// `SimilarToArray` is also true for `std::aray<...>&`, etc. +// `SimilarToArray` is also true for `std::array<...>&`, etc. template concept SimilarToArray = isArray>; diff --git a/src/util/http/HttpClient.cpp b/src/util/http/HttpClient.cpp index 1f7429255d..82cea0b6b8 100644 --- a/src/util/http/HttpClient.cpp +++ b/src/util/http/HttpClient.cpp @@ -21,7 +21,7 @@ namespace net = boost::asio; using tcp = boost::asio::ip::tcp; using ad_utility::httpUtils::Url; -// Implemented using Boost.Beast, code apapted from +// Implemented using Boost.Beast, code adapted from // https://www.boost.org/doc/libs/master/libs/beast/example/http/client/sync/http_client_sync.cpp // https://www.boost.org/doc/libs/master/libs/beast/example/http/client/sync-ssl/http_client_sync_ssl.cpp diff --git a/src/util/http/HttpClient.h b/src/util/http/HttpClient.h index 45daecff34..a526412f6a 100644 --- a/src/util/http/HttpClient.h +++ b/src/util/http/HttpClient.h @@ -40,7 +40,7 @@ class HttpClientImpl { ~HttpClientImpl(); // Send a request (the first argument must be either `http::verb::get` or - // `http::verb::post`) and return the body of the reponse (possibly very + // `http::verb::post`) and return the body of the response (possibly very // large) as an `cppcoro::generator`. The same connection // can be used for multiple requests in a row. cppcoro::generator> sendRequest( diff --git a/src/util/http/HttpUtils.cpp b/src/util/http/HttpUtils.cpp index 93ac1d9294..cae479d54f 100644 --- a/src/util/http/HttpUtils.cpp +++ b/src/util/http/HttpUtils.cpp @@ -13,7 +13,7 @@ namespace ad_utility::httpUtils { // The regex for parsing the components of a URL. We need it also as a string -// (for error messagin) and CTRE has no function for printing a regex as a +// (for error messaging) and CTRE has no function for printing a regex as a // a string, hence the two variables. static constexpr char urlRegexString[] = "^(http|https)://([^:/]+)(:([0-9]+))?(/.*)?$"; diff --git a/src/util/http/MediaTypes.h b/src/util/http/MediaTypes.h index da53387f04..43a809e33b 100644 --- a/src/util/http/MediaTypes.h +++ b/src/util/http/MediaTypes.h @@ -47,7 +47,7 @@ struct MediaTypeWithQuality { float _qualityValue; Variant _mediaType; - // Order first by the qualities, and then by the specifity of the type. + // Order first by the qualities, and then by the specificity of the type. std::partial_ordering operator<=>(const MediaTypeWithQuality& rhs) const { if (auto cmp = _qualityValue <=> rhs._qualityValue; cmp != 0) { return cmp; diff --git a/src/util/http/websocket/WebSocketSession.cpp b/src/util/http/websocket/WebSocketSession.cpp index 202c5033f0..75e6e4402d 100644 --- a/src/util/http/websocket/WebSocketSession.cpp +++ b/src/util/http/websocket/WebSocketSession.cpp @@ -122,7 +122,7 @@ net::awaitable WebSocketSession::handleSession( queryRegistry, std::move(queryId)}; // There is currently no safe way of which we know that allows us to respawn // the coroutine onto another thread AND make it safely cancellable at the - // same time. Therfore we just assert that the cancellation slot is not + // same time. Therefore we just assert that the cancellation slot is not // connected. auto slot = (co_await net::this_coro::cancellation_state).slot(); AD_CORRECTNESS_CHECK(!slot.is_connected()); diff --git a/test/AlgorithmTest.cpp b/test/AlgorithmTest.cpp index aa613e492f..485f6930cc 100644 --- a/test/AlgorithmTest.cpp +++ b/test/AlgorithmTest.cpp @@ -31,7 +31,8 @@ TEST(Algorithm, Contains) { std::vector substrings{"h", "a", "l", "ha", "al", "hal"}; ASSERT_TRUE(std::ranges::all_of( substrings, [&s](const auto& el) { return contains(s, el); })); - std::vector noSubstrings{"x", "hl", "hel"}; + std::vector noSubstrings{"x", "hl", + "hel"}; // codespell-ignore ASSERT_TRUE(std::ranges::none_of( noSubstrings, [&s](const auto& el) { return contains(s, el); })); } @@ -40,7 +41,8 @@ TEST(Algorithm, Contains) { "ha", "al", "hal"}; ASSERT_TRUE(std::ranges::all_of( substrings, [&s](const auto& el) { return contains(s, el); })); - std::vector noSubstrings{"x", "hl", "hel"}; + std::vector noSubstrings{"x", "hl", + "hel"}; // codespell-ignore ASSERT_TRUE(std::ranges::none_of( noSubstrings, [&s](const auto& el) { return contains(s, el); })); } diff --git a/test/BenchmarkMeasurementContainerTest.cpp b/test/BenchmarkMeasurementContainerTest.cpp index cb1c71bde2..a500c3df2c 100644 --- a/test/BenchmarkMeasurementContainerTest.cpp +++ b/test/BenchmarkMeasurementContainerTest.cpp @@ -88,7 +88,7 @@ TEST(BenchmarkMeasurementContainerTest, ResultGroup) { } /* -Check the content of a `ResultTable` row. +Check the content of a `Result` row. */ static void checkResultTableRow(const ResultTable& table, const size_t& rowNumber, @@ -157,7 +157,7 @@ TEST(BenchmarkMeasurementContainerTest, ResultTable) { Special case: A table with no columns. Should throw an exception on creation, because you can't add columns after creation and a table without columns is quite the stupid idea. Additionally, operations on such an empty - table can create segmentation faults. The string conversion of `ResultTable` + table can create segmentation faults. The string conversion of `Result` uses `std::ranges::max`, which really doesn't play well with empty vectors. */ ASSERT_ANY_THROW(ResultTable("1 by 0 table", {"Test"}, {})); @@ -308,7 +308,7 @@ TEST(BenchmarkMeasurementContainerTest, ResultTableEraseRow) { TEST(BenchmarkMeasurementContainerTest, ResultGroupDeleteMember) { /* - Add the given number of dummy `ResultEntry`s and dummy `ResultTable`s to the + Add the given number of dummy `ResultEntry`s and dummy `Result`s to the given group. */ auto addDummyMembers = [](ResultGroup* group, const size_t numOfEntries) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f5cc3be146..6e74705935 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -10,7 +10,7 @@ function (linkTest basename) qlever_target_link_libraries(${basename} ${ARGN} GTest::gtest GTest::gmock_main testUtil ${CMAKE_THREAD_LIBS_INIT}) endfunction() -# Add the exectutable ${basename} that is compiled from the source file +# Add the executable ${basename} that is compiled from the source file # "${basename}".cpp function (addTest basename) add_executable(${basename} "${basename}.cpp") @@ -94,6 +94,8 @@ addLinkAndDiscoverTest(SparqlParserTest parser engine sparqlExpressions) addLinkAndDiscoverTest(StringUtilsTest util) +addLinkAndDiscoverTest(CryptographicHashUtilsTest util) + addLinkAndDiscoverTest(CacheTest) addLinkAndDiscoverTest(ConcurrentCacheTest) @@ -294,6 +296,8 @@ addLinkAndDiscoverTest(ExceptionTest) addLinkAndDiscoverTestSerial(RandomExpressionTest index) +addLinkAndDiscoverTestSerial(NowDatetimeExpressionTest index) + addLinkAndDiscoverTestSerial(SortTest engine) addLinkAndDiscoverTestSerial(OrderByTest engine) diff --git a/test/CacheTest.cpp b/test/CacheTest.cpp index d28e992016..885c652ed6 100644 --- a/test/CacheTest.cpp +++ b/test/CacheTest.cpp @@ -69,7 +69,7 @@ TEST(LRUCacheTest, testSimpleMapUsage) { ASSERT_EQ(*cache["5"], "xxxxx"); // Non-existing elements must yield shared_ptr(nullptr) // this bool converts to false - ASSERT_FALSE(cache["non-existant"]); + ASSERT_FALSE(cache["non-existent"]); } // _____________________________________________________________________________ TEST(LRUCacheTest, testSimpleMapUsageWithDrop) { @@ -133,7 +133,7 @@ TEST(LRUCacheTest, testDecreasingCapacity) { cache.insert("9", "xxxxxxxxx"); cache.setMaxNumEntries(2); ASSERT_EQ(*cache["9"], "xxxxxxxxx"); // freshly inserted - ASSERT_EQ(*cache["5"], "xxxxx"); // second leat recently used + ASSERT_EQ(*cache["5"], "xxxxx"); // second least recently used ASSERT_FALSE(cache["1"]); ASSERT_FALSE(cache["2"]); ASSERT_FALSE(cache["3"]); diff --git a/test/CompressedRelationsTest.cpp b/test/CompressedRelationsTest.cpp index d333702227..c5e79c510b 100644 --- a/test/CompressedRelationsTest.cpp +++ b/test/CompressedRelationsTest.cpp @@ -507,5 +507,5 @@ TEST(CompressedRelationReader, PermutedTripleToString) { auto tr = CompressedBlockMetadata::PermutedTriple{V(12), V(13), V(27)}; std::stringstream str; str << tr; - ASSERT_EQ(str.str(), "Triple: VocabIndex:12 VocabIndex:13 VocabIndex:27\n"); + ASSERT_EQ(str.str(), "Triple: V:12 V:13 V:27\n"); } diff --git a/test/ConfigManagerTest.cpp b/test/ConfigManagerTest.cpp index 3c5131ee91..0d90283201 100644 --- a/test/ConfigManagerTest.cpp +++ b/test/ConfigManagerTest.cpp @@ -129,8 +129,8 @@ TEST(ConfigManagerTest, AddConfigurationOptionExceptionTest) { /* Trying to add a configuration option, whose entire path is a prefix of the path of an already added sub manager, should cause an exception. After all, - this would imply, that the sub manger is part of this new option. Which is not - supported at the moment. + this would imply, that the sub manager is part of this new option. Which is + not supported at the moment. */ config.addSubManager({"sub"s, "manager"s}) .addOption("someOpt"s, "", ¬Used, 42); @@ -139,8 +139,8 @@ TEST(ConfigManagerTest, AddConfigurationOptionExceptionTest) { /* Trying to add a configuration option, who contains the entire path of an - already added sub manger as prefix, should cause an exception. After all, such - recursive builds should have been done on `C++` level, not json level. + already added sub manager as prefix, should cause an exception. After all, + such recursive builds should have been done on `C++` level, not json level. */ AD_EXPECT_THROW_WITH_MESSAGE( config.addOption({"sub"s, "manager"s, "someOption"s}, "", ¬Used, 42), @@ -148,7 +148,7 @@ TEST(ConfigManagerTest, AddConfigurationOptionExceptionTest) { /* Trying to add a configuration option, whose path is the path of an already - added sub manger, should cause an exception. + added sub manager, should cause an exception. */ AD_EXPECT_THROW_WITH_MESSAGE( config.addOption({"sub"s, "manager"s}, "", ¬Used, 42), @@ -178,7 +178,7 @@ TEST(ConfigManagerTest, AddConfigurationOptionFalseExceptionTest) { The reasons, why it's not allowed, are basically the same. In the past, it was possible to cause path collisions even though there - weren't any, by having paths, which json pointer representation fullfilled the + weren't any, by having paths, which json pointer representation fulfilled the conditions for one of the cases. For example: It should be possible, to have one option under `[prefixes]` and one under `[prefixes-eternal]`. But, because `/prefixes` is a prefix of @@ -261,8 +261,8 @@ TEST(ConfigManagerTest, addSubManagerExceptionTest) { /* Trying to add a sub manager, whose entire path is a prefix of the path of an - already added sub manger, should cause an exception. After all, such recursive - builds should have been done on `C++` level, not json level. + already added sub manager, should cause an exception. After all, such + recursive builds should have been done on `C++` level, not json level. */ AD_EXPECT_THROW_WITH_MESSAGE( config.addSubManager({"Shared_part"s, "Unique_part_1"s}), @@ -280,7 +280,7 @@ TEST(ConfigManagerTest, addSubManagerExceptionTest) { R"('\[Shared_part\]\[Unique_part_1\]\[Sense_of_existence\]\[Answer\]\[42\]')")); /* - Trying to add a sub manger, whose entire path is a prefix of the path of an + Trying to add a sub manager, whose entire path is a prefix of the path of an already added config option, should cause an exception. After all, such recursive builds should have been done on `C++` level, not json level. */ @@ -291,8 +291,8 @@ TEST(ConfigManagerTest, addSubManagerExceptionTest) { /* Trying to add a sub manager, who contains the entire path of an already added config option as prefix, should cause an exception. - After all, this would imply, that the sub manger is part of this option. Which - is not supported at the moment. + After all, this would imply, that the sub manager is part of this option. + Which is not supported at the moment. */ AD_EXPECT_THROW_WITH_MESSAGE( config.addSubManager({"some"s, "option"s, "manager"s}), @@ -330,7 +330,7 @@ TEST(ConfigManagerTest, AddSubManagerFalseExceptionTest) { The reasons, why it's not allowed, are basically the same. In the past, it was possible to cause path collisions even though there - weren't any, by having paths, which json pointer representation fullfilled the + weren't any, by having paths, which json pointer representation fulfilled the conditions for one of the cases. For example: It should be possible, to have one sub manager under `[prefixes]` and one under `[prefixes-eternal]`. But, because `/prefixes` is a prefix of @@ -1034,7 +1034,7 @@ TEST(ConfigManagerTest, HumanReadableAddValidator) { return (one && !two && !three) || (!one && two && !three) || (!one && !two && three); }, - "Exactly one bool must be choosen.", "", boolOneOption, boolTwoOption, + "Exactly one bool must be chosen.", "", boolOneOption, boolTwoOption, boolThreeOption); checkValidator( m, @@ -1042,7 +1042,7 @@ TEST(ConfigManagerTest, HumanReadableAddValidator) { R"--({"numberInRange" : 60, "boolOne": true, "boolTwo": false, "boolThree": false})--"), nlohmann::json::parse( R"--({"numberInRange" : 60, "boolOne": true, "boolTwo": true, "boolThree": false})--"), - "Exactly one bool must be choosen."); + "Exactly one bool must be chosen."); } // Human readable examples for `addOptionValidator` with `Validator` functions. @@ -1094,7 +1094,7 @@ TEST(ConfigManagerTest, HumanReadableAddOptionValidator) { /* @brief Generate an informative validator name in the form of `Config manager validator y`. With `x` being the list of function argument types and `y` an -unqiue number id. +unique number id. @tparam Ts The types of the function arguments of the validator function. @@ -1167,7 +1167,7 @@ void doValidatorTest( /* @brief Adjust `variant` argument for `createDummyValueForValidator` and `generateDummyNonExceptionValidatorFunction`. - The bool type in those helper functions needs special handeling, because it + The bool type in those helper functions needs special handling, because it only has two values and can't fulfill the invariant, that `createDummyValueForValidator` and `generateDummyNonExceptionValidatorFunction` should fulfill. @@ -1218,7 +1218,7 @@ void doValidatorTest( /* @brief Test all validator functions generated by `addValidatorToConfigManager` for a given range of `variant` and a specific configuration of `Ts`. Note: - This is for specificly for testing the validators generated by calling + This is for specifically for testing the validators generated by calling `addValidatorToConfigManager` with a all values in `[variantStart, variantEnd)` as `variant` and all other arguments unchanged. @@ -1633,8 +1633,8 @@ void doValidatorTest( ConfigManager& managerToAddValidatorTo, ConstConfigOptionProxy option, const nlohmann::json::json_pointer& pathToOption) { - // The value, which causes the automaticly generated validator with the - // given variant to fail. + // The value, which causes the automatically generated validator with + // the given variant to fail. const std::string& failValue = createDummyValueForValidator(variantNumber); @@ -1695,7 +1695,7 @@ void doValidatorTest( nlohmann::json::json_pointer("/some/manager/someValue1")); /* - Reseting `mValidatorSubValidatorOption1`, so that the validator, that was + Resetting `mValidatorSubValidatorOption1`, so that the validator, that was added via `doExceptionMessageTest`, not longer fails. We can not use an r-value nlohmann json object for this, because there is no @@ -2475,7 +2475,7 @@ TEST(ConfigManagerTest, ConfigurationDocValidatorAssignment) { /* Generate the `ConfigOption`, together with their validators. Note: We do not - need working `ConfigOption`. As long as they exists, everythings fine. + need working `ConfigOption`. As long as they exists, everything fine. */ const auto configOptionKeysAndValidators{createKeyAndValidatorPairVector( []() { @@ -2486,7 +2486,7 @@ TEST(ConfigManagerTest, ConfigurationDocValidatorAssignment) { /* Generate the `ConfigManager`, together with their validators. Note: We do not - need working `ConfigManager`. As long as they exists, everythings fine. + need working `ConfigManager`. As long as they exists, everything fine. */ const auto configManagerKeysAndValidators{createKeyAndValidatorPairVector( []() { return ConfigManager{}; }, NUM_CONFIG_MANAGER)}; diff --git a/test/CopyableUniquePtrTest.cpp b/test/CopyableUniquePtrTest.cpp index f243493e35..5e5eb729a7 100644 --- a/test/CopyableUniquePtrTest.cpp +++ b/test/CopyableUniquePtrTest.cpp @@ -75,7 +75,7 @@ TEST(CopyableUniquePtr, CopyAndMoveConstructor) { { ad_utility::CopyableUniquePtr nonEmptyPointer( ad_utility::make_copyable_unique(42)); - // Saving the adress of the int object, so that we can later check, that + // Saving the address of the int object, so that we can later check, that // it was actually moved. int* const intAdress = nonEmptyPointer.get(); diff --git a/test/CryptographicHashUtilsTest.cpp b/test/CryptographicHashUtilsTest.cpp new file mode 100644 index 0000000000..5864dd9915 --- /dev/null +++ b/test/CryptographicHashUtilsTest.cpp @@ -0,0 +1,85 @@ +// Copyright 2024, University of Freiburg, +// Chair of Algorithms and Data Structures +// Author: Hannes Baumann + +#include + +#include + +#include "util/CryptographicHashUtils.h" + +using namespace ad_utility; + +// Helper to convert the hex hash values to a hex digit string +inline auto toHexString(std::vector hashed) { + return absl::StrJoin(hashed, "", hexFormatter); +}; + +std::string testStr1 = ""; +std::string testStr2 = "Friburg23o"; +std::string testStr3 = "abc"; + +// TEST MD5 +TEST(CryptographicHashUtilsTest, testMd5) { + auto res1 = toHexString(hashMd5(testStr1)); + auto res2 = toHexString(hashMd5(testStr2)); + auto res3 = toHexString(hashMd5(testStr3)); + EXPECT_EQ(res1, "d41d8cd98f00b204e9800998ecf8427e"); + EXPECT_EQ(res2, "9d9a73f67e20835e516029541595c381"); + EXPECT_EQ(res3, "900150983cd24fb0d6963f7d28e17f72"); +} + +// TEST SHA1 +TEST(CryptographicHashUtilsTest, testSha1) { + auto res1 = toHexString(hashSha1(testStr1)); + auto res2 = toHexString(hashSha1(testStr2)); + auto res3 = toHexString(hashSha1(testStr3)); + EXPECT_EQ(res1, "da39a3ee5e6b4b0d3255bfef95601890afd80709"); + EXPECT_EQ(res2, "c3a77a6104fa091f590f594b3e2dba2668196d3c"); + EXPECT_EQ(res3, "a9993e364706816aba3e25717850c26c9cd0d89d"); +} + +// TEST SHA256 +TEST(CryptographicHashUtilsTest, testSha256) { + auto res1 = toHexString(hashSha256(testStr1)); + auto res2 = toHexString(hashSha256(testStr2)); + auto res3 = toHexString(hashSha256(testStr3)); + EXPECT_EQ(res1, + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); + EXPECT_EQ(res2, + "af8d98f09845a700aea36b35e8cc3a35632e38d0f7be9c0ca508e53c578da900"); + EXPECT_EQ(res3, + "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); +} + +// TEST SHA384 +TEST(CryptographicHashUtilsTest, testSha384) { + auto res1 = toHexString(hashSha384(testStr1)); + auto res2 = toHexString(hashSha384(testStr2)); + auto res3 = toHexString(hashSha384(testStr3)); + EXPECT_EQ(res1, + "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da27" + "4edebfe76f65fbd51ad2f14898b95b"); + EXPECT_EQ(res2, + "72810006e3b418ebd179812522cafa486cd6c2a988378fac148af1a9a098a01ce3" + "373734c23978f7df68bf7e98955c02"); + EXPECT_EQ(res3, + "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed80" + "86072ba1e7cc2358baeca134c825a7"); +} + +// TEST SHA512 +TEST(CryptographicHashUtilsTest, testSha512) { + auto res1 = toHexString(hashSha512(testStr1)); + auto res2 = toHexString(hashSha512(testStr2)); + auto res3 = toHexString(hashSha512(testStr3)); + EXPECT_EQ(res1, + "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47" + "d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + EXPECT_EQ(res2, + "be4422bfad59ee51e98dc51c540dc9d85333cb786333b152d13b2bebde1bdaa499" + "e9d4e1370a5bb2e831f4443b1358f2301fd5214ba80554ea0ff1d185c3b027"); + EXPECT_EQ(res3, + "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a21" + "92992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"); +} diff --git a/test/ExportQueryExecutionTreeTest.cpp b/test/ExportQueryExecutionTreeTest.cpp index 139c480916..359a9407c6 100644 --- a/test/ExportQueryExecutionTreeTest.cpp +++ b/test/ExportQueryExecutionTreeTest.cpp @@ -57,7 +57,7 @@ nlohmann::json runJSONQuery(const std::string& kg, const std::string& query, auto qet = qp.createExecutionTree(pq); ad_utility::Timer timer{ad_utility::Timer::Started}; return ExportQueryExecutionTrees::computeResultAsJSON( - pq, qet, timer, 200, mediaType, std::move(cancellationHandle)); + pq, qet, timer, mediaType, std::move(cancellationHandle)); } // A test case that tests the correct execution and exporting of a SELECT query @@ -835,6 +835,10 @@ TEST(ExportQueryExecutionTree, CornerCases) { ExportQueryExecutionTrees::idToStringAndType(qec->getIndex(), Id::max(), LocalVocab{}), ::testing::ContainsRegex("should be unreachable")); + AD_EXPECT_THROW_WITH_MESSAGE( + ExportQueryExecutionTrees::getLiteralOrIriFromVocabIndex( + qec->getIndex(), Id::max(), LocalVocab{}), + ::testing::ContainsRegex("should be unreachable")); AD_EXPECT_THROW_WITH_MESSAGE( ExportQueryExecutionTrees::idToStringAndTypeForEncodedValue( ad_utility::testing::VocabId(12)), @@ -862,8 +866,8 @@ TEST_P(JsonMediaTypesFixture, CancellationCancelsJson) { cancellationHandle->cancel(ad_utility::CancellationState::MANUAL); AD_EXPECT_THROW_WITH_MESSAGE_AND_TYPE( ExportQueryExecutionTrees::computeResultAsJSON( - pq, qet, ad_utility::Timer{ad_utility::Timer::Started}, 200, - GetParam(), std::move(cancellationHandle)), + pq, qet, ad_utility::Timer{ad_utility::Timer::Started}, GetParam(), + std::move(cancellationHandle)), HasSubstr("Query export"), ad_utility::CancellationException); } INSTANTIATE_TEST_SUITE_P(JsonMediaTypes, JsonMediaTypesFixture, diff --git a/test/GroupByTest.cpp b/test/GroupByTest.cpp index 61c5a3b4a0..101bb842df 100644 --- a/test/GroupByTest.cpp +++ b/test/GroupByTest.cpp @@ -127,9 +127,12 @@ TEST_F(GroupByTest, doGroupBy) { // Create an input result table with a local vocabulary. auto localVocab = std::make_shared(); - localVocab->getIndexAndAddIfNotContained(""); - localVocab->getIndexAndAddIfNotContained(""); - localVocab->getIndexAndAddIfNotContained(""); + constexpr auto iriref = [](const std::string& s) { + return ad_utility::triple_component::LiteralOrIri::iriref(s); + }; + localVocab->getIndexAndAddIfNotContained(iriref("")); + localVocab->getIndexAndAddIfNotContained(iriref("")); + localVocab->getIndexAndAddIfNotContained(iriref("")); IdTable inputData(6, makeAllocator()); // The input data types are KB, KB, VERBATIM, TEXT, FLOAT, STRING. @@ -190,7 +193,7 @@ TEST_F(GroupByTest, doGroupBy) { {ParsedQuery::AggregateType::AVG, 3, 22, nullptr}, {ParsedQuery::AggregateType::AVG, 4, 23, nullptr}}; - ResultTable outTable{allocator()}; + Result outTable{allocator()}; // This is normally done when calling computeResult in the GroupBy // operation. @@ -451,10 +454,10 @@ struct GroupByOptimizations : ::testing::Test { } static SparqlExpressionPimpl makeGroupConcatPimpl( - const Variable& var, const std::string& seperator = " ") { + const Variable& var, const std::string& separator = " ") { return SparqlExpressionPimpl{ std::make_unique( - false, makeVariableExpression(var), seperator), + false, makeVariableExpression(var), separator), "GROUP_CONCAT(?someVariable)"}; } @@ -1223,7 +1226,7 @@ TEST_F(GroupByOptimizations, hashMapOptimizationGroupConcatIndex) { auto groupConcatExpression2 = makeGroupConcatPimpl(varY, ","); auto aliasGC2 = Alias{groupConcatExpression2, varW}; - // SELECT (GROUP_CONCAT(?y) as ?z) (GROUP_CONCAT(?y;seperator=",") as ?w) + // SELECT (GROUP_CONCAT(?y) as ?z) (GROUP_CONCAT(?y;separator=",") as ?w) // WHERE {...} GROUP BY ?x GroupBy groupBy{qec, variablesOnlyX, {aliasGC1, aliasGC2}, subtreeWithSort}; auto result = groupBy.getResult(); @@ -1231,7 +1234,9 @@ TEST_F(GroupByOptimizations, hashMapOptimizationGroupConcatIndex) { auto getId = makeGetId(qec->getIndex()); auto getLocalVocabId = [&result](const std::string& word) { - auto value = result->localVocab().getIndexOrNullopt(word); + auto lit = + ad_utility::triple_component::LiteralOrIri::literalWithoutQuotes(word); + auto value = result->localVocab().getIndexOrNullopt(lit); if (value.has_value()) return ValueId::makeFromLocalVocabIndex(value.value()); else @@ -1278,7 +1283,9 @@ TEST_F(GroupByOptimizations, hashMapOptimizationGroupConcatLocalVocab) { auto getId = makeGetId(qec->getIndex()); auto d = DoubleId; auto getLocalVocabId = [&result](const std::string& word) { - auto value = result->localVocab().getIndexOrNullopt(word); + auto lit = + ad_utility::triple_component::LiteralOrIri::literalWithoutQuotes(word); + auto value = result->localVocab().getIndexOrNullopt(lit); if (value.has_value()) return ValueId::makeFromLocalVocabIndex(value.value()); else diff --git a/test/IdTableHelpersTest.cpp b/test/IdTableHelpersTest.cpp index 01fad0c817..2bae9888c7 100644 --- a/test/IdTableHelpersTest.cpp +++ b/test/IdTableHelpersTest.cpp @@ -187,7 +187,7 @@ TEST(IdTableHelpersTest, createRandomlyFilledIdTableWithoutGenerators) { // The overloads that take generators for creating the content of the join // columns. TEST(IdTableHelpersTest, createRandomlyFilledIdTableWithGeneratos) { - // Creates a 'generator', that counts one up, everytime it's called. + // Creates a 'generator', that counts one up, every time it's called. auto createCountUpGenerator = []() { return [i = 0]() mutable { return ad_utility::testing::VocabId(i++); }; }; @@ -284,7 +284,7 @@ TEST(IdTableHelpersTest, createRandomlyFilledIdTableWithGeneratos) { TEST(IdTableHelpersTest, generateIdTable) { /* - Creates a 'generator', that returns a row of the given lenght, were every + Creates a 'generator', that returns a row of the given length, were every entry contains the same number. The number starts with 0 and goes on up with every call. */ diff --git a/test/IdTableTest.cpp b/test/IdTableTest.cpp index b4fb384a72..9e0c03dc78 100644 --- a/test/IdTableTest.cpp +++ b/test/IdTableTest.cpp @@ -67,7 +67,7 @@ TEST(IdTable, DocumentationOfIteratorUsage) { // The following calls do not change the table, but are also not expected to // do so because we explicitly bind to a `value_type`. { - IdTable::row_type row = t[0]; // Explitly copy/materialize the full row. + IdTable::row_type row = t[0]; // Explicitly copy/materialize the full row. row[0] = V(50); // We have changed the copied row, but not the table. ASSERT_EQ(V(50), row[0]); @@ -76,7 +76,7 @@ TEST(IdTable, DocumentationOfIteratorUsage) { { // Exactly the same example, but with `iterator`s and `iterator_traits`. std::iterator_traits::value_type row = - *t.begin(); // Explitly copy/materialize the full row. + *t.begin(); // Explicitly copy/materialize the full row. row[0] = V(51); // We have changed the copied row, but not the table. ASSERT_EQ(V(51), row[0]); @@ -254,7 +254,7 @@ void runTestForDifferentTypes(auto testCase, std::string testCaseName) { // to be made. It is necessary because for some `IdTable` instantiations // (for example when the data is stored in a `BufferedVector`) the `clone` // member function needs additional arguments. Currently, the only additional -// argument is the filenmae for the copy for `IdTables` that store their data in +// argument is the filename for the copy for `IdTables` that store their data in // a `BufferedVector`. For an example usage see the test cases below. auto clone(const auto& table, auto... args) { if constexpr (requires { table.clone(); }) { diff --git a/test/IndexTest.cpp b/test/IndexTest.cpp index e0b17f5326..3aaed82ec1 100644 --- a/test/IndexTest.cpp +++ b/test/IndexTest.cpp @@ -32,12 +32,14 @@ auto lit = ad_utility::testing::tripleComponentLiteral; auto makeTestScanWidthOne = [](const IndexImpl& index) { return [&index](const TripleComponent& c0, const TripleComponent& c1, Permutation::Enum permutation, const VectorTable& expected, + Permutation::ColumnIndices additionalColumns = {}, ad_utility::source_location l = ad_utility::source_location::current()) { auto t = generateLocationTrace(l); - IdTable result = index.scan( - c0, std::cref(c1), permutation, Permutation::ColumnIndicesRef{}, - std::make_shared>()); + IdTable result = + index.scan(c0, std::cref(c1), permutation, additionalColumns, + std::make_shared>()); + ASSERT_EQ(result.numColumns(), 1 + additionalColumns.size()); ASSERT_EQ(result, makeIdTableFromVector(expected)); }; }; @@ -132,6 +134,10 @@ TEST(IndexTest, createFromTurtleTest) { // subject that appears with . auto testOne = makeTestScanWidthOne(index); testOne(iri(""), iri(""), Permutation::PSO, {}); + // An empty scan result must still have the correct number of columns. + testOne(iri(""), iri(""), + Permutation::PSO, {}, + {ADDITIONAL_COLUMN_INDEX_SUBJECT_PATTERN}); } } { diff --git a/test/JsonCustomConverterForThirdPartyTest.cpp b/test/JsonCustomConverterForThirdPartyTest.cpp index 937e8e6316..d16c5f2b35 100644 --- a/test/JsonCustomConverterForThirdPartyTest.cpp +++ b/test/JsonCustomConverterForThirdPartyTest.cpp @@ -121,7 +121,7 @@ TEST(JsonCustomConverterForThirdParty, StdVariant) { doSimpleTest(std::monostate{}, (int)42); doSimpleTest((float)4.2777422, std::monostate{}); - // There is a custom exception, should the index for a value tpye be not + // There is a custom exception, should the index for a value type be not // valid. That is, to big, or to small. j["index"] = -1; ASSERT_THROW(variant = j.get(), nlohmann::detail::out_of_range); @@ -160,11 +160,11 @@ TEST(JsonCustomConverterForThirdParty, pointer = j.get(); }; - // Uniqe pointer doesn't own an object. + // Unique pointer doesn't own an object. doCheckPreparation(nullptr, std::make_unique(42)); ASSERT_EQ(pointer.get(), nullptr); - // Uniqe pointer owns an object. + // Unique pointer owns an object. doCheckPreparation(std::make_unique(42), nullptr); ASSERT_NE(pointer.get(), nullptr); ASSERT_EQ(*pointer, 42); diff --git a/test/LocalVocabTest.cpp b/test/LocalVocabTest.cpp index 9b2615a737..def4541b1c 100644 --- a/test/LocalVocabTest.cpp +++ b/test/LocalVocabTest.cpp @@ -21,7 +21,7 @@ #include "engine/OptionalJoin.h" #include "engine/OrderBy.h" #include "engine/QueryExecutionTree.h" -#include "engine/ResultTable.h" +#include "engine/Result.h" #include "engine/Sort.h" #include "engine/TransitivePathBase.h" #include "engine/Union.h" @@ -33,10 +33,15 @@ namespace { // Get test collection of words of a given size. The words are all distinct. -std::vector getTestCollectionOfWords(size_t size) { - std::vector testCollectionOfWords(size); - for (size_t i = 0; i < testCollectionOfWords.size(); ++i) { - testCollectionOfWords[i] = std::to_string(i * 7635475567ULL); + +using TestWords = std::vector; + +TestWords getTestCollectionOfWords(size_t size) { + using namespace ad_utility::triple_component; + TestWords testCollectionOfWords; + for (size_t i = 0; i < size; ++i) { + testCollectionOfWords.push_back( + LiteralOrIri::literalWithoutQuotes(std::to_string(i * 7635475567ULL))); } return testCollectionOfWords; } @@ -45,7 +50,7 @@ std::vector getTestCollectionOfWords(size_t size) { // _____________________________________________________________________________ TEST(LocalVocab, constructionAndAccess) { // Test collection of words. - std::vector testWords = getTestCollectionOfWords(1000); + TestWords testWords = getTestCollectionOfWords(1000); // Create empty local vocabulary. LocalVocab localVocab; @@ -80,7 +85,11 @@ TEST(LocalVocab, constructionAndAccess) { // not contained in the local vocab. This makes use of the fact that the words // in our test vocabulary only contain digits as letters, see above. for (size_t i = 0; i < testWords.size(); ++i) { - ASSERT_FALSE(localVocab.getIndexOrNullopt(testWords[i] + "A")); + std::string content{asStringViewUnsafe(testWords[i].getContent())}; + auto illegalWord = + ad_utility::triple_component::LiteralOrIri::literalWithoutQuotes( + content + "A"); + ASSERT_FALSE(localVocab.getIndexOrNullopt(illegalWord)); } // Check that a move gives the expected result. @@ -132,23 +141,27 @@ TEST(LocalVocab, merge) { std::vector indices; LocalVocab vocA; LocalVocab vocB; - indices.push_back(vocA.getIndexAndAddIfNotContained("oneA")); - indices.push_back(vocA.getIndexAndAddIfNotContained("twoA")); - indices.push_back(vocA.getIndexAndAddIfNotContained("oneB")); - indices.push_back(vocA.getIndexAndAddIfNotContained("twoB")); + constexpr auto lit = [](std::string_view s) { + return ad_utility::triple_component::LiteralOrIri::literalWithoutQuotes(s); + }; + indices.push_back(vocA.getIndexAndAddIfNotContained(lit("oneA"))); + indices.push_back(vocA.getIndexAndAddIfNotContained(lit("twoA"))); + indices.push_back(vocA.getIndexAndAddIfNotContained(lit("oneB"))); + indices.push_back(vocA.getIndexAndAddIfNotContained(lit("twoB"))); // Clone it and test that the clone contains the same words. auto vocabs = std::vector{&std::as_const(vocA), &std::as_const(vocB)}; LocalVocab localVocabMerged = LocalVocab::merge(vocabs); ASSERT_EQ(localVocabMerged.size(), 4u); ASSERT_THAT(localVocabMerged.getAllWordsForTesting(), - ::testing::UnorderedElementsAre("oneA", "twoA", "oneB", "twoB")); + ::testing::UnorderedElementsAre(lit("oneA"), lit("twoA"), + lit("oneB"), lit("twoB"))); vocA = LocalVocab{}; vocB = LocalVocab{}; - EXPECT_EQ(*indices[0], "oneA"); - EXPECT_EQ(*indices[1], "twoA"); - EXPECT_EQ(*indices[2], "oneB"); - EXPECT_EQ(*indices[3], "twoB"); + EXPECT_EQ(*indices[0], lit("oneA")); + EXPECT_EQ(*indices[1], lit("twoA")); + EXPECT_EQ(*indices[2], lit("oneB")); + EXPECT_EQ(*indices[3], lit("twoB")); } // _____________________________________________________________________________ @@ -162,12 +175,24 @@ TEST(LocalVocab, propagation) { // // NOTE: This cannot be `const Operation&` because `Operation::getResult()` is // not `const`. - auto checkLocalVocab = [&](Operation& operation, - std::vector expectedWords) -> void { - std::shared_ptr resultTable = operation.getResult(); + auto checkLocalVocab = + [&](Operation& operation, + const std::vector& expectedWordsAsStrings) -> void { + TestWords expectedWords; + auto toLitOrIri = [](const auto& word) { + using namespace ad_utility::triple_component; + if (word.starts_with('<')) { + return LiteralOrIri::iriref(word); + } else { + return LiteralOrIri::literalWithoutQuotes(word); + } + }; + std::ranges::transform(expectedWordsAsStrings, + std::back_inserter(expectedWords), toLitOrIri); + std::shared_ptr resultTable = operation.getResult(); ASSERT_TRUE(resultTable) << "Operation: " << operation.getDescriptor() << std::endl; - std::vector localVocabWords = + TestWords localVocabWords = resultTable->localVocab().getAllWordsForTesting(); // We currently allow the local vocab to have multiple IDs for the same // word, so we have to deduplicate first. @@ -278,8 +303,8 @@ TEST(LocalVocab, propagation) { testQec, {Variable{"?x"}}, {Alias{groupConcatExpression("?y", "|"), Variable{"?concat"}}}, qet(values1)); - checkLocalVocab(groupBy, std::vector{"", "", "", - "\"yN1|yN2\""}); + checkLocalVocab( + groupBy, std::vector{"", "", "", "yN1|yN2"}); // DISTINCT again, but after something has been added to the local vocabulary // (to check that the "y1|y2" added by the GROUP BY does not also appear here, diff --git a/test/NBitIntegerTest.cpp b/test/NBitIntegerTest.cpp index 5609ab2985..0a004375f0 100644 --- a/test/NBitIntegerTest.cpp +++ b/test/NBitIntegerTest.cpp @@ -93,7 +93,7 @@ auto testTranslationNearLimits = []() { // to(b))))`, when `to` is `NBitInteger::toNBit` and `from` is the // corresponding `fromNBit`. This tests the (well-defined) behavior of the // `NBitInteger`s in the presence of overflows. The `wouldOverflow(a, b)` -// function must return `true` if `f(a, b)` would overlow, leading to undefined +// function must return `true` if `f(a, b)` would overflow, leading to undefined // behavior. In those cases, the result `i(f(u(a), u(b))` is evaluated instead // of `f(a, b)`, where `i` is a cast to int64_t and `u` is a cast to `uint64_t`. // The behavior of this operation is well-defined because unsigned integer diff --git a/test/NowDatetimeExpressionTest.cpp b/test/NowDatetimeExpressionTest.cpp new file mode 100644 index 0000000000..83a5941297 --- /dev/null +++ b/test/NowDatetimeExpressionTest.cpp @@ -0,0 +1,57 @@ +// Copyright 2024, University of Freiburg, +// Chair of Algorithms and Data Structures +// Author: Hannes Baumann + +#include "./SparqlExpressionTestHelpers.h" +#include "engine/sparqlExpressions/NowDatetimeExpression.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace sparqlExpression; + +TEST(NowDatetimeExpression, nowExpressionEvaluate) { + std::string strDate = "2011-01-10T14:45:13.815-05:00"; + TestContext testContext{}; + auto& evaluationContext = testContext.context; + + // technically the evaluation context isn't necessary. + evaluationContext._beginIndex = 43; + evaluationContext._endIndex = 1044; + + // The result should hold an ID (from Date) given that NOW() should return by + // definition a xsd:dateTime: "2011-01-10T14:45:13.815-05:00"^^xsd:dateTime + auto resultAsVariant = + NowDatetimeExpression{strDate}.evaluate(&evaluationContext); + ASSERT_TRUE(std::holds_alternative(resultAsVariant)); + const auto& resultDate = std::get(resultAsVariant); + + DateOrLargeYear dateNowTest = + DateOrLargeYear(DateOrLargeYear::parseXsdDatetime(strDate)); + + ASSERT_EQ(resultDate.getDatatype(), Datatype::Date); + ASSERT_EQ(resultDate.getDate(), dateNowTest); + + evaluationContext._isPartOfGroupBy = true; + auto resultAsVariant2 = + NowDatetimeExpression{strDate}.evaluate(&evaluationContext); + ASSERT_TRUE(std::holds_alternative(resultAsVariant2)); + DateOrLargeYear singleDateNow = std::get(resultAsVariant2).getDate(); + ASSERT_EQ(singleDateNow, dateNowTest); +} + +TEST(NowDatetimeExpression, getCacheKeyNowExpression) { + std::string strDate1 = "2011-01-10T14:45:13.815-05:00"; + std::string strDate2 = "2024-06-18T12:16:33.815-06:00"; + NowDatetimeExpression dateNow1(strDate1); + NowDatetimeExpression dateNow2(strDate2); + ASSERT_TRUE(dateNow1.getUnaggregatedVariables().empty()); + auto cacheKey1 = dateNow1.getCacheKey({}); + ASSERT_THAT(cacheKey1, ::testing::StartsWith("NOW ")); + ASSERT_EQ(cacheKey1, dateNow1.getCacheKey({})); + // Given that these use the same date-time string the key should be equal. + ASSERT_EQ(cacheKey1, NowDatetimeExpression{strDate1}.getCacheKey({})); + // Given that dateNow1 and dateNow2 are constructed from different date-time + // strings, it should be rather unlikely that their cache-keys are equal. + auto cacheKey2 = dateNow2.getCacheKey({}); + ASSERT_NE(cacheKey1, cacheKey2); +} diff --git a/test/OperationTest.cpp b/test/OperationTest.cpp index b2bb425001..3d9d3d9f0e 100644 --- a/test/OperationTest.cpp +++ b/test/OperationTest.cpp @@ -39,7 +39,7 @@ TEST(OperationTest, getResultOnlyCached) { NeutralElementOperation n{qec}; // The second `true` means "only read the result if it was cached". // We have just cleared the cache, and so this should return `nullptr`. - EXPECT_EQ(n.getResult(true, true), nullptr); + EXPECT_EQ(n.getResult(true, ComputationMode::ONLY_IF_CACHED), nullptr); EXPECT_EQ(n.runtimeInfo().status_, RuntimeInformation::Status::notStarted); // Nothing has been stored in the cache by this call. EXPECT_EQ(qec->getQueryTreeCache().numNonPinnedEntries(), 0); @@ -58,7 +58,7 @@ TEST(OperationTest, getResultOnlyCached) { // When we now request to only return the result if it is cached, we should // get exactly the same `shared_ptr` as with the previous call. NeutralElementOperation n3{qec}; - EXPECT_EQ(n3.getResult(true, true), result); + EXPECT_EQ(n3.getResult(true, ComputationMode::ONLY_IF_CACHED), result); EXPECT_EQ(n3.runtimeInfo().cacheStatus_, ad_utility::CacheStatus::cachedNotPinned); @@ -67,7 +67,7 @@ TEST(OperationTest, getResultOnlyCached) { QueryExecutionContext qecCopy{*qec}; qecCopy._pinResult = true; NeutralElementOperation n4{&qecCopy}; - EXPECT_EQ(n4.getResult(true, true), result); + EXPECT_EQ(n4.getResult(true, ComputationMode::ONLY_IF_CACHED), result); // The cache status is `cachedNotPinned` because we found the element cached // but not pinned (it does reflect the status BEFORE the operation). @@ -79,7 +79,7 @@ TEST(OperationTest, getResultOnlyCached) { // We have pinned the result, so requesting it again should return a pinned // result. qecCopy._pinResult = false; - EXPECT_EQ(n4.getResult(true, true), result); + EXPECT_EQ(n4.getResult(true, ComputationMode::ONLY_IF_CACHED), result); EXPECT_EQ(n4.runtimeInfo().cacheStatus_, ad_utility::CacheStatus::cachedPinned); @@ -152,7 +152,7 @@ TEST(OperationTest, verifyExceptionIsThrownOnCancellation) { std::this_thread::sleep_for(5ms); handle->cancel(CancellationState::TIMEOUT); }}; - AD_EXPECT_THROW_WITH_MESSAGE_AND_TYPE(operation.computeResult(), + AD_EXPECT_THROW_WITH_MESSAGE_AND_TYPE(operation.computeResult(false), ::testing::HasSubstr("timed out"), ad_utility::CancellationException); } diff --git a/test/PriorityQueueTest.cpp b/test/PriorityQueueTest.cpp index 8ef15aa189..6c78acd977 100644 --- a/test/PriorityQueueTest.cpp +++ b/test/PriorityQueueTest.cpp @@ -96,11 +96,11 @@ TEST(PqTest, TreeUpdateReinsert) { ASSERT_EQ(pq.size(), 0ul); ASSERT_THROW(pq.updateKey(15, &h), ad_utility::NotInPQException); ASSERT_EQ(pq.size(), 0ul); - auto h2 = pq.insert(500, "alot"s); + auto h2 = pq.insert(500, "alot"s); // codespell-ignore ASSERT_EQ(pq.size(), 1ul); h = pq.pop(); ASSERT_EQ(h.score(), 500); - ASSERT_EQ(h.value(), "alot"s); + ASSERT_EQ(h.value(), "alot"s); // codespell-ignore }; TreeBasedPQ pq; test(pq); diff --git a/test/QueryPlannerTest.cpp b/test/QueryPlannerTest.cpp index d374994a35..1b3a74691d 100644 --- a/test/QueryPlannerTest.cpp +++ b/test/QueryPlannerTest.cpp @@ -1223,3 +1223,29 @@ TEST(QueryPlanner, CancellationCancelsQueryPlanning) { HasSubstr("Query planning"), ad_utility::CancellationException); } + +// ___________________________________________________________________________ +TEST(QueryPlanner, JoinWithService) { + auto scan = h::IndexScanFromStrings; + + auto sibling = scan("?x", "", "?y"); + + std::string_view graphPatternAsString = "{ ?x ?z . }"; + + h::expect( + "SELECT * WHERE {" + "SERVICE { ?x ?z . ?y ?a . }}", + h::Service(std::nullopt, "{ ?x ?z . ?y ?a . }")); + + h::expect( + "SELECT * WHERE { ?x ?y ." + "SERVICE { ?x ?z . }}", + h::UnorderedJoins(sibling, h::Service(sibling, graphPatternAsString))); + + h::expect( + "SELECT * WHERE { ?x ?y . " + "SERVICE { ?x ?z . ?y ?a . }}", + h::MultiColumnJoin( + sibling, + h::Sort(h::Service(sibling, "{ ?x ?z . ?y ?a . }")))); +} diff --git a/test/QueryPlannerTestHelpers.h b/test/QueryPlannerTestHelpers.h index d380978a2a..b3cf541eb8 100644 --- a/test/QueryPlannerTestHelpers.h +++ b/test/QueryPlannerTestHelpers.h @@ -4,10 +4,14 @@ #pragma once +#include +#include + #include "./util/GTestHelpers.h" #include "engine/Bind.h" #include "engine/CartesianProductJoin.h" #include "engine/CountAvailablePredicates.h" +#include "engine/Filter.h" #include "engine/IndexScan.h" #include "engine/Join.h" #include "engine/MultiColumnJoin.h" @@ -16,14 +20,13 @@ #include "engine/PathSearch.h" #include "engine/QueryExecutionTree.h" #include "engine/QueryPlanner.h" +#include "engine/Service.h" #include "engine/Sort.h" #include "engine/TextIndexScanForEntity.h" #include "engine/TextIndexScanForWord.h" #include "engine/TextLimit.h" #include "engine/TransitivePathBase.h" #include "engine/Union.h" -#include "gmock/gmock-matchers.h" -#include "gmock/gmock.h" #include "parser/SparqlParser.h" #include "util/IndexTestHelpers.h" @@ -308,6 +311,23 @@ constexpr auto OrderBy = [](const ::OrderBy::SortedVariables& sortedVariables, // Match a `UNION` operation. constexpr auto Union = MatchTypeAndOrderedChildren<::Union>; +// Match a `SERVICE` operation. +constexpr auto Service = [](const std::optional& siblingMatcher, + std::string_view graphPatternAsString) { + const auto optSiblingMatcher = + [&]() -> Matcher&> { + if (siblingMatcher.has_value()) { + return Pointee(siblingMatcher.value()); + } + return IsNull(); + }(); + + return RootOperation<::Service>( + AllOf(AD_PROPERTY(::Service, getSiblingTree, optSiblingMatcher), + AD_PROPERTY(::Service, getGraphPatternAsString, + Eq(graphPatternAsString)))); +}; + /// Parse the given SPARQL `query`, pass it to a `QueryPlanner` with empty /// execution context, and return the resulting `QueryExecutionTree` QueryExecutionTree parseAndPlan(std::string query, QueryExecutionContext* qec) { diff --git a/test/RandomExpressionTest.cpp b/test/RandomExpressionTest.cpp index 94146014ac..cbfe4aa580 100644 --- a/test/RandomExpressionTest.cpp +++ b/test/RandomExpressionTest.cpp @@ -2,8 +2,11 @@ // Chair of Algorithms and Data Structures. // Author: Johannes Kalmbach +#include + #include "./SparqlExpressionTestHelpers.h" #include "engine/sparqlExpressions/RandomExpression.h" +#include "engine/sparqlExpressions/UuidExpressions.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -58,3 +61,90 @@ TEST(RandomExpression, simpleMemberFunctions) { // probability of `1 / 2^64` of a spurious failure. ASSERT_NE(cacheKey, RandomExpression{}.getCacheKey({})); } + +using LiteralOrIri = ad_utility::triple_component::LiteralOrIri; +// The tests for UUID expressions follow almost exactly the pattern +// of the above defined test for RandomExpression. +TEST(UuidExpression, simpleMemberFunctionStrUuid) { + StrUuidExpression strUuid; + ASSERT_TRUE(strUuid.getUnaggregatedVariables().empty()); + auto cacheKeyStrUuid = strUuid.getCacheKey({}); + ASSERT_THAT(cacheKeyStrUuid, ::testing::StartsWith("STRUUID ")); + ASSERT_EQ(cacheKeyStrUuid, strUuid.getCacheKey({})); + StrUuidExpression strUuid2; + ASSERT_NE(cacheKeyStrUuid, strUuid2.getCacheKey({})); +} + +TEST(UuidExpression, simpleMemberFunctionLitUuid) { + UuidExpression iriUuid; + ASSERT_TRUE(iriUuid.getUnaggregatedVariables().empty()); + auto cacheKeyIriUuid = iriUuid.getCacheKey({}); + ASSERT_THAT(cacheKeyIriUuid, ::testing::StartsWith("UUID ")); + ASSERT_EQ(cacheKeyIriUuid, iriUuid.getCacheKey({})); + UuidExpression iriUuid2; + ASSERT_NE(cacheKeyIriUuid, iriUuid2.getCacheKey({})); +} + +TEST(UuidExpression, evaluateStrUuidExpression) { + TestContext testContext{}; + auto& evaluationContext = testContext.context; + evaluationContext._beginIndex = 43; + evaluationContext._endIndex = 1044; + auto resultAsVariant = StrUuidExpression{}.evaluate(&evaluationContext); + + using V = VectorWithMemoryLimit; + ASSERT_TRUE(std::holds_alternative(resultAsVariant)); + const auto& resultVector = std::get(resultAsVariant); + ASSERT_EQ(resultVector.size(), 1001); + + // check that none of the results equals all previous results + std::unordered_set strUuids; + for (auto uuid : resultVector) { + ASSERT_TRUE(std::holds_alternative(uuid)); + LiteralOrIri litUuid = std::get(uuid); + ASSERT_TRUE(litUuid.isLiteral()); + std::string_view strUuid = + asStringViewUnsafe(litUuid.getLiteral().getContent()); + ASSERT_EQ(strUuids.find(std::string(strUuid)), strUuids.end()); + strUuids.insert(std::string(strUuid)); + } + + evaluationContext._isPartOfGroupBy = true; + auto resultAsVariant2 = StrUuidExpression{}.evaluate(&evaluationContext); + ASSERT_TRUE(std::holds_alternative(resultAsVariant2)); + IdOrLiteralOrIri litOrIriUuid = std::get(resultAsVariant2); + ASSERT_TRUE(std::holds_alternative(litOrIriUuid)); + ASSERT_TRUE(std::get(litOrIriUuid).isLiteral()); +} + +TEST(UuidExpression, evaluateUuidExpression) { + TestContext testContext{}; + auto& evaluationContext = testContext.context; + evaluationContext._beginIndex = 43; + evaluationContext._endIndex = 1044; + auto resultAsVariant = UuidExpression{}.evaluate(&evaluationContext); + + using V = VectorWithMemoryLimit; + ASSERT_TRUE(std::holds_alternative(resultAsVariant)); + const auto& resultVector = std::get(resultAsVariant); + ASSERT_EQ(resultVector.size(), 1001); + + // check that none of the results equals all of the other results + std::unordered_set strUuids; + for (auto uuid : resultVector) { + ASSERT_TRUE(std::holds_alternative(uuid)); + LiteralOrIri litUuid = std::get(uuid); + ASSERT_TRUE(litUuid.isIri()); + std::string_view iriUuid = + asStringViewUnsafe(litUuid.getIri().getContent()); + ASSERT_EQ(strUuids.find(std::string(iriUuid)), strUuids.end()); + strUuids.insert(std::string(iriUuid)); + } + + evaluationContext._isPartOfGroupBy = true; + auto resultAsVariant2 = UuidExpression{}.evaluate(&evaluationContext); + ASSERT_TRUE(std::holds_alternative(resultAsVariant2)); + IdOrLiteralOrIri litOrIriUuid = std::get(resultAsVariant2); + ASSERT_TRUE(std::holds_alternative(litOrIriUuid)); + ASSERT_TRUE(std::get(litOrIriUuid).isIri()); +} diff --git a/test/RandomTest.cpp b/test/RandomTest.cpp index c5b049ef21..d66389d28a 100644 --- a/test/RandomTest.cpp +++ b/test/RandomTest.cpp @@ -7,9 +7,11 @@ #include #include #include +#include #include #include #include +#include #include "../test/util/RandomTestHelpers.h" #include "util/Exception.h" @@ -160,7 +162,7 @@ TEST(RandomNumberGeneratorTest, SlowRandomIntGenerator) { seed}; }); - // For use withing the range tests. + // For use within the range tests. const std::vector> ranges{ {4ul, 7ul}, {200ul, 70171ul}, {71747ul, 1936556173ul}}; @@ -179,7 +181,7 @@ TEST(RandomNumberGeneratorTest, RandomDoubleGenerator) { std::numeric_limits::max(), seed}; }); - // For use withing the range tests. + // For use within the range tests. const std::vector> ranges{ {4.74717, 7.4}, {-200.0771370, -70.77713}, {-71747.6666, 1936556173.}}; @@ -235,4 +237,28 @@ TEST(RandomShuffleTest, Seed) { }); } +TEST(UuidGeneratorTest, StrUuidGeneratorTest) { + // Test few times that the returned UUID str is not + // "00000000-0000-0000-0000-000000000000" (nil-UUID) + // and that none of the str-UUIDS is rquivalent to the already + // created ones. + // Pattern for checking that UUID is properly formatted + static constexpr auto uuidPattern = ctll::fixed_string{ + "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{" + "3}-[0-9a-fA-F]{12}$"}; + boost::uuids::string_generator getUuid; + UuidGenerator gen = UuidGenerator(); + std::unordered_set setUuids; + size_t i = 0; + while (i < 100) { + std::string strUuid = gen(); + boost::uuids::uuid uuid = getUuid(strUuid.data()); + ASSERT_EQ(uuid.is_nil(), false); + ASSERT_EQ(setUuids.find(strUuid), setUuids.end()); + ASSERT_TRUE(ctre::match(strUuid)); + setUuids.insert(strUuid); + i++; + } +} + } // namespace ad_utility diff --git a/test/ResultTableColumnOperationsTest.cpp b/test/ResultTableColumnOperationsTest.cpp index c260439811..a04ac895ff 100644 --- a/test/ResultTableColumnOperationsTest.cpp +++ b/test/ResultTableColumnOperationsTest.cpp @@ -61,7 +61,7 @@ static void compareToColumn( // For generating better messages, when failing a test. auto trace{generateLocationTrace(l, "compareToColumn")}; - // Compare every entry with the fitting comparsion function. + // Compare every entry with the fitting comparison function. AD_CONTRACT_CHECK(expectedContent.size() == tableToCompareAgainst.numRows()); for (size_t i = 0; i < expectedContent.size(); i++) { if constexpr (std::floating_point) { @@ -333,7 +333,7 @@ TEST(ResultTableColumnOperations, calculateSpeedupOfColumn) { ad_utility::SlowRandomIntGenerator rowGenerator( 0, table.numRows() - 1); - // Test things trough for all possible input and output columns. + // Test things through for all possible input and output columns. for (size_t outputColumn = 0; outputColumn < table.numColumns(); outputColumn++) { for (size_t firstInputColumn = 0; diff --git a/test/RuntimeInformationTest.cpp b/test/RuntimeInformationTest.cpp index ea6254ae78..885ca3066c 100644 --- a/test/RuntimeInformationTest.cpp +++ b/test/RuntimeInformationTest.cpp @@ -16,6 +16,18 @@ TEST(RuntimeInformation, addLimitOffsetRow) { rti.totalTime_ = 4ms; rti.sizeEstimate_ = 34; + rti.addLimitOffsetRow(LimitOffsetClause{}, 5ms, true); + EXPECT_FALSE( + rti.details_.contains("not-written-to-cache-because-child-of-limit")); + EXPECT_FALSE( + rti.details_.contains("executed-implicitly-during-query-export")); + + rti.addLimitOffsetRow(LimitOffsetClause{}, 5ms, false); + EXPECT_FALSE( + rti.details_.contains("not-written-to-cache-because-child-of-limit")); + EXPECT_FALSE( + rti.details_.contains("executed-implicitly-during-query-export")); + rti.addLimitOffsetRow(LimitOffsetClause{23, 1, 4}, 20ms, true); EXPECT_EQ(rti.descriptor_, "LIMIT 23 OFFSET 4"); EXPECT_EQ(rti.totalTime_, 24ms); @@ -27,10 +39,12 @@ TEST(RuntimeInformation, addLimitOffsetRow) { EXPECT_EQ(child.totalTime_, 4ms); EXPECT_EQ(child.getOperationTime(), 4ms); EXPECT_TRUE(child.details_.at("not-written-to-cache-because-child-of-limit")); + EXPECT_FALSE(rti.details_.at("executed-implicitly-during-query-export")); rti.addLimitOffsetRow(LimitOffsetClause{std::nullopt, 1, 17}, 15ms, false); EXPECT_FALSE(rti.children_.at(0)->details_.at( "not-written-to-cache-because-child-of-limit")); + EXPECT_TRUE(rti.details_.at("executed-implicitly-during-query-export")); EXPECT_EQ(rti.descriptor_, "OFFSET 17"); rti.addLimitOffsetRow(LimitOffsetClause{42, 1, 0}, 15ms, true); diff --git a/test/SelectClauseTest.cpp b/test/SelectClauseTest.cpp index a86f6704a2..26eceb0e93 100644 --- a/test/SelectClauseTest.cpp +++ b/test/SelectClauseTest.cpp @@ -1,6 +1,6 @@ // Copyright 2022, University of Freiburg, // Chair of Algorithms and Data Structures. -// Autor: +// Author: // 2022 - Johannes Kalmbach (kalmbach@informatik.uni-freiburg.de) #include "engine/sparqlExpressions/LiteralExpression.h" diff --git a/test/SerializerTest.cpp b/test/SerializerTest.cpp index edc2fea6b5..0ea8b1266b 100644 --- a/test/SerializerTest.cpp +++ b/test/SerializerTest.cpp @@ -165,7 +165,7 @@ TEST(Serializer, SimpleExample) { A a{}; // Uninitialized, we will read into it; serialization::FileReadSerializer reader{filename}; reader >> a; - // We have succesfully restored the values. + // We have successfully restored the values. ASSERT_EQ(a.a, 42); ASSERT_EQ(a.b, -5); } @@ -425,7 +425,7 @@ TEST(Serializer, Array) { testWithAllSerializers(testNonTriviallyCopyableDatatype); } -// Test that we can succesfully write `string_view`s to a serializer and +// Test that we can successfully write `string_view`s to a serializer and // correctly read them as `string`s. TEST(Serializer, StringViewToString) { auto testString = [](auto&& writer, auto makeReaderFromWriter) { diff --git a/test/ServiceTest.cpp b/test/ServiceTest.cpp index 66e6f2a656..161429154c 100644 --- a/test/ServiceTest.cpp +++ b/test/ServiceTest.cpp @@ -8,9 +8,11 @@ #include #include "engine/Service.h" +#include "global/RuntimeParameters.h" #include "parser/GraphPatternOperation.h" #include "util/IdTableHelpers.h" #include "util/IndexTestHelpers.h" +#include "util/TripleComponentTestHelpers.h" #include "util/http/HttpUtils.h" // Fixture that sets up a test index and a factory for producing mocks for the @@ -163,7 +165,7 @@ TEST_F(ServiceTest, computeResult) { getTsvFunctionFactory( expectedUrl, expectedSparqlQuery, "?x\t?y\n\t\n\t\n\t\n\t\n")}; - std::shared_ptr result = serviceOperation4.getResult(); + std::shared_ptr result = serviceOperation4.getResult(); // Check that `` and `` were contained in the original vocabulary and // that ``, ``, `` were added to the (initially empty) local @@ -173,9 +175,13 @@ TEST_F(ServiceTest, computeResult) { Id idY = getId(""); const auto& localVocab = result->localVocab(); EXPECT_EQ(localVocab.size(), 3); - std::optional idxBla = localVocab.getIndexOrNullopt(""); - std::optional idxBli = localVocab.getIndexOrNullopt(""); - std::optional idxBlu = localVocab.getIndexOrNullopt(""); + auto get = [&localVocab](const std::string& s) { + return localVocab.getIndexOrNullopt( + ad_utility::triple_component::LiteralOrIri::iriref(s)); + }; + std::optional idxBla = get(""); + std::optional idxBli = get(""); + std::optional idxBlu = get(""); ASSERT_TRUE(idxBli.has_value()); ASSERT_TRUE(idxBla.has_value()); ASSERT_TRUE(idxBlu.has_value()); @@ -188,4 +194,100 @@ TEST_F(ServiceTest, computeResult) { IdTable expectedIdTable = makeIdTableFromVector( {{idX, idY}, {idBla, idBli}, {idBlu, idBla}, {idBli, idBlu}}); EXPECT_EQ(result->idTable(), expectedIdTable); + + // Check 5: When a siblingTree with variables common to the Service Clause is + // passed, the Service Operation shall use the siblings result to reduce + // its Query complexity by injecting them as Value Clause + auto iri = ad_utility::testing::iri; + using TC = TripleComponent; + auto siblingTree = std::make_shared( + testQec, + std::make_shared( + testQec, + (parsedQuery::SparqlValues){ + {Variable{"?x"}, Variable{"?y"}, Variable{"?z"}}, + {{TC(iri("")), TC(iri("")), TC(iri(""))}, + {TC(iri("")), TC(iri("")), TC(iri(""))}, + {TC(iri("")), TC(iri("")), TC(iri(""))}}})); + + auto parsedServiceClause5 = parsedServiceClause; + parsedServiceClause5.graphPatternAsString_ = + "{ ?x ?y . ?y ?z2 . }"; + parsedServiceClause5.visibleVariables_.emplace_back("?z2"); + + std::string_view expectedSparqlQuery5 = + "PREFIX doof: SELECT ?x ?y ?z2 " + "WHERE { VALUES (?x ?y) { ( ) ( ) } . ?x ?y . ?y " + " ?z2 . }"; + + Service serviceOperation5{ + testQec, parsedServiceClause5, + getTsvFunctionFactory(expectedUrl, expectedSparqlQuery5, + "?x\t?y\t?z2\n\t\t\n\t\t\n<" + "blu>\t\t\n\t\t\n"), + siblingTree}; + EXPECT_NO_THROW(serviceOperation5.getResult()); + + // Check 6: SiblingTree's rows exceed maxValue + const auto maxValueRowsDefault = + RuntimeParameters().get<"service-max-value-rows">(); + RuntimeParameters().set<"service-max-value-rows">(0); + testQec->getQueryTreeCache().clearAll(); + std::string_view expectedSparqlQuery6 = + "PREFIX doof: SELECT ?x ?y ?z2 " + "WHERE { ?x ?y . ?y ?z2 . }"; + Service serviceOperation6{ + testQec, parsedServiceClause5, + getTsvFunctionFactory(expectedUrl, expectedSparqlQuery6, + "?x\t?y\t?z2\n\t\t\n\t\t\n<" + "blu>\t\t\n\t\t\n"), + siblingTree}; + EXPECT_NO_THROW(serviceOperation6.getResult()); + RuntimeParameters().set<"service-max-value-rows">(maxValueRowsDefault); +} + +TEST_F(ServiceTest, getCacheKey) { + parsedQuery::Service parsedServiceClause{{Variable{"?x"}, Variable{"?y"}}, + Iri{""}, + "PREFIX doof: ", + "{ }"}; + + // The cacheKey of the Service Operation has to depend on the cacheKey of + // the siblingTree, as it might alter the Service Query. + + Service service( + testQec, parsedServiceClause, + getTsvFunctionFactory( + "http://localhorst:80/api", + "PREFIX doof: SELECT ?x ?y WHERE { }", + "?x\t?y\n\t\n\t\n\t\n\t\n")); + + auto ck_noSibling = service.getCacheKey(); + + auto iri = ad_utility::testing::iri; + using TC = TripleComponent; + auto siblingTree = std::make_shared( + testQec, + std::make_shared( + testQec, + (parsedQuery::SparqlValues){ + {Variable{"?x"}, Variable{"?y"}, Variable{"?z"}}, + {{TC(iri("")), TC(iri("")), TC(iri(""))}, + {TC(iri("")), TC(iri("")), TC(iri(""))}}})); + service.setSiblingTree(siblingTree); + + auto ck_sibling = service.getCacheKey(); + EXPECT_NE(ck_noSibling, ck_sibling); + + auto siblingTree2 = std::make_shared( + testQec, + std::make_shared( + testQec, (parsedQuery::SparqlValues){ + {Variable{"?x"}, Variable{"?y"}, Variable{"?z"}}, + {{TC(iri("")), TC(iri("")), TC(iri(""))}}})); + + service.setSiblingTree(siblingTree2); + + auto ck_changedSibling = service.getCacheKey(); + EXPECT_NE(ck_sibling, ck_changedSibling); } diff --git a/test/SparqlAntlrParserTest.cpp b/test/SparqlAntlrParserTest.cpp index a11d54f865..e0d357f5cd 100644 --- a/test/SparqlAntlrParserTest.cpp +++ b/test/SparqlAntlrParserTest.cpp @@ -18,8 +18,10 @@ #include "SparqlAntlrParserTestHelpers.h" #include "engine/sparqlExpressions/LangExpression.h" #include "engine/sparqlExpressions/LiteralExpression.h" +#include "engine/sparqlExpressions/NowDatetimeExpression.h" #include "engine/sparqlExpressions/RandomExpression.h" #include "engine/sparqlExpressions/RegexExpression.h" +#include "engine/sparqlExpressions/UuidExpressions.h" #include "parser/ConstructClause.h" #include "parser/SparqlParserHelpers.h" #include "parser/sparqlParser/SparqlQleverVisitor.h" @@ -1382,7 +1384,9 @@ TEST(SparqlParser, builtInCall) { expectBuiltInCall("StR(?x)", matchUnary(&makeStrExpression)); expectBuiltInCall("year(?x)", matchUnary(&makeYearExpression)); expectBuiltInCall("month(?x)", matchUnary(&makeMonthExpression)); + expectBuiltInCall("tz(?x)", matchUnary(&makeTimezoneStrExpression)); expectBuiltInCall("day(?x)", matchUnary(&makeDayExpression)); + expectBuiltInCall("NOW()", matchPtr()); expectBuiltInCall("hours(?x)", matchUnary(&makeHoursExpression)); expectBuiltInCall("minutes(?x)", matchUnary(&makeMinutesExpression)); expectBuiltInCall("seconds(?x)", matchUnary(&makeSecondsExpression)); @@ -1394,8 +1398,11 @@ TEST(SparqlParser, builtInCall) { expectBuiltInCall("ISBLANK(?x)", matchUnary(&makeIsBlankExpression)); expectBuiltInCall("ISLITERAL(?x)", matchUnary(&makeIsLiteralExpression)); expectBuiltInCall("ISNUMERIC(?x)", matchUnary(&makeIsNumericExpression)); + expectBuiltInCall("DATATYPE(?x)", matchUnary(&makeDatatypeExpression)); expectBuiltInCall("BOUND(?x)", matchUnary(&makeBoundExpression)); expectBuiltInCall("RAND()", matchPtr()); + expectBuiltInCall("STRUUID()", matchPtr()); + expectBuiltInCall("UUID()", matchPtr()); expectBuiltInCall("COALESCE(?x)", matchUnary(makeCoalesceExpressionVariadic)); expectBuiltInCall("COALESCE()", matchNary(makeCoalesceExpressionVariadic)); expectBuiltInCall("COALESCE(?x, ?y, ?z)", @@ -1416,12 +1423,37 @@ TEST(SparqlParser, builtInCall) { expectBuiltInCall("IF(?a, ?h, ?c)", matchNary(&makeIfExpression, Var{"?a"}, Var{"?h"}, Var{"?c"})); + expectFails("STRDT()"); + expectFails("STRDT(?x)"); + expectBuiltInCall("STRDT(?x, ?y)", + matchNary(&makeStrIriDtExpression, Var{"?x"}, Var{"?y"})); + expectBuiltInCall( + "STRDT(?x, )", + matchNaryWithChildrenMatchers( + &makeStrIriDtExpression, variableExpressionMatcher(Var{"?x"}), + matchLiteralExpression(iri("")))); + + expectFails("STRLANG()"); + expectFails("STRALANG(?x)"); + expectBuiltInCall("STRLANG(?x, ?y)", + matchNary(&makeStrLangTagExpression, Var{"?x"}, Var{"?y"})); + expectBuiltInCall( + "STRLANG(?x, \"en\")", + matchNaryWithChildrenMatchers(&makeStrLangTagExpression, + variableExpressionMatcher(Var{"?x"}), + matchLiteralExpression(lit("en")))); + // The following three cases delegate to a separate parsing function, so we // only perform rather simple checks. expectBuiltInCall("COUNT(?x)", matchPtr()); expectBuiltInCall("regex(?x, \"ab\")", matchPtr()); expectBuiltInCall("LANG(?x)", matchPtr()); - expectFails("SHA512(?x)"); + + expectBuiltInCall("MD5(?x)", matchUnary(&makeMD5Expression)); + expectBuiltInCall("SHA1(?x)", matchUnary(&makeSHA1Expression)); + expectBuiltInCall("SHA256(?x)", matchUnary(&makeSHA256Expression)); + expectBuiltInCall("SHA384(?x)", matchUnary(&makeSHA384Expression)); + expectBuiltInCall("SHA512(?x)", matchUnary(&makeSHA512Expression)); expectBuiltInCall("encode_for_uri(?x)", matchUnary(&makeEncodeForUriExpression)); @@ -1534,6 +1566,7 @@ TEST(SparqlParser, FunctionCall) { // manually add it when constructing parser inputs. auto geof = absl::StrCat("<", GEOF_PREFIX.second); auto math = absl::StrCat("<", MATH_PREFIX.second); + auto xsd = absl::StrCat("<", XSD_PREFIX.second); // Correct function calls. Check that the parser picks the correct expression. expectFunctionCall(absl::StrCat(geof, "latitude>(?x)"), @@ -1555,6 +1588,14 @@ TEST(SparqlParser, FunctionCall) { matchUnary(&makeCosExpression)); expectFunctionCall(absl::StrCat(math, "tan>(?x)"), matchUnary(&makeTanExpression)); + expectFunctionCall(absl::StrCat(xsd, "int>(?x)"), + matchUnary(&makeConvertToIntExpression)); + expectFunctionCall(absl::StrCat(xsd, "integer>(?x)"), + matchUnary(&makeConvertToIntExpression)); + expectFunctionCall(absl::StrCat(xsd, "double>(?x)"), + matchUnary(&makeConvertToDoubleExpression)); + expectFunctionCall(absl::StrCat(xsd, "decimal>(?x)"), + matchUnary(&makeConvertToDoubleExpression)); // Wrong number of arguments. expectFunctionCallFails( @@ -1610,3 +1651,112 @@ TEST(SparqlParser, binaryStringExpressions) { expectBuiltInCall("STRAFTER(?x, ?y)", makeMatcher(&makeStrAfterExpression)); expectBuiltInCall("STRBEFORE(?x, ?y)", makeMatcher(&makeStrBeforeExpression)); } + +// Update queries are WIP. The individual parts to parse some update queries +// are in place the code to process them is still unfinished. Therefore we +// don't accept update queries. +TEST(SparqlParser, updateQueryUnsupported) { + auto expectUpdateFails = ExpectParseFails<&Parser::queryOrUpdate>{}; + auto contains = [](const std::string& s) { return ::testing::HasSubstr(s); }; + auto updateUnsupported = + contains("SPARQL 1.1 Update currently not supported by QLever."); + + // Test all the cases because some functionality will be enabled shortly. + expectUpdateFails("INSERT DATA { }", updateUnsupported); + expectUpdateFails("DELETE DATA { }", updateUnsupported); + expectUpdateFails("DELETE { } WHERE { ?s ?p ?o }", + updateUnsupported); + expectUpdateFails("INSERT { } WHERE { ?s ?p ?o }", + updateUnsupported); + expectUpdateFails("DELETE WHERE { }", updateUnsupported); + expectUpdateFails("LOAD ", updateUnsupported); + expectUpdateFails("CLEAR GRAPH ", updateUnsupported); + expectUpdateFails("DROP GRAPH ", updateUnsupported); + expectUpdateFails("CREATE GRAPH ", updateUnsupported); + expectUpdateFails("ADD GRAPH TO DEFAULT", updateUnsupported); + expectUpdateFails("MOVE DEFAULT TO GRAPH ", updateUnsupported); + expectUpdateFails("COPY GRAPH TO GRAPH ", updateUnsupported); +} + +TEST(SparqlParser, UpdateQuery) { + auto expectUpdate = ExpectCompleteParse<&Parser::update>{ + {{INTERNAL_PREDICATE_PREFIX_NAME, INTERNAL_PREDICATE_PREFIX_IRI}}}; + auto expectUpdateFails = ExpectParseFails<&Parser::update>{}; + auto Iri = [](std::string_view stringWithBrackets) { + return TripleComponent::Iri::fromIriref(stringWithBrackets); + }; + auto Literal = [](std::string s) { + return TripleComponent::Literal::fromStringRepresentation(s); + }; + + expectUpdate("INSERT DATA { }", + m::UpdateQuery({}, {{Iri(""), Iri(""), Iri("")}}, + m::GraphPattern())); + expectUpdate( + "INSERT DATA { \"foo:bar\" }", + m::UpdateQuery({}, {{Iri(""), Iri(""), Literal("\"foo:bar\"")}}, + m::GraphPattern())); + expectUpdate("DELETE DATA { }", + m::UpdateQuery({{Iri(""), Iri(""), Iri("")}}, {}, + m::GraphPattern())); + expectUpdate( + "DELETE { ?a } WHERE { ?a }", + m::UpdateQuery( + {{Var("?a"), Iri(""), Iri("")}}, {}, + m::GraphPattern(m::Triples({{Iri(""), "", Var{"?a"}}})))); + expectUpdate( + "DELETE { ?a } INSERT { ?a } WHERE { ?a }", + m::UpdateQuery( + {{Var("?a"), Iri(""), Iri("")}}, + {{Iri(""), Var("?a"), Iri("")}}, + m::GraphPattern(m::Triples({{Iri(""), "", Var{"?a"}}})))); + expectUpdate( + "DELETE WHERE { ?a ?c }", + m::UpdateQuery( + {{Var("?a"), Iri(""), Var("?c")}}, {}, + m::GraphPattern(m::Triples({{Var{"?a"}, "", Var{"?c"}}})))); + expectUpdate("CLEAR DEFAULT", + m::UpdateQuery({{Var("?s"), Var("?p"), Var("?o")}}, {}, + m::GraphPattern( + m::Triples({{Var("?s"), "?p", Var("?o")}})))); + expectUpdateFails("INSERT DATA { ?a ?b ?c }"); + expectUpdateFails("WITH DELETE { ?a ?b ?c } WHERE { ?a ?b ?c }"); + expectUpdateFails("DELETE { ?a ?b ?c } USING WHERE { ?a ?b ?c }"); + expectUpdateFails("INSERT DATA { GRAPH { } }"); + // Unsupported features. + expectUpdateFails( + "INSERT DATA { } ; INSERT { ?a } WHERE { ?a " + "}"); + expectUpdateFails("LOAD "); + expectUpdateFails("CLEAR NAMED"); + expectUpdateFails("CLEAR GRAPH "); + expectUpdateFails("CREATE GRAPH "); + expectUpdateFails("DROP GRAPH "); + expectUpdateFails("MOVE GRAPH TO DEFAULT"); + expectUpdateFails("ADD DEFAULT TO GRAPH "); + expectUpdateFails("COPY DEFAULT TO GRAPH "); + expectUpdateFails( + "DELETE { ?a } USING NAMED WHERE { ?a }"); + expectUpdateFails("WITH DELETE { ?a } WHERE { ?a }"); +} + +TEST(SparqlParser, GraphOrDefault) { + // Explicitly test this part, because all features that use it are not yet + // supported. + auto expectGraphOrDefault = ExpectCompleteParse<&Parser::graphOrDefault>{ + {{INTERNAL_PREDICATE_PREFIX_NAME, INTERNAL_PREDICATE_PREFIX_IRI}}}; + expectGraphOrDefault("DEFAULT", testing::VariantWith(testing::_)); + expectGraphOrDefault( + "GRAPH ", + testing::VariantWith(AD_PROPERTY( + TripleComponent::Iri, toStringRepresentation, testing::Eq("")))); +} + +TEST(SparqlParser, GraphRef) { + auto expectGraphRefAll = ExpectCompleteParse<&Parser::graphRefAll>{ + {{INTERNAL_PREDICATE_PREFIX_NAME, INTERNAL_PREDICATE_PREFIX_IRI}}}; + expectGraphRefAll("DEFAULT", m::Variant()); + expectGraphRefAll("NAMED", m::Variant()); + expectGraphRefAll("ALL", m::Variant()); + expectGraphRefAll("GRAPH ", m::GraphRefIri("")); +} diff --git a/test/SparqlAntlrParserTestHelpers.h b/test/SparqlAntlrParserTestHelpers.h index 9972deca8c..6092eb6485 100644 --- a/test/SparqlAntlrParserTestHelpers.h +++ b/test/SparqlAntlrParserTestHelpers.h @@ -794,7 +794,7 @@ inline auto SelectQuery = namespace pq { -// This is implemented as a separater Matcher because it generates some overhead +// This is implemented as a separated Matcher because it generates some overhead // in the tests. inline auto OriginalString = [](const std::string& originalString) -> Matcher { @@ -824,9 +824,9 @@ inline auto ConstructQuery(const std::vector>& elems, -> Matcher { return testing::AllOf( AD_PROPERTY(ParsedQuery, hasConstructClause, testing::IsTrue()), - AD_PROPERTY( - ParsedQuery, constructClause, - AD_FIELD(parsedQuery::ConstructClause, triples_, testing::Eq(elems))), + AD_PROPERTY(ParsedQuery, constructClause, + AD_FIELD(parsedQuery::ConstructClause, triples_, + testing::ElementsAreArray(elems))), RootGraphPattern(m)); } @@ -836,4 +836,28 @@ inline auto VisibleVariables = return AD_PROPERTY(ParsedQuery, getVisibleVariables, testing::Eq(elems)); }; +inline auto UpdateQuery = + [](const std::vector& toDelete, + const std::vector& toInsert, + const Matcher& graphPatternMatcher) + -> Matcher { + return testing::AllOf( + AD_PROPERTY(ParsedQuery, hasUpdateClause, testing::IsTrue()), + AD_PROPERTY(ParsedQuery, updateClause, + AD_FIELD(parsedQuery::UpdateClause, toDelete_, + testing::ElementsAreArray(toDelete))), + AD_PROPERTY(ParsedQuery, updateClause, + AD_FIELD(parsedQuery::UpdateClause, toInsert_, + testing::ElementsAreArray(toInsert))), + RootGraphPattern(graphPatternMatcher)); +}; + +template +auto inline Variant = []() { return testing::VariantWith(testing::_); }; + +auto inline GraphRefIri = [](const string& iri) { + return testing::VariantWith(AD_PROPERTY( + TripleComponent::Iri, toStringRepresentation, testing::Eq(iri))); +}; + } // namespace matchers diff --git a/test/SparqlDataTypesTest.cpp b/test/SparqlDataTypesTest.cpp index d6f24ca6f0..e4cf4279fe 100644 --- a/test/SparqlDataTypesTest.cpp +++ b/test/SparqlDataTypesTest.cpp @@ -16,7 +16,7 @@ using enum PositionInTriple; namespace { struct ContextWrapper { Index _index{ad_utility::makeUnlimitedAllocator()}; - ResultTable _resultTable{ + Result _resultTable{ IdTable{ad_utility::testing::makeAllocator()}, {}, LocalVocab{}}; // TODO `VariableToColumnMap` VariableToColumnMap _hashMap{}; @@ -27,7 +27,7 @@ struct ContextWrapper { void setIdTable(IdTable&& table) { _resultTable = - ResultTable{std::move(table), {}, _resultTable.getSharedLocalVocab()}; + Result{std::move(table), {}, _resultTable.getSharedLocalVocab()}; } }; diff --git a/test/SparqlExpressionTest.cpp b/test/SparqlExpressionTest.cpp index 5dee81b2e3..387ce1bec8 100644 --- a/test/SparqlExpressionTest.cpp +++ b/test/SparqlExpressionTest.cpp @@ -516,6 +516,35 @@ TEST(SparqlExpression, dateOperators) { testYear(Ids{Id::makeFromDouble(42.0)}, Ids{U}); testYear(Ids{Id::makeFromBool(false)}, Ids{U}); testYear(IdOrLiteralOrIriVec{lit("noDate")}, Ids{U}); + + // test makeTimezoneStrExpression + using Timezone = std::variant; + auto checkStrTimezone = testUnaryExpression<&makeTimezoneStrExpression>; + Timezone tz = -5; + auto d1 = DateOrLargeYear(Date(2011, 1, 10, 14, 45, 13.815, tz)); + checkStrTimezone(Ids{Id::makeFromDate(d1)}, + IdOrLiteralOrIriVec{lit("-05:00")}); + tz = 23; + auto d2 = DateOrLargeYear(Date(2011, 1, 10, 14, 45, 13.815, tz)); + checkStrTimezone(Ids{Id::makeFromDate(d2)}, + IdOrLiteralOrIriVec{lit("+23:00")}); + tz = Date::TimeZoneZ{}; + auto d3 = DateOrLargeYear(Date(2011, 1, 10, 14, 45, 13.815, tz)); + checkStrTimezone(Ids{Id::makeFromDate(d3)}, IdOrLiteralOrIriVec{lit("Z")}); + tz = Date::NoTimeZone{}; + DateOrLargeYear d4 = DateOrLargeYear(Date(2011, 1, 10, 14, 45, 13.815, tz)); + checkStrTimezone(Ids{Id::makeFromDate(d4)}, IdOrLiteralOrIriVec{lit("")}); + DateOrLargeYear d5 = DateOrLargeYear(Date(2012, 1, 4, 14, 45)); + checkStrTimezone(Ids{Id::makeFromDate(d5)}, IdOrLiteralOrIriVec{lit("")}); + Id U = Id::makeUndefined(); + checkStrTimezone(IdOrLiteralOrIriVec{lit("2011-01-10T14:")}, + IdOrLiteralOrIriVec{U}); + checkStrTimezone(Ids{Id::makeFromDouble(120.0123)}, IdOrLiteralOrIriVec{U}); + checkStrTimezone(Ids{Id::makeUndefined()}, IdOrLiteralOrIriVec{U}); + DateOrLargeYear d6 = DateOrLargeYear(-1394785, DateOrLargeYear::Type::Year); + checkStrTimezone(Ids{Id::makeFromDate(d6)}, IdOrLiteralOrIriVec{lit("")}); + DateOrLargeYear d7 = DateOrLargeYear(10000, DateOrLargeYear::Type::Year); + checkStrTimezone(Ids{Id::makeFromDate(d7)}, IdOrLiteralOrIriVec{lit("")}); } // _____________________________________________________________________________________ @@ -704,6 +733,54 @@ TEST(SparqlExpression, substr) { IdOrLiteralOrIri{lit("bye")}); } +// _____________________________________________________________________________________ +TEST(SparqlExpression, strIriDtTagged) { + auto U = Id::makeUndefined(); + auto checkStrIriTag = + std::bind_front(testNaryExpression, &makeStrIriDtExpression); + checkStrIriTag(IdOrLiteralOrIriVec{lit( + "123", "^^")}, + IdOrLiteralOrIriVec{lit("123")}, + IdOrLiteralOrIriVec{ + iriref("")}); + checkStrIriTag( + IdOrLiteralOrIriVec{lit("iiii", "^^")}, + IdOrLiteralOrIriVec{lit("iiii")}, + IdOrLiteralOrIriVec{iriref("")}); + checkStrIriTag(IdOrLiteralOrIriVec{U}, + IdOrLiteralOrIriVec{iriref("")}, + IdOrLiteralOrIriVec{U}); + checkStrIriTag(IdOrLiteralOrIriVec{U}, IdOrLiteralOrIriVec{lit("iiii")}, + IdOrLiteralOrIriVec{U}); + checkStrIriTag(IdOrLiteralOrIriVec{U}, IdOrLiteralOrIriVec{lit("XVII")}, + IdOrLiteralOrIriVec{lit("")}); +} + +// _____________________________________________________________________________________ +TEST(SparqlExpression, strLangTagged) { + auto U = Id::makeUndefined(); + auto checkStrTag = + std::bind_front(testNaryExpression, &makeStrLangTagExpression); + checkStrTag(IdOrLiteralOrIriVec{lit("chat", "@en")}, + IdOrLiteralOrIriVec{lit("chat")}, IdOrLiteralOrIriVec{lit("en")}); + checkStrTag(IdOrLiteralOrIriVec{lit("chat", "@en-US")}, + IdOrLiteralOrIriVec{lit("chat")}, + IdOrLiteralOrIriVec{lit("en-US")}); + checkStrTag(IdOrLiteralOrIriVec{lit("Sprachnachricht", "@de-Latn-de")}, + IdOrLiteralOrIriVec{lit("Sprachnachricht")}, + IdOrLiteralOrIriVec{lit("de-Latn-de")}); + checkStrTag(IdOrLiteralOrIriVec{U}, IdOrLiteralOrIriVec{lit("chat")}, + IdOrLiteralOrIriVec{lit("d1235")}); + checkStrTag(IdOrLiteralOrIriVec{U}, IdOrLiteralOrIriVec{lit("reporter")}, + IdOrLiteralOrIriVec{lit("@")}); + checkStrTag(IdOrLiteralOrIriVec{U}, IdOrLiteralOrIriVec{lit("chat")}, + IdOrLiteralOrIriVec{lit("")}); + checkStrTag(IdOrLiteralOrIriVec{U}, IdOrLiteralOrIriVec{U}, + IdOrLiteralOrIriVec{lit("d")}); + checkStrTag(IdOrLiteralOrIriVec{U}, IdOrLiteralOrIriVec{U}, + IdOrLiteralOrIriVec{U}); +} + // _____________________________________________________________________________________ TEST(SparqlExpression, unaryNegate) { auto checkNegate = testUnaryExpression<&makeUnaryNegateExpression>; @@ -805,6 +882,173 @@ TEST(SparqlExpression, isSomethingFunctions) { Ids{T, T, T, T, T, T, T, T, T, F}); } +// ____________________________________________________________________________ +TEST(SparqlExpression, DatatypeExpression) { + U = Id::makeUndefined(); + auto d1 = DateOrLargeYear::parseXsdDatetime("1900-12-13T03:12:00.33Z"); + auto d2 = DateOrLargeYear::parseGYear("-10000"); + auto d3 = DateOrLargeYear::parseGYear("1900"); + auto d4 = DateOrLargeYear::parseXsdDate("2024-06-13"); + auto d5 = DateOrLargeYear::parseGYearMonth("2024-06"); + Id DateId1 = Id::makeFromDate(d1); + Id DateId2 = Id::makeFromDate(d2); + Id DateId3 = Id::makeFromDate(d3); + Id DateId4 = Id::makeFromDate(d4); + Id DateId5 = Id::makeFromDate(d5); + auto checkGetDatatype = testUnaryExpression<&makeDatatypeExpression>; + checkGetDatatype(IdOrLiteralOrIriVec{testContext().x}, + IdOrLiteralOrIriVec{U}); + checkGetDatatype( + IdOrLiteralOrIriVec{testContext().alpha}, + IdOrLiteralOrIriVec{iriref("")}); + checkGetDatatype( + IdOrLiteralOrIriVec{testContext().zz}, + IdOrLiteralOrIriVec{ + iriref("")}); + checkGetDatatype( + IdOrLiteralOrIriVec{testContext().notInVocabB}, + IdOrLiteralOrIriVec{iriref("")}); + checkGetDatatype(IdOrLiteralOrIriVec{testContext().notInVocabD}, + IdOrLiteralOrIriVec{U}); + checkGetDatatype(IdOrLiteralOrIriVec{lit( + "123", "^^")}, + IdOrLiteralOrIriVec{ + iriref("")}); + checkGetDatatype( + IdOrLiteralOrIriVec{lit("Simple StrStr")}, + IdOrLiteralOrIriVec{iriref("")}); + checkGetDatatype( + IdOrLiteralOrIriVec{lit("english", "@en")}, + IdOrLiteralOrIriVec{ + iriref("")}); + checkGetDatatype(IdOrLiteralOrIriVec{U}, IdOrLiteralOrIriVec{U}); + checkGetDatatype(IdOrLiteralOrIriVec{DateId1}, + IdOrLiteralOrIriVec{ + iriref("")}); + checkGetDatatype( + IdOrLiteralOrIriVec{DateId2}, + IdOrLiteralOrIriVec{iriref("")}); + checkGetDatatype( + IdOrLiteralOrIriVec{DateId3}, + IdOrLiteralOrIriVec{iriref("")}); + checkGetDatatype( + IdOrLiteralOrIriVec{DateId4}, + IdOrLiteralOrIriVec{iriref("")}); + checkGetDatatype(IdOrLiteralOrIriVec{DateId5}, + IdOrLiteralOrIriVec{iriref( + "")}); + checkGetDatatype( + IdOrLiteralOrIriVec{Id::makeFromInt(212378233)}, + IdOrLiteralOrIriVec{iriref("")}); + checkGetDatatype( + IdOrLiteralOrIriVec{Id::makeFromDouble(2.3475)}, + IdOrLiteralOrIriVec{iriref("")}); + checkGetDatatype(IdOrLiteralOrIriVec{Id::makeFromBool(false)}, + IdOrLiteralOrIriVec{ + iriref("")}); + checkGetDatatype( + IdOrLiteralOrIriVec{Id::makeFromInt(true)}, + IdOrLiteralOrIriVec{iriref("")}); + checkGetDatatype( + IdOrLiteralOrIriVec{lit("")}, + IdOrLiteralOrIriVec{iriref("")}); + checkGetDatatype( + IdOrLiteralOrIriVec{lit(" ", "@de-LATN-de")}, + IdOrLiteralOrIriVec{ + iriref("")}); + checkGetDatatype( + IdOrLiteralOrIriVec{lit("testval", "^^")}, + IdOrLiteralOrIriVec{iriref("")}); + checkGetDatatype(IdOrLiteralOrIriVec{iriref("")}, + IdOrLiteralOrIriVec{U}); + + // test corner case DatatypeValueGetter + TestContext ctx; + AD_EXPECT_THROW_WITH_MESSAGE( + sparqlExpression::detail::DatatypeValueGetter{}(Id::max(), &ctx.context), + ::testing::ContainsRegex("should be unreachable")); +} + +// ____________________________________________________________________________ +TEST(SparqlExpression, testStrToHashExpressions) { + auto checkGetMD5Expression = testUnaryExpression<&makeMD5Expression>; + auto checkGetSHA1Expression = testUnaryExpression<&makeSHA1Expression>; + auto checkGetSHA256Expression = testUnaryExpression<&makeSHA256Expression>; + auto checkGetSHA384Expression = testUnaryExpression<&makeSHA384Expression>; + auto checkGetSHA512Expression = testUnaryExpression<&makeSHA512Expression>; + std::string testStr1 = ""; + std::string testStr2 = "Friburg23o"; + std::string testStr3 = "abc"; + checkGetMD5Expression( + idOrLitOrStringVec({U, testStr1, testStr2, testStr3}), + idOrLitOrStringVec({U, "d41d8cd98f00b204e9800998ecf8427e", + "9d9a73f67e20835e516029541595c381", + "900150983cd24fb0d6963f7d28e17f72"})); + checkGetSHA1Expression( + idOrLitOrStringVec({U, testStr1, testStr2, testStr3}), + idOrLitOrStringVec({U, "da39a3ee5e6b4b0d3255bfef95601890afd80709", + "c3a77a6104fa091f590f594b3e2dba2668196d3c", + "a9993e364706816aba3e25717850c26c9cd0d89d"})); + checkGetSHA256Expression( + idOrLitOrStringVec({U, testStr1, testStr2, testStr3}), + idOrLitOrStringVec( + {U, + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "af8d98f09845a700aea36b35e8cc3a35632e38d0f7be9c0ca508e53c578da900", + "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015a" + "d"})); + checkGetSHA384Expression( + idOrLitOrStringVec({U, testStr1, testStr2, testStr3}), + idOrLitOrStringVec({U, + "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0c" + "c7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b", + "72810006e3b418ebd179812522cafa486cd6c2a988378fac148a" + "f1a9a098a01ce3373734c23978f7df68bf7e98955c02", + "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b" + "605a43ff5bed8086072ba1e7cc2358baeca134c825a7"})); + checkGetSHA512Expression( + idOrLitOrStringVec({U, testStr1, testStr2, testStr3}), + idOrLitOrStringVec( + {U, + "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d" + "0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", + "be4422bfad59ee51e98dc51c540dc9d85333cb786333b152d13b2bebde1bdaa499e" + "9d4e1370a5bb2e831f4443b1358f2301fd5214ba80554ea0ff1d185c3b027", + "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a219" + "2992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"})); +} + +// ____________________________________________________________________________ +TEST(SparqlExpression, testToNumericExpression) { + Id T = Id::makeFromBool(true); + Id F = Id::makeFromBool(false); + auto checkGetInt = testUnaryExpression<&makeConvertToIntExpression>; + auto checkGetDouble = testUnaryExpression<&makeConvertToDoubleExpression>; + + checkGetInt( + idOrLitOrStringVec({U, " -1275", "5.97", "-78.97", "-5BoB6", "FreBurg1", + "", " .", " 42\n", " 0.01 ", "", "@", "@?+1", "1"}), + Ids{U, I(-1275), U, U, U, U, U, U, I(42), U, U, U, U, I(1)}); + checkGetDouble( + idOrLitOrStringVec({U, "-122.2", "19,96", " 128789334.345 ", "-0.f", + " 0.007 ", " -14.75 ", "Q", "@!+?", "1"}), + Ids{U, D(-122.2), U, D(128789334.345), U, D(0.007), D(-14.75), U, U, + D(1.00)}); + checkGetInt(idOrLitOrStringVec( + {U, I(-12475), I(42), I(0), D(-14.57), D(33.0), D(0.00001)}), + Ids{U, I(-12475), I(42), I(0), I(-14), I(33), I(0)}); + checkGetDouble( + idOrLitOrStringVec( + {U, I(-12475), I(42), I(0), D(-14.57), D(33.0), D(0.00001)}), + Ids{U, D(-12475.00), D(42.00), D(0.00), D(-14.57), D(33.00), D(0.00001)}); + checkGetDouble(IdOrLiteralOrIriVec{lit("."), lit("-12.745"), T, F, + lit("0.003"), lit("1")}, + Ids{U, D(-12.745), D(1.00), D(0.00), D(0.003), D(1.00)}); + checkGetInt(IdOrLiteralOrIriVec{lit("."), lit("-12.745"), T, F, lit(".03"), + lit("1"), lit("-33")}, + Ids{U, U, I(1), I(0), U, I(1), I(-33)}); +} + // ____________________________________________________________________________ TEST(SparqlExpression, geoSparqlExpressions) { auto checkLat = testUnaryExpression<&makeLatitudeExpression>; @@ -926,7 +1170,7 @@ TEST(SparqlExpression, ReplaceExpression) { IdOrLiteralOrIri{lit("(?i)[ei]")}, IdOrLiteralOrIri{lit("x")}}); - // Multiple matches withing the same string + // Multiple matches within the same string checkReplace( IdOrLiteralOrIri{lit("wEeDEflE")}, std::tuple{IdOrLiteralOrIri{lit("weeeDeeflee")}, diff --git a/test/SparqlExpressionTestHelpers.h b/test/SparqlExpressionTestHelpers.h index 169ae5da97..4f67faa8c1 100644 --- a/test/SparqlExpressionTestHelpers.h +++ b/test/SparqlExpressionTestHelpers.h @@ -3,6 +3,7 @@ // Author: Johannes Kalmbach #include "./util/IdTestHelpers.h" +#include "./util/TripleComponentTestHelpers.h" #include "engine/sparqlExpressions/SparqlExpression.h" #include "global/ValueIdComparators.h" #include "gtest/gtest.h" @@ -82,16 +83,24 @@ struct TestContext { zz = getId("\"zz\"@en"); blank = Id::makeFromBlankNodeIndex(BlankNodeIndex::make(0)); + constexpr auto lit = [](std::string_view s) { + return ad_utility::triple_component::LiteralOrIri::literalWithoutQuotes( + s); + }; + constexpr auto iri = [](const std::string& s) { + return ad_utility::triple_component::LiteralOrIri::iriref(s); + }; + notInVocabA = Id::makeFromLocalVocabIndex( - localVocab.getIndexAndAddIfNotContained("\"notInVocabA\"")); + localVocab.getIndexAndAddIfNotContained(lit("notInVocabA"))); notInVocabB = Id::makeFromLocalVocabIndex( - localVocab.getIndexAndAddIfNotContained("\"notInVocabB\"")); + localVocab.getIndexAndAddIfNotContained(lit("notInVocabB"))); notInVocabC = Id::makeFromLocalVocabIndex( - localVocab.getIndexAndAddIfNotContained("")); + localVocab.getIndexAndAddIfNotContained(iri(""))); notInVocabD = Id::makeFromLocalVocabIndex( - localVocab.getIndexAndAddIfNotContained("")); + localVocab.getIndexAndAddIfNotContained(iri(""))); notInVocabAelpha = Id::makeFromLocalVocabIndex( - localVocab.getIndexAndAddIfNotContained("\"notInVocabÄlpha\"")); + localVocab.getIndexAndAddIfNotContained(lit("notInVocabÄlpha"))); // Set up the `table` that represents the previous partial query results. It // has five columns/variables: ?ints (only integers), ?doubles (only diff --git a/test/SparqlExpressionTypesTest.cpp b/test/SparqlExpressionTypesTest.cpp index a05d650185..e95ba962f4 100644 --- a/test/SparqlExpressionTypesTest.cpp +++ b/test/SparqlExpressionTypesTest.cpp @@ -34,7 +34,7 @@ TEST(SparqlExpressionTypes, printIdOrString) { IdOrLiteralOrIri idOrString{Id::makeUndefined()}; PrintTo(idOrString, &str); - ASSERT_EQ(str.str(), "Undefined:Undefined"); + ASSERT_EQ(str.str(), "U:0"); idOrString = LiteralOrIri::literalWithoutQuotes("bimm"); // Clear the stringstream. str.str({}); diff --git a/test/StringSortComparatorTest.cpp b/test/StringSortComparatorTest.cpp index 6546b1786c..ade2178ae0 100644 --- a/test/StringSortComparatorTest.cpp +++ b/test/StringSortComparatorTest.cpp @@ -90,7 +90,7 @@ TEST(StringSortComparatorTest, TripleComponentComparatorQuarternary) { ASSERT_TRUE(comp("\"Hannibal\"@en", "\"HanNibal\"@en")); - // something is not smaller thant itself + // something is not smaller than itself ASSERT_FALSE(comp("\"beta\"", "\"beta\"")); // Testing that latin and Hindi numbers mean exactly the same up to the @@ -170,7 +170,7 @@ TEST(StringSortComparatorTest, TripleComponentComparatorTotal) { assertTrue("\"Hannibal\"@en", "\"HanNibal\"@en"); - // something is not smaller thant itself + // something is not smaller than itself assertFalse("\"beta\"", "\"beta\""); // Testing that latin and Hindi numbers mean exactly the same up to the @@ -205,7 +205,7 @@ TEST(StringSortComparatorTest, SimpleStringComparator) { ASSERT_TRUE(comp("alpha", "ALPHA")); ASSERT_FALSE(comp("ALPHA", "alpha")); - // something is not smaller thant itself + // something is not smaller than itself ASSERT_FALSE(comp("beta", "beta")); ASSERT_TRUE(comp("\"@u2", "@u2")); diff --git a/test/StringUtilsTest.cpp b/test/StringUtilsTest.cpp index 5c4763f926..9a7968994c 100644 --- a/test/StringUtilsTest.cpp +++ b/test/StringUtilsTest.cpp @@ -19,6 +19,7 @@ using ad_utility::constantTimeEquals; using ad_utility::getUTF8Substring; +using ad_utility::strIsLangTag; using ad_utility::utf8ToLower; using ad_utility::utf8ToUpper; @@ -318,6 +319,28 @@ TEST(StringUtilsTest, findLiteralEnd) { using namespace ad_utility; EXPECT_EQ(findLiteralEnd("nothing", "\""), std::string_view::npos); EXPECT_EQ(findLiteralEnd("no\"thing", "\""), 2u); - EXPECT_EQ(findLiteralEnd("no\\\"thi\"ng", "\""), 7u); + EXPECT_EQ(findLiteralEnd("no\\\"thi\"ng", "\""), 7u); // codespell-ignore EXPECT_EQ(findLiteralEnd("no\\\\\"thing", "\""), 4u); } + +TEST(StringUtilsTest, strLangTag) { + // INVALID TAGS + ASSERT_FALSE(strIsLangTag("")); + ASSERT_FALSE(strIsLangTag("de-@")); + ASSERT_FALSE(strIsLangTag("x46")); + ASSERT_FALSE(strIsLangTag("*-DE")); + ASSERT_FALSE(strIsLangTag("en@US")); + ASSERT_FALSE(strIsLangTag("de_US")); + ASSERT_FALSE(strIsLangTag("9046")); + ASSERT_FALSE(strIsLangTag("-fr-BE-")); + ASSERT_FALSE(strIsLangTag("de-366-?")); + + // VALID TAGS + ASSERT_TRUE(strIsLangTag("en")); + ASSERT_TRUE(strIsLangTag("en-US")); + ASSERT_TRUE(strIsLangTag("es-419")); + ASSERT_TRUE(strIsLangTag("zh-Hant-HK")); + ASSERT_TRUE(strIsLangTag("fr-BE-1606nict")); + ASSERT_TRUE(strIsLangTag("de-CH-x-zh")); + ASSERT_TRUE(strIsLangTag("en")); +} diff --git a/test/SynchronizedTest.cpp b/test/SynchronizedTest.cpp index fc5341bcb7..1d1db77d9f 100644 --- a/test/SynchronizedTest.cpp +++ b/test/SynchronizedTest.cpp @@ -249,8 +249,9 @@ TEST(Synchronized, SFINAE) { // Outcommenting this does not compile and cannot be brought to compile // without making usage of the Synchronized classes "withWriteLock" method - // unecessarily hard. static_assert(!AllowsNonConstExclusiveAccessLambda>::value); + // unnecessarily hard. + // static_assert(!AllowsNonConstExclusiveAccessLambda>::value); static_assert(AllowsConstExclusiveAccessLambda< const Synchronized>::value); static_assert(AllowsConstSharedAccessLambda< @@ -269,8 +270,9 @@ TEST(Synchronized, SFINAE) { // Outcommenting this does not compile and cannot be brought to compile // without making usage of the Synchronized classes "withWriteLock" method - // unecessarily hard. static_assert(!AllowsNonConstExclusiveAccessLambda>::value); + // unnecessarily hard. + // static_assert(!AllowsNonConstExclusiveAccessLambda>::value); static_assert(AllowsConstExclusiveAccessLambda< const Synchronized>::value); static_assert(!AllowsConstSharedAccessLambda< diff --git a/test/TransitivePathTest.cpp b/test/TransitivePathTest.cpp index 4e82a65202..651faa9442 100644 --- a/test/TransitivePathTest.cpp +++ b/test/TransitivePathTest.cpp @@ -476,9 +476,9 @@ TEST_P(TransitivePathTest, zeroLengthException) { left, right, 0, std::numeric_limits::max()); AD_EXPECT_THROW_WITH_MESSAGE( T->computeResultOnlyForTesting(), - ::testing::ContainsRegex( - "This query might have to evalute the empty path, which is currently " - "not supported")); + ::testing::ContainsRegex("This query might have to evaluate the empty " + "path, which is currently " + "not supported")); } INSTANTIATE_TEST_SUITE_P(TransitivePathTestSuite, TransitivePathTest, diff --git a/test/ValueIdTest.cpp b/test/ValueIdTest.cpp index becef191dd..341d988e3a 100644 --- a/test/ValueIdTest.cpp +++ b/test/ValueIdTest.cpp @@ -289,20 +289,27 @@ TEST(ValueId, toDebugString) { stream << id; ASSERT_EQ(stream.str(), expected); }; - test(ValueId::makeUndefined(), "Undefined:Undefined"); - test(ValueId::makeFromInt(-42), "Int:-42"); - test(ValueId::makeFromDouble(42.0), "Double:42.000000"); - test(ValueId::makeFromBool(false), "Bool:false"); - test(ValueId::makeFromBool(true), "Bool:true"); - test(makeVocabId(15), "VocabIndex:15"); - StringAligned16 str{"SomeValue"}; - test(ValueId::makeFromLocalVocabIndex(&str), "LocalVocabIndex:SomeValue"); - test(makeTextRecordId(37), "TextRecordIndex:37"); - test(makeWordVocabId(42), "WordVocabIndex:42"); - test(makeBlankNodeId(27), "BlankNodeIndex:27"); + test(ValueId::makeUndefined(), "U:0"); + // Values with type undefined can usually only have one value (all data bits + // zero). Sometimes ValueIds with type undefined but non-zero data bits are + // used. The following test tests one of these internal ValueIds. + ValueId customUndefined = ValueId::fromBits( + ValueId::IntegerType::fromNBit(100) | + (static_cast(Datatype::Undefined) << ValueId::numDataBits)); + test(customUndefined, "U:100"); + test(ValueId::makeFromDouble(42.0), "D:42.000000"); + test(ValueId::makeFromBool(false), "B:false"); + test(ValueId::makeFromBool(true), "B:true"); + test(makeVocabId(15), "V:15"); + auto str = ad_utility::triple_component::LiteralOrIri::literalWithoutQuotes( + "SomeValue"); + test(ValueId::makeFromLocalVocabIndex(&str), "L:\"SomeValue\""); + test(makeTextRecordId(37), "T:37"); + test(makeWordVocabId(42), "W:42"); + test(makeBlankNodeId(27), "B:27"); test(ValueId::makeFromDate( DateOrLargeYear{123456, DateOrLargeYear::Type::Year}), - "Date:123456"); + "D:123456"); // make an ID with an invalid datatype ASSERT_ANY_THROW(test(ValueId::max(), "blim")); } diff --git a/test/ValueIdTestHelpers.h b/test/ValueIdTestHelpers.h index 19aba006a3..5644caefee 100644 --- a/test/ValueIdTestHelpers.h +++ b/test/ValueIdTestHelpers.h @@ -62,7 +62,7 @@ inline uint64_t getVocabIndex(ValueId id) { return id.getVocabIndex().get(); } // TODO Make the tests more precise for the localVocabIndices. inline std::string getLocalVocabIndex(ValueId id) { AD_CORRECTNESS_CHECK(id.getDatatype() == Datatype::LocalVocabIndex); - return *id.getLocalVocabIndex(); + return std::string{asStringViewUnsafe(id.getLocalVocabIndex()->getContent())}; } inline uint64_t getTextRecordIndex(ValueId id) { return id.getTextRecordIndex().get(); diff --git a/test/ValuesForTestingTest.cpp b/test/ValuesForTestingTest.cpp index b47e5d3b38..95ce76ce46 100644 --- a/test/ValuesForTestingTest.cpp +++ b/test/ValuesForTestingTest.cpp @@ -27,8 +27,7 @@ TEST(ValuesForTesting, valuesForTesting) { ASSERT_THAT( v.getCacheKey(), - ::testing::StartsWith( - "Values for testing with 2 columns. VocabIndex:3 VocabIndex:12")); + ::testing::StartsWith("Values for testing with 2 columns. V:3 V:12")); ASSERT_THAT(v.getCacheKey(), ::testing::EndsWith("Supports limit: 0")); ASSERT_EQ(v.getDescriptor(), "explicit values for testing"); ASSERT_TRUE(v.resultSortedOn().empty()); diff --git a/test/ValuesTest.cpp b/test/ValuesTest.cpp index 001eab9116..901f06d332 100644 --- a/test/ValuesTest.cpp +++ b/test/ValuesTest.cpp @@ -9,7 +9,7 @@ #include "./util/IdTableHelpers.h" #include "./util/IdTestHelpers.h" #include "./util/TripleComponentTestHelpers.h" -#include "engine/ResultTable.h" +#include "engine/Result.h" #include "engine/Values.h" #include "engine/idTable/IdTable.h" #include "util/IndexTestHelpers.h" @@ -74,7 +74,8 @@ TEST(Values, computeResult) { const auto& table = result->idTable(); Id x = ad_utility::testing::makeGetId(testQec->getIndex())(""); auto I = ad_utility::testing::IntId; - auto l = result->localVocab().getIndexOrNullopt(""); + auto l = result->localVocab().getIndexOrNullopt( + ad_utility::triple_component::LiteralOrIri::iriref("")); ASSERT_TRUE(l.has_value()); auto U = Id::makeUndefined(); ASSERT_EQ(table, diff --git a/test/VocabularyGeneratorTest.cpp b/test/VocabularyGeneratorTest.cpp index 35b357ba07..d44f156f18 100644 --- a/test/VocabularyGeneratorTest.cpp +++ b/test/VocabularyGeneratorTest.cpp @@ -34,7 +34,7 @@ bool vocabTestCompare(const IdPairMMapVecView& a, auto V = ad_utility::testing::VocabId; } // namespace -// Test fixture that sets up the binary files vor partial vocabulary and +// Test fixture that sets up the binary files for partial vocabulary and // everything else connected with vocabulary merging. class MergeVocabularyTest : public ::testing::Test { protected: @@ -71,7 +71,7 @@ class MergeVocabularyTest : public ::testing::Test { "lead to test failures\n"; } - // make paths abolute under created tmp directory + // make paths absolute under created tmp directory _path0 = _basePath + _path0; _path1 = _basePath + _path1; _pathVocabExp = _basePath + std::string(".vocabExp"); diff --git a/test/VocabularyTestHelpers.h b/test/VocabularyTestHelpers.h index 6a46b67229..33c17fd50f 100644 --- a/test/VocabularyTestHelpers.h +++ b/test/VocabularyTestHelpers.h @@ -102,8 +102,8 @@ void testUpperAndLowerBoundContiguousIDs(const auto& vocab, auto makeWordLarger, words, ids); } -// Same as the previous function, but explictly state, which IDs are expected in -// the vocabulary. +// Same as the previous function, but explicitly state, which IDs are expected +// in the vocabulary. void testUpperAndLowerBoundWithStdLessFromWordsAndIds(auto vocabulary, const auto& words, const auto& ids) { @@ -183,7 +183,7 @@ void testUpperAndLowerBoundWithNumericComparator(auto createVocabulary) { // Checks that vocabulary[ids[i]] == words[i]. auto testAccessOperatorFromWordsAndIds(auto vocabulary, const auto& words, const auto& ids) { - // Not in any particulary order. + // Not in any particularly order. AD_CONTRACT_CHECK(words.size() == ids.size()); ASSERT_EQ(words.size(), vocabulary.size()); for (size_t i = 0; i < words.size(); ++i) { @@ -193,7 +193,7 @@ auto testAccessOperatorFromWordsAndIds(auto vocabulary, const auto& words, // Check that the `operator[]` works as expected for an unordered vocabulary, // created via `createVocabulary(std::vector)`. auto testAccessOperatorForUnorderedVocabulary(auto createVocabulary) { - // Not in any particulary order. + // Not in any particularly order. const std::vector words{"alpha", "delta", "ALPHA", "beta", "42", "31", "0a", "a0", "al"}; std::vector ids; diff --git a/test/engine/CartesianProductJoinTest.cpp b/test/engine/CartesianProductJoinTest.cpp index 33eebf82c3..f07bb11218 100644 --- a/test/engine/CartesianProductJoinTest.cpp +++ b/test/engine/CartesianProductJoinTest.cpp @@ -1,4 +1,4 @@ -// Copyright 2023, University of Freiburg, +// Copyright 2024, University of Freiburg, // Chair of Algorithms and Data Structures. // Author: Johannes Kalmbach @@ -17,13 +17,14 @@ using ad_utility::source_location; // Create a `CartesianProductJoin` the children of which are `ValuesForTesting` // with results create from the `inputs`. The children will have disjoint sets -// of variabled as required by the `CartesianProductJoin`. If +// of variable as required by the `CartesianProductJoin`. If // `useLimitInSuboperations` is true, then the `ValuesForTesting` support the // LIMIT operation directly (this makes a difference in the `computeResult` // method of `CartesianProductJoin`). CartesianProductJoin makeJoin(const std::vector& inputs, bool useLimitInSuboperations = false) { - auto qec = ad_utility::testing::getQec(); + auto qec = + ad_utility::testing::getQec(" "); std::vector> valueOperations; size_t i = 0; auto v = [&i]() mutable { return Variable{"?" + std::to_string(i++)}; }; @@ -114,7 +115,7 @@ TEST(CartesianProductJoin, computeResult) { {1, 3, 5}}, {{{0}, {1}}, {{2}, {3}}, {{4}, {5}}}); - // Heterogenous sizes. + // Heterogeneous sizes. testCartesianProduct( {{0, 2, 4}, {1, 2, 4}, {0, 2, 5}, {1, 2, 5}, {0, 2, 6}, {1, 2, 6}}, {{{0}, {1}}, {{2}}, {{4}, {5}, {6}}}); @@ -136,6 +137,30 @@ TEST(CartesianProductJoin, computeResult) { {{{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}}, {{0}}}); } +// Test the throwing of the custom out of memory exception inside the +// cartesian product join. +TEST(CartesianProductJoin, outOfMemoryException) { + std::vector tables; + VectorTable largeTable; + largeTable.emplace_back(); + for (size_t i = 0; i < 10; ++i) { + largeTable.back().push_back(0); + } + for (size_t i = 0; i < 10; ++i) { + tables.push_back(largeTable); + } + auto largeJoin = makeJoin(tables); + auto allocator = largeJoin.getExecutionContext()->getAllocator(); + // Manually deplete the allocator. + auto left = allocator.amountMemoryLeft().getBytes() / sizeof(Id); + auto ptr = allocator.allocate(left); + AD_EXPECT_THROW_WITH_MESSAGE(largeJoin.computeResultOnlyForTesting(), + ::testing::HasSubstr("cross-product")); + // Avoid memory leaks and failures of unit tests that reuse the (static) + // allocator. + allocator.deallocate(ptr, left); +} + // ______________________________________________________________ TEST(CartesianProductJoin, basicMemberFunctions) { auto join = makeJoin({{{3, 5}, {7, 9}}, {{4}, {5}, {2}}}); diff --git a/test/engine/TextIndexScanForEntityTest.cpp b/test/engine/TextIndexScanForEntityTest.cpp index c88bc64053..f2e8bcd611 100644 --- a/test/engine/TextIndexScanForEntityTest.cpp +++ b/test/engine/TextIndexScanForEntityTest.cpp @@ -32,8 +32,8 @@ TEST(TextIndexScanForEntity, EntityScanBasic) { ASSERT_EQ(s1.getResultWidth(), 3); auto result = s1.computeResultOnlyForTesting(); - ASSERT_EQ(result.width(), 3); - ASSERT_EQ(result.size(), 3); + ASSERT_EQ(result.idTable().numColumns(), 3); + ASSERT_EQ(result.idTable().size(), 3); // NOTE: because of the way the graph above is constructed, the entities are // texts @@ -61,8 +61,8 @@ TEST(TextIndexScanForEntity, FixedEntityScan) { auto result = s3.computeResultOnlyForTesting(); ASSERT_EQ(s3.getResultWidth(), 2); - ASSERT_EQ(result.width(), 2); - ASSERT_EQ(result.size(), 1); + ASSERT_EQ(result.idTable().numColumns(), 2); + ASSERT_EQ(result.idTable().size(), 1); using enum ColumnIndexAndTypeInfo::UndefStatus; VariableToColumnMap expectedVariables = { @@ -78,8 +78,8 @@ TEST(TextIndexScanForEntity, FixedEntityScan) { fixedEntity = "\"he failed the test\""; TextIndexScanForEntity s4{qec, Variable{"?text4"}, fixedEntity, "test*"}; result = s4.computeResultOnlyForTesting(); - ASSERT_EQ(result.width(), 2); - ASSERT_EQ(result.size(), 1); + ASSERT_EQ(result.idTable().numColumns(), 2); + ASSERT_EQ(result.idTable().size(), 1); ASSERT_EQ(fixedEntity, h::getTextRecordFromResultTable(qec, result, 0)); } @@ -124,7 +124,7 @@ TEST(TextIndexScanForEntity, CacheKeys) { TextIndexScanForEntity s8{qec, Variable{"?text7"}, newFixedEntity, "sentences"}; - // Same text var, same fixed entitiy, different words + // Same text var, same fixed entity, different words ASSERT_NE(s7.getCacheKeyImpl(), s8.getCacheKeyImpl()); } diff --git a/test/engine/TextIndexScanForWordTest.cpp b/test/engine/TextIndexScanForWordTest.cpp index 60806fc73a..57f4b46e02 100644 --- a/test/engine/TextIndexScanForWordTest.cpp +++ b/test/engine/TextIndexScanForWordTest.cpp @@ -32,8 +32,8 @@ TEST(TextIndexScanForWord, WordScanPrefix) { ASSERT_EQ(s1.getResultWidth(), 2); auto result = s1.computeResultOnlyForTesting(); - ASSERT_EQ(result.width(), 2); - ASSERT_EQ(result.size(), 3); + ASSERT_EQ(result.idTable().numColumns(), 2); + ASSERT_EQ(result.idTable().size(), 3); s2.getExternallyVisibleVariableColumns(); using enum ColumnIndexAndTypeInfo::UndefStatus; @@ -63,8 +63,8 @@ TEST(TextIndexScanForWord, WordScanBasic) { ASSERT_EQ(s1.getResultWidth(), 1); auto result = s1.computeResultOnlyForTesting(); - ASSERT_EQ(result.width(), 1); - ASSERT_EQ(result.size(), 2); + ASSERT_EQ(result.idTable().numColumns(), 1); + ASSERT_EQ(result.idTable().size(), 2); ASSERT_EQ("\"he failed the test\"", h::getTextRecordFromResultTable(qec, result, 0)); @@ -76,8 +76,8 @@ TEST(TextIndexScanForWord, WordScanBasic) { ASSERT_EQ(s2.getResultWidth(), 1); result = s2.computeResultOnlyForTesting(); - ASSERT_EQ(result.width(), 1); - ASSERT_EQ(result.size(), 1); + ASSERT_EQ(result.idTable().numColumns(), 1); + ASSERT_EQ(result.idTable().size(), 1); ASSERT_EQ("\"testing can help\"", h::getTextRecordFromResultTable(qec, result, 0)); diff --git a/test/engine/TextIndexScanTestHelpers.h b/test/engine/TextIndexScanTestHelpers.h index 25ff7f3aaf..ddfa1aa5df 100644 --- a/test/engine/TextIndexScanTestHelpers.h +++ b/test/engine/TextIndexScanTestHelpers.h @@ -9,7 +9,7 @@ namespace textIndexScanTestHelpers { // obtain the textRecord using idToOptionalString. // TODO: Implement a more elegant/stable version inline string getTextRecordFromResultTable(const QueryExecutionContext* qec, - const ResultTable& result, + const Result& result, const size_t& rowIndex) { return qec->getIndex() .idToOptionalString( @@ -18,7 +18,7 @@ inline string getTextRecordFromResultTable(const QueryExecutionContext* qec, } inline string getEntityFromResultTable(const QueryExecutionContext* qec, - const ResultTable& result, + const Result& result, const size_t& rowIndex) { return qec->getIndex() .idToOptionalString( @@ -27,7 +27,7 @@ inline string getEntityFromResultTable(const QueryExecutionContext* qec, } inline string getWordFromResultTable(const QueryExecutionContext* qec, - const ResultTable& result, + const Result& result, const size_t& rowIndex) { return qec->getIndex() .idToOptionalString( diff --git a/test/engine/ValuesForTesting.h b/test/engine/ValuesForTesting.h index 2c91fc1edc..a0f7e09e30 100644 --- a/test/engine/ValuesForTesting.h +++ b/test/engine/ValuesForTesting.h @@ -6,7 +6,7 @@ #include "engine/Operation.h" #include "engine/QueryExecutionContext.h" -#include "engine/ResultTable.h" +#include "engine/Result.h" #include "util/Algorithm.h" #include "util/Random.h" @@ -49,7 +49,7 @@ class ValuesForTesting : public Operation { size_t& costEstimate() { return costEstimate_; } // ___________________________________________________________________________ - ResultTable computeResult() override { + Result computeResult([[maybe_unused]] bool requestLaziness) override { auto table = table_.clone(); if (supportsLimit_) { table.erase(table.begin() + getLimit().upperBound(table.size()), diff --git a/test/util/AllocatorTestHelpers.h b/test/util/AllocatorTestHelpers.h index 1599ba9f9d..7e0a9314ec 100644 --- a/test/util/AllocatorTestHelpers.h +++ b/test/util/AllocatorTestHelpers.h @@ -10,9 +10,10 @@ namespace ad_utility::testing { // Create an unlimited allocator. -inline ad_utility::AllocatorWithLimit& makeAllocator() { - static ad_utility::AllocatorWithLimit a{ - ad_utility::makeAllocationMemoryLeftThreadsafeObject(MemorySize::max())}; +inline ad_utility::AllocatorWithLimit makeAllocator( + MemorySize memorySize = MemorySize::max()) { + ad_utility::AllocatorWithLimit a{ + ad_utility::makeAllocationMemoryLeftThreadsafeObject(memorySize)}; return a; } } // namespace ad_utility::testing diff --git a/test/util/AsyncTestHelpers.h b/test/util/AsyncTestHelpers.h index 6a02c449b7..b94daef0e9 100644 --- a/test/util/AsyncTestHelpers.h +++ b/test/util/AsyncTestHelpers.h @@ -93,7 +93,7 @@ void runAsyncTest(Func innerRun, size_t numThreads) { // Drop-in replacement for gtest's TEST() macro, but for tests that make // use of boost asio's awaitable coroutines. Note that this prevents you -// from using ASSERT_* macros unless you redefine the return keword with +// from using ASSERT_* macros unless you redefine the return keyword with // co_return so it works nicely with the coroutine. #define ASYNC_TEST(test_suite_name, test_name) \ ASYNC_TEST_N(test_suite_name, test_name, 1) diff --git a/test/util/CMakeLists.txt b/test/util/CMakeLists.txt index 65352c0ba6..62ed2007dd 100644 --- a/test/util/CMakeLists.txt +++ b/test/util/CMakeLists.txt @@ -1,3 +1,3 @@ add_library(testUtil IdTableHelpers.cpp ValidatorHelpers.cpp RandomTestHelpers.cpp BenchmarkMeasurementContainerHelpers.cpp IndexTestHelpers.cpp) # TODO Once there is more support for it, we should be able to do this cheaper with modules. -qlever_target_link_libraries(testUtil engine) +qlever_target_link_libraries(testUtil engine gmock_main) diff --git a/test/util/IdTableHelpers.cpp b/test/util/IdTableHelpers.cpp index bdb0c3a865..d643476256 100644 --- a/test/util/IdTableHelpers.cpp +++ b/test/util/IdTableHelpers.cpp @@ -1,6 +1,6 @@ // Copyright 2023, University of Freiburg, // Chair of Algorithms and Data Structures. -// Author: Andre Schlegel (Januar of 2023, schlegea@informatik.uni-freiburg.de) +// Author: Andre Schlegel (January of 2023, schlegea@informatik.uni-freiburg.de) #include "../test/util/IdTableHelpers.h" @@ -42,7 +42,7 @@ void compareIdTableWithExpectedContent( auto trace{generateLocationTrace(l, traceMessage.str())}; // Because we compare tables later by sorting them, so that every table has - // one definit form, we need to create local copies. + // one definite form, we need to create local copies. IdTable localTable{table.clone()}; IdTable localExpectedContent{expectedContent.clone()}; @@ -59,6 +59,12 @@ void compareIdTableWithExpectedContent( ASSERT_EQ(localTable, localExpectedContent); } +// ____________________________________________________________________________ +void sortIdTableByJoinColumnInPlace(IdTableAndJoinColumn& table) { + CALL_FIXED_SIZE((std::array{table.idTable.numColumns()}), &Engine::sort, + &table.idTable, table.joinColumn); +} + // ____________________________________________________________________________ IdTable generateIdTable( const size_t numberRows, const size_t numberColumns, @@ -125,7 +131,7 @@ IdTable createRandomlyFilledIdTable( return ad_utility::testing::VocabId(randomNumberGenerator()); }; - // Assiging the column number to a generator function. + // Assigning the column number to a generator function. std::vector*> columnToGenerator( numberColumns, &normalEntryGenerator); std::ranges::for_each(joinColumnWithGenerator, diff --git a/test/util/IdTableHelpers.h b/test/util/IdTableHelpers.h index 75d34bad0a..a7ca2a4279 100644 --- a/test/util/IdTableHelpers.h +++ b/test/util/IdTableHelpers.h @@ -1,6 +1,6 @@ // Copyright 2023, University of Freiburg, // Chair of Algorithms and Data Structures. -// Author: Andre Schlegel (Januar of 2023, schlegea@informatik.uni-freiburg.de) +// Author: Andre Schlegel (January of 2023, schlegea@informatik.uni-freiburg.de) #pragma once @@ -84,7 +84,7 @@ IdTable makeIdTableFromVector(const VectorTable& content, /* * @brief Tests, whether the given IdTable has the same content as the sample - * solution and, if the option was choosen, if the IdTable is sorted by + * solution and, if the option was chosen, if the IdTable is sorted by * the join column. * * @param table The IdTable that should be tested. @@ -102,6 +102,12 @@ void compareIdTableWithExpectedContent( const size_t joinColumn = 0, ad_utility::source_location l = ad_utility::source_location::current()); +/* + * @brief Sorts an IdTable in place, in the same way, that we sort them during + * normal program usage. + */ +void sortIdTableByJoinColumnInPlace(IdTableAndJoinColumn& table); + /* @brief Creates a `IdTable`, where the rows are created via generator. @@ -199,7 +205,7 @@ IdTable createRandomlyFilledIdTable( ad_utility::FastRandomIntGenerator{}())); /* -@brief Return a IdTable, that is completly randomly filled. +@brief Return a IdTable, that is completely randomly filled. @param numberRows, numberColumns The size of the IdTable, that is to be returned. diff --git a/test/util/IdTestHelpers.h b/test/util/IdTestHelpers.h index df6287af19..be88e56709 100644 --- a/test/util/IdTestHelpers.h +++ b/test/util/IdTestHelpers.h @@ -22,8 +22,10 @@ inline auto VocabId = [](const auto& v) { inline auto LocalVocabId = [](std::integral auto v) { static ad_utility::Synchronized localVocab; + using namespace ad_utility::triple_component; return Id::makeFromLocalVocabIndex( - localVocab.wlock()->getIndexAndAddIfNotContained(std::to_string(v))); + localVocab.wlock()->getIndexAndAddIfNotContained( + LiteralOrIri::literalWithoutQuotes(std::to_string(v)))); }; inline auto TextRecordId = [](const auto& t) { diff --git a/test/util/IndexTestHelpers.cpp b/test/util/IndexTestHelpers.cpp index 83d216a6bc..4128af6612 100644 --- a/test/util/IndexTestHelpers.cpp +++ b/test/util/IndexTestHelpers.cpp @@ -229,7 +229,8 @@ QueryExecutionContext* getQec(std::optional turtleInput, std::unique_ptr cache_; std::unique_ptr qec_ = std::make_unique( - *index_, cache_.get(), makeAllocator(), SortPerformanceEstimator{}); + *index_, cache_.get(), makeAllocator(MemorySize::megabytes(100)), + SortPerformanceEstimator{}); }; using Key = std::tuple, bool, bool, bool, diff --git a/test/util/JoinHelpers.h b/test/util/JoinHelpers.h index d835563fbe..2034cf03a0 100644 --- a/test/util/JoinHelpers.h +++ b/test/util/JoinHelpers.h @@ -42,7 +42,7 @@ IdTable useJoinFunctionOnIdTables(const IdTableAndJoinColumn& tableA, // You need to use this special function for executing lambdas. The normal // function for functions won't work. - // Additionaly, we need to cast the two size_t, because callFixedSize only + // Additionally, we need to cast the two size_t, because callFixedSize only // takes arrays of int. ad_utility::callFixedSize( (std::array{static_cast(tableA.idTable.numColumns()), diff --git a/test/util/OperationTestHelpers.h b/test/util/OperationTestHelpers.h index 8764aab4b7..a3f7183230 100644 --- a/test/util/OperationTestHelpers.h +++ b/test/util/OperationTestHelpers.h @@ -31,7 +31,7 @@ class StallForeverOperation : public Operation { using Operation::Operation; // Do-nothing operation that runs for 100ms without computing anything, but // which can be cancelled. - ResultTable computeResult() override { + Result computeResult([[maybe_unused]] bool requestLaziness) override { auto end = std::chrono::steady_clock::now() + 100ms; while (std::chrono::steady_clock::now() < end) { checkCancellation(); @@ -73,7 +73,7 @@ class ShallowParentOperation : public Operation { return {child_.get()}; } - ResultTable computeResult() override { + Result computeResult([[maybe_unused]] bool requestLaziness) override { auto childResult = child_->getResult(); return {childResult->idTable().clone(), resultSortedOn(), childResult->getSharedLocalVocab()}; diff --git a/test/util/ValidatorHelpers.h b/test/util/ValidatorHelpers.h index 94fd83561a..f5827c9bfa 100644 --- a/test/util/ValidatorHelpers.h +++ b/test/util/ValidatorHelpers.h @@ -52,7 +52,7 @@ auto generateDummyNonExceptionValidatorFunction(size_t variant) { return [... dummyValuesToCompareTo = createDummyValueForValidator(variant)]( const ParameterTypes&... args) { - // Special handeling for `args` of type bool is needed. For the reasoning: + // Special handling for `args` of type bool is needed. For the reasoning: // See the doc string. auto compare = [](const T& arg, const T& dummyValueToCompareTo) { diff --git a/toolchains/clang18.cmake b/toolchains/clang18.cmake index 960b30ade8..3a6e2e734b 100644 --- a/toolchains/clang18.cmake +++ b/toolchains/clang18.cmake @@ -1,3 +1,5 @@ # CMake toolchain file for using `clang++-18` set(CMAKE_C_COMPILER clang-18) set(CMAKE_CXX_COMPILER clang++-18) +# See https://github.com/llvm/llvm-project/issues/76515 +set(CMAKE_CXX_FLAGS "-Wno-deprecated-declarations")