diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..381442a4 --- /dev/null +++ b/.clang-format @@ -0,0 +1,119 @@ +--- +Language: Cpp +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: true +AlignEscapedNewlines: Right +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 0 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^(<|"(gtest|isl|json)/)' + Priority: 1 + - Regex: '.*' + Priority: 2 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '$' +IndentCaseLabels: false +IndentPPDirectives: None +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 100 +PointerAlignment: Right +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: true +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 2 +UseTab: Never +... diff --git a/.github/dependency_bot.yml b/.github/dependency_bot.yml new file mode 100644 index 00000000..5e2b228a --- /dev/null +++ b/.github/dependency_bot.yml @@ -0,0 +1,9 @@ +# Update Github action dependencies regularly + +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + # Check for updates to GitHub Actions every week + interval: "weekly" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..0ad40624 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,10 @@ +## Main changes of this PR + +## Author's checklist + +* [ ] I used the [`pre-commit` hook](https://precice.org/dev-docs-dev-tooling.html#setting-up-pre-commit) and used `pre-commit run --all` to apply all available hooks. +* [ ] I added a test to cover the proposed changes in our test suite. +* [ ] I updated the documentation in `docs/README.md`. +* [ ] I updated potential breaking changes in the tutorial [`precice/tutorials/aste-turbine`](https://github.com/precice/tutorials/tree/develop/aste-turbine). + + diff --git a/.github/workflows/aste_ci.yml b/.github/workflows/aste_ci.yml new file mode 100644 index 00000000..3e6dfb14 --- /dev/null +++ b/.github/workflows/aste_ci.yml @@ -0,0 +1,63 @@ +name: ASTE CI + +on: + push: + branches: [master, develop] + pull_request: + branches: [master, develop] + +concurrency: + group: ${ {github.event_name }}-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{github.event_name == 'pull_request'}} + +jobs: + build: + runs-on: ubuntu-latest + timeout-minutes: 30 + env: + CXX_FLAGS: "-Werror -Wall -Wextra -Wno-unused-parameter" + CTEST_OUTPUT_ON_FAILURE: "Yes" + steps: + - uses: actions/checkout@v2 + - name: install preCICE + run: | + wget https://github.com/precice/precice/releases/download/v2.5.0/libprecice2_2.5.0_focal.deb && \ + sudo apt-get -y update && \ + sudo apt-get -y install ./libprecice2_2.5.0_focal.deb + - name: install VTK + run: | + sudo apt-get -y install libvtk7-dev + - name: install example dependencies + run: | + python3 -m pip install sympy scipy jinja2 + - name: prepare directories + run: | + mkdir build_gcc build_clang + - name: build aste gcc + working-directory: build_gcc + env: + CC: gcc + CXX: g++ + run: | + cmake .. + cmake --build . + - name: run test gcc + working-directory: build_gcc + run: | + ctest + - name: install clang + run: | + sudo apt-get -y install clang + - name: build aste clang + working-directory: build_clang + env: + CC: clang + CXX: clang++ + run: | + cmake .. + cmake --build . + sudo cmake --install . + - name: run test clang + working-directory: build_clang + run: | + ctest diff --git a/.github/workflows/code_style.yml b/.github/workflows/code_style.yml new file mode 100644 index 00000000..86d489a1 --- /dev/null +++ b/.github/workflows/code_style.yml @@ -0,0 +1,27 @@ +name: Code Style +on: + pull_request: + paths: + - "**.[ch]pp" + - "**.[ch]" + - "**.xml" + - "**.py" + +jobs: + formatting: + runs-on: ubuntu-latest + steps: + - name: Checkout preCICE + uses: actions/checkout@v3 + - name: Setup python + uses: actions/setup-python@v3 + - name: Install pre-commit + run: pip install pre-commit + - name: Run checks + run: pre-commit run -a -v + - name: Git status + if: always() + run: git status + - name: Full diff + if: always() + run: git diff diff --git a/.github/workflows/link_check.yml b/.github/workflows/link_check.yml new file mode 100644 index 00000000..6e4ac5d8 --- /dev/null +++ b/.github/workflows/link_check.yml @@ -0,0 +1,14 @@ +name: Check links (manual) +on: workflow_dispatch +jobs: + check_links: + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v2 + - name: Check links in markdown files (markdown-link-check) + uses: gaurav-nelson/github-action-markdown-link-check@v1 + with: + use-quiet-mode: "yes" + use-verbose-mode: "no" + config-file: ".markdown-link-check-config.json" diff --git a/.github/workflows/lint_markdown.yml b/.github/workflows/lint_markdown.yml new file mode 100644 index 00000000..fb04c76f --- /dev/null +++ b/.github/workflows/lint_markdown.yml @@ -0,0 +1,20 @@ +name: Lint docs + +on: + push: + branches: [master, develop] + pull_request: + branches: [master, develop] + +jobs: + check_md: + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v2 + - name: Lint markdown files (markdownlint) + uses: articulate/actions-markdownlint@v1 + with: + config: .markdownlint.json + files: "." + ignore: changelog-entries diff --git a/.github/workflows/update_website.yml b/.github/workflows/update_website.yml new file mode 100644 index 00000000..ecedf412 --- /dev/null +++ b/.github/workflows/update_website.yml @@ -0,0 +1,22 @@ +name: Update website +on: + push: + branches: + - "develop" + paths: + - "docs/**" +jobs: + trigger: + runs-on: ubuntu-latest + env: + WORKFLOW_FILENAME: update-submodules.yml + steps: + - name: Trigger workflow + run: | + curl \ + --request POST \ + --url https://api.github.com/repos/precice/precice.github.io/actions/workflows/$WORKFLOW_FILENAME/dispatches \ + --header "authorization: token ${{ secrets.WORKFLOW_DISPATCH_TOKEN }}" \ + --header "Accept: application/vnd.github.v3+json" \ + --data '{"ref":"master"}' \ + --fail diff --git a/.gitignore b/.gitignore index 5dc1aacf..789a2564 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,6 @@ *.o a.out rank_* -iterations-* -convergence-* CMakeCache.txt CMakeFiles/ cmake_install.cmake @@ -27,3 +25,9 @@ testMesh.txt *.synctex.gz compile_commands.json build/ +.vscode/* +examples/replay_mode/precice-Fluid-events-summary.log +examples/replay_mode/precice-Fluid-events.json +examples/replay_mode/precice-Solid-events-summary.log +examples/replay_mode/precice-Solid-events.json +examples/replay_mode/precice-Solid-watchpoint-Flap-Tip.log diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 00000000..e1206708 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,4 @@ +{ + "MD013": false, + "MD033": false +} diff --git a/.pep8 b/.pep8 new file mode 100644 index 00000000..998b0179 --- /dev/null +++ b/.pep8 @@ -0,0 +1,6 @@ +[pycodestyle] +max_line_length = 120 +ignore = E402 +in-place = true +aggressive = 2 +recursive = true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..0b235c11 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,36 @@ +repos: + # Official repo for the clang-format hook + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: "v14.0.6" + hooks: + - id: clang-format + exclude: "^thirdparty" + types_or: [c++, c] + # isort for python imports + - repo: https://github.com/pycqa/isort + rev: 5.10.1 + hooks: + - id: isort + name: isort (python) + # black repo for python formatting + - repo: https://github.com/ambv/black + rev: 22.6.0 + hooks: + - id: black + # Official repo for default hooks + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: "v4.3.0" + hooks: + - id: check-xml + exclude: "tools" + - id: check-merge-conflict + - id: mixed-line-ending + - id: trailing-whitespace + - id: end-of-file-fixer + - id: requirements-txt-fixer + # Custom repo for the preCICE configuration formatter + - repo: https://github.com/precice/precice-pre-commit-hooks + rev: "v2.1" + hooks: + - id: format-precice-config + exclude: "tools" diff --git a/CMakeLists.txt b/CMakeLists.txt index 8554f8a1..f969e0c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,10 +2,11 @@ cmake_minimum_required (VERSION 3.1) project(ASTE) +list (APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") -list (APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake-modules") - -set (CMAKE_CXX_STANDARD 11) +set (CMAKE_CXX_STANDARD 14) +set (CMAKE_CXX_STANDARD_REQUIRED YES) +set (CMAKE_CXX_EXTENSIONS NO) if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build." FORCE) @@ -15,41 +16,104 @@ if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) endif() message(STATUS "Build configuration: " ${CMAKE_BUILD_TYPE}) +option(ASTE_SET_MESH_BLOCK "Use block versions to set mesh primitives." ON) + find_package (Threads REQUIRED) find_package(precice REQUIRED CONFIG) -find_package(Boost 1.65.1 REQUIRED COMPONENTS system program_options filesystem) +find_package(Boost 1.65.1 REQUIRED COMPONENTS log log_setup system program_options filesystem unit_test_framework) + +option(ASTE_USE_VTK_COMPONENTS "Find VTK with components" OFF) +if(ASTE_USE_VTK_COMPONENTS) + # This is broken on ubuntu 20.04 + find_package(VTK REQUIRED COMPONENTS CommonCore CommonDataModel IOXML IOLegacy) +else() + # This is broken on arch + find_package(VTK REQUIRED) +endif() +message (STATUS "VTK_VERSION: ${VTK_VERSION}") find_package(METIS) if (METIS_FOUND) add_library(metisAPI SHARED src/metisAPI.cpp) + include_directories(${METIS_INCLUDE_DIRS}) target_link_libraries(metisAPI ${METIS_LIBRARIES}) + target_include_directories(metisAPI PRIVATE ${METIS_INCLUDE_DIR}) endif() find_package(MPI REQUIRED) -add_executable(preciceMap src/preciceMap.cpp src/common.cpp src/easylogging++.cc) -target_include_directories(preciceMap PRIVATE src) -target_link_libraries(preciceMap +add_executable(precice-aste-run src/precice-aste-run.cpp src/common.cpp src/mesh.cpp src/configreader.cpp src/modes.cpp src/utilities.cpp src/logger.cpp) +target_include_directories(precice-aste-run PRIVATE src thirdparty) +target_link_libraries(precice-aste-run precice::precice Threads::Threads - Boost::boost - Boost::filesystem - Boost::program_options - Boost::system MPI::MPI_CXX + ${Boost_LIBRARIES} + ${VTK_LIBRARIES} +) + +if(ASTE_SET_MESH_BLOCK) + target_compile_definitions(precice-aste-run PRIVATE ASTE_SET_MESH_BLOCK) +endif() + +if(METIS_FOUND) + target_link_libraries(precice-aste-run metisAPI) +endif() + + +add_executable(testing tests/testing.cpp tests/read_test.cpp tests/write_test.cpp src/mesh.cpp src/logger.cpp) +target_include_directories(testing PRIVATE src thirdparty) +target_link_libraries(testing + ${Boost_LIBRARIES} + MPI::MPI_CXX + ${VTK_LIBRARIES} ) +if (VTK_VERSION VERSION_LESS "8.90.0") + # old system + include(${VTK_USE_FILE}) +else () + # vtk_module_autoinit is needed + vtk_module_autoinit( + TARGETS precice-aste-run testing + MODULES ${VTK_LIBRARIES} + ) +endif() + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/precice-aste-partition DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/precice-aste-join DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/precice-aste-evaluate DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + +include(GNUInstallDirs) +install(TARGETS precice-aste-run DESTINATION ${CMAKE_INSTALL_BINDIR}) if(METIS_FOUND) - target_link_libraries(preciceMap metisAPI) +install(TARGETS metisAPI DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif() +install(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/src/precice-aste-partition ${CMAKE_CURRENT_SOURCE_DIR}/src/precice-aste-join ${CMAKE_CURRENT_SOURCE_DIR}/src/precice-aste-evaluate DESTINATION ${CMAKE_INSTALL_BINDIR}) + +enable_testing() + +add_test(NAME read_write_test COMMAND testing WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/tests") + +# Detect and register examples as tests + +set(_examples lci_2d lci_3d nn nng_scalar nng_vector mapping_tester replay_mode) + +foreach(example IN LISTS _examples) + add_test(NAME aste.example.${example}.setup + COMMAND clean.sh + FIXTURE_SETUP ${example}) + + add_test(NAME aste.example.${example} + COMMAND run.sh + FIXTURE_REQUIRES ${example}) -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/make_mesh.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/visualize_partition.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/partition_mesh.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/join_mesh.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/eval_mesh.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/vtk_calculator.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/mesh_io.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/mesh.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + set_tests_properties(aste.example.${example} aste.example.${example}.setup + PROPERTIES + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/examples/${example}" + ENVIRONMENT "PATH=$ENV{PATH}:${CMAKE_BINARY_DIR}" + LABELS example + RUN_SERIAL ON) +endforeach() diff --git a/LICENSE b/LICENSE index 733c0723..9cecc1d4 100644 --- a/LICENSE +++ b/LICENSE @@ -672,4 +672,3 @@ may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . - diff --git a/Preallocation_Timings/make_csv.py b/Preallocation_Timings/make_csv.py deleted file mode 100755 index 67def5bc..00000000 --- a/Preallocation_Timings/make_csv.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python3 - -import argparse, itertools, pandas as pd -from ipdb import set_trace -import numpy as np - - -parser = argparse.ArgumentParser() -parser.add_argument('--files', help = "File names of log file", nargs = "+") -args = parser.parse_args() - - -def drop_and_mean(x): - return x.mask((x.index == x.idxmax()) | (x.index == x.idxmin())).mean() - - - -# Fields in a row -fields = { "initialize/map.pet.fillA.FromMeshAToMeshB" : "fillA", - "initialize/map.pet.fillC.FromMeshAToMeshB" : "fillC", - "initialize/map.pet.preallocA.FromMeshAToMeshB" : "preallocA", - "initialize/map.pet.preallocC.FromMeshAToMeshB" : "preallocC" } - -dfs = [pd.read_csv(f, parse_dates = [0], comment = "#") for f in args.files] -df = pd.concat(dfs) -df = df.reset_index() -df = df[df.Rank == 0] - -df = df.groupby(["RunName", "Name"], as_index = False).aggregate(drop_and_mean) - -df = df.pivot(index = "RunName", columns = "Name", values = "Total") - -df = df.rename(columns = fields) - -df.to_csv("data.csv", index_label = "Type", columns = fields.values()) - diff --git a/Preallocation_Timings/plot.tex b/Preallocation_Timings/plot.tex deleted file mode 100644 index 2ca1861f..00000000 --- a/Preallocation_Timings/plot.tex +++ /dev/null @@ -1,49 +0,0 @@ -\documentclass{scrartcl} - -\usepackage{pgfplots} -\usetikzlibrary{pgfplots.groupplots} -\pgfplotsset{ - compat=1.16, - table/col sep=comma} - -\usetikzlibrary{pgfplots.groupplots} - -\begin{document} - -\begin{figure}[h] - \centering - \ref{legend} - \begin{tikzpicture} - \begin{groupplot}[ - group style={columns=2, y descriptions at=edge left}, - ybar stacked, - symbolic x coords={off, computed, saved, tree}, - xtick=data, - xticklabels={No preallocation, Explicitly computed, Computed and saved, Using of spatial tree}, - /pgf/bar width=1cm, - ylabel={Time [ms]}, - x tick label style={rotate=45}, - ymax=50000, - legend entries={Filling evaluation, Preallocation evaluation, Filling interpolation, Preallocation interpolation}, - legend to name=legend, legend columns=2] - - \nextgroupplot - \addplot+ table[y=fillA]{data-80.csv}; - \addplot+ table[y=preallocA]{data-80.csv}; - \addplot+ table[y=fillC]{data-80.csv}; - \addplot+ table[y=preallocC]{data-80.csv}; - - - \nextgroupplot - \addplot+ table[y=fillA]{data-100.csv}; - \addplot+ table[y=preallocA]{data-100.csv}; - \addplot+ table[y=fillC]{data-100.csv}; - \addplot+ table[y=preallocC]{data-100.csv}; - \end{groupplot} - \end{tikzpicture} - \caption[Comparision of preallocation methods]{Comparision of different preallocations methods for mesh sizes 10000 and 14400. The plot compares times spent in the stages of preallocate and fill matrices for evaluation ($A$) and interpolation ($C$)} - \label{fig:TimingsPreallocation} -\end{figure} - - -\end{document} diff --git a/Preallocation_Timings/precice.xml.template b/Preallocation_Timings/precice.xml.template deleted file mode 100644 index 46aaaa7b..00000000 --- a/Preallocation_Timings/precice.xml.template +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Preallocation_Timings/timings.py b/Preallocation_Timings/timings.py deleted file mode 100755 index 7f8286a1..00000000 --- a/Preallocation_Timings/timings.py +++ /dev/null @@ -1,133 +0,0 @@ -#!env python3 -import contextlib, datetime, multiprocessing, os, time, subprocess, sys, socket, json -from pathlib import Path -from shutil import copy - -import numpy as np - -try: - from ipdb import set_trace -except ImportError: - from pdb import set_trace - - - -def removeEventFiles(participant): - p = Path(participant) - try: - Path(p / ("precice-%s-events.log" % participant)).unlink() - Path(p / ("precice-%s-eventTimings.log" % participant)).unlink() - except FileNotFoundError: - pass - - -def shape_parameter(mesh_size, m): - """ Computes the shape parameter for Gaussians for a given m and mesh size. """ - h = 1 / mesh_size - s = np.sqrt(- np.log(1e-9)) / (m * h) - print("################## mesh_size =", mesh_size, ', m =', m, ", h =", h, ", s =", s, "##################") - return s - -def launchSingleRun(participant, ranks, outfile = None, runName = ""): - ostream = open(outfile, "a") if outfile else sys.stdout - mesh = "../outMesh.txt" if participant == "A" else "../inMesh.txt" - os.chdir(participant) - - cmd = [mpirun, "-n", ranks, "../../readMesh", "-a", "--runName", runName, - "-c", "../precice.xml", mesh, participant] - with contextlib.redirect_stdout(ostream): - cp = subprocess.run(cmd, stdout = sys.stdout, stderr = subprocess.STDOUT, check = True) - - -def launchRun(rankA, rankB, outFileA = None, outFileB = None, runName = ""): - pA = multiprocessing.Process(target=launchSingleRun, daemon=True, args=("A", str(rankA), outFileA, runName)) - pB = multiprocessing.Process(target=launchSingleRun, daemon=True, args=("B", str(rankB), outFileB, runName)) - pA.start(); pB.start() - pA.join(); pB.join() - if (pA.exitcode != 0) or (pB.exitcode != 0): - raise Exception - - -def prepareConfigTemplate(shape_parameter, preallocation): - print("Prepare config template: preallocation =", preallocation, ", shape parameter =", shape_parameter) - with open("precice.xml.template") as f: - template = f.read() - with open("precice.xml", "w") as f: - f.write(template.format(shape_parameter = shape_parameter, preallocation = preallocation)) - - -def createMesh(size): - cmd = "../make_mesh.py {0} {0}".format(size) - subprocess.run(cmd, shell = True, check = True) - - -def doScaling(name, runNames, ranksA, ranksB, mesh_sizes, ms, preallocations): - assert(len(ranksA) == len(ranksB) == len(mesh_sizes) == len(ms) == len(preallocations)) - - removeEventFiles("A") - removeEventFiles("B") - - file_info = { "date" : datetime.datetime.now().strftime("%Y-%m-%d_%H:%M:%S"), - "name" : name, - "meshMin": min(mesh_sizes), "meshMax": min(mesh_sizes)} - - file_pattern = "{date}-{name}-{participant}.{suffix}" - - for runName, rankA, rankB, mesh_size, m, preallocation in zip(runNames, ranksA, ranksB, mesh_sizes, ms, preallocations): - print("Running on ranks = {}/{}, mesh size = {}, m = {}".format(rankA, rankB, mesh_size, m)) - createMesh(mesh_size) - prepareConfigTemplate(shape_parameter(mesh_size, m), preallocation) - launchRun(rankA, rankB, - file_pattern.format(suffix = "out", participant = "A", **file_info), - file_pattern.format(suffix = "out", participant = "B", **file_info), - runName = runName) - - - copy("A/precice-A-events.log", file_pattern.format(suffix = "events", participant = "A", **file_info)) - copy("A/precice-A-eventTimings.log", file_pattern.format(suffix= "timings", participant = "A", **file_info)) - copy("B/precice-B-events.log", file_pattern.format(suffix = "events", participant = "B", **file_info)) - copy("B/precice-B-eventTimings.log", file_pattern.format(suffix= "timings", participant = "B", **file_info)) - - with open("{date}-{name}.meta".format(**file_info), "w") as f: - json.dump({"name" : name, - "date" : file_info["date"], - "host" : socket.getfqdn(), - "ranksA" : ranksA, "ranksB" : ranksB, - "mesh_sizes" : mesh_sizes, - "m" : m, - "preallocation" : preallocations}, - f, indent = 4) - - - -ppn = 24 # Processors per nodes, 24 for hazelhen, 28 for supermuc - -# mpirun = "aprun" # for HazelHen -# mpirun = "mpirun" # for SuperMUC and anywhere else -mpirun = "/opt/mpich/bin/mpiexec" - -# nodes = 3 -# ranksB = [(nodes-1)*ppn] -# ranksA = [ppn] * len(ranksB) -# mesh_sizes = [150] * len(ranksA) - - -# mesh_sizes = [500] * 4 + [1000] * 4 - -# preallocations = ["off", "compute", "saved", "tree"] * 2 # tree, saved, estimate, compute, off -multiplicity = 4 -ranksA = [2] * multiplicity -ranksB = [2] * multiplicity -ms = [6] * multiplicity -preallocations = ["off", "compute", "saved", "tree"] - -for i in range(5): - mesh_sizes = [20] * multiplicity - doScaling("prealloc-50", - preallocations, - ranksA, ranksB, mesh_sizes, ms, preallocations) - - mesh_sizes = [40] * multiplicity - doScaling("prealloc-60", - preallocations, - ranksA, ranksB, mesh_sizes, ms, preallocations) diff --git a/RBF_Timings/evaluate.py b/RBF_Timings/evaluate.py deleted file mode 100644 index f785f412..00000000 --- a/RBF_Timings/evaluate.py +++ /dev/null @@ -1,55 +0,0 @@ -import pandas as pd, numpy as np, matplotlib.pyplot as plt - -import glob, json, os, sys -from ipdb import set_trace - -def drop_and_mean(x): - set_trace() - if len(x) >= 5: - print("Masking outlier.") - return x.mask((x.index == x.idxmax()) | (x.index == x.idxmin())).mean() - else: - print("Less than 5 values in series, only applying mean.") - return x.mean() - - -files = glob.glob(os.path.join(sys.argv[1], "*-*-B-*.json")) -print("Number of files =", len(files)) - -events = [("_GLOBAL", "global"), - ("initialize/map.pet.fillA.FromMeshAToMeshB", "fillA"), - ("initialize/map.pet.fillC.FromMeshAToMeshB", "fillC"), - ("initialize/map.pet.preallocA.FromMeshAToMeshB", "preallocA"), - ("initialize/map.pet.preallocC.FromMeshAToMeshB", "preallocC"), - ("initialize/map.pet.postFill.FromMeshAToMeshB", "postFill"), - ("initialize/map.pet.computeRescaling.FromMeshAToMeshB", "computeRescaling"), - ("initialize/map.pet.solverInit.FromMeshAToMeshB", "solverInit"), - ("initialize/map.pet.computeMapping.FromMeshAToMeshB", "computeMapping"), - ("initialize/map.pet.solveConsistent.FromMeshAToMeshB", "solveConsistent"), - ("initialize/map.pet.mapData.FromMeshAToMeshB", "mapData")] - -l = [] - -for f in files: - j = json.load(open(f)) - size = len(j["Ranks"]) - for rno, rdata in enumerate(j["Ranks"]): - for ev, evname in events: - time = rdata["Timings"][ev]["Total"] - l.append({"File": f, "Rank" : rno, "Size" : size, "Event": evname, "Time" : time}) - - -df = pd.DataFrame(l) - -# df_means = df.groupby(["Size", "Event"]).aggregate({"Time" : drop_and_mean}) - -# Taking mean amoung all ranks -df_means = df.groupby(["Size", "Event"], as_index = False)["Time"].max() -# df_means = df_means.reset_index(drop = True) -df_means = pd.pivot(df_means, index = "Size", columns = "Event", values = "Time") - -df_means.to_csv(sys.argv[1] + ".csv") - -# df_means.plot() -# plt.show() - diff --git a/RBF_Timings/hazelhen.job b/RBF_Timings/hazelhen.job deleted file mode 100644 index 9ce78e89..00000000 --- a/RBF_Timings/hazelhen.job +++ /dev/null @@ -1,26 +0,0 @@ -#PBS -N Aste_RBF -#PBS -l nodes=10:ppn=24 -#PBS -l walltime=00:20:00 -#PBS -q test - -module swap tools/python tools/python/3.5.2 - -# Change to the directory that the job was submitted from -cd $PBS_O_WORKDIR - -rm -f .A-B-*.address - -python3 timings.py --platform hazelhen --maxmpisize 240 --meshsize 100 - -# export ATP_ENABLED=1 -# limit -c unlimited - -# cd A -# aprun -n 2 ../../readMesh -a -c ../precice.xml ../inMesh.txt B & > A.out - -# cd ../B -# aprun -n 2 ../../readMesh -a -c ../precice.xml ../outMesh.txt A > B.out - -# aprun -n 4 $ASTE/aste --participant=A --nx=100 --ny=100 --x=1 --y=1 --precice-config=$ASTE/precice.xml & -# aprun -n 4 $ASTE/aste --participant=B --nx=100 --ny=100 --x=1 --y=1 --precice-config=$ASTE/precice.xml - diff --git a/RBF_Timings/precice.xml.template b/RBF_Timings/precice.xml.template deleted file mode 100644 index ff7114e4..00000000 --- a/RBF_Timings/precice.xml.template +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/RBF_Timings/supermuc.job b/RBF_Timings/supermuc.job deleted file mode 100644 index cf47067c..00000000 --- a/RBF_Timings/supermuc.job +++ /dev/null @@ -1,40 +0,0 @@ -#@ wall_clock_limit = 00:20:00 -#@ job_type = MPICH -#@ job_name = Aste_RBF_Timings -#@ class = test -#@ island_count = 1 -#@ network.MPI = sn_all,not_shared,us -#@ node = 10 -#@ tasks_per_node = 28 -#@ energy_policy_tag = my_energy_tag -#@ minimize_time_to_solution = yes -#@ output = $(job_name).$(schedd_host).$(jobid).out -#@ error = $(job_name).$(schedd_host).$(jobid).err -#@ initialdir = . -#@ notification=always -#@ notify_user = florian.lindner@ipvs.uni-stuttgart.de -#@ queue - -. /etc/profile -. /etc/profile.d/modules.sh - -module swap python python/3.5_intel -module load gcc/6 - -module unload mpi.ibm -module unload mkl -module load mpi.intel - -module load petsc/3.8 -# ulimit -c unlimited -# export I_MPI_DEBUG_COREDUMP=1 - -python3 timings.py --platform supermuc --mfile $LOADL_HOSTFILE --maxmpisize 280 --meshsize 100 - - -# cd A -# mpirun -n 2 ../../readMesh -a -c ../precice.xml ../outMesh.txt A & -# cd .. - -# cd B -# mpirun -n 2 ../../readMesh -a -c ../precice.xml ../inMesh.txt B diff --git a/RBF_Timings/timings.py b/RBF_Timings/timings.py deleted file mode 100755 index 64d34fe7..00000000 --- a/RBF_Timings/timings.py +++ /dev/null @@ -1,234 +0,0 @@ -#!env python3 -import argparse, contextlib, datetime, glob, math, multiprocessing, os, time, subprocess, sys, socket, json -from pathlib import Path -from shutil import copy -import numpy as np - -# try: - # from ipdb import set_trace -# except ImportError: - # from pdb import set_trace - -def get_mpi_cmd(platform): - if platform == "hazelhen": - return "aprun" - elif platform == "supermuc": - return "mpiexec" - elif platform == "mpich-opt": - return "/opt/mpich/bin/mpiexec --prepend-rank" - elif platform == "mpich": - return "mpiexec.mpich" - else: - return "mpiexec" - -def split_file(inputfile, lines1, lines2, output1, output2): - """ Split inputfile in two files, each containing linesN lines. Used for MPI machine files.""" - with open(inputfile) as f: - lines = f.readlines() - - with open(output1, "w") as f: - for i in range(0, lines1): - f.write(lines[i]) - - with open(output2, "w") as f: - for i in range(lines1, lines1 + lines2): - f.write(lines[i]) - -def get_machine_file(platform, sizeA, sizeB, inputfile): - if platform == "supermuc": - split_file(inputfile, sizeA, sizeB, "mfile.A", "mfile.B") - return "-f ../mfile.A", "-f ../mfile.B" - else: - return ["", ""] - - -def get_platform_node_size(platform): - if platform == "hazelhen": - return 24 - elif platform == "supermuc": - return 28 - else: - return 2 - -def get_platform_network_interface(platform): - if platform == "hazelhen": - return "ipogif0" - elif platform == "supermuc": - return "ib0" - else: - return "lo" - - -def generate_test_sizes(platform, minsize, maxsize): - node_numbers = [1, 2, 3, 4, 6, 8, 10, 12, 14, 16, 18, 20, 24, 28, 32, 40, 48, 56, 64, 72, 80, 88, 96, - 104, 112, 128, 144, 160, 176, 192, 208, 224, 240, 256, 272, 288, 304] - if platform == "hazelhen" or platform == "supermuc": - sizes = [get_platform_node_size(platform)*i for i in node_numbers] - else: - sizes = range(2, maxsize+1) - - return [i for i in sizes if minsize <= i <= maxsize] - - -def removeEventFiles(participant): - p = Path(participant) - try: - Path(p / ("precice-%s-events.json" % participant)).unlink() - except FileNotFoundError: - pass - - -def shape_parameter(mesh_size, m): - """ Computes the shape parameter for Gaussians for a given m and mesh size. """ - h = 1 / mesh_size - s = np.sqrt(- np.log(1e-9)) / (m * h) - print("################## mesh_size =", mesh_size, ', m =', m, ", h =", h, ", s =", s, "##################") - return s - -def launchSingleRun(cmd ,participant, outfile = None): - ostream = open(outfile, "a") if outfile else sys.stdout - os.chdir(participant) - - with contextlib.redirect_stdout(ostream): - cp = subprocess.run(cmd, shell = True, stdout = sys.stdout, stderr = subprocess.STDOUT, check = True) - - -def launchRun(cmdA, cmdB, outFileA = None, outFileB = None): - pA = multiprocessing.Process(target=launchSingleRun, daemon=True, args=(cmdA, "A", outFileA)) - pB = multiprocessing.Process(target=launchSingleRun, daemon=True, args=(cmdB, "B", outFileB)) - pA.start(); pB.start() - pA.join(); pB.join() - if (pA.exitcode != 0) or (pB.exitcode != 0): - raise Exception - - -def prepareConfigTemplate(platform, shape_parameter, preallocation): - print("Prepare config template: preallocation =", preallocation, ", shape parameter =", shape_parameter) - with open("precice.xml.template") as f: - template = f.read() - with open("precice.xml", "w") as f: - f.write(template.format(shape_parameter = shape_parameter, - preallocation = preallocation, - network = get_platform_network_interface(platform))) - - -def createMesh(size): - cmd = "../build/make_mesh.py --nx {0} --ny {0} mesh".format(size) - subprocess.run(cmd, shell = True, check = True) - -def evalMesh(): - cmd = '../build/eval_mesh.py mesh.txt "math.sin(x) + math.exp(z)"' - subprocess.run(cmd, shell = True, check = True) - -def partitionMesh(partitions, outname): - cmd = "../build/partition_mesh.py --algorithm uniform --numparts {} --out {} mesh.txt" - cmd = cmd.format(partitions, outname) - subprocess.run(cmd, shell = True, check = True) - - -def doScaling(args, ranksA, ranksB, mesh_sizes, ms, preallocations): - assert(len(ranksA) == len(ranksB) == len(mesh_sizes) == len(ms) == len(preallocations)) - - removeEventFiles("A") - removeEventFiles("B") - - file_info = { "date" : datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S"), - "name" : args.name, - "meshMin": min(mesh_sizes), "meshMax": min(mesh_sizes)} - - file_pattern = "{date}-{name}-{participant}-ranks{ranks}.{suffix}" - - for rankA, rankB, mesh_size, m, preallocation in zip(ranksA, ranksB, mesh_sizes, ms, preallocations): - print("Running on ranks = {}/{}, mesh size = {}, m = {}".format(rankA, rankB, mesh_size, m)) - - cmd = "{mpi} -n {size} {machinefile} ../../build/preciceMap --precice-config ../precice.xml --participant {participant} --mesh {mesh}" - machine_file = get_machine_file(args.platform, rankA, rankB, args.mfile) - cmdA = cmd.format( - mpi = get_mpi_cmd(args.platform), - size = rankA, - machinefile = machine_file[0], - participant = "A", - mesh = "../outmesh") - cmdB = cmd.format( - mpi = get_mpi_cmd(args.platform), - size = rankB, - machinefile = machine_file[1], - participant = "B", - mesh = "../inmesh") - - if args.debug: - print("Command A:", cmdA) - print("Command B:", cmdB) - - - file_info["ranks"] = rankB - createMesh(mesh_size) - evalMesh() - partitionMesh(rankA, "outmesh") - partitionMesh(rankB, "inmesh") - prepareConfigTemplate(args.platform, shape_parameter(mesh_size, m), preallocation) - launchRun(cmdA, cmdB, - file_pattern.format(suffix = "out", participant = "A", **file_info), - file_pattern.format(suffix = "out", participant = "B", **file_info)) - - - copy("A/precice-A-events.json", file_pattern.format(suffix = "json", participant = "A", **file_info)) - copy("B/precice-B-events.json", file_pattern.format(suffix = "json", participant = "B", **file_info)) - - map(os.remove, glob.glob(".A-B-*.address")) - - with open("{date}-{name}.meta".format(**file_info), "w") as f: - json.dump({"name" : args.name, - "date" : file_info["date"], - "host" : socket.getfqdn(), - "ranksA" : ranksA, "ranksB" : ranksB, - "mesh_sizes" : mesh_sizes, - "m" : m, - "preallocation" : preallocations}, - f, indent = 4) - - - -# Global: Name of mpirun command -mpirun = "" - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument("--name", help = "A name for that run.", default = "upscaling") - parser.add_argument("--mfile", help = "MPI machine file to use.") - parser.add_argument("--maxmpisize", help = "Max MPI size to upscale per participant", type = int, required = True) - parser.add_argument("--minmpisize", help = "Min MPI size to upscale per participant", type = int, default = 2) - parser.add_argument("--weakscaling", help = "Use weak scaling for the number of vertices.", action = "store_true") - parser.add_argument("--meshsize", help = "Strong scaling: mesh size. Weak scaling: meshsize^2 is base size for minimum number of ranks ", type = int, required = True) - parser.add_argument("--platform", choices = ["supermuc", "hazelhen", "mpich-opt", "mpich", "none"], default = "none") - parser.add_argument("--debug", action = "store_true", default = False) - args = parser.parse_args() - - ranks = generate_test_sizes(args.platform, - args.minmpisize, - args.maxmpisize - get_platform_node_size(args.platform)) - - mpirun = get_mpi_cmd(args.platform) - - print("Name =", args.name) - print("Platform =", args.platform) - print("MPI command =", mpirun) - print("Ranks =", ranks) - - multiplicity = len(ranks) - - ranksA = [get_platform_node_size(args.platform)] * multiplicity - ranksB = ranks - ms = [6] * multiplicity - preallocations = ["tree"] * multiplicity - - if args.weakscaling: - elems_per_proc = args.meshsize**2 / ranksA[0] - mesh_sizes = [int(math.sqrt(r * elems_per_proc)) for r in ranksB] - else: - mesh_sizes = [args.meshsize] * multiplicity - - print("Mesh Sizes =", mesh_sizes) - - doScaling(args, ranksA, ranksB, mesh_sizes, ms, preallocations) diff --git a/cmake-modules/FindMETIS.cmake b/cmake/FindMETIS.cmake similarity index 98% rename from cmake-modules/FindMETIS.cmake rename to cmake/FindMETIS.cmake index 8f147c8b..df8333f6 100644 --- a/cmake-modules/FindMETIS.cmake +++ b/cmake/FindMETIS.cmake @@ -18,7 +18,7 @@ # METIS_LIB_SUFFIX - Also search for non-standard library names with the # given suffix appended # -# NOTE: This file was modified from a ParMETIS detection script +# NOTE: This file was modified from a ParMETIS detection script #============================================================================= # Copyright (C) 2015 Jack Poulson. All rights reserved. diff --git a/contrib/demo.sh b/contrib/demo.sh deleted file mode 100755 index d0df8202..00000000 --- a/contrib/demo.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash - -set -e -set -x - -# This script assumes the ASTE binaries and python scripts are in $PATH -# Furthermore, execute in ./contrib or copy precice.xml from there to $PWD - - -# Download the red blood cell -test -f rbc.vtk || wget "https://people.sc.fsu.edu/~jburkardt/data/vtk/rbc_001.vtk" -O rbc.vtk - -# Download the bunny -test -f bunny.vtk || wget "https://www.ece.lsu.edu/xinli/Meshing/Data/bunny.vtk" -O bunny.vtk - -# Evaluate the function x+y on the bunny, write to colored.vtk -eval_mesh.py bunny.vtk -o colored.vtk "x + y" - -# Decompose both meshes to two procesors -partition_mesh.py colored.vtk -n 2 -partition_mesh.py rbc.vtk -n 2 - -rm -rf colored.dt0 && mv colored colored.dt0 -rm -rf rbc.dt0 && mv rbc rbc.dt0 - -# Map from the bunny to the red blood cell (yeah, that doesn't really make sense) -mpirun -n 2 preciceMap -v -p A --mesh colored & -mpirun -n 2 preciceMap -v -p B --mesh rbc --output mapped - -# Join the output files together to result.vtk -join_mesh.py mapped -o result.vtk diff --git a/contrib/job.supermuc b/contrib/job.supermuc deleted file mode 100644 index 1a31d43e..00000000 --- a/contrib/job.supermuc +++ /dev/null @@ -1,45 +0,0 @@ -#@ wall_clock_limit = 00:30:00 -#@ job_type = MPICH -#@ job_name = ASTE -#@ class = test -#@ island_count = 1 -#@ network.MPI = sn_all,not_shared,us -#@ node = 1 -#@ tasks_per_node = 4 -#@ energy_policy_tag = my_energy_tag -#@ minimize_time_to_solution = yes -#@ output = $(job_name).$(schedd_host).$(jobid).out -#@ error = $(job_name).$(schedd_host).$(jobid).err -#@ initialdir = . -#@ notification=always -#@ notify_user = your.address@invalid.org -#@ queue - -. /etc/profile -. /etc/profile.d/modules.sh - -module swap python python/3.5_intel -module load gcc/6 - -module unload mpi.ibm -module unload mkl -module load mpi.intel - -module load petsc/3.8 - -# Activate core dumps -ulimit -c unlimited -export I_MPI_DEBUG_COREDUMP=1 - - -# ./make_mesh.py --nx 100 --ny 100 mesh.txt -# ./partition_mesh.py mesh.txt -n 2 - -cd A -mpiexec -n 2 ../build/preciceMap --precice-config ../precice.xml --participant A --mesh ../mesh > output & -cd .. - -cd B -mpiexec -n 2 ../build/preciceMap --precice-config ../precice.xml --participant B --mesh ../mesh > output - - diff --git a/contrib/precice.xml b/contrib/precice.xml deleted file mode 100644 index 5614edf8..00000000 --- a/contrib/precice.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/contrib/timestep-demo/clean.sh b/contrib/timestep-demo/clean.sh deleted file mode 100755 index d2ab18ed..00000000 --- a/contrib/timestep-demo/clean.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/bash -rm -rf colored* rbc.dt1* bunny.vtk vtkA vtkB precice-A-events.json precice-B-events.json filtered.log mapped debug.log diff --git a/contrib/timestep-demo/demo.py b/contrib/timestep-demo/demo.py deleted file mode 100755 index e5a07b5d..00000000 --- a/contrib/timestep-demo/demo.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python3 -# This script assumes the ASTE binaries and python scripts are in $PATH -# Furthermore, execute in ./contrib/timestep-demo or copy precice.xml from there to $PWD - -import os, subprocess - -def run(cmd): - print("+ " + cmd) - subprocess.run(cmd, shell = True, check = True) - -# Get bunny and red blood cell -if not os.path.isfile("rbc.dt0.vtk"): - run("wget --quiet https://people.sc.fsu.edu/~jburkardt/data/vtk/rbc_001.vtk -O rbc.dt0.vtk") - -if not os.path.isfile("bunny.vtk"): - run("wget --quiet https://www.ece.lsu.edu/xinli/Meshing/Data/bunny.vtk -O bunny.vtk") - -# Generate 20 timesteps of bunny.vtk -files = ["colored.dt" + str(i) + ".vtk" for i in range(20)] -for t, f in enumerate(files): - if not os.path.isfile(f): - run("eval_mesh.py bunny.vtk -o " + f + " " + str(t)) - -if not all([os.path.isdir("colored.dt" + str(i)) for i in range(20)]): - run("partition_mesh.py -n 2 " + " ".join(files)) - -# Partition output mesh as well -run("partition_mesh.py -n 2 rbc.dt0.vtk ") - -# Run preCICE. Note that the meshes are named colored.dt1, colored.dt2, ... -os.makedirs("vtkA", exist_ok = True) -os.makedirs("vtkB", exist_ok = True) - -run("mpirun -n 2 preciceMap -v -c precice.xml -p A --mesh colored &") -run("mpirun -n 2 preciceMap -v -c precice.xml -p B --mesh rbc --output mapped") - diff --git a/contrib/timestep-demo/precice.xml b/contrib/timestep-demo/precice.xml deleted file mode 100644 index 70b40f19..00000000 --- a/contrib/timestep-demo/precice.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/AsteFlow.png b/docs/AsteFlow.png deleted file mode 100644 index 5d23aad3..00000000 Binary files a/docs/AsteFlow.png and /dev/null differ diff --git a/docs/README.md b/docs/README.md index 933c6df4..d0d18115 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,68 +1,310 @@ -# aste -aste stands for Artificial Solver Testing Environment for preCICE. aste facilitates getting data into preCICE and out of it. An overview is given by the following figure: -![](AsteFlow.png) +--- +title: Artificial Solver Testing Environment (ASTE) +permalink: tooling-aste.html +keywords: tooling, aste +summary: "ASTE is a lightweight wrapper around the preCICE API, which allows emulating participants to investigate simulation setups." +--- -aste consists of compiled C++ Modules and of Python modules. +## Motivation -## Python modules -### make_mesh.py -Create a simple text mesh on `[x0, x1] x [y0, y1]` with `nx x ny` points. The mesh is 3-dimensional, with the z-component set to 0. +ASTE is a collection of tools that can be used to reproduce and evaluate particular setups without using actual solver codes. There are two common use-cases, where this is particularly useful: -### eval_mesh.py -Reads a mesh as either `.vtk` or `.txt` and evaluates a function given by `-f` on it. The function gets the mesh points a numpy array of the form `x = [[x_1, y_1, z_1], ...]` and should store the result in `y`. +1. Reproducing a specific mapping setup of a coupled case, e.g., a case crashes since the mapping fails or the mapping seems to behave unexpected. ASTE allows to rerun such a case (in parallel if needed) and investigate the mapping in terms of accuracy as well as runtime. -### partition_mesh.py -Reads a mesh as either `.vtk` or `.txt`, partitions it and stores the parts in a directory like `dirname/0, 1, ...`. For partitioning two algorithms are available. The meshfree algorithm does not need any mesh topology information, whereas the topological algorithm needs topology information. This python module needs the C++ module `libmetisAPI.so` if the topological algorithm is used. +2. Replay mode, where we replace a participant in a coupled setup with ASTE resulting in a uni-directional coupling. This is useful for debugging, for developing new adapters, but also for efficiency reasons (explicit instead of implicit coupling, no computationally demanding solver needs to be executed). -### join_mesh.py -Reads a partitioned mesh from a directory like `dirname/0, 1, ...` and saves it to a single file. +## Installation -### libMetisAPI -This is a small C++ wrapper around METIS. It is only required if `partition_mesh.py` should use a topological algorithm. +The core module, which interfaces with preCICE, is called `precice-aste-run` and written in C++. In addition, ASTE offers several tools for pre- and post-processing purposes written in python. -### preciceMap -This is a C++ application, which does the coupling through precice. It expects a mesh in the format given by `partition_mesh.py`. currently, only explict coupling is supported. When using multiple timesteps, make sure to provide a mesh (with data) for each timestep. +### Dependencies -## Dependencies +The C++ core module of ASTE uses similar dependencies as preCICE itself. In particular, ASTE requires a C++ compiler, CMake, MPI and Boost. Have a look at the [corresponding preCICE documentation](https://precice.org/installation-source-dependencies.html) for required versions and on how to install these dependencies if needed. In addition, ASTE relies on preCICE (version >= 2.0) and the VTK library (version >= 7) in order to handle mesh files. The VTK library can be installed using the package manager (`libvtk-dev`), e.g., on Ubuntu -### C++ modules -##### Required -- preCICE -- MPI -- CMake -##### Optional -- METIS +```bash +sudo apt install libvtk9-dev +``` + +{% important %} +The VTK package also installs a compatible python interface to VTK, which is used in ASTE. If you already have a python VTK installation on your system (e.g. through pip), make sure that your python-vtk version is compatible with your C++ VTK version. +{% endimportant %} + +As an optional dependency for pre-processing, METIS can be installed. METIS is a graph partitioning library used for topological partitioning in the mesh partitioner and can be installed similarly via apt + +```bash +sudo apt install libmetis-dev +``` + +The python tools require -### Python modules -##### Required - NumPy -##### Optional -- vtk (Visualization Toolkit) -- scipy +- sympy (optional) + +which can be installed directly using pip and the `requirements.txt` file in the repository + +```bash +pip3 install -r requirements.txt +``` + +### Building and installation + +In order to build ASTE, clone the project repository and use the usual `CMake` steps to steer the installation procedure: + +```bash +git clone https://github.com/precice/aste.git +mkdir build && cd build +cmake .. && make +``` + +{% tip %} +You can use `ctest` in order to check that the building procedure succeeded: Run `make test`. +{% endtip %} + +In order to install ASTE and the associated tools system-wide, execute + +```bash +make install +``` + +which might require root permission. + +## Command line interface + +After the installation procedure, the following executables are available + +- `precice-aste-run`: core module interfacing with preCICE +- `precice-aste-evaluate`: python tool to compute and store data on mesh files +- `precice-aste-partition`: python tool to partition a single mesh file into several ones for parallel runs +- `precice-aste-join`: python tool to join several mesh files into a single mesh file for parallel runs. + +All ASTE tools are executed from the command line and running a particular executable with `--help` prints a complete list of available command line arguments and their meaning. There is also an ASTE tutorial [in the preCICE tutorials](https://precice.org/tutorials-aste-turbine.html). + +The following subsections explain each part of ASTE in more detail. All ASTE modules have the following three command line arguments in common + +| Flag | Explanation | +| ---------- | -------------------- | +| `--mesh` | The mesh filename/prefix used as input | +| `--data` | Name of data array (input or output depending on the module) | +| `--output` | The mesh filename used to store the output mesh | + +### precice-aste-run + +`precice-aste-run` calls the preCICE API and can be executed in serial as well as in parallel (using MPI). As stated in the introduction, there are two different use-cases, one for investigating mappings and one for replacing participants in a coupled scenario (replay mode). Configuring the replay mode in ASTE relies on a `json` configuration file (see further below). Therefore, the replay mode takes usually only the `--aste-config ` option as a command line argument. All other command line arguments are mostly used for reproducing mappings. + +| Flag | Explanation | +| --------------- | ---------------------------------------------------------------------- | +| `--aste-config` | ASTE configuration file (only used for replay mode) | +| `-v` | Enables verbose logging output from preCICE | +| `-c` | To specify preCICE configuration file (default=`"precice-config.xml"`) | +| `-p` | Participant name, which can take the arguments `A` or `B` | +| `--vector` | A bool switch to specify vector data (default=`False`) | + +{% note %} +The input mesh filename passed with the `--mesh` option does not need to coincide with the mesh names defined in the preCICE configuration file. +{% endnote %} + +For example, mapping the data "dummyData" from a mesh named `fine_mesh.vtk` to an output mesh `coarse_mesh.vtk` and saving the resulting mesh into the variable "mappedData" on the mesh `mappedMesh` would read as follows: + +```bash +precice-aste-run -p A --mesh fine_mesh --data "dummyData" +precice-aste-run -p B --mesh coarse_mesh --data "mappedData" --output mappedMesh +``` + +While the example above exexutes the mapping in serial, `precice-aste-run` can be executed in parallel (using MPI). However, this requires a partitioned mesh (one per parallel rank). In order to decompose a single mesh appropriately, the tools `precice-aste-partition` and `precice-aste-join` can be used. + +{% tip %} +If you want to reproduce a specific setup of your solvers, you can use the [export functionality](https://precice.org/configuration-export.html#enabling-exporters) of preCICE and use the generated meshes directly in `precice-aste-run`. If you run your solver in parallel, preCICE exports the decomposed meshes directly, so that no further partitioning is required. +{% endtip %} + +### precice-aste-partition + +Reads a single mesh file (either `.vtk` or `.vtu` extension) and partitions it into several mesh files. The resulting mesh files are are stored as `output_1.vtu, output_2.vtu, ...`. There are there algorithms available in order to execute the partitioning. The `meshfree` and `uniform` algorithm are rather simple algorithms, which don't require any mesh topology information. The `topological` algorithm relies on the optional dependency METIS and is more powerful, but needs topology information. + +| Flag | Explanation | +| ------------- | ------------------------------------------------------------------------------------------- | +| `--directory` | Output directory (optional) | +| `--numparts` | The number of parts to split the mesh into | +| `--algorithm` | Algorithm used for determining the partitioning (options="meshfree", "topology", "uniform") | + +Example: to divide a mesh into two parts using the `topological` partitioning and store it in a directory: + +```bash +precice-aste-partition --mesh MeshA.vtk --algorithm topology --numparts 2 --output fine_mesh --directory partitioned_mesh +``` + +{% note %} +METIS is written in C++ and used through a library interface called `libMetisAPI`. Please check your ASTE installation in case you face issues with `libMetisAPI`. +{% endnote %} + +{% note %} +`precice-aste-partition` creates also a `recovery.json` file in order to store connectivity information between the individual mesh files. The recovery file is optional and allows to restore the original connectivity information. +{% endnote %} -## Building -Make sure to have all the needed dependencies installed. Then do: +### precice-aste-join + +Reads a partitioned mesh from a given prefix (looking for `_<#filerank>.vtu)`) and saves it to a single `.vtk` or `.vtu` file. +The `-r` flag also recovers the connectivity information across several ranks from a mesh. + +| Flag | Explanation | +| ------------ | ------------------------------------------------------------------------------------- | +| `--recovery` | The path to the recovery file to fully recover connectivity information across ranks. | +| `--numparts` | The number of parts to read from the input mesh. By default, the entire mesh is read. | +| `--log` | Logging level (default="INFO") | + +For example, to join a partitioned mesh using a recovery file: + +```bash +precice-aste-join --mesh partitoned_mesh_directory/partitioned_mesh --recovery partitioned_directory --output rejoined_mesh.vtk ``` -mkdir build -cd build -cmake .. -make + +### precice-aste-evaluate + +While the previous two tools of ASTE handled the meshes for parallel runs, `precice-aste-evaluate` takes care of pre- and postprocessing the actual data on the meshes. `precice-aste-evaluate` reads a mesh as either `.vtk` or `.vtu`, evaluates a function on the mesh given by `--function` on it and stores the resulting data on this particular mesh. When using the `--diff` flag, the tool can also compute the difference between the data values already stored on the mesh and the function values (usually applied after a mapping). The `diff` flag also reports common error metrics such as the l2-norm and minimum or maximum errors on the mesh + +| Flag | Explanation | +| ------------------ | ----------------------------------------------------------------------------------- | +| `--function` | The function which should be evaluated on the mesh (see below for examples). | +| `--list-functions` | Prints a list of predefined functions. | +| `--diff` | Calculates the difference between `--diffdata` and the given function. | +| `--diffdata` | The name of the data to compute the difference used in `diff` mode. If not given, --data is used. | +| `--log` | Logging level (default="INFO") | +| `--dir` | Output directory (optional) | +| `--stat` | Store statistics of the difference calculation in a separate file called `mesh.stats.json` | +| `--gradient` | Calculate and store gradient data in addition to the given input function on the mesh.| + +The predefined functions are a collection of common interpolation functions, which are usuually too cumbersome for the command line: + +| Function | Explanation | +| ---------- | --------------------------------------------------------------------------------------- | +| franke | Franke's function has two Gaussian peaks of different heights, and a smaller dip. | +| eggholder | A function with many local extrema. | +| rosenbrock | A function having a global minimum in a narrow, parabolic valley. | + +All function provided have 3D and 2D variants (which should be applied depending on your mesh topology). Example: calculate and store the Eggholder function on given mesh + +```bash +precice-aste-evaluate --mesh 3DMesh.vtk --function "eggholder3d" --data "EggHolder" +precice-aste-evaluate --mesh 2DMeshonXY.vtk --function "eggholder2d(xy)" --data "EggHolder" +precice-aste-evaluate --mesh 2DMeshonXZ.vtk --function "eggholder2d(xz)" --data "EggHolder" +precice-aste-evaluate --mesh 2DMeshonYZ.vtk --function "eggholder2d(yz)" --data "EggHolder" ``` -If precice is not installed in `$PRECICE_ROOT/build` do `cmake -DCMAKE_LIBRARY_PATH=$PRECICE_INSTALL_DIR ..` with the correct installation directory. -### on SuperMUC -Initialize environment, e.g., put in your `.bashrc` +Example: calculating the function "sin(x)+exp(y)" on mesh `MeshA` and store the result in "MyFunc" + +```bash +precice-aste-evaluate --mesh MeshA.vtk --function "sin(x)+exp(y)" --data "MyFunc" ``` -# METIS for aste -module load metis -export METIS_DIR=$METIS_BASE # so that cmake finds metis -export CPLUS_INCLUDE_PATH="$METIS_BASE/include:$CPLUS_INCLUDE_PATH" + +Example: calculating the difference between `MappedData` and the analytic function "sin(x)" and storing the resulting difference data in the variable "Error": + +```bash +precice-aste-evaluate --mesh Mapped.vtk --function "sin(x)" --diff --diffdata "MappedData" --data "Error" +``` + +### Replay mode + +The replay mode is a bit different from the scenarios we have seen so far. Here, we emulate the behavior of individual participants in a coupled simulation. In order to configure such a scenario, each participant you want to replace needs a configuration file in JSON format with the following attributes: + +```json +{ + "participant": "Participant-Name", + "startdt": "PreCICE mesh dt number (>= 1)", + "meshes": [ + { + "mesh": "Mesh name in preCICE config file", + "meshfileprefix": "/path/to/mesh/file/with/prefix/Mesh-Participant-A", + "read-data": { + "vector": ["Vector dataname in preCICE config which has a read type"], + "scalar": ["Scalar dataname in preCICE config which has a read type"] + }, + "write-data": { + "vector": ["Vector dataname in preCICE config which has a write type"], + "scalar": ["Scalar dataname in preCICE config which has a write type"] + } + } + ], + "precice-config": "/path/to/precice/config/file/precice-config.xml" +} ``` -and execute cmake like `cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ ..` and `make`. +The JSON configuration file is similar to an adapter configuration file. The above configuration file is an example of a participant with one mesh. The user can add as many meshes as required. + +{% important %} +The first entry `mesh` refers to the mesh name in the precice configuration file (e.g. `Solid-Mesh`), whereas the second argument refers to the actual filenames on your system, which are usually generated by preCICE. +{% endimportant %} + +#### Step-by-step guide for replay mode + +{% note %} +The replay mode only supports explicit coupling schemes. +{% endnote %} +##### Step 1: Setup export of your original coupling + +In a first step we have to generate the required mesh and data files of the participant we want to emulate with ASTE. Therefore, we use the [export functionality](https://precice.org/configuration-export.html) of preCICE. After adding the `export` tag in the precice configuration file, start the coupled simulation and run as many time-steps as you need. + +As an example, we replace the `Fluid` participant of the [`perpendicular-flap`](https://precice.org/tutorials-perpendicular-flap.html) tutorial by ASTE. Therefore, we first set the export tag on the fluid participant in the configuration file (see below) and then run the simulation with one of the available fluid solvers (e.g. `fluid-openfoam` coupled to `solid-fenics`). + +```xml + + ... + + +``` + +##### Step 2: Prepare ASTE and preCICE configuration files + +Prepare an ASTE configuration for the solver you want to replace. See above for the corresponding ASTE configuration format. If your previous simulation used an implicit coupling, make sure to change the configuration to an explicit coupling. + +Referring to our example: once the simulation is done, the directory `exported-meshes` contains all necessary coupling data in order to use ASTE for the coupled simulation. We create a new directory in the `perpendicular-flap` directory called `fluid-aste` and move the `exported-meshes` into the new directory in order to run ASTE from a separate directory. Since ASTE supports only `explicit` coupling schemes, we switch from an `implicit` coupling scheme to an `explicit` coupling scheme in the preCICE configuration file: + +```xml + + + + + + + +``` + +In addition, we create and configure the `aste-config.json` file in the `fluid-aste` directory according to the data names in the `precice-config.xml` file: + +```json +{ + "participant": "Fluid", + "startdt": "1", + "meshes": [ + { + "mesh": "Fluid-Mesh", + "meshfileprefix": "./exported-meshes/Fluid-Mesh-Fluid", + "read-data": { + "vector": ["Displacement"] + }, + "write-data": { + "vector": ["Force"] + } + } + ], + "precice-config": "../precice-config.xml" +} +``` + +##### Step 3: Run your solver and ASTE + +Run your solver and ASTE as usual, e.g., execute `myFluidSolver` in one shell and `precice-aste-run` in another shell: + +```bash +./myFluidSolver & +precice-aste-run --aste-config solid-config.json +``` + +ASTE picks up the correct mesh files, extracts the data and passes the data to preCICE. + +For our example above, the fluid solver emulation via ASTE can be started by executing + +```bash + precice-aste-run --aste-config aste-config.json +``` -## Demo -A simple demonstration of aste can be run with `./demo.sh`. A bunny-shaped mesh is mapped onto a red blood cell. The result can be seen in `result.vtk`. -## Demo with multiple timesteps -A similar demo with multiple timesteps can be run with `./timesteps.py` inside `contrib/timestep-demo`. Make sure to set `astedir` inside `timesteps.py` to the correct value (By using the environment variable `ASTEDIR`). For details look into the `timesteps.py` and the corresponding `timesteps-precice.xml` file. +in the `fluid-aste` directory. Simply start any solid solver alongside (e.g. `solid-fenics`). diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 00000000..b3923e74 --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1,3 @@ +**/precice-*-*-*.json +**/fine_mesh_*.vtk +**/map_*.vtk diff --git a/examples/clean-all.sh b/examples/clean-all.sh new file mode 100755 index 00000000..deaa1bd1 --- /dev/null +++ b/examples/clean-all.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +echo "- Cleaning up all test examples..." + +find . -maxdepth 2 -mindepth 2 -name clean.sh -execdir sh -c './clean.sh' \; diff --git a/examples/coarse_mesh.vtk b/examples/coarse_mesh.vtk new file mode 100644 index 00000000..8a7974cd --- /dev/null +++ b/examples/coarse_mesh.vtk @@ -0,0 +1,2194 @@ +# vtk DataFile Version 4.2 +vtk output +ASCII +DATASET UNSTRUCTURED_GRID +POINTS 438 float +0.000159205 0.0459595 1e-07 0.0910679 0.0459595 1e-07 0.000159205 0.0459595 0.0909088 +0.00016037 0.0462879 0.0909088 0.0910679 0.0459595 0.0909088 0.00387147 0.0486486 0.999996 +0.000160265 0.0467696 0.999996 0.00230119 0.0432031 0.999996 0.0412046 0.0349339 0.999996 +0.000161941 0.0467691 0.272726 0.000140272 0.0463638 0.272726 0.0114969 0.0345959 0.272726 +0.170587 0.0345959 0.272726 0.013112 0.0572077 0.272726 0.00884021 0.0726769 1e-07 +0.0315674 0.0891891 1e-07 0.0596597 0.0891891 1e-07 0.0823869 0.0726769 1e-07 +0.000159205 0.0459595 0.0227273 0.000159205 0.0459595 0.0454544 0.000159205 0.0459595 0.0681816 +0.000159502 0.0461237 0.0909088 0.00899528 0.072889 0.0909088 0.031755 0.0892496 0.0909088 +0.0597846 0.0891483 0.0909088 0.0824255 0.0726237 0.0909088 0.0910679 0.0459595 0.0227273 +0.0910679 0.0459595 0.0454544 0.0910679 0.0459595 0.0681816 0.00160779 0.0485161 0.999996 +0.000455632 0.0445206 0.999996 0.0217529 0.0390685 0.999996 0.022538 0.0417913 0.999996 +0.000149524 0.0465665 0.272726 0.00331992 0.0380684 0.272726 0.0380119 0.0345959 0.272726 +0.064527 0.0345959 0.272726 0.091042 0.0345959 0.272726 0.117557 0.0345959 0.272726 +0.144072 0.0345959 0.272726 0.165412 0.0346094 0.301817 0.160237 0.0346229 0.330908 +0.155061 0.0346364 0.359999 0.149886 0.03465 0.389089 0.144711 0.0346635 0.41818 +0.139535 0.034677 0.447271 0.13436 0.0346905 0.476362 0.129185 0.0347041 0.505452 +0.124009 0.0347176 0.534543 0.118834 0.0347311 0.563634 0.113659 0.0347446 0.592725 +0.108484 0.0347581 0.621816 0.103308 0.0347717 0.650906 0.0981329 0.0347852 0.679997 +0.0929576 0.0347987 0.709088 0.0877823 0.0348122 0.738179 0.082607 0.0348258 0.76727 +0.0774317 0.0348393 0.79636 0.0722564 0.0348528 0.825451 0.0670811 0.0348663 0.854542 +0.0619058 0.0348798 0.883633 0.0567305 0.0348934 0.912723 0.0515552 0.0349069 0.941814 +0.0463799 0.0349204 0.970905 0.000161649 0.0467691 0.301817 0.000161591 0.0467691 0.330908 +0.000161533 0.0467692 0.359999 0.000161476 0.0467692 0.389089 0.000161418 0.0467692 0.41818 +0.00016136 0.0467692 0.447271 0.000161303 0.0467693 0.476362 0.000161245 0.0467693 0.505452 +0.000161187 0.0467693 0.534543 0.00016113 0.0467693 0.563634 0.000161072 0.0467693 0.592725 +0.000161014 0.0467694 0.621816 0.000160957 0.0467694 0.650906 0.000160899 0.0467694 0.679997 +0.000160841 0.0467694 0.709088 0.000160784 0.0467694 0.738179 0.000160726 0.0467695 0.76727 +0.000160668 0.0467695 0.79636 0.000160611 0.0467695 0.825451 0.000160553 0.0467695 0.854542 +0.000160496 0.0467695 0.883633 0.000160438 0.0467696 0.912723 0.00016038 0.0467696 0.941814 +0.000160323 0.0467696 0.970905 0.144341 0.0383645 0.272726 0.118095 0.0421331 0.272726 +0.0918496 0.0459018 0.272726 0.0656037 0.0496704 0.272726 0.0393579 0.053439 0.272726 +0.00436536 0.0548066 0.272726 0.180351 0.0355659 0.247124 0.182875 0.0368583 0.219969 +0.173208 0.0384602 0.194627 0.154249 0.0400661 0.174948 0.132548 0.0415865 0.158194 +0.11193 0.0430953 0.140165 0.0966293 0.0446053 0.117586 0.000150027 0.0463529 0.246752 +0.000156511 0.0463421 0.220778 0.000160309 0.0463312 0.194804 0.000162009 0.0463204 0.168831 +0.000162195 0.0463096 0.142857 0.000161453 0.0462987 0.116883 0.0823869 0.0192421 0.0909088 +0.0596597 0.0027298 0.0909088 0.0315674 0.0027298 0.0909088 0.00884021 0.0192421 0.0909088 +0.0823869 0.0192421 1e-07 0.0596597 0.0027298 1e-07 0.0315674 0.0027298 1e-07 +0.00884021 0.0192421 1e-07 0.022007 0.0848031 0.0454914 0.0692455 0.0847877 0.0454214 +0.0452949 0.0914127 0.0271469 0.0459833 0.0914123 0.0637238 0.00531043 0.0669774 0.035351 +0.085921 0.0669692 0.0555544 0.00700601 0.0699502 0.0640866 0.0842291 0.0699374 0.0268326 +0.0163605 0.0807496 0.0206193 0.0748968 0.0807242 0.070268 0.0236776 0.0857704 0.0689787 +0.0675852 0.0857507 0.0219677 0.00230989 0.0597758 0.0793263 0.00327545 0.0624998 0.0154839 +0.0879556 0.0624896 0.0754086 0.0890093 0.0594839 0.0113637 0.0803777 0.0351106 0.353367 +0.0688654 0.0356498 0.428232 0.0618082 0.0361449 0.498045 0.057824 0.0364874 0.549321 +0.0527641 0.0368941 0.608927 0.0474462 0.0373114 0.668037 0.041951 0.0350394 0.319395 +0.115569 0.0347948 0.323253 0.0414538 0.0356544 0.386673 0.100612 0.035131 0.393609 +0.0431123 0.0376702 0.723615 0.0912257 0.0354629 0.465921 0.0373999 0.0363523 0.461155 +0.0399376 0.0379288 0.773704 0.0782444 0.0348457 0.309233 0.0827898 0.0357801 0.536735 +0.0353389 0.037002 0.535231 0.116822 0.034889 0.356267 0.0343723 0.038372 0.820141 +0.0247109 0.0349224 0.302868 0.106022 0.035165 0.432543 0.0767264 0.0360101 0.593702 +0.0292875 0.0376123 0.589863 0.033274 0.0360396 0.419407 0.032237 0.038499 0.865279 +0.0231959 0.0354815 0.354422 0.100408 0.0353344 0.501298 0.0707996 0.0362194 0.650396 +0.0271837 0.0368435 0.494902 0.0258598 0.0385388 0.695679 0.0227554 0.038307 0.644748 +0.0270534 0.0390052 0.897763 0.0520988 0.0348122 0.297217 0.0745022 0.0353256 0.38263 +0.0858047 0.0357151 0.566139 0.0636054 0.0364942 0.700337 0.057738 0.036706 0.750517 +0.135076 0.0346796 0.304008 0.0240181 0.0389874 0.749708 0.0266937 0.0374517 0.560793 +0.00520328 0.0365679 0.283682 0.0247755 0.0391872 0.928249 0.103278 0.0347228 0.297726 +0.0654269 0.0358589 0.456729 0.0787566 0.0359195 0.623583 0.010981 0.0413636 0.984008 +0.0220582 0.0394376 0.958114 0.0544334 0.0353446 0.362264 0.0207287 0.0396925 0.840616 +0.0469618 0.0370862 0.841938 0.134641 0.0347456 0.336506 0.024711 0.0380005 0.617361 +0.0655712 0.0350455 0.331397 0.0179275 0.036001 0.398455 0.0738162 0.0360257 0.675672 +0.0597173 0.0363206 0.523982 0.112552 0.0350935 0.459507 0.021603 0.0385671 0.670112 +0.124493 0.0348831 0.383215 0.0913972 0.0349248 0.330381 0.0196008 0.0351718 0.32427 +0.0521036 0.0369097 0.79781 0.0609679 0.0355978 0.404549 0.0969276 0.0350879 0.372729 +0.120565 0.0349548 0.412445 0.0305509 0.0375729 0.983062 0.0178061 0.0392036 0.723548 +0.0216662 0.0394111 0.795517 0.0669643 0.0362186 0.724914 0.110725 0.0351256 0.482101 +0.0881811 0.0353428 0.414886 0.014853 0.0358015 0.377935 0.0465145 0.0360522 0.441799 +0.0551325 0.0366904 0.577781 0.0255271 0.0347315 0.285274 0.10336 0.0352323 0.544966 +0.085905 0.0354838 0.444305 0.0621691 0.0362316 0.779021 0.103163 0.035265 0.523838 +0.0203007 0.0364789 0.445842 0.0538326 0.0361942 0.479055 0.0777991 0.0347073 0.288636 +0.079875 0.0357274 0.485739 0.043671 0.0366043 0.508859 0.0174199 0.0368218 0.473796 +0.0185178 0.0372885 0.520727 0.0438032 0.0352217 0.340119 0.0942524 0.0353614 0.609188 +0.049849 0.0371042 0.635925 0.0787546 0.0358268 0.511465 0.0122279 0.0380547 0.577311 +0.017916 0.0395815 0.774958 0.0101214 0.035045 0.307017 0.041936 0.0372363 0.886515 +0.017373 0.0375191 0.540471 0.0816625 0.0458101 0.353933 0.0697337 0.046166 0.4284 +0.062726 0.0458882 0.498198 0.058729 0.0454984 0.549459 0.0536661 0.0451134 0.609058 +0.0482 0.0448116 0.668397 0.0432737 0.0521325 0.319382 0.114666 0.041603 0.320426 +0.101127 0.0420205 0.393683 0.0420568 0.0512124 0.386874 0.0437448 0.0443789 0.724949 +0.0917926 0.0418477 0.466012 0.0385843 0.0505074 0.461387 0.0407709 0.0438022 0.773842 +0.079086 0.0470538 0.309259 0.08336 0.0415696 0.536821 0.0365677 0.049561 0.535369 +0.123324 0.0394605 0.358102 0.0353155 0.0438426 0.820179 0.0261384 0.0548969 0.302877 +0.106451 0.0402958 0.432595 0.0772781 0.04122 0.593782 0.0305752 0.0496414 0.59002 +0.0345075 0.0518446 0.419586 0.0330432 0.0431502 0.865423 0.0246783 0.0543504 0.35468 +0.100801 0.039521 0.501361 0.0713252 0.040838 0.650479 0.0286014 0.0515726 0.495145 +0.0238126 0.049925 0.644902 0.0279889 0.0435541 0.897751 0.0532187 0.0510424 0.297179 +0.0759499 0.0461089 0.382625 0.0862777 0.0403341 0.566207 0.0641386 0.0408717 0.700437 +0.0582896 0.0406382 0.750749 0.0263164 0.0484936 0.697737 0.135032 0.0389736 0.3046 +0.0251038 0.0477382 0.750051 0.0280443 0.050585 0.56097 0.0257268 0.0432828 0.928139 +0.00943751 0.0569978 0.286637 0.103807 0.0436767 0.297624 0.0662884 0.0461437 0.456921 +0.0792184 0.0400866 0.623652 0.0123266 0.0459687 0.983872 0.0230557 0.0431557 0.957786 +0.0221042 0.0465385 0.840517 0.0475388 0.0402354 0.841885 0.0555401 0.0495788 0.362577 +0.132689 0.0386343 0.333811 0.0259475 0.0500001 0.617482 0.0665701 0.0484856 0.331472 +0.0193644 0.0545153 0.398634 0.0742516 0.0395763 0.675724 0.0606338 0.0457036 0.524123 +0.112858 0.0386149 0.459545 0.0923774 0.0447726 0.326009 0.125248 0.0385626 0.383488 +0.0211429 0.0553181 0.324355 0.0526577 0.0404484 0.797884 0.0619927 0.0478294 0.404733 +0.0218 0.0498519 0.671488 0.102769 0.0423548 0.36719 0.120855 0.0385295 0.412454 +0.0311687 0.0394524 0.98307 0.0186655 0.0495688 0.724093 0.0228859 0.047307 0.795738 +0.0673488 0.0395023 0.725143 0.111016 0.0383345 0.482138 0.0889024 0.0434468 0.414888 +0.0163392 0.0552726 0.378093 0.0476224 0.0494009 0.442004 0.0560396 0.0453627 0.577908 +0.0271694 0.0550019 0.285512 0.103622 0.0378976 0.545009 0.086568 0.0431711 0.444412 +0.0625865 0.0388156 0.779093 0.103474 0.0384915 0.523886 0.0217417 0.0534459 0.446001 +0.0548034 0.0475615 0.479257 0.0786991 0.0474958 0.288652 0.0805607 0.0432209 0.485853 +0.0448263 0.0486459 0.509042 0.0199364 0.0526085 0.521001 0.0189259 0.0534793 0.474123 +0.0452058 0.0515064 0.340277 0.0945054 0.0376963 0.609223 0.050676 0.0450674 0.636115 +0.0794268 0.0428267 0.511573 0.0138356 0.0528132 0.577332 0.0191947 0.0485398 0.775093 +0.0115595 0.0569084 0.307064 0.0186413 0.0525292 0.540632 0.0425403 0.0399564 0.88657 +0.108148 0.0420641 0.343511 0.128395 0.0564793 0.185896 0.0246209 0.064882 0.177719 +0.0640623 0.0539112 0.25156 0.11183 0.0537715 0.223798 0.0493659 0.0636715 0.202232 +0.069136 0.0776205 0.143084 0.0281442 0.0761872 0.135773 0.0877029 0.0675421 0.177909 +0.0864358 0.0597066 0.21309 0.133075 0.0484932 0.230181 0.0166354 0.0579109 0.235783 +0.0604825 0.0722848 0.167916 0.109658 0.0487824 0.24792 0.156057 0.0466887 0.199743 +0.05276 0.0844451 0.121598 0.0982714 0.0614008 0.137149 0.0746033 0.0780682 0.114628 +0.0225497 0.0608803 0.202966 0.0250346 0.0566811 0.255175 0.0122508 0.062903 0.157092 +0.154086 0.0407613 0.248826 0.109542 0.0628162 0.163739 0.0635297 0.0592584 0.22359 +0.158069 0.043867 0.224115 0.00949932 0.0572114 0.258582 0.010879 0.0693824 0.117241 +0.1317 0.0440918 0.252844 0.104787 0.0613201 0.193916 0.0875843 0.0545648 0.235778 +0.0848339 0.0505359 0.256042 0.0721635 0.0653948 0.193663 0.134824 0.052106 0.208704 +0.0361148 0.0714734 0.161508 0.0296749 0.0829236 0.114416 0.0420176 0.0568852 0.243844 +0.0884052 0.0633156 0.112564 0.0875435 0.0711327 0.155747 0.0489346 0.0783433 0.144768 +0.0088982 0.063498 0.136062 0.0441192 0.0674781 0.182889 0.0844035 0.0718067 0.13116 +0.0408385 0.0599943 0.22181 0.00291088 0.059482 0.103719 0.00783528 0.0582871 0.181396 +0.0350051 0.0279219 0.21057 0.0829863 0.0166038 0.170073 0.0744413 0.0208797 0.192662 +0.00709261 0.0352746 0.235255 0.119526 0.0302663 0.235622 0.0290415 0.015033 0.139837 +0.0763604 0.0279303 0.229395 0.135858 0.0298535 0.222024 0.114077 0.0235501 0.192102 +0.0720814 0.0108303 0.133044 0.143892 0.0329601 0.245602 0.0320915 0.0239572 0.18256 +0.0462478 0.0307745 0.240904 0.00682001 0.0355577 0.254572 0.0999339 0.0251519 0.21107 +0.0113898 0.0220096 0.119232 0.0537712 0.0151323 0.16317 0.0484396 0.00502554 0.117594 +0.15521 0.0317366 0.209714 0.105695 0.0210392 0.162543 0.0943974 0.0227718 0.136759 +0.0128112 0.0276391 0.154814 0.0990364 0.030901 0.2457 0.0593462 0.0253156 0.211578 +0.0278299 0.0335392 0.257711 0.14318 0.0295324 0.189096 0.161152 0.0335382 0.232509 +0.0153677 0.0310542 0.195044 0.0724963 0.0317041 0.252624 0.0864366 0.0232152 0.114693 +0.0510934 0.021702 0.189479 0.0286374 0.0210907 0.163398 0.00288167 0.0325463 0.104439 +0.0697986 0.00929166 0.110608 0.0775499 0.0134581 0.152702 0.0257651 0.0317531 0.232108 +0.127794 0.0268688 0.174472 0.126237 0.0327618 0.252618 0.0269949 0.00880256 0.112151 +0.013754 0.0329166 0.215511 0.0948615 0.0204778 0.18656 0.0122138 0.0306294 0.175365 +0.0534432 0.00951911 0.140149 0.128765 0.026726 0.201489 0.00770515 0.0294092 0.136719 +0.0785048 0.0246456 0.211452 0.0510532 0.032892 0.259012 0.0657778 0.0177095 0.17741 +0.161707 0.0344658 0.254774 0.0692502 0.00713413 0.0454645 0.0219769 0.00713413 0.0454645 +0.0456136 0.000505102 0.0266597 0.0456136 0.000505102 0.0638129 0.0859207 0.0249492 0.035347 +0.00530641 0.0249492 0.035347 0.0842247 0.0219745 0.064065 0.0070024 0.0219745 0.064065 +0.0742764 0.0106815 0.0205968 0.0169507 0.0106815 0.0205968 0.0675722 0.006161 0.0689286 +0.0236549 0.006161 0.0689286 0.0879524 0.029421 0.015481 0.00327471 0.029421 0.015481 +0.0890093 0.032435 0.0795452 0.00221785 0.032435 0.0795452 0.0456136 0.0437578 1e-07 +0.0456136 0.0698562 1e-07 0.0456136 0.0220627 1e-07 0.0253171 0.0528441 1e-07 +0.06591 0.0528441 1e-07 0.0263136 0.0317434 1e-07 0.0649135 0.0317434 1e-07 + +CELLS 993 3851 +2 0 14 +2 0 18 +2 1 26 +2 1 111 +2 2 21 +2 3 22 +2 4 107 +2 5 29 +2 6 30 +2 7 31 +2 8 32 +2 9 33 +2 9 64 +2 10 101 +2 11 34 +2 11 35 +2 12 40 +2 12 88 +2 12 94 +2 13 93 +2 14 15 +2 15 16 +2 16 17 +2 17 1 +2 18 19 +2 19 20 +2 20 2 +2 21 3 +2 22 23 +2 23 24 +2 24 25 +2 25 4 +2 26 27 +2 27 28 +2 28 4 +2 29 6 +2 30 7 +2 31 8 +2 32 5 +2 33 10 +2 34 10 +2 35 36 +2 36 37 +2 37 38 +2 38 39 +2 39 12 +2 40 41 +2 41 42 +2 42 43 +2 43 44 +2 44 45 +2 45 46 +2 46 47 +2 47 48 +2 48 49 +2 49 50 +2 50 51 +2 51 52 +2 52 53 +2 53 54 +2 54 55 +2 55 56 +2 56 57 +2 57 58 +2 58 59 +2 59 60 +2 60 61 +2 61 62 +2 62 63 +2 63 8 +2 64 65 +2 65 66 +2 66 67 +2 67 68 +2 68 69 +2 69 70 +2 70 71 +2 71 72 +2 72 73 +2 73 74 +2 74 75 +2 75 76 +2 76 77 +2 77 78 +2 78 79 +2 79 80 +2 80 81 +2 81 82 +2 82 83 +2 83 84 +2 84 85 +2 85 86 +2 86 87 +2 87 6 +2 88 89 +2 89 90 +2 90 91 +2 91 92 +2 92 13 +2 93 9 +2 94 95 +2 95 96 +2 96 97 +2 97 98 +2 98 99 +2 99 100 +2 100 4 +2 101 102 +2 102 103 +2 103 104 +2 104 105 +2 105 106 +2 106 3 +2 107 108 +2 108 109 +2 109 110 +2 110 2 +2 111 112 +2 112 113 +2 113 114 +2 114 0 +3 0 128 14 +3 0 428 18 +3 0 436 114 +3 1 130 26 +3 1 427 111 +3 1 435 17 +3 1 437 435 +3 2 106 21 +3 2 398 106 +3 2 430 110 +3 3 20 21 +3 3 127 20 +3 3 364 22 +3 4 129 25 +3 4 357 100 +3 4 395 107 +3 4 429 28 +3 5 31 32 +3 5 271 29 +3 6 5 29 +3 6 7 5 +3 6 30 7 +3 6 176 30 +3 6 271 87 +3 7 31 5 +3 7 176 31 +3 8 196 63 +3 8 291 32 +3 9 171 64 +3 9 267 93 +3 9 346 101 +3 10 33 101 +3 10 171 33 +3 10 379 34 +3 11 171 34 +3 11 205 171 +3 11 390 35 +3 12 88 40 +3 12 342 88 +3 12 414 94 +3 13 300 92 +3 13 346 93 +3 14 123 15 +3 14 128 123 +3 14 434 0 +3 15 117 16 +3 15 123 117 +3 15 432 14 +3 16 126 17 +3 16 432 15 +3 17 126 122 +3 17 130 1 +3 17 432 16 +3 17 435 432 +3 18 128 0 +3 18 420 19 +3 18 428 420 +3 19 119 18 +3 19 121 119 +3 19 422 20 +3 20 121 19 +3 20 127 121 +3 20 430 2 +3 21 20 2 +3 21 106 3 +3 22 125 121 +3 22 127 3 +3 22 355 23 +3 22 364 347 +3 23 125 22 +3 23 336 24 +3 23 355 336 +3 24 118 23 +3 24 124 118 +3 24 338 25 +3 25 124 24 +3 25 129 124 +3 25 357 4 +3 26 122 27 +3 26 130 122 +3 26 427 1 +3 27 120 28 +3 27 122 120 +3 27 419 26 +3 27 421 419 +3 28 129 4 +3 28 421 27 +3 28 429 421 +3 29 271 6 +3 30 176 7 +3 31 8 32 +3 31 196 8 +3 32 271 5 +3 32 291 271 +3 33 171 9 +3 34 171 10 +3 34 379 11 +3 35 205 11 +3 35 412 36 +3 36 163 35 +3 36 212 163 +3 36 394 37 +3 36 412 394 +3 37 212 36 +3 37 388 38 +3 37 394 388 +3 38 173 37 +3 38 403 39 +3 39 12 40 +3 39 168 38 +3 39 403 376 +3 39 414 12 +3 40 168 39 +3 40 263 41 +3 41 168 40 +3 41 181 168 +3 41 276 42 +3 42 181 41 +3 42 189 148 +3 42 276 243 +3 42 284 43 +3 43 189 42 +3 43 195 189 +3 43 290 44 +3 44 195 43 +3 44 290 45 +3 45 187 151 +3 45 195 44 +3 45 282 46 +3 45 290 246 +3 46 187 45 +3 46 200 187 +3 46 295 47 +3 47 200 46 +3 47 209 157 +3 47 295 252 +3 47 304 48 +3 48 209 47 +3 48 301 49 +3 48 304 301 +3 49 206 48 +3 49 259 50 +3 49 301 259 +3 50 165 49 +3 50 218 152 +3 50 259 247 +3 50 313 51 +3 51 218 50 +3 51 270 52 +3 51 313 270 +3 52 175 51 +3 52 185 158 +3 52 270 253 +3 52 280 53 +3 53 185 52 +3 53 280 54 +3 54 185 53 +3 54 199 166 +3 54 280 260 +3 54 294 55 +3 55 199 54 +3 55 261 56 +3 55 294 261 +3 56 167 55 +3 56 208 167 +3 56 303 57 +3 57 208 56 +3 57 286 58 +3 57 303 286 +3 58 180 149 +3 58 192 57 +3 58 274 59 +3 58 286 244 +3 59 180 58 +3 59 250 60 +3 59 274 250 +3 60 155 59 +3 60 224 155 +3 60 320 61 +3 61 172 162 +3 61 224 60 +3 61 266 62 +3 61 320 256 +3 62 172 61 +3 62 177 172 +3 62 272 63 +3 63 177 62 +3 63 196 177 +3 63 291 8 +3 64 223 65 +3 64 267 9 +3 64 318 267 +3 65 156 66 +3 65 191 156 +3 65 223 191 +3 65 318 64 +3 66 202 67 +3 66 251 65 +3 66 297 251 +3 67 184 68 +3 67 202 184 +3 67 297 66 +3 68 184 154 +3 68 210 69 +3 68 279 67 +3 68 305 249 +3 69 215 70 +3 69 305 68 +3 69 311 305 +3 70 215 71 +3 70 311 69 +3 71 215 159 +3 71 216 72 +3 71 310 254 +3 71 311 70 +3 72 225 73 +3 72 310 71 +3 72 319 310 +3 73 221 74 +3 73 225 170 +3 73 316 265 +3 73 319 72 +3 74 182 75 +3 74 221 153 +3 74 277 248 +3 74 316 73 +3 75 161 76 +3 75 182 161 +3 75 277 74 +3 76 188 77 +3 76 255 75 +3 76 288 255 +3 77 160 78 +3 77 188 160 +3 77 288 76 +3 78 197 79 +3 78 262 77 +3 78 292 262 +3 79 169 80 +3 79 197 169 +3 79 292 78 +3 80 222 81 +3 80 264 79 +3 80 317 264 +3 81 198 82 +3 81 222 198 +3 81 317 80 +3 82 179 83 +3 82 198 149 +3 82 273 244 +3 82 293 81 +3 83 155 84 +3 83 179 155 +3 83 273 82 +3 84 162 85 +3 84 250 83 +3 84 256 250 +3 85 172 86 +3 85 256 84 +3 85 266 256 +3 86 177 87 +3 86 266 85 +3 86 272 266 +3 87 176 6 +3 87 177 176 +3 87 272 86 +3 88 263 40 +3 88 348 89 +3 89 263 88 +3 89 268 263 +3 89 334 90 +3 89 348 334 +3 90 268 89 +3 90 307 268 +3 90 351 91 +3 91 307 90 +3 91 324 92 +3 91 351 324 +3 92 257 91 +3 92 300 257 +3 92 340 13 +3 92 356 340 +3 93 267 13 +3 93 346 9 +3 94 342 12 +3 94 345 342 +3 94 392 95 +3 94 414 392 +3 95 345 94 +3 95 384 96 +3 95 392 384 +3 96 335 95 +3 96 391 97 +3 97 335 96 +3 97 391 98 +3 98 322 97 +3 98 343 322 +3 98 385 99 +3 98 402 385 +3 99 343 98 +3 99 386 100 +3 100 337 99 +3 100 357 337 +3 100 395 4 +3 101 33 9 +3 101 332 102 +3 101 346 332 +3 101 379 10 +3 102 339 103 +3 102 369 101 +3 102 405 369 +3 103 365 104 +3 103 405 102 +3 103 407 393 +3 104 341 105 +3 104 365 341 +3 104 407 103 +3 105 360 106 +3 105 387 104 +3 105 410 387 +3 106 360 347 +3 106 364 3 +3 106 398 381 +3 106 410 105 +3 107 399 108 +3 107 425 421 +3 107 429 4 +3 108 383 109 +3 108 399 383 +3 108 425 107 +3 109 404 110 +3 109 418 108 +3 109 426 418 +3 110 398 2 +3 110 404 381 +3 110 426 109 +3 110 430 422 +3 111 423 112 +3 111 427 423 +3 111 437 1 +3 112 417 113 +3 112 423 417 +3 112 437 111 +3 113 424 114 +3 113 433 112 +3 113 436 433 +3 114 428 0 +3 114 436 113 +3 115 118 117 +3 115 123 119 +3 115 125 118 +3 116 124 120 +3 116 126 117 +3 117 118 116 +3 117 123 115 +3 117 126 16 +3 118 124 116 +3 118 125 23 +3 119 121 115 +3 119 128 18 +3 120 122 116 +3 120 129 28 +3 121 125 115 +3 121 127 22 +3 122 126 116 +3 122 130 17 +3 123 128 119 +3 124 129 120 +3 131 190 148 +3 131 194 164 +3 132 203 154 +3 132 207 174 +3 133 214 211 +3 133 220 186 +3 134 170 147 +3 134 186 146 +3 134 204 170 +3 135 182 153 +3 135 204 152 +3 135 219 182 +3 136 166 160 +3 136 185 166 +3 136 188 161 +3 136 219 158 +3 137 191 150 +3 137 217 191 +3 138 173 168 +3 138 181 148 +3 138 190 173 +3 139 178 164 +3 139 193 154 +3 139 202 156 +3 140 194 189 +3 140 201 164 +3 141 197 160 +3 141 199 167 +3 142 207 187 +3 142 213 174 +3 143 203 174 +3 143 210 203 +3 143 211 159 +3 143 215 210 +3 144 169 167 +3 144 208 192 +3 144 222 169 +3 145 183 163 +3 145 190 183 +3 145 212 173 +3 146 165 134 +3 146 206 165 +3 146 209 206 +3 146 220 209 +3 147 186 134 +3 147 214 186 +3 147 216 214 +3 147 225 216 +3 148 181 42 +3 148 190 138 +3 148 194 131 +3 149 179 82 +3 149 180 179 +3 149 192 58 +3 149 198 192 +3 150 163 137 +3 150 205 163 +3 150 223 171 +3 151 195 45 +3 151 201 195 +3 151 207 201 +3 152 165 50 +3 152 175 135 +3 152 204 165 +3 152 218 175 +3 153 182 74 +3 153 204 135 +3 153 221 170 +3 154 184 139 +3 154 193 132 +3 154 210 68 +3 155 162 84 +3 155 180 59 +3 155 224 162 +3 156 178 139 +3 156 202 66 +3 156 217 178 +3 157 200 47 +3 157 213 200 +3 157 220 213 +3 158 175 52 +3 158 185 136 +3 158 219 175 +3 159 215 143 +3 159 216 71 +3 160 166 141 +3 160 188 136 +3 160 197 78 +3 161 188 76 +3 161 219 136 +3 162 172 85 +3 162 224 61 +3 163 183 137 +3 163 205 35 +3 163 212 145 +3 164 178 131 +3 164 193 139 +3 164 194 140 +3 164 201 193 +3 165 204 134 +3 165 206 49 +3 166 185 54 +3 166 199 141 +3 167 169 141 +3 167 199 55 +3 167 208 144 +3 168 173 38 +3 168 181 138 +3 169 197 141 +3 169 222 80 +3 170 204 153 +3 170 221 73 +3 170 225 147 +3 171 205 150 +3 171 223 64 +3 172 177 86 +3 173 190 145 +3 173 212 37 +3 174 203 132 +3 174 207 142 +3 174 211 143 +3 174 213 211 +3 175 218 51 +3 175 219 135 +3 176 196 31 +3 177 196 176 +3 178 183 131 +3 178 217 183 +3 179 180 155 +3 182 219 161 +3 183 190 131 +3 183 217 137 +3 184 202 139 +3 186 214 133 +3 186 220 146 +3 187 200 142 +3 187 207 151 +3 189 194 148 +3 189 195 140 +3 191 217 156 +3 191 223 150 +3 192 198 144 +3 192 208 57 +3 193 201 132 +3 195 201 140 +3 198 222 144 +3 200 213 142 +3 201 207 132 +3 203 210 154 +3 206 209 48 +3 209 220 157 +3 210 215 69 +3 211 213 133 +3 211 214 159 +3 213 220 133 +3 214 216 159 +3 216 225 72 +3 226 275 258 +3 226 278 275 +3 226 283 278 +3 226 321 283 +3 227 287 249 +3 227 296 287 +3 227 298 269 +3 227 302 296 +3 228 308 306 +3 228 309 281 +3 228 315 308 +3 229 259 241 +3 229 281 242 +3 229 299 259 +3 230 270 247 +3 230 299 248 +3 230 314 270 +3 231 262 260 +3 231 280 253 +3 231 288 262 +3 231 314 255 +3 232 257 245 +3 232 278 257 +3 232 312 278 +3 233 276 263 +3 233 321 276 +3 234 289 258 +3 234 290 284 +3 234 296 290 +3 235 275 251 +3 235 279 249 +3 235 287 258 +3 235 297 279 +3 236 264 261 +3 236 292 264 +3 236 294 260 +3 237 295 282 +3 237 302 269 +3 237 308 295 +3 238 306 269 +3 238 311 254 +3 239 293 286 +3 239 303 261 +3 239 317 293 +3 240 283 268 +3 240 307 257 +3 241 281 229 +3 241 315 281 +3 242 265 229 +3 242 319 265 +3 243 284 42 +3 243 289 284 +3 243 321 289 +3 244 274 58 +3 244 293 82 +3 245 285 232 +3 245 300 267 +3 245 318 285 +3 246 282 45 +3 246 302 282 +3 247 299 230 +3 247 313 50 +3 248 277 230 +3 248 299 265 +3 248 316 74 +3 249 279 68 +3 249 287 235 +3 249 298 227 +3 249 305 298 +3 250 273 83 +3 250 274 273 +3 250 320 60 +3 251 285 65 +3 251 297 235 +3 251 312 285 +3 252 304 47 +3 252 315 304 +3 253 280 52 +3 253 314 231 +3 254 306 238 +3 254 309 306 +3 254 310 309 +3 254 311 71 +3 255 277 75 +3 255 288 231 +3 255 314 277 +3 256 266 61 +3 256 320 250 +3 257 278 240 +3 257 300 245 +3 257 307 91 +3 258 275 235 +3 258 289 226 +3 258 296 234 +3 259 299 247 +3 259 301 241 +3 260 262 236 +3 260 280 231 +3 260 294 54 +3 261 264 239 +3 261 294 236 +3 261 303 56 +3 262 288 77 +3 262 292 236 +3 263 268 233 +3 263 276 41 +3 264 292 79 +3 264 317 239 +3 265 299 229 +3 265 316 248 +3 265 319 73 +3 266 272 62 +3 267 300 13 +3 267 318 245 +3 268 283 233 +3 268 307 240 +3 269 298 238 +3 269 302 227 +3 269 308 237 +3 270 313 247 +3 270 314 253 +3 271 272 87 +3 271 291 272 +3 272 291 63 +3 273 274 244 +3 275 312 251 +3 276 321 243 +3 277 314 230 +3 278 283 240 +3 278 312 275 +3 279 297 67 +3 281 309 242 +3 281 315 228 +3 282 295 46 +3 282 302 237 +3 283 321 233 +3 284 289 234 +3 284 290 43 +3 285 312 232 +3 285 318 65 +3 286 293 244 +3 286 303 239 +3 287 296 258 +3 289 321 226 +3 290 296 246 +3 293 317 81 +3 295 308 252 +3 296 302 246 +3 298 305 238 +3 301 304 241 +3 304 315 241 +3 305 311 238 +3 306 308 269 +3 306 309 228 +3 308 315 252 +3 309 310 242 +3 310 319 242 +3 322 335 97 +3 322 353 335 +3 323 354 341 +3 323 361 354 +3 323 365 339 +3 324 350 344 +3 324 351 350 +3 324 356 92 +3 325 334 331 +3 325 349 330 +3 325 350 334 +3 325 353 349 +3 326 361 339 +3 326 363 344 +3 327 338 336 +3 327 359 333 +3 327 362 338 +3 328 355 347 +3 328 359 336 +3 328 360 341 +3 329 349 343 +3 329 352 349 +3 329 358 333 +3 330 350 325 +3 330 352 344 +3 331 348 342 +3 331 353 325 +3 332 339 102 +3 332 346 340 +3 332 363 339 +3 333 352 329 +3 333 358 327 +3 333 359 354 +3 333 361 352 +3 334 348 331 +3 334 351 90 +3 335 345 95 +3 335 353 345 +3 336 338 24 +3 336 355 328 +3 336 359 327 +3 337 343 99 +3 337 358 343 +3 337 362 358 +3 338 357 25 +3 338 362 357 +3 339 361 323 +3 339 363 326 +3 339 365 103 +3 340 346 13 +3 340 356 332 +3 341 354 328 +3 341 360 105 +3 341 365 323 +3 342 345 331 +3 342 348 88 +3 343 349 322 +3 343 358 329 +3 344 350 330 +3 344 352 326 +3 344 356 324 +3 344 363 356 +3 345 353 331 +3 347 355 22 +3 347 360 328 +3 347 364 106 +3 349 352 330 +3 349 353 322 +3 350 351 334 +3 352 361 326 +3 354 359 328 +3 354 361 333 +3 356 363 332 +3 357 362 337 +3 358 362 327 +3 366 389 378 +3 366 393 377 +3 366 396 389 +3 366 405 393 +3 367 400 385 +3 367 406 368 +3 367 413 382 +3 368 406 380 +3 368 411 389 +3 368 413 367 +3 369 379 101 +3 369 401 379 +3 369 405 401 +3 370 380 373 +3 370 388 380 +3 370 403 388 +3 371 397 387 +3 371 404 383 +3 371 408 382 +3 371 410 381 +3 372 394 378 +3 372 411 380 +3 373 376 370 +3 373 392 376 +3 373 409 384 +3 374 406 385 +3 374 409 380 +3 375 395 386 +3 375 399 395 +3 375 408 383 +3 376 403 370 +3 376 414 39 +3 377 396 366 +3 377 397 382 +3 377 407 397 +3 378 389 372 +3 378 401 366 +3 378 412 390 +3 379 390 11 +3 379 401 390 +3 380 388 372 +3 380 406 374 +3 380 409 373 +3 380 411 368 +3 381 398 110 +3 381 404 371 +3 381 410 106 +3 382 396 377 +3 382 397 371 +3 382 400 367 +3 382 408 400 +3 382 413 396 +3 383 399 375 +3 383 404 109 +3 383 408 371 +3 384 391 96 +3 384 392 373 +3 384 409 391 +3 385 386 99 +3 385 400 386 +3 385 402 374 +3 385 406 367 +3 386 395 100 +3 386 400 375 +3 387 407 104 +3 387 410 371 +3 388 394 372 +3 388 403 38 +3 389 396 368 +3 389 411 372 +3 390 401 378 +3 390 412 35 +3 391 402 98 +3 391 409 402 +3 392 414 376 +3 393 405 103 +3 393 407 377 +3 394 412 378 +3 395 399 107 +3 396 413 368 +3 397 407 387 +3 400 408 375 +3 401 405 366 +3 402 409 374 +3 415 418 417 +3 415 423 419 +3 415 425 418 +3 416 422 420 +3 416 424 417 +3 416 426 422 +3 417 418 416 +3 417 423 415 +3 417 424 113 +3 418 425 108 +3 418 426 416 +3 419 421 415 +3 419 427 26 +3 420 422 19 +3 420 424 416 +3 420 428 424 +3 421 425 415 +3 421 429 107 +3 422 426 110 +3 422 430 20 +3 423 427 419 +3 424 428 114 +3 431 434 432 +3 431 436 434 +3 431 437 433 +3 432 434 14 +3 432 435 431 +3 433 436 431 +3 433 437 112 +3 434 436 0 +3 435 437 431 + +CELL_TYPES 993 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 + +POINT_DATA 438 +SCALARS scalars double +LOOKUP_TABLE default +1.6755246382 0.9791806223 0.9791806223 0.97594938187 0.12925491957 0.32674332908 0.2776476709 0.26537269646 0.54790553034 +-0.21848899462 -0.21871453724 -0.21891455992 0.84665342709 -0.17856744253 1.4657434747 1.135295639 0.86221409635 0.80015646753 +1.5522257846 1.3892109713 1.194864132 0.97756806161 0.62351150718 0.25873103587 0.043676132717 0.0036947001056 0.75325315321 +0.52870128787 0.3170738414 0.30551630372 0.26085193696 0.40221609491 0.43492101536 -0.21860483282 -0.21999990002 -0.17179908702 +-0.058158766325 0.11406364917 0.33283088172 0.58285245978 1.0812401593 1.2986601063 1.4865231487 1.6341235277 1.7330499344 +1.7776648458 1.76542579 1.6970302345 1.5763758398 1.4103383427 1.2083797289 0.98200902193 0.74412641865 0.50828814461 +0.28793392513 0.095621095082 -0.057691006459 -0.16326557653 -0.2150862328 -0.21019986942 -0.14888494579 -0.034635617958 0.12603738299 +0.32397777821 -0.16077576716 -0.02400712404 0.18032386837 0.43504686237 0.71875696815 1.0076134501 1.2773431122 1.5052800239 +1.6722701842 1.7642810712 1.7735808236 1.6993879641 1.5479370694 1.3319548652 1.0695907743 0.78289178324 0.49594978977 +0.23287711157 0.015780279339 -0.13709761979 -0.21290994591 -0.20528603548 -0.11486654116 0.050750403557 0.62258815746 0.40644230393 +0.2090902005 0.040460664451 -0.090962524082 -0.20430773504 0.69810823114 0.46983854429 0.17526328013 -0.071983623309 -0.20353805407 +-0.20206347466 -0.070749910509 -0.19823053745 -0.11210076093 0.033914302466 0.23002576773 0.46307296426 0.71740811854 0.43280230672 +0.817804103 1.0933668947 1.1517427527 1.3065231917 1.5916084598 1.7217590887 1.7408274774 0.82776281929 0.36881870492 +0.71230316511 0.35370086918 1.2545105476 0.2886410948 0.93968205698 0.5430800996 1.1634248179 0.14493383167 0.56814700099 +0.59876763048 0.93603648866 1.4676191343 0.14520593653 0.75223127193 0.75616927578 1.3570237577 1.7282221487 1.768296739 +1.543121533 1.1002912641 0.099436130411 0.80378264345 0.70549326191 1.3289671025 0.59115044346 1.71691781 1.3745290533 +0.16552489742 0.31011739066 1.7438062065 1.7585555214 1.1391874861 -0.099528237524 -0.10541046472 1.6346682663 1.4900703259 +1.7398187046 0.95392866253 -0.21791242411 0.23081184222 1.7761987877 1.0561939282 1.5487600505 1.0305112263 1.4944798645 +-0.19730918942 0.014956310347 0.99059585945 1.6090416854 0.63017894114 0.218974833 0.80523893907 0.51023000968 1.7794288023 +-0.21362877479 -0.098854652254 0.43229585504 1.5428825212 1.2341282762 0.18920272181 0.063008889303 0.58920818213 -0.13535473803 +-0.20643217259 1.1196436528 1.6490393121 0.39772693916 0.59256001834 0.77884705263 1.7765589199 1.7576846815 1.3036805094 +1.4345024337 0.63514744765 -0.01678806157 -0.069083799098 1.0743353811 1.1088231691 1.6033326464 0.31492409529 0.82838938663 +0.12667992895 0.36586886253 1.7799932744 1.4023225804 0.36632022564 1.2866268824 1.6959778155 -0.17118726317 1.6312687018 +1.5902320806 -0.015743911305 1.7229314992 1.0887020743 1.6096199758 0.13504773148 1.7438324768 1.704205237 1.3179407721 +1.6488844705 0.28229588155 1.2292877294 1.3652558854 1.7797419949 1.7799736926 0.32660193937 -0.14857625197 -0.19318715181 +1.7261871417 0.88149061682 1.4473245409 1.7569640386 1.7479946948 1.4801518862 1.0175973182 0.24499749617 0.83453440776 +1.3898875271 0.86892437814 0.50677447872 1.7391916833 1.4920404464 0.11300809901 0.42922325338 1.7246326274 1.7776746585 +1.2563308179 -0.12837985231 0.013566551382 1.6624405022 1.4477489815 1.6934234131 1.1200723305 -0.21996287145 0.41344759264 +1.771083354 1.0055997763 1.6428074195 1.3990938472 -0.18425966531 0.13731969225 1.1082452004 1.5790984093 0.58084386183 +0.18057236399 0.90815905874 0.85360791763 0.41377935163 1.7736443524 -0.074241689906 -0.14524075666 0.521643864 1.6111344192 +1.1917860173 0.23708534415 0.094272041664 -0.16500712297 -0.21179598795 0.74457890718 1.1125026041 1.5754111433 0.53539018111 +0.79274350764 0.73847656099 1.7797706563 1.7650717214 0.69929284005 1.4693524192 0.13255190696 -0.090351929446 1.1997430842 +1.1901158033 1.1792988096 1.6246975813 0.337252558 0.71076199938 0.058942219385 0.33072061936 1.7794977764 1.4689112865 +0.5663189088 1.4071422981 1.6527829934 -0.080145739764 1.6153087313 1.6368475839 -0.033979523542 1.7103858036 1.2589836748 +1.6729395153 0.24549567056 1.7625958327 1.7468898672 1.7201509478 1.4637557301 0.44416086788 1.2056952443 1.2901823677 +1.7784833959 1.7677601099 0.23675999889 -0.037509956098 1.7663918651 -0.18485835219 1.002960334 -0.06399401006 -0.11185220825 +-0.070564436228 0.049950891449 -0.21993836094 -0.1905761892 0.041904725996 -0.20201496073 -0.12012930056 0.21957407853 -0.21926649414 +-0.2109343558 0.17578154702 0.14538989568 -0.070657042564 -0.20500676229 -0.11220294001 -0.18170780144 -0.19427581245 0.097148401664 +0.50782195574 -0.1960329718 -0.16854643533 0.34334045381 -0.21380838161 0.38669486359 0.3667390324 -0.11665864704 -0.023480843639 +0.063846929002 -0.20547901802 0.093947282682 -0.12017273084 0.1362833736 -0.17941664701 -0.098183556822 -0.21999652153 -0.1326245497 +0.28852059281 -0.20071087347 -0.18433135291 -0.21640360191 0.6897982209 -0.0060467306925 -0.13846275424 -0.12262685283 -0.18593564673 +-0.15399017286 0.02330796696 0.51488783435 -0.20099717127 0.038680779693 -0.20790340614 0.22466803905 0.31127048843 0.0520766098 +-0.21929050506 -0.20522718424 -0.19590491714 0.82446257655 0.098402813951 0.64065491661 0.1014550813 -0.18920247315 -0.044031358276 +0.40736851786 -0.036898941538 -0.20398719783 -0.21878957394 -0.1086107117 0.35369402577 0.032782061029 -0.13035763529 0.15693975984 +-0.088392072579 0.24841639767 0.95127553474 0.45956714543 0.018058574871 -0.19005803317 -0.20880810213 0.21847905021 0.87118797993 +-0.08792775363 -0.21249416497 0.20607549398 0.33577081443 -0.12970873945 0.61324079458 -0.21999016626 -0.17882033382 -0.08147794362 +0.57847450784 1.1250649613 1.5145759826 1.5266505277 1.2342063851 0.8884139771 1.5724226036 0.64853558408 1.3774977766 +1.2727516235 1.6659353358 0.92367986192 1.330824123 1.0198891011 1.6661772356 0.35487652417 1.1957940535 1.4065210616 +1.1841940863 1.5596037725 1.4897786446 1.1539404317 1.6161497311 1.3481254901 diff --git a/examples/fine_mesh.vtk b/examples/fine_mesh.vtk new file mode 100644 index 00000000..eb9f468b --- /dev/null +++ b/examples/fine_mesh.vtk @@ -0,0 +1,16014 @@ +# vtk DataFile Version 4.2 +vtk output +ASCII +DATASET UNSTRUCTURED_GRID +POINTS 3458 float +0.000159205 0.0459595 1e-07 0.0910679 0.0459595 1e-07 0.000159205 0.0459595 0.0909088 +0.00016037 0.0462879 0.0909088 0.0910679 0.0459595 0.0909088 0.00387147 0.0486486 0.999996 +0.000160265 0.0467696 0.999996 0.00230119 0.0432031 0.999996 0.0412046 0.0349339 0.999996 +0.000161941 0.0467691 0.272726 0.000140272 0.0463638 0.272726 0.0114969 0.0345959 0.272726 +0.170587 0.0345959 0.272726 0.013112 0.0572077 0.272726 0.00115249 0.0554099 1e-07 +0.00408894 0.0644474 1e-07 0.00884021 0.0726769 1e-07 0.0151987 0.0797386 1e-07 +0.0228864 0.0853241 1e-07 0.0315674 0.0891891 1e-07 0.0408623 0.0911648 1e-07 +0.0503648 0.0911648 1e-07 0.0596597 0.0891891 1e-07 0.0683407 0.0853241 1e-07 +0.0760285 0.0797386 1e-07 0.0823869 0.0726769 1e-07 0.0871382 0.0644474 1e-07 +0.0900746 0.0554099 1e-07 0.000159205 0.0459595 0.00909097 0.000159205 0.0459595 0.0181818 +0.000159205 0.0459595 0.0272727 0.000159205 0.0459595 0.0363636 0.000159205 0.0459595 0.0454544 +0.000159205 0.0459595 0.0545453 0.000159205 0.0459595 0.0636362 0.000159205 0.0459595 0.0727271 +0.000159205 0.0459595 0.0818179 0.000159502 0.0461237 0.0909088 0.00121724 0.0557096 0.0909088 +0.00420554 0.0647071 0.0909088 0.00899528 0.072889 0.0909088 0.0153781 0.0798993 0.0909088 +0.0230763 0.0854331 0.0909088 0.031755 0.0892496 0.0909088 0.0410365 0.0911828 0.0909088 +0.0505172 0.0911485 0.0909088 0.0597846 0.0891483 0.0909088 0.0684355 0.0852692 0.0909088 +0.0760935 0.07968 0.0909088 0.0824255 0.0726237 0.0909088 0.087156 0.0644074 0.0909088 +0.0900792 0.0553885 0.0909088 0.0910679 0.0459595 0.00909097 0.0910679 0.0459595 0.0181818 +0.0910679 0.0459595 0.0272727 0.0910679 0.0459595 0.0363636 0.0910679 0.0459595 0.0454544 +0.0910679 0.0459595 0.0545453 0.0910679 0.0459595 0.0636362 0.0910679 0.0459595 0.0727271 +0.0910679 0.0459595 0.0818179 0.00160779 0.0485161 0.999996 0.000455632 0.0445206 0.999996 +0.0120271 0.0411358 0.999996 0.0217529 0.0390685 0.999996 0.0314788 0.0370012 0.999996 +0.0318713 0.0383626 0.999996 0.022538 0.0417913 0.999996 0.0132048 0.0452199 0.999996 +0.000149524 0.0465665 0.272726 0.00331992 0.0380684 0.272726 0.02144 0.0345959 0.272726 +0.0313832 0.0345959 0.272726 0.0413263 0.0345959 0.272726 0.0512694 0.0345959 0.272726 +0.0612126 0.0345959 0.272726 0.0711557 0.0345959 0.272726 0.0810989 0.0345959 0.272726 +0.091042 0.0345959 0.272726 0.100985 0.0345959 0.272726 0.110928 0.0345959 0.272726 +0.120871 0.0345959 0.272726 0.130815 0.0345959 0.272726 0.140758 0.0345959 0.272726 +0.150701 0.0345959 0.272726 0.160644 0.0345959 0.272726 0.168839 0.0346004 0.282554 +0.16709 0.034605 0.292382 0.165342 0.0346096 0.30221 0.163593 0.0346141 0.312038 +0.161845 0.0346187 0.321866 0.160097 0.0346233 0.331694 0.158348 0.0346278 0.341522 +0.1566 0.0346324 0.35135 0.154851 0.034637 0.361178 0.153103 0.0346416 0.371006 +0.151355 0.0346461 0.380834 0.149606 0.0346507 0.390662 0.147858 0.0346553 0.40049 +0.146109 0.0346598 0.410318 0.144361 0.0346644 0.420146 0.142613 0.034669 0.429974 +0.140864 0.0346735 0.439802 0.139116 0.0346781 0.44963 0.137367 0.0346827 0.459458 +0.135619 0.0346872 0.469286 0.13387 0.0346918 0.479114 0.132122 0.0346964 0.488941 +0.130374 0.0347009 0.498769 0.128625 0.0347055 0.508597 0.126877 0.0347101 0.518425 +0.125128 0.0347147 0.528253 0.12338 0.0347192 0.538081 0.121632 0.0347238 0.547909 +0.119883 0.0347284 0.557737 0.118135 0.0347329 0.567565 0.116386 0.0347375 0.577393 +0.114638 0.0347421 0.587221 0.11289 0.0347466 0.597049 0.111141 0.0347512 0.606877 +0.109393 0.0347558 0.616705 0.107644 0.0347603 0.626533 0.105896 0.0347649 0.636361 +0.104147 0.0347695 0.646189 0.102399 0.034774 0.656017 0.100651 0.0347786 0.665845 +0.0989022 0.0347832 0.675673 0.0971538 0.0347877 0.685501 0.0954054 0.0347923 0.695329 +0.093657 0.0347969 0.705157 0.0919086 0.0348015 0.714985 0.0901602 0.034806 0.724813 +0.0884117 0.0348106 0.734641 0.0866633 0.0348152 0.744469 0.0849149 0.0348197 0.754297 +0.0831665 0.0348243 0.764125 0.0814181 0.0348289 0.773953 0.0796697 0.0348334 0.783781 +0.0779213 0.034838 0.793608 0.0761729 0.0348426 0.803436 0.0744245 0.0348471 0.813264 +0.072676 0.0348517 0.823092 0.0709276 0.0348563 0.83292 0.0691792 0.0348608 0.842748 +0.0674308 0.0348654 0.852576 0.0656824 0.03487 0.862404 0.063934 0.0348746 0.872232 +0.0621856 0.0348791 0.88206 0.0604372 0.0348837 0.891888 0.0586887 0.0348883 0.901716 +0.0569403 0.0348928 0.911544 0.0551919 0.0348974 0.921372 0.0534435 0.034902 0.9312 +0.0516951 0.0349065 0.941028 0.0499467 0.0349111 0.950856 0.0481983 0.0349157 0.960684 +0.0464499 0.0349202 0.970512 0.0447014 0.0349248 0.98034 0.042953 0.0349294 0.990168 +0.000161687 0.0467691 0.282689 0.000161667 0.0467691 0.292651 0.000161647 0.0467691 0.302614 +0.000161627 0.0467691 0.312577 0.000161608 0.0467691 0.322539 0.000161588 0.0467692 0.332502 +0.000161568 0.0467692 0.342464 0.000161548 0.0467692 0.352427 0.000161529 0.0467692 0.36239 +0.000161509 0.0467692 0.372352 0.000161489 0.0467692 0.382315 0.000161469 0.0467692 0.392277 +0.00016145 0.0467692 0.40224 0.00016143 0.0467692 0.412203 0.00016141 0.0467692 0.422165 +0.00016139 0.0467692 0.432128 0.000161371 0.0467692 0.44209 0.000161351 0.0467692 0.452053 +0.000161331 0.0467692 0.462016 0.000161311 0.0467693 0.471978 0.000161292 0.0467693 0.481941 +0.000161272 0.0467693 0.491903 0.000161252 0.0467693 0.501866 0.000161232 0.0467693 0.511829 +0.000161213 0.0467693 0.521791 0.000161193 0.0467693 0.531754 0.000161173 0.0467693 0.541716 +0.000161153 0.0467693 0.551679 0.000161134 0.0467693 0.561642 0.000161114 0.0467693 0.571604 +0.000161094 0.0467693 0.581567 0.000161074 0.0467693 0.591529 0.000161055 0.0467693 0.601492 +0.000161035 0.0467694 0.611455 0.000161015 0.0467694 0.621417 0.000160995 0.0467694 0.63138 +0.000160976 0.0467694 0.641342 0.000160956 0.0467694 0.651305 0.000160936 0.0467694 0.661268 +0.000160916 0.0467694 0.67123 0.000160897 0.0467694 0.681193 0.000160877 0.0467694 0.691155 +0.000160857 0.0467694 0.701118 0.000160837 0.0467694 0.71108 0.000160818 0.0467694 0.721043 +0.000160798 0.0467694 0.731006 0.000160778 0.0467694 0.740968 0.000160759 0.0467694 0.750931 +0.000160739 0.0467695 0.760893 0.000160719 0.0467695 0.770856 0.000160699 0.0467695 0.780819 +0.00016068 0.0467695 0.790781 0.00016066 0.0467695 0.800744 0.00016064 0.0467695 0.810706 +0.00016062 0.0467695 0.820669 0.000160601 0.0467695 0.830632 0.000160581 0.0467695 0.840594 +0.000160561 0.0467695 0.850557 0.000160541 0.0467695 0.860519 0.000160522 0.0467695 0.870482 +0.000160502 0.0467695 0.880445 0.000160482 0.0467695 0.890407 0.000160462 0.0467696 0.90037 +0.000160443 0.0467696 0.910332 0.000160423 0.0467696 0.920295 0.000160403 0.0467696 0.930258 +0.000160383 0.0467696 0.94022 0.000160364 0.0467696 0.950183 0.000160344 0.0467696 0.960145 +0.000160324 0.0467696 0.970108 0.000160304 0.0467696 0.980071 0.000160285 0.0467696 0.990033 +0.160745 0.0360091 0.272726 0.150903 0.0374223 0.272726 0.141061 0.0388356 0.272726 +0.131218 0.0402488 0.272726 0.121376 0.0416621 0.272726 0.111534 0.0430753 0.272726 +0.101692 0.0444885 0.272726 0.0918496 0.0459018 0.272726 0.0820074 0.047315 0.272726 +0.0721652 0.0487282 0.272726 0.062323 0.0501415 0.272726 0.0524808 0.0515547 0.272726 +0.0426386 0.052968 0.272726 0.0327964 0.0543812 0.272726 0.0229542 0.0557944 0.272726 +0.00436536 0.0548066 0.272726 0.174681 0.0349195 0.263626 0.178196 0.0352748 0.254289 +0.180959 0.0356682 0.244705 0.182732 0.0361064 0.234894 0.183217 0.0365949 0.224942 +0.1821 0.0371336 0.215047 0.179194 0.037712 0.205527 0.174588 0.0383101 0.196702 +0.168627 0.038908 0.188724 0.16173 0.0394943 0.181534 0.154249 0.0400661 0.174948 +0.146442 0.0406254 0.168749 0.138499 0.0411762 0.162722 0.130578 0.041723 0.156667 +0.122832 0.0422698 0.150391 0.115434 0.0428192 0.14371 0.108597 0.043372 0.136459 +0.102579 0.0439251 0.128518 0.0976588 0.0444711 0.119856 0.094063 0.044999 0.110566 +0.0918865 0.0454975 0.100843 0.000144283 0.0463598 0.263157 0.000147801 0.0463558 0.253588 +0.000150853 0.0463518 0.244018 0.00015347 0.0463478 0.234449 0.00015568 0.0463438 0.22488 +0.000157514 0.0463398 0.21531 0.000158999 0.0463358 0.205741 0.000160167 0.0463318 0.196172 +0.000161045 0.0463278 0.186602 0.000161663 0.0463238 0.177033 0.000162051 0.0463198 0.167463 +0.000162238 0.0463159 0.157894 0.000162252 0.0463119 0.148325 0.000162124 0.0463079 0.138755 +0.000161883 0.0463039 0.129186 0.000161558 0.0462999 0.119617 0.000161177 0.0462959 0.110047 +0.000160772 0.0462919 0.100478 0.0900746 0.036509 0.0909088 0.0871382 0.0274715 0.0909088 +0.0823869 0.0192421 0.0909088 0.0760285 0.0121803 0.0909088 0.0683407 0.00659483 0.0909088 +0.0596597 0.0027298 0.0909088 0.0503648 0.000754106 0.0909088 0.0408623 0.000754106 0.0909088 +0.0315674 0.0027298 0.0909088 0.0228864 0.00659483 0.0909088 0.0151987 0.0121803 0.0909088 +0.00884021 0.0192421 0.0909088 0.00408894 0.0274715 0.0909088 0.00115249 0.036509 0.0909088 +0.0900746 0.036509 1e-07 0.0871382 0.0274715 1e-07 0.0823869 0.0192421 1e-07 +0.0760285 0.0121803 1e-07 0.0683407 0.00659483 1e-07 0.0596597 0.0027298 1e-07 +0.0503648 0.000754106 1e-07 0.0408623 0.000754106 1e-07 0.0315674 0.0027298 1e-07 +0.0228864 0.00659483 1e-07 0.0151987 0.0121803 1e-07 0.00884021 0.0192421 1e-07 +0.00408894 0.0274715 1e-07 0.00115249 0.036509 1e-07 0.019649 0.0832682 0.0454642 +0.0715848 0.0832635 0.0454498 0.0458832 0.091413 0.0623875 0.0451402 0.0914113 0.0291099 +0.00718107 0.0702296 0.0650268 0.0840671 0.0701962 0.0649956 0.00740438 0.0705797 0.0254259 +0.0837958 0.0706215 0.0254057 0.066329 0.0864189 0.0679616 0.024135 0.086019 0.0680421 +0.0250016 0.0864717 0.0230764 0.0662826 0.0864426 0.0229442 0.00414062 0.064563 0.045468 +0.08709 0.0645551 0.0454507 0.0370307 0.0905961 0.0454534 0.0543286 0.0905705 0.0459802 +0.0386833 0.0908824 0.0752783 0.0386561 0.0908782 0.0156443 0.0888804 0.0598906 0.0149344 +0.00247422 0.0602806 0.0762392 0.0139901 0.07861 0.0753727 0.077257 0.0785906 0.0753508 +0.0772502 0.0785971 0.0155546 0.0139743 0.0785946 0.0155529 0.0887925 0.0601607 0.0760735 +0.00243561 0.0601638 0.0148292 0.0534961 0.0907251 0.0760211 0.0534831 0.0907274 0.0148677 +0.0155313 0.0800352 0.0590389 0.0759756 0.0797861 0.0590724 0.0160014 0.0804445 0.031042 +0.0752418 0.0804307 0.031276 0.00194578 0.0585778 0.0578036 0.00194682 0.0585814 0.0331337 +0.0892817 0.0585764 0.0577825 0.0892821 0.0585751 0.0331192 0.0619438 0.0883791 0.0362027 +0.0296529 0.0885195 0.0361615 0.0298036 0.0885757 0.0545486 0.0615675 0.088522 0.0548076 +0.0105111 0.0748371 0.0490109 0.0807272 0.0748235 0.0488449 0.0261592 0.0870402 0.0821894 +0.0258492 0.0868919 0.00887962 0.0639639 0.0875451 0.0797552 0.0639274 0.0875612 0.0111658 +0.0082476 0.0718416 0.0375936 0.082983 0.0718365 0.0375833 0.0835825 0.0709487 0.0796548 +0.00764922 0.0709556 0.0112426 0.00795329 0.0714114 0.0797872 0.0835197 0.0710438 0.0111868 +0.05619 0.0901662 0.0627603 0.0351217 0.0901864 0.0636415 0.0336503 0.0898112 0.0280594 +0.0561283 0.0901809 0.0271421 0.0901314 0.0551387 0.0234403 0.00109073 0.0551146 0.067434 +0.00108435 0.0550835 0.0235978 0.090144 0.0550776 0.0673125 0.0455129 0.0914137 0.0402162 +0.00110334 0.0551757 0.0483299 0.00628355 0.0687465 0.0535804 0.0901241 0.0551741 0.048315 +0.0849579 0.0687218 0.0535487 0.0455049 0.0914137 0.0511854 0.0457357 0.0914136 0.0822438 +0.0457073 0.0914137 0.00869425 0.0192783 0.0830074 0.0822982 0.0191552 0.0829196 0.00858297 +0.0721756 0.0828452 0.00849148 0.0721837 0.0828394 0.0823868 0.0375217 0.0906878 0.0359104 +0.0641956 0.087442 0.0455866 0.0274058 0.0876077 0.045455 0.0372271 0.0906334 0.0545977 +0.046348 0.0914079 0.0702304 0.0463409 0.091408 0.0206691 0.0539035 0.0906515 0.036124 +0.0134697 0.0780977 0.04066 0.0777591 0.0780961 0.0406423 0.0119766 0.0765316 0.0667208 +0.079059 0.076741 0.0667136 0.012174 0.0767473 0.0241945 0.0790605 0.0767393 0.0241874 +0.0534827 0.0907275 0.0549371 0.0785738 0.0772599 0.0833804 0.000784075 0.0534705 0.0399585 +0.0904427 0.0534726 0.0399463 0.0126679 0.0772753 0.00756263 0.0902744 0.0544154 0.0824266 +0.0785072 0.07733 0.00751125 0.000952918 0.0544167 0.00847953 0.000962249 0.0544658 0.0823932 +0.0131789 0.0778042 0.0833705 0.090281 0.0543809 0.00847512 0.0356781 0.0903147 0.00822737 +0.0356492 0.0903082 0.082736 0.0880783 0.062172 0.0678763 0.0032083 0.0623269 0.0230691 +0.00316155 0.0622052 0.0679962 0.0880038 0.0623656 0.0229039 0.0703018 0.0841247 0.0370786 +0.0227592 0.0852504 0.0537232 0.0208251 0.0840597 0.0371393 0.0715578 0.0832823 0.0744195 +0.0715471 0.0832897 0.0164704 0.070572 0.0839486 0.0536988 0.0185934 0.0825109 0.0684193 +0.0226404 0.085181 0.0168169 0.0551317 0.0904061 0.0841242 0.0549917 0.0904358 0.00675576 +0.0313004 0.0891014 0.0726062 0.0312317 0.0890786 0.0182116 0.0729918 0.0822435 0.066433 +0.0729891 0.0822455 0.0244603 0.0804749 0.0751277 0.0584296 0.00480126 0.0659708 0.033145 +0.086429 0.0659645 0.0331369 0.0108285 0.0752186 0.0584593 0.0182401 0.0822471 0.024487 +0.00858993 0.0723289 0.0724136 0.0827839 0.0721217 0.0720382 0.00853622 0.0722533 0.0186213 +0.0826629 0.0722928 0.0186044 0.0874746 0.0636725 0.0830247 0.0592499 0.0893201 0.0708035 +0.0037536 0.0636751 0.00787896 0.059801 0.089143 0.0199071 0.00381565 0.0638209 0.0831031 +0.0873801 0.0638942 0.00780371 0.021867 0.0847177 0.0752516 0.090498 0.0531345 0.0159819 +0.0224273 0.0850554 0.0613586 0.00074381 0.0532261 0.0751819 0.0904751 0.0532769 0.0752047 +0.000751799 0.0532752 0.0157035 0.0678864 0.0855829 0.0605503 0.00048948 0.051429 0.0318181 +0.0907381 0.0514254 0.0590908 0.00048888 0.051424 0.0590908 0.0237 0.0857827 0.030424 +0.0907382 0.051424 0.0318181 0.0673052 0.0859041 0.0304479 0.0102317 0.074494 0.0309757 +0.0804469 0.0751611 0.0311565 0.0156708 0.0801578 0.0515997 0.0758353 0.0799115 0.0514966 +0.00205076 0.0589356 0.0400044 0.0891768 0.0589342 0.0399867 0.000299638 0.0495297 0.0878428 +0.004178 0.0646461 0.0604919 0.0870511 0.0646418 0.0604694 0.00321992 0.0623569 0.0520708 +0.0880096 0.0623507 0.0520504 0.0282462 0.0879651 0.0619428 0.0862723 0.0662809 0.0741153 +0.0049576 0.0662866 0.0167849 0.00500489 0.0663809 0.074207 0.0861952 0.0664345 0.0167058 +0.00726891 0.0703682 0.0447781 0.0838987 0.0704615 0.0442725 0.0401487 0.0910841 0.0689387 +0.0398919 0.0910523 0.0223666 0.0528894 0.0908277 0.0693333 0.00768095 0.0446009 0.999996 +0.00267987 0.0460431 0.999996 0.074933 0.0351498 0.354164 0.0683198 0.0356716 0.430812 +0.0604255 0.0361765 0.498537 0.0576162 0.0365435 0.560878 0.0499555 0.037039 0.619167 +0.047169 0.0373382 0.672898 0.037082 0.035092 0.323057 0.111639 0.0348074 0.322629 +0.0401793 0.0378432 0.721627 0.0437169 0.0356491 0.388487 0.100558 0.0351348 0.394652 +0.0900427 0.0354905 0.468782 0.0392725 0.0379751 0.766677 0.0387145 0.0363267 0.460726 +0.0838903 0.0357461 0.53257 0.0359346 0.0369326 0.52831 0.115066 0.0349119 0.360402 +0.0728587 0.034881 0.312185 0.0354983 0.0382796 0.80788 0.0344953 0.0383107 0.84824 +0.0338487 0.0374286 0.585785 0.105092 0.035178 0.432665 0.0771594 0.0359953 0.594043 +0.0297482 0.0361622 0.427599 0.0956686 0.0354338 0.498947 0.028164 0.0354825 0.357617 +0.0702017 0.0362472 0.649098 0.0283632 0.0380565 0.643704 0.0296618 0.0387446 0.880075 +0.063706 0.0364858 0.701625 0.0255964 0.0391455 0.911839 0.0284341 0.0367953 0.492471 +0.0877282 0.0356579 0.563622 0.134637 0.0346757 0.301947 0.0253898 0.0374693 0.558477 +0.0716042 0.0354696 0.402465 0.0262242 0.0385213 0.696001 0.0231723 0.0393534 0.942499 +0.0572165 0.0367581 0.745647 0.0508303 0.0370918 0.780448 0.0799983 0.0358724 0.622324 +0.0649106 0.0358775 0.458582 0.0503429 0.034842 0.300225 0.0232891 0.0348675 0.297538 +0.0979563 0.0347463 0.300337 0.0238174 0.0380143 0.614944 0.0239047 0.0389689 0.745241 +0.131719 0.0347655 0.339606 0.119388 0.034968 0.411889 0.0723587 0.0360954 0.67659 +0.124172 0.0348881 0.384889 0.0466294 0.0372397 0.823801 0.0509529 0.0352267 0.345109 +0.0890632 0.0349482 0.33281 0.0822776 0.0352347 0.378392 0.0216957 0.0360089 0.402888 +0.0590477 0.036399 0.537097 0.113268 0.0350811 0.456703 0.0491197 0.0357915 0.412719 +0.0657502 0.0363024 0.722528 0.0214009 0.0393789 0.785393 0.0220482 0.0393681 0.967533 +0.0214218 0.0385807 0.67071 0.0541412 0.0354068 0.369874 0.109765 0.035144 0.482169 +0.0205447 0.039657 0.827133 0.0489615 0.0360165 0.441817 0.089541 0.0353312 0.416099 +0.0171997 0.0357877 0.378485 0.0858133 0.0354909 0.445919 0.0541726 0.0368008 0.597488 +0.103532 0.0352576 0.522151 0.0178514 0.0365473 0.448772 0.071407 0.0358683 0.479973 +0.016915 0.0353144 0.33598 0.0610452 0.0363985 0.766327 0.0437169 0.0372433 0.864259 +0.045682 0.0363782 0.483297 0.018637 0.0391156 0.718769 0.0766733 0.0358802 0.513586 +0.0172863 0.0368189 0.4733 0.0999366 0.0353228 0.54679 0.049931 0.0371207 0.641992 +0.0172659 0.0372594 0.515055 0.0158848 0.0375232 0.537081 0.0675697 0.0350427 0.332262 +0.0177448 0.0400773 0.860671 0.0532838 0.0367732 0.804086 0.094426 0.0350599 0.361697 +0.0191659 0.0394226 0.765142 0.0947743 0.0354161 0.582329 0.0160435 0.0379365 0.577639 +0.140898 0.0346952 0.321154 0.0420255 0.0366277 0.507034 0.116967 0.0346767 0.292342 +0.0692873 0.034748 0.292748 0.106321 0.034896 0.339623 0.0394066 0.037431 0.897844 +0.134974 0.034777 0.362996 0.0160657 0.0381276 0.59669 0.0426142 0.0369058 0.548807 +0.0915876 0.0354669 0.606719 0.0714849 0.0361637 0.574914 0.0453485 0.0374807 0.692495 +0.106348 0.0350277 0.377491 0.074918 0.0360129 0.549158 0.0587753 0.0363168 0.51863 +0.0123004 0.0351153 0.316994 0.0162667 0.0403704 0.894818 0.0398636 0.0371278 0.570171 +0.124212 0.0349161 0.427607 0.0554812 0.0349765 0.317528 0.0351948 0.0376565 0.928306 +0.0861678 0.0355771 0.6398 0.0264819 0.0383563 0.983359 0.148894 0.0346285 0.290736 +0.0147057 0.0385308 0.63205 0.0837915 0.0355932 0.66269 0.0355768 0.0376582 0.629207 +0.062114 0.0354519 0.38499 0.0160371 0.0399333 0.80454 0.0537529 0.0367461 0.580462 +0.0676663 0.0363444 0.609318 0.0352412 0.0352784 0.341389 0.0645937 0.0364863 0.63165 +0.0515924 0.036629 0.84155 0.0151 0.0406018 0.924784 0.037779 0.035556 0.372328 +0.0138411 0.0403957 0.843935 0.112963 0.0350666 0.500388 0.0916235 0.0348501 0.316602 +0.0411732 0.0378167 0.739955 0.036892 0.0374417 0.602939 0.0789237 0.0356937 0.692671 +0.0783501 0.0357876 0.495007 0.0127013 0.0363009 0.420016 0.0375456 0.0347551 0.288762 +0.0417495 0.0375321 0.655451 0.0616638 0.03663 0.663334 0.0122696 0.0388682 0.655213 +0.0318649 0.0378002 0.956108 0.0854421 0.0346998 0.288845 0.00977253 0.0348863 0.288204 +0.0923317 0.0354794 0.483205 0.0461139 0.036786 0.882063 0.132176 0.0348203 0.399804 +0.0769918 0.0356994 0.710778 0.0723279 0.0358232 0.735864 0.0335728 0.0380513 0.681668 +0.0484282 0.0373388 0.709099 0.0127447 0.0391436 0.685148 0.119142 0.0347343 0.309107 +0.037164 0.0358391 0.402514 0.0526738 0.0361454 0.46839 0.0332188 0.0362649 0.44375 +0.0364713 0.0381993 0.789035 0.0413743 0.0369761 0.913632 0.0102497 0.0356737 0.363696 +0.102394 0.0352047 0.569951 0.104816 0.0351493 0.416959 0.124345 0.0349091 0.446272 +0.0133922 0.0406408 0.876905 0.0587464 0.0367715 0.684804 0.0646536 0.0356278 0.415608 +0.121194 0.0349416 0.469574 0.0849245 0.0352871 0.393848 0.0370869 0.0349376 0.307226 +0.0112296 0.0371082 0.489171 0.0135909 0.0408754 0.954371 0.148715 0.0346534 0.308295 +0.0281407 0.035803 0.389222 0.0318125 0.038293 0.71039 0.0121706 0.0396362 0.733249 +0.0829375 0.0354709 0.430065 0.0282645 0.0386002 0.729263 0.1267 0.0347588 0.325806 +0.0532959 0.035843 0.426407 0.101006 0.0352647 0.447606 0.00927539 0.0365314 0.435968 +0.0322462 0.0365747 0.476285 0.0708514 0.0352703 0.368712 0.0699721 0.0358545 0.753541 +0.13411 0.034638 0.287142 0.0117766 0.0393755 0.703547 0.0114185 0.0412784 0.983812 +0.05459 0.0356247 0.398815 0.0653811 0.0359822 0.779533 0.0536652 0.0370221 0.730472 +0.0884974 0.0350321 0.348068 0.115129 0.0349943 0.397337 0.0439512 0.0353704 0.356822 +0.136514 0.0347749 0.37951 0.0711372 0.0357063 0.444715 0.0302153 0.0371852 0.541244 +0.0562386 0.0347135 0.286435 0.0342023 0.0383744 0.832114 0.0469388 0.0374351 0.754332 +0.078701 0.0356537 0.459364 0.140957 0.0347273 0.350216 0.0943945 0.0353129 0.621007 +0.06989 0.0360878 0.52819 0.109953 0.0350773 0.535255 0.104192 0.0352417 0.468922 +0.0912832 0.035548 0.516979 0.0490207 0.0351157 0.330978 0.10387 0.0346676 0.28673 +0.145293 0.0346929 0.335605 0.010035 0.0360019 0.391564 0.00978752 0.0378528 0.552266 +0.0608302 0.0352498 0.355548 0.00708469 0.0360955 0.347914 0.0638959 0.0359683 0.794417 +0.0593951 0.0361139 0.819038 0.0381813 0.0369988 0.942115 0.119576 0.0348459 0.346254 +0.00931277 0.0368314 0.461913 0.00728696 0.0356558 0.303722 0.023685 0.0365837 0.461333 +0.0827508 0.0347868 0.301855 0.122704 0.0348771 0.369738 0.0297718 0.0386242 0.756028 +0.0538965 0.0362437 0.855223 0.0283509 0.0360467 0.413943 0.0108346 0.0398988 0.751881 +0.0231715 0.0347306 0.284997 0.011503 0.0410455 0.908824 0.0102262 0.0401685 0.776025 +0.0298137 0.0369138 0.508816 0.0585656 0.036148 0.48644 0.0279795 0.0381841 0.659267 +0.0645793 0.0348415 0.303874 0.00827032 0.0373468 0.504163 0.13063 0.0348358 0.418434 +0.0237016 0.0351609 0.324737 0.0495673 0.0365936 0.528312 0.0857238 0.0354194 0.678588 +0.105766 0.0347704 0.309089 0.0410373 0.0365593 0.495128 0.0631782 0.0364673 0.590059 +0.0481393 0.0361326 0.455733 0.099524 0.0352177 0.595949 0.00968925 0.0385036 0.610658 +0.0947948 0.0351408 0.381428 0.0308826 0.0386418 0.867676 0.086168 0.0356988 0.545192 +0.114493 0.0350063 0.516373 0.0786847 0.0349437 0.324562 0.00594766 0.0370248 0.407367 +0.0276939 0.0388448 0.774198 0.0081927 0.0380466 0.565296 0.0780239 0.0350528 0.341466 +0.0310229 0.0386754 0.819401 0.071205 0.0361528 0.564862 0.106225 0.0351214 0.558548 +0.101353 0.0348804 0.330199 0.0102087 0.0403205 0.792474 0.0249776 0.0391536 0.798966 +0.0965315 0.0354244 0.532962 0.00802594 0.0376004 0.525649 0.0596026 0.0364481 0.551732 +0.076676 0.0355037 0.419592 0.0338924 0.0371608 0.972269 0.0264306 0.0375385 0.569877 +0.0228255 0.0372613 0.528591 0.117749 0.0348219 0.334472 0.00993673 0.040577 0.818836 +0.0414461 0.0359907 0.425563 0.119538 0.034945 0.490299 0.025491 0.0350244 0.312573 +0.0786489 0.0354834 0.72797 0.0261387 0.0356332 0.370853 0.0844085 0.0357566 0.57583 +0.075451 0.03534 0.38661 0.058096 0.0367854 0.6517 0.0397923 0.0374198 0.616993 +0.0888042 0.0354159 0.65122 0.0352616 0.0379 0.66887 0.0517684 0.0370509 0.772189 +0.12384 0.0349078 0.458243 0.10391 0.0349728 0.35608 0.00606358 0.0363794 0.328613 +0.0288508 0.0388026 0.891394 0.0208091 0.0363798 0.437096 0.0591934 0.0359984 0.831346 +0.131421 0.034714 0.314381 0.0106671 0.0414106 0.973222 0.0818253 0.0351571 0.363297 +0.020112 0.0354376 0.348608 0.00840544 0.0391713 0.666957 0.00932646 0.0415147 0.939134 +0.0399387 0.0379277 0.781348 0.0819537 0.0353657 0.403935 0.00571903 0.0385834 0.585831 +0.0469925 0.0373347 0.797 0.079413 0.0359125 0.605871 0.0462807 0.0370281 0.587998 +0.0924792 0.0354146 0.454964 0.0452972 0.0374139 0.813109 0.112019 0.0350926 0.442387 +0.103197 0.0352731 0.509117 0.0979696 0.0352048 0.407976 0.0597899 0.0358937 0.447532 +0.0657976 0.0351412 0.344764 0.0544963 0.0369847 0.719611 0.00806373 0.0389118 0.641867 +0.00451894 0.0380538 0.44581 0.0510968 0.0369504 0.607598 0.0947305 0.0353271 0.435144 +0.13788 0.0347634 0.389924 0.0521806 0.0362101 0.872182 0.0630675 0.035965 0.468758 +0.0280465 0.0377156 0.597444 0.0517439 0.0355099 0.380433 0.104104 0.0352555 0.49349 +0.0239525 0.0393932 0.85064 0.0800136 0.0356676 0.468947 0.066578 0.0360921 0.508877 +0.00910978 0.0407745 0.83274 0.131261 0.0347908 0.353574 0.0257457 0.0391924 0.838301 +0.0638581 0.0365029 0.62032 0.00817533 0.0386873 0.622061 0.0769314 0.0359796 0.633108 +0.0220366 0.0378287 0.586715 0.0881523 0.0356172 0.593505 0.0664421 0.0349688 0.32146 +0.0963736 0.0352751 0.424748 0.0213139 0.0368735 0.485857 0.0540194 0.036369 0.508195 +0.0469892 0.0372033 0.630883 0.115408 0.0350257 0.421146 0.094661 0.0352546 0.632076 +0.0449703 0.0369124 0.560408 0.0391969 0.0360973 0.434528 0.105192 0.0349986 0.365756 +0.0427199 0.0368228 0.536864 0.0242928 0.0380908 0.626292 0.0365322 0.0379855 0.701009 +0.038721 0.0375893 0.639864 0.00831945 0.0410469 0.855058 0.00790191 0.0411888 0.866378 +0.158518 0.0346096 0.284238 0.0760041 0.0346714 0.283269 0.108754 0.0350799 0.406281 +0.105306 0.0350777 0.580942 0.0920416 0.035127 0.372753 0.047868 0.036237 0.905032 +0.125323 0.0346325 0.282888 0.00793876 0.0360804 0.374862 0.0719023 0.0361543 0.660538 +0.0719052 0.0360731 0.54031 0.0724711 0.0355609 0.767438 0.0627993 0.0365122 0.711754 +0.114003 0.0349869 0.387924 0.0255114 0.0391067 0.92311 0.0673824 0.0363115 0.691328 +0.0189801 0.0370811 0.501525 0.00619316 0.0378262 0.515921 0.0685545 0.0359686 0.490141 +0.0494807 0.0362167 0.893539 0.020548 0.0396104 0.816801 0.112899 0.035026 0.525057 +0.0390064 0.0376902 0.874351 0.0466752 0.0346783 0.281598 0.0864189 0.0356356 0.502072 +0.0840186 0.0357239 0.520279 0.0207437 0.0374945 0.547122 0.022544 0.038608 0.681196 +0.0362242 0.0368517 0.518965 0.00610254 0.0375359 0.478697 0.0474131 0.034938 0.310203 +0.0562226 0.0367889 0.756174 0.058945 0.0358226 0.434496 0.0959734 0.0354217 0.556498 +0.0423076 0.036355 0.471914 0.0429417 0.0374004 0.854962 0.0613958 0.0364721 0.572173 +0.109227 0.034719 0.299337 0.0482714 0.0365583 0.517631 0.110753 0.0350309 0.54526 +0.0505224 0.0371494 0.661669 0.151903 0.0346569 0.324324 0.0514688 0.0363278 0.492664 +0.00792632 0.0397975 0.723093 0.0679647 0.0354905 0.807299 0.0448473 0.036318 0.924099 +0.0186172 0.0384643 0.642313 0.0956866 0.0349626 0.342139 0.00637131 0.0403591 0.766539 +0.0222694 0.0388043 0.705406 0.0822899 0.0356803 0.485757 0.154468 0.0346311 0.299938 +0.058548 0.035127 0.33777 0.0308834 0.0356782 0.379164 0.0206442 0.0398134 0.886467 +0.0355159 0.0371623 0.55676 0.083075 0.0354076 0.702708 0.0950671 0.0346481 0.281728 +0.0357036 0.0365991 0.486705 0.10126 0.0353028 0.47771 0.0500459 0.0368158 0.570414 +0.0309471 0.036403 0.454943 0.0607998 0.0366553 0.641961 0.0658743 0.0363914 0.597775 +0.123403 0.034886 0.480499 0.102021 0.0348226 0.318059 0.00712163 0.0421523 0.99285 +0.0804894 0.0357941 0.648689 0.0230546 0.0393199 0.95095 0.00776882 0.0413811 0.887642 +0.102933 0.0352514 0.458411 0.0908653 0.0352155 0.670375 0.0617145 0.0366255 0.674748 +0.0408655 0.0371591 0.579897 0.130663 0.0348232 0.437572 0.127979 0.0346696 0.295124 +0.0331134 0.0384292 0.857119 0.0389906 0.0359167 0.41347 0.0217132 0.0396682 0.871165 +0.135725 0.0347794 0.409571 0.102655 0.0350421 0.610997 0.0529324 0.0365976 0.544448 +0.0776208 0.0359763 0.583663 0.0746795 0.0348084 0.302466 0.0300721 0.0385947 0.902567 +0.0438029 0.0374473 0.834102 0.00434262 0.0390503 0.576643 0.113306 0.0346408 0.282773 +0.145141 0.0347046 0.364585 0.136037 0.0347299 0.330851 0.00383844 0.0379192 0.339375 +0.062644 0.0353762 0.374825 0.0654296 0.0346699 0.282054 0.0437485 0.0375383 0.682985 +0.142054 0.0346219 0.283646 0.0880169 0.0352461 0.687497 0.028032 0.0385681 0.720662 +0.0554217 0.0369449 0.694008 0.0355975 0.035388 0.352928 0.00696402 0.0400636 0.742518 +0.0334303 0.0383441 0.747382 0.0198172 0.0362874 0.427055 0.00667298 0.0357235 0.279817 +0.00513593 0.0388566 0.596038 0.0331147 0.0369106 0.99013 0.0385778 0.0365123 0.963441 +0.0640769 0.0363692 0.731334 0.0413288 0.0361944 0.449827 0.0784364 0.0359388 0.567568 +0.00549797 0.0396694 0.695556 0.0171508 0.0349914 0.307473 0.00596672 0.0381221 0.541877 +0.0438518 0.036273 0.934148 0.0367259 0.0378613 0.887243 0.125492 0.0348418 0.361433 +0.0201709 0.0395301 0.988673 0.00415338 0.038177 0.426801 0.00533102 0.0395231 0.677396 +0.063606 0.0355674 0.404315 0.0199516 0.0380811 0.606263 0.0850137 0.0357356 0.553501 +0.0170165 0.0377983 0.56696 0.0204561 0.0392649 0.755191 0.0186935 0.0358727 0.387412 +0.082456 0.0353297 0.718132 0.0769756 0.035435 0.74683 0.00551477 0.0398451 0.713024 +0.113636 0.0349472 0.369809 0.0285495 0.0379903 0.635685 0.0162986 0.0390493 0.69511 +0.0313045 0.0351954 0.331093 0.0690263 0.0360758 0.518895 0.0582919 0.036699 0.612246 +0.143995 0.0346543 0.301252 0.0411726 0.0348476 0.298861 0.0041345 0.0379317 0.383549 +0.059031 0.0347879 0.295769 0.0731014 0.0359675 0.70138 0.00683167 0.0417483 0.918557 +0.0194694 0.0361123 0.410265 0.0580083 0.0350479 0.327467 0.0199211 0.0399169 0.903967 +0.0731744 0.0354974 0.410457 0.0698986 0.0359794 0.49918 0.00358393 0.0385513 0.415562 +0.121298 0.0347539 0.317016 0.0263112 0.0389335 0.932577 0.0193118 0.0397912 0.97762 +0.0855393 0.0356712 0.615342 0.0941121 0.0354847 0.523791 0.0600221 0.0357105 0.847492 +0.0722772 0.035311 0.377006 0.0283604 0.0375582 0.579394 0.11442 0.0350493 0.431683 +0.0757207 0.035595 0.435637 0.0458668 0.0357074 0.397877 0.0886565 0.0355703 0.492712 +0.134496 0.0347814 0.426643 0.00704926 0.0420191 0.963009 0.0487026 0.0372978 0.763575 +0.0601542 0.0363328 0.528845 0.0649247 0.0354907 0.394699 0.0857807 0.0356243 0.630099 +0.043946 0.0352123 0.339152 0.0173276 0.0402739 0.915851 0.0254427 0.0391405 0.806322 +0.0941955 0.0354532 0.572207 0.0563056 0.0368187 0.628869 0.154789 0.0346417 0.315066 +0.0308517 0.0386322 0.782952 0.0563983 0.03585 0.864441 0.0374008 0.0380375 0.730802 +0.0467453 0.0350442 0.321807 0.016189 0.0346988 0.28169 0.103416 0.0350827 0.386873 +0.00135174 0.0435716 0.995862 0.0452085 0.0354417 0.365941 0.14923 0.0346768 0.344186 +0.0800129 0.0357382 0.67106 0.0342871 0.0380624 0.691109 0.00727298 0.041533 0.898805 +0.0138143 0.0348843 0.297502 0.0864955 0.0355742 0.47643 0.00380758 0.0386763 0.468195 +0.09575 0.0351589 0.642011 0.0532635 0.0353426 0.360979 0.071448 0.0357917 0.463183 +0.0530687 0.0355695 0.389557 0.0537513 0.0361854 0.477441 0.0935413 0.0348867 0.324789 +0.00335253 0.0384453 0.356224 0.0170226 0.0383387 0.621856 0.0310279 0.0346945 0.282192 +0.0387625 0.037327 0.595332 0.00402387 0.0376168 0.31279 0.0214326 0.0384262 0.652065 +0.0047546 0.0406884 0.785223 0.0505032 0.0372124 0.739026 0.0407469 0.0377855 0.7122 +0.0355649 0.0366463 0.981263 0.00661232 0.0419924 0.947316 0.0195749 0.0355833 0.361598 +0.0926058 0.0352362 0.400296 0.0706285 0.0354996 0.787333 0.13959 0.0346807 0.31 +0.00321085 0.0382962 0.296926 0.0202448 0.0385574 0.661174 0.032789 0.0381166 0.917638 +0.0253509 0.0371011 0.518129 0.12344 0.0349056 0.39381 0.0355289 0.0354852 0.363014 +0.0191953 0.0391484 0.727339 0.0780332 0.0357853 0.683249 0.0480549 0.0364554 0.501217 +0.0245971 0.0353217 0.340167 0.0408658 0.0364 0.950859 0.048759 0.0372002 0.650984 +0.0701413 0.0362566 0.639926 0.0185566 0.039534 0.775046 0.0972754 0.0347973 0.309867 +0.0720498 0.036184 0.624146 0.0314463 0.0380125 0.945668 0.123024 0.0348531 0.50003 +0.0322179 0.0377277 0.619538 0.0824314 0.03488 0.316564 0.0752224 0.0360632 0.615743 +0.0139797 0.0390047 0.677266 0.0551107 0.0357536 0.417191 0.0373176 0.0376942 0.648094 +0.0789369 0.0358869 0.540334 0.031579 0.0384332 0.73846 0.066175 0.0361738 0.74374 +0.00354386 0.0390441 0.497051 0.0364016 0.0357693 0.394033 0.0290562 0.0358825 0.398104 +0.0153867 0.0352184 0.326914 0.131109 0.0347999 0.451183 0.0558308 0.0367087 0.588143 +0.0938319 0.0351411 0.659785 0.00515576 0.0408711 0.805832 0.030427 0.0365277 0.467502 +0.00301587 0.0389861 0.39901 0.0157955 0.0357038 0.369951 0.0325992 0.0348518 0.297662 +0.0481161 0.0347673 0.291463 0.0211667 0.039087 0.735905 0.0337747 0.0367579 0.500832 +0.00494291 0.03924 0.633804 0.105016 0.035048 0.590984 0.0178098 0.0402069 0.934125 +0.0685299 0.0352289 0.359843 0.0330222 0.0376443 0.611965 0.0400153 0.0356107 0.380334 +0.0782791 0.034743 0.293939 0.00270712 0.0397245 0.487214 0.0949596 0.0346998 0.290834 +0.0294684 0.0380785 0.96521 0.0546256 0.0367265 0.793812 0.0555192 0.0360259 0.457628 +0.122829 0.0349211 0.403005 0.00204735 0.0396979 0.286563 0.0522464 0.0366615 0.553052 +0.0429866 0.0374727 0.843451 0.0542026 0.0357635 0.885813 0.0688234 0.0362859 0.668508 +0.0725528 0.0359129 0.718775 0.00243792 0.0394855 0.367798 0.0847178 0.0351045 0.357298 +0.028858 0.0387231 0.764824 0.118074 0.0349306 0.378203 0.0784854 0.0356186 0.449943 +0.0729103 0.0354409 0.776263 0.0858599 0.0346436 0.280105 0.144422 0.0347087 0.374766 +0.0455489 0.0371174 0.600311 0.0635741 0.0364338 0.582371 0.042787 0.0376633 0.803945 +0.0123425 0.0360928 0.401427 0.000694316 0.0424405 0.277526 0.0309864 0.0372289 0.548976 +0.0171924 0.0400121 0.834792 0.0155004 0.0405607 0.944424 0.111504 0.0349018 0.349322 +0.0385444 0.0379962 0.819016 0.0805195 0.0352782 0.73838 0.113033 0.0350862 0.465313 +0.0953871 0.0350128 0.352638 0.0151743 0.0395403 0.744327 0.0592913 0.0364784 0.774639 +0.00487431 0.0413139 0.845679 0.00313677 0.0404846 0.68617 0.0193504 0.0369957 0.493976 +0.0333234 0.0350225 0.3147 0.0403599 0.0351577 0.331364 0.112615 0.0350923 0.47514 +0.00340866 0.0395014 0.557489 0.0293404 0.0371344 0.532654 0.0788273 0.0349925 0.332401 +0.1041 0.0352552 0.501759 0.0626942 0.0349132 0.312489 0.0768762 0.0353397 0.757783 +0.0133839 0.0355393 0.354006 0.00640338 0.0418958 0.929662 0.110363 0.0349791 0.564842 +0.141628 0.0347236 0.396832 0.139816 0.0347257 0.341273 0.00379009 0.0399068 0.656364 +0.0619756 0.0357176 0.424539 0.0859758 0.0357006 0.585318 0.125719 0.0347839 0.334268 +0.0551248 0.0369595 0.703865 0.0386475 0.0380091 0.756419 0.00458234 0.0386168 0.533473 +0.158604 0.0346173 0.292499 0.0379819 0.0375262 0.906198 0.143385 0.0347146 0.383069 +0.016629 0.0366589 0.45734 0.0290137 0.038236 0.674311 0.128069 0.0348134 0.473055 +0.0426008 0.0375331 0.665282 0.11091 0.034845 0.331935 0.0646328 0.0355713 0.82458 +0.0494866 0.03583 0.915388 0.131591 0.0348092 0.370338 0.0514667 0.0365903 0.536004 +0.00306131 0.0392275 0.456044 0.147824 0.0346863 0.356652 0.0550116 0.0369511 0.669981 +0.0147789 0.0406717 0.962778 0.119443 0.034707 0.301551 0.0175284 0.039743 0.794529 +0.0165681 0.0367512 0.465797 0.0465676 0.036212 0.462916 0.0939956 0.0354878 0.541182 +0.0863894 0.0352345 0.385656 0.0455831 0.037487 0.701275 0.0560761 0.0348849 0.306725 +0.0336726 0.0360431 0.420324 0.00428179 0.0411468 0.823772 0.00265494 0.0390264 0.321367 +0.107558 0.0351309 0.424776 0.013932 0.036968 0.48132 0.033151 0.0372933 0.564833 +0.127541 0.0347051 0.306804 0.0725238 0.036161 0.601727 0.0664063 0.0363817 0.682332 +0.0651339 0.0364702 0.656036 0.00506064 0.0416002 0.876227 0.112578 0.0347711 0.313984 +0.127567 0.0348725 0.409827 0.0438578 0.0352981 0.348645 0.0158326 0.0373783 0.523162 +0.135407 0.0346159 0.279624 0.0440876 0.0357965 0.406273 0.0532442 0.0367034 0.814581 +0.0480506 0.0359667 0.433547 0.0461232 0.0374906 0.727332 0.084979 0.03524 0.710846 +0.0278751 0.0353937 0.348787 0.0332483 0.0384672 0.798636 0.0634282 0.0360092 0.478126 +0.0962601 0.0354135 0.491097 0.122816 0.0349318 0.418627 0.0136047 0.0399822 0.784431 +0.0296995 0.0362492 0.436606 0.121757 0.0349498 0.436862 0.116541 0.0350278 0.449971 +0.0664392 0.0355127 0.816315 0.0230556 0.0361685 0.41965 0.102945 0.0350773 0.601036 +0.0522942 0.0370969 0.67932 0.0158495 0.0402389 0.852218 0.0141487 0.0393148 0.711342 +0.0854027 0.0350088 0.340572 0.0934419 0.0351906 0.390766 0.0259629 0.0364 0.446503 +0.137977 0.0346503 0.293877 0.0403445 0.0350079 0.315482 0.0100326 0.0383978 0.60214 +0.00498596 0.0423159 0.954945 0.0166348 0.0377201 0.558134 0.156967 0.0346314 0.307858 +0.0441122 0.0375912 0.789061 0.0761181 0.0355492 0.427317 0.0758283 0.0353883 0.395857 +0.117085 0.0349003 0.533046 0.128305 0.0348445 0.378653 0.0801661 0.0352011 0.369022 +0.0122375 0.0365684 0.44301 0.0293152 0.0349375 0.305307 0.10003 0.0350602 0.371937 +0.0610486 0.0357092 0.840087 0.0428498 0.0367493 0.526684 0.0113421 0.0358975 0.383654 +0.059271 0.036415 0.784755 0.118806 0.0347937 0.326829 0.107554 0.0350687 0.396102 +0.0965458 0.0353938 0.564501 0.108894 0.035147 0.450482 0.0845352 0.0354212 0.423129 +0.101898 0.0350265 0.619808 0.0116968 0.0364024 0.42778 0.0858554 0.0356856 0.601178 +0.105702 0.0346283 0.279149 0.0970036 0.0352391 0.415377 0.0262593 0.0385296 0.974327 +0.00292751 0.0402052 0.615761 0.102213 0.035273 0.538385 0.0750635 0.0359717 0.533007 +0.0586938 0.0352023 0.347552 0.111969 0.0350571 0.413564 0.109104 0.0349848 0.573547 +0.0540383 0.0356945 0.40738 0.0259942 0.0391867 0.860681 0.0420135 0.0373715 0.624043 +0.111414 0.0351087 0.489545 0.0242533 0.0357587 0.381435 0.0707654 0.0357519 0.452637 +0.0775228 0.0359404 0.641476 0.00212033 0.0401686 0.437153 0.0241994 0.0367278 0.476757 +0.0283973 0.038923 0.826868 0.0675446 0.0359807 0.759318 0.0131238 0.0376729 0.544283 +0.0408657 0.0361382 0.442175 0.0620347 0.0353117 0.365122 0.0668136 0.0357339 0.43812 +0.0270145 0.0384308 0.688627 0.1011 0.0352473 0.439436 0.070742 0.0353725 0.797681 +0.146954 0.0346668 0.315322 0.133509 0.0347238 0.321954 0.0546782 0.0364885 0.824893 +0.0935941 0.0353695 0.444465 0.0961258 0.0353763 0.464914 0.112415 0.0349544 0.554923 +0.103546 0.0352494 0.529825 0.11984 0.0348974 0.510354 0.0391208 0.0377464 0.676181 +0.00468198 0.0401972 0.733566 0.102438 0.0349508 0.348101 0.0672323 0.0362478 0.556343 +0.0283318 0.0388529 0.790958 0.0585848 0.0366679 0.604837 0.0804661 0.0350799 0.348212 +0.15248 0.0346583 0.334993 0.0498059 0.0372482 0.74745 0.0819759 0.0354103 0.413472 +0.0899168 0.0352985 0.408762 0.0562422 0.0346472 0.278688 0.00329919 0.0398773 0.606713 +0.0103187 0.0367025 0.452182 0.0384193 0.0346677 0.279992 0.100008 0.0352632 0.575897 +0.0773537 0.035961 0.559142 0.00410099 0.0405607 0.756492 0.0295887 0.0359573 0.406287 +0.0860899 0.0354573 0.437711 0.012913 0.0403619 0.826024 0.0229985 0.0352425 0.332037 +0.0577278 0.0367483 0.738051 0.0135725 0.0354164 0.343421 0.0294461 0.0383905 0.703518 +0.03543 0.0378531 0.661627 0.024294 0.038743 0.713207 0.00572239 0.0423601 0.979563 +0.0280827 0.0382294 0.666531 0.0265529 0.0381827 0.992876 0.0143685 0.0381019 0.588444 +0.0127607 0.0398439 0.760544 0.0671477 0.035183 0.35181 0.0704634 0.0359885 0.727983 +0.00290747 0.0398538 0.549223 0.049474 0.0367718 0.848972 0.150552 0.0346098 0.280413 +0.0761706 0.0359215 0.524242 0.086968 0.0355227 0.46129 0.0857048 0.0349177 0.324822 +0.120864 0.0348573 0.353961 0.0457529 0.0355049 0.37376 0.0334481 0.0378172 0.936361 +0.102521 0.0352849 0.485985 0.0587574 0.0367168 0.72574 0.089006 0.0348057 0.307378 +0.109328 0.0346857 0.291918 0.0225686 0.0393393 0.959667 0.0628314 0.0363559 0.751443 +0.133205 0.0347772 0.444803 0.0486683 0.0358566 0.420362 0.00357502 0.0403609 0.70432 +0.114478 0.0348582 0.34091 0.0125484 0.0371858 0.498525 0.0139605 0.0407536 0.993327 +0.051196 0.0371631 0.68689 0.0411878 0.0378259 0.748324 0.0772965 0.0358398 0.50465 +0.0202819 0.0350996 0.317975 0.0449803 0.0358756 0.944556 0.0956793 0.0354408 0.508093 +0.129021 0.03481 0.465889 0.0846972 0.0355353 0.453712 0.0373525 0.0370068 0.542783 +0.0551765 0.0368817 0.635721 0.0469051 0.0374354 0.717598 0.06636 0.0359605 0.773174 +0.0878818 0.0351907 0.696225 0.00194718 0.0406711 0.506888 0.0388694 0.037948 0.826114 +0.13027 0.0348355 0.389001 0.0280275 0.0347814 0.290208 0.0705017 0.0362144 0.586494 +0.0702689 0.0360941 0.708815 0.0783022 0.0358704 0.656175 0.0181092 0.0347916 0.289991 +0.0988868 0.0353702 0.515691 0.119453 0.0348813 0.519781 0.03838 0.0364929 0.480118 +0.003952 0.0405508 0.749521 0.00379152 0.0427832 0.986522 0.140368 0.034736 0.357767 +0.0148459 0.0372392 0.507964 0.0366114 0.0381248 0.839249 0.0932906 0.0355038 0.548999 +0.00184626 0.0400717 0.305566 0.0345323 0.0373311 0.575494 0.0227878 0.0366748 0.468872 +0.00148207 0.0408152 0.347478 0.116367 0.0348969 0.539886 0.0235151 0.0373285 0.537517 +0.0971518 0.0350452 0.650987 0.087784 0.034746 0.296869 0.001312 0.0412152 0.377356 +0.0163219 0.0382976 0.614835 0.0519465 0.0366666 0.83375 0.0946945 0.0353277 0.61411 +0.0715053 0.035831 0.471943 0.0550019 0.0369619 0.711876 0.0357867 0.0357057 0.386562 +0.110326 0.0351138 0.508818 0.0203274 0.0359446 0.395507 0.0353776 0.0382692 0.773716 +0.0611764 0.0354548 0.856593 0.0514026 0.0360375 0.449739 0.00407968 0.0410971 0.815096 +0.126685 0.0348067 0.346886 0.0641568 0.0362919 0.543904 0.112974 0.0347429 0.307061 +0.138089 0.0347465 0.416265 0.0931824 0.0354304 0.599029 0.0809003 0.0348331 0.308401 +0.115677 0.035001 0.404851 0.0100819 0.035354 0.334949 0.0130462 0.0398988 0.769273 +0.0851921 0.0356797 0.510915 0.0873067 0.0355839 0.622945 0.00328558 0.0401514 0.649065 +0.00232141 0.0397243 0.390586 0.0151413 0.0403984 0.868557 0.1449 0.0346882 0.328152 +0.0103162 0.0403721 0.799218 0.0341812 0.0382158 0.724718 0.0657131 0.0362171 0.534871 +0.0755191 0.035191 0.361461 0.0626465 0.0347263 0.28883 0.0616126 0.0360839 0.802308 +0.100619 0.0350393 0.626883 0.0201379 0.03879 0.688549 0.0944086 0.0354232 0.473712 +0.0102955 0.0369326 0.472172 0.0778282 0.0357392 0.477772 0.0227335 0.0395568 0.896097 +0.0739122 0.0349316 0.320017 0.044062 0.0376218 0.772961 0.0139918 0.0374914 0.529526 +0.0100411 0.0380693 0.572339 0.0791263 0.0355792 0.442961 0.0300007 0.037047 0.524484 +0.042981 0.0370734 0.889748 0.028126 0.0377781 0.605657 0.0693373 0.0356225 0.424493 +0.00491659 0.0419242 0.908407 0.0928768 0.0350525 0.679708 0.0215365 0.0382813 0.635567 +0.089141 0.0353897 0.430672 0.0310501 0.0379995 0.65262 0.102349 0.0347039 0.293581 +0.115825 0.0350265 0.483846 0.0640864 0.0363681 0.565462 0.0435696 0.0374132 0.646662 +0.0136936 0.0387281 0.647602 0.0704784 0.0350763 0.339059 0.0245418 0.0346655 0.279122 +0.060399 0.0361097 0.810527 0.107308 0.0351745 0.515841 0.0522822 0.0352808 0.352571 +0.0723096 0.0349783 0.325961 0.0113699 0.0362247 0.41196 0.0505586 0.0351719 0.338368 +0.102329 0.0351382 0.401735 0.0232483 0.0365172 0.454014 0.0406798 0.0378558 0.795898 +0.0218402 0.0370994 0.509567 0.0403401 0.0359344 0.974025 0.13856 0.0347553 0.370869 +0.0472139 0.0369417 0.577512 0.0353133 0.0370071 0.535794 0.0742743 0.0358374 0.48585 +0.0212455 0.0397326 0.878717 0.0291149 0.0366989 0.483473 0.125994 0.0348093 0.492715 +0.0943533 0.03541 0.591123 0.0106842 0.0404497 0.811749 0.0729368 0.0351132 0.346555 +0.00395557 0.0413489 0.838755 0.141369 0.0347203 0.404295 0.0102814 0.0350661 0.310127 +0.00193002 0.0407699 0.525967 0.0021192 0.040988 0.626099 0.0558943 0.0356791 0.87892 +0.0302169 0.0387407 0.812356 0.0301097 0.0351046 0.321707 0.0367377 0.0380142 0.863204 +0.122425 0.0348159 0.340668 0.0426701 0.0372695 0.609416 0.0498985 0.0365887 0.862236 +0.021528 0.0354967 0.354848 0.0352348 0.0381257 0.717723 0.0872552 0.0351253 0.364702 +0.00308949 0.0412644 0.795572 0.136879 0.0347409 0.433621 0.105791 0.0351522 0.551342 +0.00125917 0.0414015 0.40725 0.0452744 0.0370045 0.871193 0.0324625 0.0382224 0.910615 +0.0262364 0.0369222 0.50118 0.134156 0.0347633 0.346512 0.0025212 0.0414527 0.775895 +0.0768158 0.0465113 0.355288 0.0693837 0.0461781 0.43056 0.059791 0.0463702 0.498335 +0.056949 0.0455118 0.563411 0.0528281 0.0449901 0.62162 0.0477895 0.0447948 0.672612 +0.112371 0.0418855 0.322977 0.0411321 0.0449911 0.721801 0.0454042 0.0506795 0.38809 +0.100974 0.0419895 0.396128 0.0430103 0.0521641 0.319828 0.0908282 0.0419871 0.466714 +0.0401501 0.0441158 0.766835 0.0387055 0.0504855 0.461532 0.0840258 0.0416101 0.530461 +0.0373317 0.0495675 0.527667 0.115304 0.0406224 0.360057 0.0354348 0.0441871 0.805893 +0.0353147 0.0430702 0.848224 0.035089 0.0489156 0.585698 0.106148 0.0403107 0.433971 +0.0775562 0.0411694 0.593815 0.0777806 0.0472566 0.308634 0.0302768 0.0535574 0.351566 +0.0311141 0.0522493 0.427529 0.0954251 0.0404275 0.500686 0.0704666 0.0410535 0.648485 +0.0291492 0.0489213 0.644886 0.0305546 0.04338 0.879924 0.0262294 0.0436288 0.911956 +0.0642425 0.0408176 0.70163 0.0882223 0.0400722 0.563222 0.028704 0.0515728 0.494083 +0.134465 0.0391021 0.302624 0.0267414 0.0508535 0.55842 0.0727002 0.0462039 0.40313 +0.0273806 0.0483086 0.696295 0.0242233 0.0433278 0.941134 0.0577656 0.0408963 0.745741 +0.051494 0.0412383 0.780584 0.0804743 0.0398964 0.622145 0.0655057 0.0462231 0.459231 +0.0252961 0.0501633 0.614895 0.0222591 0.0554917 0.300861 0.0251126 0.0478266 0.745467 +0.132249 0.0385515 0.340055 0.0733768 0.0397498 0.67561 0.124377 0.0386608 0.384921 +0.102348 0.0438581 0.299127 0.0471823 0.040916 0.823657 0.0890702 0.0451492 0.331614 +0.119773 0.0386567 0.414125 0.0550113 0.0500036 0.342753 0.0834781 0.0450335 0.379001 +0.056982 0.0504844 0.297807 0.0219236 0.054056 0.403023 0.0215761 0.0544963 0.376656 +0.0600223 0.0455268 0.537574 0.113542 0.0385672 0.457098 0.0662128 0.0398122 0.722618 +0.0500936 0.0495329 0.412588 0.0229462 0.0428574 0.967678 0.0224986 0.0476057 0.785338 +0.0547018 0.0496193 0.367486 0.0226538 0.0497027 0.670562 0.0214403 0.0551787 0.330993 +0.110149 0.0384828 0.481872 0.0217138 0.0469241 0.827136 0.0900843 0.043234 0.416211 +0.0490095 0.0491842 0.441818 0.0862563 0.0431876 0.445916 0.0550486 0.0451159 0.597512 +0.103917 0.0384536 0.522503 0.0190113 0.0538276 0.449578 0.0797628 0.0433361 0.486542 +0.0540732 0.0476685 0.479883 0.0614812 0.0394715 0.766369 0.0444251 0.0402513 0.864378 +0.077767 0.0431001 0.511728 0.0200065 0.0493807 0.719091 0.100608 0.0383896 0.545921 +0.0506756 0.0449151 0.642952 0.0194951 0.0533812 0.474511 0.0192176 0.0528181 0.515132 +0.0173589 0.0528026 0.537009 0.0536288 0.0400245 0.804179 0.0189879 0.0468795 0.860616 +0.0702799 0.0480284 0.326453 0.0951111 0.0383609 0.581966 0.0964685 0.0436327 0.351816 +0.0175337 0.0521574 0.577594 0.0206027 0.0484153 0.765244 0.14109 0.0376922 0.321247 +0.0540023 0.0469774 0.51621 0.102863 0.0421459 0.376056 0.134108 0.0377313 0.362472 +0.0398428 0.040278 0.897874 0.0175795 0.051856 0.596639 0.0443733 0.0479795 0.548853 +0.0722456 0.0425821 0.574685 0.0919006 0.0382466 0.606506 0.0461583 0.0446534 0.692637 +0.0644412 0.0478485 0.383547 0.0759412 0.0425648 0.548291 0.040451 0.053007 0.290311 +0.0853511 0.0464845 0.291183 0.0175026 0.0465161 0.894773 0.112238 0.0415067 0.341134 +0.0410019 0.0481631 0.570059 0.119681 0.0415126 0.290967 0.086477 0.0382896 0.639674 +0.12399 0.0375618 0.431417 0.0357344 0.0403088 0.928288 0.0376962 0.052107 0.372765 +0.0384704 0.0496764 0.510625 0.0272345 0.0407946 0.983606 0.149085 0.0372559 0.290747 +0.0831346 0.0382416 0.66274 0.0161905 0.0515602 0.63202 0.0367012 0.0478084 0.629129 +0.0959275 0.0444584 0.315699 0.0657383 0.042349 0.632524 0.054684 0.0455501 0.580345 +0.0380063 0.0526518 0.335629 0.0172208 0.0484368 0.804457 0.0683515 0.042444 0.609222 +0.016185 0.046174 0.925589 0.0109631 0.0564401 0.347212 0.0525381 0.0390969 0.83924 +0.0151487 0.0481858 0.843861 0.0420577 0.0443652 0.740094 0.0380405 0.0480681 0.602839 +0.0140128 0.055081 0.417165 0.0784071 0.038276 0.692031 0.0376928 0.0503443 0.479443 +0.113449 0.037507 0.498395 0.0558137 0.0435869 0.658301 0.0363365 0.0472473 0.661107 +0.0142488 0.0515686 0.655031 0.0324731 0.0401983 0.956162 0.131311 0.0372168 0.400189 +0.0601263 0.0497465 0.313985 0.0452306 0.0488595 0.493684 0.0462648 0.0390909 0.882993 +0.0772586 0.0379199 0.710808 0.0117432 0.0567952 0.31534 0.0102097 0.0570919 0.287618 +0.0726245 0.0380682 0.735912 0.0334977 0.0473943 0.681216 0.118958 0.0412386 0.308328 +0.0754942 0.0443592 0.4715 0.028332 0.0543684 0.316906 0.0142005 0.0511087 0.685213 +0.0492341 0.0436402 0.709224 0.0415648 0.0391698 0.914107 0.104638 0.0410802 0.411227 +0.0373002 0.0441867 0.78916 0.0381383 0.0515581 0.402482 0.102598 0.03739 0.5696 +0.0699979 0.0440949 0.525527 0.059543 0.0422479 0.683098 0.014722 0.0476476 0.876833 +0.0653937 0.0470908 0.415832 0.0699817 0.0487646 0.288274 0.0943815 0.0410187 0.483391 +0.0100298 0.056258 0.362481 0.0710151 0.04712 0.369152 0.0336027 0.0516081 0.443012 +0.0856806 0.0443811 0.394328 0.0572059 0.0486819 0.398596 0.120638 0.0370576 0.471214 +0.0299498 0.0530291 0.389219 0.115824 0.0396317 0.399149 0.0147699 0.0458957 0.954673 +0.148865 0.0368618 0.308403 0.0541226 0.0486573 0.426325 0.0125846 0.0542971 0.489081 +0.0329113 0.0469137 0.710625 0.0135831 0.0504644 0.733546 0.124956 0.0369985 0.447239 +0.127029 0.0396562 0.325929 0.084754 0.0437615 0.430446 0.0294575 0.0472349 0.729491 +0.101379 0.0407318 0.448061 0.0110802 0.0552898 0.435242 0.0879444 0.0446445 0.364869 +0.134576 0.0394483 0.286817 0.0702723 0.0379865 0.753552 0.0132043 0.0510132 0.703921 +0.0127152 0.0458328 0.983899 0.0655417 0.0381149 0.780367 0.0543391 0.0420409 0.730584 +0.136598 0.0369273 0.379605 0.070352 0.0457363 0.444953 0.0465034 0.0510732 0.354718 +0.0314998 0.0503241 0.541178 0.0127596 0.0556314 0.391568 0.047674 0.0428061 0.754476 +0.0350834 0.0435818 0.831948 0.0254732 0.0552241 0.287094 0.141981 0.0368728 0.349347 +0.0911786 0.0407653 0.515688 0.0762676 0.0468883 0.339919 0.0516518 0.0485038 0.456124 +0.0947766 0.0372682 0.622111 0.0556227 0.0501768 0.327448 0.145399 0.0367021 0.335698 +0.104835 0.0396633 0.469294 0.0624952 0.0486796 0.354315 0.0383956 0.0530564 0.306247 +0.0113575 0.0536085 0.552223 0.0689547 0.0409415 0.663443 0.110671 0.0369665 0.535169 +0.0641375 0.0379419 0.794459 0.0796195 0.0439827 0.458072 0.0383685 0.038965 0.941683 +0.0659614 0.0456189 0.485398 0.114167 0.0369865 0.513186 0.0108489 0.0549604 0.461778 +0.0598796 0.0380797 0.818293 0.123755 0.0390889 0.371059 0.0251945 0.0526656 0.461016 +0.0298451 0.0526636 0.4138 0.108329 0.0433303 0.282675 0.0310075 0.0463477 0.756118 +0.0123098 0.0504354 0.752054 0.0542655 0.0380754 0.855245 0.126372 0.0391065 0.353691 +0.0127348 0.0475443 0.908649 0.0106718 0.0504202 0.775322 0.102497 0.0431563 0.33178 +0.0100233 0.0545051 0.504316 0.101456 0.0368424 0.595554 0.0639802 0.0436884 0.589913 +0.0859748 0.0372047 0.678631 0.0112585 0.0527876 0.610618 0.0244513 0.054231 0.36506 +0.0318486 0.0433924 0.86773 0.0517825 0.0514107 0.287557 0.00777815 0.0564355 0.303693 +0.130947 0.0367329 0.421232 0.0738916 0.0440244 0.499114 0.0856166 0.0409688 0.545605 +0.0802211 0.0466261 0.322986 0.00979494 0.053695 0.56527 0.0707366 0.043148 0.561839 +0.0288313 0.0464273 0.774276 0.00705768 0.0553135 0.407564 0.0249711 0.0545096 0.340927 +0.0316291 0.0447486 0.818942 0.0473801 0.0476628 0.538481 0.111479 0.0406101 0.385892 +0.106145 0.0371178 0.557403 0.096849 0.0393678 0.53319 0.0902512 0.0455325 0.303531 +0.0259027 0.0465503 0.798896 0.0115887 0.0499386 0.792425 0.0623542 0.0448507 0.550568 +0.0773422 0.0451447 0.41992 0.0096445 0.054271 0.525565 0.0247537 0.0517143 0.526322 +0.0277591 0.0504865 0.569797 0.0343423 0.0388746 0.972298 0.0648885 0.0452568 0.511353 +0.00642595 0.0557206 0.327789 0.103827 0.0422771 0.363442 0.0695146 0.0486475 0.298576 +0.0113997 0.0495427 0.818834 0.112735 0.0395855 0.421072 0.0788521 0.037033 0.727987 +0.0424837 0.0504999 0.425386 0.106947 0.0429604 0.310001 0.0938694 0.0433128 0.385462 +0.0509214 0.0476874 0.506093 0.0849763 0.0403244 0.575433 0.0907694 0.0371118 0.652003 +0.0408758 0.04728 0.616898 0.0524167 0.0412788 0.772262 0.0534126 0.0496223 0.378468 +0.123462 0.0369267 0.459012 0.0588987 0.0426123 0.673765 0.0589425 0.0378209 0.831425 +0.131711 0.0392316 0.314459 0.0413508 0.0465447 0.648813 0.0297022 0.0432735 0.89135 +0.0219813 0.0535763 0.434738 0.0104392 0.0475896 0.939488 0.110828 0.0393815 0.441787 +0.0116617 0.0464658 0.972909 0.00988025 0.0522204 0.667321 0.0832939 0.044509 0.405872 +0.0474846 0.041657 0.797052 0.0457283 0.0415831 0.813192 0.0602111 0.0474333 0.440484 +0.0718159 0.0435288 0.537087 0.00730124 0.0536247 0.58582 0.0272993 0.0516083 0.506302 +0.0502609 0.0513122 0.306873 0.120063 0.0366706 0.489061 0.0798155 0.0404569 0.605659 +0.0473184 0.0466994 0.587898 0.0409188 0.0435748 0.78137 0.00448674 0.0538459 0.447409 +0.137621 0.0365101 0.389855 0.0765941 0.0459239 0.387001 0.0938896 0.04537 0.28493 +0.0551759 0.0421606 0.719719 0.0930806 0.0418869 0.455337 0.0112497 0.0523205 0.642716 +0.0508294 0.0456706 0.607076 0.0982577 0.0418135 0.422672 0.0644521 0.042877 0.620687 +0.0935336 0.0422657 0.435522 0.0519068 0.0380483 0.871488 0.0293641 0.0497297 0.59735 +0.0641744 0.0462571 0.468247 0.0876782 0.0450598 0.346385 0.0250327 0.0455809 0.850518 +0.0865856 0.0419667 0.497412 0.0265611 0.0521055 0.482714 0.0267953 0.0454388 0.838265 +0.0105475 0.0495127 0.83275 0.103574 0.0392452 0.494181 0.0773753 0.0401705 0.63315 +0.0957517 0.0425693 0.40634 0.009767 0.052896 0.622021 0.0234526 0.0509665 0.586647 +0.103388 0.0388665 0.510129 0.0885425 0.0392217 0.593162 0.0259815 0.0493137 0.656375 +0.0652699 0.0485448 0.33885 0.0488901 0.0487416 0.467392 0.094971 0.0369305 0.63215 +0.0481051 0.0456538 0.631154 0.0454494 0.0475631 0.560872 0.025642 0.0499057 0.626229 +0.0375217 0.0461835 0.701199 0.0406972 0.0506326 0.434134 0.0423399 0.0500811 0.451158 +0.158618 0.036034 0.284248 0.10555 0.0365521 0.58065 0.121716 0.0402113 0.336048 +0.00976522 0.04933 0.855064 0.00943333 0.0492234 0.866339 0.0480375 0.0377114 0.905065 +0.0561059 0.0471682 0.48863 0.107628 0.0419571 0.351956 0.0296298 0.0517841 0.471557 +0.0850372 0.0426861 0.47717 0.0633692 0.0407075 0.7118 0.0290689 0.0511689 0.515199 +0.0675137 0.0404186 0.692613 0.0726692 0.0369905 0.767473 0.113616 0.0367645 0.524546 +0.00533702 0.0548149 0.377408 0.112687 0.0407688 0.370967 0.0709581 0.0480963 0.317307 +0.00935517 0.0544486 0.514465 0.0497336 0.0377278 0.893613 0.0211822 0.0472471 0.817803 +0.0254279 0.0432798 0.931082 0.061775 0.0428434 0.642458 0.0353562 0.0532111 0.324973 +0.0397478 0.0411251 0.874402 0.0436159 0.0407844 0.854753 0.0437643 0.0486393 0.519064 +0.00483893 0.0547652 0.338679 0.0221497 0.051829 0.547063 0.0212002 0.0548624 0.355385 +0.0404819 0.0469093 0.639002 0.0819029 0.0421857 0.521329 0.0963013 0.0388601 0.556011 +0.0567566 0.0408044 0.756255 0.0235414 0.049354 0.680597 0.0401212 0.0521691 0.34616 +0.00648178 0.054519 0.478779 0.135994 0.0362649 0.409017 0.0622584 0.0443966 0.572057 +0.10202 0.0429961 0.342673 0.151996 0.0360075 0.324372 0.0681209 0.0365575 0.807253 +0.00944708 0.0514797 0.723371 0.110274 0.0367395 0.545642 0.00831522 0.0510849 0.765782 +0.0923578 0.0437785 0.374382 0.0200132 0.0506824 0.642306 0.045161 0.0376976 0.924186 +0.154561 0.0362364 0.299982 0.0235126 0.0489084 0.705711 0.0330742 0.0476742 0.67124 +0.112858 0.0423151 0.299734 0.126373 0.0407348 0.282281 0.0217647 0.045557 0.886377 +0.0553904 0.0465338 0.526783 0.036732 0.0491526 0.556703 0.0778904 0.0477279 0.282426 +0.103824 0.0400905 0.458509 0.0508389 0.0464384 0.570164 0.0830501 0.0370078 0.702846 +0.0187277 0.0531559 0.498058 0.00855253 0.0470887 0.992803 0.0809245 0.0390719 0.648723 +0.0665954 0.0430398 0.597644 0.0471997 0.0451447 0.662157 0.0239379 0.0430939 0.951138 +0.00925321 0.0489039 0.887611 0.0909618 0.0364967 0.670425 0.042036 0.047796 0.579785 +0.0617832 0.0500466 0.282752 0.0176848 0.0564246 0.281802 0.0303112 0.0427508 0.902984 +0.0315044 0.051773 0.453485 0.033886 0.0431754 0.857089 0.078368 0.0412869 0.583445 +0.0228603 0.0456405 0.871072 0.102397 0.0362188 0.610705 0.045037 0.0511485 0.363445 +0.044505 0.0412455 0.83366 0.0551979 0.0461661 0.546524 0.14473 0.0360802 0.364394 +0.00582783 0.0534675 0.57664 0.0373405 0.0536067 0.280656 0.0399365 0.0511105 0.412728 +0.0295631 0.0532241 0.380396 0.136471 0.0381416 0.330959 0.0607245 0.047122 0.452445 +0.129877 0.0364514 0.438372 0.0444649 0.045211 0.68285 0.142331 0.0384007 0.283633 +0.00710182 0.0523239 0.69563 0.0556964 0.0490939 0.388604 0.0560781 0.0426499 0.694049 +0.0880045 0.0365123 0.687807 0.0292235 0.0474567 0.720901 0.00848489 0.0513914 0.742793 +0.00670101 0.0534583 0.596011 0.0791938 0.0415437 0.567293 0.0662622 0.0473538 0.395011 +0.0211315 0.0538307 0.426618 0.0069354 0.0525605 0.677554 0.0624615 0.0483357 0.373493 +0.0645424 0.0398948 0.731427 0.0484064 0.0517569 0.296279 0.0389036 0.0377904 0.963467 +0.0344131 0.0458107 0.747446 0.047152 0.0502415 0.398039 0.121551 0.0406606 0.317238 +0.0463368 0.0488536 0.484024 0.0075339 0.0541198 0.541843 0.0335484 0.0382679 0.990195 +0.0217912 0.0483439 0.755403 0.0210375 0.0427625 0.988792 0.0441981 0.0375441 0.933843 +0.00566331 0.0546319 0.426056 0.0283677 0.0427124 0.921632 0.0214039 0.0510157 0.606177 +0.0464929 0.0515086 0.328529 0.0369021 0.0501274 0.49966 0.0860036 0.0451305 0.35533 +0.0580434 0.0442467 0.612239 0.0176025 0.0502746 0.695192 0.0853542 0.0408265 0.553118 +0.123883 0.0407051 0.299938 0.0373305 0.0413435 0.887051 0.0184862 0.0521542 0.566915 +0.124621 0.0361452 0.481025 0.0826175 0.0365902 0.7181 0.00577707 0.0552116 0.354392 +0.0299768 0.0489256 0.63615 0.021386 0.0543913 0.385827 0.077163 0.036744 0.746854 +0.0796859 0.0471571 0.299118 0.144145 0.0377201 0.301378 0.0931736 0.0401633 0.526409 +0.0202088 0.0434323 0.977816 0.00834816 0.0486114 0.918482 0.00705836 0.0520981 0.713252 +0.117064 0.040581 0.350275 0.116217 0.0421971 0.282432 0.0202825 0.0541778 0.41205 +0.0326512 0.0540233 0.297843 0.073453 0.0389801 0.701337 0.00448573 0.05485 0.281986 +0.0651453 0.0473437 0.404617 0.0210063 0.0453257 0.903913 0.0703713 0.047588 0.349476 +0.086897 0.038901 0.615562 0.021074 0.055521 0.310904 0.0737691 0.0458838 0.410912 +0.0955222 0.0443408 0.32441 0.0369317 0.0503035 0.489112 0.0729219 0.0466641 0.377825 +0.0602253 0.0368951 0.847213 0.00457321 0.0540989 0.416577 0.0867332 0.0417116 0.507205 +0.0206658 0.0554377 0.320923 0.0296854 0.0499858 0.579304 0.0774572 0.0447495 0.438152 +0.0861024 0.0386399 0.62996 0.0492032 0.0422177 0.76398 0.0435942 0.051109 0.378962 +0.107488 0.0408365 0.402652 0.0147327 0.0560943 0.336622 0.0572661 0.0440017 0.629127 +0.11327 0.0415562 0.331952 0.094256 0.0451384 0.29397 0.0083495 0.0477747 0.963116 +0.114758 0.0390196 0.431255 0.121696 0.0381603 0.422014 0.0566073 0.0371118 0.864482 +0.0355011 0.0468014 0.690984 0.154872 0.0358157 0.315115 0.038414 0.0453421 0.730973 +0.0945708 0.0387349 0.571817 0.133225 0.036153 0.429705 0.00286099 0.0488674 0.995876 +0.0277077 0.0459512 0.807091 0.0182879 0.0458052 0.915549 0.0807166 0.0384117 0.672635 +0.149334 0.0359016 0.344265 0.095985 0.0364068 0.643008 0.0856085 0.0459962 0.314562 +0.0317239 0.0455875 0.78306 0.00871535 0.0488574 0.898673 0.0049019 0.0539529 0.467359 +0.0346318 0.0527196 0.363389 0.124711 0.039141 0.362788 0.00479528 0.0543645 0.397122 +0.0576842 0.0474091 0.462857 0.00804012 0.0481717 0.947604 0.062943 0.0484362 0.364007 +0.0973936 0.0407414 0.474508 0.018483 0.0512971 0.621821 0.0757511 0.0398239 0.656822 +0.0727858 0.0412515 0.624401 0.0398798 0.0478829 0.595231 0.119927 0.0362133 0.506452 +0.0794085 0.0459505 0.364014 0.0511998 0.0424664 0.739149 0.0416912 0.0450944 0.712369 +0.00667023 0.0511426 0.786448 0.0708399 0.0367007 0.786795 0.0940619 0.0408762 0.491497 +0.141183 0.0379333 0.310598 0.118063 0.0397415 0.380026 0.0359642 0.0378756 0.98139 +0.103666 0.0432135 0.32087 0.0205385 0.0491188 0.727666 0.12391 0.0384955 0.394636 +0.0790567 0.0384354 0.682598 0.078328 0.0467257 0.332407 0.0411561 0.0376806 0.95084 +0.0153725 0.0510041 0.677305 0.0492666 0.0449593 0.65284 0.0297857 0.0539158 0.332771 +0.019802 0.0484074 0.774991 0.122123 0.0385131 0.405147 0.0759556 0.0409067 0.61528 +0.0334294 0.0485943 0.619462 0.0708784 0.0411881 0.640442 0.0738664 0.0444246 0.480804 +0.0559885 0.048533 0.417137 0.0985973 0.0442442 0.306997 0.0136453 0.0553797 0.399878 +0.0379893 0.0517274 0.393499 0.0665489 0.0390947 0.7438 0.0192107 0.0560624 0.29189 +0.0299663 0.0528901 0.398035 0.0307288 0.0411232 0.946711 0.0932063 0.0364193 0.659321 +0.00521984 0.0539008 0.496327 0.0468866 0.0512766 0.339039 0.0400785 0.0501469 0.468392 +0.029591 0.0543213 0.307698 0.0914024 0.0428204 0.42569 0.0567251 0.045022 0.588068 +0.104352 0.0417026 0.385786 0.032714 0.0463636 0.73862 0.0196261 0.0504299 0.662056 +0.0632451 0.0453252 0.521198 0.00651157 0.0530422 0.633732 0.00664708 0.0508625 0.80581 +0.0224231 0.0485728 0.736076 0.0618824 0.0496417 0.305259 0.0342335 0.0485882 0.611871 +0.0645565 0.0419666 0.656435 0.0516078 0.050921 0.318488 0.10566 0.0362804 0.589178 +0.00397401 0.0532587 0.487337 0.055021 0.0400334 0.793957 0.0619905 0.0493198 0.322677 +0.0301031 0.0405883 0.965322 0.104795 0.0388262 0.502662 0.00381701 0.0541355 0.311218 +0.0309712 0.0413789 0.937856 0.0543859 0.0367973 0.885846 0.0821713 0.0433898 0.466445 +0.0538337 0.0462416 0.554305 0.0300648 0.0463588 0.764991 0.0728802 0.0385589 0.718843 +0.130865 0.0359142 0.452564 0.00409996 0.0544642 0.295334 0.0439146 0.041076 0.843545 +0.0172613 0.0536374 0.481769 0.144348 0.0358687 0.374888 0.0465338 0.0465893 0.600221 +0.06442 0.0437868 0.582219 0.0404437 0.0426471 0.81941 0.0804511 0.042006 0.539288 +0.0728875 0.036609 0.776785 0.0864375 0.0465157 0.281318 0.00471463 0.0521822 0.686218 +0.0432359 0.0424103 0.804778 0.00364225 0.0539378 0.318969 0.0322755 0.0500573 0.548993 +0.113273 0.0383912 0.465709 0.0385642 0.0492133 0.535827 0.0806521 0.0363013 0.738403 +0.0165993 0.0496502 0.744373 0.0632583 0.0472676 0.42402 0.139532 0.0358816 0.402733 +0.0163948 0.0455872 0.946696 0.0462154 0.0480662 0.527672 0.0184 0.047567 0.834757 +0.0598643 0.0395335 0.775587 0.0374389 0.0519502 0.384945 0.0723158 0.0450146 0.464778 +0.0543067 0.0499748 0.350501 0.0367283 0.0531706 0.314582 0.00408167 0.0540404 0.368697 +0.12219 0.0360911 0.497397 0.00640825 0.050322 0.845655 0.00794373 0.0485326 0.929515 +0.124719 0.0395788 0.344096 0.00479348 0.0532466 0.557467 0.13394 0.038119 0.347573 +0.0304406 0.0506479 0.532685 0.110718 0.0361295 0.56414 0.038312 0.0403939 0.906325 +0.00469704 0.0543642 0.387472 0.143445 0.035794 0.383076 0.00333233 0.0535065 0.346668 +0.0770164 0.0363901 0.757802 0.0950301 0.0436607 0.36077 0.0179472 0.0531565 0.506692 +0.14039 0.037286 0.342241 0.00527323 0.0526027 0.656356 0.0557975 0.0424509 0.703925 +0.021052 0.0529 0.489636 0.00619242 0.0539687 0.531742 0.0336283 0.0479212 0.653084 +0.158671 0.0358229 0.292517 0.0785564 0.0443502 0.448834 0.0138257 0.0557553 0.370883 +0.0496137 0.036803 0.915413 0.112067 0.0383611 0.474481 0.13155 0.0379184 0.370604 +0.112628 0.0398571 0.410445 0.039574 0.0444934 0.756591 0.0865189 0.0398002 0.58504 +0.0158831 0.0453258 0.962796 0.0525518 0.0475745 0.497873 0.0729561 0.0443831 0.489676 +0.0627457 0.045231 0.529661 0.064808 0.0366735 0.824516 0.0283009 0.0487239 0.664443 +0.0179973 0.0538784 0.457169 0.109537 0.040737 0.393289 0.147694 0.0358655 0.35533 +0.0133639 0.0556582 0.382948 0.0408615 0.0462215 0.668678 0.0187794 0.0536209 0.466145 +0.0714654 0.0440425 0.516702 0.117473 0.0358918 0.532338 0.00423026 0.0536201 0.456903 +0.0464146 0.0443965 0.701421 0.033677 0.0414613 0.913218 0.12802 0.0359756 0.467095 +0.0271035 0.054427 0.325128 0.0655322 0.0412308 0.67727 0.0536132 0.0396977 0.814257 +0.0187047 0.0482852 0.794457 0.111951 0.0379696 0.490262 0.00585198 0.0507767 0.823782 +0.103351 0.0362728 0.603225 0.0539318 0.0437586 0.666189 0.0786072 0.045926 0.371403 +0.0346415 0.0518151 0.420121 0.0508128 0.0490398 0.433965 0.0345355 0.0493876 0.564894 +0.0930167 0.0431753 0.397935 0.0687976 0.0490822 0.280048 0.0731072 0.0417745 0.601508 +0.120616 0.0378762 0.439959 0.128944 0.0401311 0.292701 0.00661069 0.0497979 0.876215 +0.135786 0.0394383 0.279566 0.0173482 0.0530128 0.523063 0.033517 0.044827 0.797988 +0.0850298 0.0363346 0.711104 0.0469522 0.0436543 0.727466 0.058519 0.0432614 0.650479 +0.0521086 0.0437725 0.680349 0.00624783 0.0485985 0.955259 0.0617375 0.0489245 0.347009 +0.0171335 0.0475262 0.852197 0.138503 0.0387296 0.293337 0.0238987 0.0535063 0.419319 +0.0155254 0.0504195 0.711719 0.0175921 0.0455278 0.934746 0.014857 0.0493412 0.784185 +0.0623092 0.0498294 0.290914 0.0659998 0.0443702 0.543896 0.0800303 0.0461798 0.34755 +0.0451046 0.0504168 0.406276 0.0767419 0.0428384 0.530693 0.0610248 0.04747 0.431806 +0.0279446 0.0549775 0.27956 0.044826 0.0424889 0.789107 0.127524 0.0400024 0.30758 +0.0116219 0.0528456 0.602091 0.0181093 0.0523551 0.558082 0.0666485 0.036559 0.816201 +0.157032 0.0356795 0.307898 0.0479148 0.0505653 0.37224 0.0594643 0.0392975 0.785649 +0.0330099 0.0532971 0.341906 0.0937178 0.0442869 0.340098 0.0461917 0.0523309 0.280637 +0.11064 0.0428282 0.290726 0.0772031 0.0450075 0.427654 0.0770343 0.047681 0.291679 +0.0620532 0.0464085 0.477887 0.0622338 0.0367059 0.839522 0.0715267 0.0453608 0.45418 +0.0774064 0.0456142 0.39628 0.0686531 0.0485927 0.308598 0.128531 0.0381732 0.378924 +0.0554143 0.048808 0.406922 0.0136466 0.0547725 0.443215 0.0279873 0.0483291 0.688852 +0.116968 0.0382005 0.449972 0.0862766 0.039418 0.600896 0.0858399 0.0445175 0.386578 +0.096935 0.0385336 0.56403 0.0269486 0.0412654 0.97453 0.119125 0.0408064 0.326696 +0.109321 0.0361082 0.573163 0.113669 0.0418651 0.315124 0.102459 0.0396748 0.484383 +0.0982183 0.0419928 0.415013 0.0481606 0.0509578 0.34677 0.030812 0.0521699 0.435537 +0.0875627 0.0420479 0.487036 0.109141 0.0394392 0.450358 0.0629455 0.0490373 0.330644 +0.0912807 0.0401968 0.537785 0.0135653 0.0550062 0.42749 0.00429001 0.0525785 0.615738 +0.0140151 0.0559548 0.354425 0.0211076 0.0503455 0.650197 0.101702 0.0360718 0.619635 +0.0780002 0.0398269 0.641442 0.0255506 0.0528605 0.444679 0.0592292 0.0442078 0.604487 +0.0567427 0.0439224 0.636712 0.00323809 0.0529614 0.437152 0.043332 0.0466774 0.624429 +0.0587432 0.046389 0.50604 0.0535063 0.0499512 0.358793 0.0157057 0.0563952 0.30457 +0.0471715 0.0488758 0.475314 0.100322 0.0376224 0.575505 0.0678834 0.0383083 0.759351 +0.100782 0.0410291 0.439464 0.0270013 0.0448323 0.860617 0.0293774 0.0450916 0.826786 +0.0447451 0.0487728 0.502846 0.0146368 0.0531602 0.544243 0.0295315 0.0533524 0.372343 +0.0941144 0.0419645 0.444751 0.0414837 0.0503668 0.442454 0.0712188 0.0362129 0.797545 +0.00622192 0.0519036 0.733757 0.0676004 0.0410142 0.670418 0.0614129 0.0423382 0.665429 +0.0290224 0.0529125 0.406006 0.133766 0.0387527 0.322037 0.0707855 0.0473343 0.359669 +0.147251 0.0369265 0.31545 0.0661292 0.0452292 0.502841 0.0781692 0.0419408 0.55833 +0.128156 0.0373737 0.413256 0.0984314 0.0407957 0.465229 0.152536 0.0356593 0.335027 +0.103645 0.038291 0.530327 0.0692934 0.0435879 0.553565 0.0504887 0.0423901 0.747573 +0.021796 0.0541992 0.394639 0.117999 0.039523 0.389673 0.0552287 0.038994 0.823671 +0.00470798 0.0528326 0.606692 0.102374 0.0383021 0.53796 0.0820777 0.0445189 0.414459 +0.0143754 0.0487075 0.826018 0.099095 0.0415069 0.430344 0.0582976 0.0410029 0.738153 +0.115933 0.0359344 0.53995 0.0401064 0.0462237 0.675457 0.0292339 0.0459688 0.790898 +0.0305725 0.0475246 0.703778 0.113605 0.0359427 0.553419 0.0158865 0.0522848 0.58839 +0.0255422 0.048353 0.713499 0.00718617 0.0478402 0.979605 0.0866779 0.0432942 0.438001 +0.0271965 0.0404052 0.992875 0.0708198 0.0386949 0.728053 0.150734 0.037264 0.280423 +0.0375754 0.0400555 0.920853 0.00421263 0.0530082 0.549203 0.0502482 0.0393483 0.848102 +0.00497977 0.0520879 0.704626 0.101753 0.0441479 0.289163 0.0683293 0.0461982 0.437914 +0.00545661 0.0516291 0.75671 0.059339 0.041136 0.725839 0.0144837 0.0498299 0.760434 +0.0632648 0.0395521 0.751515 0.0970463 0.0432119 0.367584 0.101117 0.0444181 0.280342 +0.0839736 0.0440493 0.422702 0.0234627 0.0429557 0.959849 0.0526079 0.0484859 0.448786 +0.0518158 0.0436689 0.687009 0.105023 0.0394486 0.476705 0.0420476 0.0441625 0.748476 +0.0712144 0.0424861 0.586297 0.0437888 0.0521656 0.312631 0.011519 0.0549748 0.452988 +0.00329602 0.0526422 0.506256 0.128758 0.0392285 0.333339 0.0129673 0.0568956 0.297189 +0.0148496 0.0562175 0.326475 0.075812 0.0395614 0.6657 0.0448828 0.0368849 0.943296 +0.13772 0.0373569 0.355595 0.11002 0.0409848 0.379261 0.0855214 0.04314 0.453385 +0.0477274 0.0437363 0.717743 0.0150791 0.0447336 0.993356 0.0374007 0.0428036 0.839539 +0.0792821 0.0430245 0.503944 0.0666424 0.0381078 0.773421 0.0879043 0.0362615 0.69603 +0.0460341 0.0483931 0.511828 0.0887951 0.0453757 0.322286 0.120078 0.0358828 0.51729 +0.0706803 0.0393134 0.708815 0.0960626 0.0401229 0.508705 0.0839502 0.0457575 0.339266 +0.137845 0.0355845 0.423824 0.0517895 0.0395524 0.831423 0.0249576 0.0514967 0.53776 +0.00532064 0.0483583 0.986549 0.0357897 0.0489787 0.575417 0.0922699 0.039787 0.547188 +0.0495348 0.0494879 0.420075 0.0325398 0.054185 0.28821 0.0391773 0.052156 0.35578 +0.141887 0.03569 0.396194 0.130244 0.0376505 0.389482 0.0177949 0.0515342 0.614785 +0.0556942 0.0422606 0.711977 0.0404218 0.0424364 0.826903 0.0978851 0.0358215 0.650184 +0.0988617 0.039461 0.516405 0.0107218 0.0572215 0.279474 0.0319547 0.0515388 0.463505 +0.0949069 0.0374757 0.614283 0.0363595 0.0447755 0.773842 0.00564636 0.0509249 0.815056 +0.111024 0.0376752 0.507112 0.0385293 0.0490929 0.542852 0.070272 0.0461587 0.424515 +0.045839 0.0493538 0.460682 0.0613348 0.0362303 0.85662 0.0210796 0.0496994 0.688489 +0.0939654 0.0381114 0.598148 0.0144977 0.049678 0.769233 0.00568823 0.0517169 0.749741 +0.0708343 0.0478177 0.333422 0.0876864 0.0385521 0.622795 0.0709544 0.0399984 0.683488 +0.0415488 0.0527089 0.299109 0.00428781 0.0523299 0.648724 0.145071 0.0369347 0.328241 +0.0171475 0.055385 0.361473 0.0430708 0.0396348 0.891368 0.0617731 0.0382153 0.802087 +0.0607233 0.0381759 0.810086 0.0164802 0.0473589 0.86846 0.0547485 0.0511139 0.279642 +0.0352584 0.0461306 0.724921 0.117076 0.0373627 0.4815 0.0240495 0.0446516 0.897373 +0.0116626 0.0498104 0.799169 0.0644096 0.0441655 0.56554 0.0865074 0.0428366 0.459927 +0.0654192 0.0455484 0.493134 0.084372 0.0419451 0.513971 0.0357547 0.0499758 0.519507 +0.0157216 0.0532007 0.528911 0.0116092 0.0532776 0.57232 0.107689 0.0379845 0.51634 +0.0262489 0.0550233 0.293149 0.00304213 0.0531485 0.360746 0.00641509 0.0493379 0.908308 +0.100741 0.0360225 0.626932 0.128442 0.0357215 0.473853 0.0294518 0.0495693 0.605597 +0.0115765 0.054695 0.472437 0.0241855 0.0529512 0.452951 0.139029 0.0368247 0.369031 +0.0559082 0.0500004 0.335223 0.0929871 0.0357999 0.679727 0.0228861 0.0502557 0.635665 +0.0858056 0.0448326 0.3715 0.0376107 0.0420499 0.862941 0.0154081 0.0550096 0.406826 +0.0365408 0.0437581 0.812463 0.044845 0.0429213 0.77317 0.041915 0.0462965 0.655576 +0.0372652 0.0395755 0.935183 0.133168 0.0357313 0.445765 0.0405348 0.036703 0.974068 +0.0408371 0.0431785 0.796979 0.00142903 0.051216 0.277722 0.0791484 0.0432635 0.494313 +0.00239317 0.0526999 0.288206 0.0948868 0.0381597 0.590593 0.118279 0.0400236 0.366564 +0.0223767 0.0455845 0.878597 0.0690493 0.0453352 0.474766 0.0484708 0.0467174 0.576917 +0.0559568 0.0475177 0.471748 0.00370474 0.0528624 0.521705 0.0121173 0.0494935 0.811766 +0.00551922 0.050626 0.838755 0.00332906 0.0519652 0.626049 0.105733 0.0407466 0.418249 +0.0431395 0.0470155 0.609478 0.0362887 0.0460713 0.717922 0.0844396 0.0382223 0.655019 +0.0629145 0.0445914 0.558036 0.106155 0.0404947 0.426168 0.0560928 0.0366375 0.878991 +0.137484 0.0358298 0.41674 0.00482747 0.0511585 0.795853 0.0197824 0.055185 0.347737 +0.0719761 0.044148 0.507996 0.0780865 0.0470742 0.315941 0.0275476 0.0486641 0.675555 +0.0480006 0.0460165 0.615025 0.0506993 0.0387293 0.86192 0.102185 0.0651212 0.174604 +0.0275966 0.0700147 0.157767 0.0927054 0.0603225 0.207125 0.068275 0.0774504 0.14485 +0.108549 0.0531416 0.229078 0.0415087 0.0683893 0.177653 0.0409683 0.0593869 0.225948 +0.0294171 0.0773704 0.133459 0.0613714 0.0575767 0.233 0.14856 0.0456583 0.227497 +0.123684 0.0580425 0.184646 0.140365 0.0452296 0.239257 0.13678 0.0500156 0.218185 +0.0608974 0.0639575 0.201472 0.0997014 0.0662965 0.154862 0.076656 0.0693508 0.176123 +0.0511012 0.0845413 0.121583 0.0214177 0.0609337 0.200588 0.0848418 0.0704197 0.124341 +0.0868379 0.0524247 0.246079 0.0203569 0.0574693 0.245589 0.00982295 0.0684074 0.116326 +0.0826091 0.0581327 0.221946 0.118632 0.0472813 0.248209 0.148165 0.0494428 0.191052 +0.0164621 0.062393 0.176261 0.0426856 0.055822 0.251493 0.117478 0.0570333 0.203087 +0.0175809 0.0585954 0.222895 0.0485339 0.0752044 0.155481 0.0273865 0.0821014 0.113928 +0.0703699 0.0806919 0.113751 0.00984582 0.0632717 0.142871 0.158204 0.0395246 0.251503 +0.161533 0.0446545 0.205391 0.119406 0.0565005 0.160622 0.0398128 0.0623406 0.206749 +0.0679266 0.0533483 0.252361 0.080116 0.0645765 0.194663 0.0978322 0.0615921 0.136638 +0.0898548 0.0634863 0.119889 0.0817256 0.0727009 0.15609 0.129561 0.0560302 0.180074 +0.106798 0.0592657 0.14779 0.134993 0.0534637 0.198679 0.0594968 0.0683855 0.182766 +0.165386 0.0405706 0.234486 0.0451628 0.0798698 0.138174 0.0117306 0.062135 0.160392 +0.126268 0.0493089 0.232608 0.103495 0.0481121 0.25514 0.0665053 0.0735717 0.162406 +0.102184 0.0618496 0.193645 0.0553393 0.0607547 0.217401 0.13358 0.043392 0.254704 +0.0426561 0.0876811 0.107648 0.0820885 0.0715228 0.106247 0.0646719 0.0808812 0.129827 +0.0840212 0.0728525 0.141254 0.00901378 0.0583615 0.191482 0.117687 0.054092 0.217513 +0.116849 0.060372 0.170314 0.0324416 0.06435 0.190404 0.0576792 0.086805 0.106139 +0.00872165 0.0570322 0.2581 0.00536913 0.0605095 0.128613 0.0032728 0.0599267 0.106515 +0.0759949 0.0618006 0.208052 0.0156771 0.0769262 0.105317 0.089739 0.0588136 0.106558 +0.147076 0.0491061 0.206878 0.009647 0.0579699 0.209465 0.0763118 0.0557739 0.235922 +0.0539388 0.0717211 0.16936 0.0268816 0.0563458 0.257926 0.169297 0.0414317 0.217511 +0.0895659 0.0663282 0.182241 0.0920826 0.0549148 0.23165 0.0691217 0.0593141 0.221682 +0.0305459 0.0602385 0.216693 0.0374563 0.0824681 0.124558 0.0271804 0.0583507 0.233175 +0.0359242 0.0751297 0.148205 0.015434 0.0707652 0.128909 0.0490551 0.0656375 0.192819 +0.0805618 0.0506291 0.258233 0.0540693 0.0537005 0.258682 0.00935959 0.0574016 0.235353 +0.0905499 0.0689338 0.167565 0.146029 0.0403746 0.259414 0.0270031 0.0667856 0.171291 +0.039373 0.0715482 0.163763 0.143091 0.0493216 0.177496 0.127748 0.0553239 0.170556 +0.101545 0.0516655 0.240471 0.103269 0.0566799 0.216798 0.0476079 0.057389 0.238472 +0.154832 0.0421493 0.239773 0.117552 0.045135 0.258887 0.0212791 0.0701848 0.14622 +0.0238502 0.0628904 0.189018 0.00654439 0.0580504 0.170597 0.115067 0.0608846 0.181223 +0.0557761 0.0785837 0.144802 0.0757281 0.0768794 0.130386 0.0976181 0.0544699 0.126648 +0.0921537 0.0631142 0.195094 0.0665018 0.0662797 0.191004 0.0593837 0.0552385 0.246706 +0.0209327 0.0773524 0.118628 0.157218 0.04507 0.216748 0.160288 0.0428129 0.227537 +0.00378643 0.0594447 0.117516 0.00555391 0.0585117 0.150378 0.0711471 0.0813334 0.104061 +0.0332216 0.0573776 0.242707 0.0325847 0.0867933 0.10323 0.0930984 0.0579144 0.217593 +0.169418 0.0381393 0.245477 0.160188 0.0445739 0.19275 0.00587244 0.0558928 0.246518 +0.128624 0.0536988 0.20798 0.0634922 0.0707197 0.173705 0.0922447 0.0483778 0.261269 +0.130994 0.0466762 0.240969 0.115623 0.0503784 0.236369 0.106311 0.0642361 0.164214 +0.114821 0.0543555 0.151535 0.00478206 0.0554043 0.219777 0.00901916 0.0705766 0.102109 +0.139825 0.0523547 0.185306 0.0928911 0.068546 0.145557 0.0202516 0.0596132 0.212585 +0.107004 0.0591562 0.202559 0.164611 0.037088 0.259983 0.135752 0.0498128 0.168907 +0.137617 0.0478266 0.228839 0.0387351 0.0548609 0.261835 0.117402 0.0590451 0.19139 +0.0538891 0.0819716 0.131809 0.017997 0.0568289 0.263563 0.00397533 0.0575822 0.138608 +0.0531386 0.0587731 0.228632 0.00429769 0.0557912 0.181491 0.0623575 0.0831632 0.119598 +0.031476 0.0658936 0.181218 0.0447038 0.0608719 0.216728 0.0513374 0.062731 0.207205 +0.0763776 0.0719255 0.165298 0.104997 0.0553042 0.139946 0.126132 0.0428385 0.263409 +0.147581 0.0424607 0.246367 0.0897074 0.0683553 0.134301 0.0673382 0.0513833 0.262841 +0.00407518 0.0551115 0.200447 0.0211278 0.0661812 0.164172 0.0937607 0.0544002 0.116947 +0.0648563 0.0617262 0.211259 0.0767676 0.0535877 0.246278 0.07669 0.0765139 0.119532 +0.0721235 0.0748905 0.154415 0.148004 0.047532 0.216807 0.0619604 0.0762768 0.152872 +0.0210697 0.0821359 0.100413 0.0838306 0.0621706 0.203463 0.049863 0.0891158 0.101131 +0.0778837 0.0765496 0.0994185 0.0269605 0.0792205 0.123532 0.108473 0.0454796 0.263677 +0.138082 0.0514163 0.207884 0.0446584 0.0826679 0.12808 0.0665211 0.0557129 0.240784 +0.0137831 0.065076 0.149731 0.0861673 0.0655495 0.101571 0.0302958 0.0613668 0.207709 +0.0405907 0.0743147 0.154614 0.00327984 0.0553484 0.161445 0.174467 0.0390515 0.227309 +0.125653 0.0562219 0.196671 0.128439 0.0503208 0.161688 0.117306 0.0523002 0.226237 +0.138155 0.0409591 0.263304 0.0490485 0.0677903 0.183431 0.154211 0.0452414 0.183281 +0.0645676 0.0856908 0.0991301 0.1527 0.0478665 0.199874 0.070583 0.064025 0.199821 +0.170207 0.0415094 0.207368 0.080173 0.0671078 0.184017 0.110636 0.0604444 0.156259 +0.0418729 0.0850767 0.117882 0.0387822 0.0581921 0.234731 0.15565 0.0381601 0.263053 +0.0846631 0.05997 0.212749 0.0124989 0.0590007 0.200172 0.0200464 0.0720732 0.136081 +0.0375794 0.0801675 0.132585 0.10789 0.0495135 0.245862 0.0901315 0.0701925 0.157408 +0.0962454 0.0646269 0.185129 0.0464397 0.0774924 0.146839 0.132079 0.0551064 0.189822 +0.0704471 0.0684675 0.181528 0.0967146 0.0507618 0.24764 0.0503276 0.0867925 0.111837 +0.127176 0.0516392 0.220481 0.0582698 0.0659817 0.192607 0.167249 0.0422219 0.198702 +0.00336488 0.0540176 0.229171 0.0474764 0.0534805 0.264792 0.0184464 0.0579159 0.236754 +0.174788 0.0378993 0.237478 0.0613992 0.0798524 0.138231 0.0611333 0.0590764 0.22515 +0.125485 0.0447792 0.254574 0.0164758 0.0572848 0.253367 0.0424622 0.0642273 0.197445 +0.0567038 0.0742197 0.160689 0.0846228 0.0544411 0.237972 0.0390316 0.0892594 0.0988602 +0.144152 0.0507476 0.19855 0.00159535 0.054004 0.125253 0.032572 0.0592855 0.225525 +0.0697698 0.0801277 0.122608 0.0692553 0.0575145 0.23046 0.111342 0.0470925 0.254367 +0.0935382 0.0529995 0.239479 0.0768021 0.0766654 0.109789 0.0981332 0.067186 0.164689 +0.0848975 0.0688076 0.173998 0.0133415 0.0764357 0.0981261 0.0905533 0.0540838 0.0999235 +0.00115742 0.0544976 0.0994643 0.0137731 0.0621098 0.169323 0.0783189 0.0747273 0.147325 +0.169604 0.0369792 0.253961 0.0930757 0.0628071 0.128335 0.0113834 0.066137 0.134451 +0.0453768 0.0707144 0.17037 0.00349134 0.0540125 0.264122 0.0872286 0.0650802 0.112006 +0.111615 0.0566479 0.210617 0.00316581 0.0537373 0.238699 0.12247 0.0585896 0.177218 +0.0291463 0.0746783 0.14239 0.0341737 0.0851665 0.11162 0.12209 0.0499554 0.154851 +0.110201 0.0546564 0.22099 0.0315964 0.0628415 0.198669 0.0766642 0.0497869 0.264678 +0.0023162 0.053185 0.191328 0.0144614 0.0608036 0.183855 0.0854743 0.0722199 0.149033 +0.00256827 0.0532631 0.210221 0.00964932 0.0664622 0.124443 0.0409589 0.0662531 0.186797 +0.0994042 0.0606944 0.201251 0.0639698 0.0842628 0.109187 0.0829091 0.0711364 0.115958 +0.0357425 0.0690413 0.170834 0.0992323 0.0553058 0.225609 0.0696304 0.0785634 0.136511 +0.161561 0.040098 0.243558 0.0121423 0.0579238 0.22744 0.0851404 0.0485904 0.264837 +0.0758071 0.0599175 0.216594 0.111747 0.05069 0.144428 0.0208387 0.0749467 0.127161 +0.0513141 0.0555267 0.248978 0.00140018 0.0544395 0.110485 0.0128871 0.0576399 0.242666 +0.0577169 0.0521665 0.265145 0.0938772 0.0670188 0.174862 0.138725 0.0439909 0.247138 +0.0885487 0.0504104 0.254333 0.00709 0.0663686 0.109129 0.0344356 0.0563416 0.251967 +0.0278435 0.0556181 0.266131 0.0209068 0.0793571 0.111111 0.00156582 0.0529856 0.145355 +0.0991936 0.0466051 0.26477 0.0280382 0.0720352 0.150477 0.0122737 0.0582245 0.217275 +0.0475577 0.0730537 0.162681 0.0093934 0.0571515 0.265955 0.0829853 0.0563926 0.229763 +0.0830662 0.0728521 0.132517 0.109801 0.0601438 0.194941 0.10983 0.0629836 0.173783 +0.08758 0.0651615 0.188721 0.00442893 0.0637628 0.0986761 0.0135739 0.0733642 0.112036 +0.102613 0.0513872 0.13285 0.0219408 0.0638993 0.178889 0.0522686 0.0645506 0.198459 +0.147486 0.0444728 0.235512 0.0531257 0.0696831 0.176886 0.00139147 0.0530831 0.132161 +0.003009 0.0535081 0.253496 0.0263834 0.0569903 0.249829 0.0842338 0.0707763 0.164596 +0.146672 0.0390796 0.266291 0.0205376 0.0677127 0.155393 0.0367648 0.061031 0.213811 +0.13628 0.0524522 0.176032 0.123407 0.0481015 0.240691 0.0161382 0.0604929 0.192809 +0.0999009 0.0636072 0.144831 0.0566065 0.0887189 0.0976191 0.00131594 0.0521369 0.15268 +0.0414678 0.0568958 0.243969 0.154728 0.0466004 0.209327 0.0308081 0.0693424 0.16465 +0.106925 0.0625373 0.184757 0.0921364 0.0514703 0.107159 0.113433 0.0609231 0.163457 +0.00168978 0.0524839 0.172195 0.135001 0.0461369 0.163581 0.100819 0.0533432 0.233408 +0.0281646 0.0865854 0.097233 0.089725 0.0566145 0.225272 0.0594254 0.0540843 0.253203 +0.101113 0.0588036 0.208669 0.0759106 0.0578934 0.225975 0.0248722 0.0592497 0.222132 +0.0111104 0.0601032 0.176635 0.0749738 0.0517007 0.256501 0.13397 0.0472438 0.235471 +0.0201939 0.064453 0.171816 0.0254306 0.0576685 0.241292 0.0887136 0.0598857 0.0976832 +0.0471275 0.0546039 0.257458 0.0615182 0.0724081 0.167442 0.175371 0.0396038 0.213407 +0.0157753 0.0593831 0.205909 0.0200243 0.0584144 0.22894 0.147433 0.0486635 0.182939 +0.148292 0.0454961 0.176027 0.0576705 0.0830295 0.125659 0.0706769 0.0711806 0.170738 +0.163421 0.0436542 0.21245 0.117871 0.0481759 0.14917 0.120806 0.0549656 0.210261 +0.117174 0.043575 0.266456 0.0147161 0.0720713 0.12133 0.0573591 0.085417 0.113861 +0.00125965 0.0508844 0.268594 0.0379407 0.0778925 0.140525 0.0560891 0.0568016 0.239193 +0.0373427 0.0601643 0.219999 0.0771234 0.0758824 0.138669 0.0626217 0.0603707 0.218234 +0.107301 0.0517132 0.236387 0.0336483 0.0719959 0.157257 0.0324138 0.0801345 0.127733 +0.167232 0.0413274 0.224855 0.140765 0.0470202 0.170157 0.0327487 0.0826496 0.119352 +0.0523836 0.0801258 0.139016 0.0742061 0.0662748 0.189503 0.150755 0.0405302 0.253813 +0.0613774 0.052774 0.259317 0.1429 0.0477379 0.22308 0.154452 0.0448528 0.223684 +0.154635 0.0434762 0.232098 0.141358 0.0422389 0.253697 0.139825 0.0524454 0.193009 +0.0153686 0.0677483 0.141654 0.0828361 0.070978 0.0977261 0.0937363 0.0588231 0.122944 +0.045315 0.0904335 0.0956775 0.0546081 0.0766766 0.151699 0.129077 0.0455547 0.247983 +0.0266552 0.0837606 0.10632 0.0718551 0.0819975 0.0965592 0.0460069 0.0585574 0.231198 +0.081747 0.0518167 0.251911 0.048707 0.0599301 0.22245 0.0774175 0.0632928 0.20108 +0.0957438 0.0493053 0.254835 0.17678 0.0389178 0.219625 0.165626 0.0360101 0.266909 +0.112118 0.0223889 0.183324 0.0329761 0.0197859 0.164245 0.0582767 0.0282145 0.228021 +0.103994 0.0265166 0.217625 0.0359799 0.0127631 0.140879 0.0769031 0.0181041 0.179576 +0.0500303 0.0282805 0.225069 0.115992 0.0308058 0.240806 0.135112 0.0280716 0.20558 +0.0798077 0.0145658 0.127525 0.0935471 0.0174259 0.159398 0.139262 0.0319803 0.238591 +0.0241876 0.0286411 0.19852 0.0597364 0.0110588 0.147776 0.0555507 0.00601828 0.121471 +0.0127727 0.0210603 0.121314 0.0868688 0.0302046 0.242775 0.136556 0.027761 0.19605 +0.0226922 0.0328917 0.242491 0.0294144 0.00907077 0.117753 0.153766 0.0326276 0.230842 +0.0523794 0.0226538 0.194746 0.0770112 0.0240401 0.208284 0.0140959 0.0253084 0.146728 +0.0969111 0.0219528 0.194132 0.110722 0.0231434 0.19256 0.045384 0.0317713 0.248477 +0.157358 0.0341339 0.251481 0.127113 0.0286509 0.219626 0.0530621 0.0165634 0.168539 +0.158127 0.0322905 0.208996 0.117862 0.0257141 0.163965 0.103084 0.0207965 0.182156 +0.0168263 0.0323496 0.218634 0.0127134 0.030378 0.175534 0.0364978 0.0219628 0.178345 +0.0979974 0.0247487 0.139123 0.0857931 0.0213332 0.118552 0.0641225 0.0316309 0.251583 +0.134052 0.0289126 0.175757 0.0707324 0.0098685 0.112486 0.0455114 0.00383925 0.110748 +0.103834 0.0316619 0.249948 0.0759953 0.0142963 0.160243 0.0331165 0.0287981 0.214729 +0.0767439 0.0273706 0.226203 0.129512 0.033 0.253665 0.00522429 0.0282112 0.108058 +0.020336 0.0117551 0.108438 0.0111059 0.0344437 0.255028 0.0606051 0.0249642 0.210124 +0.0849251 0.0152126 0.145183 0.143953 0.0306323 0.220376 0.155024 0.0324555 0.193202 +0.0225919 0.0167285 0.13397 0.00607579 0.0306699 0.131741 0.00778736 0.0321553 0.160927 +0.168039 0.0341337 0.219527 0.101379 0.0291581 0.234196 0.00921833 0.0333219 0.191744 +0.0366533 0.0303433 0.231123 0.068922 0.0211704 0.193455 0.03005 0.033421 0.257514 +0.0893301 0.0311173 0.105731 0.0447174 0.0147181 0.156259 0.109053 0.0274075 0.149921 +0.129277 0.0260907 0.189346 0.115239 0.0258489 0.208092 0.067431 0.00951112 0.132742 +0.167587 0.0344392 0.238797 0.0405229 0.00796651 0.127067 0.0785905 0.0323024 0.256639 +0.0263994 0.0188698 0.150116 0.0387625 0.0255277 0.199437 0.0108304 0.0341707 0.234128 +0.0811914 0.0182026 0.106647 0.058282 0.00437812 0.105932 0.007519 0.0345649 0.20648 +0.0918477 0.0239139 0.20639 0.0913592 0.0180471 0.173333 0.142782 0.0338041 0.25724 +0.0526374 0.00862638 0.135963 0.150463 0.030745 0.20511 0.0608519 0.019021 0.181882 +0.0962059 0.0316774 0.126381 0.0695953 0.0293463 0.237333 0.0313014 0.00524414 0.10406 +0.105418 0.0205361 0.167041 0.115193 0.0331448 0.258922 0.0902935 0.027095 0.224049 +0.0832677 0.0207334 0.191546 0.0245432 0.0265728 0.184521 0.0193408 0.0246081 0.160381 +0.113889 0.02833 0.224977 0.147996 0.0324927 0.182153 0.0534314 0.0328355 0.258936 +0.0460058 0.0264936 0.211397 0.0929926 0.032668 0.258369 0.0670358 0.0161456 0.170779 +0.00431991 0.0341863 0.143874 0.0101326 0.0201601 0.10413 0.021053 0.032209 0.228912 +0.0558884 0.0303249 0.241116 0.123995 0.025359 0.175791 0.128126 0.0303807 0.23214 +0.00324388 0.0337452 0.12038 0.0740436 0.0118532 0.142557 0.130786 0.0318214 0.165731 +0.107384 0.0244958 0.204101 0.0466658 0.021005 0.183372 0.0614064 0.0134123 0.158364 +0.0217063 0.0260636 0.174823 0.0225618 0.0302564 0.209209 0.0663137 0.0265272 0.2202 +0.0340349 0.0316826 0.241096 0.00656686 0.0356186 0.244545 0.00565329 0.0344105 0.169881 +0.0428543 0.0304636 0.236682 0.0905445 0.0218796 0.130886 0.0427567 0.0183933 0.169065 +0.0341449 0.0246331 0.189004 0.166432 0.0351162 0.19822 0.10083 0.0216309 0.150571 +0.0412277 0.0333533 0.260984 0.0303388 0.0115181 0.128773 0.0932417 0.0347449 0.115893 +0.0499388 0.0118202 0.148408 0.163763 0.0346444 0.260437 0.0208933 0.0340467 0.260881 +0.152049 0.0332116 0.241433 0.106779 0.0326425 0.141184 0.0714159 0.009691 0.101132 +0.00419648 0.0362572 0.183844 0.00295227 0.0382745 0.220089 0.157488 0.0324648 0.219992 +0.0812287 0.0162715 0.169059 0.125336 0.0260577 0.199971 0.0686873 0.0330273 0.261512 +0.0140867 0.0231707 0.136119 0.0923345 0.0198646 0.184268 0.167612 0.0346861 0.250036 +0.0655602 0.00814491 0.122037 0.119962 0.0322993 0.155167 0.168146 0.0344498 0.208338 +0.173357 0.0349657 0.229273 0.0749599 0.0307835 0.246703 0.138207 0.0285163 0.185255 +0.107283 0.033592 0.263848 0.0800636 0.0161578 0.116346 0.147368 0.030446 0.19166 +0.00213769 0.0342823 0.102342 0.0979507 0.0303721 0.242475 0.00428363 0.0371856 0.262266 +0.0827287 0.0257587 0.217311 0.0451162 0.00207409 0.100611 0.152734 0.0343163 0.260773 +0.00228681 0.0377218 0.15298 0.134534 0.0339191 0.262156 0.0682013 0.0232625 0.203386 +0.0219066 0.0143303 0.123101 0.0850508 0.0284371 0.232249 0.163131 0.0336224 0.229015 +0.12668 0.0315552 0.242164 0.138066 0.030706 0.227632 0.0137681 0.0320511 0.200677 +0.0847861 0.0151292 0.155378 0.0389414 0.00613661 0.117891 0.040018 0.0288431 0.222268 +0.0346577 0.0170394 0.155333 0.0848515 0.0234337 0.100026 0.113621 0.031987 0.250107 +0.114894 0.0229098 0.172807 0.0207569 0.0336051 0.251799 0.0838484 0.0227403 0.201513 +0.137765 0.0327624 0.247415 0.0253257 0.0306566 0.219158 0.0241654 0.00768901 0.100549 +0.0695547 0.0123195 0.152026 0.0516771 0.0246052 0.204287 0.0105529 0.0214818 0.112593 +0.0183008 0.029539 0.190473 0.0315548 0.0277334 0.204739 0.044037 0.0230443 0.190999 +0.00308262 0.0383252 0.253069 0.00469391 0.0361806 0.198374 0.107064 0.0305328 0.241599 +0.107296 0.0226958 0.157796 0.027664 0.0161613 0.141792 0.080739 0.0140852 0.137067 +0.0538735 0.0130186 0.154838 0.124316 0.0338222 0.263485 0.00595959 0.0251467 0.0985631 +0.112927 0.0267871 0.215552 0.0124353 0.0344835 0.264118 0.134839 0.0291448 0.216729 +0.00195884 0.0386486 0.162321 0.0149335 0.0280275 0.166411 0.101398 0.0341901 0.132717 +0.0015618 0.0370442 0.112028 0.016313 0.0129735 0.100041 0.0562418 0.0268654 0.219143 +0.0950566 0.0200325 0.145187 0.00788604 0.0270551 0.12387 0.00129881 0.0392116 0.135175 +0.0206319 0.0202569 0.143487 0.061522 0.00614322 0.113427 0.139193 0.0346814 0.169177 +0.0139838 0.0338613 0.241025 0.0548359 0.0316129 0.250011 0.0906585 0.0379833 0.0988551 +0.110795 0.0294006 0.233082 0.0635279 0.00525331 0.0988181 0.0861372 0.0333413 0.263521 +0.0430602 0.00943027 0.134926 0.0681814 0.0193285 0.184923 0.0542058 0.00250185 0.0988306 +0.0788427 0.0157373 0.0993022 0.0777077 0.0291056 0.236366 0.0668553 0.0279805 0.228682 +0.125818 0.0273845 0.210921 0.0865532 0.0316794 0.252202 0.00785094 0.0310658 0.150566 +0.0763524 0.0220599 0.19839 0.0606472 0.0209865 0.190555 0.0587375 0.0076473 0.129744 +0.0471939 0.00543815 0.119532 0.0993852 0.0194399 0.174943 0.0732904 0.0112561 0.123485 +0.00279702 0.0385397 0.228621 0.0778725 0.0133032 0.150489 0.119749 0.0244284 0.19209 +0.0175351 0.0154855 0.11548 0.0365967 0.00274122 0.0987396 0.0605851 0.0092823 0.138618 +0.00224838 0.0391132 0.211145 0.0692493 0.0248059 0.211437 0.0570626 0.0335314 0.264608 +0.0495263 0.00708062 0.128126 0.11549 0.0349903 0.148472 0.0600397 0.0229633 0.199702 +0.0938241 0.025735 0.215882 0.160212 0.0339585 0.243297 0.150595 0.0310975 0.213912 +0.0281801 0.034087 0.265514 0.0265438 0.0207786 0.158372 0.0198917 0.022729 0.152538 +0.105961 0.0280323 0.226062 0.0165581 0.0195536 0.128991 0.0866687 0.0243894 0.111654 +0.00223601 0.0388421 0.190995 0.155694 0.0348043 0.184606 0.0384587 0.0323609 0.250616 +0.00254702 0.0389111 0.237028 0.147889 0.0335571 0.250328 0.0513143 0.018854 0.177007 +0.0888516 0.0181244 0.138526 0.00052206 0.0405979 0.0962692 0.0275524 0.0316705 0.233844 +0.176301 0.0355716 0.220442 0.085437 0.0183791 0.178976 0.0108687 0.0320576 0.183771 +0.0531447 0.00438329 0.112581 0.0773057 0.033594 0.26552 0.144747 0.0343073 0.265029 +0.0714047 0.0318932 0.253847 0.121482 0.0321093 0.24871 0.0294306 0.032751 0.248758 +0.0602669 0.0171795 0.173874 0.175587 0.0352363 0.238438 0.0939018 0.0289122 0.234118 +0.0403787 0.0136541 0.148676 0.0481327 0.0158308 0.162885 0.120894 0.0241612 0.183298 +0.0142373 0.0325139 0.210421 0.00889811 0.0286758 0.140233 0.0105909 0.0340198 0.224919 +0.159197 0.0335373 0.236566 0.12106 0.0296729 0.230724 0.0749088 0.0118305 0.13279 +0.113644 0.0243786 0.199072 0.0978446 0.0336475 0.265115 0.03856 0.0270131 0.208325 +0.0400037 0.0171932 0.161761 0.00122258 0.0390749 0.127062 0.143111 0.0296403 0.209621 +0.074639 0.025766 0.217198 0.0273008 0.00808805 0.109688 0.0359578 0.0109934 0.134287 +0.0890098 0.0167055 0.165016 0.158759 0.0327085 0.200493 0.0949711 0.0315974 0.250876 +0.0758533 0.0199777 0.188447 0.031359 0.0220057 0.171822 0.0633611 0.030453 0.243565 +0.111533 0.0381892 0.142289 0.0515079 0.0295093 0.233997 0.0491402 0.0335799 0.2643 +0.146915 0.0357355 0.17431 0.1454 0.0318906 0.232311 0.0649881 0.00668475 0.106358 +0.0967464 0.018326 0.166267 0.17294 0.0360901 0.204214 0.103532 0.0261892 0.144834 +0.126946 0.0350313 0.158608 0.116058 0.0339778 0.2663 0.11411 0.0265851 0.157251 +0.0904091 0.0254546 0.122571 0.00639385 0.0277626 0.116346 0.0847526 0.0243332 0.209623 +0.0461495 0.0241658 0.198394 0.036863 0.00475518 0.109434 0.0608883 0.0292732 0.235412 +0.0308285 0.0267405 0.196931 0.0982934 0.0233526 0.201491 0.101041 0.0249345 0.209464 +0.124517 0.0273667 0.168006 0.161796 0.0352148 0.190759 0.0439031 0.0203495 0.178308 +0.0758585 0.013193 0.107037 0.0308203 0.0303524 0.224858 0.0540403 0.0207907 0.186904 +0.129262 0.0263227 0.181481 0.103642 0.0219056 0.189896 0.0346119 0.00849522 0.123057 +0.0986531 0.0384393 0.124987 0.0349361 0.0340023 0.266139 0.0925048 0.0174607 0.152356 +0.0437034 0.0294016 0.229127 0.0919172 0.0388338 0.106283 0.107164 0.0209765 0.175907 +0.17069 0.0348887 0.25715 0.0331524 0.0155009 0.147564 0.119655 0.0278884 0.219128 +0.0147955 0.016109 0.108237 0.144179 0.0294117 0.200646 0.0263606 0.0270727 0.19149 +0.175042 0.0357305 0.212645 0.000991905 0.0404421 0.143731 0.105062 0.023144 0.197003 +0.0896044 0.02173 0.195383 0.0175897 0.0288336 0.18214 0.0140495 0.0340472 0.247863 +0.0983188 0.0276873 0.22605 0.0738671 0.0163796 0.171732 0.0134283 0.027569 0.157106 +0.0292229 0.0046578 0.097115 0.0514114 0.0031241 0.105613 0.0555093 0.0146547 0.161978 +0.0612894 0.0152596 0.166144 0.0411778 0.0221676 0.184212 0.10087 0.032665 0.257506 +0.00867855 0.0343056 0.215069 0.0292545 0.0241295 0.179118 0.0954268 0.0270294 0.131011 +0.0187352 0.0329873 0.235803 0.047197 0.0325513 0.255467 0.0882474 0.0302778 0.0976232 +0.0467527 0.027563 0.21854 0.0243837 0.0233116 0.16589 0.0684194 0.0143929 0.162928 +0.163165 0.0332609 0.213971 0.099938 0.0195439 0.158154 0.0676732 0.0175764 0.1771 +0.0065731 0.0340971 0.177697 0.108156 0.0256166 0.210587 0.00181507 0.0392735 0.176256 +0.123213 0.0298117 0.161513 0.0819045 0.0192959 0.184649 0.0823612 0.0153724 0.162435 +0.17385 0.0350807 0.2452 0.1313 0.0297988 0.225437 0.0859063 0.0194447 0.125609 +0.108351 0.0326271 0.256077 0.0527737 0.0260422 0.212807 0.0113294 0.0172867 0.0970888 +0.0447749 0.0254814 0.204559 0.0487054 0.0307922 0.242089 0.083636 0.0270345 0.224291 +0.00178004 0.0397904 0.204254 0.136113 0.0333981 0.255192 0.00709084 0.0354796 0.267968 +0.0852519 0.0173209 0.132016 0.141441 0.0313934 0.177459 0.0725367 0.0284184 0.232006 +0.00127729 0.0410023 0.266948 0.00258542 0.0320758 0.0958719 0.150797 0.0317825 0.223908 +0.000589563 0.0406837 0.105571 0.133333 0.0369833 0.16201 0.144533 0.0327658 0.242842 +0.111523 0.0231029 0.163396 0.0304191 0.013395 0.135896 0.109173 0.0273632 0.220828 +0.132364 0.0313843 0.237747 0.0596467 0.0325127 0.257304 0.151194 0.0309797 0.198271 +0.121916 0.0329654 0.255792 0.0113486 0.0240787 0.128627 0.0663892 0.0105011 0.14269 +0.0231988 0.0114977 0.114973 0.0406386 0.0277236 0.214967 0.165659 0.034681 0.267589 +0.158611 0.0345802 0.26633 0.0461546 0.0106936 0.141939 0.0537141 0.0100286 0.142445 +0.0420574 0.0313362 0.243351 0.0715827 0.00865391 0.0454544 0.0196445 0.00865391 0.0454544 +0.0460881 0.000507579 0.0291092 0.0453387 0.000505933 0.0623911 0.0840402 0.0216801 0.0650094 +0.0837943 0.0212951 0.0254078 0.00743284 0.0212951 0.0655011 0.00718689 0.0216801 0.0258995 +0.0662206 0.00544469 0.0230728 0.0662206 0.00544469 0.0678361 0.0249591 0.0054688 0.0229457 +0.0248839 0.00550724 0.0679583 0.0870894 0.0273624 0.0454544 0.00413767 0.0273624 0.0454544 +0.0541989 0.00132325 0.0454544 0.036901 0.00134792 0.0459915 0.052566 0.00103995 0.0156435 +0.052566 0.00103995 0.0752654 0.00234721 0.0320267 0.0759736 0.00234721 0.0320267 0.0149353 +0.0888799 0.0320267 0.0759736 0.0888799 0.0320267 0.0149353 0.0772512 0.0133227 0.0155539 +0.0772512 0.0133227 0.075355 0.0139759 0.0133227 0.0155539 0.0139759 0.0133227 0.075355 +0.0377392 0.00119236 0.0760421 0.0377392 0.00119236 0.0148668 0.0752303 0.0114784 0.0310337 +0.0756971 0.0118849 0.059029 0.01553 0.0118849 0.0318799 0.01553 0.0118849 0.059029 +0.0894927 0.0340968 0.0583832 0.0892817 0.0333424 0.0331221 0.00194539 0.0333424 0.0577868 +0.0018263 0.0337621 0.0327265 0.0292889 0.00353771 0.0362043 0.0617272 0.0034571 0.0546606 +0.0615775 0.00340067 0.0361592 0.0296594 0.00339699 0.0548084 0.080703 0.017066 0.0488469 +0.0105277 0.0170616 0.0419098 0.0653768 0.00502644 0.00887839 0.0653768 0.00502644 0.0820305 +0.027297 0.00435895 0.079739 0.027297 0.00435893 0.0111671 0.0829819 0.0200808 0.0375865 +0.00824522 0.0200808 0.0533224 0.0835198 0.0208753 0.0797231 0.0835198 0.0208753 0.0111858 +0.0077073 0.0208753 0.0111858 0.0077073 0.0208753 0.0797231 0.0350613 0.00174693 0.0629772 +0.0561163 0.00173513 0.0636494 0.0575757 0.00210737 0.0280587 0.0351055 0.0017364 0.0271405 +0.00109604 0.0367786 0.0674667 0.00109604 0.0367786 0.0234422 0.0901311 0.0367786 0.0674667 +0.0901311 0.0367786 0.0234422 0.0457226 0.000505233 0.0402193 0.0901241 0.0367446 0.0425907 +0.00110305 0.0367446 0.0425907 0.0851729 0.0235729 0.0536885 0.00628756 0.0231655 0.0373454 +0.045728 0.000505246 0.0511927 0.0455151 0.000505209 0.0822136 0.0455151 0.000505209 0.00869533 +0.0720719 0.00899931 0.00858243 0.0720719 0.00899931 0.0823265 0.0190483 0.00907603 0.0824199 +0.0190483 0.00907603 0.00848898 0.0537038 0.00123087 0.0359114 0.0270126 0.00448532 0.0455901 +0.063833 0.00431634 0.0454517 0.0540074 0.00128685 0.0546047 0.0448815 0.000510998 0.0206687 +0.0448815 0.000510998 0.0702402 0.0373276 0.00126671 0.036118 0.0777596 0.0138234 0.0406448 +0.0134535 0.0138374 0.0502416 0.0790581 0.015177 0.0667192 0.0790581 0.015177 0.0241897 +0.012169 0.015177 0.0667192 0.012169 0.015177 0.0241897 0.0377564 0.00118934 0.05494 +0.000784368 0.0384467 0.0509601 0.0904427 0.0384467 0.0509601 0.0127199 0.014589 0.00751042 +0.0127199 0.014589 0.0833985 0.0785216 0.0146041 0.00751982 0.0785216 0.0146041 0.0833891 +0.0902812 0.0375392 0.00847584 0.0902812 0.0375392 0.0824331 0.000945933 0.0375392 0.00847584 +0.000945933 0.0375392 0.0824331 0.055549 0.00160423 0.00822725 0.055549 0.00160423 0.0826816 +0.00316702 0.0296994 0.0228596 0.0032241 0.0295512 0.0680035 0.088003 0.0295512 0.0229054 +0.0880629 0.0297066 0.0680502 0.020929 0.00779177 0.0370819 0.0704027 0.00785965 0.0371291 +0.0704027 0.00785965 0.0537798 0.0196795 0.00862954 0.016469 0.0196763 0.00863176 0.0744411 +0.0206549 0.00797048 0.0537031 0.0685811 0.00673459 0.0168149 0.0685811 0.00673459 0.074094 +0.0362354 0.00148307 0.0841542 0.0362354 0.00148307 0.00675473 0.0599916 0.00283905 0.0182064 +0.0599916 0.00283905 0.0727025 0.0864282 0.0259528 0.0331395 0.00479895 0.0259528 0.0577694 +0.0729885 0.00967297 0.0244693 0.0729885 0.00967297 0.0664396 0.0175106 0.0102338 0.0243323 +0.0174913 0.010249 0.0665817 0.0804205 0.0167263 0.0584326 0.0108264 0.0167028 0.032472 +0.0826702 0.0196364 0.0722873 0.082662 0.0196249 0.0186048 0.00856511 0.0196249 0.0723041 +0.00855689 0.0196364 0.0186216 0.0319899 0.00259479 0.0708078 0.0314263 0.00277589 0.0199056 +0.0873802 0.0280251 0.00780357 0.0873802 0.0280251 0.0831053 0.00384688 0.0280251 0.00780357 +0.00384688 0.0280251 0.0831053 0.000729134 0.038784 0.0159833 0.000729134 0.038784 0.0749257 +0.090498 0.038784 0.0159833 0.090498 0.038784 0.0749257 0.0233435 0.00633442 0.0605505 +0.0907381 0.0404939 0.0590908 0.0907381 0.0404939 0.0318181 0.000489001 0.0404939 0.0590908 +0.000489001 0.0404939 0.0318181 0.0675217 0.00613317 0.030419 0.0675217 0.00613317 0.0604899 +0.0152779 0.0121091 0.039586 0.0239265 0.00601235 0.0304513 0.080999 0.0174293 0.0309697 +0.0103411 0.0172897 0.059625 0.0758046 0.0119801 0.0513493 0.0887589 0.0316565 0.0509168 +0.00205045 0.0329843 0.0509187 0.0870508 0.0272766 0.0604742 0.00417628 0.0272766 0.0304347 +0.00351319 0.028823 0.0384442 0.0874852 0.0282716 0.038921 0.0861946 0.0254831 0.0167066 +0.0862264 0.0255462 0.0741607 0.00500124 0.0255453 0.0167479 0.00503254 0.0254831 0.0742023 +0.0838977 0.0214559 0.044276 0.00732942 0.0214559 0.0466329 0.0513313 0.000866154 0.022367 +0.0511544 0.000844079 0.0688262 0.0383717 0.0010857 0.0693349 0.0457494 0.0458676 1e-07 +0.0456136 0.0686691 1e-07 0.0456136 0.0231071 1e-07 0.0651468 0.0481949 1e-07 +0.0245593 0.0474185 1e-07 0.0264367 0.0286925 1e-07 0.0647904 0.0286925 1e-07 +0.0274722 0.0665984 1e-07 0.0637549 0.0665984 1e-07 0.0147465 0.0364494 1e-07 +0.0764806 0.0364494 1e-07 0.0331724 0.0167062 1e-07 0.0580548 0.0167062 1e-07 +0.0535099 0.0577718 1e-07 0.0380443 0.0573856 1e-07 0.0526874 0.0345333 1e-07 +0.0395498 0.0341706 1e-07 0.0335579 0.0753986 1e-07 0.0576693 0.0753986 1e-07 +0.0158942 0.060168 1e-07 0.0753329 0.060168 1e-07 0.0456136 0.00901477 1e-07 +0.0323486 0.0448292 1e-07 0.0560188 0.0441557 1e-07 0.0824872 0.0493131 1e-07 +0.00873987 0.0493131 1e-07 0.0456136 0.08268 1e-07 0.0156305 0.0269718 1e-07 +0.0755966 0.0269718 1e-07 0.0233128 0.0184247 1e-07 0.0679143 0.0184247 1e-07 +0.0650287 0.040212 1e-07 0.0253103 0.0407549 1e-07 0.0243676 0.0762969 1e-07 +0.0668595 0.0762969 1e-07 0.0298736 0.0557925 1e-07 0.0628732 0.0564083 1e-07 +0.0180159 0.0687498 1e-07 0.0732112 0.0687498 1e-07 0.0548698 0.0259305 1e-07 +0.0364836 0.0258851 1e-07 0.037234 0.0658698 1e-07 0.0545423 0.0665064 1e-07 +0.0369408 0.00941212 1e-07 0.0542863 0.00941212 1e-07 0.0083013 0.0410085 1e-07 +0.0829258 0.0410085 1e-07 0.0456136 0.0605916 1e-07 0.0458311 0.0305399 1e-07 +0.00935422 0.0571866 1e-07 0.0818729 0.0571866 1e-07 0.0538743 0.083299 1e-07 +0.0373528 0.083299 1e-07 0.0296368 0.0818438 1e-07 0.0615903 0.0818438 1e-07 +0.0408251 0.0172664 1e-07 0.0504021 0.0172664 1e-07 0.0295759 0.0107735 1e-07 +0.0616512 0.0107735 1e-07 0.00848929 0.0337362 1e-07 0.0827378 0.0337362 1e-07 +0.0464697 0.0384646 1e-07 0.0480022 0.052572 1e-07 0.017201 0.0430323 1e-07 +0.073682 0.0430657 1e-07 0.0389915 0.049642 1e-07 0.0113363 0.0649584 1e-07 +0.0798908 0.0649584 1e-07 0.0157455 0.0192047 1e-07 0.0754816 0.0192047 1e-07 +0.0315724 0.0351195 1e-07 0.060185 0.0341974 1e-07 0.0692939 0.0349315 1e-07 +0.0216999 0.0347347 1e-07 0.0415952 0.0750567 1e-07 0.049818 0.0752683 1e-07 +0.0391136 0.0413489 1e-07 0.0183749 0.0533889 1e-07 0.0728029 0.0535926 1e-07 +0.0298514 0.0224271 1e-07 0.0614073 0.0224385 1e-07 0.022453 0.0608768 1e-07 +0.0685818 0.0608875 1e-07 0.0575419 0.0520771 1e-07 +CELLS 7232 28608 +2 0 14 +2 0 28 +2 1 52 +2 1 300 +2 2 37 +2 3 38 +2 4 286 +2 5 61 +2 6 62 +2 7 63 +2 8 66 +2 9 69 +2 9 159 +2 10 268 +2 11 70 +2 11 71 +2 12 86 +2 12 231 +2 12 247 +2 13 246 +2 14 15 +2 15 16 +2 16 17 +2 17 18 +2 18 19 +2 19 20 +2 20 21 +2 21 22 +2 22 23 +2 23 24 +2 24 25 +2 25 26 +2 26 27 +2 27 1 +2 28 29 +2 29 30 +2 30 31 +2 31 32 +2 32 33 +2 33 34 +2 34 35 +2 35 36 +2 36 2 +2 37 3 +2 38 39 +2 39 40 +2 40 41 +2 41 42 +2 42 43 +2 43 44 +2 44 45 +2 45 46 +2 46 47 +2 47 48 +2 48 49 +2 49 50 +2 50 51 +2 51 4 +2 52 53 +2 53 54 +2 54 55 +2 55 56 +2 56 57 +2 57 58 +2 58 59 +2 59 60 +2 60 4 +2 61 6 +2 62 7 +2 63 64 +2 64 65 +2 65 8 +2 66 67 +2 67 68 +2 68 5 +2 69 10 +2 70 10 +2 71 72 +2 72 73 +2 73 74 +2 74 75 +2 75 76 +2 76 77 +2 77 78 +2 78 79 +2 79 80 +2 80 81 +2 81 82 +2 82 83 +2 83 84 +2 84 85 +2 85 12 +2 86 87 +2 87 88 +2 88 89 +2 89 90 +2 90 91 +2 91 92 +2 92 93 +2 93 94 +2 94 95 +2 95 96 +2 96 97 +2 97 98 +2 98 99 +2 99 100 +2 100 101 +2 101 102 +2 102 103 +2 103 104 +2 104 105 +2 105 106 +2 106 107 +2 107 108 +2 108 109 +2 109 110 +2 110 111 +2 111 112 +2 112 113 +2 113 114 +2 114 115 +2 115 116 +2 116 117 +2 117 118 +2 118 119 +2 119 120 +2 120 121 +2 121 122 +2 122 123 +2 123 124 +2 124 125 +2 125 126 +2 126 127 +2 127 128 +2 128 129 +2 129 130 +2 130 131 +2 131 132 +2 132 133 +2 133 134 +2 134 135 +2 135 136 +2 136 137 +2 137 138 +2 138 139 +2 139 140 +2 140 141 +2 141 142 +2 142 143 +2 143 144 +2 144 145 +2 145 146 +2 146 147 +2 147 148 +2 148 149 +2 149 150 +2 150 151 +2 151 152 +2 152 153 +2 153 154 +2 154 155 +2 155 156 +2 156 157 +2 157 158 +2 158 8 +2 159 160 +2 160 161 +2 161 162 +2 162 163 +2 163 164 +2 164 165 +2 165 166 +2 166 167 +2 167 168 +2 168 169 +2 169 170 +2 170 171 +2 171 172 +2 172 173 +2 173 174 +2 174 175 +2 175 176 +2 176 177 +2 177 178 +2 178 179 +2 179 180 +2 180 181 +2 181 182 +2 182 183 +2 183 184 +2 184 185 +2 185 186 +2 186 187 +2 187 188 +2 188 189 +2 189 190 +2 190 191 +2 191 192 +2 192 193 +2 193 194 +2 194 195 +2 195 196 +2 196 197 +2 197 198 +2 198 199 +2 199 200 +2 200 201 +2 201 202 +2 202 203 +2 203 204 +2 204 205 +2 205 206 +2 206 207 +2 207 208 +2 208 209 +2 209 210 +2 210 211 +2 211 212 +2 212 213 +2 213 214 +2 214 215 +2 215 216 +2 216 217 +2 217 218 +2 218 219 +2 219 220 +2 220 221 +2 221 222 +2 222 223 +2 223 224 +2 224 225 +2 225 226 +2 226 227 +2 227 228 +2 228 229 +2 229 230 +2 230 6 +2 231 232 +2 232 233 +2 233 234 +2 234 235 +2 235 236 +2 236 237 +2 237 238 +2 238 239 +2 239 240 +2 240 241 +2 241 242 +2 242 243 +2 243 244 +2 244 245 +2 245 13 +2 246 9 +2 247 248 +2 248 249 +2 249 250 +2 250 251 +2 251 252 +2 252 253 +2 253 254 +2 254 255 +2 255 256 +2 256 257 +2 257 258 +2 258 259 +2 259 260 +2 260 261 +2 261 262 +2 262 263 +2 263 264 +2 264 265 +2 265 266 +2 266 267 +2 267 4 +2 268 269 +2 269 270 +2 270 271 +2 271 272 +2 272 273 +2 273 274 +2 274 275 +2 275 276 +2 276 277 +2 277 278 +2 278 279 +2 279 280 +2 280 281 +2 281 282 +2 282 283 +2 283 284 +2 284 285 +2 285 3 +2 286 287 +2 287 288 +2 288 289 +2 289 290 +2 290 291 +2 291 292 +2 292 293 +2 293 294 +2 294 295 +2 295 296 +2 296 297 +2 297 298 +2 298 299 +2 299 2 +2 300 301 +2 301 302 +2 302 303 +2 303 304 +2 304 305 +2 305 306 +2 306 307 +2 307 308 +2 308 309 +2 309 310 +2 310 311 +2 311 312 +2 312 313 +2 313 0 +3 0 406 14 +3 0 3305 28 +3 0 3419 313 +3 1 409 52 +3 1 3303 300 +3 1 3398 27 +3 1 3420 3398 +3 2 285 37 +3 2 464 36 +3 2 3061 285 +3 2 3306 299 +3 3 464 37 +3 3 2655 38 +3 4 404 51 +3 4 2654 267 +3 4 3014 286 +3 4 3304 60 +3 5 479 68 +3 5 480 479 +3 5 1973 61 +3 6 480 61 +3 6 996 62 +3 6 1973 230 +3 7 480 62 +3 7 887 63 +3 7 996 887 +3 8 925 158 +3 8 1907 66 +3 9 1099 159 +3 9 2395 246 +3 9 2769 268 +3 10 69 268 +3 10 1099 69 +3 10 3189 70 +3 11 923 70 +3 11 994 923 +3 11 2998 71 +3 11 3185 2998 +3 12 2804 231 +3 12 3206 247 +3 13 1867 245 +3 13 2335 1867 +3 13 2707 246 +3 14 441 15 +3 14 3399 0 +3 14 3423 3399 +3 15 441 16 +3 15 3423 14 +3 15 3440 3423 +3 16 403 17 +3 16 441 363 +3 16 3440 15 +3 17 383 18 +3 17 403 383 +3 17 3411 16 +3 18 357 19 +3 18 383 357 +3 18 3407 17 +3 18 3427 3407 +3 19 410 20 +3 19 3427 18 +3 20 381 21 +3 20 410 381 +3 20 3426 19 +3 21 425 22 +3 21 3400 20 +3 21 3425 3400 +3 22 359 23 +3 22 425 359 +3 22 3425 21 +3 22 3428 3425 +3 23 384 24 +3 23 3428 22 +3 24 405 25 +3 24 3408 23 +3 24 3412 3408 +3 25 405 365 +3 25 444 26 +3 25 3412 24 +3 25 3441 3412 +3 26 444 27 +3 26 3441 25 +3 27 409 1 +3 27 444 409 +3 27 3424 26 +3 28 406 0 +3 28 450 406 +3 28 3343 29 +3 29 450 28 +3 29 3268 30 +3 29 3343 3268 +3 30 372 29 +3 30 452 372 +3 30 3351 31 +3 31 452 30 +3 31 3273 32 +3 31 3351 3273 +3 32 401 31 +3 32 3297 33 +3 33 375 32 +3 33 454 375 +3 33 3350 34 +3 34 454 33 +3 34 3267 35 +3 34 3350 3267 +3 35 371 34 +3 35 448 371 +3 35 3344 36 +3 36 448 35 +3 36 464 407 +3 36 3306 2 +3 36 3344 3306 +3 37 285 3 +3 37 464 2 +3 38 443 407 +3 38 464 3 +3 38 2713 39 +3 39 443 38 +3 39 2713 40 +3 40 408 364 +3 40 443 39 +3 40 2653 41 +3 40 2713 2552 +3 41 408 40 +3 41 2586 42 +3 41 2653 2586 +3 42 382 41 +3 42 2742 43 +3 43 356 42 +3 43 411 356 +3 43 2642 44 +3 43 2742 2642 +3 44 411 43 +3 44 2793 45 +3 45 380 44 +3 45 424 380 +3 45 2731 46 +3 45 2793 2588 +3 46 424 45 +3 46 2607 47 +3 46 2731 2607 +3 47 358 46 +3 47 385 358 +3 47 2797 48 +3 48 385 47 +3 48 400 385 +3 48 2589 49 +3 48 2797 2589 +3 49 400 48 +3 49 439 362 +3 49 2791 50 +3 50 439 49 +3 50 2753 51 +3 50 2791 2596 +3 51 439 50 +3 51 2654 4 +3 51 2753 2654 +3 52 446 53 +3 52 3303 1 +3 52 3345 3303 +3 53 370 54 +3 53 446 370 +3 53 3345 52 +3 54 456 55 +3 54 3270 53 +3 54 3349 3270 +3 55 402 56 +3 55 456 402 +3 55 3349 54 +3 56 377 57 +3 56 402 377 +3 56 3272 55 +3 56 3298 3272 +3 57 453 58 +3 57 3298 56 +3 57 3348 3298 +3 58 373 59 +3 58 453 373 +3 58 3348 57 +3 59 449 60 +3 59 3269 58 +3 59 3346 3269 +3 60 404 4 +3 60 449 404 +3 60 3346 59 +3 61 480 5 +3 61 1973 6 +3 62 480 6 +3 62 996 7 +3 63 64 68 +3 63 479 7 +3 63 1313 64 +3 64 65 67 +3 64 1288 65 +3 64 1313 936 +3 65 8 66 +3 65 925 8 +3 65 1288 925 +3 66 2274 67 +3 67 65 66 +3 67 2274 1909 +3 67 2308 68 +3 68 64 67 +3 68 479 63 +3 68 1858 5 +3 68 2308 1858 +3 69 1099 9 +3 70 1099 10 +3 70 3185 11 +3 70 3189 3185 +3 71 994 11 +3 71 1412 994 +3 71 2998 2933 +3 71 3048 72 +3 72 1273 1013 +3 72 1412 71 +3 72 3130 73 +3 73 1273 72 +3 73 3101 74 +3 73 3130 2928 +3 74 844 73 +3 74 1270 844 +3 74 3041 75 +3 74 3101 3041 +3 75 1270 74 +3 75 2942 76 +3 75 3041 2942 +3 76 913 75 +3 76 3067 77 +3 77 823 76 +3 77 1093 823 +3 77 3017 78 +3 77 3067 3017 +3 78 1093 77 +3 78 3085 79 +3 79 878 78 +3 79 1224 878 +3 79 2952 80 +3 79 3085 2952 +3 80 1224 79 +3 80 3109 81 +3 81 908 80 +3 81 2995 82 +3 81 3109 2995 +3 82 828 81 +3 82 1173 828 +3 82 2962 83 +3 82 2995 2962 +3 83 1173 82 +3 83 1295 915 +3 83 3068 84 +3 84 1295 83 +3 84 3068 2960 +3 84 3207 85 +3 85 12 86 +3 85 1295 84 +3 85 3206 12 +3 85 3207 3206 +3 86 12 231 +3 86 822 85 +3 86 1797 87 +3 87 822 86 +3 87 1134 822 +3 87 2109 88 +3 88 1134 87 +3 88 1202 872 +3 88 2109 1845 +3 88 2181 89 +3 89 1202 88 +3 89 1969 90 +3 89 2181 1969 +3 90 989 89 +3 90 1837 91 +3 90 1969 1837 +3 91 862 90 +3 91 1266 862 +3 91 2252 92 +3 92 1266 91 +3 92 1977 93 +3 92 2252 1977 +3 93 998 92 +3 93 1147 998 +3 93 2126 94 +3 94 1147 93 +3 94 1877 95 +3 94 2126 1877 +3 95 909 94 +3 95 1094 909 +3 95 2062 96 +3 96 1094 95 +3 96 1136 1094 +3 96 2098 97 +3 97 1125 789 +3 97 1136 96 +3 97 2098 1761 +3 97 2328 98 +3 98 1125 97 +3 98 1435 1125 +3 98 2078 99 +3 98 2328 2078 +3 99 1368 900 +3 99 1435 98 +3 99 2078 1834 +3 99 2415 100 +3 100 1368 99 +3 100 2319 101 +3 100 2415 2319 +3 101 978 100 +3 101 1450 978 +3 101 1972 102 +3 101 2319 1972 +3 102 1308 895 +3 102 1450 101 +3 102 1972 1884 +3 102 2392 103 +3 103 1308 102 +3 103 2058 104 +3 103 2392 2058 +3 104 1057 103 +3 104 1320 759 +3 104 2058 1737 +3 104 2135 105 +3 105 1320 104 +3 105 2377 106 +3 106 1139 105 +3 106 1923 107 +3 106 2377 1923 +3 107 885 106 +3 107 1430 885 +3 107 1923 1756 +3 107 2088 108 +3 108 1430 107 +3 108 1994 109 +3 108 2088 1994 +3 109 1043 108 +3 109 1258 1043 +3 109 2315 110 +3 110 1258 109 +3 110 1336 1258 +3 110 2315 111 +3 111 1206 842 +3 111 1336 110 +3 111 2131 112 +3 111 2315 1811 +3 112 1206 111 +3 112 1348 1206 +3 112 2265 113 +3 113 1256 860 +3 113 1348 112 +3 113 2265 1840 +3 113 2269 114 +3 114 1256 113 +3 114 2095 115 +3 114 2269 2095 +3 115 1124 114 +3 115 1232 1124 +3 115 2205 116 +3 116 1232 115 +3 116 1798 117 +3 116 2205 1798 +3 117 825 116 +3 117 1069 825 +3 117 2045 118 +3 118 1069 117 +3 118 1190 1069 +3 118 2045 1690 +3 118 2142 119 +3 119 1190 118 +3 119 1873 120 +3 119 2142 1873 +3 120 901 119 +3 120 1221 901 +3 120 2219 121 +3 121 1221 120 +3 121 1386 1221 +3 121 2376 122 +3 122 1005 812 +3 122 1386 121 +3 122 1978 123 +3 122 2376 1790 +3 123 1005 122 +3 123 1350 1005 +3 123 2333 124 +3 124 1350 123 +3 124 2027 125 +3 124 2333 2027 +3 125 1059 124 +3 125 1864 126 +3 125 2027 1864 +3 126 892 125 +3 126 1402 892 +3 126 2383 127 +3 127 1402 126 +3 127 1890 128 +3 127 2383 1890 +3 128 916 127 +3 128 1326 916 +3 128 2312 129 +3 129 1178 877 +3 129 1326 128 +3 129 2157 130 +3 129 2312 1856 +3 130 1178 129 +3 130 1924 131 +3 130 2157 1924 +3 131 945 130 +3 131 1727 132 +3 131 1924 1727 +3 132 750 131 +3 132 1105 750 +3 132 2075 133 +3 133 1105 132 +3 133 1928 134 +3 133 2075 1928 +3 134 946 133 +3 134 1121 946 +3 134 2100 135 +3 135 1121 134 +3 135 1810 136 +3 135 2100 1810 +3 136 832 135 +3 136 1092 832 +3 136 2067 137 +3 137 1092 136 +3 137 1999 138 +3 137 2067 1999 +3 138 1024 137 +3 138 1250 1024 +3 138 2240 139 +3 139 1250 138 +3 139 1838 140 +3 139 2240 1838 +3 140 865 139 +3 140 1188 865 +3 140 2180 141 +3 141 1188 140 +3 141 2122 142 +3 141 2180 2122 +3 142 1142 141 +3 142 1212 764 +3 142 2122 1739 +3 142 2191 143 +3 143 1212 142 +3 143 1950 144 +3 143 2191 1950 +3 144 971 143 +3 144 1362 971 +3 144 2344 145 +3 145 1362 144 +3 145 1967 146 +3 145 2344 1967 +3 146 991 145 +3 146 1439 790 +3 146 1967 1771 +3 146 2414 147 +3 147 1439 146 +3 147 2053 148 +3 147 2414 2053 +3 148 1084 147 +3 148 1816 149 +3 148 2053 1816 +3 149 840 148 +3 149 1802 150 +3 149 1816 1802 +3 150 827 149 +3 150 1143 827 +3 150 2112 151 +3 151 1143 150 +3 151 1844 152 +3 151 2112 1844 +3 152 866 151 +3 152 933 866 +3 152 1910 153 +3 153 933 152 +3 153 1318 933 +3 153 2303 154 +3 154 1318 153 +3 154 2009 155 +3 154 2303 2009 +3 155 1036 154 +3 155 1901 156 +3 155 2009 1901 +3 156 926 155 +3 156 1423 926 +3 156 2393 157 +3 157 1423 156 +3 157 2003 158 +3 157 2393 2003 +3 158 1020 157 +3 158 1907 8 +3 158 2003 1907 +3 159 1081 160 +3 159 1099 1081 +3 159 2395 9 +3 159 2397 1940 +3 160 1026 161 +3 160 1081 1026 +3 160 2397 159 +3 161 1344 162 +3 161 2051 1697 +3 161 2059 160 +3 162 1160 163 +3 162 1344 1015 +3 162 2051 161 +3 162 2071 2051 +3 163 1160 164 +3 163 2071 162 +3 164 911 165 +3 164 1160 761 +3 164 1722 163 +3 164 1824 1722 +3 165 1347 166 +3 165 1824 164 +3 165 2099 1824 +3 166 1011 167 +3 166 1347 1011 +3 166 2099 165 +3 166 2374 1925 +3 167 1087 168 +3 167 2374 166 +3 168 1352 169 +3 168 2087 167 +3 169 1352 956 +3 169 1377 170 +3 169 1812 168 +3 169 2097 1812 +3 170 1062 171 +3 170 1377 1062 +3 170 2097 169 +3 171 1452 172 +3 171 1985 170 +3 172 965 173 +3 172 1452 965 +3 172 1705 171 +3 172 1951 1705 +3 173 937 174 +3 173 965 937 +3 173 1951 172 +3 174 1240 175 +3 174 1911 173 +3 174 2224 1911 +3 175 786 176 +3 175 1240 786 +3 175 2224 174 +3 176 1146 177 +3 176 1760 175 +3 176 2132 1760 +3 177 1004 178 +3 177 1146 1004 +3 177 2132 176 +3 178 850 179 +3 178 1004 850 +3 178 1982 177 +3 179 1075 180 +3 179 1833 178 +3 179 2046 1833 +3 180 1053 181 +3 180 1075 1053 +3 180 2046 179 +3 181 1327 182 +3 181 2028 180 +3 181 2298 2028 +3 182 838 183 +3 182 1327 838 +3 182 2298 181 +3 182 2404 1815 +3 183 1437 184 +3 183 2404 182 +3 184 1133 185 +3 184 1437 1133 +3 184 2404 183 +3 185 1133 932 +3 185 1293 186 +3 185 2107 184 +3 185 2278 1906 +3 186 1116 187 +3 186 1293 1116 +3 186 2278 185 +3 187 730 188 +3 187 1116 730 +3 187 2092 186 +3 188 907 189 +3 188 1702 187 +3 188 1878 1702 +3 189 773 190 +3 189 907 773 +3 189 1878 188 +3 190 924 191 +3 190 1753 189 +3 190 1893 1753 +3 191 1271 192 +3 191 1893 190 +3 191 2259 1893 +3 192 1227 193 +3 192 1271 1227 +3 192 2259 191 +3 193 1438 194 +3 193 2216 192 +3 193 2407 2216 +3 194 1068 195 +3 194 1438 1068 +3 194 2407 193 +3 195 1068 785 +3 195 1376 196 +3 195 2038 194 +3 195 2353 1766 +3 196 1127 197 +3 196 1376 1127 +3 196 2353 195 +3 197 769 198 +3 197 1127 769 +3 197 2104 196 +3 198 938 199 +3 198 1747 197 +3 198 1897 1747 +3 199 1111 200 +3 199 1897 198 +3 199 2069 1897 +3 200 930 201 +3 200 1111 930 +3 200 2069 199 +3 201 1310 202 +3 201 1887 200 +3 201 2280 1887 +3 202 947 203 +3 202 1310 947 +3 202 2280 201 +3 203 864 204 +3 203 947 864 +3 203 1934 202 +3 204 1260 205 +3 204 1839 203 +3 204 2241 1839 +3 205 1260 920 +3 205 1338 206 +3 205 2241 204 +3 205 2348 1892 +3 206 1276 207 +3 206 1338 1276 +3 206 2348 205 +3 207 869 208 +3 207 1276 869 +3 207 2283 206 +3 208 1457 209 +3 208 1841 207 +3 209 1017 210 +3 209 1457 1017 +3 209 1687 208 +3 209 1998 1687 +3 210 1449 211 +3 210 1998 209 +3 210 2416 1998 +3 211 1060 212 +3 211 1449 1060 +3 211 2416 210 +3 212 1364 213 +3 212 2039 211 +3 212 2339 2039 +3 213 1159 214 +3 213 1364 1159 +3 213 2339 212 +3 214 1159 798 +3 214 1434 215 +3 214 2141 213 +3 214 2406 1779 +3 215 1110 216 +3 215 1434 1110 +3 215 2406 214 +3 216 820 217 +3 216 1110 820 +3 216 2089 215 +3 217 821 218 +3 217 1800 216 +3 217 1801 1800 +3 218 1168 219 +3 218 1801 217 +3 218 2153 1801 +3 219 890 220 +3 219 1168 890 +3 219 2153 218 +3 220 1001 221 +3 220 1863 219 +3 220 1981 1863 +3 221 1401 222 +3 221 1981 220 +3 221 2375 1981 +3 222 959 223 +3 222 1401 959 +3 222 2375 221 +3 223 1123 224 +3 223 1933 222 +3 223 2090 1933 +3 224 1123 225 +3 224 2090 223 +3 225 1021 226 +3 225 1123 770 +3 225 1987 1744 +3 225 2090 224 +3 226 1200 227 +3 226 1987 225 +3 226 2161 1987 +3 227 979 228 +3 227 1200 979 +3 227 2161 226 +3 228 979 766 +3 228 1286 229 +3 228 1964 227 +3 228 2272 1746 +3 229 1339 230 +3 229 2272 228 +3 229 2322 2272 +3 230 996 6 +3 230 1339 996 +3 230 2322 229 +3 231 1797 86 +3 231 2276 1797 +3 231 2615 232 +3 231 2804 2615 +3 232 2276 231 +3 232 2724 233 +3 233 2154 1886 +3 233 2276 232 +3 233 2604 234 +3 233 2724 2604 +3 234 2154 233 +3 234 2573 235 +3 234 2604 2573 +3 235 1849 234 +3 235 1936 1849 +3 235 2766 236 +3 236 1936 235 +3 236 2288 1681 +3 236 2591 237 +3 236 2766 2591 +3 237 2288 236 +3 237 2703 238 +3 238 2068 1763 +3 238 2288 237 +3 238 2687 239 +3 238 2703 2546 +3 239 2068 238 +3 239 2672 240 +3 239 2687 2672 +3 240 1853 239 +3 240 2149 1853 +3 240 2576 241 +3 240 2672 2576 +3 241 2149 240 +3 241 2360 1866 +3 241 2694 242 +3 242 2360 241 +3 242 2632 243 +3 242 2694 2632 +3 243 2186 242 +3 243 2560 244 +3 243 2632 2560 +3 244 1879 243 +3 244 2175 1879 +3 244 2700 245 +3 245 2175 244 +3 245 2563 13 +3 245 2700 2563 +3 246 2335 13 +3 246 2395 1940 +3 246 2707 2662 +3 246 2769 9 +3 247 2658 2557 +3 247 2804 12 +3 247 3135 248 +3 247 3206 2932 +3 248 2658 247 +3 248 3135 2945 +3 248 3174 249 +3 249 2541 248 +3 249 2634 2541 +3 249 3073 250 +3 249 3174 3073 +3 250 2634 249 +3 250 2949 251 +3 250 3073 2949 +3 251 2600 250 +3 251 2803 2600 +3 251 3063 252 +3 252 2803 251 +3 252 3141 253 +3 253 2756 252 +3 253 3106 254 +3 253 3141 3106 +3 254 2610 253 +3 254 2630 2610 +3 254 2926 255 +3 254 3106 2926 +3 255 2630 254 +3 255 3121 256 +3 256 2542 255 +3 256 2606 2542 +3 256 3055 257 +3 256 3121 3055 +3 257 2606 256 +3 257 2760 2606 +3 257 3055 2899 +3 257 3102 258 +3 258 2760 257 +3 258 2779 2760 +3 258 3011 259 +3 258 3102 3011 +3 259 2779 258 +3 259 3193 260 +3 260 2669 2602 +3 260 2740 259 +3 260 3108 261 +3 260 3193 3108 +3 261 2669 260 +3 261 2764 2669 +3 261 3043 262 +3 261 3108 2947 +3 262 2764 261 +3 262 3099 263 +3 263 2689 262 +3 263 2715 2572 +3 263 3002 264 +3 263 3099 2935 +3 264 2715 263 +3 264 3129 265 +3 265 2528 264 +3 265 2579 2528 +3 265 2930 266 +3 265 3129 2930 +3 266 2579 265 +3 266 2737 2579 +3 266 3133 267 +3 267 2737 266 +3 267 3014 4 +3 267 3133 3014 +3 268 69 9 +3 268 2721 269 +3 268 2769 2662 +3 268 2988 2957 +3 268 3189 10 +3 269 2721 270 +3 269 2988 268 +3 270 2665 271 +3 270 2721 2543 +3 270 2988 269 +3 270 3057 2920 +3 271 2631 272 +3 271 2665 2631 +3 271 3057 270 +3 272 2551 273 +3 272 2631 2551 +3 272 3033 271 +3 273 2676 274 +3 273 2938 272 +3 273 3039 2938 +3 274 2577 275 +3 274 2676 2577 +3 274 3039 273 +3 274 3183 3039 +3 275 2673 276 +3 275 3054 2989 +3 275 3183 274 +3 276 2566 277 +3 276 2673 2566 +3 276 3054 275 +3 276 3170 2937 +3 277 2739 278 +3 277 3170 276 +3 278 2599 279 +3 278 2739 2599 +3 278 3000 2921 +3 278 3170 277 +3 279 2732 280 +3 279 3000 278 +3 280 2702 281 +3 280 2732 2702 +3 280 2961 279 +3 280 3142 2961 +3 281 2702 2564 +3 281 2720 282 +3 281 3142 280 +3 282 2644 283 +3 282 2720 2644 +3 282 3008 281 +3 282 3088 3008 +3 283 2644 2535 +3 283 2692 284 +3 283 3003 2910 +3 283 3088 282 +3 284 2692 285 +3 284 3003 283 +3 284 3192 3003 +3 285 2655 3 +3 285 2692 2655 +3 285 3192 284 +3 286 3161 287 +3 286 3304 4 +3 286 3340 3304 +3 287 2974 288 +3 287 3161 2974 +3 287 3340 286 +3 288 3021 289 +3 288 3302 3259 +3 288 3340 287 +3 289 2936 290 +3 289 3021 2936 +3 289 3302 288 +3 290 3016 291 +3 290 3280 289 +3 291 3020 292 +3 291 3254 290 +3 291 3308 3254 +3 292 2959 293 +3 292 3020 2959 +3 292 3308 291 +3 293 3037 294 +3 293 3277 292 +3 293 3321 3277 +3 294 3150 295 +3 294 3321 293 +3 295 3004 296 +3 295 3150 2981 +3 295 3255 294 +3 295 3281 3255 +3 296 3179 297 +3 296 3281 295 +3 296 3300 3281 +3 297 2996 298 +3 297 3179 2996 +3 297 3300 296 +3 297 3342 3262 +3 298 3190 299 +3 298 3342 297 +3 299 3061 2 +3 299 3190 3061 +3 299 3342 298 +3 300 3339 301 +3 300 3420 1 +3 300 3434 3420 +3 301 3339 302 +3 301 3434 300 +3 302 3301 303 +3 302 3339 3260 +3 302 3402 301 +3 302 3443 3402 +3 303 3279 304 +3 303 3301 3279 +3 303 3443 302 +3 304 3253 305 +3 304 3279 3253 +3 304 3404 303 +3 304 3432 3404 +3 305 3307 306 +3 305 3432 304 +3 306 3278 307 +3 306 3307 3278 +3 306 3418 305 +3 307 3322 308 +3 307 3395 306 +3 307 3417 3395 +3 308 3256 309 +3 308 3322 3256 +3 308 3417 307 +3 308 3431 3417 +3 309 3282 310 +3 309 3431 308 +3 310 3299 311 +3 310 3403 309 +3 310 3442 3403 +3 311 3299 3261 +3 311 3341 312 +3 311 3442 310 +3 312 3341 313 +3 312 3401 311 +3 312 3433 3401 +3 313 3305 0 +3 313 3341 3305 +3 313 3433 312 +3 314 417 388 +3 314 418 393 +3 314 460 417 +3 315 416 387 +3 315 461 394 +3 316 389 367 +3 316 399 379 +3 316 476 390 +3 316 478 366 +3 317 386 374 +3 317 392 369 +3 317 477 368 +3 318 433 376 +3 318 435 395 +3 318 465 414 +3 318 472 435 +3 319 430 396 +3 319 466 378 +3 319 470 412 +3 320 458 397 +3 320 471 413 +3 321 432 415 +3 321 438 398 +3 321 459 432 +3 321 473 438 +3 322 440 358 +3 322 451 366 +3 323 445 426 +3 323 447 422 +3 323 469 447 +3 324 427 423 +3 324 455 368 +3 325 420 359 +3 325 429 420 +3 325 442 369 +3 325 457 429 +3 326 462 375 +3 326 467 376 +3 326 474 360 +3 327 432 361 +3 327 463 432 +3 327 468 377 +3 327 475 378 +3 328 379 374 +3 328 386 351 +3 328 388 352 +3 328 389 379 +3 329 387 350 +3 329 392 374 +3 329 399 353 +3 330 411 380 +3 330 426 411 +3 330 476 426 +3 331 391 381 +3 331 477 391 +3 332 415 370 +3 332 446 409 +3 332 473 415 +3 333 414 371 +3 333 448 407 +3 333 472 414 +3 334 408 382 +3 334 422 395 +3 334 435 364 +3 334 445 422 +3 335 400 362 +3 335 419 385 +3 335 428 419 +3 335 436 396 +3 336 405 384 +3 336 429 398 +3 336 438 365 +3 337 403 363 +3 337 423 383 +3 337 434 423 +3 337 437 397 +3 338 439 404 +3 338 449 373 +3 338 470 439 +3 339 441 406 +3 339 450 372 +3 339 471 441 +3 340 390 380 +3 340 424 358 +3 340 478 390 +3 341 391 369 +3 341 425 381 +3 341 442 359 +3 342 433 395 +3 342 447 417 +3 342 460 433 +3 343 428 396 +3 343 451 428 +3 343 461 421 +3 344 434 397 +3 344 455 434 +3 344 458 393 +3 345 416 394 +3 345 457 416 +3 345 459 398 +3 346 454 371 +3 346 467 375 +3 347 413 372 +3 347 431 413 +3 347 452 401 +3 347 462 431 +3 348 412 373 +3 348 453 377 +3 348 466 412 +3 348 468 466 +3 349 456 370 +3 349 463 402 +3 350 392 329 +3 350 457 369 +3 351 386 368 +3 351 388 328 +3 351 418 388 +3 351 455 418 +3 352 389 328 +3 352 469 389 +3 353 387 329 +3 353 399 366 +3 353 421 387 +3 353 451 421 +3 354 460 393 +3 354 474 376 +3 355 430 378 +3 355 461 430 +3 355 475 394 +3 356 382 42 +3 356 445 382 +3 357 410 19 +3 357 427 410 +3 358 419 322 +3 358 424 46 +3 358 440 340 +3 359 384 23 +3 359 420 384 +3 359 425 341 +3 359 442 325 +3 360 431 326 +3 360 458 431 +3 360 474 393 +3 361 459 394 +3 361 475 327 +3 362 400 49 +3 362 436 335 +3 362 470 436 +3 363 403 16 +3 363 437 337 +3 363 471 437 +3 364 408 334 +3 364 443 40 +3 364 472 443 +3 365 405 336 +3 365 444 25 +3 365 473 444 +3 366 399 316 +3 366 440 322 +3 366 451 353 +3 366 478 440 +3 367 469 426 +3 367 476 316 +3 368 386 317 +3 368 427 324 +3 368 455 351 +3 368 477 427 +3 369 391 317 +3 369 392 350 +3 369 442 341 +3 369 457 325 +3 370 415 349 +3 370 446 332 +3 370 456 54 +3 371 414 346 +3 371 448 333 +3 371 454 34 +3 372 413 339 +3 372 450 29 +3 372 452 347 +3 373 412 338 +3 373 449 59 +3 373 453 348 +3 374 379 329 +3 374 386 328 +3 374 392 317 +3 375 401 32 +3 375 454 346 +3 375 462 401 +3 375 467 326 +3 376 433 354 +3 376 465 318 +3 376 467 465 +3 376 474 326 +3 377 453 57 +3 377 463 327 +3 377 468 348 +3 378 430 319 +3 378 468 327 +3 378 475 355 +3 379 389 316 +3 379 399 329 +3 380 390 330 +3 380 411 44 +3 380 424 340 +3 381 391 341 +3 381 410 331 +3 381 425 21 +3 382 408 41 +3 382 445 334 +3 383 403 337 +3 383 423 357 +3 384 405 24 +3 384 420 336 +3 385 400 335 +3 385 419 358 +3 387 416 350 +3 387 421 315 +3 388 417 352 +3 388 418 314 +3 389 469 367 +3 390 476 330 +3 390 478 316 +3 391 477 317 +3 393 418 344 +3 393 458 360 +3 393 460 314 +3 393 474 354 +3 394 416 315 +3 394 459 345 +3 394 461 355 +3 394 475 361 +3 395 422 342 +3 395 433 318 +3 395 435 334 +3 396 428 335 +3 396 430 343 +3 396 436 319 +3 397 434 337 +3 397 437 320 +3 397 458 344 +3 398 429 345 +3 398 438 336 +3 398 459 321 +3 401 452 31 +3 401 462 347 +3 402 456 349 +3 402 463 377 +3 404 439 51 +3 404 449 338 +3 406 441 14 +3 406 450 339 +3 407 443 333 +3 407 448 36 +3 407 464 38 +3 409 444 332 +3 409 446 52 +3 410 427 331 +3 411 426 356 +3 412 466 319 +3 412 470 338 +3 413 431 320 +3 413 471 339 +3 414 465 346 +3 414 472 318 +3 415 432 349 +3 415 473 321 +3 416 457 350 +3 417 447 352 +3 417 460 342 +3 418 455 344 +3 419 428 322 +3 420 429 336 +3 421 451 343 +3 421 461 315 +3 422 445 323 +3 422 447 342 +3 423 427 357 +3 423 434 324 +3 426 445 356 +3 426 469 323 +3 426 476 367 +3 427 477 331 +3 428 451 322 +3 429 457 345 +3 430 461 343 +3 431 458 320 +3 431 462 326 +3 432 459 361 +3 432 463 349 +3 433 460 354 +3 434 455 324 +3 435 472 364 +3 436 470 319 +3 437 471 320 +3 438 473 365 +3 439 470 362 +3 440 478 340 +3 441 471 363 +3 443 472 333 +3 444 473 332 +3 447 469 352 +3 465 467 346 +3 466 468 378 +3 479 480 7 +3 481 1265 1088 +3 481 1383 1071 +3 481 1433 1265 +3 482 1204 975 +3 482 1247 853 +3 482 1400 1204 +3 483 863 709 +3 483 964 797 +3 483 1034 863 +3 484 881 813 +3 484 1082 740 +3 484 1408 857 +3 485 953 801 +3 485 988 810 +3 485 1235 755 +3 485 1444 787 +3 486 1140 861 +3 486 1191 914 +3 486 1259 1140 +3 487 1114 951 +3 487 1198 993 +3 487 1441 1113 +3 488 1141 735 +3 488 1169 966 +3 488 1216 1141 +3 489 1177 992 +3 489 1324 1177 +3 489 1447 1019 +3 490 1008 976 +3 490 1073 793 +3 490 1358 1073 +3 491 1195 995 +3 491 1419 1023 +3 492 1003 796 +3 492 1297 1255 +3 492 1388 1003 +3 493 1132 980 +3 493 1361 1089 +3 493 1393 1361 +3 494 928 720 +3 494 1061 882 +3 494 1153 855 +3 495 970 738 +3 495 1154 725 +3 495 1296 846 +3 496 1213 816 +3 496 1397 849 +3 496 1426 1117 +3 497 815 760 +3 497 935 700 +3 497 948 815 +3 497 1299 935 +3 498 1120 711 +3 498 1370 1045 +3 498 1392 806 +3 499 1097 778 +3 499 1180 1097 +3 499 1440 986 +3 500 897 795 +3 500 1083 856 +3 500 1342 1083 +3 501 894 776 +3 501 1014 792 +3 501 1345 894 +3 502 974 779 +3 502 1161 974 +3 502 1249 788 +3 503 1129 805 +3 503 1165 884 +3 503 1223 775 +3 503 1331 903 +3 504 1158 747 +3 504 1185 763 +3 504 1189 1158 +3 505 1182 794 +3 505 1319 845 +3 506 1031 751 +3 506 1179 919 +3 506 1446 1179 +3 507 1167 754 +3 507 1239 888 +3 507 1333 830 +3 508 949 819 +3 508 1016 867 +3 508 1403 949 +3 508 1405 1016 +3 509 899 724 +3 509 934 762 +3 509 1428 899 +3 510 918 836 +3 510 1131 918 +3 510 1332 833 +3 511 962 905 +3 511 985 962 +3 511 1028 835 +3 511 1454 1028 +3 512 879 718 +3 512 1112 808 +3 512 1429 879 +3 512 1455 1112 +3 513 941 854 +3 513 987 752 +3 513 1218 987 +3 513 1275 941 +3 514 1164 896 +3 514 1197 954 +3 515 1100 876 +3 515 1163 743 +3 515 1201 847 +3 516 963 939 +3 516 1205 772 +3 517 1000 818 +3 517 1248 1000 +3 517 1283 870 +3 517 1387 1248 +3 518 1042 889 +3 518 1070 967 +3 518 1102 1070 +3 518 1301 1042 +3 519 1267 1018 +3 519 1281 1052 +3 519 1307 852 +3 520 1203 771 +3 520 1215 1078 +3 520 1393 758 +3 521 983 803 +3 521 1046 969 +3 521 1375 983 +3 522 1007 791 +3 522 1079 782 +3 522 1238 1007 +3 523 1065 957 +3 523 1157 851 +3 524 1210 931 +3 524 1330 1064 +3 524 1334 1330 +3 525 858 717 +3 525 1351 1076 +3 525 1406 858 +3 526 1044 817 +3 526 1072 1044 +3 526 1353 940 +3 526 1399 1072 +3 527 921 701 +3 527 1051 921 +3 527 1066 1051 +3 527 1108 1066 +3 528 1130 910 +3 528 1443 1130 +3 528 1456 1365 +3 529 1183 811 +3 529 1371 1080 +3 530 1085 999 +3 530 1166 893 +3 531 1030 834 +3 531 1329 1030 +3 532 1104 778 +3 532 1328 1104 +3 532 1354 906 +3 533 1171 984 +3 533 1415 1171 +3 533 1418 873 +3 534 1010 735 +3 534 1194 1118 +3 534 1298 1010 +3 535 826 723 +3 535 1155 753 +3 535 1208 826 +3 536 1277 960 +3 536 1360 1055 +3 537 1145 981 +3 537 1366 902 +3 537 1382 1366 +3 538 1106 891 +3 538 1187 759 +3 538 1219 1187 +3 539 1233 1048 +3 539 1309 898 +3 540 1292 927 +3 540 1303 784 +3 541 1039 729 +3 541 1184 1039 +3 541 1263 1151 +3 542 968 766 +3 542 1226 968 +3 542 1306 1077 +3 543 1047 769 +3 543 1138 848 +3 543 1287 1138 +3 544 912 793 +3 544 1246 912 +3 544 1300 997 +3 545 1302 880 +3 545 1407 1236 +3 546 1242 800 +3 546 1279 841 +3 547 853 782 +3 547 1176 853 +3 547 1245 1176 +3 547 1363 928 +3 548 1225 807 +3 548 1269 1225 +3 549 1063 751 +3 549 1214 829 +3 549 1237 944 +3 550 1254 777 +3 550 1278 1254 +3 550 1321 1091 +3 550 1396 1278 +3 551 1058 719 +3 551 1095 776 +3 551 1264 787 +3 552 1257 970 +3 552 1414 842 +3 553 1209 763 +3 553 1272 1209 +3 553 1420 1137 +3 554 1427 839 +3 555 1280 1035 +3 555 1372 1056 +3 556 980 852 +3 556 1109 758 +3 556 1243 832 +3 556 1325 1109 +3 557 1442 856 +3 557 1453 843 +3 558 863 718 +3 558 1009 709 +3 558 1337 855 +3 559 1032 864 +3 559 1285 917 +3 560 952 797 +3 560 1296 952 +3 560 1374 846 +3 561 1241 1162 +3 561 1346 1241 +3 561 1389 1152 +3 562 1228 860 +3 562 1343 1154 +3 562 1451 854 +3 563 819 810 +3 563 883 754 +3 563 1323 883 +3 563 1409 819 +3 564 1172 838 +3 564 1422 1029 +3 565 1244 932 +3 565 1349 847 +3 565 1394 744 +3 566 961 806 +3 566 1411 873 +3 566 1416 1118 +3 567 821 820 +3 567 1192 795 +3 567 1234 899 +3 567 1378 821 +3 568 1097 774 +3 568 1175 778 +3 568 1413 1175 +3 569 1107 760 +3 569 1211 826 +3 569 1448 1088 +3 570 1089 729 +3 570 1290 943 +3 570 1373 1290 +3 571 1129 752 +3 571 1274 825 +3 571 1431 1129 +3 572 942 743 +3 572 973 804 +3 572 1289 773 +3 572 1395 942 +3 573 1251 862 +3 573 1252 765 +3 573 1379 910 +3 574 849 708 +3 574 859 849 +3 574 1034 809 +3 574 1067 718 +3 575 908 828 +3 575 1150 858 +3 575 1305 908 +3 576 904 711 +3 576 913 823 +3 576 1074 904 +3 576 1384 913 +3 577 868 735 +3 577 1261 868 +3 577 1311 1103 +3 578 840 827 +3 578 905 762 +3 578 1135 905 +3 578 1398 840 +3 579 935 799 +3 579 1144 935 +3 579 1340 909 +3 579 1424 1144 +3 580 804 792 +3 580 1199 924 +3 580 1289 804 +3 581 1082 813 +3 581 1322 816 +3 582 969 775 +3 582 1190 901 +3 582 1355 969 +3 582 1369 1190 +3 583 929 752 +3 583 1096 857 +3 583 1331 1096 +3 583 1408 733 +3 584 1000 914 +3 584 1156 818 +3 584 1314 918 +3 585 995 723 +3 585 1090 834 +3 585 1211 815 +3 586 1050 725 +3 586 1275 1262 +3 586 1366 831 +3 587 809 797 +3 587 859 809 +3 587 981 715 +3 588 1056 761 +3 588 1160 1015 +3 588 1317 1056 +3 588 1436 931 +3 589 890 875 +3 589 1001 890 +3 589 1391 962 +3 590 1163 813 +3 590 1345 1163 +3 590 1425 894 +3 591 974 811 +3 591 978 895 +3 591 1183 713 +3 591 1186 974 +3 592 993 851 +3 592 1120 806 +3 592 1157 1120 +3 593 967 835 +3 593 1028 866 +3 593 1301 967 +3 594 983 812 +3 594 1005 756 +3 594 1239 803 +3 595 1020 925 +3 595 1226 1020 +3 595 1288 936 +3 596 1134 872 +3 596 1197 915 +3 596 1295 822 +3 597 867 785 +3 597 1012 817 +3 597 1068 802 +3 597 1403 867 +3 598 999 830 +3 598 1059 892 +3 598 1333 756 +3 599 949 817 +3 599 1235 810 +3 600 972 753 +3 600 1008 793 +3 601 986 841 +3 601 1151 737 +3 601 1380 1151 +3 601 1432 1060 +3 602 881 857 +3 602 1058 776 +3 602 1096 1058 +3 602 1425 881 +3 603 1046 801 +3 603 1165 775 +3 603 1264 884 +3 604 1035 951 +3 604 1114 984 +3 604 1171 919 +3 604 1179 1035 +3 605 988 801 +3 605 1038 883 +3 605 1041 803 +3 605 1323 988 +3 606 1083 906 +3 606 1212 971 +3 606 1294 1083 +3 606 1354 1212 +3 607 985 835 +3 607 1123 959 +3 608 874 751 +3 608 1031 997 +3 608 1073 874 +3 608 1300 1073 +3 609 800 795 +3 609 1101 800 +3 609 1192 820 +3 609 1434 798 +3 610 1119 794 +3 610 1236 748 +3 610 1359 1119 +3 611 1040 886 +3 611 1298 1045 +3 611 1304 1040 +3 612 1051 992 +3 612 1177 1018 +3 612 1315 921 +3 613 1399 792 +3 613 1444 1072 +3 614 958 836 +3 614 1033 916 +3 614 1326 877 +3 615 964 839 +3 615 977 845 +3 615 1316 964 +3 615 1427 871 +3 616 1189 922 +3 616 1222 937 +3 616 1417 960 +3 617 1065 955 +3 617 1273 844 +3 617 1330 1013 +3 618 1037 861 +3 618 1405 1049 +3 618 1409 1037 +3 619 861 754 +3 619 1085 893 +3 619 1148 861 +3 619 1167 830 +3 620 1027 769 +3 620 1410 1016 +3 621 1036 926 +3 621 1042 1036 +3 621 1306 889 +3 622 1074 823 +3 622 1093 878 +3 622 1351 1074 +3 623 1081 923 +3 623 1334 1002 +3 624 977 871 +3 624 1182 977 +3 624 1302 1182 +3 624 1388 880 +3 625 934 843 +3 625 1084 840 +3 625 1398 934 +3 625 1439 1084 +3 625 1453 790 +3 626 1080 1030 +3 626 1170 1080 +3 626 1329 789 +3 626 1435 900 +3 627 958 877 +3 627 1178 945 +3 627 1332 958 +3 628 1052 927 +3 628 1105 946 +3 628 1292 750 +3 629 1248 848 +3 629 1259 914 +3 630 1156 1131 +3 630 1324 1019 +3 630 1357 1324 +3 631 950 930 +3 631 1047 848 +3 631 1111 938 +3 631 1387 950 +3 632 1164 966 +3 632 1367 1150 +3 633 1054 976 +3 633 1055 1054 +3 633 1174 898 +3 633 1277 1055 +3 634 1009 855 +3 634 1079 791 +3 634 1153 1079 +3 635 928 882 +3 635 1185 814 +3 635 1196 1185 +3 635 1245 928 +3 636 990 771 +3 636 1263 990 +3 636 1421 1180 +3 637 1135 827 +3 637 1143 866 +3 637 1454 1135 +3 638 1063 829 +3 638 1087 1011 +3 638 1122 1022 +3 639 1218 734 +3 639 1274 987 +3 640 1161 807 +3 640 1225 781 +3 640 1231 811 +3 641 1057 759 +3 641 1186 895 +3 641 1187 779 +3 641 1308 1057 +3 642 1168 821 +3 642 1378 899 +3 642 1428 875 +3 643 1166 836 +3 643 1191 893 +3 643 1314 1191 +3 644 963 741 +3 644 1128 1048 +3 644 1233 939 +3 644 1400 1128 +3 645 1106 759 +3 645 1115 1106 +3 645 1139 885 +3 645 1320 1139 +3 646 1023 772 +3 646 1195 1023 +3 646 1205 753 +3 647 955 851 +3 647 1064 955 +3 647 1198 1113 +3 647 1210 1064 +3 648 1075 850 +3 648 1162 808 +3 648 1312 1053 +3 649 1102 889 +3 649 1149 979 +3 649 1200 1021 +3 649 1306 1149 +3 650 954 872 +3 650 1025 954 +3 650 1202 989 +3 650 1251 1025 +3 651 1237 874 +3 651 1358 1054 +3 651 1360 944 +3 652 1283 818 +3 652 1285 870 +3 652 1447 917 +3 653 1108 920 +3 653 1260 864 +3 654 1278 975 +3 654 1404 1278 +3 655 1032 917 +3 655 1066 1032 +3 655 1381 992 +3 656 966 765 +3 656 1216 966 +3 656 1252 910 +3 657 1128 853 +3 657 1176 747 +3 657 1309 1048 +3 658 891 777 +3 658 1219 891 +3 658 1249 779 +3 658 1254 1249 +3 659 1209 786 +3 659 1222 763 +3 659 1240 937 +3 660 1061 855 +3 660 1241 1061 +3 660 1429 1241 +3 661 972 912 +3 661 1208 972 +3 661 1246 1071 +3 661 1383 1208 +3 662 1052 946 +3 662 1307 1052 +3 663 896 828 +3 663 1173 915 +3 663 1197 896 +3 664 950 870 +3 664 1193 947 +3 664 1310 930 +3 665 968 936 +3 665 1286 766 +3 665 1313 887 +3 665 1339 1286 +3 666 982 939 +3 666 1008 982 +3 666 1233 976 +3 667 1092 1024 +3 667 1215 1109 +3 667 1325 1092 +3 668 1177 784 +3 668 1281 1018 +3 668 1303 927 +3 669 1107 1088 +3 669 1194 868 +3 669 1265 1194 +3 670 1217 834 +3 670 1371 824 +3 671 1006 997 +3 671 1031 919 +3 671 1415 1006 +3 672 1136 789 +3 672 1207 1144 +3 672 1329 1207 +3 672 1424 1094 +3 673 1238 782 +3 673 1247 975 +3 673 1396 1091 +3 674 1100 847 +3 674 1322 1100 +3 674 1349 1117 +3 674 1426 1322 +3 675 1065 844 +3 675 1270 913 +3 675 1384 957 +3 676 1328 906 +3 676 1342 800 +3 677 1267 852 +3 677 1315 1267 +3 678 1238 1091 +3 678 1297 796 +3 678 1321 1297 +3 679 1126 998 +3 679 1340 799 +3 679 1456 1126 +3 680 1355 1221 +3 680 1375 969 +3 680 1386 812 +3 681 981 952 +3 681 1296 1229 +3 681 1382 981 +3 682 1257 842 +3 682 1348 860 +3 683 1115 880 +3 683 1255 891 +3 683 1388 1255 +3 684 970 846 +3 684 1335 970 +3 684 1374 1319 +3 685 961 873 +3 685 993 961 +3 685 1114 993 +3 685 1418 984 +3 686 1076 878 +3 686 1224 908 +3 686 1406 1076 +3 687 1126 910 +3 687 1266 998 +3 687 1379 1266 +3 688 1098 1062 +3 688 1214 944 +3 688 1360 1098 +3 688 1377 956 +3 689 1201 730 +3 689 1244 847 +3 689 1293 932 +3 690 1246 1006 +3 690 1291 1071 +3 690 1415 1230 +3 691 1122 1011 +3 691 1282 1122 +3 691 1347 911 +3 692 1215 1024 +3 692 1385 1078 +3 693 1188 1142 +3 693 1253 1175 +3 693 1413 1188 +3 694 1301 933 +3 694 1318 1036 +3 695 1299 1103 +3 695 1365 1299 +3 695 1443 1365 +3 696 1272 1137 +3 696 1389 1004 +3 697 1002 931 +3 697 1026 1002 +3 697 1344 1026 +3 697 1436 1015 +3 698 1152 1137 +3 698 1346 1152 +3 698 1420 882 +3 699 1351 1304 +3 699 1370 904 +3 700 948 497 +3 700 1090 948 +3 700 1207 1090 +3 701 943 527 +3 701 1089 943 +3 701 1132 1089 +3 702 1294 971 +3 702 1362 991 +3 702 1445 856 +3 703 1189 960 +3 703 1277 898 +3 704 1108 943 +3 704 1290 1276 +3 704 1338 920 +3 705 1334 994 +3 705 1412 1013 +3 706 985 959 +3 706 1001 962 +3 706 1401 1001 +3 707 1184 1017 +3 707 1373 1039 +3 707 1457 869 +3 708 1067 574 +3 708 1455 1067 +3 709 839 483 +3 709 863 558 +3 709 1181 839 +3 710 1027 1016 +3 710 1287 1027 +3 710 1405 1284 +3 711 904 498 +3 711 957 576 +3 711 1157 957 +3 712 1327 1053 +3 712 1341 838 +3 713 978 591 +3 713 1170 900 +3 713 1183 1170 +3 713 1368 978 +3 714 1280 1056 +3 714 1441 951 +3 715 859 587 +3 715 1145 816 +3 715 1213 859 +3 716 999 892 +3 716 1033 999 +3 716 1402 916 +3 717 1040 525 +3 717 1169 886 +3 717 1367 1169 +3 718 879 558 +3 718 1034 574 +3 718 1067 512 +3 719 884 551 +3 719 1331 884 +3 720 1153 494 +3 720 1363 1079 +3 721 1431 1069 +3 722 1199 940 +3 722 1271 1199 +3 722 1353 802 +3 723 1155 535 +3 723 1195 1155 +3 723 1211 585 +3 724 843 509 +3 724 1234 897 +3 724 1442 843 +3 725 941 586 +3 725 1050 495 +3 725 1343 941 +3 726 1336 842 +3 726 1359 1258 +3 726 1414 1359 +3 727 1298 1118 +3 727 1392 1045 +3 727 1416 1392 +3 728 1417 965 +3 728 1452 1062 +3 729 990 541 +3 729 1039 570 +3 729 1361 990 +3 730 907 188 +3 730 1116 689 +3 730 1201 942 +3 730 1395 907 +3 731 1411 1118 +3 731 1433 1411 +3 732 1242 841 +3 732 1328 1242 +3 732 1440 1104 +3 733 929 583 +3 733 1275 929 +3 733 1408 1262 +3 734 1124 639 +3 734 1218 854 +3 734 1256 1124 +3 734 1451 1256 +3 735 868 534 +3 735 886 488 +3 735 1010 886 +3 735 1141 577 +3 736 1184 1151 +3 736 1449 1017 +3 737 986 601 +3 737 1180 986 +3 737 1263 1180 +3 738 1154 495 +3 738 1228 1154 +3 738 1257 1228 +3 739 1394 1133 +3 739 1437 838 +3 740 1082 902 +3 740 1262 484 +3 740 1366 1262 +3 741 1220 1204 +3 741 1268 1220 +3 741 1400 644 +3 742 1077 926 +3 742 1226 1077 +3 742 1423 1020 +3 743 942 515 +3 743 973 572 +3 743 1345 973 +3 744 1172 1029 +3 744 1349 565 +3 744 1394 1172 +3 744 1397 1117 +3 745 1216 1130 +3 745 1311 1141 +3 745 1443 1311 +3 746 1279 1159 +3 746 1432 841 +3 747 814 504 +3 747 1158 898 +3 747 1176 814 +3 747 1309 657 +3 748 1043 610 +3 748 1407 885 +3 748 1430 1043 +3 749 1210 1113 +3 749 1317 931 +3 749 1441 1317 +3 750 945 131 +3 750 1086 945 +3 750 1105 628 +3 750 1292 1086 +3 751 1022 506 +3 751 1031 608 +3 751 1063 1022 +3 751 1237 549 +3 752 903 583 +3 752 929 513 +3 752 987 571 +3 752 1129 903 +3 753 972 535 +3 753 982 600 +3 753 1155 646 +3 753 1205 982 +3 754 883 507 +3 754 1037 563 +3 754 1167 619 +3 755 1235 1044 +3 755 1444 485 +3 756 888 594 +3 756 1059 598 +3 756 1333 888 +3 756 1350 1059 +3 757 1259 1138 +3 757 1284 1140 +3 757 1287 1284 +3 758 980 556 +3 758 1109 520 +3 758 1393 980 +3 759 1057 104 +3 759 1106 538 +3 759 1187 641 +3 759 1320 645 +3 760 815 569 +3 760 1103 497 +3 760 1261 1103 +3 761 911 164 +3 761 1160 588 +3 761 1372 911 +3 762 875 509 +3 762 934 578 +3 762 1391 875 +3 763 922 504 +3 763 1196 553 +3 763 1209 659 +3 763 1222 922 +3 764 1142 142 +3 764 1253 1142 +3 764 1354 1253 +3 765 1025 573 +3 765 1164 1025 +3 765 1252 656 +3 766 968 665 +3 766 1149 542 +3 766 1286 228 +3 767 1383 1088 +3 767 1448 1208 +3 768 1282 1035 +3 768 1446 1122 +3 769 938 198 +3 769 1027 543 +3 769 1047 938 +3 769 1127 620 +3 770 1021 225 +3 770 1102 1021 +3 770 1123 1070 +3 771 1203 636 +3 771 1393 520 +3 772 963 516 +3 772 1205 646 +3 772 1268 963 +3 772 1269 1268 +3 773 907 572 +3 773 924 190 +3 773 1289 924 +3 774 1078 568 +3 774 1203 1078 +3 774 1421 1203 +3 775 1046 603 +3 775 1165 503 +3 775 1223 582 +3 776 1014 501 +3 776 1058 551 +3 776 1095 1014 +3 776 1425 602 +3 777 1254 658 +3 777 1321 550 +3 778 1097 568 +3 778 1104 499 +3 778 1175 532 +3 779 1186 641 +3 779 1219 658 +3 779 1249 502 +3 780 1319 1119 +3 780 1335 1319 +3 780 1414 1335 +3 781 824 640 +3 781 1269 1023 +3 781 1419 824 +3 782 1238 522 +3 782 1247 673 +3 782 1363 547 +3 783 1230 873 +3 783 1291 1230 +3 783 1433 1291 +3 784 833 540 +3 784 1303 668 +3 784 1357 833 +3 785 1068 597 +3 785 1376 195 +3 785 1410 1376 +3 786 1146 176 +3 786 1240 659 +3 786 1272 1146 +3 787 953 485 +3 787 1095 551 +3 787 1264 953 +3 787 1444 1095 +3 788 807 502 +3 788 1404 807 +3 789 1125 626 +3 789 1136 97 +3 789 1329 672 +3 790 991 146 +3 790 1439 625 +3 790 1445 991 +3 790 1453 1445 +3 791 1009 634 +3 791 1079 522 +3 791 1181 1009 +3 791 1356 1181 +3 792 804 501 +3 792 940 580 +3 792 1014 613 +3 792 1399 940 +3 793 912 600 +3 793 1008 490 +3 793 1300 544 +3 794 1119 505 +3 794 1236 610 +3 794 1302 1236 +3 795 800 500 +3 795 1192 609 +3 795 1234 567 +3 796 1007 678 +3 796 1297 492 +3 796 1356 1007 +3 796 1390 1356 +3 797 809 483 +3 797 952 587 +3 797 1316 560 +3 798 1101 609 +3 798 1279 1101 +3 798 1434 214 +3 799 1340 579 +3 799 1456 679 +3 800 1101 546 +3 800 1242 676 +3 800 1342 500 +3 801 953 603 +3 801 988 485 +3 801 1041 605 +3 801 1046 1041 +3 802 1012 597 +3 802 1227 722 +3 802 1353 1012 +3 802 1438 1227 +3 803 983 594 +3 803 1038 605 +3 803 1041 521 +3 803 1239 1038 +3 804 973 501 +3 804 1289 572 +3 805 1223 503 +3 805 1369 1223 +3 805 1431 1369 +3 806 961 592 +3 806 1120 498 +3 806 1416 566 +3 807 1161 502 +3 807 1220 548 +3 807 1225 640 +3 807 1404 1220 +3 808 1112 648 +3 808 1429 512 +3 809 859 574 +3 809 1034 483 +3 810 819 599 +3 810 1235 485 +3 810 1323 563 +3 811 1161 640 +3 811 1183 591 +3 811 1231 529 +3 812 1005 594 +3 812 1375 680 +3 812 1386 122 +3 813 876 581 +3 813 881 590 +3 813 1082 484 +3 813 1163 876 +3 814 1185 504 +3 814 1245 635 +3 815 948 585 +3 815 1211 569 +3 816 902 581 +3 816 1145 902 +3 816 1213 715 +3 816 1426 496 +3 817 1012 526 +3 817 1044 599 +3 817 1403 597 +3 818 1000 584 +3 818 1019 652 +3 818 1156 1019 +3 818 1283 517 +3 819 949 599 +3 819 1049 508 +3 819 1409 1049 +3 820 821 217 +3 820 1110 609 +3 820 1192 567 +3 821 1168 218 +3 821 1378 642 +3 822 1134 596 +3 822 1295 85 +3 823 913 76 +3 823 1074 576 +3 823 1093 622 +3 824 1217 670 +3 824 1231 640 +3 824 1371 1231 +3 824 1419 1217 +3 825 1069 571 +3 825 1232 116 +3 825 1274 1232 +3 826 1211 723 +3 826 1448 569 +3 827 840 149 +3 827 1135 578 +3 827 1143 637 +3 828 896 575 +3 828 908 81 +3 828 1173 663 +3 829 1063 549 +3 829 1087 638 +3 829 1214 956 +3 829 1352 1087 +3 830 1085 619 +3 830 1167 507 +3 830 1333 598 +3 831 1050 586 +3 831 1229 1050 +3 831 1382 1229 +3 832 1121 135 +3 832 1243 1121 +3 832 1325 556 +3 833 1086 540 +3 833 1131 510 +3 833 1332 1086 +3 833 1357 1131 +3 834 995 585 +3 834 1030 670 +3 834 1090 531 +3 834 1217 995 +3 835 985 511 +3 835 1028 593 +3 835 1070 607 +3 836 918 643 +3 836 958 510 +3 836 1033 614 +3 836 1166 1033 +3 837 1312 1112 +3 837 1341 1312 +3 837 1422 1341 +3 837 1455 1422 +3 838 1172 739 +3 838 1327 712 +3 838 1341 564 +3 838 1437 183 +3 839 964 483 +3 839 1181 554 +3 839 1427 615 +3 840 1084 148 +3 840 1398 625 +3 841 1242 546 +3 841 1279 746 +3 841 1432 601 +3 841 1440 732 +3 842 1206 682 +3 842 1257 552 +3 842 1336 111 +3 842 1414 726 +3 843 934 509 +3 843 1442 557 +3 843 1453 625 +3 844 1065 617 +3 844 1270 675 +3 844 1273 73 +3 845 977 505 +3 845 1316 615 +3 845 1374 1316 +3 846 970 495 +3 846 1296 560 +3 846 1374 684 +3 847 1100 515 +3 847 1201 689 +3 847 1244 565 +3 847 1349 674 +3 848 1047 543 +3 848 1138 629 +3 848 1387 631 +3 849 1029 708 +3 849 1213 496 +3 849 1397 1029 +3 850 1075 179 +3 850 1162 648 +3 850 1389 1162 +3 851 955 523 +3 851 1157 592 +3 851 1198 647 +3 852 980 677 +3 852 1243 556 +3 852 1267 519 +3 852 1307 1243 +3 853 1128 482 +3 853 1176 657 +3 853 1247 782 +3 854 1218 513 +3 854 1343 562 +3 854 1451 734 +3 855 1009 558 +3 855 1061 494 +3 855 1153 634 +3 855 1337 660 +3 856 897 500 +3 856 1294 702 +3 856 1442 897 +3 856 1445 557 +3 857 881 484 +3 857 1096 602 +3 857 1408 583 +3 858 1305 575 +3 858 1367 717 +3 858 1406 1305 +3 859 1213 849 +3 860 1228 682 +3 860 1348 113 +3 860 1451 562 +3 861 1037 754 +3 861 1140 618 +3 861 1148 486 +3 862 989 90 +3 862 1251 989 +3 862 1379 573 +3 863 1034 718 +3 864 1032 653 +3 864 1193 559 +3 864 1260 204 +3 865 1250 139 +3 865 1385 1250 +3 865 1413 1385 +3 866 933 593 +3 866 1028 637 +3 866 1143 151 +3 867 1403 508 +3 867 1410 785 +3 868 1107 669 +3 868 1194 534 +3 868 1261 1107 +3 869 1373 707 +3 869 1457 208 +3 870 950 517 +3 870 1193 664 +3 870 1283 652 +3 870 1285 1193 +3 871 977 615 +3 871 1003 624 +3 871 1390 1003 +3 871 1427 1390 +3 872 954 596 +3 872 1134 88 +3 872 1202 650 +3 873 961 566 +3 873 1230 533 +3 873 1411 783 +3 873 1418 685 +3 874 1237 751 +3 874 1358 651 +3 875 890 642 +3 875 1391 589 +3 875 1428 509 +3 876 1100 581 +3 876 1163 515 +3 877 958 614 +3 877 1178 627 +3 877 1326 129 +3 878 1076 622 +3 878 1093 78 +3 878 1224 686 +3 879 1337 558 +3 879 1429 1337 +3 880 1115 545 +3 880 1302 624 +3 880 1388 683 +3 881 1425 590 +3 882 928 494 +3 882 1061 698 +3 882 1196 635 +3 882 1420 1196 +3 883 1038 507 +3 883 1323 605 +3 884 1165 603 +3 884 1264 551 +3 884 1331 503 +3 885 1115 645 +3 885 1139 106 +3 885 1407 1115 +3 885 1430 748 +3 886 1010 611 +3 886 1040 717 +3 886 1169 488 +3 887 1313 63 +3 887 1339 665 +3 888 1239 594 +3 888 1333 507 +3 889 1042 621 +3 889 1102 518 +3 889 1306 649 +3 890 1001 220 +3 890 1168 642 +3 891 1106 683 +3 891 1219 538 +3 891 1255 777 +3 892 999 598 +3 892 1059 125 +3 892 1402 716 +3 893 1085 530 +3 893 1148 619 +3 893 1166 643 +3 893 1191 1148 +3 894 1345 590 +3 894 1425 776 +3 895 1186 591 +3 895 1308 641 +3 895 1450 102 +3 896 1150 575 +3 896 1164 1150 +3 896 1197 514 +3 897 1234 795 +3 897 1442 724 +3 898 1158 703 +3 898 1174 539 +3 898 1277 633 +3 898 1309 747 +3 899 1234 724 +3 899 1378 567 +3 899 1428 642 +3 900 1170 626 +3 900 1368 713 +3 900 1435 99 +3 901 1190 119 +3 901 1355 582 +3 902 1082 581 +3 902 1145 537 +3 902 1366 740 +3 903 1129 503 +3 903 1331 583 +3 904 1074 699 +3 904 1370 498 +3 905 1391 762 +3 905 1454 511 +3 906 1328 532 +3 906 1342 676 +3 906 1354 606 +3 907 1395 572 +3 908 1224 80 +3 908 1305 686 +3 909 1147 94 +3 909 1340 1147 +3 909 1424 579 +3 910 1126 528 +3 910 1130 656 +3 910 1252 573 +3 910 1379 687 +3 911 1282 691 +3 911 1347 165 +3 911 1372 1282 +3 912 972 600 +3 912 1246 661 +3 913 1270 75 +3 913 1384 675 +3 914 1000 629 +3 914 1259 486 +3 914 1314 584 +3 915 1173 83 +3 915 1197 663 +3 915 1295 596 +3 916 1033 716 +3 916 1326 614 +3 916 1402 127 +3 917 1032 559 +3 917 1285 652 +3 917 1381 655 +3 917 1447 1381 +3 918 1156 584 +3 918 1314 643 +3 919 1031 506 +3 919 1171 671 +3 919 1179 604 +3 920 1108 704 +3 920 1260 653 +3 920 1338 205 +3 921 1051 612 +3 921 1132 701 +3 921 1315 1132 +3 922 1189 504 +3 922 1222 616 +3 923 994 623 +3 923 1099 70 +3 924 1271 191 +3 924 1289 580 +3 925 1020 158 +3 925 1288 595 +3 926 1036 155 +3 926 1077 621 +3 926 1423 742 +3 927 1281 668 +3 927 1292 628 +3 927 1303 540 +3 928 1245 547 +3 928 1363 720 +3 929 1275 513 +3 930 950 664 +3 930 1111 631 +3 930 1310 201 +3 931 1002 524 +3 931 1210 749 +3 931 1317 588 +3 931 1436 697 +3 932 1133 565 +3 932 1244 689 +3 932 1293 185 +3 933 1301 593 +3 933 1318 694 +3 934 1398 578 +3 935 1144 700 +3 935 1299 799 +3 936 968 595 +3 936 1288 64 +3 936 1313 665 +3 937 965 616 +3 937 1222 659 +3 937 1240 174 +3 938 1047 631 +3 938 1111 199 +3 939 963 644 +3 939 982 516 +3 939 1233 666 +3 940 1199 580 +3 940 1353 722 +3 940 1399 526 +3 941 1275 586 +3 941 1343 854 +3 942 1201 515 +3 942 1395 730 +3 943 1089 570 +3 943 1108 527 +3 943 1290 704 +3 944 1214 549 +3 944 1237 651 +3 944 1360 688 +3 945 1086 627 +3 945 1178 130 +3 946 1052 628 +3 946 1105 133 +3 946 1121 662 +3 947 1193 864 +3 947 1310 664 +3 948 1090 585 +3 949 1403 817 +3 950 1387 517 +3 951 1114 604 +3 951 1280 714 +3 951 1441 487 +3 952 981 587 +3 952 1296 681 +3 953 1264 603 +3 954 1025 514 +3 954 1197 596 +3 955 1064 617 +3 955 1065 523 +3 956 1214 688 +3 956 1352 829 +3 956 1377 169 +3 957 1065 675 +3 957 1157 523 +3 957 1384 576 +3 958 1332 510 +3 959 985 607 +3 959 1123 223 +3 959 1401 706 +3 960 1098 536 +3 960 1189 616 +3 960 1277 703 +3 960 1417 1098 +3 961 993 592 +3 962 985 706 +3 962 1001 589 +3 962 1391 905 +3 963 1268 741 +3 964 1316 797 +3 965 1417 616 +3 965 1452 728 +3 966 1164 765 +3 966 1169 632 +3 966 1216 488 +3 967 1070 835 +3 967 1301 518 +3 968 1226 595 +3 969 1046 775 +3 969 1355 680 +3 969 1375 521 +3 970 1257 738 +3 970 1335 552 +3 971 1212 143 +3 971 1294 606 +3 971 1362 702 +3 972 1208 535 +3 973 1345 501 +3 974 1161 811 +3 974 1186 779 +3 975 1204 654 +3 975 1247 482 +3 975 1396 673 +3 976 1008 666 +3 976 1054 490 +3 976 1174 633 +3 976 1233 1174 +3 977 1182 505 +3 978 1368 100 +3 978 1450 895 +3 979 1149 766 +3 979 1200 649 +3 980 1132 677 +3 980 1393 493 +3 981 1145 715 +3 981 1382 537 +3 982 1008 600 +3 982 1205 516 +3 983 1375 812 +3 984 1114 685 +3 984 1171 604 +3 984 1418 533 +3 986 1180 499 +3 986 1440 841 +3 987 1218 639 +3 987 1274 571 +3 988 1323 810 +3 989 1202 89 +3 989 1251 650 +3 990 1263 541 +3 990 1361 771 +3 991 1362 145 +3 991 1445 702 +3 992 1051 655 +3 992 1177 612 +3 992 1381 489 +3 993 1114 487 +3 993 1198 851 +3 994 1334 623 +3 994 1412 705 +3 995 1195 723 +3 995 1217 491 +3 996 1339 887 +3 997 1006 544 +3 997 1031 671 +3 997 1300 608 +3 998 1126 687 +3 998 1147 679 +3 998 1266 92 +3 999 1033 530 +3 999 1085 830 +3 1000 1248 629 +3 1001 1401 221 +3 1002 1026 623 +3 1002 1334 524 +3 1003 1388 624 +3 1003 1390 796 +3 1004 1146 696 +3 1004 1389 850 +3 1005 1350 756 +3 1006 1246 544 +3 1006 1415 690 +3 1007 1238 678 +3 1007 1356 791 +3 1009 1181 709 +3 1010 1298 611 +3 1011 1087 167 +3 1011 1122 638 +3 1011 1347 691 +3 1012 1353 526 +3 1013 1273 617 +3 1013 1330 705 +3 1013 1412 72 +3 1014 1095 613 +3 1015 1160 162 +3 1015 1344 697 +3 1015 1436 588 +3 1016 1027 620 +3 1016 1405 710 +3 1016 1410 867 +3 1017 1184 736 +3 1017 1449 210 +3 1017 1457 707 +3 1018 1177 668 +3 1018 1267 612 +3 1018 1281 519 +3 1019 1156 630 +3 1019 1324 489 +3 1019 1447 652 +3 1020 1226 742 +3 1020 1423 157 +3 1021 1102 649 +3 1021 1200 226 +3 1022 1063 638 +3 1022 1446 506 +3 1023 1195 491 +3 1023 1269 772 +3 1023 1419 781 +3 1024 1092 137 +3 1024 1215 667 +3 1024 1250 692 +3 1025 1164 514 +3 1025 1251 573 +3 1026 1081 623 +3 1026 1344 161 +3 1027 1287 543 +3 1028 1454 637 +3 1029 1172 564 +3 1029 1397 744 +3 1029 1422 708 +3 1030 1080 670 +3 1030 1329 626 +3 1032 1066 653 +3 1033 1166 530 +3 1035 1179 768 +3 1035 1280 951 +3 1035 1282 555 +3 1036 1042 694 +3 1036 1318 154 +3 1037 1409 563 +3 1038 1239 507 +3 1039 1184 707 +3 1039 1373 570 +3 1040 1304 525 +3 1041 1046 521 +3 1042 1301 694 +3 1043 1258 610 +3 1043 1430 108 +3 1044 1072 755 +3 1044 1235 599 +3 1045 1298 727 +3 1045 1304 611 +3 1045 1370 1304 +3 1045 1392 498 +3 1048 1128 657 +3 1048 1233 644 +3 1048 1309 539 +3 1049 1405 508 +3 1049 1409 618 +3 1050 1229 495 +3 1051 1066 655 +3 1052 1281 927 +3 1052 1307 519 +3 1053 1075 648 +3 1053 1312 712 +3 1053 1327 181 +3 1054 1055 651 +3 1054 1358 490 +3 1055 1277 536 +3 1055 1360 651 +3 1056 1280 555 +3 1056 1317 714 +3 1056 1372 761 +3 1057 1308 103 +3 1058 1096 719 +3 1059 1350 124 +3 1060 1364 212 +3 1060 1380 601 +3 1060 1432 1364 +3 1060 1449 1380 +3 1061 1346 698 +3 1062 1098 728 +3 1062 1377 688 +3 1062 1452 171 +3 1064 1210 524 +3 1064 1330 617 +3 1066 1108 653 +3 1067 1455 512 +3 1068 1438 802 +3 1069 1190 721 +3 1069 1431 571 +3 1070 1102 770 +3 1070 1123 607 +3 1071 1246 690 +3 1071 1291 481 +3 1071 1383 661 +3 1072 1399 613 +3 1072 1444 755 +3 1073 1300 793 +3 1073 1358 874 +3 1074 1351 699 +3 1076 1351 622 +3 1076 1406 525 +3 1077 1226 542 +3 1077 1306 621 +3 1078 1203 520 +3 1078 1215 692 +3 1078 1385 568 +3 1079 1153 720 +3 1079 1363 782 +3 1080 1170 529 +3 1080 1371 670 +3 1081 1099 923 +3 1083 1294 856 +3 1083 1342 906 +3 1084 1439 147 +3 1086 1292 540 +3 1086 1332 627 +3 1087 1352 168 +3 1088 1107 569 +3 1088 1265 669 +3 1088 1383 481 +3 1088 1448 767 +3 1089 1132 493 +3 1089 1361 729 +3 1090 1207 531 +3 1091 1238 673 +3 1091 1321 678 +3 1091 1396 550 +3 1092 1325 832 +3 1094 1136 672 +3 1094 1424 909 +3 1095 1444 613 +3 1096 1331 719 +3 1097 1421 774 +3 1098 1360 536 +3 1098 1417 728 +3 1100 1322 581 +3 1101 1279 546 +3 1103 1261 577 +3 1103 1299 497 +3 1103 1311 695 +3 1104 1328 732 +3 1104 1440 499 +3 1106 1115 683 +3 1107 1261 760 +3 1109 1215 520 +3 1109 1325 667 +3 1110 1434 609 +3 1112 1312 648 +3 1112 1455 837 +3 1113 1198 487 +3 1113 1210 647 +3 1113 1441 749 +3 1115 1407 545 +3 1116 1293 689 +3 1117 1349 744 +3 1117 1397 496 +3 1117 1426 674 +3 1118 1194 731 +3 1118 1298 534 +3 1118 1411 566 +3 1118 1416 727 +3 1119 1319 505 +3 1119 1359 780 +3 1120 1157 711 +3 1121 1243 662 +3 1122 1282 768 +3 1122 1446 1022 +3 1124 1232 639 +3 1124 1256 114 +3 1125 1435 626 +3 1126 1456 528 +3 1127 1376 620 +3 1128 1400 482 +3 1129 1431 805 +3 1130 1216 656 +3 1130 1443 745 +3 1131 1156 918 +3 1131 1357 630 +3 1132 1315 677 +3 1133 1394 565 +3 1133 1437 739 +3 1135 1454 905 +3 1137 1152 696 +3 1137 1272 553 +3 1137 1420 698 +3 1138 1259 629 +3 1138 1287 757 +3 1139 1320 105 +3 1140 1259 757 +3 1140 1284 618 +3 1141 1216 745 +3 1141 1311 577 +3 1142 1188 141 +3 1142 1253 693 +3 1144 1207 700 +3 1144 1424 672 +3 1146 1272 696 +3 1147 1340 679 +3 1148 1191 486 +3 1149 1306 542 +3 1150 1164 632 +3 1150 1367 858 +3 1151 1184 541 +3 1151 1263 737 +3 1151 1380 736 +3 1152 1346 561 +3 1152 1389 696 +3 1154 1228 562 +3 1154 1343 725 +3 1155 1195 646 +3 1158 1189 703 +3 1159 1279 798 +3 1159 1364 746 +3 1162 1241 808 +3 1162 1389 561 +3 1163 1345 743 +3 1169 1367 632 +3 1170 1183 529 +3 1171 1415 671 +3 1172 1394 739 +3 1174 1233 539 +3 1175 1253 532 +3 1175 1413 693 +3 1176 1245 814 +3 1177 1324 784 +3 1179 1446 768 +3 1180 1263 636 +3 1180 1421 1097 +3 1181 1356 554 +3 1182 1302 794 +3 1185 1196 763 +3 1187 1219 779 +3 1188 1413 865 +3 1190 1369 721 +3 1191 1314 914 +3 1193 1285 559 +3 1194 1265 731 +3 1196 1420 553 +3 1199 1271 924 +3 1203 1421 636 +3 1204 1220 654 +3 1204 1400 741 +3 1206 1348 682 +3 1207 1329 531 +3 1208 1383 767 +3 1208 1448 826 +3 1209 1272 786 +3 1212 1354 764 +3 1217 1419 491 +3 1220 1268 548 +3 1220 1404 654 +3 1221 1355 901 +3 1221 1386 680 +3 1223 1369 582 +3 1225 1269 781 +3 1227 1271 722 +3 1227 1438 193 +3 1228 1257 682 +3 1229 1296 495 +3 1229 1382 681 +3 1230 1291 690 +3 1230 1415 533 +3 1231 1371 529 +3 1232 1274 639 +3 1236 1302 545 +3 1236 1407 748 +3 1241 1346 1061 +3 1241 1429 808 +3 1242 1328 676 +3 1243 1307 662 +3 1248 1387 848 +3 1249 1254 788 +3 1250 1385 692 +3 1253 1354 532 +3 1254 1278 788 +3 1255 1297 777 +3 1255 1388 492 +3 1256 1451 860 +3 1258 1336 726 +3 1258 1359 610 +3 1262 1275 733 +3 1262 1366 586 +3 1262 1408 484 +3 1265 1433 731 +3 1266 1379 862 +3 1267 1315 612 +3 1268 1269 548 +3 1276 1290 869 +3 1276 1338 704 +3 1278 1396 975 +3 1278 1404 788 +3 1282 1372 555 +3 1284 1287 710 +3 1284 1405 618 +3 1286 1339 229 +3 1290 1373 869 +3 1291 1433 481 +3 1297 1321 777 +3 1299 1365 799 +3 1304 1351 525 +3 1304 1370 699 +3 1305 1406 686 +3 1311 1443 695 +3 1312 1341 712 +3 1316 1374 560 +3 1317 1441 714 +3 1319 1335 684 +3 1319 1374 845 +3 1322 1426 816 +3 1324 1357 784 +3 1330 1334 705 +3 1335 1414 552 +3 1337 1429 660 +3 1341 1422 564 +3 1356 1390 554 +3 1359 1414 780 +3 1361 1393 771 +3 1364 1432 746 +3 1365 1443 528 +3 1365 1456 799 +3 1366 1382 831 +3 1369 1431 721 +3 1376 1410 620 +3 1380 1449 736 +3 1381 1447 489 +3 1385 1413 568 +3 1390 1427 554 +3 1392 1416 806 +3 1411 1433 783 +3 1422 1455 708 +3 1445 1453 557 +3 1458 1995 1916 +3 1458 2171 1943 +3 1458 2246 1995 +3 1459 2282 1955 +3 1459 2342 2077 +3 1460 2367 1803 +3 1461 1855 1835 +3 1461 2055 1792 +3 1461 2412 2055 +3 1462 1961 1769 +3 1462 2225 1791 +3 1462 2421 2225 +3 1463 2143 1861 +3 1463 2160 1738 +3 1463 2266 1885 +3 1464 2004 1688 +3 1464 2204 1904 +3 1464 2206 2004 +3 1465 2307 1997 +3 1465 2361 1970 +3 1465 2410 2361 +3 1466 1888 1736 +3 1466 1903 1888 +3 1466 2022 1903 +3 1466 2083 2022 +3 1467 2034 1730 +3 1467 2125 2034 +3 1467 2148 1782 +3 1468 2086 1820 +3 1468 2296 2086 +3 1469 2054 1806 +3 1469 2251 1765 +3 1469 2366 2054 +3 1470 2116 2056 +3 1470 2389 1957 +3 1471 2336 2030 +3 1471 2343 1796 +3 1472 1931 1828 +3 1472 2173 2066 +3 1472 2214 1931 +3 1473 2080 1823 +3 1473 2094 2074 +3 1473 2369 1718 +3 1474 1804 1723 +3 1474 1935 1804 +3 1474 1984 1685 +3 1474 2399 1984 +3 1475 2156 1974 +3 1475 2388 2070 +3 1475 2394 2156 +3 1476 1778 1775 +3 1476 1870 1822 +3 1476 2309 1778 +3 1477 1784 1772 +3 1477 1954 1784 +3 1477 1993 1758 +3 1477 2323 1954 +3 1478 2232 1745 +3 1478 2263 2232 +3 1478 2413 2263 +3 1479 2117 1871 +3 1479 2150 1757 +3 1479 2200 1786 +3 1479 2295 1860 +3 1480 1929 1724 +3 1480 1979 1712 +3 1480 2194 1814 +3 1480 2419 1979 +3 1481 1826 1694 +3 1481 2184 1706 +3 1481 2327 1832 +3 1481 2417 1826 +3 1482 1795 1728 +3 1482 1896 1743 +3 1482 2165 1896 +3 1482 2210 1795 +3 1483 2000 1776 +3 1483 2050 1780 +3 1483 2317 2050 +3 1484 1991 1859 +3 1484 2017 1819 +3 1484 2043 1991 +3 1484 2159 2043 +3 1484 2220 2017 +3 1485 2108 1741 +3 1485 2218 1787 +3 1485 2384 1843 +3 1486 1821 1695 +3 1486 1850 1742 +3 1486 1921 1821 +3 1486 2400 1850 +3 1487 1975 1912 +3 1487 2134 1868 +3 1488 1939 1809 +3 1488 2105 1807 +3 1488 2316 1939 +3 1489 1894 1732 +3 1489 2202 1829 +3 1489 2249 1894 +3 1490 1857 1754 +3 1490 1948 1777 +3 1490 2106 1857 +3 1491 2001 1930 +3 1491 2152 1920 +3 1491 2164 2152 +3 1491 2177 1740 +3 1492 1922 1719 +3 1492 2072 1825 +3 1492 2147 1852 +3 1492 2179 1922 +3 1493 1946 1748 +3 1493 2193 1895 +3 1494 1918 1846 +3 1494 2268 1794 +3 1494 2345 1918 +3 1495 2052 1818 +3 1495 2079 1862 +3 1495 2167 2079 +3 1496 2255 1830 +3 1496 2264 1996 +3 1496 2286 2023 +3 1497 2082 1735 +3 1497 2176 2047 +3 1497 2183 2082 +3 1497 2389 1759 +3 1498 1992 1781 +3 1498 2015 1992 +3 1498 2350 1944 +3 1499 1986 1773 +3 1499 2192 1883 +3 1500 1990 1793 +3 1500 2330 1990 +3 1500 2378 1913 +3 1501 2031 1938 +3 1501 2228 1945 +3 1501 2300 2228 +3 1501 2373 2024 +3 1502 1908 1682 +3 1502 2076 1908 +3 1503 2103 1882 +3 1503 2299 2091 +3 1504 2007 1976 +3 1504 2242 2137 +3 1504 2302 2242 +3 1504 2351 2007 +3 1505 2195 2002 +3 1505 2257 2006 +3 1505 2329 2195 +3 1506 1963 1712 +3 1506 2020 1729 +3 1506 2281 1963 +3 1507 2138 1750 +3 1507 2258 2138 +3 1507 2320 2258 +3 1507 2332 1875 +3 1508 2185 1688 +3 1508 2314 1701 +3 1508 2318 2185 +3 1509 2115 1726 +3 1509 2250 2014 +3 1510 2162 1788 +3 1510 2209 2085 +3 1510 2382 2029 +3 1511 1949 1762 +3 1511 2144 1949 +3 1511 2201 1730 +3 1511 2385 2144 +3 1512 1900 1755 +3 1512 2041 1724 +3 1512 2169 1696 +3 1513 2244 2025 +3 1513 2256 2021 +3 1513 2387 1937 +3 1514 1927 1881 +3 1514 2127 1927 +3 1514 2237 1694 +3 1515 1851 1708 +3 1515 2121 1851 +3 1515 2170 1752 +3 1516 2073 1737 +3 1516 2212 1854 +3 1517 1807 1764 +3 1517 2057 1807 +3 1517 2275 2057 +3 1517 2284 1899 +3 1518 2172 1880 +3 1518 2196 2172 +3 1518 2325 2019 +3 1519 2118 1746 +3 1519 2203 2049 +3 1519 2290 2118 +3 1520 1980 1704 +3 1520 2168 2139 +3 1520 2267 1980 +3 1521 2182 1736 +3 1521 2227 1874 +3 1522 2010 1831 +3 1522 2036 1747 +3 1522 2123 2036 +3 1522 2420 1847 +3 1523 1960 1706 +3 1523 2136 1953 +3 1523 2301 1960 +3 1524 2207 2140 +3 1524 2293 2207 +3 1524 2362 2113 +3 1525 2081 1778 +3 1525 2234 1817 +3 1525 2262 2081 +3 1526 1782 1748 +3 1526 2032 1768 +3 1526 2208 1782 +3 1526 2289 2032 +3 1527 2146 1795 +3 1527 2239 1796 +3 1527 2291 1751 +3 1528 2273 1955 +3 1528 2306 1765 +3 1529 1860 1691 +3 1529 2033 1758 +3 1529 2063 1767 +3 1529 2222 1860 +3 1530 2253 1811 +3 1530 2334 1931 +3 1530 2372 2334 +3 1531 2221 2197 +3 1531 2297 2124 +3 1531 2380 2221 +3 1532 2211 1806 +3 1532 2396 2211 +3 1533 1905 1803 +3 1533 2229 1905 +3 1533 2403 2229 +3 1534 1957 1735 +3 1534 2231 1830 +3 1534 2311 1810 +3 1535 1821 1771 +3 1535 2386 1821 +3 1535 2422 1822 +3 1536 2130 1828 +3 1536 2368 1952 +3 1536 2418 2130 +3 1537 2005 1891 +3 1537 2166 1839 +3 1537 2271 2166 +3 1538 1829 1710 +3 1538 2260 2214 +3 1538 2324 1829 +3 1539 1827 1741 +3 1539 2159 1819 +3 1539 2223 1791 +3 1540 2061 1777 +3 1540 2379 2061 +3 1541 1808 1754 +3 1541 2102 1815 +3 1541 2155 1718 +3 1542 2107 1906 +3 1542 2236 1825 +3 1542 2321 1718 +3 1542 2370 2107 +3 1543 2047 1749 +3 1543 2070 1750 +3 1543 2357 2047 +3 1543 2358 2357 +3 1544 2163 1800 +3 1544 2233 1775 +3 1544 2359 1872 +3 1545 2008 1701 +3 1545 2349 2008 +3 1546 1971 1732 +3 1546 2045 1798 +3 1546 2230 1971 +3 1546 2398 2045 +3 1547 2101 1723 +3 1547 2185 1774 +3 1548 1878 1753 +3 1548 1954 1719 +3 1548 2270 1784 +3 1548 2371 1878 +3 1549 2013 1704 +3 1549 2056 1908 +3 1549 2347 2013 +3 1550 2001 1740 +3 1550 2245 1882 +3 1550 2247 2001 +3 1550 2354 1837 +3 1551 2037 1721 +3 1551 2080 1851 +3 1551 2226 1731 +3 1551 2313 1823 +3 1552 1813 1723 +3 1552 1842 1730 +3 1552 2287 1842 +3 1552 2305 1813 +3 1553 2304 1685 +3 1553 2381 1877 +3 1554 1921 1742 +3 1554 2096 1802 +3 1554 2356 1921 +3 1555 1913 1772 +3 1555 2178 1913 +3 1555 2270 1893 +3 1556 1852 1792 +3 1556 1876 1708 +3 1556 2055 1876 +3 1556 2072 1852 +3 1556 2341 2072 +3 1557 1871 1732 +3 1557 1894 1703 +3 1557 2295 1871 +3 1557 2365 1835 +3 1558 2200 1757 +3 1558 2337 1873 +3 1558 2346 2200 +3 1559 1968 1794 +3 1559 2133 1889 +3 1559 2292 1885 +3 1560 1895 1762 +3 1560 1898 1736 +3 1560 1949 1898 +3 1561 1919 1700 +3 1561 2066 1752 +3 1561 2249 1919 +3 1561 2254 2249 +3 1562 1900 1696 +3 1562 2186 1879 +3 1562 2326 1938 +3 1562 2352 1900 +3 1563 1929 1712 +3 1563 1963 1763 +3 1563 2068 1853 +3 1563 2189 1929 +3 1564 1981 1942 +3 1564 2363 1850 +3 1565 1836 1804 +3 1565 1962 1688 +3 1565 2091 1799 +3 1566 1855 1792 +3 1566 2323 1865 +3 1566 2402 1855 +3 1567 2152 1849 +3 1567 2187 1848 +3 1568 1859 1733 +3 1568 1956 1781 +3 1568 1978 1790 +3 1568 2220 1859 +3 1569 1966 1965 +3 1569 1972 1698 +3 1569 2151 1884 +3 1570 1910 1844 +3 1570 1912 1818 +3 1570 2277 1912 +3 1570 2391 1910 +3 1571 2083 1958 +3 1571 2182 1874 +3 1571 2237 1881 +3 1572 1915 1754 +3 1572 2235 1915 +3 1572 2313 2235 +3 1572 2369 1823 +3 1573 1932 1909 +3 1573 2203 1932 +3 1573 2274 1907 +3 1574 1930 1845 +3 1574 2109 1797 +3 1574 2164 1930 +3 1574 2276 1886 +3 1575 1976 1864 +3 1575 2302 1976 +3 1575 2411 1991 +3 1576 1990 1783 +3 1576 2038 1766 +3 1576 2384 1793 +3 1577 1827 1791 +3 1577 1926 1827 +3 1577 2016 1793 +3 1577 2225 2016 +3 1578 2004 1729 +3 1578 2020 1712 +3 1578 2314 1947 +3 1579 1992 1769 +3 1579 2017 1781 +3 1579 2223 1819 +3 1580 2064 1835 +3 1580 2402 1758 +3 1581 1914 1820 +3 1581 2029 1914 +3 1581 2184 1832 +3 1582 1974 1713 +3 1582 2364 2039 +3 1582 2405 1817 +3 1583 1917 1769 +3 1583 2015 1757 +3 1583 2150 1860 +3 1583 2222 1917 +3 1584 1975 1933 +3 1584 2167 1818 +3 1585 1960 1824 +3 1585 2099 1925 +3 1585 2417 1960 +3 1586 2191 1739 +3 1586 2279 1950 +3 1586 2320 1875 +3 1587 2081 1779 +3 1587 2089 1800 +3 1587 2163 1775 +3 1587 2406 2089 +3 1588 2035 1902 +3 1588 2158 1970 +3 1588 2255 1996 +3 1588 2294 2255 +3 1589 1993 1772 +3 1589 2063 1993 +3 1589 2378 2042 +3 1589 2409 2063 +3 1590 1951 1911 +3 1590 2165 1937 +3 1590 2215 1896 +3 1590 2387 1705 +3 1591 1939 1856 +3 1591 2312 1890 +3 1591 2351 1809 +3 1592 1805 1777 +3 1592 1948 1905 +3 1592 2030 1805 +3 1592 2229 2030 +3 1593 2088 1756 +3 1593 2140 1780 +3 1593 2340 1994 +3 1594 2011 1861 +3 1594 2159 2011 +3 1594 2243 2043 +3 1595 2108 1787 +3 1595 2123 1847 +3 1595 2128 1861 +3 1595 2390 2108 +3 1596 2036 1787 +3 1596 2104 1747 +3 1596 2218 1766 +3 1596 2353 2104 +3 1597 2026 1862 +3 1597 2049 1901 +3 1597 2290 2049 +3 1598 2250 1834 +3 1598 2328 1761 +3 1598 2329 2006 +3 1599 2041 1755 +3 1599 2048 1814 +3 1599 2194 2041 +3 1600 1948 1915 +3 1600 2119 1803 +3 1600 2235 2119 +3 1601 2356 1816 +3 1601 2414 1771 +3 1602 2057 1924 +3 1602 2157 1856 +3 1602 2316 2057 +3 1603 1953 1945 +3 1603 2071 1722 +3 1603 2228 1697 +3 1603 2301 1953 +3 1604 2024 1867 +3 1604 2300 2024 +3 1604 2335 1940 +3 1604 2397 2059 +3 1605 2023 1928 +3 1605 2075 1727 +3 1605 2275 1899 +3 1606 1968 1885 +3 1606 2198 1968 +3 1606 2266 1847 +3 1606 2420 1831 +3 1607 1848 1729 +3 1607 1920 1848 +3 1607 2177 1920 +3 1607 2206 1904 +3 1608 2018 1806 +3 1608 2401 2018 +3 1609 2031 1945 +3 1609 2086 2031 +3 1609 2136 1820 +3 1610 2010 1897 +3 1610 2069 1887 +3 1610 2345 1831 +3 1611 2133 1997 +3 1611 2331 2105 +3 1612 2112 1802 +3 1612 2277 1844 +3 1613 1959 1782 +3 1613 2115 1959 +3 1613 2408 2115 +3 1614 2176 1759 +3 1614 2267 2156 +3 1614 2394 2176 +3 1615 2172 1903 +3 1615 2244 1880 +3 1616 2095 1710 +3 1616 2202 1971 +3 1616 2205 2095 +3 1616 2230 2205 +3 1617 2121 1752 +3 1617 2130 2037 +3 1617 2173 1828 +3 1618 1889 1809 +3 1618 2137 1738 +3 1618 2292 1889 +3 1618 2351 2137 +3 1619 1863 1850 +3 1619 2153 1863 +3 1619 2359 1801 +3 1619 2400 1872 +3 1620 1946 1941 +3 1620 2196 2019 +3 1620 2342 1716 +3 1621 2149 1866 +3 1621 2169 1724 +3 1621 2189 1853 +3 1622 1989 1806 +3 1622 2207 1989 +3 1622 2211 2000 +3 1623 2217 1925 +3 1623 2355 2217 +3 1623 2374 2087 +3 1624 1988 1898 +3 1624 2144 1995 +3 1624 2246 1988 +3 1625 1869 1796 +3 1625 2221 1869 +3 1625 2239 1795 +3 1626 2148 1730 +3 1626 2193 1748 +3 1626 2201 1762 +3 1627 1895 1888 +3 1627 1941 1895 +3 1627 2196 1941 +3 1628 2135 1737 +3 1628 2362 1923 +3 1628 2377 2135 +3 1629 2025 2022 +3 1629 2083 1881 +3 1629 2256 2025 +3 1630 2014 2006 +3 1630 2115 2014 +3 1630 2125 1959 +3 1630 2257 2125 +3 1631 2079 1987 +3 1631 2161 1964 +3 1631 2290 1862 +3 1632 2181 1845 +3 1632 2247 1969 +3 1633 2077 2019 +3 1633 2174 2077 +3 1633 2325 1728 +3 1634 2028 1857 +3 1634 2046 2028 +3 1634 2061 1833 +3 1634 2106 2061 +3 1635 1997 1794 +3 1635 2268 1846 +3 1635 2271 1891 +3 1635 2410 1997 +3 1636 2005 1839 +3 1636 2040 2005 +3 1636 2076 2040 +3 1636 2241 1892 +3 1637 2199 1737 +3 1637 2392 1884 +3 1638 2204 1799 +3 1638 2245 1740 +3 1638 2299 1882 +3 1639 2188 1955 +3 1639 2273 1770 +3 1639 2289 2188 +3 1640 2035 1970 +3 1640 2040 2035 +3 1640 2361 1891 +3 1641 2212 1745 +3 1641 2238 1765 +3 1642 2197 1743 +3 1642 2215 1911 +3 1642 2224 2197 +3 1643 2101 1916 +3 1643 2287 2101 +3 1643 2385 1842 +3 1644 2154 1849 +3 1644 2164 1886 +3 1645 2100 1928 +3 1645 2231 2100 +3 1645 2286 2231 +3 1646 1918 1887 +3 1646 2166 1846 +3 1646 2280 1934 +3 1647 1932 1746 +3 1647 2308 1909 +3 1647 2322 1858 +3 1648 2183 1999 +3 1648 2311 2082 +3 1649 2158 1996 +3 1649 2264 1899 +3 1649 2284 1764 +3 1650 2098 2062 +3 1650 2329 1761 +3 1650 2381 2114 +3 1651 2110 1955 +3 1651 2192 2110 +3 1651 2282 1751 +3 1652 2209 1832 +3 1652 2227 2085 +3 1652 2327 1874 +3 1653 2321 1825 +3 1653 2341 2074 +3 1654 2097 1985 +3 1654 2127 2097 +3 1654 2256 1927 +3 1655 1957 1830 +3 1655 2116 1957 +3 1655 2294 2116 +3 1656 2234 1778 +3 1656 2309 1875 +3 1656 2332 2234 +3 1657 2175 1867 +3 1657 2326 2175 +3 1657 2373 2326 +3 1658 2103 2093 +3 1658 2126 1977 +3 1658 2304 2126 +3 1659 2317 1952 +3 1659 2334 2317 +3 1659 2368 1828 +3 1660 2318 2008 +3 1660 2349 1788 +3 1661 1986 1883 +3 1661 2291 1796 +3 1661 2343 1789 +3 1662 2337 1944 +3 1662 2350 1790 +3 1662 2376 2219 +3 1663 2044 1914 +3 1663 2048 2044 +3 1663 2213 2048 +3 1663 2382 2213 +3 1664 2103 1977 +3 1664 2354 1882 +3 1665 2073 1854 +3 1665 2113 2073 +3 1665 2251 1989 +3 1665 2293 2113 +3 1666 2162 2085 +3 1666 2227 1988 +3 1666 2246 1943 +3 1667 2296 1755 +3 1667 2352 1938 +3 1668 2092 1702 +3 1668 2179 1825 +3 1668 2236 1906 +3 1668 2278 2092 +3 1669 2243 2242 +3 1669 2302 1991 +3 1670 2131 1811 +3 1670 2260 1840 +3 1670 2265 2131 +3 1671 2183 2047 +3 1671 2240 1999 +3 1671 2357 2240 +3 1672 2084 2054 +3 1672 2192 2084 +3 1672 2306 2110 +3 1672 2366 2306 +3 1673 2026 2009 +3 1673 2052 2026 +3 1673 2303 1910 +3 1673 2391 2052 +3 1674 2120 2018 +3 1674 2190 1803 +3 1674 2367 2120 +3 1674 2401 2190 +3 1675 2315 1994 +3 1675 2372 1811 +3 1676 2129 2124 +3 1676 2132 1982 +3 1676 2297 2132 +3 1676 2379 2129 +3 1677 2258 2122 +3 1677 2358 2138 +3 1678 2114 1984 +3 1678 2195 2114 +3 1678 2399 1813 +3 1679 2129 1805 +3 1679 2336 1869 +3 1679 2380 2124 +3 1680 2145 1880 +3 1680 2165 2145 +3 1680 2244 1937 +3 1681 1936 236 +3 1681 2187 1936 +3 1681 2281 2187 +3 1681 2288 2281 +3 1682 1902 1502 +3 1682 2116 1902 +3 1683 2076 1892 +3 1683 2285 1908 +3 1683 2348 2283 +3 1684 2279 1822 +3 1684 2344 1950 +3 1684 2422 1967 +3 1685 1935 1474 +3 1685 1984 1553 +3 1685 2091 1935 +3 1685 2093 2091 +3 1685 2304 2093 +3 1686 1975 1942 +3 1686 2375 1933 +3 1687 1841 208 +3 1687 2168 2013 +3 1687 2347 1841 +3 1688 1836 1565 +3 1688 1947 1508 +3 1688 1962 1464 +3 1688 2004 1947 +3 1688 2185 1836 +3 1689 2102 1857 +3 1689 2298 1815 +3 1690 2142 118 +3 1690 2346 2142 +3 1690 2398 2346 +3 1691 2033 1529 +3 1691 2064 2033 +3 1691 2295 2064 +3 1692 2007 1890 +3 1692 2383 1864 +3 1693 2216 1783 +3 1693 2259 2216 +3 1693 2330 1913 +3 1694 1983 1481 +3 1694 2111 1514 +3 1694 2237 1983 +3 1694 2355 2111 +3 1695 1872 1486 +3 1695 2233 1872 +3 1695 2386 1870 +3 1696 1900 1512 +3 1696 2169 1866 +3 1696 2186 1562 +3 1696 2360 2186 +3 1697 2051 1603 +3 1697 2059 161 +3 1697 2300 2059 +3 1698 1966 1569 +3 1698 2250 1966 +3 1698 2415 2250 +3 1699 2367 2248 +3 1699 2396 2120 +3 1699 2418 2310 +3 1700 2066 1561 +3 1700 2214 2066 +3 1700 2324 2214 +3 1701 1814 1545 +3 1701 2008 1508 +3 1701 2314 1979 +3 1701 2419 1814 +3 1702 2092 187 +3 1702 2179 1668 +3 1702 2371 1922 +3 1703 2365 1557 +3 1703 2412 2365 +3 1704 2013 1520 +3 1704 2056 1549 +3 1704 2338 2056 +3 1705 1951 1590 +3 1705 1985 171 +3 1705 2021 1985 +3 1705 2387 2021 +3 1706 2012 1523 +3 1706 2184 2012 +3 1706 2417 1481 +3 1707 1974 1817 +3 1707 2332 2065 +3 1707 2388 1974 +3 1708 1876 1515 +3 1708 2080 2074 +3 1708 2341 1556 +3 1709 2257 2002 +3 1709 2305 2034 +3 1710 1840 1538 +3 1710 2202 1616 +3 1710 2269 1840 +3 1711 2253 1931 +3 1711 2260 2253 +3 1712 1929 1480 +3 1712 1963 1563 +3 1712 1979 1578 +3 1712 2020 1506 +3 1713 2139 1582 +3 1713 2267 2139 +3 1714 2168 1998 +3 1714 2364 2139 +3 1714 2416 2364 +3 1715 2170 1876 +3 1715 2254 2170 +3 1715 2412 2254 +3 1716 1946 1620 +3 1716 2261 1946 +3 1716 2289 2261 +3 1716 2342 2188 +3 1717 2155 1815 +3 1717 2370 2155 +3 1717 2404 2107 +3 1718 1808 1541 +3 1718 2094 1473 +3 1718 2321 2094 +3 1718 2369 1808 +3 1718 2370 1542 +3 1719 1922 1548 +3 1719 2147 1492 +3 1719 2323 2147 +3 1720 2203 2003 +3 1720 2393 1901 +3 1721 2226 1551 +3 1721 2248 2226 +3 1721 2418 2248 +3 1722 2071 163 +3 1722 2301 1603 +3 1723 1804 1547 +3 1723 1813 1474 +3 1723 2287 1552 +3 1724 2169 1512 +3 1724 2189 1621 +3 1724 2194 1480 +3 1725 2262 1817 +3 1725 2339 2141 +3 1725 2405 2339 +3 1726 1966 1509 +3 1726 2413 1965 +3 1727 2075 132 +3 1727 2275 1605 +3 1728 2145 1482 +3 1728 2146 1633 +3 1728 2325 1880 +3 1729 1848 1506 +3 1729 2020 1578 +3 1729 2206 1607 +3 1730 1842 1511 +3 1730 2034 1552 +3 1730 2148 1467 +3 1730 2201 1626 +3 1731 2226 2119 +3 1731 2313 1551 +3 1732 1894 1557 +3 1732 1971 1489 +3 1732 2117 1546 +3 1733 1978 1568 +3 1733 2333 1978 +3 1733 2411 2027 +3 1734 2042 2016 +3 1734 2409 2042 +3 1734 2421 2409 +3 1735 2082 1534 +3 1735 2389 1497 +3 1736 1888 1560 +3 1736 1898 1521 +3 1736 1958 1466 +3 1736 2182 1958 +3 1737 2058 1637 +3 1737 2073 1628 +3 1737 2135 104 +3 1737 2199 1516 +3 1738 2143 1463 +3 1738 2160 1618 +3 1738 2243 2143 +3 1739 2191 142 +3 1739 2320 1586 +3 1740 1904 1638 +3 1740 2001 1491 +3 1740 2177 1904 +3 1740 2245 1550 +3 1741 1827 1485 +3 1741 2011 1539 +3 1741 2390 2011 +3 1742 1868 1554 +3 1742 1921 1486 +3 1742 2363 1868 +3 1743 2210 1482 +3 1743 2215 1642 +3 1743 2221 2210 +3 1744 2090 225 +3 1744 2167 2090 +3 1745 1965 1478 +3 1745 2151 1965 +3 1745 2199 2151 +3 1745 2212 2199 +3 1745 2232 1641 +3 1746 1932 1519 +3 1746 1964 228 +3 1746 2118 1964 +3 1746 2272 1647 +3 1747 2010 1522 +3 1747 2036 1596 +3 1747 2104 197 +3 1748 2148 1626 +3 1748 2193 1493 +3 1748 2261 1526 +3 1749 2070 1543 +3 1749 2394 2070 +3 1750 2065 1507 +3 1750 2138 1543 +3 1750 2388 2065 +3 1751 1883 1651 +3 1751 2146 1527 +3 1751 2174 2146 +3 1751 2282 2174 +3 1751 2291 1883 +3 1752 2121 1515 +3 1752 2170 1561 +3 1752 2173 1617 +3 1753 1878 189 +3 1753 2270 1548 +3 1754 1808 1572 +3 1754 1915 1490 +3 1754 2102 1541 +3 1755 2041 1512 +3 1755 2044 1599 +3 1755 2296 2044 +3 1755 2352 1667 +3 1756 2088 107 +3 1756 2140 1593 +3 1756 2362 2140 +3 1757 1944 1558 +3 1757 2015 1944 +3 1757 2150 1583 +3 1757 2200 1479 +3 1758 1865 1477 +3 1758 2033 1580 +3 1758 2063 1529 +3 1758 2402 1865 +3 1759 1980 1614 +3 1759 2176 1497 +3 1759 2338 1980 +3 1759 2389 2338 +3 1760 2224 175 +3 1760 2297 2197 +3 1761 2098 1650 +3 1761 2328 97 +3 1761 2329 1598 +3 1762 1949 1560 +3 1762 2193 1626 +3 1762 2201 1511 +3 1763 2068 1563 +3 1763 2288 238 +3 1764 2158 1649 +3 1764 2284 1517 +3 1764 2307 2158 +3 1764 2331 2307 +3 1765 1854 1641 +3 1765 2238 1528 +3 1765 2251 1854 +3 1765 2366 1469 +3 1766 1843 1576 +3 1766 2038 195 +3 1766 2218 1843 +3 1766 2353 1596 +3 1767 2222 1529 +3 1767 2421 1917 +3 1768 2208 1526 +3 1768 2408 2208 +3 1768 2413 2408 +3 1769 1917 1462 +3 1769 1961 1579 +3 1769 2015 1583 +3 1770 2032 1639 +3 1770 2238 2232 +3 1770 2263 2032 +3 1770 2273 2238 +3 1771 1821 1601 +3 1771 2414 146 +3 1771 2422 1535 +3 1772 1784 1555 +3 1772 1993 1477 +3 1772 2378 1589 +3 1773 2084 1499 +3 1773 2401 2084 +3 1773 2403 2190 +3 1774 1916 1547 +3 1774 2171 1916 +3 1774 2318 2171 +3 1775 1778 1587 +3 1775 1870 1476 +3 1775 2163 1544 +3 1775 2233 1870 +3 1776 1952 1483 +3 1776 2310 1952 +3 1776 2396 2310 +3 1777 1805 1540 +3 1777 1948 1592 +3 1777 2106 1490 +3 1778 2081 1587 +3 1778 2234 1525 +3 1778 2309 1656 +3 1779 2141 214 +3 1779 2262 2141 +3 1779 2406 1587 +3 1780 2000 1483 +3 1780 2050 1593 +3 1780 2207 2000 +3 1781 1956 1498 +3 1781 1992 1579 +3 1781 2220 1568 +3 1782 1959 1467 +3 1782 2148 1748 +3 1782 2208 1613 +3 1783 2038 1576 +3 1783 2330 1693 +3 1783 2407 2038 +3 1784 1954 1548 +3 1784 2270 1555 +3 1785 2340 2050 +3 1785 2372 2340 +3 1786 2117 1479 +3 1786 2398 2117 +3 1787 2108 1485 +3 1787 2123 1595 +3 1787 2218 1596 +3 1788 1943 1660 +3 1788 2162 1943 +3 1788 2349 2213 +3 1788 2382 1510 +3 1789 1986 1661 +3 1789 2343 2030 +3 1789 2403 1986 +3 1790 1956 1568 +3 1790 1978 122 +3 1790 2350 1956 +3 1790 2376 1662 +3 1791 1827 1539 +3 1791 1961 1462 +3 1791 2223 1961 +3 1791 2225 1577 +3 1792 1855 1461 +3 1792 2055 1556 +3 1792 2147 1566 +3 1793 1926 1577 +3 1793 1990 1576 +3 1793 2016 1500 +3 1793 2384 1926 +3 1794 1968 1494 +3 1794 2133 1559 +3 1794 2268 1635 +3 1795 2146 1728 +3 1795 2210 1625 +3 1795 2239 1527 +3 1796 1869 1471 +3 1796 2239 1625 +3 1796 2291 1527 +3 1796 2343 1661 +3 1797 2109 87 +3 1797 2276 1574 +3 1798 2045 117 +3 1798 2230 1546 +3 1799 1962 1565 +3 1799 2204 1962 +3 1799 2299 1638 +3 1800 1801 1544 +3 1800 2089 216 +3 1800 2163 1587 +3 1801 2153 1619 +3 1801 2359 1544 +3 1802 1816 1554 +3 1802 2096 1612 +3 1802 2112 150 +3 1803 1905 1600 +3 1803 2119 1460 +3 1803 2190 1533 +3 1803 2367 1674 +3 1804 1836 1547 +3 1804 1935 1565 +3 1805 2129 1540 +3 1805 2336 1679 +3 1806 1989 1469 +3 1806 2018 1532 +3 1806 2054 1608 +3 1806 2211 1622 +3 1807 2316 1488 +3 1807 2331 1764 +3 1808 2369 1572 +3 1809 1889 1488 +3 1809 1939 1591 +3 1809 2351 1618 +3 1810 2067 136 +3 1810 2231 1534 +3 1810 2311 2067 +3 1811 2131 111 +3 1811 2253 1670 +3 1811 2315 1675 +3 1811 2372 1530 +3 1812 2087 168 +3 1812 2111 2087 +3 1812 2127 2111 +3 1813 2002 1678 +3 1813 2305 2002 +3 1813 2399 1474 +3 1814 2048 1545 +3 1814 2194 1599 +3 1814 2419 1480 +3 1815 2102 1689 +3 1815 2155 1541 +3 1815 2298 182 +3 1815 2404 1717 +3 1816 2053 1601 +3 1816 2356 1554 +3 1817 1974 1582 +3 1817 2234 1707 +3 1817 2262 1525 +3 1817 2405 1725 +3 1818 1912 1584 +3 1818 2052 1570 +3 1818 2167 1495 +3 1819 2017 1579 +3 1819 2159 1484 +3 1819 2223 1539 +3 1820 1914 1468 +3 1820 2012 1581 +3 1820 2086 1609 +3 1820 2136 2012 +3 1821 1921 1601 +3 1821 2386 1695 +3 1822 2060 1476 +3 1822 2279 2060 +3 1822 2386 1535 +3 1822 2422 1684 +3 1823 2080 1551 +3 1823 2313 1572 +3 1823 2369 1473 +3 1824 1960 1722 +3 1824 2099 1585 +3 1825 2072 1653 +3 1825 2179 1492 +3 1825 2236 1668 +3 1825 2321 1542 +3 1826 2355 1694 +3 1826 2417 2217 +3 1827 1926 1485 +3 1828 1931 1659 +3 1828 2130 1617 +3 1828 2173 1472 +3 1828 2368 1536 +3 1829 1919 1489 +3 1829 2202 1710 +3 1829 2324 1919 +3 1830 1957 1534 +3 1830 2255 1655 +3 1830 2286 1496 +3 1831 2010 1610 +3 1831 2198 1606 +3 1831 2345 2198 +3 1831 2420 1522 +3 1832 2029 1581 +3 1832 2184 1481 +3 1832 2209 2029 +3 1832 2327 1652 +3 1833 1982 178 +3 1833 2046 1634 +3 1833 2379 1982 +3 1834 2078 1598 +3 1834 2415 99 +3 1835 1855 1580 +3 1835 2064 1557 +3 1835 2365 1461 +3 1836 2185 1547 +3 1837 2247 1550 +3 1837 2252 91 +3 1837 2354 2252 +3 1838 2180 140 +3 1838 2358 2180 +3 1839 1934 203 +3 1839 2005 1537 +3 1839 2166 1934 +3 1839 2241 1636 +3 1840 2260 1538 +3 1840 2265 1670 +3 1840 2269 113 +3 1841 2283 207 +3 1841 2285 2283 +3 1841 2347 2285 +3 1842 2287 1643 +3 1842 2385 1511 +3 1843 2218 1485 +3 1843 2384 1576 +3 1844 1910 152 +3 1844 2112 1612 +3 1844 2277 1570 +3 1845 1930 1632 +3 1845 2109 1574 +3 1845 2181 88 +3 1846 1918 1646 +3 1846 2268 1494 +3 1846 2271 1635 +3 1847 2123 1522 +3 1847 2128 1595 +3 1847 2266 2128 +3 1847 2420 1606 +3 1848 1920 1567 +3 1848 2187 1506 +3 1849 1936 1567 +3 1849 2152 1644 +3 1849 2154 234 +3 1850 1863 1564 +3 1850 2363 1742 +3 1850 2400 1619 +3 1851 2037 1551 +3 1851 2080 1708 +3 1851 2121 2037 +3 1852 2072 1492 +3 1852 2147 1792 +3 1853 2068 239 +3 1853 2149 1621 +3 1853 2189 1563 +3 1854 2073 1516 +3 1854 2212 1641 +3 1854 2251 1665 +3 1855 2402 1580 +3 1856 1939 1602 +3 1856 2157 129 +3 1856 2312 1591 +3 1857 2028 1689 +3 1857 2102 1754 +3 1857 2106 1634 +3 1858 1973 5 +3 1858 2308 1647 +3 1858 2322 1973 +3 1859 2220 1484 +3 1859 2411 1733 +3 1860 2150 1479 +3 1860 2222 1583 +3 1860 2295 1691 +3 1861 2128 1463 +3 1861 2143 1594 +3 1861 2390 1595 +3 1862 2026 1495 +3 1862 2079 1631 +3 1862 2290 1597 +3 1863 1981 1564 +3 1863 2153 219 +3 1864 1976 1692 +3 1864 2027 1575 +3 1864 2383 126 +3 1865 2323 1477 +3 1865 2402 1566 +3 1866 2149 241 +3 1866 2169 1621 +3 1866 2360 1696 +3 1867 2024 1657 +3 1867 2175 245 +3 1867 2335 1604 +3 1868 1942 1487 +3 1868 2096 1554 +3 1868 2134 2096 +3 1868 2363 1942 +3 1869 2336 1471 +3 1869 2380 1679 +3 1870 2233 1695 +3 1870 2386 1822 +3 1871 2117 1732 +3 1871 2295 1479 +3 1872 2233 1544 +3 1872 2359 1619 +3 1872 2400 1486 +3 1873 2142 1558 +3 1873 2219 120 +3 1873 2337 2219 +3 1874 1983 1571 +3 1874 2182 1521 +3 1874 2227 1652 +3 1874 2327 1983 +3 1875 2060 1586 +3 1875 2309 2060 +3 1875 2320 1507 +3 1875 2332 1656 +3 1876 2055 1715 +3 1876 2170 1515 +3 1877 2062 95 +3 1877 2304 1553 +3 1877 2381 2062 +3 1878 2371 1702 +3 1879 2186 243 +3 1879 2326 1562 +3 1880 2145 1728 +3 1880 2172 1615 +3 1880 2244 1680 +3 1880 2325 1518 +3 1881 1927 1629 +3 1881 2083 1571 +3 1881 2237 1514 +3 1882 2103 1664 +3 1882 2245 1638 +3 1882 2299 1503 +3 1882 2354 1550 +3 1883 1986 1499 +3 1883 2192 1651 +3 1883 2291 1661 +3 1884 1972 1569 +3 1884 2151 1637 +3 1884 2392 102 +3 1885 1968 1559 +3 1885 2160 1463 +3 1885 2266 1606 +3 1885 2292 2160 +3 1886 2154 1644 +3 1886 2164 1574 +3 1886 2276 233 +3 1887 1918 1610 +3 1887 2069 200 +3 1887 2280 1646 +3 1888 1895 1560 +3 1888 1903 1627 +3 1889 2105 1488 +3 1889 2133 2105 +3 1889 2292 1559 +3 1890 2007 1591 +3 1890 2312 128 +3 1890 2383 1692 +3 1891 2005 1640 +3 1891 2271 1537 +3 1891 2410 1635 +3 1892 2076 1636 +3 1892 2241 205 +3 1892 2348 1683 +3 1893 2178 1555 +3 1893 2259 2178 +3 1893 2270 1753 +3 1894 2249 1703 +3 1895 1941 1493 +3 1895 2193 1762 +3 1896 2165 1590 +3 1896 2215 1743 +3 1897 2010 1747 +3 1897 2069 1610 +3 1898 1949 1624 +3 1898 1988 1521 +3 1899 2023 1605 +3 1899 2264 2023 +3 1899 2275 1517 +3 1899 2284 1649 +3 1900 2352 1755 +3 1901 2009 1597 +3 1901 2049 1720 +3 1901 2393 156 +3 1902 2035 1502 +3 1902 2294 1588 +3 1903 2022 1615 +3 1903 2196 1627 +3 1904 2177 1607 +3 1904 2204 1638 +3 1904 2206 1464 +3 1905 1948 1600 +3 1905 2229 1592 +3 1906 2107 185 +3 1906 2236 1542 +3 1906 2278 1668 +3 1907 2003 1573 +3 1907 2274 66 +3 1908 2056 1682 +3 1908 2076 1683 +3 1908 2285 1549 +3 1909 1932 1647 +3 1909 2274 1573 +3 1909 2308 67 +3 1910 2303 153 +3 1910 2391 1673 +3 1911 1951 173 +3 1911 2215 1590 +3 1911 2224 1642 +3 1912 1975 1584 +3 1912 2134 1487 +3 1912 2277 2134 +3 1913 2178 1693 +3 1913 2330 1500 +3 1913 2378 1772 +3 1914 2044 1468 +3 1914 2382 1663 +3 1915 1948 1490 +3 1915 2235 1600 +3 1916 1995 1643 +3 1916 2101 1547 +3 1916 2171 1458 +3 1917 2222 1767 +3 1917 2421 1462 +3 1918 2345 1610 +3 1919 2249 1489 +3 1919 2324 1700 +3 1920 2152 1567 +3 1920 2177 1491 +3 1921 2356 1601 +3 1922 2179 1702 +3 1922 2371 1548 +3 1923 2362 1756 +3 1923 2377 1628 +3 1924 2057 1727 +3 1924 2157 1602 +3 1925 2099 166 +3 1925 2217 1585 +3 1925 2374 1623 +3 1926 2384 1485 +3 1927 2127 1654 +3 1927 2256 1629 +3 1928 2023 1645 +3 1928 2075 1605 +3 1928 2100 134 +3 1929 2189 1724 +3 1930 2001 1632 +3 1930 2164 1491 +3 1931 2214 1711 +3 1931 2253 1530 +3 1931 2334 1659 +3 1932 2203 1519 +3 1933 1975 1686 +3 1933 2090 1584 +3 1933 2375 222 +3 1934 2166 1646 +3 1934 2280 202 +3 1935 2091 1565 +3 1936 2187 1567 +3 1937 2165 1680 +3 1937 2244 1513 +3 1937 2387 1590 +3 1938 2031 1667 +3 1938 2352 1562 +3 1938 2373 1501 +3 1939 2316 1602 +3 1940 2335 246 +3 1940 2395 159 +3 1940 2397 1604 +3 1941 1946 1493 +3 1941 2196 1620 +3 1942 1975 1487 +3 1942 1981 1686 +3 1942 2363 1564 +3 1943 2162 1666 +3 1943 2171 1660 +3 1943 2246 1458 +3 1944 2015 1498 +3 1944 2337 1558 +3 1944 2350 1662 +3 1945 1953 1609 +3 1945 2031 1501 +3 1945 2228 1603 +3 1946 2261 1748 +3 1947 2004 1578 +3 1947 2314 1508 +3 1949 2144 1624 +3 1950 2191 1586 +3 1950 2279 1684 +3 1950 2344 144 +3 1952 2310 1536 +3 1952 2317 1483 +3 1952 2368 1659 +3 1953 2136 1609 +3 1953 2301 1523 +3 1954 2323 1719 +3 1955 2110 1528 +3 1955 2188 1459 +3 1955 2273 1639 +3 1955 2282 1651 +3 1956 2350 1498 +3 1957 2116 1470 +3 1957 2389 1735 +3 1958 2083 1466 +3 1958 2182 1571 +3 1959 2115 1630 +3 1959 2125 1467 +3 1960 2301 1722 +3 1960 2417 1706 +3 1961 2223 1579 +3 1962 2204 1464 +3 1963 2281 1763 +3 1964 2118 1631 +3 1964 2161 227 +3 1965 1966 1726 +3 1965 2151 1569 +3 1965 2413 1478 +3 1966 2250 1509 +3 1967 2344 1684 +3 1967 2422 1771 +3 1968 2198 1494 +3 1969 2181 1632 +3 1969 2247 1837 +3 1970 2035 1588 +3 1970 2158 1465 +3 1970 2361 1640 +3 1971 2202 1489 +3 1971 2230 1616 +3 1972 2319 1698 +3 1973 2322 230 +3 1974 2156 1713 +3 1974 2388 1475 +3 1976 2007 1692 +3 1976 2302 1504 +3 1977 2103 1658 +3 1977 2126 93 +3 1977 2252 1664 +3 1978 2333 123 +3 1979 2314 1578 +3 1979 2419 1701 +3 1980 2267 1614 +3 1980 2338 1704 +3 1981 2375 1686 +3 1982 2132 177 +3 1982 2379 1676 +3 1983 2237 1571 +3 1983 2327 1481 +3 1984 2114 1553 +3 1984 2399 1678 +3 1985 2021 1654 +3 1985 2097 170 +3 1986 2403 1773 +3 1987 2079 1744 +3 1987 2161 1631 +3 1988 2227 1521 +3 1988 2246 1666 +3 1989 2251 1469 +3 1989 2293 1665 +3 1990 2330 1783 +3 1991 2043 1669 +3 1991 2302 1575 +3 1991 2411 1859 +3 1992 2015 1769 +3 1993 2063 1758 +3 1994 2088 1593 +3 1994 2315 109 +3 1994 2340 1675 +3 1995 2246 1624 +3 1995 2385 1643 +3 1996 2158 1588 +3 1996 2255 1496 +3 1996 2264 1649 +3 1997 2133 1794 +3 1997 2307 1611 +3 1997 2410 1465 +3 1998 2168 1687 +3 1998 2416 1714 +3 1999 2067 1648 +3 1999 2183 1671 +3 1999 2240 138 +3 2000 2207 1622 +3 2000 2211 1776 +3 2001 2247 1632 +3 2002 2195 1678 +3 2002 2257 1505 +3 2002 2305 1709 +3 2003 2203 1573 +3 2003 2393 1720 +3 2004 2206 1729 +3 2005 2040 1640 +3 2006 2014 1598 +3 2006 2257 1630 +3 2006 2329 1505 +3 2007 2351 1591 +3 2008 2318 1508 +3 2008 2349 1660 +3 2009 2026 1597 +3 2009 2303 1673 +3 2011 2159 1539 +3 2011 2390 1861 +3 2012 2136 1523 +3 2012 2184 1581 +3 2013 2168 1520 +3 2013 2347 1687 +3 2014 2115 1509 +3 2014 2250 1598 +3 2016 2042 1500 +3 2016 2225 1734 +3 2017 2220 1781 +3 2018 2120 1532 +3 2018 2401 1674 +3 2019 2077 1620 +3 2019 2196 1518 +3 2019 2325 1633 +3 2021 2256 1654 +3 2021 2387 1513 +3 2022 2025 1615 +3 2022 2083 1629 +3 2023 2264 1496 +3 2023 2286 1645 +3 2024 2300 1501 +3 2024 2373 1657 +3 2025 2244 1615 +3 2025 2256 1513 +3 2026 2052 1495 +3 2027 2333 1733 +3 2027 2411 1575 +3 2028 2046 180 +3 2028 2298 1689 +3 2029 2209 1510 +3 2029 2382 1914 +3 2030 2229 1789 +3 2030 2336 1805 +3 2030 2343 1471 +3 2031 2086 1667 +3 2032 2263 1768 +3 2032 2289 1639 +3 2033 2064 1580 +3 2034 2125 1709 +3 2034 2305 1552 +3 2035 2040 1502 +3 2036 2123 1787 +3 2037 2121 1617 +3 2037 2130 1721 +3 2038 2407 194 +3 2039 2405 1582 +3 2039 2416 211 +3 2040 2076 1502 +3 2041 2194 1724 +3 2042 2378 1500 +3 2042 2409 1589 +3 2043 2159 1594 +3 2043 2243 1669 +3 2044 2048 1599 +3 2044 2296 1468 +3 2045 2398 1690 +3 2047 2176 1749 +3 2047 2183 1497 +3 2047 2357 1671 +3 2048 2213 1545 +3 2049 2203 1720 +3 2049 2290 1519 +3 2050 2317 1785 +3 2050 2340 1593 +3 2051 2071 1603 +3 2052 2391 1570 +3 2053 2414 1601 +3 2054 2084 1608 +3 2054 2366 1672 +3 2055 2412 1715 +3 2056 2116 1682 +3 2056 2338 1470 +3 2057 2275 1727 +3 2057 2316 1807 +3 2058 2392 1637 +3 2059 2300 1604 +3 2059 2397 160 +3 2060 2279 1586 +3 2060 2309 1476 +3 2061 2106 1777 +3 2061 2379 1833 +3 2062 2098 96 +3 2062 2381 1650 +3 2063 2409 1767 +3 2064 2295 1557 +3 2065 2332 1507 +3 2065 2388 1707 +3 2066 2173 1752 +3 2066 2214 1472 +3 2067 2311 1648 +3 2070 2388 1750 +3 2070 2394 1475 +3 2072 2341 1653 +3 2073 2113 1628 +3 2074 2080 1473 +3 2074 2094 1653 +3 2074 2341 1708 +3 2077 2174 1459 +3 2077 2342 1620 +3 2078 2328 1598 +3 2079 2167 1744 +3 2081 2262 1779 +3 2082 2183 1648 +3 2082 2311 1534 +3 2084 2192 1499 +3 2084 2401 1608 +3 2085 2162 1510 +3 2085 2209 1652 +3 2085 2227 1666 +3 2086 2296 1667 +3 2087 2111 1623 +3 2087 2374 167 +3 2089 2406 215 +3 2090 2167 1584 +3 2091 2093 1503 +3 2091 2299 1799 +3 2092 2278 186 +3 2093 2103 1503 +3 2093 2304 1658 +3 2094 2321 1653 +3 2095 2205 115 +3 2095 2269 1710 +3 2096 2134 1612 +3 2097 2127 1812 +3 2100 2231 1810 +3 2101 2287 1723 +3 2104 2353 196 +3 2105 2133 1611 +3 2105 2331 1807 +3 2107 2370 1717 +3 2107 2404 184 +3 2108 2390 1741 +3 2110 2192 1672 +3 2110 2306 1528 +3 2111 2127 1514 +3 2111 2355 1623 +3 2113 2293 1524 +3 2113 2362 1628 +3 2114 2195 1650 +3 2114 2381 1553 +3 2115 2408 1726 +3 2116 2294 1902 +3 2117 2398 1546 +3 2118 2290 1631 +3 2119 2226 1460 +3 2119 2235 1731 +3 2120 2367 1699 +3 2120 2396 1532 +3 2122 2180 1677 +3 2122 2258 1739 +3 2124 2129 1679 +3 2124 2297 1676 +3 2124 2380 1531 +3 2125 2257 1709 +3 2126 2304 1877 +3 2128 2266 1463 +3 2129 2379 1540 +3 2130 2418 1721 +3 2131 2265 112 +3 2132 2297 1760 +3 2134 2277 1612 +3 2135 2377 105 +3 2137 2242 1738 +3 2137 2351 1504 +3 2138 2258 1677 +3 2138 2358 1543 +3 2139 2168 1714 +3 2139 2267 1520 +3 2139 2364 1582 +3 2140 2207 1780 +3 2140 2362 1524 +3 2141 2262 1725 +3 2141 2339 213 +3 2142 2346 1558 +3 2143 2243 1594 +3 2144 2385 1995 +3 2145 2165 1482 +3 2146 2174 1633 +3 2147 2323 1566 +3 2151 2199 1637 +3 2152 2164 1644 +3 2155 2370 1718 +3 2156 2267 1713 +3 2156 2394 1614 +3 2158 2307 1465 +3 2160 2292 1618 +3 2166 2271 1846 +3 2170 2254 1561 +3 2171 2318 1660 +3 2172 2196 1903 +3 2174 2282 1459 +3 2175 2326 1879 +3 2176 2394 1749 +3 2178 2259 1693 +3 2180 2358 1677 +3 2185 2318 1774 +3 2186 2360 242 +3 2187 2281 1506 +3 2188 2289 1716 +3 2188 2342 1459 +3 2190 2401 1773 +3 2190 2403 1533 +3 2195 2329 1650 +3 2197 2221 1743 +3 2197 2224 1760 +3 2197 2297 1531 +3 2198 2345 1494 +3 2199 2212 1516 +3 2200 2346 1786 +3 2205 2230 1798 +3 2207 2293 1989 +3 2208 2408 1613 +3 2210 2221 1625 +3 2211 2396 1776 +3 2213 2349 1545 +3 2213 2382 1788 +3 2214 2260 1711 +3 2214 2324 1538 +3 2216 2259 192 +3 2216 2407 1783 +3 2217 2355 1826 +3 2217 2417 1585 +3 2219 2337 1662 +3 2219 2376 121 +3 2221 2380 1869 +3 2225 2421 1734 +3 2226 2248 1460 +3 2228 2300 1697 +3 2229 2403 1789 +3 2231 2286 1830 +3 2232 2238 1641 +3 2232 2263 1770 +3 2234 2332 1707 +3 2235 2313 1731 +3 2238 2273 1528 +3 2240 2357 1838 +3 2242 2243 1738 +3 2242 2302 1669 +3 2248 2367 1460 +3 2248 2418 1699 +3 2249 2254 1703 +3 2250 2415 1834 +3 2252 2354 1664 +3 2253 2260 1670 +3 2254 2412 1703 +3 2255 2294 1655 +3 2258 2320 1739 +3 2261 2289 1526 +3 2263 2413 1768 +3 2272 2322 1647 +3 2281 2288 1763 +3 2283 2285 1683 +3 2283 2348 206 +3 2285 2347 1549 +3 2306 2366 1765 +3 2307 2331 1611 +3 2310 2396 1699 +3 2310 2418 1536 +3 2317 2334 1785 +3 2319 2415 1698 +3 2326 2373 1938 +3 2334 2372 1785 +3 2338 2389 1470 +3 2339 2405 2039 +3 2340 2372 1675 +3 2346 2398 1786 +3 2357 2358 1838 +3 2361 2410 1891 +3 2364 2416 2039 +3 2365 2412 1461 +3 2408 2413 1726 +3 2409 2421 1767 +3 2423 2695 2622 +3 2423 2711 2549 +3 2423 2736 2711 +3 2424 2725 2578 +3 2424 2776 2704 +3 2425 2616 2540 +3 2425 2679 2529 +3 2425 2745 2679 +3 2426 2585 2583 +3 2426 2635 2526 +3 2426 2684 2635 +3 2426 2773 2684 +3 2427 2775 2548 +3 2428 2678 2605 +3 2428 2682 2568 +3 2428 2719 2661 +3 2429 2645 2614 +3 2429 2772 2645 +3 2429 2800 2569 +3 2430 2690 2618 +3 2430 2770 2619 +3 2430 2777 2590 +3 2431 2636 2565 +3 2431 2647 2636 +3 2431 2771 2594 +3 2432 2785 2559 +3 2432 2786 2584 +3 2432 2787 2786 +3 2433 2624 2465 +3 2433 2666 2525 +3 2434 2696 2574 +3 2434 2718 2559 +3 2434 2750 2547 +3 2435 2592 2544 +3 2435 2628 2559 +3 2435 2785 2584 +3 2436 2609 2530 +3 2436 2717 2570 +3 2437 2612 2466 +3 2437 2651 2549 +3 2437 2730 2554 +3 2438 2625 2611 +3 2438 2652 2571 +3 2438 2762 2625 +3 2439 2593 2562 +3 2439 2613 2593 +3 2439 2627 2613 +3 2439 2761 2567 +3 2439 2768 2627 +3 2440 2671 2523 +3 2440 2729 2617 +3 2440 2757 2555 +3 2441 2582 2527 +3 2441 2659 2463 +3 2441 2681 2582 +3 2441 2709 2575 +3 2442 2641 2581 +3 2442 2649 2641 +3 2442 2697 2626 +3 2442 2799 2697 +3 2443 2693 2638 +3 2443 2752 2633 +3 2444 2698 2535 +3 2444 2714 2698 +3 2444 2767 2714 +3 2445 2743 2540 +3 2445 2746 2708 +3 2446 2648 2521 +3 2446 2728 2548 +3 2446 2795 2728 +3 2447 2608 2542 +3 2447 2643 2608 +3 2447 2759 2553 +3 2447 2789 2643 +3 2448 2748 2674 +3 2448 2751 2656 +3 2449 2699 2560 +3 2449 2733 2699 +3 2449 2754 2691 +3 2450 2601 2561 +3 2450 2710 2556 +3 2450 2765 2544 +3 2451 2705 2686 +3 2451 2747 2555 +3 2451 2758 2747 +3 2452 2623 2598 +3 2452 2706 2640 +3 2452 2794 2623 +3 2453 2701 2532 +3 2453 2780 2668 +3 2453 2796 2701 +3 2454 2646 2582 +3 2454 2650 2537 +3 2454 2680 2567 +3 2455 2564 2536 +3 2455 2660 2564 +3 2455 2790 2660 +3 2456 2615 2557 +3 2456 2658 2541 +3 2456 2685 2520 +3 2456 2783 2615 +3 2457 2630 2542 +3 2457 2763 2610 +3 2458 2669 2550 +3 2458 2738 2484 +3 2459 2671 2597 +3 2459 2726 2569 +3 2460 2594 2531 +3 2460 2749 2581 +3 2460 2784 2576 +3 2461 2587 2529 +3 2461 2712 2611 +3 2461 2782 2609 +3 2461 2801 2587 +3 2462 2575 2554 +3 2462 2659 2575 +3 2462 2715 2528 +3 2462 2730 2572 +3 2463 2681 2441 +3 2463 2792 2579 +3 2464 2583 2571 +3 2464 2657 2583 +3 2464 2675 2657 +3 2464 2723 2621 +3 2465 2624 2553 +3 2465 2666 2433 +3 2465 2727 2516 +3 2466 2612 2550 +3 2466 2689 2572 +3 2466 2730 2437 +3 2467 2601 2544 +3 2467 2624 2601 +3 2467 2789 2624 +3 2468 2625 2545 +3 2468 2629 2530 +3 2468 2719 2605 +3 2469 2634 2600 +3 2469 2685 2541 +3 2469 2778 2534 +3 2469 2787 2520 +3 2470 2770 2623 +3 2470 2781 2562 +3 2471 2595 2536 +3 2471 2599 2524 +3 2471 2656 2578 +3 2471 2725 2595 +3 2472 2603 2548 +3 2472 2628 2603 +3 2472 2728 2547 +3 2472 2750 2559 +3 2473 2648 2620 +3 2473 2703 2591 +3 2473 2802 2703 +3 2474 2762 2571 +3 2475 2622 2529 +3 2475 2679 2556 +3 2475 2736 2622 +3 2476 2570 2569 +3 2476 2580 2570 +3 2476 2774 2580 +3 2476 2800 2565 +3 2477 2637 2573 +3 2477 2788 2696 +3 2477 2795 2637 +3 2478 2627 2588 +3 2478 2642 2539 +3 2478 2668 2613 +3 2479 2663 2596 +3 2479 2681 2663 +3 2479 2791 2589 +3 2480 2646 2567 +3 2480 2684 2527 +3 2480 2761 2562 +3 2481 2675 2554 +3 2481 2773 2657 +3 2482 2673 2577 +3 2482 2674 2566 +3 2482 2729 2674 +3 2483 2670 2603 +3 2483 2765 2664 +3 2484 2516 2458 +3 2484 2666 2516 +3 2484 2711 2525 +3 2484 2738 2711 +3 2485 2568 2523 +3 2485 2671 2639 +3 2485 2678 2568 +3 2486 2680 2607 +3 2486 2731 2588 +3 2486 2768 2680 +3 2487 2638 2543 +3 2487 2707 2563 +3 2487 2721 2662 +3 2488 2677 2535 +3 2488 2720 2564 +3 2489 2692 2535 +3 2489 2713 2655 +3 2490 2609 2580 +3 2490 2616 2587 +3 2490 2688 2616 +3 2490 2801 2609 +3 2491 2653 2552 +3 2491 2701 2586 +3 2491 2714 2701 +3 2492 2663 2579 +3 2492 2737 2654 +3 2492 2753 2596 +3 2493 2592 2584 +3 2493 2643 2592 +3 2493 2734 2608 +3 2494 2617 2577 +3 2494 2676 2551 +3 2494 2705 2555 +3 2494 2757 2617 +3 2495 2594 2581 +3 2495 2647 2594 +3 2495 2746 2647 +3 2496 2706 2661 +3 2496 2719 2545 +3 2496 2755 2640 +3 2497 2638 2563 +3 2497 2700 2560 +3 2497 2722 2638 +3 2498 2756 2610 +3 2498 2763 2533 +3 2498 2778 2600 +3 2498 2803 2756 +3 2499 2652 2611 +3 2499 2695 2652 +3 2499 2712 2622 +3 2500 2708 2641 +3 2500 2741 2683 +3 2500 2743 2708 +3 2501 2688 2580 +3 2501 2746 2688 +3 2501 2774 2636 +3 2502 2597 2555 +3 2502 2726 2597 +3 2502 2747 2645 +3 2502 2772 2726 +3 2503 2619 2593 +3 2503 2777 2619 +3 2503 2780 2777 +3 2504 2752 2538 +3 2504 2758 2633 +3 2505 2770 2667 +3 2505 2776 2598 +3 2506 2660 2618 +3 2506 2677 2660 +3 2506 2767 2677 +3 2507 2629 2605 +3 2507 2678 2639 +3 2507 2717 2629 +3 2508 2749 2672 +3 2508 2799 2749 +3 2509 2744 2691 +3 2509 2754 2632 +3 2509 2784 2744 +3 2510 2686 2631 +3 2510 2693 2633 +3 2511 2651 2621 +3 2511 2695 2651 +3 2511 2723 2652 +3 2512 2724 2615 +3 2512 2788 2604 +3 2513 2716 2568 +3 2513 2735 2578 +3 2513 2751 2716 +3 2514 2682 2661 +3 2514 2706 2598 +3 2514 2735 2682 +3 2514 2776 2735 +3 2515 2727 2553 +3 2515 2779 2727 +3 2516 2602 2458 +3 2516 2666 2465 +3 2516 2727 2558 +3 2517 2626 2620 +3 2517 2649 2626 +3 2517 2741 2649 +3 2517 2775 2741 +3 2518 2670 2664 +3 2518 2683 2670 +3 2518 2745 2540 +3 2519 2733 2691 +3 2519 2771 2565 +3 2519 2798 2614 +3 2520 2574 2456 +3 2520 2685 2469 +3 2520 2718 2574 +3 2520 2787 2718 +3 2521 2637 2446 +3 2521 2648 2591 +3 2521 2766 2573 +3 2522 2667 2618 +3 2522 2704 2667 +3 2522 2725 2704 +3 2522 2790 2595 +3 2523 2671 2485 +3 2523 2716 2674 +3 2523 2729 2440 +3 2524 2656 2471 +3 2524 2739 2566 +3 2524 2748 2656 +3 2525 2561 2433 +3 2525 2666 2484 +3 2525 2736 2561 +3 2526 2585 2426 +3 2526 2781 2623 +3 2526 2794 2585 +3 2527 2646 2480 +3 2527 2709 2441 +3 2527 2773 2709 +3 2528 2659 2462 +3 2528 2715 264 +3 2528 2792 2659 +3 2529 2587 2425 +3 2529 2679 2475 +3 2529 2712 2461 +3 2530 2625 2468 +3 2530 2629 2436 +3 2530 2782 2625 +3 2531 2744 2460 +3 2531 2771 2691 +3 2532 2590 2453 +3 2532 2690 2590 +3 2532 2767 2690 +3 2533 2734 2584 +3 2533 2763 2734 +3 2533 2778 2498 +3 2533 2786 2534 +3 2534 2778 2533 +3 2534 2787 2469 +3 2535 2644 2488 +3 2535 2677 2444 +3 2535 2692 283 +3 2535 2698 2489 +3 2536 2595 2455 +3 2536 2599 2471 +3 2536 2732 2599 +3 2537 2650 2589 +3 2537 2680 2454 +3 2537 2797 2607 +3 2538 2614 2504 +3 2538 2722 2699 +3 2538 2733 2614 +3 2538 2752 2722 +3 2539 2668 2478 +3 2539 2796 2668 +3 2540 2616 2445 +3 2540 2683 2518 +3 2540 2743 2683 +3 2540 2745 2425 +3 2541 2634 2469 +3 2541 2658 248 +3 2541 2685 2456 +3 2542 2606 2447 +3 2542 2608 2457 +3 2542 2630 255 +3 2543 2665 270 +3 2543 2693 2665 +3 2543 2721 2487 +3 2544 2592 2467 +3 2544 2601 2450 +3 2544 2628 2435 +3 2544 2765 2628 +3 2545 2719 2468 +3 2545 2755 2496 +3 2545 2762 2755 +3 2546 2687 238 +3 2546 2697 2687 +3 2546 2802 2697 +3 2547 2696 2434 +3 2547 2750 2472 +3 2547 2795 2696 +3 2548 2603 2427 +3 2548 2620 2446 +3 2548 2728 2472 +3 2548 2775 2620 +3 2549 2612 2437 +3 2549 2651 2423 +3 2549 2738 2612 +3 2550 2612 2458 +3 2550 2689 2466 +3 2550 2764 2689 +3 2551 2676 273 +3 2551 2705 2494 +3 2552 2653 40 +3 2552 2713 2698 +3 2552 2714 2491 +3 2553 2727 2465 +3 2553 2759 2515 +3 2553 2789 2447 +3 2554 2575 2481 +3 2554 2621 2437 +3 2554 2675 2621 +3 2554 2730 2462 +3 2555 2597 2440 +3 2555 2705 2451 +3 2555 2747 2502 +3 2555 2757 2494 +3 2556 2664 2450 +3 2556 2710 2475 +3 2556 2745 2664 +3 2557 2658 2456 +3 2557 2804 247 +3 2558 2602 2516 +3 2558 2740 2602 +3 2558 2779 2740 +3 2559 2628 2472 +3 2559 2718 2432 +3 2559 2750 2434 +3 2559 2785 2435 +3 2560 2699 2497 +3 2560 2700 244 +3 2560 2754 2449 +3 2561 2601 2433 +3 2561 2710 2450 +3 2561 2736 2710 +3 2562 2593 2470 +3 2562 2635 2480 +3 2562 2761 2439 +3 2562 2781 2635 +3 2563 2638 2487 +3 2563 2700 2497 +3 2563 2707 13 +3 2564 2660 2488 +3 2564 2702 2536 +3 2564 2720 281 +3 2565 2636 2476 +3 2565 2771 2431 +3 2565 2798 2519 +3 2565 2800 2798 +3 2566 2673 2482 +3 2566 2739 277 +3 2566 2748 2524 +3 2567 2646 2454 +3 2567 2761 2480 +3 2567 2768 2439 +3 2568 2678 2428 +3 2568 2682 2513 +3 2568 2716 2523 +3 2569 2570 2459 +3 2569 2772 2429 +3 2569 2800 2476 +3 2570 2580 2436 +3 2570 2639 2459 +3 2570 2717 2639 +3 2571 2583 2474 +3 2571 2723 2464 +3 2571 2762 2438 +3 2572 2689 263 +3 2572 2715 2462 +3 2572 2730 2466 +3 2573 2604 2477 +3 2573 2637 2521 +3 2573 2766 235 +3 2574 2718 2434 +3 2574 2783 2456 +3 2574 2788 2783 +3 2575 2659 2441 +3 2575 2709 2481 +3 2576 2694 241 +3 2576 2749 2460 +3 2576 2784 2694 +3 2577 2617 2482 +3 2577 2673 275 +3 2577 2676 2494 +3 2578 2725 2471 +3 2578 2735 2424 +3 2578 2751 2513 +3 2579 2663 2463 +3 2579 2737 2492 +3 2579 2792 2528 +3 2580 2609 2436 +3 2580 2688 2490 +3 2580 2774 2501 +3 2581 2594 2460 +3 2581 2641 2495 +3 2581 2799 2442 +3 2582 2646 2527 +3 2582 2650 2454 +3 2582 2681 2650 +3 2583 2585 2474 +3 2583 2657 2426 +3 2584 2592 2435 +3 2584 2734 2493 +3 2584 2785 2432 +3 2584 2786 2533 +3 2585 2640 2474 +3 2585 2794 2640 +3 2586 2653 2491 +3 2586 2742 42 +3 2586 2796 2742 +3 2587 2616 2425 +3 2587 2801 2490 +3 2588 2627 2486 +3 2588 2642 2478 +3 2588 2731 45 +3 2588 2793 2642 +3 2589 2650 2479 +3 2589 2791 49 +3 2589 2797 2537 +3 2590 2690 2430 +3 2590 2780 2453 +3 2591 2648 2473 +3 2591 2703 237 +3 2591 2766 2521 +3 2592 2643 2467 +3 2593 2613 2503 +3 2593 2619 2470 +3 2594 2647 2431 +3 2594 2771 2531 +3 2595 2725 2522 +3 2595 2790 2455 +3 2596 2663 2492 +3 2596 2753 50 +3 2596 2791 2479 +3 2597 2671 2440 +3 2597 2726 2459 +3 2598 2623 2505 +3 2598 2706 2452 +3 2598 2776 2514 +3 2599 2732 279 +3 2599 2739 2524 +3 2600 2634 250 +3 2600 2778 2469 +3 2600 2803 2498 +3 2601 2624 2433 +3 2602 2669 2458 +3 2602 2740 260 +3 2603 2628 2483 +3 2603 2670 2427 +3 2604 2724 2512 +3 2604 2788 2477 +3 2605 2629 2468 +3 2605 2678 2507 +3 2605 2719 2428 +3 2606 2759 2447 +3 2606 2760 2759 +3 2607 2680 2537 +3 2607 2731 2486 +3 2607 2797 47 +3 2608 2643 2493 +3 2608 2734 2457 +3 2609 2782 2530 +3 2609 2801 2461 +3 2610 2630 2457 +3 2610 2756 253 +3 2610 2763 2498 +3 2611 2652 2438 +3 2611 2712 2499 +3 2611 2782 2461 +3 2612 2738 2458 +3 2613 2627 2478 +3 2613 2780 2503 +3 2614 2645 2504 +3 2614 2733 2519 +3 2614 2798 2429 +3 2615 2724 232 +3 2615 2783 2512 +3 2615 2804 2557 +3 2616 2688 2445 +3 2617 2729 2482 +3 2617 2757 2440 +3 2618 2667 2430 +3 2618 2690 2506 +3 2618 2790 2522 +3 2619 2770 2470 +3 2619 2777 2430 +3 2620 2626 2473 +3 2620 2648 2446 +3 2620 2775 2517 +3 2621 2651 2437 +3 2621 2675 2464 +3 2621 2723 2511 +3 2622 2695 2499 +3 2622 2712 2529 +3 2622 2736 2423 +3 2623 2770 2505 +3 2623 2781 2470 +3 2623 2794 2526 +3 2624 2789 2553 +3 2625 2762 2545 +3 2625 2782 2611 +3 2626 2649 2442 +3 2626 2802 2473 +3 2627 2768 2486 +3 2628 2765 2483 +3 2629 2717 2436 +3 2631 2665 2510 +3 2631 2686 2551 +3 2632 2694 2509 +3 2632 2754 2560 +3 2633 2686 2510 +3 2633 2693 2443 +3 2633 2752 2504 +3 2633 2758 2686 +3 2635 2684 2480 +3 2635 2781 2526 +3 2636 2647 2501 +3 2636 2774 2476 +3 2637 2795 2446 +3 2638 2693 2543 +3 2638 2722 2443 +3 2639 2671 2459 +3 2639 2678 2485 +3 2639 2717 2507 +3 2640 2706 2496 +3 2640 2755 2474 +3 2640 2794 2452 +3 2641 2649 2500 +3 2641 2708 2495 +3 2642 2742 2539 +3 2642 2793 44 +3 2643 2789 2467 +3 2644 2720 2488 +3 2645 2747 2504 +3 2645 2772 2502 +3 2647 2746 2501 +3 2649 2741 2500 +3 2650 2681 2479 +3 2651 2695 2423 +3 2652 2695 2511 +3 2652 2723 2571 +3 2654 2737 267 +3 2654 2753 2492 +3 2655 2692 2489 +3 2655 2713 38 +3 2656 2748 2448 +3 2656 2751 2578 +3 2657 2675 2481 +3 2657 2773 2426 +3 2659 2792 2463 +3 2660 2677 2488 +3 2660 2790 2618 +3 2661 2682 2428 +3 2661 2706 2514 +3 2661 2719 2496 +3 2662 2707 2487 +3 2662 2721 268 +3 2662 2769 246 +3 2663 2681 2463 +3 2664 2670 2483 +3 2664 2745 2518 +3 2664 2765 2450 +3 2665 2693 2510 +3 2667 2704 2505 +3 2667 2770 2430 +3 2668 2780 2613 +3 2668 2796 2453 +3 2669 2764 2550 +3 2670 2683 2427 +3 2672 2687 2508 +3 2672 2749 2576 +3 2674 2716 2448 +3 2674 2729 2523 +3 2674 2748 2566 +3 2677 2767 2444 +3 2679 2745 2556 +3 2680 2768 2567 +3 2682 2735 2513 +3 2683 2741 2427 +3 2683 2743 2500 +3 2684 2773 2527 +3 2686 2705 2551 +3 2686 2758 2451 +3 2687 2697 2508 +3 2688 2746 2445 +3 2689 2764 262 +3 2690 2767 2506 +3 2691 2733 2449 +3 2691 2744 2531 +3 2691 2754 2509 +3 2691 2771 2519 +3 2694 2784 2509 +3 2696 2788 2574 +3 2696 2795 2477 +3 2697 2799 2508 +3 2697 2802 2626 +3 2698 2713 2489 +3 2698 2714 2552 +3 2699 2722 2497 +3 2699 2733 2538 +3 2701 2714 2532 +3 2701 2796 2586 +3 2702 2732 2536 +3 2703 2802 2546 +3 2704 2725 2424 +3 2704 2776 2505 +3 2708 2743 2445 +3 2708 2746 2495 +3 2709 2773 2481 +3 2710 2736 2475 +3 2711 2736 2525 +3 2711 2738 2549 +3 2714 2767 2532 +3 2716 2751 2448 +3 2718 2787 2432 +3 2722 2752 2443 +3 2726 2772 2569 +3 2727 2779 2558 +3 2728 2795 2547 +3 2734 2763 2457 +3 2735 2776 2424 +3 2740 2779 259 +3 2741 2775 2427 +3 2742 2796 2539 +3 2744 2784 2460 +3 2747 2758 2504 +3 2749 2799 2581 +3 2755 2762 2474 +3 2756 2803 252 +3 2759 2760 2515 +3 2760 2779 2515 +3 2777 2780 2590 +3 2783 2788 2512 +3 2786 2787 2534 +3 2798 2800 2429 +3 2805 3035 2830 +3 2805 3077 3035 +3 2805 3127 2837 +3 2805 3134 2976 +3 2806 3049 2973 +3 2806 3087 2924 +3 2806 3163 3049 +3 2807 3005 2918 +3 2807 3100 2811 +3 2807 3116 3100 +3 2808 3147 3045 +3 2808 3169 2997 +3 2808 3197 3051 +3 2809 3092 3018 +3 2809 3136 2992 +3 2809 3196 3092 +3 2809 3208 3075 +3 2810 3096 3019 +3 2810 3148 2940 +3 2810 3167 3148 +3 2810 3172 3096 +3 2811 3005 2807 +3 2811 3132 2972 +3 2811 3162 3005 +3 2812 3070 2975 +3 2812 3082 2967 +3 2813 2941 2822 +3 2813 3024 2941 +3 2813 3089 2999 +3 2813 3139 3089 +3 2814 3032 2953 +3 2814 3083 3032 +3 2814 3186 2993 +3 2815 3093 2970 +3 2815 3105 3093 +3 2815 3166 3105 +3 2816 3194 2979 +3 2816 3198 2968 +3 2817 2986 2917 +3 2817 3117 2986 +3 2817 3140 3117 +3 2818 2982 2915 +3 2818 2994 2931 +3 2818 3203 2982 +3 2818 3209 3038 +3 2819 3010 2946 +3 2819 3042 3030 +3 2819 3066 3010 +3 2820 3036 2964 +3 2820 3112 2984 +3 2820 3202 3007 +3 2821 3022 2965 +3 2821 3025 2950 +3 2821 3074 2956 +3 2821 3095 3025 +3 2822 2941 2871 +3 2822 3139 2813 +3 2823 3062 2919 +3 2823 3071 2977 +3 2823 3146 3012 +3 2823 3159 3062 +3 2824 3115 2971 +3 2824 3128 2929 +3 2824 3204 3091 +3 2825 3081 2934 +3 2825 3191 2939 +3 2826 3044 2983 +3 2826 3114 2987 +3 2826 3125 3028 +3 2827 3027 2978 +3 2827 3040 2963 +3 2827 3090 3040 +3 2827 3113 2958 +3 2828 3079 2943 +3 2828 3149 3026 +3 2829 3143 3118 +3 2829 3144 2944 +3 2830 3127 2805 +3 2830 3143 3127 +3 2831 3160 3056 +3 2831 3181 3013 +3 2831 3210 3181 +3 2832 2945 2932 +3 2832 3046 2945 +3 2832 3058 2934 +3 2833 3024 2999 +3 2833 3137 3024 +3 2833 3175 3082 +3 2834 3059 2924 +3 2834 3072 3059 +3 2834 3153 3072 +3 2835 3047 2887 +3 2835 3094 2948 +3 2835 3165 2939 +3 2836 3120 2976 +3 2836 3171 3120 +3 2836 3195 3110 +3 2837 3127 2944 +3 2837 3134 2805 +3 2838 2980 2906 +3 2838 3078 2917 +3 2838 3156 3078 +3 2839 3001 2916 +3 2839 3145 3065 +3 2839 3168 2921 +3 2840 3097 2924 +3 2840 3154 2925 +3 2840 3157 3097 +3 2841 3002 2935 +3 2841 3060 2923 +3 2841 3107 3006 +3 2841 3158 3002 +3 2842 3176 2953 +3 2843 3069 2942 +3 2843 3098 2950 +3 2843 3199 3013 +3 2844 3120 2912 +3 2844 3126 2908 +3 2844 3187 2951 +3 2845 3032 2946 +3 2845 3104 2936 +3 2845 3123 2953 +3 2846 3030 2971 +3 2846 3066 3030 +3 2846 3115 2959 +3 2846 3151 3066 +3 2847 2990 2975 +3 2847 3095 2956 +3 2847 3155 3095 +3 2847 3177 3155 +3 2848 3034 2970 +3 2848 3164 2982 +3 2848 3173 2940 +3 2849 2980 2917 +3 2849 3124 2980 +3 2849 3205 2972 +3 2850 3023 2918 +3 2850 3090 2958 +3 2850 3182 2965 +3 2850 3188 3023 +3 2851 3070 2967 +3 2851 3184 2962 +3 2851 3201 3070 +3 2852 2996 2905 +3 2852 3003 2955 +3 2852 3112 3003 +3 2853 3004 2981 +3 2853 3138 3004 +3 2853 3204 3036 +3 2854 2977 2933 +3 2854 2988 2920 +3 2854 2998 2957 +3 2854 3146 2977 +3 2855 3040 2918 +3 2855 3044 2963 +3 2855 3178 2983 +3 2856 3034 2911 +3 2856 3060 3006 +3 2856 3131 2970 +3 2857 3089 3047 +3 2857 3103 2968 +3 2857 3191 3103 +3 2858 3121 3094 +3 2858 3200 2954 +3 2859 2964 2929 +3 2859 3009 2943 +3 2859 3052 2964 +3 2859 3196 2992 +3 2860 3079 2904 +3 2860 3088 2910 +3 2860 3202 2943 +3 2861 3000 2961 +3 2861 3001 2921 +3 2861 3149 3001 +3 2862 2966 2939 +3 2862 3063 2949 +3 2862 3141 3063 +3 2862 3165 2948 +3 2863 2990 2956 +3 2863 3015 2990 +3 2863 3051 3015 +3 2863 3147 3051 +3 2864 2985 2969 +3 2864 3054 2937 +3 2864 3065 2985 +3 2865 2922 2919 +3 2865 3124 2972 +3 2865 3132 2922 +3 2866 3027 2963 +3 2866 3028 3019 +3 2866 3044 3028 +3 2866 3096 3027 +3 2867 3048 2933 +3 2867 3056 2928 +3 2867 3071 3056 +3 2867 3130 3048 +3 2868 3053 2974 +3 2868 3133 2930 +3 2868 3161 3014 +3 2869 3075 2931 +3 2869 3087 2973 +3 2870 2991 2927 +3 2870 3107 2935 +3 2870 3110 2991 +3 2871 2951 2822 +3 2871 3126 2951 +3 2872 3084 2941 +3 2872 3137 2997 +3 2872 3169 2913 +3 2873 3029 2946 +3 2873 3038 3029 +3 2873 3083 2911 +3 2873 3203 3038 +3 2874 2966 2949 +3 2874 3081 2966 +3 2874 3174 2945 +3 2875 3042 3018 +3 2875 3092 2929 +3 2875 3128 2971 +3 2876 3025 3017 +3 2876 3067 2942 +3 2876 3069 2950 +3 2877 3009 2992 +3 2877 3050 3009 +3 2877 3136 2973 +3 2878 3086 2986 +3 2878 3117 2925 +3 2878 3180 3086 +3 2879 3012 2920 +3 2879 3057 3033 +3 2879 3080 2906 +3 2879 3159 3012 +3 2880 3021 2974 +3 2880 3053 2953 +3 2880 3123 3021 +3 2881 3020 3016 +3 2881 3104 3010 +3 2881 3151 3020 +3 2882 2989 2969 +3 2882 3156 3039 +3 2882 3183 2989 +3 2883 3113 2978 +3 2883 3119 3045 +3 2883 3144 3118 +3 2884 3031 2944 +3 2884 3064 2940 +3 2884 3105 3031 +3 2885 3058 2960 +3 2885 3068 2962 +3 2885 3184 2979 +3 2886 3042 3029 +3 2886 3208 3018 +3 2886 3209 3208 +3 2887 3094 2835 +3 2887 3200 3094 +3 2888 3125 3059 +3 2888 3167 3019 +3 2889 3111 2930 +3 2889 3129 3002 +3 2889 3158 3111 +3 2890 3022 2950 +3 2890 3116 3023 +3 2890 3188 3022 +3 2891 3091 2981 +3 2891 3115 3091 +3 2891 3150 3037 +3 2892 3134 3031 +3 2892 3166 2991 +3 2892 3195 2976 +3 2893 3109 2952 +3 2893 3177 2975 +3 2893 3201 2995 +3 2894 3074 2965 +3 2894 3147 3074 +3 2894 3182 2958 +3 2895 3144 2978 +3 2895 3172 2944 +3 2896 3140 2985 +3 2896 3145 2916 +3 2896 3157 2925 +3 2897 3050 3049 +3 2897 3149 3050 +3 2897 3163 3001 +3 2898 3082 3015 +3 2898 3137 3082 +3 2898 3197 2997 +3 2899 2954 2951 +3 2899 3055 2954 +3 2899 3102 257 +3 2899 3187 3102 +3 2900 3160 3013 +3 2900 3199 3041 +3 2901 3178 3162 +3 2901 3180 2983 +3 2901 3205 3086 +3 2902 3085 3017 +3 2902 3155 3085 +3 2903 3164 3148 +3 2903 3167 3072 +3 2904 3008 2860 +3 2904 3026 2961 +3 2904 3079 3026 +3 2904 3142 3008 +3 2905 2984 2852 +3 2905 3138 2984 +3 2905 3179 3004 +3 2906 3080 2838 +3 2906 3124 3062 +3 2906 3159 2879 +3 2907 3098 3013 +3 2907 3116 3098 +3 2907 3181 3100 +3 2908 3077 2976 +3 2908 3120 2844 +3 2908 3126 3077 +3 2909 3175 2968 +3 2909 3198 2967 +3 2910 3007 2860 +3 2910 3088 283 +3 2910 3112 3007 +3 2911 2993 2856 +3 2911 3034 2982 +3 2911 3083 2993 +3 2911 3203 2873 +3 2912 3011 2844 +3 2912 3171 3108 +3 2912 3193 3011 +3 2913 3084 2872 +3 2913 3119 3118 +3 2913 3143 3084 +3 2913 3169 3119 +3 2914 3122 3059 +3 2914 3125 2987 +3 2914 3154 3122 +3 2915 2994 2818 +3 2915 3152 2994 +3 2915 3153 3152 +3 2915 3164 3153 +3 2916 3145 2839 +3 2916 3157 2896 +3 2916 3163 3097 +3 2917 2969 2817 +3 2917 2980 2838 +3 2917 2986 2849 +3 2917 3078 2969 +3 2918 3005 2855 +3 2918 3023 2807 +3 2918 3090 2850 +3 2919 3062 2865 +3 2919 3071 2823 +3 2919 3210 3056 +3 2920 2988 270 +3 2920 3057 2879 +3 2920 3146 2854 +3 2921 3000 2861 +3 2921 3001 2839 +3 2921 3170 278 +3 2922 3132 3100 +3 2922 3210 2919 +3 2923 3158 2841 +3 2923 3176 3111 +3 2923 3186 3176 +3 2924 3076 2834 +3 2924 3087 3076 +3 2924 3097 2806 +3 2924 3122 2840 +3 2925 2987 2878 +3 2925 3140 2896 +3 2925 3154 2987 +3 2925 3157 2840 +3 2926 3106 2948 +3 2926 3121 255 +3 2927 3107 2870 +3 2927 3131 3006 +3 2927 3166 3131 +3 2928 3101 73 +3 2928 3130 2867 +3 2928 3160 3101 +3 2929 2964 2824 +3 2929 3128 2875 +3 2929 3196 2859 +3 2930 3053 2868 +3 2930 3111 3053 +3 2930 3129 2889 +3 2930 3133 266 +3 2931 2994 2869 +3 2931 3209 2818 +3 2932 2960 2832 +3 2932 3135 247 +3 2932 3207 2960 +3 2933 2977 2867 +3 2933 2998 2854 +3 2933 3048 71 +3 2934 3046 2832 +3 2934 3081 3046 +3 2934 3103 2825 +3 2934 3194 3103 +3 2935 3002 263 +3 2935 3043 2870 +3 2935 3099 3043 +3 2935 3107 2841 +3 2936 3016 290 +3 2936 3104 3016 +3 2936 3123 2845 +3 2937 3054 276 +3 2937 3065 2864 +3 2937 3168 3065 +3 2937 3170 3168 +3 2938 3033 272 +3 2938 3080 3033 +3 2938 3156 3080 +3 2939 2966 2825 +3 2939 3047 2835 +3 2939 3165 2862 +3 2939 3191 3047 +3 2940 3064 2810 +3 2940 3093 2884 +3 2940 3148 2848 +3 2940 3173 3093 +3 2941 3024 2872 +3 2941 3035 2871 +3 2941 3084 3035 +3 2942 3067 76 +3 2942 3069 2876 +3 2942 3199 2843 +3 2943 3009 2828 +3 2943 3052 2859 +3 2943 3079 2860 +3 2943 3202 3052 +3 2944 3031 2837 +3 2944 3064 2884 +3 2944 3127 2829 +3 2944 3144 2895 +3 2944 3172 3064 +3 2945 3046 2874 +3 2945 3135 2932 +3 2945 3174 248 +3 2946 3010 2845 +3 2946 3029 2819 +3 2946 3032 2873 +3 2947 3043 261 +3 2947 3110 3043 +3 2947 3171 3110 +3 2948 3094 2926 +3 2948 3141 2862 +3 2948 3165 2835 +3 2949 2966 2862 +3 2949 3063 251 +3 2949 3073 2874 +3 2950 3022 2821 +3 2950 3025 2876 +3 2950 3069 2843 +3 2950 3098 2890 +3 2951 2954 2822 +3 2951 3126 2844 +3 2951 3187 2899 +3 2952 3109 80 +3 2952 3177 2893 +3 2953 3032 2845 +3 2953 3053 2842 +3 2953 3123 2880 +3 2953 3176 2814 +3 2954 3055 2858 +3 2954 3139 2822 +3 2954 3200 3139 +3 2955 2996 2852 +3 2955 3190 2996 +3 2955 3192 3061 +3 2956 2990 2847 +3 2956 3074 2863 +3 2956 3095 2821 +3 2957 2988 2854 +3 2957 3189 268 +3 2958 3045 2894 +3 2958 3090 2827 +3 2958 3113 3045 +3 2958 3182 2850 +3 2959 3037 293 +3 2959 3115 3037 +3 2959 3151 2846 +3 2960 3058 2832 +3 2960 3068 2885 +3 2960 3207 84 +3 2961 3000 279 +3 2961 3026 2861 +3 2961 3142 2904 +3 2962 2995 2851 +3 2962 3068 83 +3 2962 3184 2885 +3 2963 3027 2827 +3 2963 3040 2855 +3 2963 3044 2866 +3 2964 3052 2820 +3 2964 3204 2824 +3 2965 3022 2850 +3 2965 3074 2821 +3 2965 3182 2894 +3 2966 3081 2825 +3 2967 2979 2851 +3 2967 3070 2812 +3 2967 3082 2909 +3 2967 3198 2979 +3 2968 2999 2857 +3 2968 3103 2816 +3 2968 3175 2999 +3 2968 3198 2909 +3 2969 2985 2817 +3 2969 2989 2864 +3 2969 3078 2882 +3 2970 3034 2856 +3 2970 3131 2815 +3 2970 3173 2848 +3 2971 3030 2875 +3 2971 3115 2846 +3 2971 3128 2824 +3 2972 3124 2849 +3 2972 3132 2865 +3 2972 3162 2811 +3 2972 3205 3162 +3 2973 3049 2877 +3 2973 3075 2869 +3 2973 3087 2806 +3 2973 3136 3075 +3 2974 3021 288 +3 2974 3053 2880 +3 2974 3161 2868 +3 2975 2990 2812 +3 2975 3177 2847 +3 2975 3201 2893 +3 2976 3077 2805 +3 2976 3120 2908 +3 2976 3134 2892 +3 2976 3195 2836 +3 2977 3071 2867 +3 2977 3146 2823 +3 2978 3027 2895 +3 2978 3113 2827 +3 2978 3144 2883 +3 2979 3058 2885 +3 2979 3184 2851 +3 2979 3194 3058 +3 2979 3198 2816 +3 2980 3124 2906 +3 2981 3004 295 +3 2981 3091 2853 +3 2981 3150 2891 +3 2982 3034 2848 +3 2982 3164 2915 +3 2982 3203 2911 +3 2983 3044 2855 +3 2983 3114 2826 +3 2983 3178 2901 +3 2983 3180 3114 +3 2984 3036 2820 +3 2984 3112 2852 +3 2984 3138 3036 +3 2985 3140 2817 +3 2985 3145 2896 +3 2986 3086 2849 +3 2986 3117 2878 +3 2987 3114 2878 +3 2987 3125 2826 +3 2987 3154 2914 +3 2989 3054 2864 +3 2989 3183 275 +3 2990 3015 2812 +3 2991 3166 2927 +3 2991 3195 2892 +3 2992 3009 2859 +3 2992 3136 2877 +3 2992 3196 2809 +3 2993 3060 2856 +3 2993 3083 2814 +3 2993 3186 3060 +3 2994 3076 2869 +3 2994 3152 3076 +3 2995 3109 2893 +3 2995 3201 2851 +3 2996 3179 2905 +3 2996 3190 298 +3 2997 3137 2898 +3 2997 3169 2872 +3 2997 3197 2808 +3 2998 3185 2957 +3 2999 3024 2813 +3 2999 3089 2857 +3 2999 3175 2833 +3 3001 3149 2897 +3 3001 3163 2916 +3 3002 3129 264 +3 3002 3158 2889 +3 3003 3112 2910 +3 3003 3192 2955 +3 3004 3138 2905 +3 3004 3179 296 +3 3005 3178 2855 +3 3006 3060 2841 +3 3006 3107 2927 +3 3006 3131 2856 +3 3007 3112 2820 +3 3007 3202 2860 +3 3008 3088 2860 +3 3008 3142 281 +3 3009 3050 2828 +3 3010 3066 2881 +3 3010 3104 2845 +3 3011 3187 2844 +3 3011 3193 259 +3 3012 3146 2920 +3 3012 3159 2823 +3 3013 3098 2843 +3 3013 3160 2831 +3 3013 3181 2907 +3 3013 3199 2900 +3 3014 3133 2868 +3 3014 3161 286 +3 3015 3051 2898 +3 3015 3082 2812 +3 3016 3020 291 +3 3016 3104 2881 +3 3017 3025 2902 +3 3017 3067 2876 +3 3017 3085 78 +3 3018 3042 2886 +3 3018 3092 2875 +3 3018 3208 2809 +3 3019 3028 2888 +3 3019 3096 2866 +3 3019 3167 2810 +3 3020 3151 2959 +3 3021 3123 2936 +3 3022 3188 2850 +3 3023 3116 2807 +3 3023 3188 2890 +3 3024 3137 2872 +3 3025 3095 2902 +3 3026 3079 2828 +3 3026 3149 2861 +3 3027 3096 2895 +3 3028 3044 2826 +3 3028 3125 2888 +3 3029 3038 2886 +3 3029 3042 2819 +3 3030 3042 2875 +3 3030 3066 2819 +3 3031 3105 2892 +3 3031 3134 2837 +3 3032 3083 2873 +3 3033 3057 271 +3 3033 3080 2879 +3 3035 3077 2871 +3 3035 3084 2830 +3 3036 3138 2853 +3 3036 3204 2964 +3 3037 3115 2891 +3 3037 3150 294 +3 3038 3203 2818 +3 3038 3209 2886 +3 3039 3156 2938 +3 3039 3183 2882 +3 3040 3090 2918 +3 3041 3101 2900 +3 3041 3199 2942 +3 3043 3099 262 +3 3043 3110 2870 +3 3045 3113 2883 +3 3045 3119 2808 +3 3045 3147 2894 +3 3046 3081 2874 +3 3047 3089 2887 +3 3047 3191 2857 +3 3048 3130 72 +3 3049 3050 2877 +3 3049 3163 2897 +3 3050 3149 2828 +3 3051 3147 2808 +3 3051 3197 2898 +3 3052 3202 2820 +3 3053 3111 2842 +3 3055 3121 2858 +3 3056 3071 2919 +3 3056 3160 2928 +3 3056 3210 2831 +3 3058 3194 2934 +3 3059 3072 2888 +3 3059 3122 2924 +3 3059 3125 2914 +3 3060 3186 2923 +3 3061 3190 2955 +3 3061 3192 285 +3 3062 3124 2865 +3 3062 3159 2906 +3 3063 3141 252 +3 3064 3172 2810 +3 3065 3145 2985 +3 3065 3168 2839 +3 3066 3151 2881 +3 3070 3201 2975 +3 3072 3153 2903 +3 3072 3167 2888 +3 3073 3174 2874 +3 3074 3147 2863 +3 3075 3136 2809 +3 3075 3208 2931 +3 3076 3087 2869 +3 3076 3152 2834 +3 3077 3126 2871 +3 3078 3156 2882 +3 3080 3156 2838 +3 3082 3137 2833 +3 3082 3175 2909 +3 3084 3143 2830 +3 3085 3155 2952 +3 3086 3180 2901 +3 3086 3205 2849 +3 3089 3139 2887 +3 3091 3115 2824 +3 3091 3204 2853 +3 3092 3196 2929 +3 3093 3105 2884 +3 3093 3173 2970 +3 3094 3121 2926 +3 3094 3200 2858 +3 3095 3155 2902 +3 3096 3172 2895 +3 3097 3157 2916 +3 3097 3163 2806 +3 3098 3116 2890 +3 3100 3116 2907 +3 3100 3132 2811 +3 3100 3181 2922 +3 3101 3160 2900 +3 3102 3187 3011 +3 3103 3191 2825 +3 3103 3194 2816 +3 3105 3166 2892 +3 3106 3141 2948 +3 3108 3171 2947 +3 3108 3193 2912 +3 3110 3171 2836 +3 3110 3195 2991 +3 3111 3158 2923 +3 3111 3176 2842 +3 3114 3180 2878 +3 3117 3140 2925 +3 3118 3119 2883 +3 3118 3143 2913 +3 3118 3144 2829 +3 3119 3169 2808 +3 3120 3171 2912 +3 3122 3154 2840 +3 3127 3143 2829 +3 3131 3166 2815 +3 3139 3200 2887 +3 3148 3164 2848 +3 3148 3167 2903 +3 3152 3153 2834 +3 3153 3164 2903 +3 3155 3177 2952 +3 3162 3178 3005 +3 3162 3205 2901 +3 3168 3170 2921 +3 3176 3186 2814 +3 3181 3210 2922 +3 3185 3189 2957 +3 3206 3207 2932 +3 3208 3209 2931 +3 3211 3314 3290 +3 3211 3315 3285 +3 3211 3358 3315 +3 3212 3313 3284 +3 3212 3318 3291 +3 3212 3354 3313 +3 3213 3283 3271 +3 3213 3289 3266 +3 3213 3371 3265 +3 3214 3286 3264 +3 3214 3296 3276 +3 3214 3372 3288 +3 3214 3373 3263 +3 3215 3331 3274 +3 3215 3333 3292 +3 3215 3361 3312 +3 3215 3366 3333 +3 3216 3356 3293 +3 3216 3365 3311 +3 3217 3357 3294 +3 3217 3368 3310 +3 3218 3332 3275 +3 3218 3336 3295 +3 3218 3362 3309 +3 3218 3367 3336 +3 3219 3323 3319 +3 3219 3352 3265 +3 3220 3324 3264 +3 3220 3328 3320 +3 3220 3353 3328 +3 3221 3316 3256 +3 3221 3329 3316 +3 3221 3338 3266 +3 3221 3355 3329 +3 3222 3337 3255 +3 3222 3347 3263 +3 3223 3359 3274 +3 3223 3364 3272 +3 3223 3369 3364 +3 3224 3360 3273 +3 3224 3363 3275 +3 3224 3370 3258 +3 3225 3276 3271 +3 3225 3283 3249 +3 3225 3285 3248 +3 3225 3286 3276 +3 3226 3284 3247 +3 3226 3289 3271 +3 3226 3296 3250 +3 3227 3287 3278 +3 3227 3371 3287 +3 3228 3308 3277 +3 3228 3324 3308 +3 3228 3372 3324 +3 3229 3342 3306 +3 3229 3344 3267 +3 3229 3368 3342 +3 3230 3309 3268 +3 3230 3343 3305 +3 3230 3367 3309 +3 3231 3312 3269 +3 3231 3346 3304 +3 3231 3366 3312 +3 3232 3339 3303 +3 3232 3345 3270 +3 3232 3365 3339 +3 3233 3301 3260 +3 3233 3319 3279 +3 3233 3327 3319 +3 3233 3334 3293 +3 3234 3302 3280 +3 3234 3328 3292 +3 3234 3333 3259 +3 3235 3299 3282 +3 3235 3329 3295 +3 3235 3336 3261 +3 3236 3300 3262 +3 3236 3317 3281 +3 3236 3330 3317 +3 3236 3335 3294 +3 3237 3288 3277 +3 3237 3321 3255 +3 3237 3373 3288 +3 3238 3287 3266 +3 3238 3322 3278 +3 3238 3338 3256 +3 3239 3327 3293 +3 3239 3352 3327 +3 3239 3356 3290 +3 3240 3331 3292 +3 3240 3353 3315 +3 3240 3358 3331 +3 3241 3332 3295 +3 3241 3354 3332 +3 3241 3355 3313 +3 3242 3330 3294 +3 3242 3347 3330 +3 3242 3357 3291 +3 3243 3348 3269 +3 3243 3359 3298 +3 3243 3361 3359 +3 3244 3311 3270 +3 3244 3325 3311 +3 3244 3349 3272 +3 3244 3364 3325 +3 3245 3310 3267 +3 3245 3326 3310 +3 3245 3350 3297 +3 3245 3360 3326 +3 3246 3351 3268 +3 3246 3363 3273 +3 3247 3289 3226 +3 3247 3355 3266 +3 3248 3286 3225 +3 3248 3353 3264 +3 3249 3283 3265 +3 3249 3285 3225 +3 3249 3314 3285 +3 3249 3352 3314 +3 3250 3284 3226 +3 3250 3296 3263 +3 3250 3318 3284 +3 3250 3347 3318 +3 3251 3358 3290 +3 3251 3369 3274 +3 3252 3354 3291 +3 3252 3370 3275 +3 3253 3307 305 +3 3253 3323 3307 +3 3254 3280 290 +3 3254 3320 3280 +3 3254 3324 3320 +3 3255 3317 3222 +3 3255 3321 294 +3 3255 3337 3237 +3 3256 3282 309 +3 3256 3316 3282 +3 3256 3322 3238 +3 3256 3338 3221 +3 3257 3356 3325 +3 3257 3369 3290 +3 3258 3326 3224 +3 3258 3357 3326 +3 3258 3370 3291 +3 3259 3302 3234 +3 3259 3340 288 +3 3259 3366 3340 +3 3260 3301 302 +3 3260 3334 3233 +3 3260 3365 3334 +3 3261 3299 3235 +3 3261 3341 311 +3 3261 3367 3341 +3 3262 3300 297 +3 3262 3335 3236 +3 3262 3368 3335 +3 3263 3296 3214 +3 3263 3337 3222 +3 3263 3347 3250 +3 3263 3373 3337 +3 3264 3286 3248 +3 3264 3353 3220 +3 3264 3372 3214 +3 3265 3283 3213 +3 3265 3323 3219 +3 3265 3352 3249 +3 3265 3371 3323 +3 3266 3287 3213 +3 3266 3289 3247 +3 3266 3338 3238 +3 3266 3355 3221 +3 3267 3310 3229 +3 3267 3344 35 +3 3267 3350 3245 +3 3268 3309 3246 +3 3268 3343 3230 +3 3268 3351 30 +3 3269 3312 3243 +3 3269 3346 3231 +3 3269 3348 58 +3 3270 3311 3232 +3 3270 3345 53 +3 3270 3349 3244 +3 3271 3276 3226 +3 3271 3283 3225 +3 3271 3289 3213 +3 3272 3349 55 +3 3272 3359 3223 +3 3272 3364 3244 +3 3273 3297 32 +3 3273 3351 3246 +3 3273 3360 3297 +3 3273 3363 3224 +3 3274 3331 3251 +3 3274 3361 3215 +3 3274 3369 3223 +3 3275 3332 3252 +3 3275 3362 3218 +3 3275 3363 3362 +3 3275 3370 3224 +3 3276 3286 3214 +3 3276 3296 3226 +3 3277 3288 3228 +3 3277 3308 292 +3 3277 3321 3237 +3 3278 3287 3238 +3 3278 3307 3227 +3 3278 3322 307 +3 3279 3301 3233 +3 3279 3319 3253 +3 3280 3302 289 +3 3280 3320 3234 +3 3281 3300 3236 +3 3281 3317 3255 +3 3282 3299 310 +3 3282 3316 3235 +3 3284 3313 3247 +3 3284 3318 3212 +3 3285 3314 3211 +3 3285 3315 3248 +3 3287 3371 3213 +3 3288 3372 3228 +3 3288 3373 3214 +3 3290 3314 3239 +3 3290 3356 3257 +3 3290 3358 3211 +3 3290 3369 3251 +3 3291 3318 3242 +3 3291 3354 3212 +3 3291 3357 3258 +3 3291 3370 3252 +3 3292 3328 3240 +3 3292 3331 3215 +3 3292 3333 3234 +3 3293 3327 3233 +3 3293 3334 3216 +3 3293 3356 3239 +3 3294 3330 3236 +3 3294 3335 3217 +3 3294 3357 3242 +3 3295 3329 3241 +3 3295 3332 3218 +3 3295 3336 3235 +3 3297 3350 33 +3 3297 3360 3245 +3 3298 3348 3243 +3 3298 3359 3272 +3 3303 3339 300 +3 3303 3345 3232 +3 3304 3340 3231 +3 3304 3346 60 +3 3305 3341 3230 +3 3305 3343 28 +3 3306 3342 299 +3 3306 3344 3229 +3 3307 3323 3227 +3 3308 3324 3254 +3 3309 3362 3246 +3 3309 3367 3218 +3 3310 3326 3217 +3 3310 3368 3229 +3 3311 3325 3216 +3 3311 3365 3232 +3 3312 3361 3243 +3 3312 3366 3215 +3 3313 3354 3241 +3 3313 3355 3247 +3 3314 3352 3239 +3 3315 3353 3248 +3 3315 3358 3240 +3 3316 3329 3235 +3 3317 3330 3222 +3 3318 3347 3242 +3 3319 3323 3253 +3 3319 3327 3219 +3 3320 3324 3220 +3 3320 3328 3234 +3 3323 3371 3227 +3 3324 3372 3264 +3 3325 3356 3216 +3 3325 3364 3257 +3 3326 3357 3217 +3 3326 3360 3224 +3 3327 3352 3219 +3 3328 3353 3240 +3 3329 3355 3241 +3 3330 3347 3222 +3 3331 3358 3251 +3 3332 3354 3252 +3 3333 3366 3259 +3 3334 3365 3216 +3 3335 3368 3217 +3 3336 3367 3261 +3 3337 3373 3237 +3 3339 3365 3260 +3 3340 3366 3231 +3 3341 3367 3230 +3 3342 3368 3262 +3 3359 3361 3274 +3 3362 3363 3246 +3 3364 3369 3257 +3 3374 3436 3397 +3 3374 3439 3436 +3 3374 3450 3439 +3 3375 3421 3415 +3 3375 3449 3416 +3 3376 3422 3413 +3 3376 3429 3414 +3 3376 3430 3429 +3 3377 3405 3397 +3 3377 3438 3405 +3 3377 3452 3438 +3 3377 3457 3410 +3 3378 3409 3396 +3 3378 3451 3409 +3 3379 3403 3401 +3 3379 3444 3414 +3 3379 3447 3444 +3 3379 3453 3403 +3 3380 3446 3402 +3 3380 3454 3413 +3 3381 3407 3391 +3 3381 3411 3407 +3 3381 3415 3409 +3 3381 3455 3411 +3 3382 3416 3392 +3 3382 3456 3410 +3 3383 3433 3419 +3 3383 3447 3401 +3 3384 3434 3402 +3 3384 3438 3420 +3 3384 3446 3438 +3 3385 3429 3417 +3 3385 3431 3403 +3 3385 3453 3414 +3 3386 3430 3413 +3 3386 3432 3418 +3 3386 3454 3404 +3 3387 3416 3410 +3 3387 3421 3416 +3 3387 3436 3421 +3 3387 3457 3436 +3 3388 3439 3409 +3 3389 3435 3397 +3 3389 3445 3413 +3 3390 3422 3414 +3 3390 3435 3422 +3 3390 3450 3435 +3 3391 3415 3381 +3 3391 3427 3426 +3 3391 3448 3415 +3 3392 3408 3382 +3 3392 3428 3408 +3 3392 3449 3425 +3 3393 3440 3411 +3 3393 3451 3423 +3 3393 3455 3451 +3 3394 3441 3424 +3 3394 3456 3412 +3 3395 3418 306 +3 3395 3430 3418 +3 3396 3406 3378 +3 3396 3444 3406 +3 3396 3450 3444 +3 3397 3435 3374 +3 3397 3445 3389 +3 3397 3457 3377 +3 3398 3424 27 +3 3398 3452 3424 +3 3399 3419 0 +3 3399 3437 3419 +3 3399 3451 3437 +3 3400 3426 20 +3 3400 3448 3426 +3 3400 3449 3448 +3 3401 3433 3383 +3 3401 3442 311 +3 3401 3447 3379 +3 3402 3404 3380 +3 3402 3434 301 +3 3402 3443 3404 +3 3402 3446 3384 +3 3403 3431 309 +3 3403 3442 3401 +3 3403 3453 3385 +3 3404 3432 3386 +3 3404 3443 303 +3 3404 3454 3380 +3 3405 3445 3397 +3 3405 3446 3445 +3 3406 3437 3378 +3 3406 3447 3437 +3 3407 3411 17 +3 3407 3427 3391 +3 3408 3412 3382 +3 3408 3428 23 +3 3409 3415 3388 +3 3409 3439 3396 +3 3409 3455 3381 +3 3410 3416 3382 +3 3410 3452 3377 +3 3410 3456 3452 +3 3410 3457 3387 +3 3411 3440 16 +3 3411 3455 3393 +3 3412 3441 3394 +3 3412 3456 3382 +3 3413 3422 3389 +3 3413 3430 3376 +3 3413 3445 3380 +3 3413 3454 3386 +3 3414 3422 3376 +3 3414 3429 3385 +3 3414 3444 3390 +3 3414 3453 3379 +3 3415 3421 3388 +3 3415 3448 3375 +3 3416 3421 3375 +3 3416 3449 3392 +3 3417 3429 3395 +3 3417 3431 3385 +3 3418 3430 3386 +3 3418 3432 305 +3 3419 3433 313 +3 3419 3437 3383 +3 3420 3434 3384 +3 3420 3438 3398 +3 3421 3436 3388 +3 3422 3435 3389 +3 3423 3440 3393 +3 3423 3451 3399 +3 3424 3441 26 +3 3424 3452 3394 +3 3425 3428 3392 +3 3425 3449 3400 +3 3426 3427 19 +3 3426 3448 3391 +3 3429 3430 3395 +3 3435 3450 3374 +3 3436 3439 3388 +3 3436 3457 3397 +3 3437 3447 3383 +3 3437 3451 3378 +3 3438 3446 3405 +3 3438 3452 3398 +3 3439 3450 3396 +3 3444 3447 3406 +3 3444 3450 3390 +3 3445 3446 3380 +3 3448 3449 3375 +3 3451 3455 3409 +3 3452 3456 3394 + +CELL_TYPES 7232 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 + +POINT_DATA 3458 +SCALARS scalars double +LOOKUP_TABLE default +1.6755246382 0.9791806223 0.9791806223 0.97594938187 0.12925491957 0.32674332908 0.2776476709 0.26537269646 0.54790553034 +-0.21848899462 -0.21871453724 -0.21891455992 0.84665342709 -0.17856744253 1.6242536107 1.5541884277 1.4657434756 1.3621923503 +1.2494702901 1.1352956356 1.0279120984 0.93487312743 0.86221409821 0.81414061254 0.79312421951 0.80015646774 0.83491193657 +0.89569004477 1.6314269455 1.5802975714 1.5225587782 1.4586874133 1.3892109713 1.3147032374 1.2357795488 1.1530917128 +1.0673226235 0.97756806161 0.87230841844 0.75258544172 0.62351150851 0.49302670378 0.36915058044 0.25873103277 0.16650020876 +0.094748228714 0.043676133967 0.012239424449 -0.00085049056056 0.0036947002414 0.026134812423 0.067560414732 0.88939364767 0.79870322351 +0.707858335 0.617609243 0.52870128787 0.44186873392 0.35782870532 0.27727526364 0.20087367574 0.30551630372 0.26085193696 +0.33248261206 0.40221609491 0.474164333 0.49090946769 0.43492101536 0.38013531824 -0.21860483282 -0.21999990002 -0.20935679925 +-0.19002571784 -0.16111227699 -0.12290209694 -0.075772635406 -0.02018945884 0.043298356616 0.11406364917 0.19140736677 0.27456547266 +0.36271649289 0.45498963119 0.55047337116 0.64822448055 0.74727732904 0.92700938405 1.0064051127 1.0843220202 1.1602511728 +1.2336966205 1.3041786361 1.3712368488 1.4344332513 1.4933550605 1.547617414 1.5968658838 1.6407787913 1.6790693085 +1.7114873312 1.7378211132 1.7578986488 1.7715887966 1.778802136 1.7794915513 1.7736525394 1.7613232392 1.7425841827 +1.7175577686 1.6864074632 1.6493367325 1.606587713 1.5584396307 1.5052069767 1.4472374533 1.3849097028 1.3186308344 +1.248833765 1.1759743914 1.1005286129 1.0229892221 0.94386268688 0.86366584185 0.7829225126 0.70216009423 0.62190610654 +0.54268474835 0.46501347365 0.38939961165 0.31633705305 0.2463030241 0.17975496944 0.11712756421 0.058829874861 0.0052426872228 +-0.043283980687 -0.086433164889 -0.12392302578 -0.15550868901 -0.180983845 -0.20018209643 -0.21297804515 -0.21928811126 -0.21907107899 +-0.21232836594 -0.19910401381 -0.17948440074 -0.15359767711 -0.12161292848 -0.083739071172 -0.040223487689 0.0086495891313 0.062560932655 +0.12115840756 0.18405926988 0.25085266704 0.32110232136 0.3943493798 0.47011541101 -0.20807267878 -0.18785742448 -0.15804382837 +-0.11892755494 -0.070896524324 -0.014427065188 0.049920809018 0.12150895379 0.19962742213 0.28350150513 0.37229941487 0.46514053332 +0.56110414555 0.65923857053 0.75857059904 0.85811514514 0.95688501528 1.0539006985 1.1482000803 1.2388479839 1.3249454448 +1.4056386256 1.4801272836 1.5476727072 1.6076050415 1.6593299313 1.7023344156 1.7361920144 1.7605669584 1.7752175189 +1.7799984047 1.7748622033 1.7598598509 1.7351401274 1.7009481808 1.6576230962 1.6055945329 1.5453784635 1.4775720571 +1.4028477567 1.3219466109 1.2356709247 1.144876303 1.0504631654 0.95336781667 0.85455316148 0.75499915491 0.65569308429 +0.55761977817 0.46175183962 0.36904000087 0.28040369479 0.19672193674 0.11882460736 0.047484222473 -0.01659172796 -0.072767796139 +-0.12048687821 -0.15927573911 -0.18874970572 -0.20861648166 -0.21867904609 -0.2188376075 -0.20909059342 -0.18953466601 -0.16036376341 +-0.12186717646 -0.074426679786 -0.018512745681 0.045320121609 0.11643888496 0.19413825227 0.76241422949 0.67829990008 0.59490769465 +0.51282974156 0.43264883727 0.3549343082 0.28023796823 0.2090902005 0.14199619143 0.079432343644 0.021842893229 -0.030363244546 +-0.076815378752 -0.1171836749 -0.15118149694 -0.20430773504 0.79987406568 0.74521915938 0.68109670552 0.60583329596 0.51822873301 +0.41876520742 0.3110804081 0.20190534345 0.098508562201 0.0062048589826 -0.071983637658 -0.13448442589 -0.18039364864 -0.20905411933 +-0.21991103435 -0.21257264778 -0.18707791994 -0.1443875336 -0.086957367726 -0.018911605271 0.054700304845 -0.21898841526 -0.21012065805 +-0.19219107636 -0.16536255105 -0.12987956477 -0.086065983105 -0.034322102404 0.024879005766 0.090995821162 0.16342333305 0.2414985847 +0.32450675189 0.41168770058 0.50224296338 0.59534306942 0.69013516017 0.78575082394 0.88131407132 0.21195574355 0.31433274552 +0.43280230545 0.56140042231 0.69246486262 0.81780410665 0.92995124339 1.0230844378 1.093366893 1.1387199261 1.1582627095 +1.1517427525 1.1192352923 1.0612474234 1.0802545292 1.1920461437 1.3065231906 1.4155401339 1.5121272707 1.591608462 +1.6521627887 1.6946460237 1.7217590881 1.7368564596 1.7427529387 1.7408274774 1.7306086293 1.7099146759 0.86687326153 +0.361144653 0.36673175754 0.6942875803 0.92589838003 0.1975067245 1.291299307 0.55452226136 0.18577761785 0.57040169005 +1.0033974887 0.59517018306 1.1960344919 0.39043213832 0.62067619447 0.44840245598 0.32031309912 0.8987292909 0.71379076294 +0.95987196479 0.67128308005 0.10483555049 0.63726617945 1.2502533541 0.15161858362 1.4949202081 0.18954169396 0.76001543195 +0.80473955548 0.23403135997 1.0716163497 0.48573338641 1.1578969598 1.3725148243 0.31325240746 0.54329988893 0.48977838326 +0.80745467835 0.62218079451 0.3198406734 1.0052556193 0.32429958483 0.40621048039 1.1272052982 0.10435016451 0.72428193257 +1.1638563283 0.43406795708 0.083102279045 1.4028043917 0.75927866652 0.69340229586 0.28280024781 0.46666823295 0.8355583309 +0.61701301468 0.66395380037 1.108205709 1.4783862114 0.25344355635 0.58071180237 1.2809597459 1.060862375 0.42273671824 +0.29926980744 0.47470945647 0.19641615201 0.89240580146 0.50841190057 1.2277235732 0.71571823772 0.06034723537 0.70965533009 +0.38924947134 0.74611739694 0.52892902976 0.29263750932 0.7666175091 0.5461917549 1.0259716759 0.39595072208 0.79850519537 +0.17136487756 1.2056125059 0.55292226657 0.37162212621 0.047937225353 1.368065989 0.51537080392 1.3411203028 0.13550107661 +0.71735362804 1.5829955967 0.97139543078 0.60811823746 0.8194158338 1.0066092537 0.28647581874 0.20674785042 1.4124822932 +1.0149499226 0.61876937867 0.44250461463 0.73348485006 0.92998653117 0.11926367298 0.63820354149 0.29060362974 0.65588171292 +1.0987528699 0.11624837386 0.82894394466 0.42839546936 0.96451374261 0.17809352216 0.55577006473 0.2407679354 1.2869349416 +0.49931562787 0.90540097344 1.0955679242 0.8174626293 0.13682195105 1.3252501597 0.6159407388 0.083203590137 0.19657561309 +1.5095885771 0.66255791331 0.8433570505 0.76001760909 0.53495478381 0.75465469384 0.66265403578 1.0556619548 0.19996695446 +1.5465750616 0.24087382873 1.4494218456 0.35248135204 1.2246286365 0.95088624831 0.61179621044 0.51734248648 1.1820750787 +0.4874918602 0.87636366667 0.29913767987 1.3119392503 0.47476945249 0.97285883603 1.0540826331 0.25660827822 1.1641797053 +0.34205604159 0.57081213946 0.13893174208 1.4169274193 0.89461644693 0.65774840097 1.1197436846 0.37632522956 0.36229441535 +0.81767966727 0.24906107837 0.32462157616 0.29323135309 0.71013711515 1.3736946587 1.7254596243 1.7445162662 1.4920135658 +1.0562887221 0.091019742036 0.75836733523 0.63796587338 0.74614686152 1.3372442562 1.7227443468 0.22757806246 1.3814269582 +1.75160456 1.7433942612 1.1614945482 0.28908435961 -0.040680764072 -0.19712242798 1.7389735177 1.6305131831 1.4847030175 +1.0008674262 1.7798502555 0.30078946569 1.0741026301 1.4636451775 -0.2181982889 0.61655407578 -0.16241170212 1.5408439441 +1.6126629393 0.78021256649 1.7775634908 1.1537000623 1.0240237488 -0.030690288698 0.26395039273 0.042257147609 1.2346987235 +1.5515737875 0.023271924651 -0.13497574145 0.40722560575 1.6648755632 0.55478116338 1.1215008653 1.5934508245 0.7835423385 +1.4447115535 -0.16003076697 0.39104289995 0.63632677859 1.0241558206 0.67374111655 1.7791074084 1.7530563221 1.0408588855 +0.39812748569 0.20897892604 0.13114612235 1.3000060199 0.66210977117 1.7799230739 -0.071774297163 1.3074156194 1.422165108 +0.39273142557 1.599103998 1.6045260176 1.7272606498 1.0939205417 1.6968399539 0.041872610997 0.074075455077 -0.21962421153 +1.5882557871 0.86865045064 1.7797624851 1.3125922888 1.6390889538 1.3141891734 1.6123954824 1.7092950553 0.42431944633 +-0.19137405751 -0.10544439672 0.97812541812 0.4059977216 1.4459627025 1.7794553734 1.032319404 1.6904970083 0.51082441871 +0.10235142258 0.87586165911 -0.16859146456 1.3570230331 1.7546490697 1.7799999968 1.2736172599 1.6364507411 0.88056726549 +1.2384737382 1.7299552819 1.7693654674 -0.096377971322 -0.21597352977 1.7622988608 1.6947815613 0.18880755439 -0.0527216022 +1.0162750161 0.2886798176 0.81018970005 1.6220761446 0.81322767245 1.5176354225 0.89293342411 0.097541128502 1.6904501513 +1.4399080082 0.2208956263 1.2826670046 -0.21193883752 -0.14863448728 0.52702414235 -0.12344628885 1.7598706414 0.50207265734 +0.45079170699 1.6625490968 0.56284128412 1.7616743194 0.75779708398 -0.11200536353 1.2652547551 1.0154676941 1.4906892197 +0.1073093101 0.19691407093 -0.20255952197 1.765068477 -0.19482770843 1.5966683845 0.40842139555 0.22682590264 1.0955695198 +0.68546672779 1.2449847075 0.69752921811 0.82277096307 1.5376456976 1.1877105153 0.074539377375 -0.099946779704 0.2020624201 +1.4821984033 1.5357843652 1.7541365471 -0.21334866373 0.83073721956 1.2118188724 1.77965962 1.1952412986 -0.015530618908 +1.3952439587 -0.0077818623677 0.98283025508 0.6002521502 0.8290108813 0.78342439278 1.4778188827 0.67291396727 0.93958377947 +1.2087109638 1.682859554 0.8851646931 1.4533011829 0.81594409043 0.10593941505 0.62711322033 1.0821948532 0.19046104279 +0.95697400523 -0.036303770216 0.42995824863 0.78359014514 1.4705249808 0.43620795997 1.4942899184 1.4995803164 1.7607095384 +-0.026684309788 -0.14945186721 0.27181311959 1.6346079349 1.2997959442 1.11992624 1.7782899869 1.6479872336 1.760139185 +1.7680241883 0.24776023528 0.33631241687 1.2091193492 0.44992719522 1.7399092641 0.58514577468 0.06163434235 -0.10608409811 +-0.18124769639 0.047065681674 1.0701396779 1.1399168616 -0.1676330393 1.2626083239 0.28445109692 1.3118664044 0.39957458065 +-0.21958366702 0.85095515697 0.60868822891 -0.1789837912 -0.2022020427 0.38119666578 1.6439421786 1.6708218985 1.3443741379 +0.15164495668 1.4871192108 1.6829600817 0.011563812066 1.7704294813 0.63716013592 0.56554316844 1.6294048372 1.5974310352 +1.4147345055 1.3001896892 1.7337495873 1.1705709575 -0.21860754384 1.7058949995 1.7103069957 0.45549492458 0.57252355865 +0.2544333845 1.7659498956 0.61381502061 -0.080885742132 1.6851723305 1.534597402 0.73194437084 0.23528466225 0.078865697569 +1.7137698041 1.6216704718 1.7611162882 1.3490289581 0.24681976957 1.7784724657 1.7024557104 0.9373766395 0.035681248645 +1.0922926632 1.7664777929 -0.051334187588 0.24285795416 0.4033819057 1.5596017406 1.0386431033 1.1584974663 1.5706858676 +0.87941738727 1.2002016425 0.093909324102 1.7735916078 1.0150200706 -0.062459760119 -0.20630454949 1.0084284917 -0.20732187482 +0.8726355579 0.10380791408 0.87028100538 0.15837742763 1.430804563 -0.10930476298 0.10707249237 1.259558845 1.7798352388 +-0.038782504916 1.3788081563 1.6890141058 1.6784341576 -0.11311473697 1.7055906275 1.7614944333 1.4235397045 1.4392062943 +0.52740057832 0.52587950731 1.6023625863 0.95060003397 1.5617898946 1.587339682 1.5715198291 -0.2036740987 1.6023404104 +1.7197585677 0.74448618549 1.7789736983 -0.17968280311 1.6860644902 1.7659687446 -0.046161284492 1.2452130093 -0.14399826085 +1.3829313502 1.6986880185 1.1636918092 1.7633708528 1.4097538333 0.31495939504 1.5323214565 1.4454200624 1.7361145589 +1.4266794009 1.6233079352 1.0119338174 1.7702552372 1.1563335703 1.1201487786 1.7729140803 1.6033166511 0.87855449706 +1.4182608424 -0.14846752299 -0.18374611389 0.84123086168 0.081755907296 1.4894827513 1.3777832562 1.0629108518 -0.11310653369 +0.49984618238 0.28001571554 0.9472433727 1.7601266798 -0.0037715413904 0.52613216577 1.3905472038 -0.11935534778 0.68391527795 +1.5401021595 1.5551909256 1.7239018646 -0.15319704272 -0.012933632469 1.6819075417 -0.21632990576 -0.10330645719 1.7791215255 +1.7731597902 1.753761523 1.1973259287 1.7149136845 1.2690237177 0.071872164964 0.18451100394 1.328232889 1.6077289714 +1.4927281036 -0.21742792002 1.6942180964 0.50407282381 1.7467536854 1.589644059 1.1328062428 1.1661460294 1.6676504833 +0.92529746874 -0.17010271758 -0.029280544744 1.5378673272 0.79549679584 0.50488036314 0.96805635336 1.7499157341 0.95703770126 +0.39247905807 0.52762662412 -0.21901125173 1.7799372939 0.4296683867 0.21704289523 1.5492646168 1.7701514989 1.7383670214 +1.2686460121 1.22379058 1.5336362869 1.7745253992 0.6173631366 0.23672532107 0.98283636458 0.020636747071 -0.21838404083 +1.7301020173 0.66964628644 0.90278800394 1.7365028195 1.7482636903 0.6457405172 -0.21047063169 0.9505461941 -0.21507236035 +1.6658683375 1.1388498516 1.7783990674 1.5516196057 0.22127190456 -0.17893733546 -0.18343453226 1.7765721059 0.38580226132 +1.448298304 1.0791421693 -0.0039868873598 0.79605811743 0.0023885524726 0.98969091989 0.67104753584 0.52908911704 0.76135850708 +0.7702314165 0.32421467036 0.7385386547 0.44879223799 0.89892923772 -0.21675853532 1.7731495756 0.39609129019 0.20691547209 +0.33263708079 1.3121303888 1.6396311702 1.2120342934 -0.11845608694 1.6916451151 0.026841992084 -0.2013323477 1.2640520841 +0.2902257033 0.75892529467 1.3703440591 1.0969312878 1.7159775372 1.6763556495 1.7778596361 0.48913148431 0.49154644047 +0.29601893273 0.10687915059 1.0468691959 1.2342539398 1.5191029858 1.1223322831 0.10832982802 1.7790662252 1.4844257184 +0.86651828984 -0.041235438944 0.33942310987 0.051238572631 0.53210660698 -0.18974889055 0.72610216302 0.29430436733 -0.19734286956 +1.2407978527 1.7530697702 0.64499765087 0.79828934 -0.070721277822 0.19219712539 1.2492611119 1.748740283 -0.21997212081 +0.91315452616 1.765595559 1.670814651 1.4668430255 0.86202628698 1.7735318605 1.7279755804 0.0125843294 0.18138202845 +1.7795539058 1.0164938102 1.1124852629 0.27508110685 -0.172412307 0.025385244399 1.5215837828 1.3724109274 1.106480058 +0.15871722587 -0.20991885942 0.57308245517 0.15399029035 -0.20308565205 1.2952704862 0.22553705843 0.53601198812 1.3184020908 +0.76586725756 0.99763940465 -0.21868281924 -0.16910496773 1.7358706319 1.1642573472 0.90445772792 0.56514971541 1.6170335203 +0.84950348045 1.5999846424 0.60075645552 0.11151611351 1.6628073184 -0.16356942164 1.688535221 -0.14000159756 1.4504005062 +0.34262808168 0.37824356168 0.7266836159 0.33530920633 -0.08055825165 0.26172590648 1.3187820895 -0.10225555796 0.90995215144 +-0.19068297401 1.3885412553 -0.11575822738 1.6682058318 1.5037164826 0.41641991648 0.77715761274 0.66357351997 1.6906603609 +0.12700479644 0.12489404998 1.2458110483 1.1608760771 0.32054496692 0.49117955189 1.2856918719 0.032489847438 1.736544688 +1.5986989399 0.4149991446 1.3311110815 1.3039491509 1.1399028704 1.3634103586 1.7441986019 0.55130438777 0.20967269361 +1.4118956484 0.72966547046 0.69813216218 -0.025904313027 1.7737038915 1.6460070679 0.74641094673 0.16324744643 1.370902486 +0.48231216933 0.30242796524 -0.092968069243 -0.044276399272 0.67260638099 1.6221492087 1.6591685283 1.2971381416 -0.099188808917 +0.70370402653 1.6360946983 0.62780037533 0.1805811952 1.3314181341 0.29404335576 0.16058271317 -0.060204754176 1.4828111351 +1.5603089349 -0.2100077428 1.7707094081 -0.20281262313 -0.1650600756 0.89753660211 0.37367440714 0.20289462996 0.83877684404 +0.32705187271 1.3443814497 1.5804702733 -0.057211514835 0.13097557682 1.5156182285 1.6343043527 1.6373962702 -0.056011568781 +0.5678606335 -0.21788728903 1.7738151566 -0.095266717003 -0.056421531835 1.0224514796 -0.11192307015 0.14516326204 1.7689397741 +0.89772062456 0.64399121054 0.02864753864 -0.094638479426 1.3078539287 1.4909355969 0.0080326733447 0.17994657822 1.7785035092 +1.7412777025 1.7376994232 0.53241861213 1.771824114 0.20596196443 0.031357842015 0.14879858121 -0.15770564632 1.4632007661 +1.631821323 1.2111372335 1.5335025607 1.2681187473 1.4861467968 1.0131554309 0.67468799408 0.32108115585 1.6495696767 +0.92430191175 -0.14403803425 1.5628909661 1.1637807452 1.2044651142 1.7770988333 1.1692557255 0.84446549414 -0.20438753126 +-0.055216437558 1.3891576864 1.7790938032 1.0476355754 1.4081977285 1.0124007729 0.053451057288 0.62525061106 0.16370914806 +1.2406903071 1.4576529163 1.6916694509 1.1326584561 0.79053485683 0.10901880923 0.96690109341 0.036679990866 -0.10285618183 +1.6004876007 1.352712764 1.7775800733 0.75811352467 1.4615411293 0.78278342116 1.0540244004 -0.20087323074 0.68110834583 +1.6269759841 0.3591540863 1.6480879291 0.56574842741 0.92863217082 -0.14885257941 1.2268611254 0.52729453172 0.33903483423 +0.2221208743 0.029026413278 1.6539378649 1.7784616283 1.6480991214 0.27775509643 1.0880610498 1.7202270392 1.7443598813 +-0.19083465586 0.85627385177 1.2269923476 0.94609700487 -0.16218185243 0.98447743264 0.67762924276 1.2431905366 1.1474503055 +0.73267512334 0.059833499161 1.7553440602 -0.046638643361 1.7674968952 1.0584487317 0.026305088158 1.4068083113 1.1307259697 +1.6234469029 1.4285157471 0.91112709271 0.98431814407 -0.070422345332 1.1302881139 -0.21841364861 1.7558192736 0.38740220715 +-0.033664335228 0.87176406197 1.4047861781 1.5568070635 1.7234343536 1.4382259013 1.0627470344 0.82638482129 1.3665523381 +0.28520134604 1.4716795898 0.21172271486 1.7336224382 1.6690514316 1.7676637181 0.48648081885 1.5592785343 1.4069418566 +1.0358580114 -0.20622776426 1.5109418697 1.7769990915 0.48646727716 1.5501972339 1.0799039804 0.86194205356 1.3966271049 +-0.10565312258 0.080678086833 1.725264937 1.241247656 0.69240613201 1.4198353864 1.0881633918 1.6451470084 -0.14611216463 +1.0342224414 0.96835063646 -0.18530636988 1.6330988649 1.7295416144 1.5186444548 1.6998796345 1.7131446464 1.0978830834 +0.8494702414 0.92202054683 1.7307836136 0.11503641718 1.5333146213 0.70526485253 1.2672412058 0.30844224688 1.341498555 +1.3670323087 -0.070333391814 1.7568254367 1.0560148231 -0.1452120341 1.4559893685 1.6841615181 0.62309392999 0.78593622608 +1.5508636382 -0.026973832346 0.055983239914 0.32596422949 0.070854591456 0.91997209675 1.2636988442 0.87141263115 0.1212806758 +1.2816917788 0.37273705039 1.7720782603 0.50604452156 0.60985425522 0.30904864028 1.7147156809 -0.21736587628 0.72339210408 +1.77678964 1.6824484587 0.52490537935 1.1550374101 0.61850326028 -0.015182355902 1.7789753585 0.42945221137 0.39012665711 +0.43421435271 0.076846011155 0.17296684624 1.7679610905 1.1101644035 1.1429404362 0.96892860936 1.4762803395 0.28732485658 +0.88131456167 0.37279108443 1.7744585957 -0.049839931413 0.10463662165 1.7740717287 1.7799017319 1.6357817798 1.7737607401 +1.3248346728 0.61535384199 -0.0039225790335 0.44746370199 1.4851787605 -0.14281760828 1.5170360761 -0.14544784491 1.5767418426 +0.48657906819 0.92994004836 -0.1790047211 1.7566998836 1.6769517424 1.5229828197 0.69385042514 0.1632496455 1.3580393159 +1.5558738401 -0.17968245899 1.6600898606 -0.16498529581 1.7619316813 1.3204344761 0.052523227926 1.5890223573 1.7354598797 +0.80214162223 0.28451138829 0.28872157695 1.6965785348 -0.19983748648 1.1810474025 1.662149043 0.59662699162 0.64853448386 +1.7465465263 0.5866275319 0.1992510737 -0.21423173783 1.3926429396 0.099282548046 1.1429058762 1.7671731314 0.61613120655 +1.7040790621 1.3259864997 0.32618052762 1.5265727495 -0.0086062731139 0.42006807001 1.7793985615 1.1653809827 1.5810006771 +0.40345136365 -0.20315370463 1.1369668769 0.17873372718 0.66310108948 1.7764046037 0.78932368744 0.028479130002 -0.13115081742 +1.0065836595 1.1501925842 1.7494673828 1.2432059497 1.7124019707 -0.20737154344 0.36878978442 0.14156065809 1.6701636411 +1.7769052177 1.5406284763 1.7130973656 -0.1829011747 1.6879513723 1.3298152253 -0.21185773556 0.55943310058 1.5634093572 +1.5244016267 1.3750124929 0.38501715325 1.7779664675 1.7101481791 1.3259612324 1.5337484828 0.51687946293 -0.19093232855 +-0.15784682402 1.7353218853 0.47393868949 0.40916795645 0.66342699007 0.32586460462 1.4085056078 1.19268836 0.0027036458021 +1.6063940036 0.30710342426 1.4464636332 1.7249058999 1.7596599896 1.7281067143 -0.21961297526 1.483617813 1.7484157233 +1.3812963996 0.080391420306 0.61442852068 -0.054161694738 1.6672969555 -0.1358612559 1.6072972403 1.6975691655 -0.1810132403 +-0.038708236303 0.033243815321 -0.21897772059 1.0435547906 1.5994356921 -0.21805014996 0.22059993104 0.72317577147 0.93777351966 +0.26134783518 1.753487433 1.5822963635 0.56832985514 -0.21396198043 -0.14558549543 1.5822142271 1.207673445 0.44207484636 +0.8536909213 1.4607842272 1.7517575851 1.7103118946 1.3928034583 0.98064430351 0.83990997193 0.55663742546 0.90898455266 +1.4076455313 0.24681094623 1.7388447738 0.16923123113 1.4937544279 1.7416654512 1.7705585549 1.2126625795 -0.062100436716 +-0.2074347989 1.6955821558 1.6675098381 1.4458061224 0.41309758823 0.42923243044 1.1662203388 1.7766235358 1.0312108783 +1.3646276706 -0.21353076455 -0.1436269495 0.56868982005 1.5868572165 1.6379229659 0.82950212482 1.7770400623 1.2663888311 +0.91374004228 -0.0087182031084 0.22360240731 0.0097846382281 1.1958012778 1.6199576673 1.5936673521 -0.019382374575 0.45588149721 +1.1658845402 0.7466267921 1.4741225627 0.52382703397 -0.17317794513 0.72597314234 1.6285065367 0.54743533097 1.134832459 +0.16715673472 0.85756377264 0.59595436006 1.7690613651 1.7617925445 0.36090698229 1.1783844695 0.16628210813 0.13544867044 +0.78568333716 1.1921326465 0.18580450456 1.7797611048 -0.11290316633 1.4853439641 1.4147813921 1.6430142173 1.5489603055 +1.7139267065 1.2697278377 1.7626086849 1.6729502069 0.049378231065 -0.21783838587 1.779085559 0.74920472144 1.6240515259 +1.2315990791 1.4699985635 1.6965190709 1.757720448 -0.12198209177 -0.20723694676 0.51830372134 1.423914199 0.98531120993 +1.7620679088 0.31057854021 1.0639480409 1.7738141222 1.2578959466 1.3697280447 -0.1575862331 1.7095678318 1.771707428 +1.5985324393 1.2483745988 0.79949055053 1.0235017278 1.706878498 0.012649585888 0.31626809849 -0.2067227952 1.0142076864 +1.7326225967 0.59037705099 0.98804722831 1.7181679685 -0.034728373667 0.69340028653 1.7366653411 0.31891351599 0.83845616206 +0.79282030671 1.5354061463 1.437572707 0.62904138253 1.2130431769 1.6465226854 0.34546551722 0.030591081923 1.3882094304 +-0.11839224318 0.2435380957 -0.21327589759 -0.15840135318 0.38030559071 1.6017652317 0.92963557916 0.54894544786 1.6005726244 +1.7579639867 1.0534387468 1.1759255893 1.3815970903 0.13025903112 1.6075819586 0.32371499102 1.6989285857 -0.18672097487 +0.38516499937 0.013353136648 -0.13807354022 0.20543798963 1.010802549 0.7528615912 1.7124529251 0.12338263277 1.121729717 +0.6137714365 -0.086004066017 1.535924714 0.027077738019 0.98787127097 1.4675442675 1.7736212064 0.78509317842 -0.21946383929 +1.3202829012 0.18105263713 1.7754649939 0.36794793473 0.93979176561 1.3194944109 1.2868338951 1.106356649 1.7799825132 +0.78958529292 1.5203934366 0.033898469863 1.00691238 1.3269063004 1.5294549189 0.72950583364 0.65834810115 1.7617678832 +0.992127944 1.5489705525 0.57364114796 1.7081194902 1.0790838406 1.0392008351 0.67620728821 0.088090584143 0.95174484845 +0.2394426106 -0.053964259812 0.37621032627 1.5104065713 1.5620946156 0.59168772101 1.7785868205 0.66743930604 0.21900724892 +-0.16966078809 -0.079593540459 1.3193114733 1.7614084604 0.69844976734 1.531549371 1.0873662204 0.40915687499 1.2289591228 +1.7694675645 0.72253764595 0.10911815749 1.7738132963 0.90029696962 1.6351903092 -0.11632343722 1.6731716252 0.058885198581 +1.7312906724 1.7158227931 1.3141367 -0.18580671063 1.3664264635 1.4059709339 1.0280821168 0.41927792203 0.31755630569 +0.49021162559 -0.21869586856 1.241168095 -0.18522299406 0.29168447373 0.84190171443 1.608291126 1.2729305086 1.5495714978 +0.61661462562 1.6745114176 0.50848769006 -0.21998781574 0.059245204475 -0.079005150598 1.7033568667 1.773635675 1.685297685 +0.56757773117 1.7799902493 1.6697274736 0.18170903376 0.76696222755 0.29330061725 -0.11085015701 1.7786453117 1.3989591277 +1.5295063897 1.6967702585 0.46615021976 0.022476591375 0.14690619616 1.7369337207 1.4331082872 1.7055236511 1.7475903764 +1.7606118111 0.26550276052 1.7776752916 0.05362404829 1.1537652161 0.26157153623 -0.029784906761 1.6329111326 0.22801372431 +1.2340551739 0.66693979468 1.2717065667 1.752241381 1.5290634005 0.83511710246 1.4997508759 0.058761159973 0.88245488975 +1.7760261059 0.88105005777 -0.20980880082 0.92114695593 1.2478859865 -0.19622928632 1.160709345 -0.072320407877 1.7147580199 +0.14716438006 1.3109835707 1.364580101 -0.065742031085 -0.13319502659 1.4753386308 1.7510680011 1.7630701317 1.6885106246 +0.19252930898 1.7647671477 1.3402293873 1.6397731148 0.059412071192 1.1182245812 1.5801065106 1.153518494 0.32667707224 +0.46868510366 1.7086126756 1.4911380186 1.5099307821 1.5725909444 1.3228454998 1.6219163347 -0.20207019269 1.6664156055 +1.6593028231 0.85875678923 -0.19730413871 1.7797228733 1.5642060423 -0.16930223944 -0.099169161663 1.7762335449 1.1201006275 +1.4500056499 1.6253104435 1.726857563 1.751182189 1.3809773122 1.2917980715 0.59532506087 1.5862897958 0.99184696139 +1.3486393699 1.7474954787 1.5221128603 0.78493676706 1.2960646974 1.4419341833 0.85653287125 1.3662841476 1.0441881958 +-0.18016928835 -0.20475698422 -0.10543701646 1.7144276012 1.0784015249 1.5093121445 1.7526881254 0.47991308086 1.7264253742 +0.62910639905 -0.013987738005 1.6733354861 0.44954290641 1.2871200426 0.43825262102 1.6573458711 -0.14643462901 -0.06595111985 +-0.060214402993 1.1539031297 0.23449919634 -0.21182334504 -0.2194473513 1.7658361312 0.11346385673 1.7773537359 0.39250713183 +1.33640112 1.7654164155 1.5888896826 0.1479612715 1.0936695093 0.45796115526 1.4129905829 1.6713763845 1.6556910075 +0.94375862638 1.1798645977 -0.17370726264 0.79099959597 1.5800746927 0.3925718247 1.1627700056 1.4423629441 -0.018698007446 +0.97416226448 0.85259345158 1.1079140113 0.61741172353 0.56323700584 -0.21371100184 1.7799924627 1.769836652 0.18928660834 +1.746657146 1.7044398628 0.41367132454 1.6143888071 0.29083223055 0.94601158286 1.484124278 1.0840783434 0.053044886223 +-0.21945886404 0.65547027567 1.6959282003 0.08633197403 -0.1340985416 -0.16418658208 1.3893429107 -0.21653476612 1.513173927 +-0.219577957 1.1330047375 0.66417559073 -0.19351311411 1.7609138517 1.4540330534 1.7771005211 -0.05949540756 1.099646929 +0.69952630528 1.1166262638 1.5574039769 1.7522390081 0.90836645018 0.71131282889 1.0787876239 0.99974360785 0.70627775668 +0.51398172789 0.65846947401 0.60814658119 1.7414642574 1.6069585856 1.1452346596 1.0787833705 1.2448661617 0.9101458861 +0.29649227999 0.099853300443 0.22034861201 0.36976196827 1.0195813924 0.86201284753 1.6618430483 1.7493524059 0.41330204906 +0.38928972709 0.32742365379 0.035538742151 0.93055328268 -0.096458409696 1.6562464134 0.34766558096 1.6945966746 0.93166768878 +1.4308377055 1.0014406217 1.6528404445 0.71292649346 -0.19309966399 1.7757371247 1.7709381189 0.2839077017 0.25001306982 +1.4268589261 0.68380165143 0.095713842342 0.34253588607 0.89974785752 1.7310224613 0.23114009191 -0.16616130426 0.9095356468 +1.1386395341 0.48073085408 0.93212247658 0.017467950727 0.50007183709 -0.18333663365 1.2227605695 -0.18169576449 0.74197616947 +1.206283569 0.037097036222 1.3390656998 0.71039729951 1.6479610951 1.0387425079 -0.2198277741 0.82009545215 1.7773139843 +0.1041425768 1.7333763034 1.5578284904 1.0821565181 0.13576461298 0.80426614915 1.4955207659 0.18449263508 1.302718915 +0.93476649283 0.41024126361 0.060437726586 1.687771325 1.6740562219 -0.20766365188 0.9008180048 1.1187946593 0.49088237729 +1.499270788 1.7375663094 0.283528099 -0.035458862219 -0.1517332479 0.71639624004 1.3302081989 0.87981429782 0.53189486731 +0.098554517074 -0.21053660903 1.3024704173 0.57644930646 1.3061098011 0.63098638154 1.6032522424 -0.037708066788 0.82146166918 +1.7677394494 1.5863612629 0.90964648751 1.2325308142 1.6342184885 1.7218369472 0.96034442989 0.32340299348 0.64287275755 +0.22478074074 -0.10633833883 1.7798226554 0.96371373949 1.3977850308 0.35109519019 0.74510614709 0.66103138179 1.5365568359 +0.63361262371 0.64265051371 0.13669659397 1.1851670467 1.1540073856 0.2593033238 0.23363137943 1.5907536076 1.2877374373 +1.5240560185 1.1030004049 1.7376011747 1.2631064023 0.56762744291 0.75663998336 0.89947942016 0.18244407932 -0.082785556023 +0.87637257235 0.05575307456 0.74451995582 1.526037049 0.44616921209 1.5467615699 0.06523740012 1.5550120927 1.5967950391 +1.3495958744 0.46258980067 1.2880025846 1.7798949598 1.5762794106 0.077279259249 0.56495160878 0.26196182619 1.5676909413 +1.0025212053 0.29862876797 1.2965378413 1.4493346596 -0.08043799089 0.41604297425 0.18646660501 1.7639055457 -0.072467864766 +0.00072005141861 -0.16090142459 1.7147913195 1.7462297365 0.24867612975 0.34607842852 1.7759750573 -0.142073909 -0.21029634045 +1.5072387666 1.5237417203 1.5759305004 1.5932547266 -0.14114945904 1.7246521699 -0.066210774914 0.24063679701 1.1903503737 +-0.087552995724 -0.031609316976 1.7795477072 1.7740164601 1.7788889828 0.13609814631 0.53041832137 1.3716194167 1.6567556365 +-0.0087622933679 1.7779749458 -0.13409162119 -0.00074993073561 0.81094714242 1.6751175347 0.61617353047 0.16090919421 0.3502656872 +1.7428041566 -0.14070148481 -0.12681315126 1.1430558779 1.7718047105 1.2452632256 1.7694412058 1.4573123334 -0.13081956001 +0.53545353699 1.5699709552 0.15329391281 0.023394312011 1.0584896759 1.655061848 1.2477815813 1.4330934421 0.61302942823 +1.5777135996 1.7144247341 1.2661207089 0.93707140352 1.6241696995 0.4770848077 -0.048979442605 1.7794189245 1.4152579926 +1.5737239143 0.25510017244 1.4545765622 0.094330550005 1.7343880459 1.7573936918 1.7756605053 -0.20645102878 1.2053078809 +1.3263997219 1.4418184518 1.4060691548 0.58849870319 1.0720570046 1.4033842722 1.7792428445 1.6198240395 1.2015456341 +0.7117140069 -0.11658963173 1.7796158947 0.1781628831 0.79364870032 -0.15968181546 0.090723617803 1.7729714169 -0.033488196031 +1.192770075 0.99352816542 1.0244704127 1.1260773233 1.3657334072 1.7590638624 1.3682427528 0.11081857225 1.4166048983 +1.7357278513 0.68551308187 -0.21514817083 0.61625839346 1.7197336944 -0.0090949506751 0.32648581014 0.45903903794 1.1053606585 +0.87154906752 9.2416546433e-05 0.64473275143 -0.18735713433 0.77330851077 1.0321013947 0.85726814405 -0.070490762357 0.19097617691 +0.14976141968 1.7465235308 0.80521064209 1.0808520389 1.7559958322 1.4170120271 -0.10550132162 -0.0096466360926 0.8186665014 +1.7077710465 1.7799974095 -0.19350706397 1.0695020027 0.7748168017 -0.056094820155 0.36288947295 0.84858463321 -0.016079908619 +0.51283254531 1.4877126265 0.25863904024 1.6932106892 -0.21919366408 1.6205433846 1.2423235305 0.34148275586 1.4571581973 +1.1685506253 1.1730517928 0.9809212897 1.7532594897 1.3347569547 1.2212235061 1.5371842919 0.24193669368 0.93328337387 +1.3994583882 0.77419828634 1.7798377479 1.5245449151 0.52920567812 1.2353803019 1.7731954568 1.7371472496 0.49777192511 +1.6973440473 1.0256847699 1.6835227091 0.328506047 1.3751769123 1.056254107 1.0383299979 1.2755850847 1.4795294067 +1.2419639059 0.99932434005 1.4315324861 1.7653358552 0.69024060822 -0.030892503812 1.6221322231 1.4390055679 0.06163491324 +1.6713710707 -0.21497647152 -0.13622944566 1.7293775068 1.766780445 0.62056515533 1.6693449485 1.3696777981 -0.15050319585 +0.7151981309 0.84361238433 0.94147313788 0.94624060884 1.0110603803 0.84545190958 1.060093109 1.7700495588 1.657001778 +1.6598092445 1.7516640239 1.276730816 1.6849860686 1.7081902191 0.25685392257 0.77394966629 1.4686012074 -0.18993230502 +1.7161980261 1.6560552843 1.4228120232 -0.080895628618 1.6198850142 0.28264359764 1.5850770935 1.0139210254 0.057765613119 +0.81521913062 1.5140852782 1.7403806388 0.76003793956 0.17539888465 1.6033797067 0.39906155972 0.28164773477 0.75182180961 +-0.067221879635 1.7561255295 -0.21885829242 1.0148287978 0.42608734795 1.5056817464 0.49982629198 0.38216226964 0.3965788163 +0.14397488604 1.1379179908 0.34178599192 1.4937687899 0.11097498337 1.4878199345 0.80904494772 1.7774504825 0.30683382295 +1.5339162469 0.19365679465 1.2439329782 1.5692316513 1.0763534987 -0.083348023385 0.10795128236 0.82322957373 0.10207370606 +1.3399538941 1.3365892205 1.6748428264 0.54416253222 0.33256959622 -0.19426800255 1.7797861632 -0.020260005876 0.43899904265 +1.7557583022 0.63271448413 1.6807417682 0.45207560574 1.7662997759 0.75734556578 1.7321350967 -0.20063316559 1.7700703158 +0.22090050823 1.7296522896 1.6531031752 1.2405260048 -0.040934078011 0.54107646093 1.6348782951 1.5387387499 1.6283412027 +0.5371164482 -0.16695845887 0.7950747156 1.7453310929 -0.16520359857 1.4671741846 1.1577136778 0.139011402 0.020665972951 +1.7424471153 1.7797676972 1.4219688382 1.5288704804 -0.21315469922 1.0383395998 1.3041646905 0.31812591674 0.56422563529 +0.58952441512 1.1356891128 0.68969681712 0.07763245414 1.4977503379 1.1602606827 0.41621202855 -0.17049948489 -0.13948651298 +-0.16443558752 -0.21482415793 0.023894517482 0.57240670881 1.777097887 -0.19229023419 0.096581964774 1.6769548491 1.7047288305 +1.75082118 1.7728452925 1.7534803329 1.7338903245 1.7760529283 1.7237704616 -0.043851938397 0.26327628304 -0.19679819295 +0.995327842 1.7753007463 1.6256608051 1.4046572839 1.335100831 1.4516685395 0.48345344425 0.5508903146 1.4731959047 +1.084102237 -0.21999923867 0.84001086751 -0.09893894076 0.094433932585 1.1842070692 0.012238900704 1.7706934746 0.31598877871 +-0.036872546131 -0.20689376962 1.7732867066 -0.17784263079 1.3590673073 1.2909452452 -0.21916750595 1.7042686117 1.6856572097 +1.6423210792 1.6573586331 0.0094001769094 -0.10893884756 1.6426796715 1.5845389914 1.5363097641 0.63170702081 0.85709597317 +1.7115166716 1.6298933247 -0.17754509637 1.7076806529 0.16340541404 0.31348291541 1.7791189052 0.48317015431 1.1100087924 +1.47149867 -0.2160678648 -0.18174182671 -0.052159837881 -0.11608144841 -0.19231869779 0.059376663176 -0.18480888019 -0.21263483449 +0.040946289997 -0.14944523205 0.30475360237 -0.086757638735 0.33258002712 0.16484621606 -0.21260634945 -0.21775611087 -0.21682524633 +-0.062259781381 -0.17165962796 -0.16088257355 0.02282615391 -0.21571923183 0.413947393 -0.10454343827 0.23938928367 0.044921583108 +-0.050698198645 -0.15645532786 -0.025434252165 -0.20863934053 -0.15957881981 0.16423440245 -0.10069743359 0.22439780456 0.5616988141 +0.218161985 -0.19508366293 -0.21861877676 -0.048278863341 -0.18842449065 -0.20366909396 -0.13740466753 -0.21933646785 -0.090262069251 +-0.21999532029 0.034671405243 -0.21938378337 0.47687820615 -0.092976229494 0.0825869318 0.19042032614 0.17886799075 -0.21319132159 +-0.12678978191 -0.20136479543 0.39461620417 0.0563627531 -0.076156533506 -0.14574515008 -0.20717620792 -0.07094124419 0.049218648487 +-0.16481923138 -0.18386787659 -0.024856908547 -0.21530465942 0.41454667343 0.65398429297 -0.17021241756 0.38285413189 -0.050671476868 +0.14981668474 -0.15204805895 -0.078486110846 -0.20174074329 -0.18378789393 0.36313425664 -0.19139433749 -0.019170230121 -0.15604288511 +-0.21776847795 0.013076728993 -0.21896664543 -0.07304501455 0.23173906336 -0.21779132987 0.050116741514 -0.086361642069 -0.21275415313 +-0.21170506856 0.52851884393 -0.10195595647 -0.14309185893 -0.068585861561 -0.14311815875 0.079872647417 -0.030451876781 -0.17735349689 +0.4419437623 0.30352279761 0.058445339757 -0.14717186161 0.07592616585 -0.12890118352 -0.15938137484 -0.1718277248 -0.15791450354 +-0.15518191223 -0.21537071803 -0.11080288077 0.21673316524 0.28136134296 0.38505908832 0.54553316717 0.23730325776 -0.058553837781 +-0.20172573751 0.17061231996 -0.075406075797 0.59895863124 0.10772862789 -0.21827427889 0.056154089849 -0.21805222132 0.14078742016 +0.27791858113 0.14447718976 -0.19885288494 -0.21785383268 -0.1620997136 0.53623097647 -0.026100597038 -0.21743381052 -0.19652836217 +-0.074814669584 0.68457559399 -0.1398389521 0.24073312173 -0.13603558621 -0.079357484839 -0.11387004734 -0.19078902675 0.36235252491 +-0.18539515904 0.032023731856 -0.10214340094 -0.15739803913 -0.21668554193 -0.21747057774 -0.21998441815 -0.21033890684 0.40111161417 +0.43869870256 -0.19634120413 -0.0013135909185 -0.074995383961 -0.029918044065 -0.10208969419 -0.19208870847 -0.031117450413 -0.13542353995 +-0.21190750166 0.22450315158 -0.19355102068 0.33122974363 -0.15832124621 0.041866903466 -0.043595968785 0.11587064155 0.26922240138 +0.10677399097 -0.052314379642 -0.10299563825 0.12430052801 -0.040381450646 -0.20908668293 -0.1220073794 0.19090731185 0.48055271538 +-0.019784793036 -0.18564395885 0.095471826739 0.49577306496 -0.2103691024 0.0060457188508 -0.017469060186 0.12969115903 -0.19952678573 +0.28177792275 -0.20534968116 -0.21132727221 0.010843977344 -0.20464691959 0.63674154885 -0.12803495949 -0.13108760542 0.12724772373 +-0.023122697487 0.15141200712 -0.21936177242 -0.16973077451 -0.12734033363 -0.028920630698 -0.21802666523 0.090187772396 -0.014856184219 +0.1210449594 -0.21963564928 0.19031710572 -0.18213849948 -0.089851373086 -0.21994563622 0.57081625661 -0.16047780729 -0.17172158816 +0.33246611322 -0.21160306946 -0.21497991472 -0.19469050008 -0.028752045778 0.13523528849 0.078224690419 0.54450603042 -0.21948052647 +-0.13449587726 -0.1286692459 0.22832434096 0.027252419746 -0.093220134025 -0.20746634716 -0.2108421016 0.47662046901 0.012578199377 +0.79960150083 0.0084577369193 -0.21050901873 0.67326052585 -0.1755100305 0.2582360687 -0.18188485289 -0.21721415178 -0.098327907387 +-0.017770342386 -0.20283042538 -0.12424557694 0.0020763413087 0.10659347773 -0.21189999468 0.026146071867 -0.19792141358 0.06188278123 +-0.0017677228345 -0.07232122105 -0.21723927036 -0.10650000268 0.35881612447 -0.19976690018 -0.11070294536 -0.063301867092 -0.12408569247 +-0.14664163363 -0.010068111517 -0.17693529423 0.52271080456 -0.2061651097 0.11558540774 -0.1480714442 -0.21734071485 0.1679341964 +-0.13447107874 0.68768446449 -0.21995328359 -0.040395985532 -0.19676497357 0.37786269741 0.077095632981 0.52767635343 -0.17942231304 +-0.15787660544 0.26333706312 0.36470681425 0.20983614231 -0.024425886009 -0.18539014654 -0.17274005076 -0.20322739797 -0.072621585884 +-0.18709465569 -0.094075431658 -0.16784958648 -0.18295715776 0.68227375454 0.37320477815 -0.18294197982 -0.10030235045 -0.21993741591 +0.35616354122 -0.20955669638 0.48872222058 -0.21914070853 -0.20192215143 -0.21851708466 0.58920952116 0.0184927582 -0.21967437886 +-0.094666614369 0.22330496164 -0.12166670548 -0.21830697851 0.023039612579 0.30890546003 -0.18057378222 0.21055438782 -0.10063864726 +-0.14082441911 -0.025701558184 -0.19215558357 0.14123558075 -0.17366554203 0.037569925211 0.25813667382 -0.059449578892 -0.085057000628 +-0.075506651055 -0.11773480004 -0.21687675943 -0.0080833440881 0.008859270033 0.26111956275 -0.058125046508 -0.21476985122 0.0016526432137 +-0.12031435055 -0.21183120358 0.36442161778 -0.16574546164 -0.21770198442 -0.016836686274 -0.069079127938 -0.10791648032 -0.21987779658 +0.28561031371 -0.21994407711 0.027353704261 0.35375291235 0.29149225537 -0.059069363728 -0.2178370487 -0.05754991439 -0.1489440685 +-0.2194401514 -0.19482987542 -0.1835913425 0.092257793029 -0.091482062376 0.040708976317 0.41071097022 -0.12567429493 0.079064453919 +-0.13048545753 -0.20750446878 0.52155288716 -0.049215082615 0.23598600454 0.31600562611 0.38112271964 0.44702496189 0.022421452024 +0.15361191795 -0.030266183824 -0.14621168979 0.10315835503 -0.17179759323 0.31268578033 0.21819543717 -0.023601650384 -0.19675501541 +0.023700105878 -0.2057068343 -0.18206862152 0.12547710369 0.42851258872 0.7530645186 -0.21932592041 0.21595419072 -0.21999376999 +-0.16283473844 0.46029035215 -0.14270303613 -0.21419538645 0.037796358287 -0.07458194502 0.1762583829 -0.12565293658 0.20381413209 +-0.029142426969 0.20311309263 0.5233043934 0.79932662876 -0.11742621911 -0.11512924462 -0.20709222738 0.7884183211 0.26583527586 +-0.12312425904 -0.21883663604 0.49354260372 -0.21993231861 -0.21248640088 -0.2134260935 0.5010868184 -0.038323633883 0.055131388807 +0.12193176078 -0.21781060608 -0.2167021895 -0.1144954997 0.2026642073 0.06455878366 -0.086372164328 0.14656706467 -0.16546561005 +-0.18998599668 0.42765998509 0.74981256569 0.023498011478 -0.024330578265 -0.15044873215 -0.20697463176 0.25679044595 0.93522907709 +0.94475282733 -0.21079132692 -0.20299912935 0.0077263285971 0.089072697291 -0.0067783975398 0.6185983847 0.66617435091 0.35596569174 +0.30461621439 -0.094815429603 0.082398032348 -0.20716471588 -0.17350993504 -0.21767146975 0.14269887555 0.22684549211 -0.18166772827 +-0.17368497499 -0.15930267308 0.27788123414 0.48051065685 0.59627817998 -0.080917709148 0.40624082224 -0.095505146338 -0.15926836384 +0.30971917613 0.66512553778 -0.012463943741 -0.2168075545 -0.17104331731 0.41453957019 0.38922580923 0.029243937482 -0.085801114852 +-0.04592760674 -0.19564587077 0.9439951103 -0.19768768349 0.18296777764 -0.18302602999 -0.20272861891 0.072768032998 0.32488464179 +-0.082618257523 -0.10475450304 -0.17220169062 -0.17455765172 0.014323764606 -0.044211875491 0.52968147469 1.0046398837 -0.16928039585 +-0.21134043834 -0.21397161429 0.05852798268 0.77710928449 0.12532904247 -0.20996486964 -0.1962851867 -0.027340013519 0.090331916264 +0.17073351706 -0.087159909856 -0.21993742205 -0.21730329457 -0.1826172619 0.27562928974 -0.21913510701 0.020658467865 0.11212052706 +-0.0076733688104 0.12460676756 -0.13660949888 -0.19717793713 0.64490999311 0.016963221753 0.2737119916 0.65638089678 -0.2198618601 +0.34913876149 -0.16423276189 0.53104972182 0.15730369856 -0.083595811248 0.20471874705 -0.1088371448 -0.15158215888 -0.10201359153 +0.61775303729 -0.20439063366 0.59207640752 0.40293866625 -0.21773543349 0.21283620102 0.44987853711 -0.14759586957 -0.14933307706 +0.16281311731 0.25315823689 -0.070875581042 0.96215817669 -0.063847047837 -0.21457228517 -0.21323421047 0.87265492998 0.54798382243 +0.42857615977 0.38478792598 -0.20141420689 0.75742391305 -0.17055584907 0.34080372141 0.12938359405 0.099569803066 0.00031411212961 +-0.051683727529 0.72113556831 -0.19359723397 0.30100585022 0.28980310423 0.094538514352 -0.21937018327 -0.21680345631 -0.21816575668 +0.27190617425 -0.14483519582 1.0242641232 0.085152485986 -0.16411412036 0.90419742488 0.054108593849 -0.096947676022 -0.066838148324 +-0.20069294557 0.047701071758 -0.015866950944 -0.18542851922 0.49848385747 0.099743278183 0.17759917272 0.30395047831 1.050683066 +-0.13669529607 -0.21951263577 -0.0065840191222 0.33740754938 0.2805877623 -0.11670226899 0.84441234282 1.0539730856 -0.21291722912 +-0.078308711221 0.76268327596 0.59501824109 0.51041468415 0.54217500543 -0.17855002944 -0.18819346279 -0.19523800905 0.13259625664 +-0.05028136856 0.674997199 0.0077400723165 0.48125931197 -0.13420014069 0.79541293827 0.42022550309 -0.17818666471 -0.21562385023 +-0.097754777612 -0.065790936516 0.46161202283 -0.20497518982 -0.1332085152 0.39935439944 0.62972585131 -0.1992811513 0.29224377845 +-0.12389144808 0.031464561006 -0.19566126181 0.86569003287 0.96887959975 0.28828597723 -0.035890927104 -0.21624688501 -0.13695132774 +0.50697820068 -0.20845939489 -0.17093818277 -0.19743987 0.44866674704 0.093727458579 -0.21073674742 0.31277529066 0.40834585662 +-0.11651463907 0.6998507791 0.1697886845 0.09840887375 -0.03996086032 -0.21735377189 -0.15704290833 0.39551415367 -0.0039209729235 +0.0065791910072 0.97563532121 -0.19783755132 0.40050982112 -0.17120614694 0.13870940094 0.65007033361 -0.032360908858 0.51177747604 +-0.12902704977 0.14394527798 -0.21948165162 -0.028977571211 0.56198778522 -0.12991127902 0.33938210657 0.13755527067 -0.20994354271 +-0.0619730642 0.57421148889 -0.12205314647 0.37279610257 -0.001973444181 0.19530729553 -0.19381356095 0.10106097153 -0.1400393967 +0.1999575772 0.67737914099 0.0037684744224 -0.21940706755 0.89974010408 0.5407618403 -0.12717333379 0.067694677453 -0.026342903142 +-0.17568550283 0.15037700542 -0.19316333014 -0.19557307149 -0.21996343847 -0.16649366963 -0.12979028441 0.20192501304 0.57201946284 +-0.16662404154 0.23202340884 -0.14259572754 -0.21793655579 0.25813705897 -0.2068858078 0.053270163027 0.84572828734 -0.21896535619 +-0.11848100196 0.84024191357 -0.2134933998 -0.04725263389 -0.21597242562 -0.19744151075 -0.21835825561 0.038907304685 0.025553628605 +0.39972997623 -0.18070038733 -0.085700913572 -0.19387929177 -0.21991763785 0.68928116469 -0.087420269467 -0.19820056816 -0.088623867737 +-0.2128957919 0.0629610285 -0.21489154293 0.69500140521 0.39853489311 -0.085265054184 0.95842280703 -0.044895966525 0.010259042094 +0.31980405248 0.50282115617 -0.21390116304 -0.21723258321 0.1245041787 -0.20348380634 -0.14904657371 -0.086918308848 0.38117224594 +1.0378917636 0.7493126584 0.097906044404 0.024686848861 -0.0062889509399 0.061267199471 -0.066692322821 0.095275963644 -0.041411343564 +-0.18474167398 -0.19791447284 0.22306767661 -0.19739319286 0.244532783 0.005070416052 0.20842480131 -0.15404006053 -0.088765629401 +0.20477912245 -0.1747428203 0.21316991374 -0.2199928277 -0.18019325553 -0.077754440583 0.60975740473 0.030680850177 0.10659976713 +0.10436011765 -0.19471404395 1.0886245569 -0.14359722368 -0.21724302107 -0.19844214629 0.0045363296545 0.3312523384 -0.21934442133 +0.08022196781 -0.15542240172 -0.20237625284 -0.21878394256 1.0423585602 0.17679592852 0.88217360282 -0.20354323236 0.29096576896 +-0.20700764571 0.55562366351 -0.1281102006 0.13774039598 -0.15832572146 -0.0082420494568 0.2107003863 0.71031175273 0.19489893955 +0.85402838203 -0.17285103632 0.74691218289 0.66309887613 0.37491224778 0.30841666101 -0.2196659276 1.0887572799 1.5201330498 +1.506866141 1.2492483061 0.64392299629 1.0427047416 1.3679372928 1.6337429783 1.3638115134 0.95487787268 1.640911964 +1.3341168575 0.75173680524 1.4982269221 1.3120591845 1.4456703687 1.5496556095 1.0583567537 1.2304963813 1.6608732987 +0.39241934082 0.99078414031 1.2677560557 0.69162207487 1.6895795502 1.297785376 1.1887274218 1.6387435865 1.1633057461 +0.8844951557 1.6092971799 1.429067185 0.53363306785 0.79333390909 1.3772354617 1.555588336 1.5510490839 1.1438035838 +1.3106965905 1.4181923858 0.88444655351 1.5480586305 1.4818417446 0.82644181059 1.2211203954 1.6897018178 0.94356669832 +1.4647872955 0.51289637218 1.1831783155 1.7019604385 1.2486296216 1.3221070154 1.128329585 1.4191391289 1.5822010606 +1.2746075664 1.5978289181 0.41561980316 0.84722693425 1.4290418767 0.65651876266 1.4735555197 0.72647977071 1.5650714446 +1.3417808708 1.0644737384 1.634007317 1.4043191394 0.71686121389 1.2287387153 1.7137185907 1.3949601758 1.4972971855 +1.201215677 1.234496149 1.5696171303 1.1827038557 1.5136464335 1.0259681512 1.4941941868 0.74126329156 1.1569940282 +1.3692613629 1.6501168822 1.3707103212 1.4001118508 0.5542639644 1.7199907384 1.2272805508 1.314859149 0.58686973209 +0.98634154465 0.27296819036 1.6717451647 1.1337851063 1.5737755102 0.95159426711 1.6287071048 1.3137327827 0.94543677644 +0.49653968284 1.5712005089 1.1849108649 1.0277668473 1.6814104914 1.2969679296 1.4598163342 1.3847806411 0.85662439197 +1.1248412231 1.6827259106 1.4692296602 0.99380186224 0.89533380142 1.4131260604 1.2589766957 0.85970045259 1.6474377434 +1.3671847113 0.79500131902 1.6053285956 0.60575102877 1.1340330147 1.3161379212 1.6724048678 1.2741623963 1.637153726 +1.1122685329 0.37744174204 1.7023197883 1.1886949687 1.6299193024 1.1936032332 0.89786902084 0.32597258955 1.3998193298 +0.45365794261 0.72033040243 1.3196825186 1.5264998156 1.2855833734 1.0073435634 1.5639893664 1.6031260812 1.0532937777 +1.4228692575 0.95849441517 0.63795548685 1.4327902794 0.60370667369 1.5945312249 1.5397916055 0.80401626948 1.0630314456 +0.49545043184 1.6702308589 1.2800150998 0.85443131312 1.5088315235 1.5146511292 1.1346590679 1.2443253987 1.3888615476 +1.1950238119 1.5530205563 1.2035655176 1.5319512956 1.6318476534 1.3739548327 1.369216393 1.0440920074 1.6517857002 +1.2072916406 1.658163878 1.5133157538 1.222135959 1.3581799069 1.4231376034 1.520350106 1.2428702623 1.0178157656 +1.5044062049 0.99411558047 1.6344608241 1.4966713078 1.3188322198 1.0301077486 1.616171492 1.0639004691 1.6906163682 +1.2985132371 1.694155533 1.4298639508 1.2754805207 1.5695918806 1.3146979329 0.91878146884 1.4349635804 1.1490441769 +1.4266149886 0.93060946745 1.4709433172 1.5917298841 1.2939274231 1.1325626547 1.6744797636 1.5838923439 1.6608700472 +1.1054163417 1.2670805584 1.5022744706 1.5666642509 0.95922678642 0.977749964 1.1362736448 1.2203507846 0.91603176496 +1.6159607704 1.5596527133 1.6996940632 1.5289979623 1.6921669413 1.1749886487 1.4404760186 1.3154613055 1.6040152873 +1.1724727671 1.412255004 1.5028023512 0.90199838935 1.7195428518 1.364231313 1.5657305707 1.3666951307 1.2842746014 +1.6249380954 1.173353261 1.0945018898 1.4733808455 1.5333603701 1.0820481704 1.646431429 1.4486097581 1.4524372855 +1.0526078653 1.2369870533 diff --git a/examples/lci_2d/clean.sh b/examples/lci_2d/clean.sh new file mode 100755 index 00000000..9865414a --- /dev/null +++ b/examples/lci_2d/clean.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -e -x + +rm -f -r precice-run +rm -f precice-*-events*.json +rm -f *.log +rm -f map*.vtk +rm -f fine_mesh_*.vtk +rm -f precice-*.json diff --git a/examples/lci_2d/coarse_mesh.vtk b/examples/lci_2d/coarse_mesh.vtk new file mode 100644 index 00000000..029c86ff Binary files /dev/null and b/examples/lci_2d/coarse_mesh.vtk differ diff --git a/examples/lci_2d/fine_mesh.vtk b/examples/lci_2d/fine_mesh.vtk new file mode 100644 index 00000000..4e3c86d2 Binary files /dev/null and b/examples/lci_2d/fine_mesh.vtk differ diff --git a/examples/lci_2d/precice-config.xml b/examples/lci_2d/precice-config.xml new file mode 100644 index 00000000..683022c4 --- /dev/null +++ b/examples/lci_2d/precice-config.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/lci_2d/run.sh b/examples/lci_2d/run.sh new file mode 100755 index 00000000..7220b687 --- /dev/null +++ b/examples/lci_2d/run.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -e -x + +# Calculate franke function on fine mesh +precice-aste-evaluate -m ./fine_mesh.vtk -f "franke2d(xy)" -d "Franke Function" -o "fine_mesh_lci.vtk" + +# Map from the finer mesh to coarser mesh +precice-aste-run -v -p A --mesh fine_mesh_lci --data "Franke Function" & +precice-aste-run -v -p B --mesh ./coarse_mesh --output map_nn --data "InterpolatedData" + +# Calculate statistics +precice-aste-evaluate -m map_nn.vtk -f "franke2d(xy)" -d difference --diffdata "InterpolatedData" --diff diff --git a/examples/lci_3d/clean.sh b/examples/lci_3d/clean.sh new file mode 100755 index 00000000..eb71aca8 --- /dev/null +++ b/examples/lci_3d/clean.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -e -x + +rm -f -r precice-run +rm -f precice-*-events*.json +rm -f *.log +rm -f map*.vtk +rm -f fine_mesh_*.vtk diff --git a/examples/lci_3d/coarse_mesh.vtk b/examples/lci_3d/coarse_mesh.vtk new file mode 100644 index 00000000..8385446f Binary files /dev/null and b/examples/lci_3d/coarse_mesh.vtk differ diff --git a/examples/lci_3d/fine_mesh.vtk b/examples/lci_3d/fine_mesh.vtk new file mode 100644 index 00000000..98706ed7 Binary files /dev/null and b/examples/lci_3d/fine_mesh.vtk differ diff --git a/examples/lci_3d/precice-config.xml b/examples/lci_3d/precice-config.xml new file mode 100644 index 00000000..2ab5e86c --- /dev/null +++ b/examples/lci_3d/precice-config.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/lci_3d/run.sh b/examples/lci_3d/run.sh new file mode 100755 index 00000000..ac3057da --- /dev/null +++ b/examples/lci_3d/run.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -e -x + +# Calculate franke function on fine mesh +precice-aste-evaluate -m ./fine_mesh.vtk -f "franke3d" -d "Franke Function" -o "fine_mesh_lci.vtk" + +# Map from the finer mesh to coarser mesh +precice-aste-run -v -p A --mesh fine_mesh_lci --data "Franke Function" & +precice-aste-run -v -p B --mesh ./coarse_mesh --output map_nn --data "InterpolatedData" + +# Calculate statistics +precice-aste-evaluate -m map_nn.vtk -f "franke3d" -d difference --diffdata "InterpolatedData" --diff diff --git a/examples/mapping_tester/.gitignore b/examples/mapping_tester/.gitignore new file mode 100644 index 00000000..67cd9b98 --- /dev/null +++ b/examples/mapping_tester/.gitignore @@ -0,0 +1,2 @@ +case/ +test-statistics.csv diff --git a/examples/mapping_tester/clean.sh b/examples/mapping_tester/clean.sh new file mode 100755 index 00000000..5e2369c5 --- /dev/null +++ b/examples/mapping_tester/clean.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +rm -f test-statistics.csv +rm -fr ./case/ diff --git a/examples/mapping_tester/coarse_mesh.vtk b/examples/mapping_tester/coarse_mesh.vtk new file mode 100644 index 00000000..8a7974cd --- /dev/null +++ b/examples/mapping_tester/coarse_mesh.vtk @@ -0,0 +1,2194 @@ +# vtk DataFile Version 4.2 +vtk output +ASCII +DATASET UNSTRUCTURED_GRID +POINTS 438 float +0.000159205 0.0459595 1e-07 0.0910679 0.0459595 1e-07 0.000159205 0.0459595 0.0909088 +0.00016037 0.0462879 0.0909088 0.0910679 0.0459595 0.0909088 0.00387147 0.0486486 0.999996 +0.000160265 0.0467696 0.999996 0.00230119 0.0432031 0.999996 0.0412046 0.0349339 0.999996 +0.000161941 0.0467691 0.272726 0.000140272 0.0463638 0.272726 0.0114969 0.0345959 0.272726 +0.170587 0.0345959 0.272726 0.013112 0.0572077 0.272726 0.00884021 0.0726769 1e-07 +0.0315674 0.0891891 1e-07 0.0596597 0.0891891 1e-07 0.0823869 0.0726769 1e-07 +0.000159205 0.0459595 0.0227273 0.000159205 0.0459595 0.0454544 0.000159205 0.0459595 0.0681816 +0.000159502 0.0461237 0.0909088 0.00899528 0.072889 0.0909088 0.031755 0.0892496 0.0909088 +0.0597846 0.0891483 0.0909088 0.0824255 0.0726237 0.0909088 0.0910679 0.0459595 0.0227273 +0.0910679 0.0459595 0.0454544 0.0910679 0.0459595 0.0681816 0.00160779 0.0485161 0.999996 +0.000455632 0.0445206 0.999996 0.0217529 0.0390685 0.999996 0.022538 0.0417913 0.999996 +0.000149524 0.0465665 0.272726 0.00331992 0.0380684 0.272726 0.0380119 0.0345959 0.272726 +0.064527 0.0345959 0.272726 0.091042 0.0345959 0.272726 0.117557 0.0345959 0.272726 +0.144072 0.0345959 0.272726 0.165412 0.0346094 0.301817 0.160237 0.0346229 0.330908 +0.155061 0.0346364 0.359999 0.149886 0.03465 0.389089 0.144711 0.0346635 0.41818 +0.139535 0.034677 0.447271 0.13436 0.0346905 0.476362 0.129185 0.0347041 0.505452 +0.124009 0.0347176 0.534543 0.118834 0.0347311 0.563634 0.113659 0.0347446 0.592725 +0.108484 0.0347581 0.621816 0.103308 0.0347717 0.650906 0.0981329 0.0347852 0.679997 +0.0929576 0.0347987 0.709088 0.0877823 0.0348122 0.738179 0.082607 0.0348258 0.76727 +0.0774317 0.0348393 0.79636 0.0722564 0.0348528 0.825451 0.0670811 0.0348663 0.854542 +0.0619058 0.0348798 0.883633 0.0567305 0.0348934 0.912723 0.0515552 0.0349069 0.941814 +0.0463799 0.0349204 0.970905 0.000161649 0.0467691 0.301817 0.000161591 0.0467691 0.330908 +0.000161533 0.0467692 0.359999 0.000161476 0.0467692 0.389089 0.000161418 0.0467692 0.41818 +0.00016136 0.0467692 0.447271 0.000161303 0.0467693 0.476362 0.000161245 0.0467693 0.505452 +0.000161187 0.0467693 0.534543 0.00016113 0.0467693 0.563634 0.000161072 0.0467693 0.592725 +0.000161014 0.0467694 0.621816 0.000160957 0.0467694 0.650906 0.000160899 0.0467694 0.679997 +0.000160841 0.0467694 0.709088 0.000160784 0.0467694 0.738179 0.000160726 0.0467695 0.76727 +0.000160668 0.0467695 0.79636 0.000160611 0.0467695 0.825451 0.000160553 0.0467695 0.854542 +0.000160496 0.0467695 0.883633 0.000160438 0.0467696 0.912723 0.00016038 0.0467696 0.941814 +0.000160323 0.0467696 0.970905 0.144341 0.0383645 0.272726 0.118095 0.0421331 0.272726 +0.0918496 0.0459018 0.272726 0.0656037 0.0496704 0.272726 0.0393579 0.053439 0.272726 +0.00436536 0.0548066 0.272726 0.180351 0.0355659 0.247124 0.182875 0.0368583 0.219969 +0.173208 0.0384602 0.194627 0.154249 0.0400661 0.174948 0.132548 0.0415865 0.158194 +0.11193 0.0430953 0.140165 0.0966293 0.0446053 0.117586 0.000150027 0.0463529 0.246752 +0.000156511 0.0463421 0.220778 0.000160309 0.0463312 0.194804 0.000162009 0.0463204 0.168831 +0.000162195 0.0463096 0.142857 0.000161453 0.0462987 0.116883 0.0823869 0.0192421 0.0909088 +0.0596597 0.0027298 0.0909088 0.0315674 0.0027298 0.0909088 0.00884021 0.0192421 0.0909088 +0.0823869 0.0192421 1e-07 0.0596597 0.0027298 1e-07 0.0315674 0.0027298 1e-07 +0.00884021 0.0192421 1e-07 0.022007 0.0848031 0.0454914 0.0692455 0.0847877 0.0454214 +0.0452949 0.0914127 0.0271469 0.0459833 0.0914123 0.0637238 0.00531043 0.0669774 0.035351 +0.085921 0.0669692 0.0555544 0.00700601 0.0699502 0.0640866 0.0842291 0.0699374 0.0268326 +0.0163605 0.0807496 0.0206193 0.0748968 0.0807242 0.070268 0.0236776 0.0857704 0.0689787 +0.0675852 0.0857507 0.0219677 0.00230989 0.0597758 0.0793263 0.00327545 0.0624998 0.0154839 +0.0879556 0.0624896 0.0754086 0.0890093 0.0594839 0.0113637 0.0803777 0.0351106 0.353367 +0.0688654 0.0356498 0.428232 0.0618082 0.0361449 0.498045 0.057824 0.0364874 0.549321 +0.0527641 0.0368941 0.608927 0.0474462 0.0373114 0.668037 0.041951 0.0350394 0.319395 +0.115569 0.0347948 0.323253 0.0414538 0.0356544 0.386673 0.100612 0.035131 0.393609 +0.0431123 0.0376702 0.723615 0.0912257 0.0354629 0.465921 0.0373999 0.0363523 0.461155 +0.0399376 0.0379288 0.773704 0.0782444 0.0348457 0.309233 0.0827898 0.0357801 0.536735 +0.0353389 0.037002 0.535231 0.116822 0.034889 0.356267 0.0343723 0.038372 0.820141 +0.0247109 0.0349224 0.302868 0.106022 0.035165 0.432543 0.0767264 0.0360101 0.593702 +0.0292875 0.0376123 0.589863 0.033274 0.0360396 0.419407 0.032237 0.038499 0.865279 +0.0231959 0.0354815 0.354422 0.100408 0.0353344 0.501298 0.0707996 0.0362194 0.650396 +0.0271837 0.0368435 0.494902 0.0258598 0.0385388 0.695679 0.0227554 0.038307 0.644748 +0.0270534 0.0390052 0.897763 0.0520988 0.0348122 0.297217 0.0745022 0.0353256 0.38263 +0.0858047 0.0357151 0.566139 0.0636054 0.0364942 0.700337 0.057738 0.036706 0.750517 +0.135076 0.0346796 0.304008 0.0240181 0.0389874 0.749708 0.0266937 0.0374517 0.560793 +0.00520328 0.0365679 0.283682 0.0247755 0.0391872 0.928249 0.103278 0.0347228 0.297726 +0.0654269 0.0358589 0.456729 0.0787566 0.0359195 0.623583 0.010981 0.0413636 0.984008 +0.0220582 0.0394376 0.958114 0.0544334 0.0353446 0.362264 0.0207287 0.0396925 0.840616 +0.0469618 0.0370862 0.841938 0.134641 0.0347456 0.336506 0.024711 0.0380005 0.617361 +0.0655712 0.0350455 0.331397 0.0179275 0.036001 0.398455 0.0738162 0.0360257 0.675672 +0.0597173 0.0363206 0.523982 0.112552 0.0350935 0.459507 0.021603 0.0385671 0.670112 +0.124493 0.0348831 0.383215 0.0913972 0.0349248 0.330381 0.0196008 0.0351718 0.32427 +0.0521036 0.0369097 0.79781 0.0609679 0.0355978 0.404549 0.0969276 0.0350879 0.372729 +0.120565 0.0349548 0.412445 0.0305509 0.0375729 0.983062 0.0178061 0.0392036 0.723548 +0.0216662 0.0394111 0.795517 0.0669643 0.0362186 0.724914 0.110725 0.0351256 0.482101 +0.0881811 0.0353428 0.414886 0.014853 0.0358015 0.377935 0.0465145 0.0360522 0.441799 +0.0551325 0.0366904 0.577781 0.0255271 0.0347315 0.285274 0.10336 0.0352323 0.544966 +0.085905 0.0354838 0.444305 0.0621691 0.0362316 0.779021 0.103163 0.035265 0.523838 +0.0203007 0.0364789 0.445842 0.0538326 0.0361942 0.479055 0.0777991 0.0347073 0.288636 +0.079875 0.0357274 0.485739 0.043671 0.0366043 0.508859 0.0174199 0.0368218 0.473796 +0.0185178 0.0372885 0.520727 0.0438032 0.0352217 0.340119 0.0942524 0.0353614 0.609188 +0.049849 0.0371042 0.635925 0.0787546 0.0358268 0.511465 0.0122279 0.0380547 0.577311 +0.017916 0.0395815 0.774958 0.0101214 0.035045 0.307017 0.041936 0.0372363 0.886515 +0.017373 0.0375191 0.540471 0.0816625 0.0458101 0.353933 0.0697337 0.046166 0.4284 +0.062726 0.0458882 0.498198 0.058729 0.0454984 0.549459 0.0536661 0.0451134 0.609058 +0.0482 0.0448116 0.668397 0.0432737 0.0521325 0.319382 0.114666 0.041603 0.320426 +0.101127 0.0420205 0.393683 0.0420568 0.0512124 0.386874 0.0437448 0.0443789 0.724949 +0.0917926 0.0418477 0.466012 0.0385843 0.0505074 0.461387 0.0407709 0.0438022 0.773842 +0.079086 0.0470538 0.309259 0.08336 0.0415696 0.536821 0.0365677 0.049561 0.535369 +0.123324 0.0394605 0.358102 0.0353155 0.0438426 0.820179 0.0261384 0.0548969 0.302877 +0.106451 0.0402958 0.432595 0.0772781 0.04122 0.593782 0.0305752 0.0496414 0.59002 +0.0345075 0.0518446 0.419586 0.0330432 0.0431502 0.865423 0.0246783 0.0543504 0.35468 +0.100801 0.039521 0.501361 0.0713252 0.040838 0.650479 0.0286014 0.0515726 0.495145 +0.0238126 0.049925 0.644902 0.0279889 0.0435541 0.897751 0.0532187 0.0510424 0.297179 +0.0759499 0.0461089 0.382625 0.0862777 0.0403341 0.566207 0.0641386 0.0408717 0.700437 +0.0582896 0.0406382 0.750749 0.0263164 0.0484936 0.697737 0.135032 0.0389736 0.3046 +0.0251038 0.0477382 0.750051 0.0280443 0.050585 0.56097 0.0257268 0.0432828 0.928139 +0.00943751 0.0569978 0.286637 0.103807 0.0436767 0.297624 0.0662884 0.0461437 0.456921 +0.0792184 0.0400866 0.623652 0.0123266 0.0459687 0.983872 0.0230557 0.0431557 0.957786 +0.0221042 0.0465385 0.840517 0.0475388 0.0402354 0.841885 0.0555401 0.0495788 0.362577 +0.132689 0.0386343 0.333811 0.0259475 0.0500001 0.617482 0.0665701 0.0484856 0.331472 +0.0193644 0.0545153 0.398634 0.0742516 0.0395763 0.675724 0.0606338 0.0457036 0.524123 +0.112858 0.0386149 0.459545 0.0923774 0.0447726 0.326009 0.125248 0.0385626 0.383488 +0.0211429 0.0553181 0.324355 0.0526577 0.0404484 0.797884 0.0619927 0.0478294 0.404733 +0.0218 0.0498519 0.671488 0.102769 0.0423548 0.36719 0.120855 0.0385295 0.412454 +0.0311687 0.0394524 0.98307 0.0186655 0.0495688 0.724093 0.0228859 0.047307 0.795738 +0.0673488 0.0395023 0.725143 0.111016 0.0383345 0.482138 0.0889024 0.0434468 0.414888 +0.0163392 0.0552726 0.378093 0.0476224 0.0494009 0.442004 0.0560396 0.0453627 0.577908 +0.0271694 0.0550019 0.285512 0.103622 0.0378976 0.545009 0.086568 0.0431711 0.444412 +0.0625865 0.0388156 0.779093 0.103474 0.0384915 0.523886 0.0217417 0.0534459 0.446001 +0.0548034 0.0475615 0.479257 0.0786991 0.0474958 0.288652 0.0805607 0.0432209 0.485853 +0.0448263 0.0486459 0.509042 0.0199364 0.0526085 0.521001 0.0189259 0.0534793 0.474123 +0.0452058 0.0515064 0.340277 0.0945054 0.0376963 0.609223 0.050676 0.0450674 0.636115 +0.0794268 0.0428267 0.511573 0.0138356 0.0528132 0.577332 0.0191947 0.0485398 0.775093 +0.0115595 0.0569084 0.307064 0.0186413 0.0525292 0.540632 0.0425403 0.0399564 0.88657 +0.108148 0.0420641 0.343511 0.128395 0.0564793 0.185896 0.0246209 0.064882 0.177719 +0.0640623 0.0539112 0.25156 0.11183 0.0537715 0.223798 0.0493659 0.0636715 0.202232 +0.069136 0.0776205 0.143084 0.0281442 0.0761872 0.135773 0.0877029 0.0675421 0.177909 +0.0864358 0.0597066 0.21309 0.133075 0.0484932 0.230181 0.0166354 0.0579109 0.235783 +0.0604825 0.0722848 0.167916 0.109658 0.0487824 0.24792 0.156057 0.0466887 0.199743 +0.05276 0.0844451 0.121598 0.0982714 0.0614008 0.137149 0.0746033 0.0780682 0.114628 +0.0225497 0.0608803 0.202966 0.0250346 0.0566811 0.255175 0.0122508 0.062903 0.157092 +0.154086 0.0407613 0.248826 0.109542 0.0628162 0.163739 0.0635297 0.0592584 0.22359 +0.158069 0.043867 0.224115 0.00949932 0.0572114 0.258582 0.010879 0.0693824 0.117241 +0.1317 0.0440918 0.252844 0.104787 0.0613201 0.193916 0.0875843 0.0545648 0.235778 +0.0848339 0.0505359 0.256042 0.0721635 0.0653948 0.193663 0.134824 0.052106 0.208704 +0.0361148 0.0714734 0.161508 0.0296749 0.0829236 0.114416 0.0420176 0.0568852 0.243844 +0.0884052 0.0633156 0.112564 0.0875435 0.0711327 0.155747 0.0489346 0.0783433 0.144768 +0.0088982 0.063498 0.136062 0.0441192 0.0674781 0.182889 0.0844035 0.0718067 0.13116 +0.0408385 0.0599943 0.22181 0.00291088 0.059482 0.103719 0.00783528 0.0582871 0.181396 +0.0350051 0.0279219 0.21057 0.0829863 0.0166038 0.170073 0.0744413 0.0208797 0.192662 +0.00709261 0.0352746 0.235255 0.119526 0.0302663 0.235622 0.0290415 0.015033 0.139837 +0.0763604 0.0279303 0.229395 0.135858 0.0298535 0.222024 0.114077 0.0235501 0.192102 +0.0720814 0.0108303 0.133044 0.143892 0.0329601 0.245602 0.0320915 0.0239572 0.18256 +0.0462478 0.0307745 0.240904 0.00682001 0.0355577 0.254572 0.0999339 0.0251519 0.21107 +0.0113898 0.0220096 0.119232 0.0537712 0.0151323 0.16317 0.0484396 0.00502554 0.117594 +0.15521 0.0317366 0.209714 0.105695 0.0210392 0.162543 0.0943974 0.0227718 0.136759 +0.0128112 0.0276391 0.154814 0.0990364 0.030901 0.2457 0.0593462 0.0253156 0.211578 +0.0278299 0.0335392 0.257711 0.14318 0.0295324 0.189096 0.161152 0.0335382 0.232509 +0.0153677 0.0310542 0.195044 0.0724963 0.0317041 0.252624 0.0864366 0.0232152 0.114693 +0.0510934 0.021702 0.189479 0.0286374 0.0210907 0.163398 0.00288167 0.0325463 0.104439 +0.0697986 0.00929166 0.110608 0.0775499 0.0134581 0.152702 0.0257651 0.0317531 0.232108 +0.127794 0.0268688 0.174472 0.126237 0.0327618 0.252618 0.0269949 0.00880256 0.112151 +0.013754 0.0329166 0.215511 0.0948615 0.0204778 0.18656 0.0122138 0.0306294 0.175365 +0.0534432 0.00951911 0.140149 0.128765 0.026726 0.201489 0.00770515 0.0294092 0.136719 +0.0785048 0.0246456 0.211452 0.0510532 0.032892 0.259012 0.0657778 0.0177095 0.17741 +0.161707 0.0344658 0.254774 0.0692502 0.00713413 0.0454645 0.0219769 0.00713413 0.0454645 +0.0456136 0.000505102 0.0266597 0.0456136 0.000505102 0.0638129 0.0859207 0.0249492 0.035347 +0.00530641 0.0249492 0.035347 0.0842247 0.0219745 0.064065 0.0070024 0.0219745 0.064065 +0.0742764 0.0106815 0.0205968 0.0169507 0.0106815 0.0205968 0.0675722 0.006161 0.0689286 +0.0236549 0.006161 0.0689286 0.0879524 0.029421 0.015481 0.00327471 0.029421 0.015481 +0.0890093 0.032435 0.0795452 0.00221785 0.032435 0.0795452 0.0456136 0.0437578 1e-07 +0.0456136 0.0698562 1e-07 0.0456136 0.0220627 1e-07 0.0253171 0.0528441 1e-07 +0.06591 0.0528441 1e-07 0.0263136 0.0317434 1e-07 0.0649135 0.0317434 1e-07 + +CELLS 993 3851 +2 0 14 +2 0 18 +2 1 26 +2 1 111 +2 2 21 +2 3 22 +2 4 107 +2 5 29 +2 6 30 +2 7 31 +2 8 32 +2 9 33 +2 9 64 +2 10 101 +2 11 34 +2 11 35 +2 12 40 +2 12 88 +2 12 94 +2 13 93 +2 14 15 +2 15 16 +2 16 17 +2 17 1 +2 18 19 +2 19 20 +2 20 2 +2 21 3 +2 22 23 +2 23 24 +2 24 25 +2 25 4 +2 26 27 +2 27 28 +2 28 4 +2 29 6 +2 30 7 +2 31 8 +2 32 5 +2 33 10 +2 34 10 +2 35 36 +2 36 37 +2 37 38 +2 38 39 +2 39 12 +2 40 41 +2 41 42 +2 42 43 +2 43 44 +2 44 45 +2 45 46 +2 46 47 +2 47 48 +2 48 49 +2 49 50 +2 50 51 +2 51 52 +2 52 53 +2 53 54 +2 54 55 +2 55 56 +2 56 57 +2 57 58 +2 58 59 +2 59 60 +2 60 61 +2 61 62 +2 62 63 +2 63 8 +2 64 65 +2 65 66 +2 66 67 +2 67 68 +2 68 69 +2 69 70 +2 70 71 +2 71 72 +2 72 73 +2 73 74 +2 74 75 +2 75 76 +2 76 77 +2 77 78 +2 78 79 +2 79 80 +2 80 81 +2 81 82 +2 82 83 +2 83 84 +2 84 85 +2 85 86 +2 86 87 +2 87 6 +2 88 89 +2 89 90 +2 90 91 +2 91 92 +2 92 13 +2 93 9 +2 94 95 +2 95 96 +2 96 97 +2 97 98 +2 98 99 +2 99 100 +2 100 4 +2 101 102 +2 102 103 +2 103 104 +2 104 105 +2 105 106 +2 106 3 +2 107 108 +2 108 109 +2 109 110 +2 110 2 +2 111 112 +2 112 113 +2 113 114 +2 114 0 +3 0 128 14 +3 0 428 18 +3 0 436 114 +3 1 130 26 +3 1 427 111 +3 1 435 17 +3 1 437 435 +3 2 106 21 +3 2 398 106 +3 2 430 110 +3 3 20 21 +3 3 127 20 +3 3 364 22 +3 4 129 25 +3 4 357 100 +3 4 395 107 +3 4 429 28 +3 5 31 32 +3 5 271 29 +3 6 5 29 +3 6 7 5 +3 6 30 7 +3 6 176 30 +3 6 271 87 +3 7 31 5 +3 7 176 31 +3 8 196 63 +3 8 291 32 +3 9 171 64 +3 9 267 93 +3 9 346 101 +3 10 33 101 +3 10 171 33 +3 10 379 34 +3 11 171 34 +3 11 205 171 +3 11 390 35 +3 12 88 40 +3 12 342 88 +3 12 414 94 +3 13 300 92 +3 13 346 93 +3 14 123 15 +3 14 128 123 +3 14 434 0 +3 15 117 16 +3 15 123 117 +3 15 432 14 +3 16 126 17 +3 16 432 15 +3 17 126 122 +3 17 130 1 +3 17 432 16 +3 17 435 432 +3 18 128 0 +3 18 420 19 +3 18 428 420 +3 19 119 18 +3 19 121 119 +3 19 422 20 +3 20 121 19 +3 20 127 121 +3 20 430 2 +3 21 20 2 +3 21 106 3 +3 22 125 121 +3 22 127 3 +3 22 355 23 +3 22 364 347 +3 23 125 22 +3 23 336 24 +3 23 355 336 +3 24 118 23 +3 24 124 118 +3 24 338 25 +3 25 124 24 +3 25 129 124 +3 25 357 4 +3 26 122 27 +3 26 130 122 +3 26 427 1 +3 27 120 28 +3 27 122 120 +3 27 419 26 +3 27 421 419 +3 28 129 4 +3 28 421 27 +3 28 429 421 +3 29 271 6 +3 30 176 7 +3 31 8 32 +3 31 196 8 +3 32 271 5 +3 32 291 271 +3 33 171 9 +3 34 171 10 +3 34 379 11 +3 35 205 11 +3 35 412 36 +3 36 163 35 +3 36 212 163 +3 36 394 37 +3 36 412 394 +3 37 212 36 +3 37 388 38 +3 37 394 388 +3 38 173 37 +3 38 403 39 +3 39 12 40 +3 39 168 38 +3 39 403 376 +3 39 414 12 +3 40 168 39 +3 40 263 41 +3 41 168 40 +3 41 181 168 +3 41 276 42 +3 42 181 41 +3 42 189 148 +3 42 276 243 +3 42 284 43 +3 43 189 42 +3 43 195 189 +3 43 290 44 +3 44 195 43 +3 44 290 45 +3 45 187 151 +3 45 195 44 +3 45 282 46 +3 45 290 246 +3 46 187 45 +3 46 200 187 +3 46 295 47 +3 47 200 46 +3 47 209 157 +3 47 295 252 +3 47 304 48 +3 48 209 47 +3 48 301 49 +3 48 304 301 +3 49 206 48 +3 49 259 50 +3 49 301 259 +3 50 165 49 +3 50 218 152 +3 50 259 247 +3 50 313 51 +3 51 218 50 +3 51 270 52 +3 51 313 270 +3 52 175 51 +3 52 185 158 +3 52 270 253 +3 52 280 53 +3 53 185 52 +3 53 280 54 +3 54 185 53 +3 54 199 166 +3 54 280 260 +3 54 294 55 +3 55 199 54 +3 55 261 56 +3 55 294 261 +3 56 167 55 +3 56 208 167 +3 56 303 57 +3 57 208 56 +3 57 286 58 +3 57 303 286 +3 58 180 149 +3 58 192 57 +3 58 274 59 +3 58 286 244 +3 59 180 58 +3 59 250 60 +3 59 274 250 +3 60 155 59 +3 60 224 155 +3 60 320 61 +3 61 172 162 +3 61 224 60 +3 61 266 62 +3 61 320 256 +3 62 172 61 +3 62 177 172 +3 62 272 63 +3 63 177 62 +3 63 196 177 +3 63 291 8 +3 64 223 65 +3 64 267 9 +3 64 318 267 +3 65 156 66 +3 65 191 156 +3 65 223 191 +3 65 318 64 +3 66 202 67 +3 66 251 65 +3 66 297 251 +3 67 184 68 +3 67 202 184 +3 67 297 66 +3 68 184 154 +3 68 210 69 +3 68 279 67 +3 68 305 249 +3 69 215 70 +3 69 305 68 +3 69 311 305 +3 70 215 71 +3 70 311 69 +3 71 215 159 +3 71 216 72 +3 71 310 254 +3 71 311 70 +3 72 225 73 +3 72 310 71 +3 72 319 310 +3 73 221 74 +3 73 225 170 +3 73 316 265 +3 73 319 72 +3 74 182 75 +3 74 221 153 +3 74 277 248 +3 74 316 73 +3 75 161 76 +3 75 182 161 +3 75 277 74 +3 76 188 77 +3 76 255 75 +3 76 288 255 +3 77 160 78 +3 77 188 160 +3 77 288 76 +3 78 197 79 +3 78 262 77 +3 78 292 262 +3 79 169 80 +3 79 197 169 +3 79 292 78 +3 80 222 81 +3 80 264 79 +3 80 317 264 +3 81 198 82 +3 81 222 198 +3 81 317 80 +3 82 179 83 +3 82 198 149 +3 82 273 244 +3 82 293 81 +3 83 155 84 +3 83 179 155 +3 83 273 82 +3 84 162 85 +3 84 250 83 +3 84 256 250 +3 85 172 86 +3 85 256 84 +3 85 266 256 +3 86 177 87 +3 86 266 85 +3 86 272 266 +3 87 176 6 +3 87 177 176 +3 87 272 86 +3 88 263 40 +3 88 348 89 +3 89 263 88 +3 89 268 263 +3 89 334 90 +3 89 348 334 +3 90 268 89 +3 90 307 268 +3 90 351 91 +3 91 307 90 +3 91 324 92 +3 91 351 324 +3 92 257 91 +3 92 300 257 +3 92 340 13 +3 92 356 340 +3 93 267 13 +3 93 346 9 +3 94 342 12 +3 94 345 342 +3 94 392 95 +3 94 414 392 +3 95 345 94 +3 95 384 96 +3 95 392 384 +3 96 335 95 +3 96 391 97 +3 97 335 96 +3 97 391 98 +3 98 322 97 +3 98 343 322 +3 98 385 99 +3 98 402 385 +3 99 343 98 +3 99 386 100 +3 100 337 99 +3 100 357 337 +3 100 395 4 +3 101 33 9 +3 101 332 102 +3 101 346 332 +3 101 379 10 +3 102 339 103 +3 102 369 101 +3 102 405 369 +3 103 365 104 +3 103 405 102 +3 103 407 393 +3 104 341 105 +3 104 365 341 +3 104 407 103 +3 105 360 106 +3 105 387 104 +3 105 410 387 +3 106 360 347 +3 106 364 3 +3 106 398 381 +3 106 410 105 +3 107 399 108 +3 107 425 421 +3 107 429 4 +3 108 383 109 +3 108 399 383 +3 108 425 107 +3 109 404 110 +3 109 418 108 +3 109 426 418 +3 110 398 2 +3 110 404 381 +3 110 426 109 +3 110 430 422 +3 111 423 112 +3 111 427 423 +3 111 437 1 +3 112 417 113 +3 112 423 417 +3 112 437 111 +3 113 424 114 +3 113 433 112 +3 113 436 433 +3 114 428 0 +3 114 436 113 +3 115 118 117 +3 115 123 119 +3 115 125 118 +3 116 124 120 +3 116 126 117 +3 117 118 116 +3 117 123 115 +3 117 126 16 +3 118 124 116 +3 118 125 23 +3 119 121 115 +3 119 128 18 +3 120 122 116 +3 120 129 28 +3 121 125 115 +3 121 127 22 +3 122 126 116 +3 122 130 17 +3 123 128 119 +3 124 129 120 +3 131 190 148 +3 131 194 164 +3 132 203 154 +3 132 207 174 +3 133 214 211 +3 133 220 186 +3 134 170 147 +3 134 186 146 +3 134 204 170 +3 135 182 153 +3 135 204 152 +3 135 219 182 +3 136 166 160 +3 136 185 166 +3 136 188 161 +3 136 219 158 +3 137 191 150 +3 137 217 191 +3 138 173 168 +3 138 181 148 +3 138 190 173 +3 139 178 164 +3 139 193 154 +3 139 202 156 +3 140 194 189 +3 140 201 164 +3 141 197 160 +3 141 199 167 +3 142 207 187 +3 142 213 174 +3 143 203 174 +3 143 210 203 +3 143 211 159 +3 143 215 210 +3 144 169 167 +3 144 208 192 +3 144 222 169 +3 145 183 163 +3 145 190 183 +3 145 212 173 +3 146 165 134 +3 146 206 165 +3 146 209 206 +3 146 220 209 +3 147 186 134 +3 147 214 186 +3 147 216 214 +3 147 225 216 +3 148 181 42 +3 148 190 138 +3 148 194 131 +3 149 179 82 +3 149 180 179 +3 149 192 58 +3 149 198 192 +3 150 163 137 +3 150 205 163 +3 150 223 171 +3 151 195 45 +3 151 201 195 +3 151 207 201 +3 152 165 50 +3 152 175 135 +3 152 204 165 +3 152 218 175 +3 153 182 74 +3 153 204 135 +3 153 221 170 +3 154 184 139 +3 154 193 132 +3 154 210 68 +3 155 162 84 +3 155 180 59 +3 155 224 162 +3 156 178 139 +3 156 202 66 +3 156 217 178 +3 157 200 47 +3 157 213 200 +3 157 220 213 +3 158 175 52 +3 158 185 136 +3 158 219 175 +3 159 215 143 +3 159 216 71 +3 160 166 141 +3 160 188 136 +3 160 197 78 +3 161 188 76 +3 161 219 136 +3 162 172 85 +3 162 224 61 +3 163 183 137 +3 163 205 35 +3 163 212 145 +3 164 178 131 +3 164 193 139 +3 164 194 140 +3 164 201 193 +3 165 204 134 +3 165 206 49 +3 166 185 54 +3 166 199 141 +3 167 169 141 +3 167 199 55 +3 167 208 144 +3 168 173 38 +3 168 181 138 +3 169 197 141 +3 169 222 80 +3 170 204 153 +3 170 221 73 +3 170 225 147 +3 171 205 150 +3 171 223 64 +3 172 177 86 +3 173 190 145 +3 173 212 37 +3 174 203 132 +3 174 207 142 +3 174 211 143 +3 174 213 211 +3 175 218 51 +3 175 219 135 +3 176 196 31 +3 177 196 176 +3 178 183 131 +3 178 217 183 +3 179 180 155 +3 182 219 161 +3 183 190 131 +3 183 217 137 +3 184 202 139 +3 186 214 133 +3 186 220 146 +3 187 200 142 +3 187 207 151 +3 189 194 148 +3 189 195 140 +3 191 217 156 +3 191 223 150 +3 192 198 144 +3 192 208 57 +3 193 201 132 +3 195 201 140 +3 198 222 144 +3 200 213 142 +3 201 207 132 +3 203 210 154 +3 206 209 48 +3 209 220 157 +3 210 215 69 +3 211 213 133 +3 211 214 159 +3 213 220 133 +3 214 216 159 +3 216 225 72 +3 226 275 258 +3 226 278 275 +3 226 283 278 +3 226 321 283 +3 227 287 249 +3 227 296 287 +3 227 298 269 +3 227 302 296 +3 228 308 306 +3 228 309 281 +3 228 315 308 +3 229 259 241 +3 229 281 242 +3 229 299 259 +3 230 270 247 +3 230 299 248 +3 230 314 270 +3 231 262 260 +3 231 280 253 +3 231 288 262 +3 231 314 255 +3 232 257 245 +3 232 278 257 +3 232 312 278 +3 233 276 263 +3 233 321 276 +3 234 289 258 +3 234 290 284 +3 234 296 290 +3 235 275 251 +3 235 279 249 +3 235 287 258 +3 235 297 279 +3 236 264 261 +3 236 292 264 +3 236 294 260 +3 237 295 282 +3 237 302 269 +3 237 308 295 +3 238 306 269 +3 238 311 254 +3 239 293 286 +3 239 303 261 +3 239 317 293 +3 240 283 268 +3 240 307 257 +3 241 281 229 +3 241 315 281 +3 242 265 229 +3 242 319 265 +3 243 284 42 +3 243 289 284 +3 243 321 289 +3 244 274 58 +3 244 293 82 +3 245 285 232 +3 245 300 267 +3 245 318 285 +3 246 282 45 +3 246 302 282 +3 247 299 230 +3 247 313 50 +3 248 277 230 +3 248 299 265 +3 248 316 74 +3 249 279 68 +3 249 287 235 +3 249 298 227 +3 249 305 298 +3 250 273 83 +3 250 274 273 +3 250 320 60 +3 251 285 65 +3 251 297 235 +3 251 312 285 +3 252 304 47 +3 252 315 304 +3 253 280 52 +3 253 314 231 +3 254 306 238 +3 254 309 306 +3 254 310 309 +3 254 311 71 +3 255 277 75 +3 255 288 231 +3 255 314 277 +3 256 266 61 +3 256 320 250 +3 257 278 240 +3 257 300 245 +3 257 307 91 +3 258 275 235 +3 258 289 226 +3 258 296 234 +3 259 299 247 +3 259 301 241 +3 260 262 236 +3 260 280 231 +3 260 294 54 +3 261 264 239 +3 261 294 236 +3 261 303 56 +3 262 288 77 +3 262 292 236 +3 263 268 233 +3 263 276 41 +3 264 292 79 +3 264 317 239 +3 265 299 229 +3 265 316 248 +3 265 319 73 +3 266 272 62 +3 267 300 13 +3 267 318 245 +3 268 283 233 +3 268 307 240 +3 269 298 238 +3 269 302 227 +3 269 308 237 +3 270 313 247 +3 270 314 253 +3 271 272 87 +3 271 291 272 +3 272 291 63 +3 273 274 244 +3 275 312 251 +3 276 321 243 +3 277 314 230 +3 278 283 240 +3 278 312 275 +3 279 297 67 +3 281 309 242 +3 281 315 228 +3 282 295 46 +3 282 302 237 +3 283 321 233 +3 284 289 234 +3 284 290 43 +3 285 312 232 +3 285 318 65 +3 286 293 244 +3 286 303 239 +3 287 296 258 +3 289 321 226 +3 290 296 246 +3 293 317 81 +3 295 308 252 +3 296 302 246 +3 298 305 238 +3 301 304 241 +3 304 315 241 +3 305 311 238 +3 306 308 269 +3 306 309 228 +3 308 315 252 +3 309 310 242 +3 310 319 242 +3 322 335 97 +3 322 353 335 +3 323 354 341 +3 323 361 354 +3 323 365 339 +3 324 350 344 +3 324 351 350 +3 324 356 92 +3 325 334 331 +3 325 349 330 +3 325 350 334 +3 325 353 349 +3 326 361 339 +3 326 363 344 +3 327 338 336 +3 327 359 333 +3 327 362 338 +3 328 355 347 +3 328 359 336 +3 328 360 341 +3 329 349 343 +3 329 352 349 +3 329 358 333 +3 330 350 325 +3 330 352 344 +3 331 348 342 +3 331 353 325 +3 332 339 102 +3 332 346 340 +3 332 363 339 +3 333 352 329 +3 333 358 327 +3 333 359 354 +3 333 361 352 +3 334 348 331 +3 334 351 90 +3 335 345 95 +3 335 353 345 +3 336 338 24 +3 336 355 328 +3 336 359 327 +3 337 343 99 +3 337 358 343 +3 337 362 358 +3 338 357 25 +3 338 362 357 +3 339 361 323 +3 339 363 326 +3 339 365 103 +3 340 346 13 +3 340 356 332 +3 341 354 328 +3 341 360 105 +3 341 365 323 +3 342 345 331 +3 342 348 88 +3 343 349 322 +3 343 358 329 +3 344 350 330 +3 344 352 326 +3 344 356 324 +3 344 363 356 +3 345 353 331 +3 347 355 22 +3 347 360 328 +3 347 364 106 +3 349 352 330 +3 349 353 322 +3 350 351 334 +3 352 361 326 +3 354 359 328 +3 354 361 333 +3 356 363 332 +3 357 362 337 +3 358 362 327 +3 366 389 378 +3 366 393 377 +3 366 396 389 +3 366 405 393 +3 367 400 385 +3 367 406 368 +3 367 413 382 +3 368 406 380 +3 368 411 389 +3 368 413 367 +3 369 379 101 +3 369 401 379 +3 369 405 401 +3 370 380 373 +3 370 388 380 +3 370 403 388 +3 371 397 387 +3 371 404 383 +3 371 408 382 +3 371 410 381 +3 372 394 378 +3 372 411 380 +3 373 376 370 +3 373 392 376 +3 373 409 384 +3 374 406 385 +3 374 409 380 +3 375 395 386 +3 375 399 395 +3 375 408 383 +3 376 403 370 +3 376 414 39 +3 377 396 366 +3 377 397 382 +3 377 407 397 +3 378 389 372 +3 378 401 366 +3 378 412 390 +3 379 390 11 +3 379 401 390 +3 380 388 372 +3 380 406 374 +3 380 409 373 +3 380 411 368 +3 381 398 110 +3 381 404 371 +3 381 410 106 +3 382 396 377 +3 382 397 371 +3 382 400 367 +3 382 408 400 +3 382 413 396 +3 383 399 375 +3 383 404 109 +3 383 408 371 +3 384 391 96 +3 384 392 373 +3 384 409 391 +3 385 386 99 +3 385 400 386 +3 385 402 374 +3 385 406 367 +3 386 395 100 +3 386 400 375 +3 387 407 104 +3 387 410 371 +3 388 394 372 +3 388 403 38 +3 389 396 368 +3 389 411 372 +3 390 401 378 +3 390 412 35 +3 391 402 98 +3 391 409 402 +3 392 414 376 +3 393 405 103 +3 393 407 377 +3 394 412 378 +3 395 399 107 +3 396 413 368 +3 397 407 387 +3 400 408 375 +3 401 405 366 +3 402 409 374 +3 415 418 417 +3 415 423 419 +3 415 425 418 +3 416 422 420 +3 416 424 417 +3 416 426 422 +3 417 418 416 +3 417 423 415 +3 417 424 113 +3 418 425 108 +3 418 426 416 +3 419 421 415 +3 419 427 26 +3 420 422 19 +3 420 424 416 +3 420 428 424 +3 421 425 415 +3 421 429 107 +3 422 426 110 +3 422 430 20 +3 423 427 419 +3 424 428 114 +3 431 434 432 +3 431 436 434 +3 431 437 433 +3 432 434 14 +3 432 435 431 +3 433 436 431 +3 433 437 112 +3 434 436 0 +3 435 437 431 + +CELL_TYPES 993 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 + +POINT_DATA 438 +SCALARS scalars double +LOOKUP_TABLE default +1.6755246382 0.9791806223 0.9791806223 0.97594938187 0.12925491957 0.32674332908 0.2776476709 0.26537269646 0.54790553034 +-0.21848899462 -0.21871453724 -0.21891455992 0.84665342709 -0.17856744253 1.4657434747 1.135295639 0.86221409635 0.80015646753 +1.5522257846 1.3892109713 1.194864132 0.97756806161 0.62351150718 0.25873103587 0.043676132717 0.0036947001056 0.75325315321 +0.52870128787 0.3170738414 0.30551630372 0.26085193696 0.40221609491 0.43492101536 -0.21860483282 -0.21999990002 -0.17179908702 +-0.058158766325 0.11406364917 0.33283088172 0.58285245978 1.0812401593 1.2986601063 1.4865231487 1.6341235277 1.7330499344 +1.7776648458 1.76542579 1.6970302345 1.5763758398 1.4103383427 1.2083797289 0.98200902193 0.74412641865 0.50828814461 +0.28793392513 0.095621095082 -0.057691006459 -0.16326557653 -0.2150862328 -0.21019986942 -0.14888494579 -0.034635617958 0.12603738299 +0.32397777821 -0.16077576716 -0.02400712404 0.18032386837 0.43504686237 0.71875696815 1.0076134501 1.2773431122 1.5052800239 +1.6722701842 1.7642810712 1.7735808236 1.6993879641 1.5479370694 1.3319548652 1.0695907743 0.78289178324 0.49594978977 +0.23287711157 0.015780279339 -0.13709761979 -0.21290994591 -0.20528603548 -0.11486654116 0.050750403557 0.62258815746 0.40644230393 +0.2090902005 0.040460664451 -0.090962524082 -0.20430773504 0.69810823114 0.46983854429 0.17526328013 -0.071983623309 -0.20353805407 +-0.20206347466 -0.070749910509 -0.19823053745 -0.11210076093 0.033914302466 0.23002576773 0.46307296426 0.71740811854 0.43280230672 +0.817804103 1.0933668947 1.1517427527 1.3065231917 1.5916084598 1.7217590887 1.7408274774 0.82776281929 0.36881870492 +0.71230316511 0.35370086918 1.2545105476 0.2886410948 0.93968205698 0.5430800996 1.1634248179 0.14493383167 0.56814700099 +0.59876763048 0.93603648866 1.4676191343 0.14520593653 0.75223127193 0.75616927578 1.3570237577 1.7282221487 1.768296739 +1.543121533 1.1002912641 0.099436130411 0.80378264345 0.70549326191 1.3289671025 0.59115044346 1.71691781 1.3745290533 +0.16552489742 0.31011739066 1.7438062065 1.7585555214 1.1391874861 -0.099528237524 -0.10541046472 1.6346682663 1.4900703259 +1.7398187046 0.95392866253 -0.21791242411 0.23081184222 1.7761987877 1.0561939282 1.5487600505 1.0305112263 1.4944798645 +-0.19730918942 0.014956310347 0.99059585945 1.6090416854 0.63017894114 0.218974833 0.80523893907 0.51023000968 1.7794288023 +-0.21362877479 -0.098854652254 0.43229585504 1.5428825212 1.2341282762 0.18920272181 0.063008889303 0.58920818213 -0.13535473803 +-0.20643217259 1.1196436528 1.6490393121 0.39772693916 0.59256001834 0.77884705263 1.7765589199 1.7576846815 1.3036805094 +1.4345024337 0.63514744765 -0.01678806157 -0.069083799098 1.0743353811 1.1088231691 1.6033326464 0.31492409529 0.82838938663 +0.12667992895 0.36586886253 1.7799932744 1.4023225804 0.36632022564 1.2866268824 1.6959778155 -0.17118726317 1.6312687018 +1.5902320806 -0.015743911305 1.7229314992 1.0887020743 1.6096199758 0.13504773148 1.7438324768 1.704205237 1.3179407721 +1.6488844705 0.28229588155 1.2292877294 1.3652558854 1.7797419949 1.7799736926 0.32660193937 -0.14857625197 -0.19318715181 +1.7261871417 0.88149061682 1.4473245409 1.7569640386 1.7479946948 1.4801518862 1.0175973182 0.24499749617 0.83453440776 +1.3898875271 0.86892437814 0.50677447872 1.7391916833 1.4920404464 0.11300809901 0.42922325338 1.7246326274 1.7776746585 +1.2563308179 -0.12837985231 0.013566551382 1.6624405022 1.4477489815 1.6934234131 1.1200723305 -0.21996287145 0.41344759264 +1.771083354 1.0055997763 1.6428074195 1.3990938472 -0.18425966531 0.13731969225 1.1082452004 1.5790984093 0.58084386183 +0.18057236399 0.90815905874 0.85360791763 0.41377935163 1.7736443524 -0.074241689906 -0.14524075666 0.521643864 1.6111344192 +1.1917860173 0.23708534415 0.094272041664 -0.16500712297 -0.21179598795 0.74457890718 1.1125026041 1.5754111433 0.53539018111 +0.79274350764 0.73847656099 1.7797706563 1.7650717214 0.69929284005 1.4693524192 0.13255190696 -0.090351929446 1.1997430842 +1.1901158033 1.1792988096 1.6246975813 0.337252558 0.71076199938 0.058942219385 0.33072061936 1.7794977764 1.4689112865 +0.5663189088 1.4071422981 1.6527829934 -0.080145739764 1.6153087313 1.6368475839 -0.033979523542 1.7103858036 1.2589836748 +1.6729395153 0.24549567056 1.7625958327 1.7468898672 1.7201509478 1.4637557301 0.44416086788 1.2056952443 1.2901823677 +1.7784833959 1.7677601099 0.23675999889 -0.037509956098 1.7663918651 -0.18485835219 1.002960334 -0.06399401006 -0.11185220825 +-0.070564436228 0.049950891449 -0.21993836094 -0.1905761892 0.041904725996 -0.20201496073 -0.12012930056 0.21957407853 -0.21926649414 +-0.2109343558 0.17578154702 0.14538989568 -0.070657042564 -0.20500676229 -0.11220294001 -0.18170780144 -0.19427581245 0.097148401664 +0.50782195574 -0.1960329718 -0.16854643533 0.34334045381 -0.21380838161 0.38669486359 0.3667390324 -0.11665864704 -0.023480843639 +0.063846929002 -0.20547901802 0.093947282682 -0.12017273084 0.1362833736 -0.17941664701 -0.098183556822 -0.21999652153 -0.1326245497 +0.28852059281 -0.20071087347 -0.18433135291 -0.21640360191 0.6897982209 -0.0060467306925 -0.13846275424 -0.12262685283 -0.18593564673 +-0.15399017286 0.02330796696 0.51488783435 -0.20099717127 0.038680779693 -0.20790340614 0.22466803905 0.31127048843 0.0520766098 +-0.21929050506 -0.20522718424 -0.19590491714 0.82446257655 0.098402813951 0.64065491661 0.1014550813 -0.18920247315 -0.044031358276 +0.40736851786 -0.036898941538 -0.20398719783 -0.21878957394 -0.1086107117 0.35369402577 0.032782061029 -0.13035763529 0.15693975984 +-0.088392072579 0.24841639767 0.95127553474 0.45956714543 0.018058574871 -0.19005803317 -0.20880810213 0.21847905021 0.87118797993 +-0.08792775363 -0.21249416497 0.20607549398 0.33577081443 -0.12970873945 0.61324079458 -0.21999016626 -0.17882033382 -0.08147794362 +0.57847450784 1.1250649613 1.5145759826 1.5266505277 1.2342063851 0.8884139771 1.5724226036 0.64853558408 1.3774977766 +1.2727516235 1.6659353358 0.92367986192 1.330824123 1.0198891011 1.6661772356 0.35487652417 1.1957940535 1.4065210616 +1.1841940863 1.5596037725 1.4897786446 1.1539404317 1.6161497311 1.3481254901 diff --git a/examples/mapping_tester/fine_mesh.vtk b/examples/mapping_tester/fine_mesh.vtk new file mode 100644 index 00000000..eb9f468b --- /dev/null +++ b/examples/mapping_tester/fine_mesh.vtk @@ -0,0 +1,16014 @@ +# vtk DataFile Version 4.2 +vtk output +ASCII +DATASET UNSTRUCTURED_GRID +POINTS 3458 float +0.000159205 0.0459595 1e-07 0.0910679 0.0459595 1e-07 0.000159205 0.0459595 0.0909088 +0.00016037 0.0462879 0.0909088 0.0910679 0.0459595 0.0909088 0.00387147 0.0486486 0.999996 +0.000160265 0.0467696 0.999996 0.00230119 0.0432031 0.999996 0.0412046 0.0349339 0.999996 +0.000161941 0.0467691 0.272726 0.000140272 0.0463638 0.272726 0.0114969 0.0345959 0.272726 +0.170587 0.0345959 0.272726 0.013112 0.0572077 0.272726 0.00115249 0.0554099 1e-07 +0.00408894 0.0644474 1e-07 0.00884021 0.0726769 1e-07 0.0151987 0.0797386 1e-07 +0.0228864 0.0853241 1e-07 0.0315674 0.0891891 1e-07 0.0408623 0.0911648 1e-07 +0.0503648 0.0911648 1e-07 0.0596597 0.0891891 1e-07 0.0683407 0.0853241 1e-07 +0.0760285 0.0797386 1e-07 0.0823869 0.0726769 1e-07 0.0871382 0.0644474 1e-07 +0.0900746 0.0554099 1e-07 0.000159205 0.0459595 0.00909097 0.000159205 0.0459595 0.0181818 +0.000159205 0.0459595 0.0272727 0.000159205 0.0459595 0.0363636 0.000159205 0.0459595 0.0454544 +0.000159205 0.0459595 0.0545453 0.000159205 0.0459595 0.0636362 0.000159205 0.0459595 0.0727271 +0.000159205 0.0459595 0.0818179 0.000159502 0.0461237 0.0909088 0.00121724 0.0557096 0.0909088 +0.00420554 0.0647071 0.0909088 0.00899528 0.072889 0.0909088 0.0153781 0.0798993 0.0909088 +0.0230763 0.0854331 0.0909088 0.031755 0.0892496 0.0909088 0.0410365 0.0911828 0.0909088 +0.0505172 0.0911485 0.0909088 0.0597846 0.0891483 0.0909088 0.0684355 0.0852692 0.0909088 +0.0760935 0.07968 0.0909088 0.0824255 0.0726237 0.0909088 0.087156 0.0644074 0.0909088 +0.0900792 0.0553885 0.0909088 0.0910679 0.0459595 0.00909097 0.0910679 0.0459595 0.0181818 +0.0910679 0.0459595 0.0272727 0.0910679 0.0459595 0.0363636 0.0910679 0.0459595 0.0454544 +0.0910679 0.0459595 0.0545453 0.0910679 0.0459595 0.0636362 0.0910679 0.0459595 0.0727271 +0.0910679 0.0459595 0.0818179 0.00160779 0.0485161 0.999996 0.000455632 0.0445206 0.999996 +0.0120271 0.0411358 0.999996 0.0217529 0.0390685 0.999996 0.0314788 0.0370012 0.999996 +0.0318713 0.0383626 0.999996 0.022538 0.0417913 0.999996 0.0132048 0.0452199 0.999996 +0.000149524 0.0465665 0.272726 0.00331992 0.0380684 0.272726 0.02144 0.0345959 0.272726 +0.0313832 0.0345959 0.272726 0.0413263 0.0345959 0.272726 0.0512694 0.0345959 0.272726 +0.0612126 0.0345959 0.272726 0.0711557 0.0345959 0.272726 0.0810989 0.0345959 0.272726 +0.091042 0.0345959 0.272726 0.100985 0.0345959 0.272726 0.110928 0.0345959 0.272726 +0.120871 0.0345959 0.272726 0.130815 0.0345959 0.272726 0.140758 0.0345959 0.272726 +0.150701 0.0345959 0.272726 0.160644 0.0345959 0.272726 0.168839 0.0346004 0.282554 +0.16709 0.034605 0.292382 0.165342 0.0346096 0.30221 0.163593 0.0346141 0.312038 +0.161845 0.0346187 0.321866 0.160097 0.0346233 0.331694 0.158348 0.0346278 0.341522 +0.1566 0.0346324 0.35135 0.154851 0.034637 0.361178 0.153103 0.0346416 0.371006 +0.151355 0.0346461 0.380834 0.149606 0.0346507 0.390662 0.147858 0.0346553 0.40049 +0.146109 0.0346598 0.410318 0.144361 0.0346644 0.420146 0.142613 0.034669 0.429974 +0.140864 0.0346735 0.439802 0.139116 0.0346781 0.44963 0.137367 0.0346827 0.459458 +0.135619 0.0346872 0.469286 0.13387 0.0346918 0.479114 0.132122 0.0346964 0.488941 +0.130374 0.0347009 0.498769 0.128625 0.0347055 0.508597 0.126877 0.0347101 0.518425 +0.125128 0.0347147 0.528253 0.12338 0.0347192 0.538081 0.121632 0.0347238 0.547909 +0.119883 0.0347284 0.557737 0.118135 0.0347329 0.567565 0.116386 0.0347375 0.577393 +0.114638 0.0347421 0.587221 0.11289 0.0347466 0.597049 0.111141 0.0347512 0.606877 +0.109393 0.0347558 0.616705 0.107644 0.0347603 0.626533 0.105896 0.0347649 0.636361 +0.104147 0.0347695 0.646189 0.102399 0.034774 0.656017 0.100651 0.0347786 0.665845 +0.0989022 0.0347832 0.675673 0.0971538 0.0347877 0.685501 0.0954054 0.0347923 0.695329 +0.093657 0.0347969 0.705157 0.0919086 0.0348015 0.714985 0.0901602 0.034806 0.724813 +0.0884117 0.0348106 0.734641 0.0866633 0.0348152 0.744469 0.0849149 0.0348197 0.754297 +0.0831665 0.0348243 0.764125 0.0814181 0.0348289 0.773953 0.0796697 0.0348334 0.783781 +0.0779213 0.034838 0.793608 0.0761729 0.0348426 0.803436 0.0744245 0.0348471 0.813264 +0.072676 0.0348517 0.823092 0.0709276 0.0348563 0.83292 0.0691792 0.0348608 0.842748 +0.0674308 0.0348654 0.852576 0.0656824 0.03487 0.862404 0.063934 0.0348746 0.872232 +0.0621856 0.0348791 0.88206 0.0604372 0.0348837 0.891888 0.0586887 0.0348883 0.901716 +0.0569403 0.0348928 0.911544 0.0551919 0.0348974 0.921372 0.0534435 0.034902 0.9312 +0.0516951 0.0349065 0.941028 0.0499467 0.0349111 0.950856 0.0481983 0.0349157 0.960684 +0.0464499 0.0349202 0.970512 0.0447014 0.0349248 0.98034 0.042953 0.0349294 0.990168 +0.000161687 0.0467691 0.282689 0.000161667 0.0467691 0.292651 0.000161647 0.0467691 0.302614 +0.000161627 0.0467691 0.312577 0.000161608 0.0467691 0.322539 0.000161588 0.0467692 0.332502 +0.000161568 0.0467692 0.342464 0.000161548 0.0467692 0.352427 0.000161529 0.0467692 0.36239 +0.000161509 0.0467692 0.372352 0.000161489 0.0467692 0.382315 0.000161469 0.0467692 0.392277 +0.00016145 0.0467692 0.40224 0.00016143 0.0467692 0.412203 0.00016141 0.0467692 0.422165 +0.00016139 0.0467692 0.432128 0.000161371 0.0467692 0.44209 0.000161351 0.0467692 0.452053 +0.000161331 0.0467692 0.462016 0.000161311 0.0467693 0.471978 0.000161292 0.0467693 0.481941 +0.000161272 0.0467693 0.491903 0.000161252 0.0467693 0.501866 0.000161232 0.0467693 0.511829 +0.000161213 0.0467693 0.521791 0.000161193 0.0467693 0.531754 0.000161173 0.0467693 0.541716 +0.000161153 0.0467693 0.551679 0.000161134 0.0467693 0.561642 0.000161114 0.0467693 0.571604 +0.000161094 0.0467693 0.581567 0.000161074 0.0467693 0.591529 0.000161055 0.0467693 0.601492 +0.000161035 0.0467694 0.611455 0.000161015 0.0467694 0.621417 0.000160995 0.0467694 0.63138 +0.000160976 0.0467694 0.641342 0.000160956 0.0467694 0.651305 0.000160936 0.0467694 0.661268 +0.000160916 0.0467694 0.67123 0.000160897 0.0467694 0.681193 0.000160877 0.0467694 0.691155 +0.000160857 0.0467694 0.701118 0.000160837 0.0467694 0.71108 0.000160818 0.0467694 0.721043 +0.000160798 0.0467694 0.731006 0.000160778 0.0467694 0.740968 0.000160759 0.0467694 0.750931 +0.000160739 0.0467695 0.760893 0.000160719 0.0467695 0.770856 0.000160699 0.0467695 0.780819 +0.00016068 0.0467695 0.790781 0.00016066 0.0467695 0.800744 0.00016064 0.0467695 0.810706 +0.00016062 0.0467695 0.820669 0.000160601 0.0467695 0.830632 0.000160581 0.0467695 0.840594 +0.000160561 0.0467695 0.850557 0.000160541 0.0467695 0.860519 0.000160522 0.0467695 0.870482 +0.000160502 0.0467695 0.880445 0.000160482 0.0467695 0.890407 0.000160462 0.0467696 0.90037 +0.000160443 0.0467696 0.910332 0.000160423 0.0467696 0.920295 0.000160403 0.0467696 0.930258 +0.000160383 0.0467696 0.94022 0.000160364 0.0467696 0.950183 0.000160344 0.0467696 0.960145 +0.000160324 0.0467696 0.970108 0.000160304 0.0467696 0.980071 0.000160285 0.0467696 0.990033 +0.160745 0.0360091 0.272726 0.150903 0.0374223 0.272726 0.141061 0.0388356 0.272726 +0.131218 0.0402488 0.272726 0.121376 0.0416621 0.272726 0.111534 0.0430753 0.272726 +0.101692 0.0444885 0.272726 0.0918496 0.0459018 0.272726 0.0820074 0.047315 0.272726 +0.0721652 0.0487282 0.272726 0.062323 0.0501415 0.272726 0.0524808 0.0515547 0.272726 +0.0426386 0.052968 0.272726 0.0327964 0.0543812 0.272726 0.0229542 0.0557944 0.272726 +0.00436536 0.0548066 0.272726 0.174681 0.0349195 0.263626 0.178196 0.0352748 0.254289 +0.180959 0.0356682 0.244705 0.182732 0.0361064 0.234894 0.183217 0.0365949 0.224942 +0.1821 0.0371336 0.215047 0.179194 0.037712 0.205527 0.174588 0.0383101 0.196702 +0.168627 0.038908 0.188724 0.16173 0.0394943 0.181534 0.154249 0.0400661 0.174948 +0.146442 0.0406254 0.168749 0.138499 0.0411762 0.162722 0.130578 0.041723 0.156667 +0.122832 0.0422698 0.150391 0.115434 0.0428192 0.14371 0.108597 0.043372 0.136459 +0.102579 0.0439251 0.128518 0.0976588 0.0444711 0.119856 0.094063 0.044999 0.110566 +0.0918865 0.0454975 0.100843 0.000144283 0.0463598 0.263157 0.000147801 0.0463558 0.253588 +0.000150853 0.0463518 0.244018 0.00015347 0.0463478 0.234449 0.00015568 0.0463438 0.22488 +0.000157514 0.0463398 0.21531 0.000158999 0.0463358 0.205741 0.000160167 0.0463318 0.196172 +0.000161045 0.0463278 0.186602 0.000161663 0.0463238 0.177033 0.000162051 0.0463198 0.167463 +0.000162238 0.0463159 0.157894 0.000162252 0.0463119 0.148325 0.000162124 0.0463079 0.138755 +0.000161883 0.0463039 0.129186 0.000161558 0.0462999 0.119617 0.000161177 0.0462959 0.110047 +0.000160772 0.0462919 0.100478 0.0900746 0.036509 0.0909088 0.0871382 0.0274715 0.0909088 +0.0823869 0.0192421 0.0909088 0.0760285 0.0121803 0.0909088 0.0683407 0.00659483 0.0909088 +0.0596597 0.0027298 0.0909088 0.0503648 0.000754106 0.0909088 0.0408623 0.000754106 0.0909088 +0.0315674 0.0027298 0.0909088 0.0228864 0.00659483 0.0909088 0.0151987 0.0121803 0.0909088 +0.00884021 0.0192421 0.0909088 0.00408894 0.0274715 0.0909088 0.00115249 0.036509 0.0909088 +0.0900746 0.036509 1e-07 0.0871382 0.0274715 1e-07 0.0823869 0.0192421 1e-07 +0.0760285 0.0121803 1e-07 0.0683407 0.00659483 1e-07 0.0596597 0.0027298 1e-07 +0.0503648 0.000754106 1e-07 0.0408623 0.000754106 1e-07 0.0315674 0.0027298 1e-07 +0.0228864 0.00659483 1e-07 0.0151987 0.0121803 1e-07 0.00884021 0.0192421 1e-07 +0.00408894 0.0274715 1e-07 0.00115249 0.036509 1e-07 0.019649 0.0832682 0.0454642 +0.0715848 0.0832635 0.0454498 0.0458832 0.091413 0.0623875 0.0451402 0.0914113 0.0291099 +0.00718107 0.0702296 0.0650268 0.0840671 0.0701962 0.0649956 0.00740438 0.0705797 0.0254259 +0.0837958 0.0706215 0.0254057 0.066329 0.0864189 0.0679616 0.024135 0.086019 0.0680421 +0.0250016 0.0864717 0.0230764 0.0662826 0.0864426 0.0229442 0.00414062 0.064563 0.045468 +0.08709 0.0645551 0.0454507 0.0370307 0.0905961 0.0454534 0.0543286 0.0905705 0.0459802 +0.0386833 0.0908824 0.0752783 0.0386561 0.0908782 0.0156443 0.0888804 0.0598906 0.0149344 +0.00247422 0.0602806 0.0762392 0.0139901 0.07861 0.0753727 0.077257 0.0785906 0.0753508 +0.0772502 0.0785971 0.0155546 0.0139743 0.0785946 0.0155529 0.0887925 0.0601607 0.0760735 +0.00243561 0.0601638 0.0148292 0.0534961 0.0907251 0.0760211 0.0534831 0.0907274 0.0148677 +0.0155313 0.0800352 0.0590389 0.0759756 0.0797861 0.0590724 0.0160014 0.0804445 0.031042 +0.0752418 0.0804307 0.031276 0.00194578 0.0585778 0.0578036 0.00194682 0.0585814 0.0331337 +0.0892817 0.0585764 0.0577825 0.0892821 0.0585751 0.0331192 0.0619438 0.0883791 0.0362027 +0.0296529 0.0885195 0.0361615 0.0298036 0.0885757 0.0545486 0.0615675 0.088522 0.0548076 +0.0105111 0.0748371 0.0490109 0.0807272 0.0748235 0.0488449 0.0261592 0.0870402 0.0821894 +0.0258492 0.0868919 0.00887962 0.0639639 0.0875451 0.0797552 0.0639274 0.0875612 0.0111658 +0.0082476 0.0718416 0.0375936 0.082983 0.0718365 0.0375833 0.0835825 0.0709487 0.0796548 +0.00764922 0.0709556 0.0112426 0.00795329 0.0714114 0.0797872 0.0835197 0.0710438 0.0111868 +0.05619 0.0901662 0.0627603 0.0351217 0.0901864 0.0636415 0.0336503 0.0898112 0.0280594 +0.0561283 0.0901809 0.0271421 0.0901314 0.0551387 0.0234403 0.00109073 0.0551146 0.067434 +0.00108435 0.0550835 0.0235978 0.090144 0.0550776 0.0673125 0.0455129 0.0914137 0.0402162 +0.00110334 0.0551757 0.0483299 0.00628355 0.0687465 0.0535804 0.0901241 0.0551741 0.048315 +0.0849579 0.0687218 0.0535487 0.0455049 0.0914137 0.0511854 0.0457357 0.0914136 0.0822438 +0.0457073 0.0914137 0.00869425 0.0192783 0.0830074 0.0822982 0.0191552 0.0829196 0.00858297 +0.0721756 0.0828452 0.00849148 0.0721837 0.0828394 0.0823868 0.0375217 0.0906878 0.0359104 +0.0641956 0.087442 0.0455866 0.0274058 0.0876077 0.045455 0.0372271 0.0906334 0.0545977 +0.046348 0.0914079 0.0702304 0.0463409 0.091408 0.0206691 0.0539035 0.0906515 0.036124 +0.0134697 0.0780977 0.04066 0.0777591 0.0780961 0.0406423 0.0119766 0.0765316 0.0667208 +0.079059 0.076741 0.0667136 0.012174 0.0767473 0.0241945 0.0790605 0.0767393 0.0241874 +0.0534827 0.0907275 0.0549371 0.0785738 0.0772599 0.0833804 0.000784075 0.0534705 0.0399585 +0.0904427 0.0534726 0.0399463 0.0126679 0.0772753 0.00756263 0.0902744 0.0544154 0.0824266 +0.0785072 0.07733 0.00751125 0.000952918 0.0544167 0.00847953 0.000962249 0.0544658 0.0823932 +0.0131789 0.0778042 0.0833705 0.090281 0.0543809 0.00847512 0.0356781 0.0903147 0.00822737 +0.0356492 0.0903082 0.082736 0.0880783 0.062172 0.0678763 0.0032083 0.0623269 0.0230691 +0.00316155 0.0622052 0.0679962 0.0880038 0.0623656 0.0229039 0.0703018 0.0841247 0.0370786 +0.0227592 0.0852504 0.0537232 0.0208251 0.0840597 0.0371393 0.0715578 0.0832823 0.0744195 +0.0715471 0.0832897 0.0164704 0.070572 0.0839486 0.0536988 0.0185934 0.0825109 0.0684193 +0.0226404 0.085181 0.0168169 0.0551317 0.0904061 0.0841242 0.0549917 0.0904358 0.00675576 +0.0313004 0.0891014 0.0726062 0.0312317 0.0890786 0.0182116 0.0729918 0.0822435 0.066433 +0.0729891 0.0822455 0.0244603 0.0804749 0.0751277 0.0584296 0.00480126 0.0659708 0.033145 +0.086429 0.0659645 0.0331369 0.0108285 0.0752186 0.0584593 0.0182401 0.0822471 0.024487 +0.00858993 0.0723289 0.0724136 0.0827839 0.0721217 0.0720382 0.00853622 0.0722533 0.0186213 +0.0826629 0.0722928 0.0186044 0.0874746 0.0636725 0.0830247 0.0592499 0.0893201 0.0708035 +0.0037536 0.0636751 0.00787896 0.059801 0.089143 0.0199071 0.00381565 0.0638209 0.0831031 +0.0873801 0.0638942 0.00780371 0.021867 0.0847177 0.0752516 0.090498 0.0531345 0.0159819 +0.0224273 0.0850554 0.0613586 0.00074381 0.0532261 0.0751819 0.0904751 0.0532769 0.0752047 +0.000751799 0.0532752 0.0157035 0.0678864 0.0855829 0.0605503 0.00048948 0.051429 0.0318181 +0.0907381 0.0514254 0.0590908 0.00048888 0.051424 0.0590908 0.0237 0.0857827 0.030424 +0.0907382 0.051424 0.0318181 0.0673052 0.0859041 0.0304479 0.0102317 0.074494 0.0309757 +0.0804469 0.0751611 0.0311565 0.0156708 0.0801578 0.0515997 0.0758353 0.0799115 0.0514966 +0.00205076 0.0589356 0.0400044 0.0891768 0.0589342 0.0399867 0.000299638 0.0495297 0.0878428 +0.004178 0.0646461 0.0604919 0.0870511 0.0646418 0.0604694 0.00321992 0.0623569 0.0520708 +0.0880096 0.0623507 0.0520504 0.0282462 0.0879651 0.0619428 0.0862723 0.0662809 0.0741153 +0.0049576 0.0662866 0.0167849 0.00500489 0.0663809 0.074207 0.0861952 0.0664345 0.0167058 +0.00726891 0.0703682 0.0447781 0.0838987 0.0704615 0.0442725 0.0401487 0.0910841 0.0689387 +0.0398919 0.0910523 0.0223666 0.0528894 0.0908277 0.0693333 0.00768095 0.0446009 0.999996 +0.00267987 0.0460431 0.999996 0.074933 0.0351498 0.354164 0.0683198 0.0356716 0.430812 +0.0604255 0.0361765 0.498537 0.0576162 0.0365435 0.560878 0.0499555 0.037039 0.619167 +0.047169 0.0373382 0.672898 0.037082 0.035092 0.323057 0.111639 0.0348074 0.322629 +0.0401793 0.0378432 0.721627 0.0437169 0.0356491 0.388487 0.100558 0.0351348 0.394652 +0.0900427 0.0354905 0.468782 0.0392725 0.0379751 0.766677 0.0387145 0.0363267 0.460726 +0.0838903 0.0357461 0.53257 0.0359346 0.0369326 0.52831 0.115066 0.0349119 0.360402 +0.0728587 0.034881 0.312185 0.0354983 0.0382796 0.80788 0.0344953 0.0383107 0.84824 +0.0338487 0.0374286 0.585785 0.105092 0.035178 0.432665 0.0771594 0.0359953 0.594043 +0.0297482 0.0361622 0.427599 0.0956686 0.0354338 0.498947 0.028164 0.0354825 0.357617 +0.0702017 0.0362472 0.649098 0.0283632 0.0380565 0.643704 0.0296618 0.0387446 0.880075 +0.063706 0.0364858 0.701625 0.0255964 0.0391455 0.911839 0.0284341 0.0367953 0.492471 +0.0877282 0.0356579 0.563622 0.134637 0.0346757 0.301947 0.0253898 0.0374693 0.558477 +0.0716042 0.0354696 0.402465 0.0262242 0.0385213 0.696001 0.0231723 0.0393534 0.942499 +0.0572165 0.0367581 0.745647 0.0508303 0.0370918 0.780448 0.0799983 0.0358724 0.622324 +0.0649106 0.0358775 0.458582 0.0503429 0.034842 0.300225 0.0232891 0.0348675 0.297538 +0.0979563 0.0347463 0.300337 0.0238174 0.0380143 0.614944 0.0239047 0.0389689 0.745241 +0.131719 0.0347655 0.339606 0.119388 0.034968 0.411889 0.0723587 0.0360954 0.67659 +0.124172 0.0348881 0.384889 0.0466294 0.0372397 0.823801 0.0509529 0.0352267 0.345109 +0.0890632 0.0349482 0.33281 0.0822776 0.0352347 0.378392 0.0216957 0.0360089 0.402888 +0.0590477 0.036399 0.537097 0.113268 0.0350811 0.456703 0.0491197 0.0357915 0.412719 +0.0657502 0.0363024 0.722528 0.0214009 0.0393789 0.785393 0.0220482 0.0393681 0.967533 +0.0214218 0.0385807 0.67071 0.0541412 0.0354068 0.369874 0.109765 0.035144 0.482169 +0.0205447 0.039657 0.827133 0.0489615 0.0360165 0.441817 0.089541 0.0353312 0.416099 +0.0171997 0.0357877 0.378485 0.0858133 0.0354909 0.445919 0.0541726 0.0368008 0.597488 +0.103532 0.0352576 0.522151 0.0178514 0.0365473 0.448772 0.071407 0.0358683 0.479973 +0.016915 0.0353144 0.33598 0.0610452 0.0363985 0.766327 0.0437169 0.0372433 0.864259 +0.045682 0.0363782 0.483297 0.018637 0.0391156 0.718769 0.0766733 0.0358802 0.513586 +0.0172863 0.0368189 0.4733 0.0999366 0.0353228 0.54679 0.049931 0.0371207 0.641992 +0.0172659 0.0372594 0.515055 0.0158848 0.0375232 0.537081 0.0675697 0.0350427 0.332262 +0.0177448 0.0400773 0.860671 0.0532838 0.0367732 0.804086 0.094426 0.0350599 0.361697 +0.0191659 0.0394226 0.765142 0.0947743 0.0354161 0.582329 0.0160435 0.0379365 0.577639 +0.140898 0.0346952 0.321154 0.0420255 0.0366277 0.507034 0.116967 0.0346767 0.292342 +0.0692873 0.034748 0.292748 0.106321 0.034896 0.339623 0.0394066 0.037431 0.897844 +0.134974 0.034777 0.362996 0.0160657 0.0381276 0.59669 0.0426142 0.0369058 0.548807 +0.0915876 0.0354669 0.606719 0.0714849 0.0361637 0.574914 0.0453485 0.0374807 0.692495 +0.106348 0.0350277 0.377491 0.074918 0.0360129 0.549158 0.0587753 0.0363168 0.51863 +0.0123004 0.0351153 0.316994 0.0162667 0.0403704 0.894818 0.0398636 0.0371278 0.570171 +0.124212 0.0349161 0.427607 0.0554812 0.0349765 0.317528 0.0351948 0.0376565 0.928306 +0.0861678 0.0355771 0.6398 0.0264819 0.0383563 0.983359 0.148894 0.0346285 0.290736 +0.0147057 0.0385308 0.63205 0.0837915 0.0355932 0.66269 0.0355768 0.0376582 0.629207 +0.062114 0.0354519 0.38499 0.0160371 0.0399333 0.80454 0.0537529 0.0367461 0.580462 +0.0676663 0.0363444 0.609318 0.0352412 0.0352784 0.341389 0.0645937 0.0364863 0.63165 +0.0515924 0.036629 0.84155 0.0151 0.0406018 0.924784 0.037779 0.035556 0.372328 +0.0138411 0.0403957 0.843935 0.112963 0.0350666 0.500388 0.0916235 0.0348501 0.316602 +0.0411732 0.0378167 0.739955 0.036892 0.0374417 0.602939 0.0789237 0.0356937 0.692671 +0.0783501 0.0357876 0.495007 0.0127013 0.0363009 0.420016 0.0375456 0.0347551 0.288762 +0.0417495 0.0375321 0.655451 0.0616638 0.03663 0.663334 0.0122696 0.0388682 0.655213 +0.0318649 0.0378002 0.956108 0.0854421 0.0346998 0.288845 0.00977253 0.0348863 0.288204 +0.0923317 0.0354794 0.483205 0.0461139 0.036786 0.882063 0.132176 0.0348203 0.399804 +0.0769918 0.0356994 0.710778 0.0723279 0.0358232 0.735864 0.0335728 0.0380513 0.681668 +0.0484282 0.0373388 0.709099 0.0127447 0.0391436 0.685148 0.119142 0.0347343 0.309107 +0.037164 0.0358391 0.402514 0.0526738 0.0361454 0.46839 0.0332188 0.0362649 0.44375 +0.0364713 0.0381993 0.789035 0.0413743 0.0369761 0.913632 0.0102497 0.0356737 0.363696 +0.102394 0.0352047 0.569951 0.104816 0.0351493 0.416959 0.124345 0.0349091 0.446272 +0.0133922 0.0406408 0.876905 0.0587464 0.0367715 0.684804 0.0646536 0.0356278 0.415608 +0.121194 0.0349416 0.469574 0.0849245 0.0352871 0.393848 0.0370869 0.0349376 0.307226 +0.0112296 0.0371082 0.489171 0.0135909 0.0408754 0.954371 0.148715 0.0346534 0.308295 +0.0281407 0.035803 0.389222 0.0318125 0.038293 0.71039 0.0121706 0.0396362 0.733249 +0.0829375 0.0354709 0.430065 0.0282645 0.0386002 0.729263 0.1267 0.0347588 0.325806 +0.0532959 0.035843 0.426407 0.101006 0.0352647 0.447606 0.00927539 0.0365314 0.435968 +0.0322462 0.0365747 0.476285 0.0708514 0.0352703 0.368712 0.0699721 0.0358545 0.753541 +0.13411 0.034638 0.287142 0.0117766 0.0393755 0.703547 0.0114185 0.0412784 0.983812 +0.05459 0.0356247 0.398815 0.0653811 0.0359822 0.779533 0.0536652 0.0370221 0.730472 +0.0884974 0.0350321 0.348068 0.115129 0.0349943 0.397337 0.0439512 0.0353704 0.356822 +0.136514 0.0347749 0.37951 0.0711372 0.0357063 0.444715 0.0302153 0.0371852 0.541244 +0.0562386 0.0347135 0.286435 0.0342023 0.0383744 0.832114 0.0469388 0.0374351 0.754332 +0.078701 0.0356537 0.459364 0.140957 0.0347273 0.350216 0.0943945 0.0353129 0.621007 +0.06989 0.0360878 0.52819 0.109953 0.0350773 0.535255 0.104192 0.0352417 0.468922 +0.0912832 0.035548 0.516979 0.0490207 0.0351157 0.330978 0.10387 0.0346676 0.28673 +0.145293 0.0346929 0.335605 0.010035 0.0360019 0.391564 0.00978752 0.0378528 0.552266 +0.0608302 0.0352498 0.355548 0.00708469 0.0360955 0.347914 0.0638959 0.0359683 0.794417 +0.0593951 0.0361139 0.819038 0.0381813 0.0369988 0.942115 0.119576 0.0348459 0.346254 +0.00931277 0.0368314 0.461913 0.00728696 0.0356558 0.303722 0.023685 0.0365837 0.461333 +0.0827508 0.0347868 0.301855 0.122704 0.0348771 0.369738 0.0297718 0.0386242 0.756028 +0.0538965 0.0362437 0.855223 0.0283509 0.0360467 0.413943 0.0108346 0.0398988 0.751881 +0.0231715 0.0347306 0.284997 0.011503 0.0410455 0.908824 0.0102262 0.0401685 0.776025 +0.0298137 0.0369138 0.508816 0.0585656 0.036148 0.48644 0.0279795 0.0381841 0.659267 +0.0645793 0.0348415 0.303874 0.00827032 0.0373468 0.504163 0.13063 0.0348358 0.418434 +0.0237016 0.0351609 0.324737 0.0495673 0.0365936 0.528312 0.0857238 0.0354194 0.678588 +0.105766 0.0347704 0.309089 0.0410373 0.0365593 0.495128 0.0631782 0.0364673 0.590059 +0.0481393 0.0361326 0.455733 0.099524 0.0352177 0.595949 0.00968925 0.0385036 0.610658 +0.0947948 0.0351408 0.381428 0.0308826 0.0386418 0.867676 0.086168 0.0356988 0.545192 +0.114493 0.0350063 0.516373 0.0786847 0.0349437 0.324562 0.00594766 0.0370248 0.407367 +0.0276939 0.0388448 0.774198 0.0081927 0.0380466 0.565296 0.0780239 0.0350528 0.341466 +0.0310229 0.0386754 0.819401 0.071205 0.0361528 0.564862 0.106225 0.0351214 0.558548 +0.101353 0.0348804 0.330199 0.0102087 0.0403205 0.792474 0.0249776 0.0391536 0.798966 +0.0965315 0.0354244 0.532962 0.00802594 0.0376004 0.525649 0.0596026 0.0364481 0.551732 +0.076676 0.0355037 0.419592 0.0338924 0.0371608 0.972269 0.0264306 0.0375385 0.569877 +0.0228255 0.0372613 0.528591 0.117749 0.0348219 0.334472 0.00993673 0.040577 0.818836 +0.0414461 0.0359907 0.425563 0.119538 0.034945 0.490299 0.025491 0.0350244 0.312573 +0.0786489 0.0354834 0.72797 0.0261387 0.0356332 0.370853 0.0844085 0.0357566 0.57583 +0.075451 0.03534 0.38661 0.058096 0.0367854 0.6517 0.0397923 0.0374198 0.616993 +0.0888042 0.0354159 0.65122 0.0352616 0.0379 0.66887 0.0517684 0.0370509 0.772189 +0.12384 0.0349078 0.458243 0.10391 0.0349728 0.35608 0.00606358 0.0363794 0.328613 +0.0288508 0.0388026 0.891394 0.0208091 0.0363798 0.437096 0.0591934 0.0359984 0.831346 +0.131421 0.034714 0.314381 0.0106671 0.0414106 0.973222 0.0818253 0.0351571 0.363297 +0.020112 0.0354376 0.348608 0.00840544 0.0391713 0.666957 0.00932646 0.0415147 0.939134 +0.0399387 0.0379277 0.781348 0.0819537 0.0353657 0.403935 0.00571903 0.0385834 0.585831 +0.0469925 0.0373347 0.797 0.079413 0.0359125 0.605871 0.0462807 0.0370281 0.587998 +0.0924792 0.0354146 0.454964 0.0452972 0.0374139 0.813109 0.112019 0.0350926 0.442387 +0.103197 0.0352731 0.509117 0.0979696 0.0352048 0.407976 0.0597899 0.0358937 0.447532 +0.0657976 0.0351412 0.344764 0.0544963 0.0369847 0.719611 0.00806373 0.0389118 0.641867 +0.00451894 0.0380538 0.44581 0.0510968 0.0369504 0.607598 0.0947305 0.0353271 0.435144 +0.13788 0.0347634 0.389924 0.0521806 0.0362101 0.872182 0.0630675 0.035965 0.468758 +0.0280465 0.0377156 0.597444 0.0517439 0.0355099 0.380433 0.104104 0.0352555 0.49349 +0.0239525 0.0393932 0.85064 0.0800136 0.0356676 0.468947 0.066578 0.0360921 0.508877 +0.00910978 0.0407745 0.83274 0.131261 0.0347908 0.353574 0.0257457 0.0391924 0.838301 +0.0638581 0.0365029 0.62032 0.00817533 0.0386873 0.622061 0.0769314 0.0359796 0.633108 +0.0220366 0.0378287 0.586715 0.0881523 0.0356172 0.593505 0.0664421 0.0349688 0.32146 +0.0963736 0.0352751 0.424748 0.0213139 0.0368735 0.485857 0.0540194 0.036369 0.508195 +0.0469892 0.0372033 0.630883 0.115408 0.0350257 0.421146 0.094661 0.0352546 0.632076 +0.0449703 0.0369124 0.560408 0.0391969 0.0360973 0.434528 0.105192 0.0349986 0.365756 +0.0427199 0.0368228 0.536864 0.0242928 0.0380908 0.626292 0.0365322 0.0379855 0.701009 +0.038721 0.0375893 0.639864 0.00831945 0.0410469 0.855058 0.00790191 0.0411888 0.866378 +0.158518 0.0346096 0.284238 0.0760041 0.0346714 0.283269 0.108754 0.0350799 0.406281 +0.105306 0.0350777 0.580942 0.0920416 0.035127 0.372753 0.047868 0.036237 0.905032 +0.125323 0.0346325 0.282888 0.00793876 0.0360804 0.374862 0.0719023 0.0361543 0.660538 +0.0719052 0.0360731 0.54031 0.0724711 0.0355609 0.767438 0.0627993 0.0365122 0.711754 +0.114003 0.0349869 0.387924 0.0255114 0.0391067 0.92311 0.0673824 0.0363115 0.691328 +0.0189801 0.0370811 0.501525 0.00619316 0.0378262 0.515921 0.0685545 0.0359686 0.490141 +0.0494807 0.0362167 0.893539 0.020548 0.0396104 0.816801 0.112899 0.035026 0.525057 +0.0390064 0.0376902 0.874351 0.0466752 0.0346783 0.281598 0.0864189 0.0356356 0.502072 +0.0840186 0.0357239 0.520279 0.0207437 0.0374945 0.547122 0.022544 0.038608 0.681196 +0.0362242 0.0368517 0.518965 0.00610254 0.0375359 0.478697 0.0474131 0.034938 0.310203 +0.0562226 0.0367889 0.756174 0.058945 0.0358226 0.434496 0.0959734 0.0354217 0.556498 +0.0423076 0.036355 0.471914 0.0429417 0.0374004 0.854962 0.0613958 0.0364721 0.572173 +0.109227 0.034719 0.299337 0.0482714 0.0365583 0.517631 0.110753 0.0350309 0.54526 +0.0505224 0.0371494 0.661669 0.151903 0.0346569 0.324324 0.0514688 0.0363278 0.492664 +0.00792632 0.0397975 0.723093 0.0679647 0.0354905 0.807299 0.0448473 0.036318 0.924099 +0.0186172 0.0384643 0.642313 0.0956866 0.0349626 0.342139 0.00637131 0.0403591 0.766539 +0.0222694 0.0388043 0.705406 0.0822899 0.0356803 0.485757 0.154468 0.0346311 0.299938 +0.058548 0.035127 0.33777 0.0308834 0.0356782 0.379164 0.0206442 0.0398134 0.886467 +0.0355159 0.0371623 0.55676 0.083075 0.0354076 0.702708 0.0950671 0.0346481 0.281728 +0.0357036 0.0365991 0.486705 0.10126 0.0353028 0.47771 0.0500459 0.0368158 0.570414 +0.0309471 0.036403 0.454943 0.0607998 0.0366553 0.641961 0.0658743 0.0363914 0.597775 +0.123403 0.034886 0.480499 0.102021 0.0348226 0.318059 0.00712163 0.0421523 0.99285 +0.0804894 0.0357941 0.648689 0.0230546 0.0393199 0.95095 0.00776882 0.0413811 0.887642 +0.102933 0.0352514 0.458411 0.0908653 0.0352155 0.670375 0.0617145 0.0366255 0.674748 +0.0408655 0.0371591 0.579897 0.130663 0.0348232 0.437572 0.127979 0.0346696 0.295124 +0.0331134 0.0384292 0.857119 0.0389906 0.0359167 0.41347 0.0217132 0.0396682 0.871165 +0.135725 0.0347794 0.409571 0.102655 0.0350421 0.610997 0.0529324 0.0365976 0.544448 +0.0776208 0.0359763 0.583663 0.0746795 0.0348084 0.302466 0.0300721 0.0385947 0.902567 +0.0438029 0.0374473 0.834102 0.00434262 0.0390503 0.576643 0.113306 0.0346408 0.282773 +0.145141 0.0347046 0.364585 0.136037 0.0347299 0.330851 0.00383844 0.0379192 0.339375 +0.062644 0.0353762 0.374825 0.0654296 0.0346699 0.282054 0.0437485 0.0375383 0.682985 +0.142054 0.0346219 0.283646 0.0880169 0.0352461 0.687497 0.028032 0.0385681 0.720662 +0.0554217 0.0369449 0.694008 0.0355975 0.035388 0.352928 0.00696402 0.0400636 0.742518 +0.0334303 0.0383441 0.747382 0.0198172 0.0362874 0.427055 0.00667298 0.0357235 0.279817 +0.00513593 0.0388566 0.596038 0.0331147 0.0369106 0.99013 0.0385778 0.0365123 0.963441 +0.0640769 0.0363692 0.731334 0.0413288 0.0361944 0.449827 0.0784364 0.0359388 0.567568 +0.00549797 0.0396694 0.695556 0.0171508 0.0349914 0.307473 0.00596672 0.0381221 0.541877 +0.0438518 0.036273 0.934148 0.0367259 0.0378613 0.887243 0.125492 0.0348418 0.361433 +0.0201709 0.0395301 0.988673 0.00415338 0.038177 0.426801 0.00533102 0.0395231 0.677396 +0.063606 0.0355674 0.404315 0.0199516 0.0380811 0.606263 0.0850137 0.0357356 0.553501 +0.0170165 0.0377983 0.56696 0.0204561 0.0392649 0.755191 0.0186935 0.0358727 0.387412 +0.082456 0.0353297 0.718132 0.0769756 0.035435 0.74683 0.00551477 0.0398451 0.713024 +0.113636 0.0349472 0.369809 0.0285495 0.0379903 0.635685 0.0162986 0.0390493 0.69511 +0.0313045 0.0351954 0.331093 0.0690263 0.0360758 0.518895 0.0582919 0.036699 0.612246 +0.143995 0.0346543 0.301252 0.0411726 0.0348476 0.298861 0.0041345 0.0379317 0.383549 +0.059031 0.0347879 0.295769 0.0731014 0.0359675 0.70138 0.00683167 0.0417483 0.918557 +0.0194694 0.0361123 0.410265 0.0580083 0.0350479 0.327467 0.0199211 0.0399169 0.903967 +0.0731744 0.0354974 0.410457 0.0698986 0.0359794 0.49918 0.00358393 0.0385513 0.415562 +0.121298 0.0347539 0.317016 0.0263112 0.0389335 0.932577 0.0193118 0.0397912 0.97762 +0.0855393 0.0356712 0.615342 0.0941121 0.0354847 0.523791 0.0600221 0.0357105 0.847492 +0.0722772 0.035311 0.377006 0.0283604 0.0375582 0.579394 0.11442 0.0350493 0.431683 +0.0757207 0.035595 0.435637 0.0458668 0.0357074 0.397877 0.0886565 0.0355703 0.492712 +0.134496 0.0347814 0.426643 0.00704926 0.0420191 0.963009 0.0487026 0.0372978 0.763575 +0.0601542 0.0363328 0.528845 0.0649247 0.0354907 0.394699 0.0857807 0.0356243 0.630099 +0.043946 0.0352123 0.339152 0.0173276 0.0402739 0.915851 0.0254427 0.0391405 0.806322 +0.0941955 0.0354532 0.572207 0.0563056 0.0368187 0.628869 0.154789 0.0346417 0.315066 +0.0308517 0.0386322 0.782952 0.0563983 0.03585 0.864441 0.0374008 0.0380375 0.730802 +0.0467453 0.0350442 0.321807 0.016189 0.0346988 0.28169 0.103416 0.0350827 0.386873 +0.00135174 0.0435716 0.995862 0.0452085 0.0354417 0.365941 0.14923 0.0346768 0.344186 +0.0800129 0.0357382 0.67106 0.0342871 0.0380624 0.691109 0.00727298 0.041533 0.898805 +0.0138143 0.0348843 0.297502 0.0864955 0.0355742 0.47643 0.00380758 0.0386763 0.468195 +0.09575 0.0351589 0.642011 0.0532635 0.0353426 0.360979 0.071448 0.0357917 0.463183 +0.0530687 0.0355695 0.389557 0.0537513 0.0361854 0.477441 0.0935413 0.0348867 0.324789 +0.00335253 0.0384453 0.356224 0.0170226 0.0383387 0.621856 0.0310279 0.0346945 0.282192 +0.0387625 0.037327 0.595332 0.00402387 0.0376168 0.31279 0.0214326 0.0384262 0.652065 +0.0047546 0.0406884 0.785223 0.0505032 0.0372124 0.739026 0.0407469 0.0377855 0.7122 +0.0355649 0.0366463 0.981263 0.00661232 0.0419924 0.947316 0.0195749 0.0355833 0.361598 +0.0926058 0.0352362 0.400296 0.0706285 0.0354996 0.787333 0.13959 0.0346807 0.31 +0.00321085 0.0382962 0.296926 0.0202448 0.0385574 0.661174 0.032789 0.0381166 0.917638 +0.0253509 0.0371011 0.518129 0.12344 0.0349056 0.39381 0.0355289 0.0354852 0.363014 +0.0191953 0.0391484 0.727339 0.0780332 0.0357853 0.683249 0.0480549 0.0364554 0.501217 +0.0245971 0.0353217 0.340167 0.0408658 0.0364 0.950859 0.048759 0.0372002 0.650984 +0.0701413 0.0362566 0.639926 0.0185566 0.039534 0.775046 0.0972754 0.0347973 0.309867 +0.0720498 0.036184 0.624146 0.0314463 0.0380125 0.945668 0.123024 0.0348531 0.50003 +0.0322179 0.0377277 0.619538 0.0824314 0.03488 0.316564 0.0752224 0.0360632 0.615743 +0.0139797 0.0390047 0.677266 0.0551107 0.0357536 0.417191 0.0373176 0.0376942 0.648094 +0.0789369 0.0358869 0.540334 0.031579 0.0384332 0.73846 0.066175 0.0361738 0.74374 +0.00354386 0.0390441 0.497051 0.0364016 0.0357693 0.394033 0.0290562 0.0358825 0.398104 +0.0153867 0.0352184 0.326914 0.131109 0.0347999 0.451183 0.0558308 0.0367087 0.588143 +0.0938319 0.0351411 0.659785 0.00515576 0.0408711 0.805832 0.030427 0.0365277 0.467502 +0.00301587 0.0389861 0.39901 0.0157955 0.0357038 0.369951 0.0325992 0.0348518 0.297662 +0.0481161 0.0347673 0.291463 0.0211667 0.039087 0.735905 0.0337747 0.0367579 0.500832 +0.00494291 0.03924 0.633804 0.105016 0.035048 0.590984 0.0178098 0.0402069 0.934125 +0.0685299 0.0352289 0.359843 0.0330222 0.0376443 0.611965 0.0400153 0.0356107 0.380334 +0.0782791 0.034743 0.293939 0.00270712 0.0397245 0.487214 0.0949596 0.0346998 0.290834 +0.0294684 0.0380785 0.96521 0.0546256 0.0367265 0.793812 0.0555192 0.0360259 0.457628 +0.122829 0.0349211 0.403005 0.00204735 0.0396979 0.286563 0.0522464 0.0366615 0.553052 +0.0429866 0.0374727 0.843451 0.0542026 0.0357635 0.885813 0.0688234 0.0362859 0.668508 +0.0725528 0.0359129 0.718775 0.00243792 0.0394855 0.367798 0.0847178 0.0351045 0.357298 +0.028858 0.0387231 0.764824 0.118074 0.0349306 0.378203 0.0784854 0.0356186 0.449943 +0.0729103 0.0354409 0.776263 0.0858599 0.0346436 0.280105 0.144422 0.0347087 0.374766 +0.0455489 0.0371174 0.600311 0.0635741 0.0364338 0.582371 0.042787 0.0376633 0.803945 +0.0123425 0.0360928 0.401427 0.000694316 0.0424405 0.277526 0.0309864 0.0372289 0.548976 +0.0171924 0.0400121 0.834792 0.0155004 0.0405607 0.944424 0.111504 0.0349018 0.349322 +0.0385444 0.0379962 0.819016 0.0805195 0.0352782 0.73838 0.113033 0.0350862 0.465313 +0.0953871 0.0350128 0.352638 0.0151743 0.0395403 0.744327 0.0592913 0.0364784 0.774639 +0.00487431 0.0413139 0.845679 0.00313677 0.0404846 0.68617 0.0193504 0.0369957 0.493976 +0.0333234 0.0350225 0.3147 0.0403599 0.0351577 0.331364 0.112615 0.0350923 0.47514 +0.00340866 0.0395014 0.557489 0.0293404 0.0371344 0.532654 0.0788273 0.0349925 0.332401 +0.1041 0.0352552 0.501759 0.0626942 0.0349132 0.312489 0.0768762 0.0353397 0.757783 +0.0133839 0.0355393 0.354006 0.00640338 0.0418958 0.929662 0.110363 0.0349791 0.564842 +0.141628 0.0347236 0.396832 0.139816 0.0347257 0.341273 0.00379009 0.0399068 0.656364 +0.0619756 0.0357176 0.424539 0.0859758 0.0357006 0.585318 0.125719 0.0347839 0.334268 +0.0551248 0.0369595 0.703865 0.0386475 0.0380091 0.756419 0.00458234 0.0386168 0.533473 +0.158604 0.0346173 0.292499 0.0379819 0.0375262 0.906198 0.143385 0.0347146 0.383069 +0.016629 0.0366589 0.45734 0.0290137 0.038236 0.674311 0.128069 0.0348134 0.473055 +0.0426008 0.0375331 0.665282 0.11091 0.034845 0.331935 0.0646328 0.0355713 0.82458 +0.0494866 0.03583 0.915388 0.131591 0.0348092 0.370338 0.0514667 0.0365903 0.536004 +0.00306131 0.0392275 0.456044 0.147824 0.0346863 0.356652 0.0550116 0.0369511 0.669981 +0.0147789 0.0406717 0.962778 0.119443 0.034707 0.301551 0.0175284 0.039743 0.794529 +0.0165681 0.0367512 0.465797 0.0465676 0.036212 0.462916 0.0939956 0.0354878 0.541182 +0.0863894 0.0352345 0.385656 0.0455831 0.037487 0.701275 0.0560761 0.0348849 0.306725 +0.0336726 0.0360431 0.420324 0.00428179 0.0411468 0.823772 0.00265494 0.0390264 0.321367 +0.107558 0.0351309 0.424776 0.013932 0.036968 0.48132 0.033151 0.0372933 0.564833 +0.127541 0.0347051 0.306804 0.0725238 0.036161 0.601727 0.0664063 0.0363817 0.682332 +0.0651339 0.0364702 0.656036 0.00506064 0.0416002 0.876227 0.112578 0.0347711 0.313984 +0.127567 0.0348725 0.409827 0.0438578 0.0352981 0.348645 0.0158326 0.0373783 0.523162 +0.135407 0.0346159 0.279624 0.0440876 0.0357965 0.406273 0.0532442 0.0367034 0.814581 +0.0480506 0.0359667 0.433547 0.0461232 0.0374906 0.727332 0.084979 0.03524 0.710846 +0.0278751 0.0353937 0.348787 0.0332483 0.0384672 0.798636 0.0634282 0.0360092 0.478126 +0.0962601 0.0354135 0.491097 0.122816 0.0349318 0.418627 0.0136047 0.0399822 0.784431 +0.0296995 0.0362492 0.436606 0.121757 0.0349498 0.436862 0.116541 0.0350278 0.449971 +0.0664392 0.0355127 0.816315 0.0230556 0.0361685 0.41965 0.102945 0.0350773 0.601036 +0.0522942 0.0370969 0.67932 0.0158495 0.0402389 0.852218 0.0141487 0.0393148 0.711342 +0.0854027 0.0350088 0.340572 0.0934419 0.0351906 0.390766 0.0259629 0.0364 0.446503 +0.137977 0.0346503 0.293877 0.0403445 0.0350079 0.315482 0.0100326 0.0383978 0.60214 +0.00498596 0.0423159 0.954945 0.0166348 0.0377201 0.558134 0.156967 0.0346314 0.307858 +0.0441122 0.0375912 0.789061 0.0761181 0.0355492 0.427317 0.0758283 0.0353883 0.395857 +0.117085 0.0349003 0.533046 0.128305 0.0348445 0.378653 0.0801661 0.0352011 0.369022 +0.0122375 0.0365684 0.44301 0.0293152 0.0349375 0.305307 0.10003 0.0350602 0.371937 +0.0610486 0.0357092 0.840087 0.0428498 0.0367493 0.526684 0.0113421 0.0358975 0.383654 +0.059271 0.036415 0.784755 0.118806 0.0347937 0.326829 0.107554 0.0350687 0.396102 +0.0965458 0.0353938 0.564501 0.108894 0.035147 0.450482 0.0845352 0.0354212 0.423129 +0.101898 0.0350265 0.619808 0.0116968 0.0364024 0.42778 0.0858554 0.0356856 0.601178 +0.105702 0.0346283 0.279149 0.0970036 0.0352391 0.415377 0.0262593 0.0385296 0.974327 +0.00292751 0.0402052 0.615761 0.102213 0.035273 0.538385 0.0750635 0.0359717 0.533007 +0.0586938 0.0352023 0.347552 0.111969 0.0350571 0.413564 0.109104 0.0349848 0.573547 +0.0540383 0.0356945 0.40738 0.0259942 0.0391867 0.860681 0.0420135 0.0373715 0.624043 +0.111414 0.0351087 0.489545 0.0242533 0.0357587 0.381435 0.0707654 0.0357519 0.452637 +0.0775228 0.0359404 0.641476 0.00212033 0.0401686 0.437153 0.0241994 0.0367278 0.476757 +0.0283973 0.038923 0.826868 0.0675446 0.0359807 0.759318 0.0131238 0.0376729 0.544283 +0.0408657 0.0361382 0.442175 0.0620347 0.0353117 0.365122 0.0668136 0.0357339 0.43812 +0.0270145 0.0384308 0.688627 0.1011 0.0352473 0.439436 0.070742 0.0353725 0.797681 +0.146954 0.0346668 0.315322 0.133509 0.0347238 0.321954 0.0546782 0.0364885 0.824893 +0.0935941 0.0353695 0.444465 0.0961258 0.0353763 0.464914 0.112415 0.0349544 0.554923 +0.103546 0.0352494 0.529825 0.11984 0.0348974 0.510354 0.0391208 0.0377464 0.676181 +0.00468198 0.0401972 0.733566 0.102438 0.0349508 0.348101 0.0672323 0.0362478 0.556343 +0.0283318 0.0388529 0.790958 0.0585848 0.0366679 0.604837 0.0804661 0.0350799 0.348212 +0.15248 0.0346583 0.334993 0.0498059 0.0372482 0.74745 0.0819759 0.0354103 0.413472 +0.0899168 0.0352985 0.408762 0.0562422 0.0346472 0.278688 0.00329919 0.0398773 0.606713 +0.0103187 0.0367025 0.452182 0.0384193 0.0346677 0.279992 0.100008 0.0352632 0.575897 +0.0773537 0.035961 0.559142 0.00410099 0.0405607 0.756492 0.0295887 0.0359573 0.406287 +0.0860899 0.0354573 0.437711 0.012913 0.0403619 0.826024 0.0229985 0.0352425 0.332037 +0.0577278 0.0367483 0.738051 0.0135725 0.0354164 0.343421 0.0294461 0.0383905 0.703518 +0.03543 0.0378531 0.661627 0.024294 0.038743 0.713207 0.00572239 0.0423601 0.979563 +0.0280827 0.0382294 0.666531 0.0265529 0.0381827 0.992876 0.0143685 0.0381019 0.588444 +0.0127607 0.0398439 0.760544 0.0671477 0.035183 0.35181 0.0704634 0.0359885 0.727983 +0.00290747 0.0398538 0.549223 0.049474 0.0367718 0.848972 0.150552 0.0346098 0.280413 +0.0761706 0.0359215 0.524242 0.086968 0.0355227 0.46129 0.0857048 0.0349177 0.324822 +0.120864 0.0348573 0.353961 0.0457529 0.0355049 0.37376 0.0334481 0.0378172 0.936361 +0.102521 0.0352849 0.485985 0.0587574 0.0367168 0.72574 0.089006 0.0348057 0.307378 +0.109328 0.0346857 0.291918 0.0225686 0.0393393 0.959667 0.0628314 0.0363559 0.751443 +0.133205 0.0347772 0.444803 0.0486683 0.0358566 0.420362 0.00357502 0.0403609 0.70432 +0.114478 0.0348582 0.34091 0.0125484 0.0371858 0.498525 0.0139605 0.0407536 0.993327 +0.051196 0.0371631 0.68689 0.0411878 0.0378259 0.748324 0.0772965 0.0358398 0.50465 +0.0202819 0.0350996 0.317975 0.0449803 0.0358756 0.944556 0.0956793 0.0354408 0.508093 +0.129021 0.03481 0.465889 0.0846972 0.0355353 0.453712 0.0373525 0.0370068 0.542783 +0.0551765 0.0368817 0.635721 0.0469051 0.0374354 0.717598 0.06636 0.0359605 0.773174 +0.0878818 0.0351907 0.696225 0.00194718 0.0406711 0.506888 0.0388694 0.037948 0.826114 +0.13027 0.0348355 0.389001 0.0280275 0.0347814 0.290208 0.0705017 0.0362144 0.586494 +0.0702689 0.0360941 0.708815 0.0783022 0.0358704 0.656175 0.0181092 0.0347916 0.289991 +0.0988868 0.0353702 0.515691 0.119453 0.0348813 0.519781 0.03838 0.0364929 0.480118 +0.003952 0.0405508 0.749521 0.00379152 0.0427832 0.986522 0.140368 0.034736 0.357767 +0.0148459 0.0372392 0.507964 0.0366114 0.0381248 0.839249 0.0932906 0.0355038 0.548999 +0.00184626 0.0400717 0.305566 0.0345323 0.0373311 0.575494 0.0227878 0.0366748 0.468872 +0.00148207 0.0408152 0.347478 0.116367 0.0348969 0.539886 0.0235151 0.0373285 0.537517 +0.0971518 0.0350452 0.650987 0.087784 0.034746 0.296869 0.001312 0.0412152 0.377356 +0.0163219 0.0382976 0.614835 0.0519465 0.0366666 0.83375 0.0946945 0.0353277 0.61411 +0.0715053 0.035831 0.471943 0.0550019 0.0369619 0.711876 0.0357867 0.0357057 0.386562 +0.110326 0.0351138 0.508818 0.0203274 0.0359446 0.395507 0.0353776 0.0382692 0.773716 +0.0611764 0.0354548 0.856593 0.0514026 0.0360375 0.449739 0.00407968 0.0410971 0.815096 +0.126685 0.0348067 0.346886 0.0641568 0.0362919 0.543904 0.112974 0.0347429 0.307061 +0.138089 0.0347465 0.416265 0.0931824 0.0354304 0.599029 0.0809003 0.0348331 0.308401 +0.115677 0.035001 0.404851 0.0100819 0.035354 0.334949 0.0130462 0.0398988 0.769273 +0.0851921 0.0356797 0.510915 0.0873067 0.0355839 0.622945 0.00328558 0.0401514 0.649065 +0.00232141 0.0397243 0.390586 0.0151413 0.0403984 0.868557 0.1449 0.0346882 0.328152 +0.0103162 0.0403721 0.799218 0.0341812 0.0382158 0.724718 0.0657131 0.0362171 0.534871 +0.0755191 0.035191 0.361461 0.0626465 0.0347263 0.28883 0.0616126 0.0360839 0.802308 +0.100619 0.0350393 0.626883 0.0201379 0.03879 0.688549 0.0944086 0.0354232 0.473712 +0.0102955 0.0369326 0.472172 0.0778282 0.0357392 0.477772 0.0227335 0.0395568 0.896097 +0.0739122 0.0349316 0.320017 0.044062 0.0376218 0.772961 0.0139918 0.0374914 0.529526 +0.0100411 0.0380693 0.572339 0.0791263 0.0355792 0.442961 0.0300007 0.037047 0.524484 +0.042981 0.0370734 0.889748 0.028126 0.0377781 0.605657 0.0693373 0.0356225 0.424493 +0.00491659 0.0419242 0.908407 0.0928768 0.0350525 0.679708 0.0215365 0.0382813 0.635567 +0.089141 0.0353897 0.430672 0.0310501 0.0379995 0.65262 0.102349 0.0347039 0.293581 +0.115825 0.0350265 0.483846 0.0640864 0.0363681 0.565462 0.0435696 0.0374132 0.646662 +0.0136936 0.0387281 0.647602 0.0704784 0.0350763 0.339059 0.0245418 0.0346655 0.279122 +0.060399 0.0361097 0.810527 0.107308 0.0351745 0.515841 0.0522822 0.0352808 0.352571 +0.0723096 0.0349783 0.325961 0.0113699 0.0362247 0.41196 0.0505586 0.0351719 0.338368 +0.102329 0.0351382 0.401735 0.0232483 0.0365172 0.454014 0.0406798 0.0378558 0.795898 +0.0218402 0.0370994 0.509567 0.0403401 0.0359344 0.974025 0.13856 0.0347553 0.370869 +0.0472139 0.0369417 0.577512 0.0353133 0.0370071 0.535794 0.0742743 0.0358374 0.48585 +0.0212455 0.0397326 0.878717 0.0291149 0.0366989 0.483473 0.125994 0.0348093 0.492715 +0.0943533 0.03541 0.591123 0.0106842 0.0404497 0.811749 0.0729368 0.0351132 0.346555 +0.00395557 0.0413489 0.838755 0.141369 0.0347203 0.404295 0.0102814 0.0350661 0.310127 +0.00193002 0.0407699 0.525967 0.0021192 0.040988 0.626099 0.0558943 0.0356791 0.87892 +0.0302169 0.0387407 0.812356 0.0301097 0.0351046 0.321707 0.0367377 0.0380142 0.863204 +0.122425 0.0348159 0.340668 0.0426701 0.0372695 0.609416 0.0498985 0.0365887 0.862236 +0.021528 0.0354967 0.354848 0.0352348 0.0381257 0.717723 0.0872552 0.0351253 0.364702 +0.00308949 0.0412644 0.795572 0.136879 0.0347409 0.433621 0.105791 0.0351522 0.551342 +0.00125917 0.0414015 0.40725 0.0452744 0.0370045 0.871193 0.0324625 0.0382224 0.910615 +0.0262364 0.0369222 0.50118 0.134156 0.0347633 0.346512 0.0025212 0.0414527 0.775895 +0.0768158 0.0465113 0.355288 0.0693837 0.0461781 0.43056 0.059791 0.0463702 0.498335 +0.056949 0.0455118 0.563411 0.0528281 0.0449901 0.62162 0.0477895 0.0447948 0.672612 +0.112371 0.0418855 0.322977 0.0411321 0.0449911 0.721801 0.0454042 0.0506795 0.38809 +0.100974 0.0419895 0.396128 0.0430103 0.0521641 0.319828 0.0908282 0.0419871 0.466714 +0.0401501 0.0441158 0.766835 0.0387055 0.0504855 0.461532 0.0840258 0.0416101 0.530461 +0.0373317 0.0495675 0.527667 0.115304 0.0406224 0.360057 0.0354348 0.0441871 0.805893 +0.0353147 0.0430702 0.848224 0.035089 0.0489156 0.585698 0.106148 0.0403107 0.433971 +0.0775562 0.0411694 0.593815 0.0777806 0.0472566 0.308634 0.0302768 0.0535574 0.351566 +0.0311141 0.0522493 0.427529 0.0954251 0.0404275 0.500686 0.0704666 0.0410535 0.648485 +0.0291492 0.0489213 0.644886 0.0305546 0.04338 0.879924 0.0262294 0.0436288 0.911956 +0.0642425 0.0408176 0.70163 0.0882223 0.0400722 0.563222 0.028704 0.0515728 0.494083 +0.134465 0.0391021 0.302624 0.0267414 0.0508535 0.55842 0.0727002 0.0462039 0.40313 +0.0273806 0.0483086 0.696295 0.0242233 0.0433278 0.941134 0.0577656 0.0408963 0.745741 +0.051494 0.0412383 0.780584 0.0804743 0.0398964 0.622145 0.0655057 0.0462231 0.459231 +0.0252961 0.0501633 0.614895 0.0222591 0.0554917 0.300861 0.0251126 0.0478266 0.745467 +0.132249 0.0385515 0.340055 0.0733768 0.0397498 0.67561 0.124377 0.0386608 0.384921 +0.102348 0.0438581 0.299127 0.0471823 0.040916 0.823657 0.0890702 0.0451492 0.331614 +0.119773 0.0386567 0.414125 0.0550113 0.0500036 0.342753 0.0834781 0.0450335 0.379001 +0.056982 0.0504844 0.297807 0.0219236 0.054056 0.403023 0.0215761 0.0544963 0.376656 +0.0600223 0.0455268 0.537574 0.113542 0.0385672 0.457098 0.0662128 0.0398122 0.722618 +0.0500936 0.0495329 0.412588 0.0229462 0.0428574 0.967678 0.0224986 0.0476057 0.785338 +0.0547018 0.0496193 0.367486 0.0226538 0.0497027 0.670562 0.0214403 0.0551787 0.330993 +0.110149 0.0384828 0.481872 0.0217138 0.0469241 0.827136 0.0900843 0.043234 0.416211 +0.0490095 0.0491842 0.441818 0.0862563 0.0431876 0.445916 0.0550486 0.0451159 0.597512 +0.103917 0.0384536 0.522503 0.0190113 0.0538276 0.449578 0.0797628 0.0433361 0.486542 +0.0540732 0.0476685 0.479883 0.0614812 0.0394715 0.766369 0.0444251 0.0402513 0.864378 +0.077767 0.0431001 0.511728 0.0200065 0.0493807 0.719091 0.100608 0.0383896 0.545921 +0.0506756 0.0449151 0.642952 0.0194951 0.0533812 0.474511 0.0192176 0.0528181 0.515132 +0.0173589 0.0528026 0.537009 0.0536288 0.0400245 0.804179 0.0189879 0.0468795 0.860616 +0.0702799 0.0480284 0.326453 0.0951111 0.0383609 0.581966 0.0964685 0.0436327 0.351816 +0.0175337 0.0521574 0.577594 0.0206027 0.0484153 0.765244 0.14109 0.0376922 0.321247 +0.0540023 0.0469774 0.51621 0.102863 0.0421459 0.376056 0.134108 0.0377313 0.362472 +0.0398428 0.040278 0.897874 0.0175795 0.051856 0.596639 0.0443733 0.0479795 0.548853 +0.0722456 0.0425821 0.574685 0.0919006 0.0382466 0.606506 0.0461583 0.0446534 0.692637 +0.0644412 0.0478485 0.383547 0.0759412 0.0425648 0.548291 0.040451 0.053007 0.290311 +0.0853511 0.0464845 0.291183 0.0175026 0.0465161 0.894773 0.112238 0.0415067 0.341134 +0.0410019 0.0481631 0.570059 0.119681 0.0415126 0.290967 0.086477 0.0382896 0.639674 +0.12399 0.0375618 0.431417 0.0357344 0.0403088 0.928288 0.0376962 0.052107 0.372765 +0.0384704 0.0496764 0.510625 0.0272345 0.0407946 0.983606 0.149085 0.0372559 0.290747 +0.0831346 0.0382416 0.66274 0.0161905 0.0515602 0.63202 0.0367012 0.0478084 0.629129 +0.0959275 0.0444584 0.315699 0.0657383 0.042349 0.632524 0.054684 0.0455501 0.580345 +0.0380063 0.0526518 0.335629 0.0172208 0.0484368 0.804457 0.0683515 0.042444 0.609222 +0.016185 0.046174 0.925589 0.0109631 0.0564401 0.347212 0.0525381 0.0390969 0.83924 +0.0151487 0.0481858 0.843861 0.0420577 0.0443652 0.740094 0.0380405 0.0480681 0.602839 +0.0140128 0.055081 0.417165 0.0784071 0.038276 0.692031 0.0376928 0.0503443 0.479443 +0.113449 0.037507 0.498395 0.0558137 0.0435869 0.658301 0.0363365 0.0472473 0.661107 +0.0142488 0.0515686 0.655031 0.0324731 0.0401983 0.956162 0.131311 0.0372168 0.400189 +0.0601263 0.0497465 0.313985 0.0452306 0.0488595 0.493684 0.0462648 0.0390909 0.882993 +0.0772586 0.0379199 0.710808 0.0117432 0.0567952 0.31534 0.0102097 0.0570919 0.287618 +0.0726245 0.0380682 0.735912 0.0334977 0.0473943 0.681216 0.118958 0.0412386 0.308328 +0.0754942 0.0443592 0.4715 0.028332 0.0543684 0.316906 0.0142005 0.0511087 0.685213 +0.0492341 0.0436402 0.709224 0.0415648 0.0391698 0.914107 0.104638 0.0410802 0.411227 +0.0373002 0.0441867 0.78916 0.0381383 0.0515581 0.402482 0.102598 0.03739 0.5696 +0.0699979 0.0440949 0.525527 0.059543 0.0422479 0.683098 0.014722 0.0476476 0.876833 +0.0653937 0.0470908 0.415832 0.0699817 0.0487646 0.288274 0.0943815 0.0410187 0.483391 +0.0100298 0.056258 0.362481 0.0710151 0.04712 0.369152 0.0336027 0.0516081 0.443012 +0.0856806 0.0443811 0.394328 0.0572059 0.0486819 0.398596 0.120638 0.0370576 0.471214 +0.0299498 0.0530291 0.389219 0.115824 0.0396317 0.399149 0.0147699 0.0458957 0.954673 +0.148865 0.0368618 0.308403 0.0541226 0.0486573 0.426325 0.0125846 0.0542971 0.489081 +0.0329113 0.0469137 0.710625 0.0135831 0.0504644 0.733546 0.124956 0.0369985 0.447239 +0.127029 0.0396562 0.325929 0.084754 0.0437615 0.430446 0.0294575 0.0472349 0.729491 +0.101379 0.0407318 0.448061 0.0110802 0.0552898 0.435242 0.0879444 0.0446445 0.364869 +0.134576 0.0394483 0.286817 0.0702723 0.0379865 0.753552 0.0132043 0.0510132 0.703921 +0.0127152 0.0458328 0.983899 0.0655417 0.0381149 0.780367 0.0543391 0.0420409 0.730584 +0.136598 0.0369273 0.379605 0.070352 0.0457363 0.444953 0.0465034 0.0510732 0.354718 +0.0314998 0.0503241 0.541178 0.0127596 0.0556314 0.391568 0.047674 0.0428061 0.754476 +0.0350834 0.0435818 0.831948 0.0254732 0.0552241 0.287094 0.141981 0.0368728 0.349347 +0.0911786 0.0407653 0.515688 0.0762676 0.0468883 0.339919 0.0516518 0.0485038 0.456124 +0.0947766 0.0372682 0.622111 0.0556227 0.0501768 0.327448 0.145399 0.0367021 0.335698 +0.104835 0.0396633 0.469294 0.0624952 0.0486796 0.354315 0.0383956 0.0530564 0.306247 +0.0113575 0.0536085 0.552223 0.0689547 0.0409415 0.663443 0.110671 0.0369665 0.535169 +0.0641375 0.0379419 0.794459 0.0796195 0.0439827 0.458072 0.0383685 0.038965 0.941683 +0.0659614 0.0456189 0.485398 0.114167 0.0369865 0.513186 0.0108489 0.0549604 0.461778 +0.0598796 0.0380797 0.818293 0.123755 0.0390889 0.371059 0.0251945 0.0526656 0.461016 +0.0298451 0.0526636 0.4138 0.108329 0.0433303 0.282675 0.0310075 0.0463477 0.756118 +0.0123098 0.0504354 0.752054 0.0542655 0.0380754 0.855245 0.126372 0.0391065 0.353691 +0.0127348 0.0475443 0.908649 0.0106718 0.0504202 0.775322 0.102497 0.0431563 0.33178 +0.0100233 0.0545051 0.504316 0.101456 0.0368424 0.595554 0.0639802 0.0436884 0.589913 +0.0859748 0.0372047 0.678631 0.0112585 0.0527876 0.610618 0.0244513 0.054231 0.36506 +0.0318486 0.0433924 0.86773 0.0517825 0.0514107 0.287557 0.00777815 0.0564355 0.303693 +0.130947 0.0367329 0.421232 0.0738916 0.0440244 0.499114 0.0856166 0.0409688 0.545605 +0.0802211 0.0466261 0.322986 0.00979494 0.053695 0.56527 0.0707366 0.043148 0.561839 +0.0288313 0.0464273 0.774276 0.00705768 0.0553135 0.407564 0.0249711 0.0545096 0.340927 +0.0316291 0.0447486 0.818942 0.0473801 0.0476628 0.538481 0.111479 0.0406101 0.385892 +0.106145 0.0371178 0.557403 0.096849 0.0393678 0.53319 0.0902512 0.0455325 0.303531 +0.0259027 0.0465503 0.798896 0.0115887 0.0499386 0.792425 0.0623542 0.0448507 0.550568 +0.0773422 0.0451447 0.41992 0.0096445 0.054271 0.525565 0.0247537 0.0517143 0.526322 +0.0277591 0.0504865 0.569797 0.0343423 0.0388746 0.972298 0.0648885 0.0452568 0.511353 +0.00642595 0.0557206 0.327789 0.103827 0.0422771 0.363442 0.0695146 0.0486475 0.298576 +0.0113997 0.0495427 0.818834 0.112735 0.0395855 0.421072 0.0788521 0.037033 0.727987 +0.0424837 0.0504999 0.425386 0.106947 0.0429604 0.310001 0.0938694 0.0433128 0.385462 +0.0509214 0.0476874 0.506093 0.0849763 0.0403244 0.575433 0.0907694 0.0371118 0.652003 +0.0408758 0.04728 0.616898 0.0524167 0.0412788 0.772262 0.0534126 0.0496223 0.378468 +0.123462 0.0369267 0.459012 0.0588987 0.0426123 0.673765 0.0589425 0.0378209 0.831425 +0.131711 0.0392316 0.314459 0.0413508 0.0465447 0.648813 0.0297022 0.0432735 0.89135 +0.0219813 0.0535763 0.434738 0.0104392 0.0475896 0.939488 0.110828 0.0393815 0.441787 +0.0116617 0.0464658 0.972909 0.00988025 0.0522204 0.667321 0.0832939 0.044509 0.405872 +0.0474846 0.041657 0.797052 0.0457283 0.0415831 0.813192 0.0602111 0.0474333 0.440484 +0.0718159 0.0435288 0.537087 0.00730124 0.0536247 0.58582 0.0272993 0.0516083 0.506302 +0.0502609 0.0513122 0.306873 0.120063 0.0366706 0.489061 0.0798155 0.0404569 0.605659 +0.0473184 0.0466994 0.587898 0.0409188 0.0435748 0.78137 0.00448674 0.0538459 0.447409 +0.137621 0.0365101 0.389855 0.0765941 0.0459239 0.387001 0.0938896 0.04537 0.28493 +0.0551759 0.0421606 0.719719 0.0930806 0.0418869 0.455337 0.0112497 0.0523205 0.642716 +0.0508294 0.0456706 0.607076 0.0982577 0.0418135 0.422672 0.0644521 0.042877 0.620687 +0.0935336 0.0422657 0.435522 0.0519068 0.0380483 0.871488 0.0293641 0.0497297 0.59735 +0.0641744 0.0462571 0.468247 0.0876782 0.0450598 0.346385 0.0250327 0.0455809 0.850518 +0.0865856 0.0419667 0.497412 0.0265611 0.0521055 0.482714 0.0267953 0.0454388 0.838265 +0.0105475 0.0495127 0.83275 0.103574 0.0392452 0.494181 0.0773753 0.0401705 0.63315 +0.0957517 0.0425693 0.40634 0.009767 0.052896 0.622021 0.0234526 0.0509665 0.586647 +0.103388 0.0388665 0.510129 0.0885425 0.0392217 0.593162 0.0259815 0.0493137 0.656375 +0.0652699 0.0485448 0.33885 0.0488901 0.0487416 0.467392 0.094971 0.0369305 0.63215 +0.0481051 0.0456538 0.631154 0.0454494 0.0475631 0.560872 0.025642 0.0499057 0.626229 +0.0375217 0.0461835 0.701199 0.0406972 0.0506326 0.434134 0.0423399 0.0500811 0.451158 +0.158618 0.036034 0.284248 0.10555 0.0365521 0.58065 0.121716 0.0402113 0.336048 +0.00976522 0.04933 0.855064 0.00943333 0.0492234 0.866339 0.0480375 0.0377114 0.905065 +0.0561059 0.0471682 0.48863 0.107628 0.0419571 0.351956 0.0296298 0.0517841 0.471557 +0.0850372 0.0426861 0.47717 0.0633692 0.0407075 0.7118 0.0290689 0.0511689 0.515199 +0.0675137 0.0404186 0.692613 0.0726692 0.0369905 0.767473 0.113616 0.0367645 0.524546 +0.00533702 0.0548149 0.377408 0.112687 0.0407688 0.370967 0.0709581 0.0480963 0.317307 +0.00935517 0.0544486 0.514465 0.0497336 0.0377278 0.893613 0.0211822 0.0472471 0.817803 +0.0254279 0.0432798 0.931082 0.061775 0.0428434 0.642458 0.0353562 0.0532111 0.324973 +0.0397478 0.0411251 0.874402 0.0436159 0.0407844 0.854753 0.0437643 0.0486393 0.519064 +0.00483893 0.0547652 0.338679 0.0221497 0.051829 0.547063 0.0212002 0.0548624 0.355385 +0.0404819 0.0469093 0.639002 0.0819029 0.0421857 0.521329 0.0963013 0.0388601 0.556011 +0.0567566 0.0408044 0.756255 0.0235414 0.049354 0.680597 0.0401212 0.0521691 0.34616 +0.00648178 0.054519 0.478779 0.135994 0.0362649 0.409017 0.0622584 0.0443966 0.572057 +0.10202 0.0429961 0.342673 0.151996 0.0360075 0.324372 0.0681209 0.0365575 0.807253 +0.00944708 0.0514797 0.723371 0.110274 0.0367395 0.545642 0.00831522 0.0510849 0.765782 +0.0923578 0.0437785 0.374382 0.0200132 0.0506824 0.642306 0.045161 0.0376976 0.924186 +0.154561 0.0362364 0.299982 0.0235126 0.0489084 0.705711 0.0330742 0.0476742 0.67124 +0.112858 0.0423151 0.299734 0.126373 0.0407348 0.282281 0.0217647 0.045557 0.886377 +0.0553904 0.0465338 0.526783 0.036732 0.0491526 0.556703 0.0778904 0.0477279 0.282426 +0.103824 0.0400905 0.458509 0.0508389 0.0464384 0.570164 0.0830501 0.0370078 0.702846 +0.0187277 0.0531559 0.498058 0.00855253 0.0470887 0.992803 0.0809245 0.0390719 0.648723 +0.0665954 0.0430398 0.597644 0.0471997 0.0451447 0.662157 0.0239379 0.0430939 0.951138 +0.00925321 0.0489039 0.887611 0.0909618 0.0364967 0.670425 0.042036 0.047796 0.579785 +0.0617832 0.0500466 0.282752 0.0176848 0.0564246 0.281802 0.0303112 0.0427508 0.902984 +0.0315044 0.051773 0.453485 0.033886 0.0431754 0.857089 0.078368 0.0412869 0.583445 +0.0228603 0.0456405 0.871072 0.102397 0.0362188 0.610705 0.045037 0.0511485 0.363445 +0.044505 0.0412455 0.83366 0.0551979 0.0461661 0.546524 0.14473 0.0360802 0.364394 +0.00582783 0.0534675 0.57664 0.0373405 0.0536067 0.280656 0.0399365 0.0511105 0.412728 +0.0295631 0.0532241 0.380396 0.136471 0.0381416 0.330959 0.0607245 0.047122 0.452445 +0.129877 0.0364514 0.438372 0.0444649 0.045211 0.68285 0.142331 0.0384007 0.283633 +0.00710182 0.0523239 0.69563 0.0556964 0.0490939 0.388604 0.0560781 0.0426499 0.694049 +0.0880045 0.0365123 0.687807 0.0292235 0.0474567 0.720901 0.00848489 0.0513914 0.742793 +0.00670101 0.0534583 0.596011 0.0791938 0.0415437 0.567293 0.0662622 0.0473538 0.395011 +0.0211315 0.0538307 0.426618 0.0069354 0.0525605 0.677554 0.0624615 0.0483357 0.373493 +0.0645424 0.0398948 0.731427 0.0484064 0.0517569 0.296279 0.0389036 0.0377904 0.963467 +0.0344131 0.0458107 0.747446 0.047152 0.0502415 0.398039 0.121551 0.0406606 0.317238 +0.0463368 0.0488536 0.484024 0.0075339 0.0541198 0.541843 0.0335484 0.0382679 0.990195 +0.0217912 0.0483439 0.755403 0.0210375 0.0427625 0.988792 0.0441981 0.0375441 0.933843 +0.00566331 0.0546319 0.426056 0.0283677 0.0427124 0.921632 0.0214039 0.0510157 0.606177 +0.0464929 0.0515086 0.328529 0.0369021 0.0501274 0.49966 0.0860036 0.0451305 0.35533 +0.0580434 0.0442467 0.612239 0.0176025 0.0502746 0.695192 0.0853542 0.0408265 0.553118 +0.123883 0.0407051 0.299938 0.0373305 0.0413435 0.887051 0.0184862 0.0521542 0.566915 +0.124621 0.0361452 0.481025 0.0826175 0.0365902 0.7181 0.00577707 0.0552116 0.354392 +0.0299768 0.0489256 0.63615 0.021386 0.0543913 0.385827 0.077163 0.036744 0.746854 +0.0796859 0.0471571 0.299118 0.144145 0.0377201 0.301378 0.0931736 0.0401633 0.526409 +0.0202088 0.0434323 0.977816 0.00834816 0.0486114 0.918482 0.00705836 0.0520981 0.713252 +0.117064 0.040581 0.350275 0.116217 0.0421971 0.282432 0.0202825 0.0541778 0.41205 +0.0326512 0.0540233 0.297843 0.073453 0.0389801 0.701337 0.00448573 0.05485 0.281986 +0.0651453 0.0473437 0.404617 0.0210063 0.0453257 0.903913 0.0703713 0.047588 0.349476 +0.086897 0.038901 0.615562 0.021074 0.055521 0.310904 0.0737691 0.0458838 0.410912 +0.0955222 0.0443408 0.32441 0.0369317 0.0503035 0.489112 0.0729219 0.0466641 0.377825 +0.0602253 0.0368951 0.847213 0.00457321 0.0540989 0.416577 0.0867332 0.0417116 0.507205 +0.0206658 0.0554377 0.320923 0.0296854 0.0499858 0.579304 0.0774572 0.0447495 0.438152 +0.0861024 0.0386399 0.62996 0.0492032 0.0422177 0.76398 0.0435942 0.051109 0.378962 +0.107488 0.0408365 0.402652 0.0147327 0.0560943 0.336622 0.0572661 0.0440017 0.629127 +0.11327 0.0415562 0.331952 0.094256 0.0451384 0.29397 0.0083495 0.0477747 0.963116 +0.114758 0.0390196 0.431255 0.121696 0.0381603 0.422014 0.0566073 0.0371118 0.864482 +0.0355011 0.0468014 0.690984 0.154872 0.0358157 0.315115 0.038414 0.0453421 0.730973 +0.0945708 0.0387349 0.571817 0.133225 0.036153 0.429705 0.00286099 0.0488674 0.995876 +0.0277077 0.0459512 0.807091 0.0182879 0.0458052 0.915549 0.0807166 0.0384117 0.672635 +0.149334 0.0359016 0.344265 0.095985 0.0364068 0.643008 0.0856085 0.0459962 0.314562 +0.0317239 0.0455875 0.78306 0.00871535 0.0488574 0.898673 0.0049019 0.0539529 0.467359 +0.0346318 0.0527196 0.363389 0.124711 0.039141 0.362788 0.00479528 0.0543645 0.397122 +0.0576842 0.0474091 0.462857 0.00804012 0.0481717 0.947604 0.062943 0.0484362 0.364007 +0.0973936 0.0407414 0.474508 0.018483 0.0512971 0.621821 0.0757511 0.0398239 0.656822 +0.0727858 0.0412515 0.624401 0.0398798 0.0478829 0.595231 0.119927 0.0362133 0.506452 +0.0794085 0.0459505 0.364014 0.0511998 0.0424664 0.739149 0.0416912 0.0450944 0.712369 +0.00667023 0.0511426 0.786448 0.0708399 0.0367007 0.786795 0.0940619 0.0408762 0.491497 +0.141183 0.0379333 0.310598 0.118063 0.0397415 0.380026 0.0359642 0.0378756 0.98139 +0.103666 0.0432135 0.32087 0.0205385 0.0491188 0.727666 0.12391 0.0384955 0.394636 +0.0790567 0.0384354 0.682598 0.078328 0.0467257 0.332407 0.0411561 0.0376806 0.95084 +0.0153725 0.0510041 0.677305 0.0492666 0.0449593 0.65284 0.0297857 0.0539158 0.332771 +0.019802 0.0484074 0.774991 0.122123 0.0385131 0.405147 0.0759556 0.0409067 0.61528 +0.0334294 0.0485943 0.619462 0.0708784 0.0411881 0.640442 0.0738664 0.0444246 0.480804 +0.0559885 0.048533 0.417137 0.0985973 0.0442442 0.306997 0.0136453 0.0553797 0.399878 +0.0379893 0.0517274 0.393499 0.0665489 0.0390947 0.7438 0.0192107 0.0560624 0.29189 +0.0299663 0.0528901 0.398035 0.0307288 0.0411232 0.946711 0.0932063 0.0364193 0.659321 +0.00521984 0.0539008 0.496327 0.0468866 0.0512766 0.339039 0.0400785 0.0501469 0.468392 +0.029591 0.0543213 0.307698 0.0914024 0.0428204 0.42569 0.0567251 0.045022 0.588068 +0.104352 0.0417026 0.385786 0.032714 0.0463636 0.73862 0.0196261 0.0504299 0.662056 +0.0632451 0.0453252 0.521198 0.00651157 0.0530422 0.633732 0.00664708 0.0508625 0.80581 +0.0224231 0.0485728 0.736076 0.0618824 0.0496417 0.305259 0.0342335 0.0485882 0.611871 +0.0645565 0.0419666 0.656435 0.0516078 0.050921 0.318488 0.10566 0.0362804 0.589178 +0.00397401 0.0532587 0.487337 0.055021 0.0400334 0.793957 0.0619905 0.0493198 0.322677 +0.0301031 0.0405883 0.965322 0.104795 0.0388262 0.502662 0.00381701 0.0541355 0.311218 +0.0309712 0.0413789 0.937856 0.0543859 0.0367973 0.885846 0.0821713 0.0433898 0.466445 +0.0538337 0.0462416 0.554305 0.0300648 0.0463588 0.764991 0.0728802 0.0385589 0.718843 +0.130865 0.0359142 0.452564 0.00409996 0.0544642 0.295334 0.0439146 0.041076 0.843545 +0.0172613 0.0536374 0.481769 0.144348 0.0358687 0.374888 0.0465338 0.0465893 0.600221 +0.06442 0.0437868 0.582219 0.0404437 0.0426471 0.81941 0.0804511 0.042006 0.539288 +0.0728875 0.036609 0.776785 0.0864375 0.0465157 0.281318 0.00471463 0.0521822 0.686218 +0.0432359 0.0424103 0.804778 0.00364225 0.0539378 0.318969 0.0322755 0.0500573 0.548993 +0.113273 0.0383912 0.465709 0.0385642 0.0492133 0.535827 0.0806521 0.0363013 0.738403 +0.0165993 0.0496502 0.744373 0.0632583 0.0472676 0.42402 0.139532 0.0358816 0.402733 +0.0163948 0.0455872 0.946696 0.0462154 0.0480662 0.527672 0.0184 0.047567 0.834757 +0.0598643 0.0395335 0.775587 0.0374389 0.0519502 0.384945 0.0723158 0.0450146 0.464778 +0.0543067 0.0499748 0.350501 0.0367283 0.0531706 0.314582 0.00408167 0.0540404 0.368697 +0.12219 0.0360911 0.497397 0.00640825 0.050322 0.845655 0.00794373 0.0485326 0.929515 +0.124719 0.0395788 0.344096 0.00479348 0.0532466 0.557467 0.13394 0.038119 0.347573 +0.0304406 0.0506479 0.532685 0.110718 0.0361295 0.56414 0.038312 0.0403939 0.906325 +0.00469704 0.0543642 0.387472 0.143445 0.035794 0.383076 0.00333233 0.0535065 0.346668 +0.0770164 0.0363901 0.757802 0.0950301 0.0436607 0.36077 0.0179472 0.0531565 0.506692 +0.14039 0.037286 0.342241 0.00527323 0.0526027 0.656356 0.0557975 0.0424509 0.703925 +0.021052 0.0529 0.489636 0.00619242 0.0539687 0.531742 0.0336283 0.0479212 0.653084 +0.158671 0.0358229 0.292517 0.0785564 0.0443502 0.448834 0.0138257 0.0557553 0.370883 +0.0496137 0.036803 0.915413 0.112067 0.0383611 0.474481 0.13155 0.0379184 0.370604 +0.112628 0.0398571 0.410445 0.039574 0.0444934 0.756591 0.0865189 0.0398002 0.58504 +0.0158831 0.0453258 0.962796 0.0525518 0.0475745 0.497873 0.0729561 0.0443831 0.489676 +0.0627457 0.045231 0.529661 0.064808 0.0366735 0.824516 0.0283009 0.0487239 0.664443 +0.0179973 0.0538784 0.457169 0.109537 0.040737 0.393289 0.147694 0.0358655 0.35533 +0.0133639 0.0556582 0.382948 0.0408615 0.0462215 0.668678 0.0187794 0.0536209 0.466145 +0.0714654 0.0440425 0.516702 0.117473 0.0358918 0.532338 0.00423026 0.0536201 0.456903 +0.0464146 0.0443965 0.701421 0.033677 0.0414613 0.913218 0.12802 0.0359756 0.467095 +0.0271035 0.054427 0.325128 0.0655322 0.0412308 0.67727 0.0536132 0.0396977 0.814257 +0.0187047 0.0482852 0.794457 0.111951 0.0379696 0.490262 0.00585198 0.0507767 0.823782 +0.103351 0.0362728 0.603225 0.0539318 0.0437586 0.666189 0.0786072 0.045926 0.371403 +0.0346415 0.0518151 0.420121 0.0508128 0.0490398 0.433965 0.0345355 0.0493876 0.564894 +0.0930167 0.0431753 0.397935 0.0687976 0.0490822 0.280048 0.0731072 0.0417745 0.601508 +0.120616 0.0378762 0.439959 0.128944 0.0401311 0.292701 0.00661069 0.0497979 0.876215 +0.135786 0.0394383 0.279566 0.0173482 0.0530128 0.523063 0.033517 0.044827 0.797988 +0.0850298 0.0363346 0.711104 0.0469522 0.0436543 0.727466 0.058519 0.0432614 0.650479 +0.0521086 0.0437725 0.680349 0.00624783 0.0485985 0.955259 0.0617375 0.0489245 0.347009 +0.0171335 0.0475262 0.852197 0.138503 0.0387296 0.293337 0.0238987 0.0535063 0.419319 +0.0155254 0.0504195 0.711719 0.0175921 0.0455278 0.934746 0.014857 0.0493412 0.784185 +0.0623092 0.0498294 0.290914 0.0659998 0.0443702 0.543896 0.0800303 0.0461798 0.34755 +0.0451046 0.0504168 0.406276 0.0767419 0.0428384 0.530693 0.0610248 0.04747 0.431806 +0.0279446 0.0549775 0.27956 0.044826 0.0424889 0.789107 0.127524 0.0400024 0.30758 +0.0116219 0.0528456 0.602091 0.0181093 0.0523551 0.558082 0.0666485 0.036559 0.816201 +0.157032 0.0356795 0.307898 0.0479148 0.0505653 0.37224 0.0594643 0.0392975 0.785649 +0.0330099 0.0532971 0.341906 0.0937178 0.0442869 0.340098 0.0461917 0.0523309 0.280637 +0.11064 0.0428282 0.290726 0.0772031 0.0450075 0.427654 0.0770343 0.047681 0.291679 +0.0620532 0.0464085 0.477887 0.0622338 0.0367059 0.839522 0.0715267 0.0453608 0.45418 +0.0774064 0.0456142 0.39628 0.0686531 0.0485927 0.308598 0.128531 0.0381732 0.378924 +0.0554143 0.048808 0.406922 0.0136466 0.0547725 0.443215 0.0279873 0.0483291 0.688852 +0.116968 0.0382005 0.449972 0.0862766 0.039418 0.600896 0.0858399 0.0445175 0.386578 +0.096935 0.0385336 0.56403 0.0269486 0.0412654 0.97453 0.119125 0.0408064 0.326696 +0.109321 0.0361082 0.573163 0.113669 0.0418651 0.315124 0.102459 0.0396748 0.484383 +0.0982183 0.0419928 0.415013 0.0481606 0.0509578 0.34677 0.030812 0.0521699 0.435537 +0.0875627 0.0420479 0.487036 0.109141 0.0394392 0.450358 0.0629455 0.0490373 0.330644 +0.0912807 0.0401968 0.537785 0.0135653 0.0550062 0.42749 0.00429001 0.0525785 0.615738 +0.0140151 0.0559548 0.354425 0.0211076 0.0503455 0.650197 0.101702 0.0360718 0.619635 +0.0780002 0.0398269 0.641442 0.0255506 0.0528605 0.444679 0.0592292 0.0442078 0.604487 +0.0567427 0.0439224 0.636712 0.00323809 0.0529614 0.437152 0.043332 0.0466774 0.624429 +0.0587432 0.046389 0.50604 0.0535063 0.0499512 0.358793 0.0157057 0.0563952 0.30457 +0.0471715 0.0488758 0.475314 0.100322 0.0376224 0.575505 0.0678834 0.0383083 0.759351 +0.100782 0.0410291 0.439464 0.0270013 0.0448323 0.860617 0.0293774 0.0450916 0.826786 +0.0447451 0.0487728 0.502846 0.0146368 0.0531602 0.544243 0.0295315 0.0533524 0.372343 +0.0941144 0.0419645 0.444751 0.0414837 0.0503668 0.442454 0.0712188 0.0362129 0.797545 +0.00622192 0.0519036 0.733757 0.0676004 0.0410142 0.670418 0.0614129 0.0423382 0.665429 +0.0290224 0.0529125 0.406006 0.133766 0.0387527 0.322037 0.0707855 0.0473343 0.359669 +0.147251 0.0369265 0.31545 0.0661292 0.0452292 0.502841 0.0781692 0.0419408 0.55833 +0.128156 0.0373737 0.413256 0.0984314 0.0407957 0.465229 0.152536 0.0356593 0.335027 +0.103645 0.038291 0.530327 0.0692934 0.0435879 0.553565 0.0504887 0.0423901 0.747573 +0.021796 0.0541992 0.394639 0.117999 0.039523 0.389673 0.0552287 0.038994 0.823671 +0.00470798 0.0528326 0.606692 0.102374 0.0383021 0.53796 0.0820777 0.0445189 0.414459 +0.0143754 0.0487075 0.826018 0.099095 0.0415069 0.430344 0.0582976 0.0410029 0.738153 +0.115933 0.0359344 0.53995 0.0401064 0.0462237 0.675457 0.0292339 0.0459688 0.790898 +0.0305725 0.0475246 0.703778 0.113605 0.0359427 0.553419 0.0158865 0.0522848 0.58839 +0.0255422 0.048353 0.713499 0.00718617 0.0478402 0.979605 0.0866779 0.0432942 0.438001 +0.0271965 0.0404052 0.992875 0.0708198 0.0386949 0.728053 0.150734 0.037264 0.280423 +0.0375754 0.0400555 0.920853 0.00421263 0.0530082 0.549203 0.0502482 0.0393483 0.848102 +0.00497977 0.0520879 0.704626 0.101753 0.0441479 0.289163 0.0683293 0.0461982 0.437914 +0.00545661 0.0516291 0.75671 0.059339 0.041136 0.725839 0.0144837 0.0498299 0.760434 +0.0632648 0.0395521 0.751515 0.0970463 0.0432119 0.367584 0.101117 0.0444181 0.280342 +0.0839736 0.0440493 0.422702 0.0234627 0.0429557 0.959849 0.0526079 0.0484859 0.448786 +0.0518158 0.0436689 0.687009 0.105023 0.0394486 0.476705 0.0420476 0.0441625 0.748476 +0.0712144 0.0424861 0.586297 0.0437888 0.0521656 0.312631 0.011519 0.0549748 0.452988 +0.00329602 0.0526422 0.506256 0.128758 0.0392285 0.333339 0.0129673 0.0568956 0.297189 +0.0148496 0.0562175 0.326475 0.075812 0.0395614 0.6657 0.0448828 0.0368849 0.943296 +0.13772 0.0373569 0.355595 0.11002 0.0409848 0.379261 0.0855214 0.04314 0.453385 +0.0477274 0.0437363 0.717743 0.0150791 0.0447336 0.993356 0.0374007 0.0428036 0.839539 +0.0792821 0.0430245 0.503944 0.0666424 0.0381078 0.773421 0.0879043 0.0362615 0.69603 +0.0460341 0.0483931 0.511828 0.0887951 0.0453757 0.322286 0.120078 0.0358828 0.51729 +0.0706803 0.0393134 0.708815 0.0960626 0.0401229 0.508705 0.0839502 0.0457575 0.339266 +0.137845 0.0355845 0.423824 0.0517895 0.0395524 0.831423 0.0249576 0.0514967 0.53776 +0.00532064 0.0483583 0.986549 0.0357897 0.0489787 0.575417 0.0922699 0.039787 0.547188 +0.0495348 0.0494879 0.420075 0.0325398 0.054185 0.28821 0.0391773 0.052156 0.35578 +0.141887 0.03569 0.396194 0.130244 0.0376505 0.389482 0.0177949 0.0515342 0.614785 +0.0556942 0.0422606 0.711977 0.0404218 0.0424364 0.826903 0.0978851 0.0358215 0.650184 +0.0988617 0.039461 0.516405 0.0107218 0.0572215 0.279474 0.0319547 0.0515388 0.463505 +0.0949069 0.0374757 0.614283 0.0363595 0.0447755 0.773842 0.00564636 0.0509249 0.815056 +0.111024 0.0376752 0.507112 0.0385293 0.0490929 0.542852 0.070272 0.0461587 0.424515 +0.045839 0.0493538 0.460682 0.0613348 0.0362303 0.85662 0.0210796 0.0496994 0.688489 +0.0939654 0.0381114 0.598148 0.0144977 0.049678 0.769233 0.00568823 0.0517169 0.749741 +0.0708343 0.0478177 0.333422 0.0876864 0.0385521 0.622795 0.0709544 0.0399984 0.683488 +0.0415488 0.0527089 0.299109 0.00428781 0.0523299 0.648724 0.145071 0.0369347 0.328241 +0.0171475 0.055385 0.361473 0.0430708 0.0396348 0.891368 0.0617731 0.0382153 0.802087 +0.0607233 0.0381759 0.810086 0.0164802 0.0473589 0.86846 0.0547485 0.0511139 0.279642 +0.0352584 0.0461306 0.724921 0.117076 0.0373627 0.4815 0.0240495 0.0446516 0.897373 +0.0116626 0.0498104 0.799169 0.0644096 0.0441655 0.56554 0.0865074 0.0428366 0.459927 +0.0654192 0.0455484 0.493134 0.084372 0.0419451 0.513971 0.0357547 0.0499758 0.519507 +0.0157216 0.0532007 0.528911 0.0116092 0.0532776 0.57232 0.107689 0.0379845 0.51634 +0.0262489 0.0550233 0.293149 0.00304213 0.0531485 0.360746 0.00641509 0.0493379 0.908308 +0.100741 0.0360225 0.626932 0.128442 0.0357215 0.473853 0.0294518 0.0495693 0.605597 +0.0115765 0.054695 0.472437 0.0241855 0.0529512 0.452951 0.139029 0.0368247 0.369031 +0.0559082 0.0500004 0.335223 0.0929871 0.0357999 0.679727 0.0228861 0.0502557 0.635665 +0.0858056 0.0448326 0.3715 0.0376107 0.0420499 0.862941 0.0154081 0.0550096 0.406826 +0.0365408 0.0437581 0.812463 0.044845 0.0429213 0.77317 0.041915 0.0462965 0.655576 +0.0372652 0.0395755 0.935183 0.133168 0.0357313 0.445765 0.0405348 0.036703 0.974068 +0.0408371 0.0431785 0.796979 0.00142903 0.051216 0.277722 0.0791484 0.0432635 0.494313 +0.00239317 0.0526999 0.288206 0.0948868 0.0381597 0.590593 0.118279 0.0400236 0.366564 +0.0223767 0.0455845 0.878597 0.0690493 0.0453352 0.474766 0.0484708 0.0467174 0.576917 +0.0559568 0.0475177 0.471748 0.00370474 0.0528624 0.521705 0.0121173 0.0494935 0.811766 +0.00551922 0.050626 0.838755 0.00332906 0.0519652 0.626049 0.105733 0.0407466 0.418249 +0.0431395 0.0470155 0.609478 0.0362887 0.0460713 0.717922 0.0844396 0.0382223 0.655019 +0.0629145 0.0445914 0.558036 0.106155 0.0404947 0.426168 0.0560928 0.0366375 0.878991 +0.137484 0.0358298 0.41674 0.00482747 0.0511585 0.795853 0.0197824 0.055185 0.347737 +0.0719761 0.044148 0.507996 0.0780865 0.0470742 0.315941 0.0275476 0.0486641 0.675555 +0.0480006 0.0460165 0.615025 0.0506993 0.0387293 0.86192 0.102185 0.0651212 0.174604 +0.0275966 0.0700147 0.157767 0.0927054 0.0603225 0.207125 0.068275 0.0774504 0.14485 +0.108549 0.0531416 0.229078 0.0415087 0.0683893 0.177653 0.0409683 0.0593869 0.225948 +0.0294171 0.0773704 0.133459 0.0613714 0.0575767 0.233 0.14856 0.0456583 0.227497 +0.123684 0.0580425 0.184646 0.140365 0.0452296 0.239257 0.13678 0.0500156 0.218185 +0.0608974 0.0639575 0.201472 0.0997014 0.0662965 0.154862 0.076656 0.0693508 0.176123 +0.0511012 0.0845413 0.121583 0.0214177 0.0609337 0.200588 0.0848418 0.0704197 0.124341 +0.0868379 0.0524247 0.246079 0.0203569 0.0574693 0.245589 0.00982295 0.0684074 0.116326 +0.0826091 0.0581327 0.221946 0.118632 0.0472813 0.248209 0.148165 0.0494428 0.191052 +0.0164621 0.062393 0.176261 0.0426856 0.055822 0.251493 0.117478 0.0570333 0.203087 +0.0175809 0.0585954 0.222895 0.0485339 0.0752044 0.155481 0.0273865 0.0821014 0.113928 +0.0703699 0.0806919 0.113751 0.00984582 0.0632717 0.142871 0.158204 0.0395246 0.251503 +0.161533 0.0446545 0.205391 0.119406 0.0565005 0.160622 0.0398128 0.0623406 0.206749 +0.0679266 0.0533483 0.252361 0.080116 0.0645765 0.194663 0.0978322 0.0615921 0.136638 +0.0898548 0.0634863 0.119889 0.0817256 0.0727009 0.15609 0.129561 0.0560302 0.180074 +0.106798 0.0592657 0.14779 0.134993 0.0534637 0.198679 0.0594968 0.0683855 0.182766 +0.165386 0.0405706 0.234486 0.0451628 0.0798698 0.138174 0.0117306 0.062135 0.160392 +0.126268 0.0493089 0.232608 0.103495 0.0481121 0.25514 0.0665053 0.0735717 0.162406 +0.102184 0.0618496 0.193645 0.0553393 0.0607547 0.217401 0.13358 0.043392 0.254704 +0.0426561 0.0876811 0.107648 0.0820885 0.0715228 0.106247 0.0646719 0.0808812 0.129827 +0.0840212 0.0728525 0.141254 0.00901378 0.0583615 0.191482 0.117687 0.054092 0.217513 +0.116849 0.060372 0.170314 0.0324416 0.06435 0.190404 0.0576792 0.086805 0.106139 +0.00872165 0.0570322 0.2581 0.00536913 0.0605095 0.128613 0.0032728 0.0599267 0.106515 +0.0759949 0.0618006 0.208052 0.0156771 0.0769262 0.105317 0.089739 0.0588136 0.106558 +0.147076 0.0491061 0.206878 0.009647 0.0579699 0.209465 0.0763118 0.0557739 0.235922 +0.0539388 0.0717211 0.16936 0.0268816 0.0563458 0.257926 0.169297 0.0414317 0.217511 +0.0895659 0.0663282 0.182241 0.0920826 0.0549148 0.23165 0.0691217 0.0593141 0.221682 +0.0305459 0.0602385 0.216693 0.0374563 0.0824681 0.124558 0.0271804 0.0583507 0.233175 +0.0359242 0.0751297 0.148205 0.015434 0.0707652 0.128909 0.0490551 0.0656375 0.192819 +0.0805618 0.0506291 0.258233 0.0540693 0.0537005 0.258682 0.00935959 0.0574016 0.235353 +0.0905499 0.0689338 0.167565 0.146029 0.0403746 0.259414 0.0270031 0.0667856 0.171291 +0.039373 0.0715482 0.163763 0.143091 0.0493216 0.177496 0.127748 0.0553239 0.170556 +0.101545 0.0516655 0.240471 0.103269 0.0566799 0.216798 0.0476079 0.057389 0.238472 +0.154832 0.0421493 0.239773 0.117552 0.045135 0.258887 0.0212791 0.0701848 0.14622 +0.0238502 0.0628904 0.189018 0.00654439 0.0580504 0.170597 0.115067 0.0608846 0.181223 +0.0557761 0.0785837 0.144802 0.0757281 0.0768794 0.130386 0.0976181 0.0544699 0.126648 +0.0921537 0.0631142 0.195094 0.0665018 0.0662797 0.191004 0.0593837 0.0552385 0.246706 +0.0209327 0.0773524 0.118628 0.157218 0.04507 0.216748 0.160288 0.0428129 0.227537 +0.00378643 0.0594447 0.117516 0.00555391 0.0585117 0.150378 0.0711471 0.0813334 0.104061 +0.0332216 0.0573776 0.242707 0.0325847 0.0867933 0.10323 0.0930984 0.0579144 0.217593 +0.169418 0.0381393 0.245477 0.160188 0.0445739 0.19275 0.00587244 0.0558928 0.246518 +0.128624 0.0536988 0.20798 0.0634922 0.0707197 0.173705 0.0922447 0.0483778 0.261269 +0.130994 0.0466762 0.240969 0.115623 0.0503784 0.236369 0.106311 0.0642361 0.164214 +0.114821 0.0543555 0.151535 0.00478206 0.0554043 0.219777 0.00901916 0.0705766 0.102109 +0.139825 0.0523547 0.185306 0.0928911 0.068546 0.145557 0.0202516 0.0596132 0.212585 +0.107004 0.0591562 0.202559 0.164611 0.037088 0.259983 0.135752 0.0498128 0.168907 +0.137617 0.0478266 0.228839 0.0387351 0.0548609 0.261835 0.117402 0.0590451 0.19139 +0.0538891 0.0819716 0.131809 0.017997 0.0568289 0.263563 0.00397533 0.0575822 0.138608 +0.0531386 0.0587731 0.228632 0.00429769 0.0557912 0.181491 0.0623575 0.0831632 0.119598 +0.031476 0.0658936 0.181218 0.0447038 0.0608719 0.216728 0.0513374 0.062731 0.207205 +0.0763776 0.0719255 0.165298 0.104997 0.0553042 0.139946 0.126132 0.0428385 0.263409 +0.147581 0.0424607 0.246367 0.0897074 0.0683553 0.134301 0.0673382 0.0513833 0.262841 +0.00407518 0.0551115 0.200447 0.0211278 0.0661812 0.164172 0.0937607 0.0544002 0.116947 +0.0648563 0.0617262 0.211259 0.0767676 0.0535877 0.246278 0.07669 0.0765139 0.119532 +0.0721235 0.0748905 0.154415 0.148004 0.047532 0.216807 0.0619604 0.0762768 0.152872 +0.0210697 0.0821359 0.100413 0.0838306 0.0621706 0.203463 0.049863 0.0891158 0.101131 +0.0778837 0.0765496 0.0994185 0.0269605 0.0792205 0.123532 0.108473 0.0454796 0.263677 +0.138082 0.0514163 0.207884 0.0446584 0.0826679 0.12808 0.0665211 0.0557129 0.240784 +0.0137831 0.065076 0.149731 0.0861673 0.0655495 0.101571 0.0302958 0.0613668 0.207709 +0.0405907 0.0743147 0.154614 0.00327984 0.0553484 0.161445 0.174467 0.0390515 0.227309 +0.125653 0.0562219 0.196671 0.128439 0.0503208 0.161688 0.117306 0.0523002 0.226237 +0.138155 0.0409591 0.263304 0.0490485 0.0677903 0.183431 0.154211 0.0452414 0.183281 +0.0645676 0.0856908 0.0991301 0.1527 0.0478665 0.199874 0.070583 0.064025 0.199821 +0.170207 0.0415094 0.207368 0.080173 0.0671078 0.184017 0.110636 0.0604444 0.156259 +0.0418729 0.0850767 0.117882 0.0387822 0.0581921 0.234731 0.15565 0.0381601 0.263053 +0.0846631 0.05997 0.212749 0.0124989 0.0590007 0.200172 0.0200464 0.0720732 0.136081 +0.0375794 0.0801675 0.132585 0.10789 0.0495135 0.245862 0.0901315 0.0701925 0.157408 +0.0962454 0.0646269 0.185129 0.0464397 0.0774924 0.146839 0.132079 0.0551064 0.189822 +0.0704471 0.0684675 0.181528 0.0967146 0.0507618 0.24764 0.0503276 0.0867925 0.111837 +0.127176 0.0516392 0.220481 0.0582698 0.0659817 0.192607 0.167249 0.0422219 0.198702 +0.00336488 0.0540176 0.229171 0.0474764 0.0534805 0.264792 0.0184464 0.0579159 0.236754 +0.174788 0.0378993 0.237478 0.0613992 0.0798524 0.138231 0.0611333 0.0590764 0.22515 +0.125485 0.0447792 0.254574 0.0164758 0.0572848 0.253367 0.0424622 0.0642273 0.197445 +0.0567038 0.0742197 0.160689 0.0846228 0.0544411 0.237972 0.0390316 0.0892594 0.0988602 +0.144152 0.0507476 0.19855 0.00159535 0.054004 0.125253 0.032572 0.0592855 0.225525 +0.0697698 0.0801277 0.122608 0.0692553 0.0575145 0.23046 0.111342 0.0470925 0.254367 +0.0935382 0.0529995 0.239479 0.0768021 0.0766654 0.109789 0.0981332 0.067186 0.164689 +0.0848975 0.0688076 0.173998 0.0133415 0.0764357 0.0981261 0.0905533 0.0540838 0.0999235 +0.00115742 0.0544976 0.0994643 0.0137731 0.0621098 0.169323 0.0783189 0.0747273 0.147325 +0.169604 0.0369792 0.253961 0.0930757 0.0628071 0.128335 0.0113834 0.066137 0.134451 +0.0453768 0.0707144 0.17037 0.00349134 0.0540125 0.264122 0.0872286 0.0650802 0.112006 +0.111615 0.0566479 0.210617 0.00316581 0.0537373 0.238699 0.12247 0.0585896 0.177218 +0.0291463 0.0746783 0.14239 0.0341737 0.0851665 0.11162 0.12209 0.0499554 0.154851 +0.110201 0.0546564 0.22099 0.0315964 0.0628415 0.198669 0.0766642 0.0497869 0.264678 +0.0023162 0.053185 0.191328 0.0144614 0.0608036 0.183855 0.0854743 0.0722199 0.149033 +0.00256827 0.0532631 0.210221 0.00964932 0.0664622 0.124443 0.0409589 0.0662531 0.186797 +0.0994042 0.0606944 0.201251 0.0639698 0.0842628 0.109187 0.0829091 0.0711364 0.115958 +0.0357425 0.0690413 0.170834 0.0992323 0.0553058 0.225609 0.0696304 0.0785634 0.136511 +0.161561 0.040098 0.243558 0.0121423 0.0579238 0.22744 0.0851404 0.0485904 0.264837 +0.0758071 0.0599175 0.216594 0.111747 0.05069 0.144428 0.0208387 0.0749467 0.127161 +0.0513141 0.0555267 0.248978 0.00140018 0.0544395 0.110485 0.0128871 0.0576399 0.242666 +0.0577169 0.0521665 0.265145 0.0938772 0.0670188 0.174862 0.138725 0.0439909 0.247138 +0.0885487 0.0504104 0.254333 0.00709 0.0663686 0.109129 0.0344356 0.0563416 0.251967 +0.0278435 0.0556181 0.266131 0.0209068 0.0793571 0.111111 0.00156582 0.0529856 0.145355 +0.0991936 0.0466051 0.26477 0.0280382 0.0720352 0.150477 0.0122737 0.0582245 0.217275 +0.0475577 0.0730537 0.162681 0.0093934 0.0571515 0.265955 0.0829853 0.0563926 0.229763 +0.0830662 0.0728521 0.132517 0.109801 0.0601438 0.194941 0.10983 0.0629836 0.173783 +0.08758 0.0651615 0.188721 0.00442893 0.0637628 0.0986761 0.0135739 0.0733642 0.112036 +0.102613 0.0513872 0.13285 0.0219408 0.0638993 0.178889 0.0522686 0.0645506 0.198459 +0.147486 0.0444728 0.235512 0.0531257 0.0696831 0.176886 0.00139147 0.0530831 0.132161 +0.003009 0.0535081 0.253496 0.0263834 0.0569903 0.249829 0.0842338 0.0707763 0.164596 +0.146672 0.0390796 0.266291 0.0205376 0.0677127 0.155393 0.0367648 0.061031 0.213811 +0.13628 0.0524522 0.176032 0.123407 0.0481015 0.240691 0.0161382 0.0604929 0.192809 +0.0999009 0.0636072 0.144831 0.0566065 0.0887189 0.0976191 0.00131594 0.0521369 0.15268 +0.0414678 0.0568958 0.243969 0.154728 0.0466004 0.209327 0.0308081 0.0693424 0.16465 +0.106925 0.0625373 0.184757 0.0921364 0.0514703 0.107159 0.113433 0.0609231 0.163457 +0.00168978 0.0524839 0.172195 0.135001 0.0461369 0.163581 0.100819 0.0533432 0.233408 +0.0281646 0.0865854 0.097233 0.089725 0.0566145 0.225272 0.0594254 0.0540843 0.253203 +0.101113 0.0588036 0.208669 0.0759106 0.0578934 0.225975 0.0248722 0.0592497 0.222132 +0.0111104 0.0601032 0.176635 0.0749738 0.0517007 0.256501 0.13397 0.0472438 0.235471 +0.0201939 0.064453 0.171816 0.0254306 0.0576685 0.241292 0.0887136 0.0598857 0.0976832 +0.0471275 0.0546039 0.257458 0.0615182 0.0724081 0.167442 0.175371 0.0396038 0.213407 +0.0157753 0.0593831 0.205909 0.0200243 0.0584144 0.22894 0.147433 0.0486635 0.182939 +0.148292 0.0454961 0.176027 0.0576705 0.0830295 0.125659 0.0706769 0.0711806 0.170738 +0.163421 0.0436542 0.21245 0.117871 0.0481759 0.14917 0.120806 0.0549656 0.210261 +0.117174 0.043575 0.266456 0.0147161 0.0720713 0.12133 0.0573591 0.085417 0.113861 +0.00125965 0.0508844 0.268594 0.0379407 0.0778925 0.140525 0.0560891 0.0568016 0.239193 +0.0373427 0.0601643 0.219999 0.0771234 0.0758824 0.138669 0.0626217 0.0603707 0.218234 +0.107301 0.0517132 0.236387 0.0336483 0.0719959 0.157257 0.0324138 0.0801345 0.127733 +0.167232 0.0413274 0.224855 0.140765 0.0470202 0.170157 0.0327487 0.0826496 0.119352 +0.0523836 0.0801258 0.139016 0.0742061 0.0662748 0.189503 0.150755 0.0405302 0.253813 +0.0613774 0.052774 0.259317 0.1429 0.0477379 0.22308 0.154452 0.0448528 0.223684 +0.154635 0.0434762 0.232098 0.141358 0.0422389 0.253697 0.139825 0.0524454 0.193009 +0.0153686 0.0677483 0.141654 0.0828361 0.070978 0.0977261 0.0937363 0.0588231 0.122944 +0.045315 0.0904335 0.0956775 0.0546081 0.0766766 0.151699 0.129077 0.0455547 0.247983 +0.0266552 0.0837606 0.10632 0.0718551 0.0819975 0.0965592 0.0460069 0.0585574 0.231198 +0.081747 0.0518167 0.251911 0.048707 0.0599301 0.22245 0.0774175 0.0632928 0.20108 +0.0957438 0.0493053 0.254835 0.17678 0.0389178 0.219625 0.165626 0.0360101 0.266909 +0.112118 0.0223889 0.183324 0.0329761 0.0197859 0.164245 0.0582767 0.0282145 0.228021 +0.103994 0.0265166 0.217625 0.0359799 0.0127631 0.140879 0.0769031 0.0181041 0.179576 +0.0500303 0.0282805 0.225069 0.115992 0.0308058 0.240806 0.135112 0.0280716 0.20558 +0.0798077 0.0145658 0.127525 0.0935471 0.0174259 0.159398 0.139262 0.0319803 0.238591 +0.0241876 0.0286411 0.19852 0.0597364 0.0110588 0.147776 0.0555507 0.00601828 0.121471 +0.0127727 0.0210603 0.121314 0.0868688 0.0302046 0.242775 0.136556 0.027761 0.19605 +0.0226922 0.0328917 0.242491 0.0294144 0.00907077 0.117753 0.153766 0.0326276 0.230842 +0.0523794 0.0226538 0.194746 0.0770112 0.0240401 0.208284 0.0140959 0.0253084 0.146728 +0.0969111 0.0219528 0.194132 0.110722 0.0231434 0.19256 0.045384 0.0317713 0.248477 +0.157358 0.0341339 0.251481 0.127113 0.0286509 0.219626 0.0530621 0.0165634 0.168539 +0.158127 0.0322905 0.208996 0.117862 0.0257141 0.163965 0.103084 0.0207965 0.182156 +0.0168263 0.0323496 0.218634 0.0127134 0.030378 0.175534 0.0364978 0.0219628 0.178345 +0.0979974 0.0247487 0.139123 0.0857931 0.0213332 0.118552 0.0641225 0.0316309 0.251583 +0.134052 0.0289126 0.175757 0.0707324 0.0098685 0.112486 0.0455114 0.00383925 0.110748 +0.103834 0.0316619 0.249948 0.0759953 0.0142963 0.160243 0.0331165 0.0287981 0.214729 +0.0767439 0.0273706 0.226203 0.129512 0.033 0.253665 0.00522429 0.0282112 0.108058 +0.020336 0.0117551 0.108438 0.0111059 0.0344437 0.255028 0.0606051 0.0249642 0.210124 +0.0849251 0.0152126 0.145183 0.143953 0.0306323 0.220376 0.155024 0.0324555 0.193202 +0.0225919 0.0167285 0.13397 0.00607579 0.0306699 0.131741 0.00778736 0.0321553 0.160927 +0.168039 0.0341337 0.219527 0.101379 0.0291581 0.234196 0.00921833 0.0333219 0.191744 +0.0366533 0.0303433 0.231123 0.068922 0.0211704 0.193455 0.03005 0.033421 0.257514 +0.0893301 0.0311173 0.105731 0.0447174 0.0147181 0.156259 0.109053 0.0274075 0.149921 +0.129277 0.0260907 0.189346 0.115239 0.0258489 0.208092 0.067431 0.00951112 0.132742 +0.167587 0.0344392 0.238797 0.0405229 0.00796651 0.127067 0.0785905 0.0323024 0.256639 +0.0263994 0.0188698 0.150116 0.0387625 0.0255277 0.199437 0.0108304 0.0341707 0.234128 +0.0811914 0.0182026 0.106647 0.058282 0.00437812 0.105932 0.007519 0.0345649 0.20648 +0.0918477 0.0239139 0.20639 0.0913592 0.0180471 0.173333 0.142782 0.0338041 0.25724 +0.0526374 0.00862638 0.135963 0.150463 0.030745 0.20511 0.0608519 0.019021 0.181882 +0.0962059 0.0316774 0.126381 0.0695953 0.0293463 0.237333 0.0313014 0.00524414 0.10406 +0.105418 0.0205361 0.167041 0.115193 0.0331448 0.258922 0.0902935 0.027095 0.224049 +0.0832677 0.0207334 0.191546 0.0245432 0.0265728 0.184521 0.0193408 0.0246081 0.160381 +0.113889 0.02833 0.224977 0.147996 0.0324927 0.182153 0.0534314 0.0328355 0.258936 +0.0460058 0.0264936 0.211397 0.0929926 0.032668 0.258369 0.0670358 0.0161456 0.170779 +0.00431991 0.0341863 0.143874 0.0101326 0.0201601 0.10413 0.021053 0.032209 0.228912 +0.0558884 0.0303249 0.241116 0.123995 0.025359 0.175791 0.128126 0.0303807 0.23214 +0.00324388 0.0337452 0.12038 0.0740436 0.0118532 0.142557 0.130786 0.0318214 0.165731 +0.107384 0.0244958 0.204101 0.0466658 0.021005 0.183372 0.0614064 0.0134123 0.158364 +0.0217063 0.0260636 0.174823 0.0225618 0.0302564 0.209209 0.0663137 0.0265272 0.2202 +0.0340349 0.0316826 0.241096 0.00656686 0.0356186 0.244545 0.00565329 0.0344105 0.169881 +0.0428543 0.0304636 0.236682 0.0905445 0.0218796 0.130886 0.0427567 0.0183933 0.169065 +0.0341449 0.0246331 0.189004 0.166432 0.0351162 0.19822 0.10083 0.0216309 0.150571 +0.0412277 0.0333533 0.260984 0.0303388 0.0115181 0.128773 0.0932417 0.0347449 0.115893 +0.0499388 0.0118202 0.148408 0.163763 0.0346444 0.260437 0.0208933 0.0340467 0.260881 +0.152049 0.0332116 0.241433 0.106779 0.0326425 0.141184 0.0714159 0.009691 0.101132 +0.00419648 0.0362572 0.183844 0.00295227 0.0382745 0.220089 0.157488 0.0324648 0.219992 +0.0812287 0.0162715 0.169059 0.125336 0.0260577 0.199971 0.0686873 0.0330273 0.261512 +0.0140867 0.0231707 0.136119 0.0923345 0.0198646 0.184268 0.167612 0.0346861 0.250036 +0.0655602 0.00814491 0.122037 0.119962 0.0322993 0.155167 0.168146 0.0344498 0.208338 +0.173357 0.0349657 0.229273 0.0749599 0.0307835 0.246703 0.138207 0.0285163 0.185255 +0.107283 0.033592 0.263848 0.0800636 0.0161578 0.116346 0.147368 0.030446 0.19166 +0.00213769 0.0342823 0.102342 0.0979507 0.0303721 0.242475 0.00428363 0.0371856 0.262266 +0.0827287 0.0257587 0.217311 0.0451162 0.00207409 0.100611 0.152734 0.0343163 0.260773 +0.00228681 0.0377218 0.15298 0.134534 0.0339191 0.262156 0.0682013 0.0232625 0.203386 +0.0219066 0.0143303 0.123101 0.0850508 0.0284371 0.232249 0.163131 0.0336224 0.229015 +0.12668 0.0315552 0.242164 0.138066 0.030706 0.227632 0.0137681 0.0320511 0.200677 +0.0847861 0.0151292 0.155378 0.0389414 0.00613661 0.117891 0.040018 0.0288431 0.222268 +0.0346577 0.0170394 0.155333 0.0848515 0.0234337 0.100026 0.113621 0.031987 0.250107 +0.114894 0.0229098 0.172807 0.0207569 0.0336051 0.251799 0.0838484 0.0227403 0.201513 +0.137765 0.0327624 0.247415 0.0253257 0.0306566 0.219158 0.0241654 0.00768901 0.100549 +0.0695547 0.0123195 0.152026 0.0516771 0.0246052 0.204287 0.0105529 0.0214818 0.112593 +0.0183008 0.029539 0.190473 0.0315548 0.0277334 0.204739 0.044037 0.0230443 0.190999 +0.00308262 0.0383252 0.253069 0.00469391 0.0361806 0.198374 0.107064 0.0305328 0.241599 +0.107296 0.0226958 0.157796 0.027664 0.0161613 0.141792 0.080739 0.0140852 0.137067 +0.0538735 0.0130186 0.154838 0.124316 0.0338222 0.263485 0.00595959 0.0251467 0.0985631 +0.112927 0.0267871 0.215552 0.0124353 0.0344835 0.264118 0.134839 0.0291448 0.216729 +0.00195884 0.0386486 0.162321 0.0149335 0.0280275 0.166411 0.101398 0.0341901 0.132717 +0.0015618 0.0370442 0.112028 0.016313 0.0129735 0.100041 0.0562418 0.0268654 0.219143 +0.0950566 0.0200325 0.145187 0.00788604 0.0270551 0.12387 0.00129881 0.0392116 0.135175 +0.0206319 0.0202569 0.143487 0.061522 0.00614322 0.113427 0.139193 0.0346814 0.169177 +0.0139838 0.0338613 0.241025 0.0548359 0.0316129 0.250011 0.0906585 0.0379833 0.0988551 +0.110795 0.0294006 0.233082 0.0635279 0.00525331 0.0988181 0.0861372 0.0333413 0.263521 +0.0430602 0.00943027 0.134926 0.0681814 0.0193285 0.184923 0.0542058 0.00250185 0.0988306 +0.0788427 0.0157373 0.0993022 0.0777077 0.0291056 0.236366 0.0668553 0.0279805 0.228682 +0.125818 0.0273845 0.210921 0.0865532 0.0316794 0.252202 0.00785094 0.0310658 0.150566 +0.0763524 0.0220599 0.19839 0.0606472 0.0209865 0.190555 0.0587375 0.0076473 0.129744 +0.0471939 0.00543815 0.119532 0.0993852 0.0194399 0.174943 0.0732904 0.0112561 0.123485 +0.00279702 0.0385397 0.228621 0.0778725 0.0133032 0.150489 0.119749 0.0244284 0.19209 +0.0175351 0.0154855 0.11548 0.0365967 0.00274122 0.0987396 0.0605851 0.0092823 0.138618 +0.00224838 0.0391132 0.211145 0.0692493 0.0248059 0.211437 0.0570626 0.0335314 0.264608 +0.0495263 0.00708062 0.128126 0.11549 0.0349903 0.148472 0.0600397 0.0229633 0.199702 +0.0938241 0.025735 0.215882 0.160212 0.0339585 0.243297 0.150595 0.0310975 0.213912 +0.0281801 0.034087 0.265514 0.0265438 0.0207786 0.158372 0.0198917 0.022729 0.152538 +0.105961 0.0280323 0.226062 0.0165581 0.0195536 0.128991 0.0866687 0.0243894 0.111654 +0.00223601 0.0388421 0.190995 0.155694 0.0348043 0.184606 0.0384587 0.0323609 0.250616 +0.00254702 0.0389111 0.237028 0.147889 0.0335571 0.250328 0.0513143 0.018854 0.177007 +0.0888516 0.0181244 0.138526 0.00052206 0.0405979 0.0962692 0.0275524 0.0316705 0.233844 +0.176301 0.0355716 0.220442 0.085437 0.0183791 0.178976 0.0108687 0.0320576 0.183771 +0.0531447 0.00438329 0.112581 0.0773057 0.033594 0.26552 0.144747 0.0343073 0.265029 +0.0714047 0.0318932 0.253847 0.121482 0.0321093 0.24871 0.0294306 0.032751 0.248758 +0.0602669 0.0171795 0.173874 0.175587 0.0352363 0.238438 0.0939018 0.0289122 0.234118 +0.0403787 0.0136541 0.148676 0.0481327 0.0158308 0.162885 0.120894 0.0241612 0.183298 +0.0142373 0.0325139 0.210421 0.00889811 0.0286758 0.140233 0.0105909 0.0340198 0.224919 +0.159197 0.0335373 0.236566 0.12106 0.0296729 0.230724 0.0749088 0.0118305 0.13279 +0.113644 0.0243786 0.199072 0.0978446 0.0336475 0.265115 0.03856 0.0270131 0.208325 +0.0400037 0.0171932 0.161761 0.00122258 0.0390749 0.127062 0.143111 0.0296403 0.209621 +0.074639 0.025766 0.217198 0.0273008 0.00808805 0.109688 0.0359578 0.0109934 0.134287 +0.0890098 0.0167055 0.165016 0.158759 0.0327085 0.200493 0.0949711 0.0315974 0.250876 +0.0758533 0.0199777 0.188447 0.031359 0.0220057 0.171822 0.0633611 0.030453 0.243565 +0.111533 0.0381892 0.142289 0.0515079 0.0295093 0.233997 0.0491402 0.0335799 0.2643 +0.146915 0.0357355 0.17431 0.1454 0.0318906 0.232311 0.0649881 0.00668475 0.106358 +0.0967464 0.018326 0.166267 0.17294 0.0360901 0.204214 0.103532 0.0261892 0.144834 +0.126946 0.0350313 0.158608 0.116058 0.0339778 0.2663 0.11411 0.0265851 0.157251 +0.0904091 0.0254546 0.122571 0.00639385 0.0277626 0.116346 0.0847526 0.0243332 0.209623 +0.0461495 0.0241658 0.198394 0.036863 0.00475518 0.109434 0.0608883 0.0292732 0.235412 +0.0308285 0.0267405 0.196931 0.0982934 0.0233526 0.201491 0.101041 0.0249345 0.209464 +0.124517 0.0273667 0.168006 0.161796 0.0352148 0.190759 0.0439031 0.0203495 0.178308 +0.0758585 0.013193 0.107037 0.0308203 0.0303524 0.224858 0.0540403 0.0207907 0.186904 +0.129262 0.0263227 0.181481 0.103642 0.0219056 0.189896 0.0346119 0.00849522 0.123057 +0.0986531 0.0384393 0.124987 0.0349361 0.0340023 0.266139 0.0925048 0.0174607 0.152356 +0.0437034 0.0294016 0.229127 0.0919172 0.0388338 0.106283 0.107164 0.0209765 0.175907 +0.17069 0.0348887 0.25715 0.0331524 0.0155009 0.147564 0.119655 0.0278884 0.219128 +0.0147955 0.016109 0.108237 0.144179 0.0294117 0.200646 0.0263606 0.0270727 0.19149 +0.175042 0.0357305 0.212645 0.000991905 0.0404421 0.143731 0.105062 0.023144 0.197003 +0.0896044 0.02173 0.195383 0.0175897 0.0288336 0.18214 0.0140495 0.0340472 0.247863 +0.0983188 0.0276873 0.22605 0.0738671 0.0163796 0.171732 0.0134283 0.027569 0.157106 +0.0292229 0.0046578 0.097115 0.0514114 0.0031241 0.105613 0.0555093 0.0146547 0.161978 +0.0612894 0.0152596 0.166144 0.0411778 0.0221676 0.184212 0.10087 0.032665 0.257506 +0.00867855 0.0343056 0.215069 0.0292545 0.0241295 0.179118 0.0954268 0.0270294 0.131011 +0.0187352 0.0329873 0.235803 0.047197 0.0325513 0.255467 0.0882474 0.0302778 0.0976232 +0.0467527 0.027563 0.21854 0.0243837 0.0233116 0.16589 0.0684194 0.0143929 0.162928 +0.163165 0.0332609 0.213971 0.099938 0.0195439 0.158154 0.0676732 0.0175764 0.1771 +0.0065731 0.0340971 0.177697 0.108156 0.0256166 0.210587 0.00181507 0.0392735 0.176256 +0.123213 0.0298117 0.161513 0.0819045 0.0192959 0.184649 0.0823612 0.0153724 0.162435 +0.17385 0.0350807 0.2452 0.1313 0.0297988 0.225437 0.0859063 0.0194447 0.125609 +0.108351 0.0326271 0.256077 0.0527737 0.0260422 0.212807 0.0113294 0.0172867 0.0970888 +0.0447749 0.0254814 0.204559 0.0487054 0.0307922 0.242089 0.083636 0.0270345 0.224291 +0.00178004 0.0397904 0.204254 0.136113 0.0333981 0.255192 0.00709084 0.0354796 0.267968 +0.0852519 0.0173209 0.132016 0.141441 0.0313934 0.177459 0.0725367 0.0284184 0.232006 +0.00127729 0.0410023 0.266948 0.00258542 0.0320758 0.0958719 0.150797 0.0317825 0.223908 +0.000589563 0.0406837 0.105571 0.133333 0.0369833 0.16201 0.144533 0.0327658 0.242842 +0.111523 0.0231029 0.163396 0.0304191 0.013395 0.135896 0.109173 0.0273632 0.220828 +0.132364 0.0313843 0.237747 0.0596467 0.0325127 0.257304 0.151194 0.0309797 0.198271 +0.121916 0.0329654 0.255792 0.0113486 0.0240787 0.128627 0.0663892 0.0105011 0.14269 +0.0231988 0.0114977 0.114973 0.0406386 0.0277236 0.214967 0.165659 0.034681 0.267589 +0.158611 0.0345802 0.26633 0.0461546 0.0106936 0.141939 0.0537141 0.0100286 0.142445 +0.0420574 0.0313362 0.243351 0.0715827 0.00865391 0.0454544 0.0196445 0.00865391 0.0454544 +0.0460881 0.000507579 0.0291092 0.0453387 0.000505933 0.0623911 0.0840402 0.0216801 0.0650094 +0.0837943 0.0212951 0.0254078 0.00743284 0.0212951 0.0655011 0.00718689 0.0216801 0.0258995 +0.0662206 0.00544469 0.0230728 0.0662206 0.00544469 0.0678361 0.0249591 0.0054688 0.0229457 +0.0248839 0.00550724 0.0679583 0.0870894 0.0273624 0.0454544 0.00413767 0.0273624 0.0454544 +0.0541989 0.00132325 0.0454544 0.036901 0.00134792 0.0459915 0.052566 0.00103995 0.0156435 +0.052566 0.00103995 0.0752654 0.00234721 0.0320267 0.0759736 0.00234721 0.0320267 0.0149353 +0.0888799 0.0320267 0.0759736 0.0888799 0.0320267 0.0149353 0.0772512 0.0133227 0.0155539 +0.0772512 0.0133227 0.075355 0.0139759 0.0133227 0.0155539 0.0139759 0.0133227 0.075355 +0.0377392 0.00119236 0.0760421 0.0377392 0.00119236 0.0148668 0.0752303 0.0114784 0.0310337 +0.0756971 0.0118849 0.059029 0.01553 0.0118849 0.0318799 0.01553 0.0118849 0.059029 +0.0894927 0.0340968 0.0583832 0.0892817 0.0333424 0.0331221 0.00194539 0.0333424 0.0577868 +0.0018263 0.0337621 0.0327265 0.0292889 0.00353771 0.0362043 0.0617272 0.0034571 0.0546606 +0.0615775 0.00340067 0.0361592 0.0296594 0.00339699 0.0548084 0.080703 0.017066 0.0488469 +0.0105277 0.0170616 0.0419098 0.0653768 0.00502644 0.00887839 0.0653768 0.00502644 0.0820305 +0.027297 0.00435895 0.079739 0.027297 0.00435893 0.0111671 0.0829819 0.0200808 0.0375865 +0.00824522 0.0200808 0.0533224 0.0835198 0.0208753 0.0797231 0.0835198 0.0208753 0.0111858 +0.0077073 0.0208753 0.0111858 0.0077073 0.0208753 0.0797231 0.0350613 0.00174693 0.0629772 +0.0561163 0.00173513 0.0636494 0.0575757 0.00210737 0.0280587 0.0351055 0.0017364 0.0271405 +0.00109604 0.0367786 0.0674667 0.00109604 0.0367786 0.0234422 0.0901311 0.0367786 0.0674667 +0.0901311 0.0367786 0.0234422 0.0457226 0.000505233 0.0402193 0.0901241 0.0367446 0.0425907 +0.00110305 0.0367446 0.0425907 0.0851729 0.0235729 0.0536885 0.00628756 0.0231655 0.0373454 +0.045728 0.000505246 0.0511927 0.0455151 0.000505209 0.0822136 0.0455151 0.000505209 0.00869533 +0.0720719 0.00899931 0.00858243 0.0720719 0.00899931 0.0823265 0.0190483 0.00907603 0.0824199 +0.0190483 0.00907603 0.00848898 0.0537038 0.00123087 0.0359114 0.0270126 0.00448532 0.0455901 +0.063833 0.00431634 0.0454517 0.0540074 0.00128685 0.0546047 0.0448815 0.000510998 0.0206687 +0.0448815 0.000510998 0.0702402 0.0373276 0.00126671 0.036118 0.0777596 0.0138234 0.0406448 +0.0134535 0.0138374 0.0502416 0.0790581 0.015177 0.0667192 0.0790581 0.015177 0.0241897 +0.012169 0.015177 0.0667192 0.012169 0.015177 0.0241897 0.0377564 0.00118934 0.05494 +0.000784368 0.0384467 0.0509601 0.0904427 0.0384467 0.0509601 0.0127199 0.014589 0.00751042 +0.0127199 0.014589 0.0833985 0.0785216 0.0146041 0.00751982 0.0785216 0.0146041 0.0833891 +0.0902812 0.0375392 0.00847584 0.0902812 0.0375392 0.0824331 0.000945933 0.0375392 0.00847584 +0.000945933 0.0375392 0.0824331 0.055549 0.00160423 0.00822725 0.055549 0.00160423 0.0826816 +0.00316702 0.0296994 0.0228596 0.0032241 0.0295512 0.0680035 0.088003 0.0295512 0.0229054 +0.0880629 0.0297066 0.0680502 0.020929 0.00779177 0.0370819 0.0704027 0.00785965 0.0371291 +0.0704027 0.00785965 0.0537798 0.0196795 0.00862954 0.016469 0.0196763 0.00863176 0.0744411 +0.0206549 0.00797048 0.0537031 0.0685811 0.00673459 0.0168149 0.0685811 0.00673459 0.074094 +0.0362354 0.00148307 0.0841542 0.0362354 0.00148307 0.00675473 0.0599916 0.00283905 0.0182064 +0.0599916 0.00283905 0.0727025 0.0864282 0.0259528 0.0331395 0.00479895 0.0259528 0.0577694 +0.0729885 0.00967297 0.0244693 0.0729885 0.00967297 0.0664396 0.0175106 0.0102338 0.0243323 +0.0174913 0.010249 0.0665817 0.0804205 0.0167263 0.0584326 0.0108264 0.0167028 0.032472 +0.0826702 0.0196364 0.0722873 0.082662 0.0196249 0.0186048 0.00856511 0.0196249 0.0723041 +0.00855689 0.0196364 0.0186216 0.0319899 0.00259479 0.0708078 0.0314263 0.00277589 0.0199056 +0.0873802 0.0280251 0.00780357 0.0873802 0.0280251 0.0831053 0.00384688 0.0280251 0.00780357 +0.00384688 0.0280251 0.0831053 0.000729134 0.038784 0.0159833 0.000729134 0.038784 0.0749257 +0.090498 0.038784 0.0159833 0.090498 0.038784 0.0749257 0.0233435 0.00633442 0.0605505 +0.0907381 0.0404939 0.0590908 0.0907381 0.0404939 0.0318181 0.000489001 0.0404939 0.0590908 +0.000489001 0.0404939 0.0318181 0.0675217 0.00613317 0.030419 0.0675217 0.00613317 0.0604899 +0.0152779 0.0121091 0.039586 0.0239265 0.00601235 0.0304513 0.080999 0.0174293 0.0309697 +0.0103411 0.0172897 0.059625 0.0758046 0.0119801 0.0513493 0.0887589 0.0316565 0.0509168 +0.00205045 0.0329843 0.0509187 0.0870508 0.0272766 0.0604742 0.00417628 0.0272766 0.0304347 +0.00351319 0.028823 0.0384442 0.0874852 0.0282716 0.038921 0.0861946 0.0254831 0.0167066 +0.0862264 0.0255462 0.0741607 0.00500124 0.0255453 0.0167479 0.00503254 0.0254831 0.0742023 +0.0838977 0.0214559 0.044276 0.00732942 0.0214559 0.0466329 0.0513313 0.000866154 0.022367 +0.0511544 0.000844079 0.0688262 0.0383717 0.0010857 0.0693349 0.0457494 0.0458676 1e-07 +0.0456136 0.0686691 1e-07 0.0456136 0.0231071 1e-07 0.0651468 0.0481949 1e-07 +0.0245593 0.0474185 1e-07 0.0264367 0.0286925 1e-07 0.0647904 0.0286925 1e-07 +0.0274722 0.0665984 1e-07 0.0637549 0.0665984 1e-07 0.0147465 0.0364494 1e-07 +0.0764806 0.0364494 1e-07 0.0331724 0.0167062 1e-07 0.0580548 0.0167062 1e-07 +0.0535099 0.0577718 1e-07 0.0380443 0.0573856 1e-07 0.0526874 0.0345333 1e-07 +0.0395498 0.0341706 1e-07 0.0335579 0.0753986 1e-07 0.0576693 0.0753986 1e-07 +0.0158942 0.060168 1e-07 0.0753329 0.060168 1e-07 0.0456136 0.00901477 1e-07 +0.0323486 0.0448292 1e-07 0.0560188 0.0441557 1e-07 0.0824872 0.0493131 1e-07 +0.00873987 0.0493131 1e-07 0.0456136 0.08268 1e-07 0.0156305 0.0269718 1e-07 +0.0755966 0.0269718 1e-07 0.0233128 0.0184247 1e-07 0.0679143 0.0184247 1e-07 +0.0650287 0.040212 1e-07 0.0253103 0.0407549 1e-07 0.0243676 0.0762969 1e-07 +0.0668595 0.0762969 1e-07 0.0298736 0.0557925 1e-07 0.0628732 0.0564083 1e-07 +0.0180159 0.0687498 1e-07 0.0732112 0.0687498 1e-07 0.0548698 0.0259305 1e-07 +0.0364836 0.0258851 1e-07 0.037234 0.0658698 1e-07 0.0545423 0.0665064 1e-07 +0.0369408 0.00941212 1e-07 0.0542863 0.00941212 1e-07 0.0083013 0.0410085 1e-07 +0.0829258 0.0410085 1e-07 0.0456136 0.0605916 1e-07 0.0458311 0.0305399 1e-07 +0.00935422 0.0571866 1e-07 0.0818729 0.0571866 1e-07 0.0538743 0.083299 1e-07 +0.0373528 0.083299 1e-07 0.0296368 0.0818438 1e-07 0.0615903 0.0818438 1e-07 +0.0408251 0.0172664 1e-07 0.0504021 0.0172664 1e-07 0.0295759 0.0107735 1e-07 +0.0616512 0.0107735 1e-07 0.00848929 0.0337362 1e-07 0.0827378 0.0337362 1e-07 +0.0464697 0.0384646 1e-07 0.0480022 0.052572 1e-07 0.017201 0.0430323 1e-07 +0.073682 0.0430657 1e-07 0.0389915 0.049642 1e-07 0.0113363 0.0649584 1e-07 +0.0798908 0.0649584 1e-07 0.0157455 0.0192047 1e-07 0.0754816 0.0192047 1e-07 +0.0315724 0.0351195 1e-07 0.060185 0.0341974 1e-07 0.0692939 0.0349315 1e-07 +0.0216999 0.0347347 1e-07 0.0415952 0.0750567 1e-07 0.049818 0.0752683 1e-07 +0.0391136 0.0413489 1e-07 0.0183749 0.0533889 1e-07 0.0728029 0.0535926 1e-07 +0.0298514 0.0224271 1e-07 0.0614073 0.0224385 1e-07 0.022453 0.0608768 1e-07 +0.0685818 0.0608875 1e-07 0.0575419 0.0520771 1e-07 +CELLS 7232 28608 +2 0 14 +2 0 28 +2 1 52 +2 1 300 +2 2 37 +2 3 38 +2 4 286 +2 5 61 +2 6 62 +2 7 63 +2 8 66 +2 9 69 +2 9 159 +2 10 268 +2 11 70 +2 11 71 +2 12 86 +2 12 231 +2 12 247 +2 13 246 +2 14 15 +2 15 16 +2 16 17 +2 17 18 +2 18 19 +2 19 20 +2 20 21 +2 21 22 +2 22 23 +2 23 24 +2 24 25 +2 25 26 +2 26 27 +2 27 1 +2 28 29 +2 29 30 +2 30 31 +2 31 32 +2 32 33 +2 33 34 +2 34 35 +2 35 36 +2 36 2 +2 37 3 +2 38 39 +2 39 40 +2 40 41 +2 41 42 +2 42 43 +2 43 44 +2 44 45 +2 45 46 +2 46 47 +2 47 48 +2 48 49 +2 49 50 +2 50 51 +2 51 4 +2 52 53 +2 53 54 +2 54 55 +2 55 56 +2 56 57 +2 57 58 +2 58 59 +2 59 60 +2 60 4 +2 61 6 +2 62 7 +2 63 64 +2 64 65 +2 65 8 +2 66 67 +2 67 68 +2 68 5 +2 69 10 +2 70 10 +2 71 72 +2 72 73 +2 73 74 +2 74 75 +2 75 76 +2 76 77 +2 77 78 +2 78 79 +2 79 80 +2 80 81 +2 81 82 +2 82 83 +2 83 84 +2 84 85 +2 85 12 +2 86 87 +2 87 88 +2 88 89 +2 89 90 +2 90 91 +2 91 92 +2 92 93 +2 93 94 +2 94 95 +2 95 96 +2 96 97 +2 97 98 +2 98 99 +2 99 100 +2 100 101 +2 101 102 +2 102 103 +2 103 104 +2 104 105 +2 105 106 +2 106 107 +2 107 108 +2 108 109 +2 109 110 +2 110 111 +2 111 112 +2 112 113 +2 113 114 +2 114 115 +2 115 116 +2 116 117 +2 117 118 +2 118 119 +2 119 120 +2 120 121 +2 121 122 +2 122 123 +2 123 124 +2 124 125 +2 125 126 +2 126 127 +2 127 128 +2 128 129 +2 129 130 +2 130 131 +2 131 132 +2 132 133 +2 133 134 +2 134 135 +2 135 136 +2 136 137 +2 137 138 +2 138 139 +2 139 140 +2 140 141 +2 141 142 +2 142 143 +2 143 144 +2 144 145 +2 145 146 +2 146 147 +2 147 148 +2 148 149 +2 149 150 +2 150 151 +2 151 152 +2 152 153 +2 153 154 +2 154 155 +2 155 156 +2 156 157 +2 157 158 +2 158 8 +2 159 160 +2 160 161 +2 161 162 +2 162 163 +2 163 164 +2 164 165 +2 165 166 +2 166 167 +2 167 168 +2 168 169 +2 169 170 +2 170 171 +2 171 172 +2 172 173 +2 173 174 +2 174 175 +2 175 176 +2 176 177 +2 177 178 +2 178 179 +2 179 180 +2 180 181 +2 181 182 +2 182 183 +2 183 184 +2 184 185 +2 185 186 +2 186 187 +2 187 188 +2 188 189 +2 189 190 +2 190 191 +2 191 192 +2 192 193 +2 193 194 +2 194 195 +2 195 196 +2 196 197 +2 197 198 +2 198 199 +2 199 200 +2 200 201 +2 201 202 +2 202 203 +2 203 204 +2 204 205 +2 205 206 +2 206 207 +2 207 208 +2 208 209 +2 209 210 +2 210 211 +2 211 212 +2 212 213 +2 213 214 +2 214 215 +2 215 216 +2 216 217 +2 217 218 +2 218 219 +2 219 220 +2 220 221 +2 221 222 +2 222 223 +2 223 224 +2 224 225 +2 225 226 +2 226 227 +2 227 228 +2 228 229 +2 229 230 +2 230 6 +2 231 232 +2 232 233 +2 233 234 +2 234 235 +2 235 236 +2 236 237 +2 237 238 +2 238 239 +2 239 240 +2 240 241 +2 241 242 +2 242 243 +2 243 244 +2 244 245 +2 245 13 +2 246 9 +2 247 248 +2 248 249 +2 249 250 +2 250 251 +2 251 252 +2 252 253 +2 253 254 +2 254 255 +2 255 256 +2 256 257 +2 257 258 +2 258 259 +2 259 260 +2 260 261 +2 261 262 +2 262 263 +2 263 264 +2 264 265 +2 265 266 +2 266 267 +2 267 4 +2 268 269 +2 269 270 +2 270 271 +2 271 272 +2 272 273 +2 273 274 +2 274 275 +2 275 276 +2 276 277 +2 277 278 +2 278 279 +2 279 280 +2 280 281 +2 281 282 +2 282 283 +2 283 284 +2 284 285 +2 285 3 +2 286 287 +2 287 288 +2 288 289 +2 289 290 +2 290 291 +2 291 292 +2 292 293 +2 293 294 +2 294 295 +2 295 296 +2 296 297 +2 297 298 +2 298 299 +2 299 2 +2 300 301 +2 301 302 +2 302 303 +2 303 304 +2 304 305 +2 305 306 +2 306 307 +2 307 308 +2 308 309 +2 309 310 +2 310 311 +2 311 312 +2 312 313 +2 313 0 +3 0 406 14 +3 0 3305 28 +3 0 3419 313 +3 1 409 52 +3 1 3303 300 +3 1 3398 27 +3 1 3420 3398 +3 2 285 37 +3 2 464 36 +3 2 3061 285 +3 2 3306 299 +3 3 464 37 +3 3 2655 38 +3 4 404 51 +3 4 2654 267 +3 4 3014 286 +3 4 3304 60 +3 5 479 68 +3 5 480 479 +3 5 1973 61 +3 6 480 61 +3 6 996 62 +3 6 1973 230 +3 7 480 62 +3 7 887 63 +3 7 996 887 +3 8 925 158 +3 8 1907 66 +3 9 1099 159 +3 9 2395 246 +3 9 2769 268 +3 10 69 268 +3 10 1099 69 +3 10 3189 70 +3 11 923 70 +3 11 994 923 +3 11 2998 71 +3 11 3185 2998 +3 12 2804 231 +3 12 3206 247 +3 13 1867 245 +3 13 2335 1867 +3 13 2707 246 +3 14 441 15 +3 14 3399 0 +3 14 3423 3399 +3 15 441 16 +3 15 3423 14 +3 15 3440 3423 +3 16 403 17 +3 16 441 363 +3 16 3440 15 +3 17 383 18 +3 17 403 383 +3 17 3411 16 +3 18 357 19 +3 18 383 357 +3 18 3407 17 +3 18 3427 3407 +3 19 410 20 +3 19 3427 18 +3 20 381 21 +3 20 410 381 +3 20 3426 19 +3 21 425 22 +3 21 3400 20 +3 21 3425 3400 +3 22 359 23 +3 22 425 359 +3 22 3425 21 +3 22 3428 3425 +3 23 384 24 +3 23 3428 22 +3 24 405 25 +3 24 3408 23 +3 24 3412 3408 +3 25 405 365 +3 25 444 26 +3 25 3412 24 +3 25 3441 3412 +3 26 444 27 +3 26 3441 25 +3 27 409 1 +3 27 444 409 +3 27 3424 26 +3 28 406 0 +3 28 450 406 +3 28 3343 29 +3 29 450 28 +3 29 3268 30 +3 29 3343 3268 +3 30 372 29 +3 30 452 372 +3 30 3351 31 +3 31 452 30 +3 31 3273 32 +3 31 3351 3273 +3 32 401 31 +3 32 3297 33 +3 33 375 32 +3 33 454 375 +3 33 3350 34 +3 34 454 33 +3 34 3267 35 +3 34 3350 3267 +3 35 371 34 +3 35 448 371 +3 35 3344 36 +3 36 448 35 +3 36 464 407 +3 36 3306 2 +3 36 3344 3306 +3 37 285 3 +3 37 464 2 +3 38 443 407 +3 38 464 3 +3 38 2713 39 +3 39 443 38 +3 39 2713 40 +3 40 408 364 +3 40 443 39 +3 40 2653 41 +3 40 2713 2552 +3 41 408 40 +3 41 2586 42 +3 41 2653 2586 +3 42 382 41 +3 42 2742 43 +3 43 356 42 +3 43 411 356 +3 43 2642 44 +3 43 2742 2642 +3 44 411 43 +3 44 2793 45 +3 45 380 44 +3 45 424 380 +3 45 2731 46 +3 45 2793 2588 +3 46 424 45 +3 46 2607 47 +3 46 2731 2607 +3 47 358 46 +3 47 385 358 +3 47 2797 48 +3 48 385 47 +3 48 400 385 +3 48 2589 49 +3 48 2797 2589 +3 49 400 48 +3 49 439 362 +3 49 2791 50 +3 50 439 49 +3 50 2753 51 +3 50 2791 2596 +3 51 439 50 +3 51 2654 4 +3 51 2753 2654 +3 52 446 53 +3 52 3303 1 +3 52 3345 3303 +3 53 370 54 +3 53 446 370 +3 53 3345 52 +3 54 456 55 +3 54 3270 53 +3 54 3349 3270 +3 55 402 56 +3 55 456 402 +3 55 3349 54 +3 56 377 57 +3 56 402 377 +3 56 3272 55 +3 56 3298 3272 +3 57 453 58 +3 57 3298 56 +3 57 3348 3298 +3 58 373 59 +3 58 453 373 +3 58 3348 57 +3 59 449 60 +3 59 3269 58 +3 59 3346 3269 +3 60 404 4 +3 60 449 404 +3 60 3346 59 +3 61 480 5 +3 61 1973 6 +3 62 480 6 +3 62 996 7 +3 63 64 68 +3 63 479 7 +3 63 1313 64 +3 64 65 67 +3 64 1288 65 +3 64 1313 936 +3 65 8 66 +3 65 925 8 +3 65 1288 925 +3 66 2274 67 +3 67 65 66 +3 67 2274 1909 +3 67 2308 68 +3 68 64 67 +3 68 479 63 +3 68 1858 5 +3 68 2308 1858 +3 69 1099 9 +3 70 1099 10 +3 70 3185 11 +3 70 3189 3185 +3 71 994 11 +3 71 1412 994 +3 71 2998 2933 +3 71 3048 72 +3 72 1273 1013 +3 72 1412 71 +3 72 3130 73 +3 73 1273 72 +3 73 3101 74 +3 73 3130 2928 +3 74 844 73 +3 74 1270 844 +3 74 3041 75 +3 74 3101 3041 +3 75 1270 74 +3 75 2942 76 +3 75 3041 2942 +3 76 913 75 +3 76 3067 77 +3 77 823 76 +3 77 1093 823 +3 77 3017 78 +3 77 3067 3017 +3 78 1093 77 +3 78 3085 79 +3 79 878 78 +3 79 1224 878 +3 79 2952 80 +3 79 3085 2952 +3 80 1224 79 +3 80 3109 81 +3 81 908 80 +3 81 2995 82 +3 81 3109 2995 +3 82 828 81 +3 82 1173 828 +3 82 2962 83 +3 82 2995 2962 +3 83 1173 82 +3 83 1295 915 +3 83 3068 84 +3 84 1295 83 +3 84 3068 2960 +3 84 3207 85 +3 85 12 86 +3 85 1295 84 +3 85 3206 12 +3 85 3207 3206 +3 86 12 231 +3 86 822 85 +3 86 1797 87 +3 87 822 86 +3 87 1134 822 +3 87 2109 88 +3 88 1134 87 +3 88 1202 872 +3 88 2109 1845 +3 88 2181 89 +3 89 1202 88 +3 89 1969 90 +3 89 2181 1969 +3 90 989 89 +3 90 1837 91 +3 90 1969 1837 +3 91 862 90 +3 91 1266 862 +3 91 2252 92 +3 92 1266 91 +3 92 1977 93 +3 92 2252 1977 +3 93 998 92 +3 93 1147 998 +3 93 2126 94 +3 94 1147 93 +3 94 1877 95 +3 94 2126 1877 +3 95 909 94 +3 95 1094 909 +3 95 2062 96 +3 96 1094 95 +3 96 1136 1094 +3 96 2098 97 +3 97 1125 789 +3 97 1136 96 +3 97 2098 1761 +3 97 2328 98 +3 98 1125 97 +3 98 1435 1125 +3 98 2078 99 +3 98 2328 2078 +3 99 1368 900 +3 99 1435 98 +3 99 2078 1834 +3 99 2415 100 +3 100 1368 99 +3 100 2319 101 +3 100 2415 2319 +3 101 978 100 +3 101 1450 978 +3 101 1972 102 +3 101 2319 1972 +3 102 1308 895 +3 102 1450 101 +3 102 1972 1884 +3 102 2392 103 +3 103 1308 102 +3 103 2058 104 +3 103 2392 2058 +3 104 1057 103 +3 104 1320 759 +3 104 2058 1737 +3 104 2135 105 +3 105 1320 104 +3 105 2377 106 +3 106 1139 105 +3 106 1923 107 +3 106 2377 1923 +3 107 885 106 +3 107 1430 885 +3 107 1923 1756 +3 107 2088 108 +3 108 1430 107 +3 108 1994 109 +3 108 2088 1994 +3 109 1043 108 +3 109 1258 1043 +3 109 2315 110 +3 110 1258 109 +3 110 1336 1258 +3 110 2315 111 +3 111 1206 842 +3 111 1336 110 +3 111 2131 112 +3 111 2315 1811 +3 112 1206 111 +3 112 1348 1206 +3 112 2265 113 +3 113 1256 860 +3 113 1348 112 +3 113 2265 1840 +3 113 2269 114 +3 114 1256 113 +3 114 2095 115 +3 114 2269 2095 +3 115 1124 114 +3 115 1232 1124 +3 115 2205 116 +3 116 1232 115 +3 116 1798 117 +3 116 2205 1798 +3 117 825 116 +3 117 1069 825 +3 117 2045 118 +3 118 1069 117 +3 118 1190 1069 +3 118 2045 1690 +3 118 2142 119 +3 119 1190 118 +3 119 1873 120 +3 119 2142 1873 +3 120 901 119 +3 120 1221 901 +3 120 2219 121 +3 121 1221 120 +3 121 1386 1221 +3 121 2376 122 +3 122 1005 812 +3 122 1386 121 +3 122 1978 123 +3 122 2376 1790 +3 123 1005 122 +3 123 1350 1005 +3 123 2333 124 +3 124 1350 123 +3 124 2027 125 +3 124 2333 2027 +3 125 1059 124 +3 125 1864 126 +3 125 2027 1864 +3 126 892 125 +3 126 1402 892 +3 126 2383 127 +3 127 1402 126 +3 127 1890 128 +3 127 2383 1890 +3 128 916 127 +3 128 1326 916 +3 128 2312 129 +3 129 1178 877 +3 129 1326 128 +3 129 2157 130 +3 129 2312 1856 +3 130 1178 129 +3 130 1924 131 +3 130 2157 1924 +3 131 945 130 +3 131 1727 132 +3 131 1924 1727 +3 132 750 131 +3 132 1105 750 +3 132 2075 133 +3 133 1105 132 +3 133 1928 134 +3 133 2075 1928 +3 134 946 133 +3 134 1121 946 +3 134 2100 135 +3 135 1121 134 +3 135 1810 136 +3 135 2100 1810 +3 136 832 135 +3 136 1092 832 +3 136 2067 137 +3 137 1092 136 +3 137 1999 138 +3 137 2067 1999 +3 138 1024 137 +3 138 1250 1024 +3 138 2240 139 +3 139 1250 138 +3 139 1838 140 +3 139 2240 1838 +3 140 865 139 +3 140 1188 865 +3 140 2180 141 +3 141 1188 140 +3 141 2122 142 +3 141 2180 2122 +3 142 1142 141 +3 142 1212 764 +3 142 2122 1739 +3 142 2191 143 +3 143 1212 142 +3 143 1950 144 +3 143 2191 1950 +3 144 971 143 +3 144 1362 971 +3 144 2344 145 +3 145 1362 144 +3 145 1967 146 +3 145 2344 1967 +3 146 991 145 +3 146 1439 790 +3 146 1967 1771 +3 146 2414 147 +3 147 1439 146 +3 147 2053 148 +3 147 2414 2053 +3 148 1084 147 +3 148 1816 149 +3 148 2053 1816 +3 149 840 148 +3 149 1802 150 +3 149 1816 1802 +3 150 827 149 +3 150 1143 827 +3 150 2112 151 +3 151 1143 150 +3 151 1844 152 +3 151 2112 1844 +3 152 866 151 +3 152 933 866 +3 152 1910 153 +3 153 933 152 +3 153 1318 933 +3 153 2303 154 +3 154 1318 153 +3 154 2009 155 +3 154 2303 2009 +3 155 1036 154 +3 155 1901 156 +3 155 2009 1901 +3 156 926 155 +3 156 1423 926 +3 156 2393 157 +3 157 1423 156 +3 157 2003 158 +3 157 2393 2003 +3 158 1020 157 +3 158 1907 8 +3 158 2003 1907 +3 159 1081 160 +3 159 1099 1081 +3 159 2395 9 +3 159 2397 1940 +3 160 1026 161 +3 160 1081 1026 +3 160 2397 159 +3 161 1344 162 +3 161 2051 1697 +3 161 2059 160 +3 162 1160 163 +3 162 1344 1015 +3 162 2051 161 +3 162 2071 2051 +3 163 1160 164 +3 163 2071 162 +3 164 911 165 +3 164 1160 761 +3 164 1722 163 +3 164 1824 1722 +3 165 1347 166 +3 165 1824 164 +3 165 2099 1824 +3 166 1011 167 +3 166 1347 1011 +3 166 2099 165 +3 166 2374 1925 +3 167 1087 168 +3 167 2374 166 +3 168 1352 169 +3 168 2087 167 +3 169 1352 956 +3 169 1377 170 +3 169 1812 168 +3 169 2097 1812 +3 170 1062 171 +3 170 1377 1062 +3 170 2097 169 +3 171 1452 172 +3 171 1985 170 +3 172 965 173 +3 172 1452 965 +3 172 1705 171 +3 172 1951 1705 +3 173 937 174 +3 173 965 937 +3 173 1951 172 +3 174 1240 175 +3 174 1911 173 +3 174 2224 1911 +3 175 786 176 +3 175 1240 786 +3 175 2224 174 +3 176 1146 177 +3 176 1760 175 +3 176 2132 1760 +3 177 1004 178 +3 177 1146 1004 +3 177 2132 176 +3 178 850 179 +3 178 1004 850 +3 178 1982 177 +3 179 1075 180 +3 179 1833 178 +3 179 2046 1833 +3 180 1053 181 +3 180 1075 1053 +3 180 2046 179 +3 181 1327 182 +3 181 2028 180 +3 181 2298 2028 +3 182 838 183 +3 182 1327 838 +3 182 2298 181 +3 182 2404 1815 +3 183 1437 184 +3 183 2404 182 +3 184 1133 185 +3 184 1437 1133 +3 184 2404 183 +3 185 1133 932 +3 185 1293 186 +3 185 2107 184 +3 185 2278 1906 +3 186 1116 187 +3 186 1293 1116 +3 186 2278 185 +3 187 730 188 +3 187 1116 730 +3 187 2092 186 +3 188 907 189 +3 188 1702 187 +3 188 1878 1702 +3 189 773 190 +3 189 907 773 +3 189 1878 188 +3 190 924 191 +3 190 1753 189 +3 190 1893 1753 +3 191 1271 192 +3 191 1893 190 +3 191 2259 1893 +3 192 1227 193 +3 192 1271 1227 +3 192 2259 191 +3 193 1438 194 +3 193 2216 192 +3 193 2407 2216 +3 194 1068 195 +3 194 1438 1068 +3 194 2407 193 +3 195 1068 785 +3 195 1376 196 +3 195 2038 194 +3 195 2353 1766 +3 196 1127 197 +3 196 1376 1127 +3 196 2353 195 +3 197 769 198 +3 197 1127 769 +3 197 2104 196 +3 198 938 199 +3 198 1747 197 +3 198 1897 1747 +3 199 1111 200 +3 199 1897 198 +3 199 2069 1897 +3 200 930 201 +3 200 1111 930 +3 200 2069 199 +3 201 1310 202 +3 201 1887 200 +3 201 2280 1887 +3 202 947 203 +3 202 1310 947 +3 202 2280 201 +3 203 864 204 +3 203 947 864 +3 203 1934 202 +3 204 1260 205 +3 204 1839 203 +3 204 2241 1839 +3 205 1260 920 +3 205 1338 206 +3 205 2241 204 +3 205 2348 1892 +3 206 1276 207 +3 206 1338 1276 +3 206 2348 205 +3 207 869 208 +3 207 1276 869 +3 207 2283 206 +3 208 1457 209 +3 208 1841 207 +3 209 1017 210 +3 209 1457 1017 +3 209 1687 208 +3 209 1998 1687 +3 210 1449 211 +3 210 1998 209 +3 210 2416 1998 +3 211 1060 212 +3 211 1449 1060 +3 211 2416 210 +3 212 1364 213 +3 212 2039 211 +3 212 2339 2039 +3 213 1159 214 +3 213 1364 1159 +3 213 2339 212 +3 214 1159 798 +3 214 1434 215 +3 214 2141 213 +3 214 2406 1779 +3 215 1110 216 +3 215 1434 1110 +3 215 2406 214 +3 216 820 217 +3 216 1110 820 +3 216 2089 215 +3 217 821 218 +3 217 1800 216 +3 217 1801 1800 +3 218 1168 219 +3 218 1801 217 +3 218 2153 1801 +3 219 890 220 +3 219 1168 890 +3 219 2153 218 +3 220 1001 221 +3 220 1863 219 +3 220 1981 1863 +3 221 1401 222 +3 221 1981 220 +3 221 2375 1981 +3 222 959 223 +3 222 1401 959 +3 222 2375 221 +3 223 1123 224 +3 223 1933 222 +3 223 2090 1933 +3 224 1123 225 +3 224 2090 223 +3 225 1021 226 +3 225 1123 770 +3 225 1987 1744 +3 225 2090 224 +3 226 1200 227 +3 226 1987 225 +3 226 2161 1987 +3 227 979 228 +3 227 1200 979 +3 227 2161 226 +3 228 979 766 +3 228 1286 229 +3 228 1964 227 +3 228 2272 1746 +3 229 1339 230 +3 229 2272 228 +3 229 2322 2272 +3 230 996 6 +3 230 1339 996 +3 230 2322 229 +3 231 1797 86 +3 231 2276 1797 +3 231 2615 232 +3 231 2804 2615 +3 232 2276 231 +3 232 2724 233 +3 233 2154 1886 +3 233 2276 232 +3 233 2604 234 +3 233 2724 2604 +3 234 2154 233 +3 234 2573 235 +3 234 2604 2573 +3 235 1849 234 +3 235 1936 1849 +3 235 2766 236 +3 236 1936 235 +3 236 2288 1681 +3 236 2591 237 +3 236 2766 2591 +3 237 2288 236 +3 237 2703 238 +3 238 2068 1763 +3 238 2288 237 +3 238 2687 239 +3 238 2703 2546 +3 239 2068 238 +3 239 2672 240 +3 239 2687 2672 +3 240 1853 239 +3 240 2149 1853 +3 240 2576 241 +3 240 2672 2576 +3 241 2149 240 +3 241 2360 1866 +3 241 2694 242 +3 242 2360 241 +3 242 2632 243 +3 242 2694 2632 +3 243 2186 242 +3 243 2560 244 +3 243 2632 2560 +3 244 1879 243 +3 244 2175 1879 +3 244 2700 245 +3 245 2175 244 +3 245 2563 13 +3 245 2700 2563 +3 246 2335 13 +3 246 2395 1940 +3 246 2707 2662 +3 246 2769 9 +3 247 2658 2557 +3 247 2804 12 +3 247 3135 248 +3 247 3206 2932 +3 248 2658 247 +3 248 3135 2945 +3 248 3174 249 +3 249 2541 248 +3 249 2634 2541 +3 249 3073 250 +3 249 3174 3073 +3 250 2634 249 +3 250 2949 251 +3 250 3073 2949 +3 251 2600 250 +3 251 2803 2600 +3 251 3063 252 +3 252 2803 251 +3 252 3141 253 +3 253 2756 252 +3 253 3106 254 +3 253 3141 3106 +3 254 2610 253 +3 254 2630 2610 +3 254 2926 255 +3 254 3106 2926 +3 255 2630 254 +3 255 3121 256 +3 256 2542 255 +3 256 2606 2542 +3 256 3055 257 +3 256 3121 3055 +3 257 2606 256 +3 257 2760 2606 +3 257 3055 2899 +3 257 3102 258 +3 258 2760 257 +3 258 2779 2760 +3 258 3011 259 +3 258 3102 3011 +3 259 2779 258 +3 259 3193 260 +3 260 2669 2602 +3 260 2740 259 +3 260 3108 261 +3 260 3193 3108 +3 261 2669 260 +3 261 2764 2669 +3 261 3043 262 +3 261 3108 2947 +3 262 2764 261 +3 262 3099 263 +3 263 2689 262 +3 263 2715 2572 +3 263 3002 264 +3 263 3099 2935 +3 264 2715 263 +3 264 3129 265 +3 265 2528 264 +3 265 2579 2528 +3 265 2930 266 +3 265 3129 2930 +3 266 2579 265 +3 266 2737 2579 +3 266 3133 267 +3 267 2737 266 +3 267 3014 4 +3 267 3133 3014 +3 268 69 9 +3 268 2721 269 +3 268 2769 2662 +3 268 2988 2957 +3 268 3189 10 +3 269 2721 270 +3 269 2988 268 +3 270 2665 271 +3 270 2721 2543 +3 270 2988 269 +3 270 3057 2920 +3 271 2631 272 +3 271 2665 2631 +3 271 3057 270 +3 272 2551 273 +3 272 2631 2551 +3 272 3033 271 +3 273 2676 274 +3 273 2938 272 +3 273 3039 2938 +3 274 2577 275 +3 274 2676 2577 +3 274 3039 273 +3 274 3183 3039 +3 275 2673 276 +3 275 3054 2989 +3 275 3183 274 +3 276 2566 277 +3 276 2673 2566 +3 276 3054 275 +3 276 3170 2937 +3 277 2739 278 +3 277 3170 276 +3 278 2599 279 +3 278 2739 2599 +3 278 3000 2921 +3 278 3170 277 +3 279 2732 280 +3 279 3000 278 +3 280 2702 281 +3 280 2732 2702 +3 280 2961 279 +3 280 3142 2961 +3 281 2702 2564 +3 281 2720 282 +3 281 3142 280 +3 282 2644 283 +3 282 2720 2644 +3 282 3008 281 +3 282 3088 3008 +3 283 2644 2535 +3 283 2692 284 +3 283 3003 2910 +3 283 3088 282 +3 284 2692 285 +3 284 3003 283 +3 284 3192 3003 +3 285 2655 3 +3 285 2692 2655 +3 285 3192 284 +3 286 3161 287 +3 286 3304 4 +3 286 3340 3304 +3 287 2974 288 +3 287 3161 2974 +3 287 3340 286 +3 288 3021 289 +3 288 3302 3259 +3 288 3340 287 +3 289 2936 290 +3 289 3021 2936 +3 289 3302 288 +3 290 3016 291 +3 290 3280 289 +3 291 3020 292 +3 291 3254 290 +3 291 3308 3254 +3 292 2959 293 +3 292 3020 2959 +3 292 3308 291 +3 293 3037 294 +3 293 3277 292 +3 293 3321 3277 +3 294 3150 295 +3 294 3321 293 +3 295 3004 296 +3 295 3150 2981 +3 295 3255 294 +3 295 3281 3255 +3 296 3179 297 +3 296 3281 295 +3 296 3300 3281 +3 297 2996 298 +3 297 3179 2996 +3 297 3300 296 +3 297 3342 3262 +3 298 3190 299 +3 298 3342 297 +3 299 3061 2 +3 299 3190 3061 +3 299 3342 298 +3 300 3339 301 +3 300 3420 1 +3 300 3434 3420 +3 301 3339 302 +3 301 3434 300 +3 302 3301 303 +3 302 3339 3260 +3 302 3402 301 +3 302 3443 3402 +3 303 3279 304 +3 303 3301 3279 +3 303 3443 302 +3 304 3253 305 +3 304 3279 3253 +3 304 3404 303 +3 304 3432 3404 +3 305 3307 306 +3 305 3432 304 +3 306 3278 307 +3 306 3307 3278 +3 306 3418 305 +3 307 3322 308 +3 307 3395 306 +3 307 3417 3395 +3 308 3256 309 +3 308 3322 3256 +3 308 3417 307 +3 308 3431 3417 +3 309 3282 310 +3 309 3431 308 +3 310 3299 311 +3 310 3403 309 +3 310 3442 3403 +3 311 3299 3261 +3 311 3341 312 +3 311 3442 310 +3 312 3341 313 +3 312 3401 311 +3 312 3433 3401 +3 313 3305 0 +3 313 3341 3305 +3 313 3433 312 +3 314 417 388 +3 314 418 393 +3 314 460 417 +3 315 416 387 +3 315 461 394 +3 316 389 367 +3 316 399 379 +3 316 476 390 +3 316 478 366 +3 317 386 374 +3 317 392 369 +3 317 477 368 +3 318 433 376 +3 318 435 395 +3 318 465 414 +3 318 472 435 +3 319 430 396 +3 319 466 378 +3 319 470 412 +3 320 458 397 +3 320 471 413 +3 321 432 415 +3 321 438 398 +3 321 459 432 +3 321 473 438 +3 322 440 358 +3 322 451 366 +3 323 445 426 +3 323 447 422 +3 323 469 447 +3 324 427 423 +3 324 455 368 +3 325 420 359 +3 325 429 420 +3 325 442 369 +3 325 457 429 +3 326 462 375 +3 326 467 376 +3 326 474 360 +3 327 432 361 +3 327 463 432 +3 327 468 377 +3 327 475 378 +3 328 379 374 +3 328 386 351 +3 328 388 352 +3 328 389 379 +3 329 387 350 +3 329 392 374 +3 329 399 353 +3 330 411 380 +3 330 426 411 +3 330 476 426 +3 331 391 381 +3 331 477 391 +3 332 415 370 +3 332 446 409 +3 332 473 415 +3 333 414 371 +3 333 448 407 +3 333 472 414 +3 334 408 382 +3 334 422 395 +3 334 435 364 +3 334 445 422 +3 335 400 362 +3 335 419 385 +3 335 428 419 +3 335 436 396 +3 336 405 384 +3 336 429 398 +3 336 438 365 +3 337 403 363 +3 337 423 383 +3 337 434 423 +3 337 437 397 +3 338 439 404 +3 338 449 373 +3 338 470 439 +3 339 441 406 +3 339 450 372 +3 339 471 441 +3 340 390 380 +3 340 424 358 +3 340 478 390 +3 341 391 369 +3 341 425 381 +3 341 442 359 +3 342 433 395 +3 342 447 417 +3 342 460 433 +3 343 428 396 +3 343 451 428 +3 343 461 421 +3 344 434 397 +3 344 455 434 +3 344 458 393 +3 345 416 394 +3 345 457 416 +3 345 459 398 +3 346 454 371 +3 346 467 375 +3 347 413 372 +3 347 431 413 +3 347 452 401 +3 347 462 431 +3 348 412 373 +3 348 453 377 +3 348 466 412 +3 348 468 466 +3 349 456 370 +3 349 463 402 +3 350 392 329 +3 350 457 369 +3 351 386 368 +3 351 388 328 +3 351 418 388 +3 351 455 418 +3 352 389 328 +3 352 469 389 +3 353 387 329 +3 353 399 366 +3 353 421 387 +3 353 451 421 +3 354 460 393 +3 354 474 376 +3 355 430 378 +3 355 461 430 +3 355 475 394 +3 356 382 42 +3 356 445 382 +3 357 410 19 +3 357 427 410 +3 358 419 322 +3 358 424 46 +3 358 440 340 +3 359 384 23 +3 359 420 384 +3 359 425 341 +3 359 442 325 +3 360 431 326 +3 360 458 431 +3 360 474 393 +3 361 459 394 +3 361 475 327 +3 362 400 49 +3 362 436 335 +3 362 470 436 +3 363 403 16 +3 363 437 337 +3 363 471 437 +3 364 408 334 +3 364 443 40 +3 364 472 443 +3 365 405 336 +3 365 444 25 +3 365 473 444 +3 366 399 316 +3 366 440 322 +3 366 451 353 +3 366 478 440 +3 367 469 426 +3 367 476 316 +3 368 386 317 +3 368 427 324 +3 368 455 351 +3 368 477 427 +3 369 391 317 +3 369 392 350 +3 369 442 341 +3 369 457 325 +3 370 415 349 +3 370 446 332 +3 370 456 54 +3 371 414 346 +3 371 448 333 +3 371 454 34 +3 372 413 339 +3 372 450 29 +3 372 452 347 +3 373 412 338 +3 373 449 59 +3 373 453 348 +3 374 379 329 +3 374 386 328 +3 374 392 317 +3 375 401 32 +3 375 454 346 +3 375 462 401 +3 375 467 326 +3 376 433 354 +3 376 465 318 +3 376 467 465 +3 376 474 326 +3 377 453 57 +3 377 463 327 +3 377 468 348 +3 378 430 319 +3 378 468 327 +3 378 475 355 +3 379 389 316 +3 379 399 329 +3 380 390 330 +3 380 411 44 +3 380 424 340 +3 381 391 341 +3 381 410 331 +3 381 425 21 +3 382 408 41 +3 382 445 334 +3 383 403 337 +3 383 423 357 +3 384 405 24 +3 384 420 336 +3 385 400 335 +3 385 419 358 +3 387 416 350 +3 387 421 315 +3 388 417 352 +3 388 418 314 +3 389 469 367 +3 390 476 330 +3 390 478 316 +3 391 477 317 +3 393 418 344 +3 393 458 360 +3 393 460 314 +3 393 474 354 +3 394 416 315 +3 394 459 345 +3 394 461 355 +3 394 475 361 +3 395 422 342 +3 395 433 318 +3 395 435 334 +3 396 428 335 +3 396 430 343 +3 396 436 319 +3 397 434 337 +3 397 437 320 +3 397 458 344 +3 398 429 345 +3 398 438 336 +3 398 459 321 +3 401 452 31 +3 401 462 347 +3 402 456 349 +3 402 463 377 +3 404 439 51 +3 404 449 338 +3 406 441 14 +3 406 450 339 +3 407 443 333 +3 407 448 36 +3 407 464 38 +3 409 444 332 +3 409 446 52 +3 410 427 331 +3 411 426 356 +3 412 466 319 +3 412 470 338 +3 413 431 320 +3 413 471 339 +3 414 465 346 +3 414 472 318 +3 415 432 349 +3 415 473 321 +3 416 457 350 +3 417 447 352 +3 417 460 342 +3 418 455 344 +3 419 428 322 +3 420 429 336 +3 421 451 343 +3 421 461 315 +3 422 445 323 +3 422 447 342 +3 423 427 357 +3 423 434 324 +3 426 445 356 +3 426 469 323 +3 426 476 367 +3 427 477 331 +3 428 451 322 +3 429 457 345 +3 430 461 343 +3 431 458 320 +3 431 462 326 +3 432 459 361 +3 432 463 349 +3 433 460 354 +3 434 455 324 +3 435 472 364 +3 436 470 319 +3 437 471 320 +3 438 473 365 +3 439 470 362 +3 440 478 340 +3 441 471 363 +3 443 472 333 +3 444 473 332 +3 447 469 352 +3 465 467 346 +3 466 468 378 +3 479 480 7 +3 481 1265 1088 +3 481 1383 1071 +3 481 1433 1265 +3 482 1204 975 +3 482 1247 853 +3 482 1400 1204 +3 483 863 709 +3 483 964 797 +3 483 1034 863 +3 484 881 813 +3 484 1082 740 +3 484 1408 857 +3 485 953 801 +3 485 988 810 +3 485 1235 755 +3 485 1444 787 +3 486 1140 861 +3 486 1191 914 +3 486 1259 1140 +3 487 1114 951 +3 487 1198 993 +3 487 1441 1113 +3 488 1141 735 +3 488 1169 966 +3 488 1216 1141 +3 489 1177 992 +3 489 1324 1177 +3 489 1447 1019 +3 490 1008 976 +3 490 1073 793 +3 490 1358 1073 +3 491 1195 995 +3 491 1419 1023 +3 492 1003 796 +3 492 1297 1255 +3 492 1388 1003 +3 493 1132 980 +3 493 1361 1089 +3 493 1393 1361 +3 494 928 720 +3 494 1061 882 +3 494 1153 855 +3 495 970 738 +3 495 1154 725 +3 495 1296 846 +3 496 1213 816 +3 496 1397 849 +3 496 1426 1117 +3 497 815 760 +3 497 935 700 +3 497 948 815 +3 497 1299 935 +3 498 1120 711 +3 498 1370 1045 +3 498 1392 806 +3 499 1097 778 +3 499 1180 1097 +3 499 1440 986 +3 500 897 795 +3 500 1083 856 +3 500 1342 1083 +3 501 894 776 +3 501 1014 792 +3 501 1345 894 +3 502 974 779 +3 502 1161 974 +3 502 1249 788 +3 503 1129 805 +3 503 1165 884 +3 503 1223 775 +3 503 1331 903 +3 504 1158 747 +3 504 1185 763 +3 504 1189 1158 +3 505 1182 794 +3 505 1319 845 +3 506 1031 751 +3 506 1179 919 +3 506 1446 1179 +3 507 1167 754 +3 507 1239 888 +3 507 1333 830 +3 508 949 819 +3 508 1016 867 +3 508 1403 949 +3 508 1405 1016 +3 509 899 724 +3 509 934 762 +3 509 1428 899 +3 510 918 836 +3 510 1131 918 +3 510 1332 833 +3 511 962 905 +3 511 985 962 +3 511 1028 835 +3 511 1454 1028 +3 512 879 718 +3 512 1112 808 +3 512 1429 879 +3 512 1455 1112 +3 513 941 854 +3 513 987 752 +3 513 1218 987 +3 513 1275 941 +3 514 1164 896 +3 514 1197 954 +3 515 1100 876 +3 515 1163 743 +3 515 1201 847 +3 516 963 939 +3 516 1205 772 +3 517 1000 818 +3 517 1248 1000 +3 517 1283 870 +3 517 1387 1248 +3 518 1042 889 +3 518 1070 967 +3 518 1102 1070 +3 518 1301 1042 +3 519 1267 1018 +3 519 1281 1052 +3 519 1307 852 +3 520 1203 771 +3 520 1215 1078 +3 520 1393 758 +3 521 983 803 +3 521 1046 969 +3 521 1375 983 +3 522 1007 791 +3 522 1079 782 +3 522 1238 1007 +3 523 1065 957 +3 523 1157 851 +3 524 1210 931 +3 524 1330 1064 +3 524 1334 1330 +3 525 858 717 +3 525 1351 1076 +3 525 1406 858 +3 526 1044 817 +3 526 1072 1044 +3 526 1353 940 +3 526 1399 1072 +3 527 921 701 +3 527 1051 921 +3 527 1066 1051 +3 527 1108 1066 +3 528 1130 910 +3 528 1443 1130 +3 528 1456 1365 +3 529 1183 811 +3 529 1371 1080 +3 530 1085 999 +3 530 1166 893 +3 531 1030 834 +3 531 1329 1030 +3 532 1104 778 +3 532 1328 1104 +3 532 1354 906 +3 533 1171 984 +3 533 1415 1171 +3 533 1418 873 +3 534 1010 735 +3 534 1194 1118 +3 534 1298 1010 +3 535 826 723 +3 535 1155 753 +3 535 1208 826 +3 536 1277 960 +3 536 1360 1055 +3 537 1145 981 +3 537 1366 902 +3 537 1382 1366 +3 538 1106 891 +3 538 1187 759 +3 538 1219 1187 +3 539 1233 1048 +3 539 1309 898 +3 540 1292 927 +3 540 1303 784 +3 541 1039 729 +3 541 1184 1039 +3 541 1263 1151 +3 542 968 766 +3 542 1226 968 +3 542 1306 1077 +3 543 1047 769 +3 543 1138 848 +3 543 1287 1138 +3 544 912 793 +3 544 1246 912 +3 544 1300 997 +3 545 1302 880 +3 545 1407 1236 +3 546 1242 800 +3 546 1279 841 +3 547 853 782 +3 547 1176 853 +3 547 1245 1176 +3 547 1363 928 +3 548 1225 807 +3 548 1269 1225 +3 549 1063 751 +3 549 1214 829 +3 549 1237 944 +3 550 1254 777 +3 550 1278 1254 +3 550 1321 1091 +3 550 1396 1278 +3 551 1058 719 +3 551 1095 776 +3 551 1264 787 +3 552 1257 970 +3 552 1414 842 +3 553 1209 763 +3 553 1272 1209 +3 553 1420 1137 +3 554 1427 839 +3 555 1280 1035 +3 555 1372 1056 +3 556 980 852 +3 556 1109 758 +3 556 1243 832 +3 556 1325 1109 +3 557 1442 856 +3 557 1453 843 +3 558 863 718 +3 558 1009 709 +3 558 1337 855 +3 559 1032 864 +3 559 1285 917 +3 560 952 797 +3 560 1296 952 +3 560 1374 846 +3 561 1241 1162 +3 561 1346 1241 +3 561 1389 1152 +3 562 1228 860 +3 562 1343 1154 +3 562 1451 854 +3 563 819 810 +3 563 883 754 +3 563 1323 883 +3 563 1409 819 +3 564 1172 838 +3 564 1422 1029 +3 565 1244 932 +3 565 1349 847 +3 565 1394 744 +3 566 961 806 +3 566 1411 873 +3 566 1416 1118 +3 567 821 820 +3 567 1192 795 +3 567 1234 899 +3 567 1378 821 +3 568 1097 774 +3 568 1175 778 +3 568 1413 1175 +3 569 1107 760 +3 569 1211 826 +3 569 1448 1088 +3 570 1089 729 +3 570 1290 943 +3 570 1373 1290 +3 571 1129 752 +3 571 1274 825 +3 571 1431 1129 +3 572 942 743 +3 572 973 804 +3 572 1289 773 +3 572 1395 942 +3 573 1251 862 +3 573 1252 765 +3 573 1379 910 +3 574 849 708 +3 574 859 849 +3 574 1034 809 +3 574 1067 718 +3 575 908 828 +3 575 1150 858 +3 575 1305 908 +3 576 904 711 +3 576 913 823 +3 576 1074 904 +3 576 1384 913 +3 577 868 735 +3 577 1261 868 +3 577 1311 1103 +3 578 840 827 +3 578 905 762 +3 578 1135 905 +3 578 1398 840 +3 579 935 799 +3 579 1144 935 +3 579 1340 909 +3 579 1424 1144 +3 580 804 792 +3 580 1199 924 +3 580 1289 804 +3 581 1082 813 +3 581 1322 816 +3 582 969 775 +3 582 1190 901 +3 582 1355 969 +3 582 1369 1190 +3 583 929 752 +3 583 1096 857 +3 583 1331 1096 +3 583 1408 733 +3 584 1000 914 +3 584 1156 818 +3 584 1314 918 +3 585 995 723 +3 585 1090 834 +3 585 1211 815 +3 586 1050 725 +3 586 1275 1262 +3 586 1366 831 +3 587 809 797 +3 587 859 809 +3 587 981 715 +3 588 1056 761 +3 588 1160 1015 +3 588 1317 1056 +3 588 1436 931 +3 589 890 875 +3 589 1001 890 +3 589 1391 962 +3 590 1163 813 +3 590 1345 1163 +3 590 1425 894 +3 591 974 811 +3 591 978 895 +3 591 1183 713 +3 591 1186 974 +3 592 993 851 +3 592 1120 806 +3 592 1157 1120 +3 593 967 835 +3 593 1028 866 +3 593 1301 967 +3 594 983 812 +3 594 1005 756 +3 594 1239 803 +3 595 1020 925 +3 595 1226 1020 +3 595 1288 936 +3 596 1134 872 +3 596 1197 915 +3 596 1295 822 +3 597 867 785 +3 597 1012 817 +3 597 1068 802 +3 597 1403 867 +3 598 999 830 +3 598 1059 892 +3 598 1333 756 +3 599 949 817 +3 599 1235 810 +3 600 972 753 +3 600 1008 793 +3 601 986 841 +3 601 1151 737 +3 601 1380 1151 +3 601 1432 1060 +3 602 881 857 +3 602 1058 776 +3 602 1096 1058 +3 602 1425 881 +3 603 1046 801 +3 603 1165 775 +3 603 1264 884 +3 604 1035 951 +3 604 1114 984 +3 604 1171 919 +3 604 1179 1035 +3 605 988 801 +3 605 1038 883 +3 605 1041 803 +3 605 1323 988 +3 606 1083 906 +3 606 1212 971 +3 606 1294 1083 +3 606 1354 1212 +3 607 985 835 +3 607 1123 959 +3 608 874 751 +3 608 1031 997 +3 608 1073 874 +3 608 1300 1073 +3 609 800 795 +3 609 1101 800 +3 609 1192 820 +3 609 1434 798 +3 610 1119 794 +3 610 1236 748 +3 610 1359 1119 +3 611 1040 886 +3 611 1298 1045 +3 611 1304 1040 +3 612 1051 992 +3 612 1177 1018 +3 612 1315 921 +3 613 1399 792 +3 613 1444 1072 +3 614 958 836 +3 614 1033 916 +3 614 1326 877 +3 615 964 839 +3 615 977 845 +3 615 1316 964 +3 615 1427 871 +3 616 1189 922 +3 616 1222 937 +3 616 1417 960 +3 617 1065 955 +3 617 1273 844 +3 617 1330 1013 +3 618 1037 861 +3 618 1405 1049 +3 618 1409 1037 +3 619 861 754 +3 619 1085 893 +3 619 1148 861 +3 619 1167 830 +3 620 1027 769 +3 620 1410 1016 +3 621 1036 926 +3 621 1042 1036 +3 621 1306 889 +3 622 1074 823 +3 622 1093 878 +3 622 1351 1074 +3 623 1081 923 +3 623 1334 1002 +3 624 977 871 +3 624 1182 977 +3 624 1302 1182 +3 624 1388 880 +3 625 934 843 +3 625 1084 840 +3 625 1398 934 +3 625 1439 1084 +3 625 1453 790 +3 626 1080 1030 +3 626 1170 1080 +3 626 1329 789 +3 626 1435 900 +3 627 958 877 +3 627 1178 945 +3 627 1332 958 +3 628 1052 927 +3 628 1105 946 +3 628 1292 750 +3 629 1248 848 +3 629 1259 914 +3 630 1156 1131 +3 630 1324 1019 +3 630 1357 1324 +3 631 950 930 +3 631 1047 848 +3 631 1111 938 +3 631 1387 950 +3 632 1164 966 +3 632 1367 1150 +3 633 1054 976 +3 633 1055 1054 +3 633 1174 898 +3 633 1277 1055 +3 634 1009 855 +3 634 1079 791 +3 634 1153 1079 +3 635 928 882 +3 635 1185 814 +3 635 1196 1185 +3 635 1245 928 +3 636 990 771 +3 636 1263 990 +3 636 1421 1180 +3 637 1135 827 +3 637 1143 866 +3 637 1454 1135 +3 638 1063 829 +3 638 1087 1011 +3 638 1122 1022 +3 639 1218 734 +3 639 1274 987 +3 640 1161 807 +3 640 1225 781 +3 640 1231 811 +3 641 1057 759 +3 641 1186 895 +3 641 1187 779 +3 641 1308 1057 +3 642 1168 821 +3 642 1378 899 +3 642 1428 875 +3 643 1166 836 +3 643 1191 893 +3 643 1314 1191 +3 644 963 741 +3 644 1128 1048 +3 644 1233 939 +3 644 1400 1128 +3 645 1106 759 +3 645 1115 1106 +3 645 1139 885 +3 645 1320 1139 +3 646 1023 772 +3 646 1195 1023 +3 646 1205 753 +3 647 955 851 +3 647 1064 955 +3 647 1198 1113 +3 647 1210 1064 +3 648 1075 850 +3 648 1162 808 +3 648 1312 1053 +3 649 1102 889 +3 649 1149 979 +3 649 1200 1021 +3 649 1306 1149 +3 650 954 872 +3 650 1025 954 +3 650 1202 989 +3 650 1251 1025 +3 651 1237 874 +3 651 1358 1054 +3 651 1360 944 +3 652 1283 818 +3 652 1285 870 +3 652 1447 917 +3 653 1108 920 +3 653 1260 864 +3 654 1278 975 +3 654 1404 1278 +3 655 1032 917 +3 655 1066 1032 +3 655 1381 992 +3 656 966 765 +3 656 1216 966 +3 656 1252 910 +3 657 1128 853 +3 657 1176 747 +3 657 1309 1048 +3 658 891 777 +3 658 1219 891 +3 658 1249 779 +3 658 1254 1249 +3 659 1209 786 +3 659 1222 763 +3 659 1240 937 +3 660 1061 855 +3 660 1241 1061 +3 660 1429 1241 +3 661 972 912 +3 661 1208 972 +3 661 1246 1071 +3 661 1383 1208 +3 662 1052 946 +3 662 1307 1052 +3 663 896 828 +3 663 1173 915 +3 663 1197 896 +3 664 950 870 +3 664 1193 947 +3 664 1310 930 +3 665 968 936 +3 665 1286 766 +3 665 1313 887 +3 665 1339 1286 +3 666 982 939 +3 666 1008 982 +3 666 1233 976 +3 667 1092 1024 +3 667 1215 1109 +3 667 1325 1092 +3 668 1177 784 +3 668 1281 1018 +3 668 1303 927 +3 669 1107 1088 +3 669 1194 868 +3 669 1265 1194 +3 670 1217 834 +3 670 1371 824 +3 671 1006 997 +3 671 1031 919 +3 671 1415 1006 +3 672 1136 789 +3 672 1207 1144 +3 672 1329 1207 +3 672 1424 1094 +3 673 1238 782 +3 673 1247 975 +3 673 1396 1091 +3 674 1100 847 +3 674 1322 1100 +3 674 1349 1117 +3 674 1426 1322 +3 675 1065 844 +3 675 1270 913 +3 675 1384 957 +3 676 1328 906 +3 676 1342 800 +3 677 1267 852 +3 677 1315 1267 +3 678 1238 1091 +3 678 1297 796 +3 678 1321 1297 +3 679 1126 998 +3 679 1340 799 +3 679 1456 1126 +3 680 1355 1221 +3 680 1375 969 +3 680 1386 812 +3 681 981 952 +3 681 1296 1229 +3 681 1382 981 +3 682 1257 842 +3 682 1348 860 +3 683 1115 880 +3 683 1255 891 +3 683 1388 1255 +3 684 970 846 +3 684 1335 970 +3 684 1374 1319 +3 685 961 873 +3 685 993 961 +3 685 1114 993 +3 685 1418 984 +3 686 1076 878 +3 686 1224 908 +3 686 1406 1076 +3 687 1126 910 +3 687 1266 998 +3 687 1379 1266 +3 688 1098 1062 +3 688 1214 944 +3 688 1360 1098 +3 688 1377 956 +3 689 1201 730 +3 689 1244 847 +3 689 1293 932 +3 690 1246 1006 +3 690 1291 1071 +3 690 1415 1230 +3 691 1122 1011 +3 691 1282 1122 +3 691 1347 911 +3 692 1215 1024 +3 692 1385 1078 +3 693 1188 1142 +3 693 1253 1175 +3 693 1413 1188 +3 694 1301 933 +3 694 1318 1036 +3 695 1299 1103 +3 695 1365 1299 +3 695 1443 1365 +3 696 1272 1137 +3 696 1389 1004 +3 697 1002 931 +3 697 1026 1002 +3 697 1344 1026 +3 697 1436 1015 +3 698 1152 1137 +3 698 1346 1152 +3 698 1420 882 +3 699 1351 1304 +3 699 1370 904 +3 700 948 497 +3 700 1090 948 +3 700 1207 1090 +3 701 943 527 +3 701 1089 943 +3 701 1132 1089 +3 702 1294 971 +3 702 1362 991 +3 702 1445 856 +3 703 1189 960 +3 703 1277 898 +3 704 1108 943 +3 704 1290 1276 +3 704 1338 920 +3 705 1334 994 +3 705 1412 1013 +3 706 985 959 +3 706 1001 962 +3 706 1401 1001 +3 707 1184 1017 +3 707 1373 1039 +3 707 1457 869 +3 708 1067 574 +3 708 1455 1067 +3 709 839 483 +3 709 863 558 +3 709 1181 839 +3 710 1027 1016 +3 710 1287 1027 +3 710 1405 1284 +3 711 904 498 +3 711 957 576 +3 711 1157 957 +3 712 1327 1053 +3 712 1341 838 +3 713 978 591 +3 713 1170 900 +3 713 1183 1170 +3 713 1368 978 +3 714 1280 1056 +3 714 1441 951 +3 715 859 587 +3 715 1145 816 +3 715 1213 859 +3 716 999 892 +3 716 1033 999 +3 716 1402 916 +3 717 1040 525 +3 717 1169 886 +3 717 1367 1169 +3 718 879 558 +3 718 1034 574 +3 718 1067 512 +3 719 884 551 +3 719 1331 884 +3 720 1153 494 +3 720 1363 1079 +3 721 1431 1069 +3 722 1199 940 +3 722 1271 1199 +3 722 1353 802 +3 723 1155 535 +3 723 1195 1155 +3 723 1211 585 +3 724 843 509 +3 724 1234 897 +3 724 1442 843 +3 725 941 586 +3 725 1050 495 +3 725 1343 941 +3 726 1336 842 +3 726 1359 1258 +3 726 1414 1359 +3 727 1298 1118 +3 727 1392 1045 +3 727 1416 1392 +3 728 1417 965 +3 728 1452 1062 +3 729 990 541 +3 729 1039 570 +3 729 1361 990 +3 730 907 188 +3 730 1116 689 +3 730 1201 942 +3 730 1395 907 +3 731 1411 1118 +3 731 1433 1411 +3 732 1242 841 +3 732 1328 1242 +3 732 1440 1104 +3 733 929 583 +3 733 1275 929 +3 733 1408 1262 +3 734 1124 639 +3 734 1218 854 +3 734 1256 1124 +3 734 1451 1256 +3 735 868 534 +3 735 886 488 +3 735 1010 886 +3 735 1141 577 +3 736 1184 1151 +3 736 1449 1017 +3 737 986 601 +3 737 1180 986 +3 737 1263 1180 +3 738 1154 495 +3 738 1228 1154 +3 738 1257 1228 +3 739 1394 1133 +3 739 1437 838 +3 740 1082 902 +3 740 1262 484 +3 740 1366 1262 +3 741 1220 1204 +3 741 1268 1220 +3 741 1400 644 +3 742 1077 926 +3 742 1226 1077 +3 742 1423 1020 +3 743 942 515 +3 743 973 572 +3 743 1345 973 +3 744 1172 1029 +3 744 1349 565 +3 744 1394 1172 +3 744 1397 1117 +3 745 1216 1130 +3 745 1311 1141 +3 745 1443 1311 +3 746 1279 1159 +3 746 1432 841 +3 747 814 504 +3 747 1158 898 +3 747 1176 814 +3 747 1309 657 +3 748 1043 610 +3 748 1407 885 +3 748 1430 1043 +3 749 1210 1113 +3 749 1317 931 +3 749 1441 1317 +3 750 945 131 +3 750 1086 945 +3 750 1105 628 +3 750 1292 1086 +3 751 1022 506 +3 751 1031 608 +3 751 1063 1022 +3 751 1237 549 +3 752 903 583 +3 752 929 513 +3 752 987 571 +3 752 1129 903 +3 753 972 535 +3 753 982 600 +3 753 1155 646 +3 753 1205 982 +3 754 883 507 +3 754 1037 563 +3 754 1167 619 +3 755 1235 1044 +3 755 1444 485 +3 756 888 594 +3 756 1059 598 +3 756 1333 888 +3 756 1350 1059 +3 757 1259 1138 +3 757 1284 1140 +3 757 1287 1284 +3 758 980 556 +3 758 1109 520 +3 758 1393 980 +3 759 1057 104 +3 759 1106 538 +3 759 1187 641 +3 759 1320 645 +3 760 815 569 +3 760 1103 497 +3 760 1261 1103 +3 761 911 164 +3 761 1160 588 +3 761 1372 911 +3 762 875 509 +3 762 934 578 +3 762 1391 875 +3 763 922 504 +3 763 1196 553 +3 763 1209 659 +3 763 1222 922 +3 764 1142 142 +3 764 1253 1142 +3 764 1354 1253 +3 765 1025 573 +3 765 1164 1025 +3 765 1252 656 +3 766 968 665 +3 766 1149 542 +3 766 1286 228 +3 767 1383 1088 +3 767 1448 1208 +3 768 1282 1035 +3 768 1446 1122 +3 769 938 198 +3 769 1027 543 +3 769 1047 938 +3 769 1127 620 +3 770 1021 225 +3 770 1102 1021 +3 770 1123 1070 +3 771 1203 636 +3 771 1393 520 +3 772 963 516 +3 772 1205 646 +3 772 1268 963 +3 772 1269 1268 +3 773 907 572 +3 773 924 190 +3 773 1289 924 +3 774 1078 568 +3 774 1203 1078 +3 774 1421 1203 +3 775 1046 603 +3 775 1165 503 +3 775 1223 582 +3 776 1014 501 +3 776 1058 551 +3 776 1095 1014 +3 776 1425 602 +3 777 1254 658 +3 777 1321 550 +3 778 1097 568 +3 778 1104 499 +3 778 1175 532 +3 779 1186 641 +3 779 1219 658 +3 779 1249 502 +3 780 1319 1119 +3 780 1335 1319 +3 780 1414 1335 +3 781 824 640 +3 781 1269 1023 +3 781 1419 824 +3 782 1238 522 +3 782 1247 673 +3 782 1363 547 +3 783 1230 873 +3 783 1291 1230 +3 783 1433 1291 +3 784 833 540 +3 784 1303 668 +3 784 1357 833 +3 785 1068 597 +3 785 1376 195 +3 785 1410 1376 +3 786 1146 176 +3 786 1240 659 +3 786 1272 1146 +3 787 953 485 +3 787 1095 551 +3 787 1264 953 +3 787 1444 1095 +3 788 807 502 +3 788 1404 807 +3 789 1125 626 +3 789 1136 97 +3 789 1329 672 +3 790 991 146 +3 790 1439 625 +3 790 1445 991 +3 790 1453 1445 +3 791 1009 634 +3 791 1079 522 +3 791 1181 1009 +3 791 1356 1181 +3 792 804 501 +3 792 940 580 +3 792 1014 613 +3 792 1399 940 +3 793 912 600 +3 793 1008 490 +3 793 1300 544 +3 794 1119 505 +3 794 1236 610 +3 794 1302 1236 +3 795 800 500 +3 795 1192 609 +3 795 1234 567 +3 796 1007 678 +3 796 1297 492 +3 796 1356 1007 +3 796 1390 1356 +3 797 809 483 +3 797 952 587 +3 797 1316 560 +3 798 1101 609 +3 798 1279 1101 +3 798 1434 214 +3 799 1340 579 +3 799 1456 679 +3 800 1101 546 +3 800 1242 676 +3 800 1342 500 +3 801 953 603 +3 801 988 485 +3 801 1041 605 +3 801 1046 1041 +3 802 1012 597 +3 802 1227 722 +3 802 1353 1012 +3 802 1438 1227 +3 803 983 594 +3 803 1038 605 +3 803 1041 521 +3 803 1239 1038 +3 804 973 501 +3 804 1289 572 +3 805 1223 503 +3 805 1369 1223 +3 805 1431 1369 +3 806 961 592 +3 806 1120 498 +3 806 1416 566 +3 807 1161 502 +3 807 1220 548 +3 807 1225 640 +3 807 1404 1220 +3 808 1112 648 +3 808 1429 512 +3 809 859 574 +3 809 1034 483 +3 810 819 599 +3 810 1235 485 +3 810 1323 563 +3 811 1161 640 +3 811 1183 591 +3 811 1231 529 +3 812 1005 594 +3 812 1375 680 +3 812 1386 122 +3 813 876 581 +3 813 881 590 +3 813 1082 484 +3 813 1163 876 +3 814 1185 504 +3 814 1245 635 +3 815 948 585 +3 815 1211 569 +3 816 902 581 +3 816 1145 902 +3 816 1213 715 +3 816 1426 496 +3 817 1012 526 +3 817 1044 599 +3 817 1403 597 +3 818 1000 584 +3 818 1019 652 +3 818 1156 1019 +3 818 1283 517 +3 819 949 599 +3 819 1049 508 +3 819 1409 1049 +3 820 821 217 +3 820 1110 609 +3 820 1192 567 +3 821 1168 218 +3 821 1378 642 +3 822 1134 596 +3 822 1295 85 +3 823 913 76 +3 823 1074 576 +3 823 1093 622 +3 824 1217 670 +3 824 1231 640 +3 824 1371 1231 +3 824 1419 1217 +3 825 1069 571 +3 825 1232 116 +3 825 1274 1232 +3 826 1211 723 +3 826 1448 569 +3 827 840 149 +3 827 1135 578 +3 827 1143 637 +3 828 896 575 +3 828 908 81 +3 828 1173 663 +3 829 1063 549 +3 829 1087 638 +3 829 1214 956 +3 829 1352 1087 +3 830 1085 619 +3 830 1167 507 +3 830 1333 598 +3 831 1050 586 +3 831 1229 1050 +3 831 1382 1229 +3 832 1121 135 +3 832 1243 1121 +3 832 1325 556 +3 833 1086 540 +3 833 1131 510 +3 833 1332 1086 +3 833 1357 1131 +3 834 995 585 +3 834 1030 670 +3 834 1090 531 +3 834 1217 995 +3 835 985 511 +3 835 1028 593 +3 835 1070 607 +3 836 918 643 +3 836 958 510 +3 836 1033 614 +3 836 1166 1033 +3 837 1312 1112 +3 837 1341 1312 +3 837 1422 1341 +3 837 1455 1422 +3 838 1172 739 +3 838 1327 712 +3 838 1341 564 +3 838 1437 183 +3 839 964 483 +3 839 1181 554 +3 839 1427 615 +3 840 1084 148 +3 840 1398 625 +3 841 1242 546 +3 841 1279 746 +3 841 1432 601 +3 841 1440 732 +3 842 1206 682 +3 842 1257 552 +3 842 1336 111 +3 842 1414 726 +3 843 934 509 +3 843 1442 557 +3 843 1453 625 +3 844 1065 617 +3 844 1270 675 +3 844 1273 73 +3 845 977 505 +3 845 1316 615 +3 845 1374 1316 +3 846 970 495 +3 846 1296 560 +3 846 1374 684 +3 847 1100 515 +3 847 1201 689 +3 847 1244 565 +3 847 1349 674 +3 848 1047 543 +3 848 1138 629 +3 848 1387 631 +3 849 1029 708 +3 849 1213 496 +3 849 1397 1029 +3 850 1075 179 +3 850 1162 648 +3 850 1389 1162 +3 851 955 523 +3 851 1157 592 +3 851 1198 647 +3 852 980 677 +3 852 1243 556 +3 852 1267 519 +3 852 1307 1243 +3 853 1128 482 +3 853 1176 657 +3 853 1247 782 +3 854 1218 513 +3 854 1343 562 +3 854 1451 734 +3 855 1009 558 +3 855 1061 494 +3 855 1153 634 +3 855 1337 660 +3 856 897 500 +3 856 1294 702 +3 856 1442 897 +3 856 1445 557 +3 857 881 484 +3 857 1096 602 +3 857 1408 583 +3 858 1305 575 +3 858 1367 717 +3 858 1406 1305 +3 859 1213 849 +3 860 1228 682 +3 860 1348 113 +3 860 1451 562 +3 861 1037 754 +3 861 1140 618 +3 861 1148 486 +3 862 989 90 +3 862 1251 989 +3 862 1379 573 +3 863 1034 718 +3 864 1032 653 +3 864 1193 559 +3 864 1260 204 +3 865 1250 139 +3 865 1385 1250 +3 865 1413 1385 +3 866 933 593 +3 866 1028 637 +3 866 1143 151 +3 867 1403 508 +3 867 1410 785 +3 868 1107 669 +3 868 1194 534 +3 868 1261 1107 +3 869 1373 707 +3 869 1457 208 +3 870 950 517 +3 870 1193 664 +3 870 1283 652 +3 870 1285 1193 +3 871 977 615 +3 871 1003 624 +3 871 1390 1003 +3 871 1427 1390 +3 872 954 596 +3 872 1134 88 +3 872 1202 650 +3 873 961 566 +3 873 1230 533 +3 873 1411 783 +3 873 1418 685 +3 874 1237 751 +3 874 1358 651 +3 875 890 642 +3 875 1391 589 +3 875 1428 509 +3 876 1100 581 +3 876 1163 515 +3 877 958 614 +3 877 1178 627 +3 877 1326 129 +3 878 1076 622 +3 878 1093 78 +3 878 1224 686 +3 879 1337 558 +3 879 1429 1337 +3 880 1115 545 +3 880 1302 624 +3 880 1388 683 +3 881 1425 590 +3 882 928 494 +3 882 1061 698 +3 882 1196 635 +3 882 1420 1196 +3 883 1038 507 +3 883 1323 605 +3 884 1165 603 +3 884 1264 551 +3 884 1331 503 +3 885 1115 645 +3 885 1139 106 +3 885 1407 1115 +3 885 1430 748 +3 886 1010 611 +3 886 1040 717 +3 886 1169 488 +3 887 1313 63 +3 887 1339 665 +3 888 1239 594 +3 888 1333 507 +3 889 1042 621 +3 889 1102 518 +3 889 1306 649 +3 890 1001 220 +3 890 1168 642 +3 891 1106 683 +3 891 1219 538 +3 891 1255 777 +3 892 999 598 +3 892 1059 125 +3 892 1402 716 +3 893 1085 530 +3 893 1148 619 +3 893 1166 643 +3 893 1191 1148 +3 894 1345 590 +3 894 1425 776 +3 895 1186 591 +3 895 1308 641 +3 895 1450 102 +3 896 1150 575 +3 896 1164 1150 +3 896 1197 514 +3 897 1234 795 +3 897 1442 724 +3 898 1158 703 +3 898 1174 539 +3 898 1277 633 +3 898 1309 747 +3 899 1234 724 +3 899 1378 567 +3 899 1428 642 +3 900 1170 626 +3 900 1368 713 +3 900 1435 99 +3 901 1190 119 +3 901 1355 582 +3 902 1082 581 +3 902 1145 537 +3 902 1366 740 +3 903 1129 503 +3 903 1331 583 +3 904 1074 699 +3 904 1370 498 +3 905 1391 762 +3 905 1454 511 +3 906 1328 532 +3 906 1342 676 +3 906 1354 606 +3 907 1395 572 +3 908 1224 80 +3 908 1305 686 +3 909 1147 94 +3 909 1340 1147 +3 909 1424 579 +3 910 1126 528 +3 910 1130 656 +3 910 1252 573 +3 910 1379 687 +3 911 1282 691 +3 911 1347 165 +3 911 1372 1282 +3 912 972 600 +3 912 1246 661 +3 913 1270 75 +3 913 1384 675 +3 914 1000 629 +3 914 1259 486 +3 914 1314 584 +3 915 1173 83 +3 915 1197 663 +3 915 1295 596 +3 916 1033 716 +3 916 1326 614 +3 916 1402 127 +3 917 1032 559 +3 917 1285 652 +3 917 1381 655 +3 917 1447 1381 +3 918 1156 584 +3 918 1314 643 +3 919 1031 506 +3 919 1171 671 +3 919 1179 604 +3 920 1108 704 +3 920 1260 653 +3 920 1338 205 +3 921 1051 612 +3 921 1132 701 +3 921 1315 1132 +3 922 1189 504 +3 922 1222 616 +3 923 994 623 +3 923 1099 70 +3 924 1271 191 +3 924 1289 580 +3 925 1020 158 +3 925 1288 595 +3 926 1036 155 +3 926 1077 621 +3 926 1423 742 +3 927 1281 668 +3 927 1292 628 +3 927 1303 540 +3 928 1245 547 +3 928 1363 720 +3 929 1275 513 +3 930 950 664 +3 930 1111 631 +3 930 1310 201 +3 931 1002 524 +3 931 1210 749 +3 931 1317 588 +3 931 1436 697 +3 932 1133 565 +3 932 1244 689 +3 932 1293 185 +3 933 1301 593 +3 933 1318 694 +3 934 1398 578 +3 935 1144 700 +3 935 1299 799 +3 936 968 595 +3 936 1288 64 +3 936 1313 665 +3 937 965 616 +3 937 1222 659 +3 937 1240 174 +3 938 1047 631 +3 938 1111 199 +3 939 963 644 +3 939 982 516 +3 939 1233 666 +3 940 1199 580 +3 940 1353 722 +3 940 1399 526 +3 941 1275 586 +3 941 1343 854 +3 942 1201 515 +3 942 1395 730 +3 943 1089 570 +3 943 1108 527 +3 943 1290 704 +3 944 1214 549 +3 944 1237 651 +3 944 1360 688 +3 945 1086 627 +3 945 1178 130 +3 946 1052 628 +3 946 1105 133 +3 946 1121 662 +3 947 1193 864 +3 947 1310 664 +3 948 1090 585 +3 949 1403 817 +3 950 1387 517 +3 951 1114 604 +3 951 1280 714 +3 951 1441 487 +3 952 981 587 +3 952 1296 681 +3 953 1264 603 +3 954 1025 514 +3 954 1197 596 +3 955 1064 617 +3 955 1065 523 +3 956 1214 688 +3 956 1352 829 +3 956 1377 169 +3 957 1065 675 +3 957 1157 523 +3 957 1384 576 +3 958 1332 510 +3 959 985 607 +3 959 1123 223 +3 959 1401 706 +3 960 1098 536 +3 960 1189 616 +3 960 1277 703 +3 960 1417 1098 +3 961 993 592 +3 962 985 706 +3 962 1001 589 +3 962 1391 905 +3 963 1268 741 +3 964 1316 797 +3 965 1417 616 +3 965 1452 728 +3 966 1164 765 +3 966 1169 632 +3 966 1216 488 +3 967 1070 835 +3 967 1301 518 +3 968 1226 595 +3 969 1046 775 +3 969 1355 680 +3 969 1375 521 +3 970 1257 738 +3 970 1335 552 +3 971 1212 143 +3 971 1294 606 +3 971 1362 702 +3 972 1208 535 +3 973 1345 501 +3 974 1161 811 +3 974 1186 779 +3 975 1204 654 +3 975 1247 482 +3 975 1396 673 +3 976 1008 666 +3 976 1054 490 +3 976 1174 633 +3 976 1233 1174 +3 977 1182 505 +3 978 1368 100 +3 978 1450 895 +3 979 1149 766 +3 979 1200 649 +3 980 1132 677 +3 980 1393 493 +3 981 1145 715 +3 981 1382 537 +3 982 1008 600 +3 982 1205 516 +3 983 1375 812 +3 984 1114 685 +3 984 1171 604 +3 984 1418 533 +3 986 1180 499 +3 986 1440 841 +3 987 1218 639 +3 987 1274 571 +3 988 1323 810 +3 989 1202 89 +3 989 1251 650 +3 990 1263 541 +3 990 1361 771 +3 991 1362 145 +3 991 1445 702 +3 992 1051 655 +3 992 1177 612 +3 992 1381 489 +3 993 1114 487 +3 993 1198 851 +3 994 1334 623 +3 994 1412 705 +3 995 1195 723 +3 995 1217 491 +3 996 1339 887 +3 997 1006 544 +3 997 1031 671 +3 997 1300 608 +3 998 1126 687 +3 998 1147 679 +3 998 1266 92 +3 999 1033 530 +3 999 1085 830 +3 1000 1248 629 +3 1001 1401 221 +3 1002 1026 623 +3 1002 1334 524 +3 1003 1388 624 +3 1003 1390 796 +3 1004 1146 696 +3 1004 1389 850 +3 1005 1350 756 +3 1006 1246 544 +3 1006 1415 690 +3 1007 1238 678 +3 1007 1356 791 +3 1009 1181 709 +3 1010 1298 611 +3 1011 1087 167 +3 1011 1122 638 +3 1011 1347 691 +3 1012 1353 526 +3 1013 1273 617 +3 1013 1330 705 +3 1013 1412 72 +3 1014 1095 613 +3 1015 1160 162 +3 1015 1344 697 +3 1015 1436 588 +3 1016 1027 620 +3 1016 1405 710 +3 1016 1410 867 +3 1017 1184 736 +3 1017 1449 210 +3 1017 1457 707 +3 1018 1177 668 +3 1018 1267 612 +3 1018 1281 519 +3 1019 1156 630 +3 1019 1324 489 +3 1019 1447 652 +3 1020 1226 742 +3 1020 1423 157 +3 1021 1102 649 +3 1021 1200 226 +3 1022 1063 638 +3 1022 1446 506 +3 1023 1195 491 +3 1023 1269 772 +3 1023 1419 781 +3 1024 1092 137 +3 1024 1215 667 +3 1024 1250 692 +3 1025 1164 514 +3 1025 1251 573 +3 1026 1081 623 +3 1026 1344 161 +3 1027 1287 543 +3 1028 1454 637 +3 1029 1172 564 +3 1029 1397 744 +3 1029 1422 708 +3 1030 1080 670 +3 1030 1329 626 +3 1032 1066 653 +3 1033 1166 530 +3 1035 1179 768 +3 1035 1280 951 +3 1035 1282 555 +3 1036 1042 694 +3 1036 1318 154 +3 1037 1409 563 +3 1038 1239 507 +3 1039 1184 707 +3 1039 1373 570 +3 1040 1304 525 +3 1041 1046 521 +3 1042 1301 694 +3 1043 1258 610 +3 1043 1430 108 +3 1044 1072 755 +3 1044 1235 599 +3 1045 1298 727 +3 1045 1304 611 +3 1045 1370 1304 +3 1045 1392 498 +3 1048 1128 657 +3 1048 1233 644 +3 1048 1309 539 +3 1049 1405 508 +3 1049 1409 618 +3 1050 1229 495 +3 1051 1066 655 +3 1052 1281 927 +3 1052 1307 519 +3 1053 1075 648 +3 1053 1312 712 +3 1053 1327 181 +3 1054 1055 651 +3 1054 1358 490 +3 1055 1277 536 +3 1055 1360 651 +3 1056 1280 555 +3 1056 1317 714 +3 1056 1372 761 +3 1057 1308 103 +3 1058 1096 719 +3 1059 1350 124 +3 1060 1364 212 +3 1060 1380 601 +3 1060 1432 1364 +3 1060 1449 1380 +3 1061 1346 698 +3 1062 1098 728 +3 1062 1377 688 +3 1062 1452 171 +3 1064 1210 524 +3 1064 1330 617 +3 1066 1108 653 +3 1067 1455 512 +3 1068 1438 802 +3 1069 1190 721 +3 1069 1431 571 +3 1070 1102 770 +3 1070 1123 607 +3 1071 1246 690 +3 1071 1291 481 +3 1071 1383 661 +3 1072 1399 613 +3 1072 1444 755 +3 1073 1300 793 +3 1073 1358 874 +3 1074 1351 699 +3 1076 1351 622 +3 1076 1406 525 +3 1077 1226 542 +3 1077 1306 621 +3 1078 1203 520 +3 1078 1215 692 +3 1078 1385 568 +3 1079 1153 720 +3 1079 1363 782 +3 1080 1170 529 +3 1080 1371 670 +3 1081 1099 923 +3 1083 1294 856 +3 1083 1342 906 +3 1084 1439 147 +3 1086 1292 540 +3 1086 1332 627 +3 1087 1352 168 +3 1088 1107 569 +3 1088 1265 669 +3 1088 1383 481 +3 1088 1448 767 +3 1089 1132 493 +3 1089 1361 729 +3 1090 1207 531 +3 1091 1238 673 +3 1091 1321 678 +3 1091 1396 550 +3 1092 1325 832 +3 1094 1136 672 +3 1094 1424 909 +3 1095 1444 613 +3 1096 1331 719 +3 1097 1421 774 +3 1098 1360 536 +3 1098 1417 728 +3 1100 1322 581 +3 1101 1279 546 +3 1103 1261 577 +3 1103 1299 497 +3 1103 1311 695 +3 1104 1328 732 +3 1104 1440 499 +3 1106 1115 683 +3 1107 1261 760 +3 1109 1215 520 +3 1109 1325 667 +3 1110 1434 609 +3 1112 1312 648 +3 1112 1455 837 +3 1113 1198 487 +3 1113 1210 647 +3 1113 1441 749 +3 1115 1407 545 +3 1116 1293 689 +3 1117 1349 744 +3 1117 1397 496 +3 1117 1426 674 +3 1118 1194 731 +3 1118 1298 534 +3 1118 1411 566 +3 1118 1416 727 +3 1119 1319 505 +3 1119 1359 780 +3 1120 1157 711 +3 1121 1243 662 +3 1122 1282 768 +3 1122 1446 1022 +3 1124 1232 639 +3 1124 1256 114 +3 1125 1435 626 +3 1126 1456 528 +3 1127 1376 620 +3 1128 1400 482 +3 1129 1431 805 +3 1130 1216 656 +3 1130 1443 745 +3 1131 1156 918 +3 1131 1357 630 +3 1132 1315 677 +3 1133 1394 565 +3 1133 1437 739 +3 1135 1454 905 +3 1137 1152 696 +3 1137 1272 553 +3 1137 1420 698 +3 1138 1259 629 +3 1138 1287 757 +3 1139 1320 105 +3 1140 1259 757 +3 1140 1284 618 +3 1141 1216 745 +3 1141 1311 577 +3 1142 1188 141 +3 1142 1253 693 +3 1144 1207 700 +3 1144 1424 672 +3 1146 1272 696 +3 1147 1340 679 +3 1148 1191 486 +3 1149 1306 542 +3 1150 1164 632 +3 1150 1367 858 +3 1151 1184 541 +3 1151 1263 737 +3 1151 1380 736 +3 1152 1346 561 +3 1152 1389 696 +3 1154 1228 562 +3 1154 1343 725 +3 1155 1195 646 +3 1158 1189 703 +3 1159 1279 798 +3 1159 1364 746 +3 1162 1241 808 +3 1162 1389 561 +3 1163 1345 743 +3 1169 1367 632 +3 1170 1183 529 +3 1171 1415 671 +3 1172 1394 739 +3 1174 1233 539 +3 1175 1253 532 +3 1175 1413 693 +3 1176 1245 814 +3 1177 1324 784 +3 1179 1446 768 +3 1180 1263 636 +3 1180 1421 1097 +3 1181 1356 554 +3 1182 1302 794 +3 1185 1196 763 +3 1187 1219 779 +3 1188 1413 865 +3 1190 1369 721 +3 1191 1314 914 +3 1193 1285 559 +3 1194 1265 731 +3 1196 1420 553 +3 1199 1271 924 +3 1203 1421 636 +3 1204 1220 654 +3 1204 1400 741 +3 1206 1348 682 +3 1207 1329 531 +3 1208 1383 767 +3 1208 1448 826 +3 1209 1272 786 +3 1212 1354 764 +3 1217 1419 491 +3 1220 1268 548 +3 1220 1404 654 +3 1221 1355 901 +3 1221 1386 680 +3 1223 1369 582 +3 1225 1269 781 +3 1227 1271 722 +3 1227 1438 193 +3 1228 1257 682 +3 1229 1296 495 +3 1229 1382 681 +3 1230 1291 690 +3 1230 1415 533 +3 1231 1371 529 +3 1232 1274 639 +3 1236 1302 545 +3 1236 1407 748 +3 1241 1346 1061 +3 1241 1429 808 +3 1242 1328 676 +3 1243 1307 662 +3 1248 1387 848 +3 1249 1254 788 +3 1250 1385 692 +3 1253 1354 532 +3 1254 1278 788 +3 1255 1297 777 +3 1255 1388 492 +3 1256 1451 860 +3 1258 1336 726 +3 1258 1359 610 +3 1262 1275 733 +3 1262 1366 586 +3 1262 1408 484 +3 1265 1433 731 +3 1266 1379 862 +3 1267 1315 612 +3 1268 1269 548 +3 1276 1290 869 +3 1276 1338 704 +3 1278 1396 975 +3 1278 1404 788 +3 1282 1372 555 +3 1284 1287 710 +3 1284 1405 618 +3 1286 1339 229 +3 1290 1373 869 +3 1291 1433 481 +3 1297 1321 777 +3 1299 1365 799 +3 1304 1351 525 +3 1304 1370 699 +3 1305 1406 686 +3 1311 1443 695 +3 1312 1341 712 +3 1316 1374 560 +3 1317 1441 714 +3 1319 1335 684 +3 1319 1374 845 +3 1322 1426 816 +3 1324 1357 784 +3 1330 1334 705 +3 1335 1414 552 +3 1337 1429 660 +3 1341 1422 564 +3 1356 1390 554 +3 1359 1414 780 +3 1361 1393 771 +3 1364 1432 746 +3 1365 1443 528 +3 1365 1456 799 +3 1366 1382 831 +3 1369 1431 721 +3 1376 1410 620 +3 1380 1449 736 +3 1381 1447 489 +3 1385 1413 568 +3 1390 1427 554 +3 1392 1416 806 +3 1411 1433 783 +3 1422 1455 708 +3 1445 1453 557 +3 1458 1995 1916 +3 1458 2171 1943 +3 1458 2246 1995 +3 1459 2282 1955 +3 1459 2342 2077 +3 1460 2367 1803 +3 1461 1855 1835 +3 1461 2055 1792 +3 1461 2412 2055 +3 1462 1961 1769 +3 1462 2225 1791 +3 1462 2421 2225 +3 1463 2143 1861 +3 1463 2160 1738 +3 1463 2266 1885 +3 1464 2004 1688 +3 1464 2204 1904 +3 1464 2206 2004 +3 1465 2307 1997 +3 1465 2361 1970 +3 1465 2410 2361 +3 1466 1888 1736 +3 1466 1903 1888 +3 1466 2022 1903 +3 1466 2083 2022 +3 1467 2034 1730 +3 1467 2125 2034 +3 1467 2148 1782 +3 1468 2086 1820 +3 1468 2296 2086 +3 1469 2054 1806 +3 1469 2251 1765 +3 1469 2366 2054 +3 1470 2116 2056 +3 1470 2389 1957 +3 1471 2336 2030 +3 1471 2343 1796 +3 1472 1931 1828 +3 1472 2173 2066 +3 1472 2214 1931 +3 1473 2080 1823 +3 1473 2094 2074 +3 1473 2369 1718 +3 1474 1804 1723 +3 1474 1935 1804 +3 1474 1984 1685 +3 1474 2399 1984 +3 1475 2156 1974 +3 1475 2388 2070 +3 1475 2394 2156 +3 1476 1778 1775 +3 1476 1870 1822 +3 1476 2309 1778 +3 1477 1784 1772 +3 1477 1954 1784 +3 1477 1993 1758 +3 1477 2323 1954 +3 1478 2232 1745 +3 1478 2263 2232 +3 1478 2413 2263 +3 1479 2117 1871 +3 1479 2150 1757 +3 1479 2200 1786 +3 1479 2295 1860 +3 1480 1929 1724 +3 1480 1979 1712 +3 1480 2194 1814 +3 1480 2419 1979 +3 1481 1826 1694 +3 1481 2184 1706 +3 1481 2327 1832 +3 1481 2417 1826 +3 1482 1795 1728 +3 1482 1896 1743 +3 1482 2165 1896 +3 1482 2210 1795 +3 1483 2000 1776 +3 1483 2050 1780 +3 1483 2317 2050 +3 1484 1991 1859 +3 1484 2017 1819 +3 1484 2043 1991 +3 1484 2159 2043 +3 1484 2220 2017 +3 1485 2108 1741 +3 1485 2218 1787 +3 1485 2384 1843 +3 1486 1821 1695 +3 1486 1850 1742 +3 1486 1921 1821 +3 1486 2400 1850 +3 1487 1975 1912 +3 1487 2134 1868 +3 1488 1939 1809 +3 1488 2105 1807 +3 1488 2316 1939 +3 1489 1894 1732 +3 1489 2202 1829 +3 1489 2249 1894 +3 1490 1857 1754 +3 1490 1948 1777 +3 1490 2106 1857 +3 1491 2001 1930 +3 1491 2152 1920 +3 1491 2164 2152 +3 1491 2177 1740 +3 1492 1922 1719 +3 1492 2072 1825 +3 1492 2147 1852 +3 1492 2179 1922 +3 1493 1946 1748 +3 1493 2193 1895 +3 1494 1918 1846 +3 1494 2268 1794 +3 1494 2345 1918 +3 1495 2052 1818 +3 1495 2079 1862 +3 1495 2167 2079 +3 1496 2255 1830 +3 1496 2264 1996 +3 1496 2286 2023 +3 1497 2082 1735 +3 1497 2176 2047 +3 1497 2183 2082 +3 1497 2389 1759 +3 1498 1992 1781 +3 1498 2015 1992 +3 1498 2350 1944 +3 1499 1986 1773 +3 1499 2192 1883 +3 1500 1990 1793 +3 1500 2330 1990 +3 1500 2378 1913 +3 1501 2031 1938 +3 1501 2228 1945 +3 1501 2300 2228 +3 1501 2373 2024 +3 1502 1908 1682 +3 1502 2076 1908 +3 1503 2103 1882 +3 1503 2299 2091 +3 1504 2007 1976 +3 1504 2242 2137 +3 1504 2302 2242 +3 1504 2351 2007 +3 1505 2195 2002 +3 1505 2257 2006 +3 1505 2329 2195 +3 1506 1963 1712 +3 1506 2020 1729 +3 1506 2281 1963 +3 1507 2138 1750 +3 1507 2258 2138 +3 1507 2320 2258 +3 1507 2332 1875 +3 1508 2185 1688 +3 1508 2314 1701 +3 1508 2318 2185 +3 1509 2115 1726 +3 1509 2250 2014 +3 1510 2162 1788 +3 1510 2209 2085 +3 1510 2382 2029 +3 1511 1949 1762 +3 1511 2144 1949 +3 1511 2201 1730 +3 1511 2385 2144 +3 1512 1900 1755 +3 1512 2041 1724 +3 1512 2169 1696 +3 1513 2244 2025 +3 1513 2256 2021 +3 1513 2387 1937 +3 1514 1927 1881 +3 1514 2127 1927 +3 1514 2237 1694 +3 1515 1851 1708 +3 1515 2121 1851 +3 1515 2170 1752 +3 1516 2073 1737 +3 1516 2212 1854 +3 1517 1807 1764 +3 1517 2057 1807 +3 1517 2275 2057 +3 1517 2284 1899 +3 1518 2172 1880 +3 1518 2196 2172 +3 1518 2325 2019 +3 1519 2118 1746 +3 1519 2203 2049 +3 1519 2290 2118 +3 1520 1980 1704 +3 1520 2168 2139 +3 1520 2267 1980 +3 1521 2182 1736 +3 1521 2227 1874 +3 1522 2010 1831 +3 1522 2036 1747 +3 1522 2123 2036 +3 1522 2420 1847 +3 1523 1960 1706 +3 1523 2136 1953 +3 1523 2301 1960 +3 1524 2207 2140 +3 1524 2293 2207 +3 1524 2362 2113 +3 1525 2081 1778 +3 1525 2234 1817 +3 1525 2262 2081 +3 1526 1782 1748 +3 1526 2032 1768 +3 1526 2208 1782 +3 1526 2289 2032 +3 1527 2146 1795 +3 1527 2239 1796 +3 1527 2291 1751 +3 1528 2273 1955 +3 1528 2306 1765 +3 1529 1860 1691 +3 1529 2033 1758 +3 1529 2063 1767 +3 1529 2222 1860 +3 1530 2253 1811 +3 1530 2334 1931 +3 1530 2372 2334 +3 1531 2221 2197 +3 1531 2297 2124 +3 1531 2380 2221 +3 1532 2211 1806 +3 1532 2396 2211 +3 1533 1905 1803 +3 1533 2229 1905 +3 1533 2403 2229 +3 1534 1957 1735 +3 1534 2231 1830 +3 1534 2311 1810 +3 1535 1821 1771 +3 1535 2386 1821 +3 1535 2422 1822 +3 1536 2130 1828 +3 1536 2368 1952 +3 1536 2418 2130 +3 1537 2005 1891 +3 1537 2166 1839 +3 1537 2271 2166 +3 1538 1829 1710 +3 1538 2260 2214 +3 1538 2324 1829 +3 1539 1827 1741 +3 1539 2159 1819 +3 1539 2223 1791 +3 1540 2061 1777 +3 1540 2379 2061 +3 1541 1808 1754 +3 1541 2102 1815 +3 1541 2155 1718 +3 1542 2107 1906 +3 1542 2236 1825 +3 1542 2321 1718 +3 1542 2370 2107 +3 1543 2047 1749 +3 1543 2070 1750 +3 1543 2357 2047 +3 1543 2358 2357 +3 1544 2163 1800 +3 1544 2233 1775 +3 1544 2359 1872 +3 1545 2008 1701 +3 1545 2349 2008 +3 1546 1971 1732 +3 1546 2045 1798 +3 1546 2230 1971 +3 1546 2398 2045 +3 1547 2101 1723 +3 1547 2185 1774 +3 1548 1878 1753 +3 1548 1954 1719 +3 1548 2270 1784 +3 1548 2371 1878 +3 1549 2013 1704 +3 1549 2056 1908 +3 1549 2347 2013 +3 1550 2001 1740 +3 1550 2245 1882 +3 1550 2247 2001 +3 1550 2354 1837 +3 1551 2037 1721 +3 1551 2080 1851 +3 1551 2226 1731 +3 1551 2313 1823 +3 1552 1813 1723 +3 1552 1842 1730 +3 1552 2287 1842 +3 1552 2305 1813 +3 1553 2304 1685 +3 1553 2381 1877 +3 1554 1921 1742 +3 1554 2096 1802 +3 1554 2356 1921 +3 1555 1913 1772 +3 1555 2178 1913 +3 1555 2270 1893 +3 1556 1852 1792 +3 1556 1876 1708 +3 1556 2055 1876 +3 1556 2072 1852 +3 1556 2341 2072 +3 1557 1871 1732 +3 1557 1894 1703 +3 1557 2295 1871 +3 1557 2365 1835 +3 1558 2200 1757 +3 1558 2337 1873 +3 1558 2346 2200 +3 1559 1968 1794 +3 1559 2133 1889 +3 1559 2292 1885 +3 1560 1895 1762 +3 1560 1898 1736 +3 1560 1949 1898 +3 1561 1919 1700 +3 1561 2066 1752 +3 1561 2249 1919 +3 1561 2254 2249 +3 1562 1900 1696 +3 1562 2186 1879 +3 1562 2326 1938 +3 1562 2352 1900 +3 1563 1929 1712 +3 1563 1963 1763 +3 1563 2068 1853 +3 1563 2189 1929 +3 1564 1981 1942 +3 1564 2363 1850 +3 1565 1836 1804 +3 1565 1962 1688 +3 1565 2091 1799 +3 1566 1855 1792 +3 1566 2323 1865 +3 1566 2402 1855 +3 1567 2152 1849 +3 1567 2187 1848 +3 1568 1859 1733 +3 1568 1956 1781 +3 1568 1978 1790 +3 1568 2220 1859 +3 1569 1966 1965 +3 1569 1972 1698 +3 1569 2151 1884 +3 1570 1910 1844 +3 1570 1912 1818 +3 1570 2277 1912 +3 1570 2391 1910 +3 1571 2083 1958 +3 1571 2182 1874 +3 1571 2237 1881 +3 1572 1915 1754 +3 1572 2235 1915 +3 1572 2313 2235 +3 1572 2369 1823 +3 1573 1932 1909 +3 1573 2203 1932 +3 1573 2274 1907 +3 1574 1930 1845 +3 1574 2109 1797 +3 1574 2164 1930 +3 1574 2276 1886 +3 1575 1976 1864 +3 1575 2302 1976 +3 1575 2411 1991 +3 1576 1990 1783 +3 1576 2038 1766 +3 1576 2384 1793 +3 1577 1827 1791 +3 1577 1926 1827 +3 1577 2016 1793 +3 1577 2225 2016 +3 1578 2004 1729 +3 1578 2020 1712 +3 1578 2314 1947 +3 1579 1992 1769 +3 1579 2017 1781 +3 1579 2223 1819 +3 1580 2064 1835 +3 1580 2402 1758 +3 1581 1914 1820 +3 1581 2029 1914 +3 1581 2184 1832 +3 1582 1974 1713 +3 1582 2364 2039 +3 1582 2405 1817 +3 1583 1917 1769 +3 1583 2015 1757 +3 1583 2150 1860 +3 1583 2222 1917 +3 1584 1975 1933 +3 1584 2167 1818 +3 1585 1960 1824 +3 1585 2099 1925 +3 1585 2417 1960 +3 1586 2191 1739 +3 1586 2279 1950 +3 1586 2320 1875 +3 1587 2081 1779 +3 1587 2089 1800 +3 1587 2163 1775 +3 1587 2406 2089 +3 1588 2035 1902 +3 1588 2158 1970 +3 1588 2255 1996 +3 1588 2294 2255 +3 1589 1993 1772 +3 1589 2063 1993 +3 1589 2378 2042 +3 1589 2409 2063 +3 1590 1951 1911 +3 1590 2165 1937 +3 1590 2215 1896 +3 1590 2387 1705 +3 1591 1939 1856 +3 1591 2312 1890 +3 1591 2351 1809 +3 1592 1805 1777 +3 1592 1948 1905 +3 1592 2030 1805 +3 1592 2229 2030 +3 1593 2088 1756 +3 1593 2140 1780 +3 1593 2340 1994 +3 1594 2011 1861 +3 1594 2159 2011 +3 1594 2243 2043 +3 1595 2108 1787 +3 1595 2123 1847 +3 1595 2128 1861 +3 1595 2390 2108 +3 1596 2036 1787 +3 1596 2104 1747 +3 1596 2218 1766 +3 1596 2353 2104 +3 1597 2026 1862 +3 1597 2049 1901 +3 1597 2290 2049 +3 1598 2250 1834 +3 1598 2328 1761 +3 1598 2329 2006 +3 1599 2041 1755 +3 1599 2048 1814 +3 1599 2194 2041 +3 1600 1948 1915 +3 1600 2119 1803 +3 1600 2235 2119 +3 1601 2356 1816 +3 1601 2414 1771 +3 1602 2057 1924 +3 1602 2157 1856 +3 1602 2316 2057 +3 1603 1953 1945 +3 1603 2071 1722 +3 1603 2228 1697 +3 1603 2301 1953 +3 1604 2024 1867 +3 1604 2300 2024 +3 1604 2335 1940 +3 1604 2397 2059 +3 1605 2023 1928 +3 1605 2075 1727 +3 1605 2275 1899 +3 1606 1968 1885 +3 1606 2198 1968 +3 1606 2266 1847 +3 1606 2420 1831 +3 1607 1848 1729 +3 1607 1920 1848 +3 1607 2177 1920 +3 1607 2206 1904 +3 1608 2018 1806 +3 1608 2401 2018 +3 1609 2031 1945 +3 1609 2086 2031 +3 1609 2136 1820 +3 1610 2010 1897 +3 1610 2069 1887 +3 1610 2345 1831 +3 1611 2133 1997 +3 1611 2331 2105 +3 1612 2112 1802 +3 1612 2277 1844 +3 1613 1959 1782 +3 1613 2115 1959 +3 1613 2408 2115 +3 1614 2176 1759 +3 1614 2267 2156 +3 1614 2394 2176 +3 1615 2172 1903 +3 1615 2244 1880 +3 1616 2095 1710 +3 1616 2202 1971 +3 1616 2205 2095 +3 1616 2230 2205 +3 1617 2121 1752 +3 1617 2130 2037 +3 1617 2173 1828 +3 1618 1889 1809 +3 1618 2137 1738 +3 1618 2292 1889 +3 1618 2351 2137 +3 1619 1863 1850 +3 1619 2153 1863 +3 1619 2359 1801 +3 1619 2400 1872 +3 1620 1946 1941 +3 1620 2196 2019 +3 1620 2342 1716 +3 1621 2149 1866 +3 1621 2169 1724 +3 1621 2189 1853 +3 1622 1989 1806 +3 1622 2207 1989 +3 1622 2211 2000 +3 1623 2217 1925 +3 1623 2355 2217 +3 1623 2374 2087 +3 1624 1988 1898 +3 1624 2144 1995 +3 1624 2246 1988 +3 1625 1869 1796 +3 1625 2221 1869 +3 1625 2239 1795 +3 1626 2148 1730 +3 1626 2193 1748 +3 1626 2201 1762 +3 1627 1895 1888 +3 1627 1941 1895 +3 1627 2196 1941 +3 1628 2135 1737 +3 1628 2362 1923 +3 1628 2377 2135 +3 1629 2025 2022 +3 1629 2083 1881 +3 1629 2256 2025 +3 1630 2014 2006 +3 1630 2115 2014 +3 1630 2125 1959 +3 1630 2257 2125 +3 1631 2079 1987 +3 1631 2161 1964 +3 1631 2290 1862 +3 1632 2181 1845 +3 1632 2247 1969 +3 1633 2077 2019 +3 1633 2174 2077 +3 1633 2325 1728 +3 1634 2028 1857 +3 1634 2046 2028 +3 1634 2061 1833 +3 1634 2106 2061 +3 1635 1997 1794 +3 1635 2268 1846 +3 1635 2271 1891 +3 1635 2410 1997 +3 1636 2005 1839 +3 1636 2040 2005 +3 1636 2076 2040 +3 1636 2241 1892 +3 1637 2199 1737 +3 1637 2392 1884 +3 1638 2204 1799 +3 1638 2245 1740 +3 1638 2299 1882 +3 1639 2188 1955 +3 1639 2273 1770 +3 1639 2289 2188 +3 1640 2035 1970 +3 1640 2040 2035 +3 1640 2361 1891 +3 1641 2212 1745 +3 1641 2238 1765 +3 1642 2197 1743 +3 1642 2215 1911 +3 1642 2224 2197 +3 1643 2101 1916 +3 1643 2287 2101 +3 1643 2385 1842 +3 1644 2154 1849 +3 1644 2164 1886 +3 1645 2100 1928 +3 1645 2231 2100 +3 1645 2286 2231 +3 1646 1918 1887 +3 1646 2166 1846 +3 1646 2280 1934 +3 1647 1932 1746 +3 1647 2308 1909 +3 1647 2322 1858 +3 1648 2183 1999 +3 1648 2311 2082 +3 1649 2158 1996 +3 1649 2264 1899 +3 1649 2284 1764 +3 1650 2098 2062 +3 1650 2329 1761 +3 1650 2381 2114 +3 1651 2110 1955 +3 1651 2192 2110 +3 1651 2282 1751 +3 1652 2209 1832 +3 1652 2227 2085 +3 1652 2327 1874 +3 1653 2321 1825 +3 1653 2341 2074 +3 1654 2097 1985 +3 1654 2127 2097 +3 1654 2256 1927 +3 1655 1957 1830 +3 1655 2116 1957 +3 1655 2294 2116 +3 1656 2234 1778 +3 1656 2309 1875 +3 1656 2332 2234 +3 1657 2175 1867 +3 1657 2326 2175 +3 1657 2373 2326 +3 1658 2103 2093 +3 1658 2126 1977 +3 1658 2304 2126 +3 1659 2317 1952 +3 1659 2334 2317 +3 1659 2368 1828 +3 1660 2318 2008 +3 1660 2349 1788 +3 1661 1986 1883 +3 1661 2291 1796 +3 1661 2343 1789 +3 1662 2337 1944 +3 1662 2350 1790 +3 1662 2376 2219 +3 1663 2044 1914 +3 1663 2048 2044 +3 1663 2213 2048 +3 1663 2382 2213 +3 1664 2103 1977 +3 1664 2354 1882 +3 1665 2073 1854 +3 1665 2113 2073 +3 1665 2251 1989 +3 1665 2293 2113 +3 1666 2162 2085 +3 1666 2227 1988 +3 1666 2246 1943 +3 1667 2296 1755 +3 1667 2352 1938 +3 1668 2092 1702 +3 1668 2179 1825 +3 1668 2236 1906 +3 1668 2278 2092 +3 1669 2243 2242 +3 1669 2302 1991 +3 1670 2131 1811 +3 1670 2260 1840 +3 1670 2265 2131 +3 1671 2183 2047 +3 1671 2240 1999 +3 1671 2357 2240 +3 1672 2084 2054 +3 1672 2192 2084 +3 1672 2306 2110 +3 1672 2366 2306 +3 1673 2026 2009 +3 1673 2052 2026 +3 1673 2303 1910 +3 1673 2391 2052 +3 1674 2120 2018 +3 1674 2190 1803 +3 1674 2367 2120 +3 1674 2401 2190 +3 1675 2315 1994 +3 1675 2372 1811 +3 1676 2129 2124 +3 1676 2132 1982 +3 1676 2297 2132 +3 1676 2379 2129 +3 1677 2258 2122 +3 1677 2358 2138 +3 1678 2114 1984 +3 1678 2195 2114 +3 1678 2399 1813 +3 1679 2129 1805 +3 1679 2336 1869 +3 1679 2380 2124 +3 1680 2145 1880 +3 1680 2165 2145 +3 1680 2244 1937 +3 1681 1936 236 +3 1681 2187 1936 +3 1681 2281 2187 +3 1681 2288 2281 +3 1682 1902 1502 +3 1682 2116 1902 +3 1683 2076 1892 +3 1683 2285 1908 +3 1683 2348 2283 +3 1684 2279 1822 +3 1684 2344 1950 +3 1684 2422 1967 +3 1685 1935 1474 +3 1685 1984 1553 +3 1685 2091 1935 +3 1685 2093 2091 +3 1685 2304 2093 +3 1686 1975 1942 +3 1686 2375 1933 +3 1687 1841 208 +3 1687 2168 2013 +3 1687 2347 1841 +3 1688 1836 1565 +3 1688 1947 1508 +3 1688 1962 1464 +3 1688 2004 1947 +3 1688 2185 1836 +3 1689 2102 1857 +3 1689 2298 1815 +3 1690 2142 118 +3 1690 2346 2142 +3 1690 2398 2346 +3 1691 2033 1529 +3 1691 2064 2033 +3 1691 2295 2064 +3 1692 2007 1890 +3 1692 2383 1864 +3 1693 2216 1783 +3 1693 2259 2216 +3 1693 2330 1913 +3 1694 1983 1481 +3 1694 2111 1514 +3 1694 2237 1983 +3 1694 2355 2111 +3 1695 1872 1486 +3 1695 2233 1872 +3 1695 2386 1870 +3 1696 1900 1512 +3 1696 2169 1866 +3 1696 2186 1562 +3 1696 2360 2186 +3 1697 2051 1603 +3 1697 2059 161 +3 1697 2300 2059 +3 1698 1966 1569 +3 1698 2250 1966 +3 1698 2415 2250 +3 1699 2367 2248 +3 1699 2396 2120 +3 1699 2418 2310 +3 1700 2066 1561 +3 1700 2214 2066 +3 1700 2324 2214 +3 1701 1814 1545 +3 1701 2008 1508 +3 1701 2314 1979 +3 1701 2419 1814 +3 1702 2092 187 +3 1702 2179 1668 +3 1702 2371 1922 +3 1703 2365 1557 +3 1703 2412 2365 +3 1704 2013 1520 +3 1704 2056 1549 +3 1704 2338 2056 +3 1705 1951 1590 +3 1705 1985 171 +3 1705 2021 1985 +3 1705 2387 2021 +3 1706 2012 1523 +3 1706 2184 2012 +3 1706 2417 1481 +3 1707 1974 1817 +3 1707 2332 2065 +3 1707 2388 1974 +3 1708 1876 1515 +3 1708 2080 2074 +3 1708 2341 1556 +3 1709 2257 2002 +3 1709 2305 2034 +3 1710 1840 1538 +3 1710 2202 1616 +3 1710 2269 1840 +3 1711 2253 1931 +3 1711 2260 2253 +3 1712 1929 1480 +3 1712 1963 1563 +3 1712 1979 1578 +3 1712 2020 1506 +3 1713 2139 1582 +3 1713 2267 2139 +3 1714 2168 1998 +3 1714 2364 2139 +3 1714 2416 2364 +3 1715 2170 1876 +3 1715 2254 2170 +3 1715 2412 2254 +3 1716 1946 1620 +3 1716 2261 1946 +3 1716 2289 2261 +3 1716 2342 2188 +3 1717 2155 1815 +3 1717 2370 2155 +3 1717 2404 2107 +3 1718 1808 1541 +3 1718 2094 1473 +3 1718 2321 2094 +3 1718 2369 1808 +3 1718 2370 1542 +3 1719 1922 1548 +3 1719 2147 1492 +3 1719 2323 2147 +3 1720 2203 2003 +3 1720 2393 1901 +3 1721 2226 1551 +3 1721 2248 2226 +3 1721 2418 2248 +3 1722 2071 163 +3 1722 2301 1603 +3 1723 1804 1547 +3 1723 1813 1474 +3 1723 2287 1552 +3 1724 2169 1512 +3 1724 2189 1621 +3 1724 2194 1480 +3 1725 2262 1817 +3 1725 2339 2141 +3 1725 2405 2339 +3 1726 1966 1509 +3 1726 2413 1965 +3 1727 2075 132 +3 1727 2275 1605 +3 1728 2145 1482 +3 1728 2146 1633 +3 1728 2325 1880 +3 1729 1848 1506 +3 1729 2020 1578 +3 1729 2206 1607 +3 1730 1842 1511 +3 1730 2034 1552 +3 1730 2148 1467 +3 1730 2201 1626 +3 1731 2226 2119 +3 1731 2313 1551 +3 1732 1894 1557 +3 1732 1971 1489 +3 1732 2117 1546 +3 1733 1978 1568 +3 1733 2333 1978 +3 1733 2411 2027 +3 1734 2042 2016 +3 1734 2409 2042 +3 1734 2421 2409 +3 1735 2082 1534 +3 1735 2389 1497 +3 1736 1888 1560 +3 1736 1898 1521 +3 1736 1958 1466 +3 1736 2182 1958 +3 1737 2058 1637 +3 1737 2073 1628 +3 1737 2135 104 +3 1737 2199 1516 +3 1738 2143 1463 +3 1738 2160 1618 +3 1738 2243 2143 +3 1739 2191 142 +3 1739 2320 1586 +3 1740 1904 1638 +3 1740 2001 1491 +3 1740 2177 1904 +3 1740 2245 1550 +3 1741 1827 1485 +3 1741 2011 1539 +3 1741 2390 2011 +3 1742 1868 1554 +3 1742 1921 1486 +3 1742 2363 1868 +3 1743 2210 1482 +3 1743 2215 1642 +3 1743 2221 2210 +3 1744 2090 225 +3 1744 2167 2090 +3 1745 1965 1478 +3 1745 2151 1965 +3 1745 2199 2151 +3 1745 2212 2199 +3 1745 2232 1641 +3 1746 1932 1519 +3 1746 1964 228 +3 1746 2118 1964 +3 1746 2272 1647 +3 1747 2010 1522 +3 1747 2036 1596 +3 1747 2104 197 +3 1748 2148 1626 +3 1748 2193 1493 +3 1748 2261 1526 +3 1749 2070 1543 +3 1749 2394 2070 +3 1750 2065 1507 +3 1750 2138 1543 +3 1750 2388 2065 +3 1751 1883 1651 +3 1751 2146 1527 +3 1751 2174 2146 +3 1751 2282 2174 +3 1751 2291 1883 +3 1752 2121 1515 +3 1752 2170 1561 +3 1752 2173 1617 +3 1753 1878 189 +3 1753 2270 1548 +3 1754 1808 1572 +3 1754 1915 1490 +3 1754 2102 1541 +3 1755 2041 1512 +3 1755 2044 1599 +3 1755 2296 2044 +3 1755 2352 1667 +3 1756 2088 107 +3 1756 2140 1593 +3 1756 2362 2140 +3 1757 1944 1558 +3 1757 2015 1944 +3 1757 2150 1583 +3 1757 2200 1479 +3 1758 1865 1477 +3 1758 2033 1580 +3 1758 2063 1529 +3 1758 2402 1865 +3 1759 1980 1614 +3 1759 2176 1497 +3 1759 2338 1980 +3 1759 2389 2338 +3 1760 2224 175 +3 1760 2297 2197 +3 1761 2098 1650 +3 1761 2328 97 +3 1761 2329 1598 +3 1762 1949 1560 +3 1762 2193 1626 +3 1762 2201 1511 +3 1763 2068 1563 +3 1763 2288 238 +3 1764 2158 1649 +3 1764 2284 1517 +3 1764 2307 2158 +3 1764 2331 2307 +3 1765 1854 1641 +3 1765 2238 1528 +3 1765 2251 1854 +3 1765 2366 1469 +3 1766 1843 1576 +3 1766 2038 195 +3 1766 2218 1843 +3 1766 2353 1596 +3 1767 2222 1529 +3 1767 2421 1917 +3 1768 2208 1526 +3 1768 2408 2208 +3 1768 2413 2408 +3 1769 1917 1462 +3 1769 1961 1579 +3 1769 2015 1583 +3 1770 2032 1639 +3 1770 2238 2232 +3 1770 2263 2032 +3 1770 2273 2238 +3 1771 1821 1601 +3 1771 2414 146 +3 1771 2422 1535 +3 1772 1784 1555 +3 1772 1993 1477 +3 1772 2378 1589 +3 1773 2084 1499 +3 1773 2401 2084 +3 1773 2403 2190 +3 1774 1916 1547 +3 1774 2171 1916 +3 1774 2318 2171 +3 1775 1778 1587 +3 1775 1870 1476 +3 1775 2163 1544 +3 1775 2233 1870 +3 1776 1952 1483 +3 1776 2310 1952 +3 1776 2396 2310 +3 1777 1805 1540 +3 1777 1948 1592 +3 1777 2106 1490 +3 1778 2081 1587 +3 1778 2234 1525 +3 1778 2309 1656 +3 1779 2141 214 +3 1779 2262 2141 +3 1779 2406 1587 +3 1780 2000 1483 +3 1780 2050 1593 +3 1780 2207 2000 +3 1781 1956 1498 +3 1781 1992 1579 +3 1781 2220 1568 +3 1782 1959 1467 +3 1782 2148 1748 +3 1782 2208 1613 +3 1783 2038 1576 +3 1783 2330 1693 +3 1783 2407 2038 +3 1784 1954 1548 +3 1784 2270 1555 +3 1785 2340 2050 +3 1785 2372 2340 +3 1786 2117 1479 +3 1786 2398 2117 +3 1787 2108 1485 +3 1787 2123 1595 +3 1787 2218 1596 +3 1788 1943 1660 +3 1788 2162 1943 +3 1788 2349 2213 +3 1788 2382 1510 +3 1789 1986 1661 +3 1789 2343 2030 +3 1789 2403 1986 +3 1790 1956 1568 +3 1790 1978 122 +3 1790 2350 1956 +3 1790 2376 1662 +3 1791 1827 1539 +3 1791 1961 1462 +3 1791 2223 1961 +3 1791 2225 1577 +3 1792 1855 1461 +3 1792 2055 1556 +3 1792 2147 1566 +3 1793 1926 1577 +3 1793 1990 1576 +3 1793 2016 1500 +3 1793 2384 1926 +3 1794 1968 1494 +3 1794 2133 1559 +3 1794 2268 1635 +3 1795 2146 1728 +3 1795 2210 1625 +3 1795 2239 1527 +3 1796 1869 1471 +3 1796 2239 1625 +3 1796 2291 1527 +3 1796 2343 1661 +3 1797 2109 87 +3 1797 2276 1574 +3 1798 2045 117 +3 1798 2230 1546 +3 1799 1962 1565 +3 1799 2204 1962 +3 1799 2299 1638 +3 1800 1801 1544 +3 1800 2089 216 +3 1800 2163 1587 +3 1801 2153 1619 +3 1801 2359 1544 +3 1802 1816 1554 +3 1802 2096 1612 +3 1802 2112 150 +3 1803 1905 1600 +3 1803 2119 1460 +3 1803 2190 1533 +3 1803 2367 1674 +3 1804 1836 1547 +3 1804 1935 1565 +3 1805 2129 1540 +3 1805 2336 1679 +3 1806 1989 1469 +3 1806 2018 1532 +3 1806 2054 1608 +3 1806 2211 1622 +3 1807 2316 1488 +3 1807 2331 1764 +3 1808 2369 1572 +3 1809 1889 1488 +3 1809 1939 1591 +3 1809 2351 1618 +3 1810 2067 136 +3 1810 2231 1534 +3 1810 2311 2067 +3 1811 2131 111 +3 1811 2253 1670 +3 1811 2315 1675 +3 1811 2372 1530 +3 1812 2087 168 +3 1812 2111 2087 +3 1812 2127 2111 +3 1813 2002 1678 +3 1813 2305 2002 +3 1813 2399 1474 +3 1814 2048 1545 +3 1814 2194 1599 +3 1814 2419 1480 +3 1815 2102 1689 +3 1815 2155 1541 +3 1815 2298 182 +3 1815 2404 1717 +3 1816 2053 1601 +3 1816 2356 1554 +3 1817 1974 1582 +3 1817 2234 1707 +3 1817 2262 1525 +3 1817 2405 1725 +3 1818 1912 1584 +3 1818 2052 1570 +3 1818 2167 1495 +3 1819 2017 1579 +3 1819 2159 1484 +3 1819 2223 1539 +3 1820 1914 1468 +3 1820 2012 1581 +3 1820 2086 1609 +3 1820 2136 2012 +3 1821 1921 1601 +3 1821 2386 1695 +3 1822 2060 1476 +3 1822 2279 2060 +3 1822 2386 1535 +3 1822 2422 1684 +3 1823 2080 1551 +3 1823 2313 1572 +3 1823 2369 1473 +3 1824 1960 1722 +3 1824 2099 1585 +3 1825 2072 1653 +3 1825 2179 1492 +3 1825 2236 1668 +3 1825 2321 1542 +3 1826 2355 1694 +3 1826 2417 2217 +3 1827 1926 1485 +3 1828 1931 1659 +3 1828 2130 1617 +3 1828 2173 1472 +3 1828 2368 1536 +3 1829 1919 1489 +3 1829 2202 1710 +3 1829 2324 1919 +3 1830 1957 1534 +3 1830 2255 1655 +3 1830 2286 1496 +3 1831 2010 1610 +3 1831 2198 1606 +3 1831 2345 2198 +3 1831 2420 1522 +3 1832 2029 1581 +3 1832 2184 1481 +3 1832 2209 2029 +3 1832 2327 1652 +3 1833 1982 178 +3 1833 2046 1634 +3 1833 2379 1982 +3 1834 2078 1598 +3 1834 2415 99 +3 1835 1855 1580 +3 1835 2064 1557 +3 1835 2365 1461 +3 1836 2185 1547 +3 1837 2247 1550 +3 1837 2252 91 +3 1837 2354 2252 +3 1838 2180 140 +3 1838 2358 2180 +3 1839 1934 203 +3 1839 2005 1537 +3 1839 2166 1934 +3 1839 2241 1636 +3 1840 2260 1538 +3 1840 2265 1670 +3 1840 2269 113 +3 1841 2283 207 +3 1841 2285 2283 +3 1841 2347 2285 +3 1842 2287 1643 +3 1842 2385 1511 +3 1843 2218 1485 +3 1843 2384 1576 +3 1844 1910 152 +3 1844 2112 1612 +3 1844 2277 1570 +3 1845 1930 1632 +3 1845 2109 1574 +3 1845 2181 88 +3 1846 1918 1646 +3 1846 2268 1494 +3 1846 2271 1635 +3 1847 2123 1522 +3 1847 2128 1595 +3 1847 2266 2128 +3 1847 2420 1606 +3 1848 1920 1567 +3 1848 2187 1506 +3 1849 1936 1567 +3 1849 2152 1644 +3 1849 2154 234 +3 1850 1863 1564 +3 1850 2363 1742 +3 1850 2400 1619 +3 1851 2037 1551 +3 1851 2080 1708 +3 1851 2121 2037 +3 1852 2072 1492 +3 1852 2147 1792 +3 1853 2068 239 +3 1853 2149 1621 +3 1853 2189 1563 +3 1854 2073 1516 +3 1854 2212 1641 +3 1854 2251 1665 +3 1855 2402 1580 +3 1856 1939 1602 +3 1856 2157 129 +3 1856 2312 1591 +3 1857 2028 1689 +3 1857 2102 1754 +3 1857 2106 1634 +3 1858 1973 5 +3 1858 2308 1647 +3 1858 2322 1973 +3 1859 2220 1484 +3 1859 2411 1733 +3 1860 2150 1479 +3 1860 2222 1583 +3 1860 2295 1691 +3 1861 2128 1463 +3 1861 2143 1594 +3 1861 2390 1595 +3 1862 2026 1495 +3 1862 2079 1631 +3 1862 2290 1597 +3 1863 1981 1564 +3 1863 2153 219 +3 1864 1976 1692 +3 1864 2027 1575 +3 1864 2383 126 +3 1865 2323 1477 +3 1865 2402 1566 +3 1866 2149 241 +3 1866 2169 1621 +3 1866 2360 1696 +3 1867 2024 1657 +3 1867 2175 245 +3 1867 2335 1604 +3 1868 1942 1487 +3 1868 2096 1554 +3 1868 2134 2096 +3 1868 2363 1942 +3 1869 2336 1471 +3 1869 2380 1679 +3 1870 2233 1695 +3 1870 2386 1822 +3 1871 2117 1732 +3 1871 2295 1479 +3 1872 2233 1544 +3 1872 2359 1619 +3 1872 2400 1486 +3 1873 2142 1558 +3 1873 2219 120 +3 1873 2337 2219 +3 1874 1983 1571 +3 1874 2182 1521 +3 1874 2227 1652 +3 1874 2327 1983 +3 1875 2060 1586 +3 1875 2309 2060 +3 1875 2320 1507 +3 1875 2332 1656 +3 1876 2055 1715 +3 1876 2170 1515 +3 1877 2062 95 +3 1877 2304 1553 +3 1877 2381 2062 +3 1878 2371 1702 +3 1879 2186 243 +3 1879 2326 1562 +3 1880 2145 1728 +3 1880 2172 1615 +3 1880 2244 1680 +3 1880 2325 1518 +3 1881 1927 1629 +3 1881 2083 1571 +3 1881 2237 1514 +3 1882 2103 1664 +3 1882 2245 1638 +3 1882 2299 1503 +3 1882 2354 1550 +3 1883 1986 1499 +3 1883 2192 1651 +3 1883 2291 1661 +3 1884 1972 1569 +3 1884 2151 1637 +3 1884 2392 102 +3 1885 1968 1559 +3 1885 2160 1463 +3 1885 2266 1606 +3 1885 2292 2160 +3 1886 2154 1644 +3 1886 2164 1574 +3 1886 2276 233 +3 1887 1918 1610 +3 1887 2069 200 +3 1887 2280 1646 +3 1888 1895 1560 +3 1888 1903 1627 +3 1889 2105 1488 +3 1889 2133 2105 +3 1889 2292 1559 +3 1890 2007 1591 +3 1890 2312 128 +3 1890 2383 1692 +3 1891 2005 1640 +3 1891 2271 1537 +3 1891 2410 1635 +3 1892 2076 1636 +3 1892 2241 205 +3 1892 2348 1683 +3 1893 2178 1555 +3 1893 2259 2178 +3 1893 2270 1753 +3 1894 2249 1703 +3 1895 1941 1493 +3 1895 2193 1762 +3 1896 2165 1590 +3 1896 2215 1743 +3 1897 2010 1747 +3 1897 2069 1610 +3 1898 1949 1624 +3 1898 1988 1521 +3 1899 2023 1605 +3 1899 2264 2023 +3 1899 2275 1517 +3 1899 2284 1649 +3 1900 2352 1755 +3 1901 2009 1597 +3 1901 2049 1720 +3 1901 2393 156 +3 1902 2035 1502 +3 1902 2294 1588 +3 1903 2022 1615 +3 1903 2196 1627 +3 1904 2177 1607 +3 1904 2204 1638 +3 1904 2206 1464 +3 1905 1948 1600 +3 1905 2229 1592 +3 1906 2107 185 +3 1906 2236 1542 +3 1906 2278 1668 +3 1907 2003 1573 +3 1907 2274 66 +3 1908 2056 1682 +3 1908 2076 1683 +3 1908 2285 1549 +3 1909 1932 1647 +3 1909 2274 1573 +3 1909 2308 67 +3 1910 2303 153 +3 1910 2391 1673 +3 1911 1951 173 +3 1911 2215 1590 +3 1911 2224 1642 +3 1912 1975 1584 +3 1912 2134 1487 +3 1912 2277 2134 +3 1913 2178 1693 +3 1913 2330 1500 +3 1913 2378 1772 +3 1914 2044 1468 +3 1914 2382 1663 +3 1915 1948 1490 +3 1915 2235 1600 +3 1916 1995 1643 +3 1916 2101 1547 +3 1916 2171 1458 +3 1917 2222 1767 +3 1917 2421 1462 +3 1918 2345 1610 +3 1919 2249 1489 +3 1919 2324 1700 +3 1920 2152 1567 +3 1920 2177 1491 +3 1921 2356 1601 +3 1922 2179 1702 +3 1922 2371 1548 +3 1923 2362 1756 +3 1923 2377 1628 +3 1924 2057 1727 +3 1924 2157 1602 +3 1925 2099 166 +3 1925 2217 1585 +3 1925 2374 1623 +3 1926 2384 1485 +3 1927 2127 1654 +3 1927 2256 1629 +3 1928 2023 1645 +3 1928 2075 1605 +3 1928 2100 134 +3 1929 2189 1724 +3 1930 2001 1632 +3 1930 2164 1491 +3 1931 2214 1711 +3 1931 2253 1530 +3 1931 2334 1659 +3 1932 2203 1519 +3 1933 1975 1686 +3 1933 2090 1584 +3 1933 2375 222 +3 1934 2166 1646 +3 1934 2280 202 +3 1935 2091 1565 +3 1936 2187 1567 +3 1937 2165 1680 +3 1937 2244 1513 +3 1937 2387 1590 +3 1938 2031 1667 +3 1938 2352 1562 +3 1938 2373 1501 +3 1939 2316 1602 +3 1940 2335 246 +3 1940 2395 159 +3 1940 2397 1604 +3 1941 1946 1493 +3 1941 2196 1620 +3 1942 1975 1487 +3 1942 1981 1686 +3 1942 2363 1564 +3 1943 2162 1666 +3 1943 2171 1660 +3 1943 2246 1458 +3 1944 2015 1498 +3 1944 2337 1558 +3 1944 2350 1662 +3 1945 1953 1609 +3 1945 2031 1501 +3 1945 2228 1603 +3 1946 2261 1748 +3 1947 2004 1578 +3 1947 2314 1508 +3 1949 2144 1624 +3 1950 2191 1586 +3 1950 2279 1684 +3 1950 2344 144 +3 1952 2310 1536 +3 1952 2317 1483 +3 1952 2368 1659 +3 1953 2136 1609 +3 1953 2301 1523 +3 1954 2323 1719 +3 1955 2110 1528 +3 1955 2188 1459 +3 1955 2273 1639 +3 1955 2282 1651 +3 1956 2350 1498 +3 1957 2116 1470 +3 1957 2389 1735 +3 1958 2083 1466 +3 1958 2182 1571 +3 1959 2115 1630 +3 1959 2125 1467 +3 1960 2301 1722 +3 1960 2417 1706 +3 1961 2223 1579 +3 1962 2204 1464 +3 1963 2281 1763 +3 1964 2118 1631 +3 1964 2161 227 +3 1965 1966 1726 +3 1965 2151 1569 +3 1965 2413 1478 +3 1966 2250 1509 +3 1967 2344 1684 +3 1967 2422 1771 +3 1968 2198 1494 +3 1969 2181 1632 +3 1969 2247 1837 +3 1970 2035 1588 +3 1970 2158 1465 +3 1970 2361 1640 +3 1971 2202 1489 +3 1971 2230 1616 +3 1972 2319 1698 +3 1973 2322 230 +3 1974 2156 1713 +3 1974 2388 1475 +3 1976 2007 1692 +3 1976 2302 1504 +3 1977 2103 1658 +3 1977 2126 93 +3 1977 2252 1664 +3 1978 2333 123 +3 1979 2314 1578 +3 1979 2419 1701 +3 1980 2267 1614 +3 1980 2338 1704 +3 1981 2375 1686 +3 1982 2132 177 +3 1982 2379 1676 +3 1983 2237 1571 +3 1983 2327 1481 +3 1984 2114 1553 +3 1984 2399 1678 +3 1985 2021 1654 +3 1985 2097 170 +3 1986 2403 1773 +3 1987 2079 1744 +3 1987 2161 1631 +3 1988 2227 1521 +3 1988 2246 1666 +3 1989 2251 1469 +3 1989 2293 1665 +3 1990 2330 1783 +3 1991 2043 1669 +3 1991 2302 1575 +3 1991 2411 1859 +3 1992 2015 1769 +3 1993 2063 1758 +3 1994 2088 1593 +3 1994 2315 109 +3 1994 2340 1675 +3 1995 2246 1624 +3 1995 2385 1643 +3 1996 2158 1588 +3 1996 2255 1496 +3 1996 2264 1649 +3 1997 2133 1794 +3 1997 2307 1611 +3 1997 2410 1465 +3 1998 2168 1687 +3 1998 2416 1714 +3 1999 2067 1648 +3 1999 2183 1671 +3 1999 2240 138 +3 2000 2207 1622 +3 2000 2211 1776 +3 2001 2247 1632 +3 2002 2195 1678 +3 2002 2257 1505 +3 2002 2305 1709 +3 2003 2203 1573 +3 2003 2393 1720 +3 2004 2206 1729 +3 2005 2040 1640 +3 2006 2014 1598 +3 2006 2257 1630 +3 2006 2329 1505 +3 2007 2351 1591 +3 2008 2318 1508 +3 2008 2349 1660 +3 2009 2026 1597 +3 2009 2303 1673 +3 2011 2159 1539 +3 2011 2390 1861 +3 2012 2136 1523 +3 2012 2184 1581 +3 2013 2168 1520 +3 2013 2347 1687 +3 2014 2115 1509 +3 2014 2250 1598 +3 2016 2042 1500 +3 2016 2225 1734 +3 2017 2220 1781 +3 2018 2120 1532 +3 2018 2401 1674 +3 2019 2077 1620 +3 2019 2196 1518 +3 2019 2325 1633 +3 2021 2256 1654 +3 2021 2387 1513 +3 2022 2025 1615 +3 2022 2083 1629 +3 2023 2264 1496 +3 2023 2286 1645 +3 2024 2300 1501 +3 2024 2373 1657 +3 2025 2244 1615 +3 2025 2256 1513 +3 2026 2052 1495 +3 2027 2333 1733 +3 2027 2411 1575 +3 2028 2046 180 +3 2028 2298 1689 +3 2029 2209 1510 +3 2029 2382 1914 +3 2030 2229 1789 +3 2030 2336 1805 +3 2030 2343 1471 +3 2031 2086 1667 +3 2032 2263 1768 +3 2032 2289 1639 +3 2033 2064 1580 +3 2034 2125 1709 +3 2034 2305 1552 +3 2035 2040 1502 +3 2036 2123 1787 +3 2037 2121 1617 +3 2037 2130 1721 +3 2038 2407 194 +3 2039 2405 1582 +3 2039 2416 211 +3 2040 2076 1502 +3 2041 2194 1724 +3 2042 2378 1500 +3 2042 2409 1589 +3 2043 2159 1594 +3 2043 2243 1669 +3 2044 2048 1599 +3 2044 2296 1468 +3 2045 2398 1690 +3 2047 2176 1749 +3 2047 2183 1497 +3 2047 2357 1671 +3 2048 2213 1545 +3 2049 2203 1720 +3 2049 2290 1519 +3 2050 2317 1785 +3 2050 2340 1593 +3 2051 2071 1603 +3 2052 2391 1570 +3 2053 2414 1601 +3 2054 2084 1608 +3 2054 2366 1672 +3 2055 2412 1715 +3 2056 2116 1682 +3 2056 2338 1470 +3 2057 2275 1727 +3 2057 2316 1807 +3 2058 2392 1637 +3 2059 2300 1604 +3 2059 2397 160 +3 2060 2279 1586 +3 2060 2309 1476 +3 2061 2106 1777 +3 2061 2379 1833 +3 2062 2098 96 +3 2062 2381 1650 +3 2063 2409 1767 +3 2064 2295 1557 +3 2065 2332 1507 +3 2065 2388 1707 +3 2066 2173 1752 +3 2066 2214 1472 +3 2067 2311 1648 +3 2070 2388 1750 +3 2070 2394 1475 +3 2072 2341 1653 +3 2073 2113 1628 +3 2074 2080 1473 +3 2074 2094 1653 +3 2074 2341 1708 +3 2077 2174 1459 +3 2077 2342 1620 +3 2078 2328 1598 +3 2079 2167 1744 +3 2081 2262 1779 +3 2082 2183 1648 +3 2082 2311 1534 +3 2084 2192 1499 +3 2084 2401 1608 +3 2085 2162 1510 +3 2085 2209 1652 +3 2085 2227 1666 +3 2086 2296 1667 +3 2087 2111 1623 +3 2087 2374 167 +3 2089 2406 215 +3 2090 2167 1584 +3 2091 2093 1503 +3 2091 2299 1799 +3 2092 2278 186 +3 2093 2103 1503 +3 2093 2304 1658 +3 2094 2321 1653 +3 2095 2205 115 +3 2095 2269 1710 +3 2096 2134 1612 +3 2097 2127 1812 +3 2100 2231 1810 +3 2101 2287 1723 +3 2104 2353 196 +3 2105 2133 1611 +3 2105 2331 1807 +3 2107 2370 1717 +3 2107 2404 184 +3 2108 2390 1741 +3 2110 2192 1672 +3 2110 2306 1528 +3 2111 2127 1514 +3 2111 2355 1623 +3 2113 2293 1524 +3 2113 2362 1628 +3 2114 2195 1650 +3 2114 2381 1553 +3 2115 2408 1726 +3 2116 2294 1902 +3 2117 2398 1546 +3 2118 2290 1631 +3 2119 2226 1460 +3 2119 2235 1731 +3 2120 2367 1699 +3 2120 2396 1532 +3 2122 2180 1677 +3 2122 2258 1739 +3 2124 2129 1679 +3 2124 2297 1676 +3 2124 2380 1531 +3 2125 2257 1709 +3 2126 2304 1877 +3 2128 2266 1463 +3 2129 2379 1540 +3 2130 2418 1721 +3 2131 2265 112 +3 2132 2297 1760 +3 2134 2277 1612 +3 2135 2377 105 +3 2137 2242 1738 +3 2137 2351 1504 +3 2138 2258 1677 +3 2138 2358 1543 +3 2139 2168 1714 +3 2139 2267 1520 +3 2139 2364 1582 +3 2140 2207 1780 +3 2140 2362 1524 +3 2141 2262 1725 +3 2141 2339 213 +3 2142 2346 1558 +3 2143 2243 1594 +3 2144 2385 1995 +3 2145 2165 1482 +3 2146 2174 1633 +3 2147 2323 1566 +3 2151 2199 1637 +3 2152 2164 1644 +3 2155 2370 1718 +3 2156 2267 1713 +3 2156 2394 1614 +3 2158 2307 1465 +3 2160 2292 1618 +3 2166 2271 1846 +3 2170 2254 1561 +3 2171 2318 1660 +3 2172 2196 1903 +3 2174 2282 1459 +3 2175 2326 1879 +3 2176 2394 1749 +3 2178 2259 1693 +3 2180 2358 1677 +3 2185 2318 1774 +3 2186 2360 242 +3 2187 2281 1506 +3 2188 2289 1716 +3 2188 2342 1459 +3 2190 2401 1773 +3 2190 2403 1533 +3 2195 2329 1650 +3 2197 2221 1743 +3 2197 2224 1760 +3 2197 2297 1531 +3 2198 2345 1494 +3 2199 2212 1516 +3 2200 2346 1786 +3 2205 2230 1798 +3 2207 2293 1989 +3 2208 2408 1613 +3 2210 2221 1625 +3 2211 2396 1776 +3 2213 2349 1545 +3 2213 2382 1788 +3 2214 2260 1711 +3 2214 2324 1538 +3 2216 2259 192 +3 2216 2407 1783 +3 2217 2355 1826 +3 2217 2417 1585 +3 2219 2337 1662 +3 2219 2376 121 +3 2221 2380 1869 +3 2225 2421 1734 +3 2226 2248 1460 +3 2228 2300 1697 +3 2229 2403 1789 +3 2231 2286 1830 +3 2232 2238 1641 +3 2232 2263 1770 +3 2234 2332 1707 +3 2235 2313 1731 +3 2238 2273 1528 +3 2240 2357 1838 +3 2242 2243 1738 +3 2242 2302 1669 +3 2248 2367 1460 +3 2248 2418 1699 +3 2249 2254 1703 +3 2250 2415 1834 +3 2252 2354 1664 +3 2253 2260 1670 +3 2254 2412 1703 +3 2255 2294 1655 +3 2258 2320 1739 +3 2261 2289 1526 +3 2263 2413 1768 +3 2272 2322 1647 +3 2281 2288 1763 +3 2283 2285 1683 +3 2283 2348 206 +3 2285 2347 1549 +3 2306 2366 1765 +3 2307 2331 1611 +3 2310 2396 1699 +3 2310 2418 1536 +3 2317 2334 1785 +3 2319 2415 1698 +3 2326 2373 1938 +3 2334 2372 1785 +3 2338 2389 1470 +3 2339 2405 2039 +3 2340 2372 1675 +3 2346 2398 1786 +3 2357 2358 1838 +3 2361 2410 1891 +3 2364 2416 2039 +3 2365 2412 1461 +3 2408 2413 1726 +3 2409 2421 1767 +3 2423 2695 2622 +3 2423 2711 2549 +3 2423 2736 2711 +3 2424 2725 2578 +3 2424 2776 2704 +3 2425 2616 2540 +3 2425 2679 2529 +3 2425 2745 2679 +3 2426 2585 2583 +3 2426 2635 2526 +3 2426 2684 2635 +3 2426 2773 2684 +3 2427 2775 2548 +3 2428 2678 2605 +3 2428 2682 2568 +3 2428 2719 2661 +3 2429 2645 2614 +3 2429 2772 2645 +3 2429 2800 2569 +3 2430 2690 2618 +3 2430 2770 2619 +3 2430 2777 2590 +3 2431 2636 2565 +3 2431 2647 2636 +3 2431 2771 2594 +3 2432 2785 2559 +3 2432 2786 2584 +3 2432 2787 2786 +3 2433 2624 2465 +3 2433 2666 2525 +3 2434 2696 2574 +3 2434 2718 2559 +3 2434 2750 2547 +3 2435 2592 2544 +3 2435 2628 2559 +3 2435 2785 2584 +3 2436 2609 2530 +3 2436 2717 2570 +3 2437 2612 2466 +3 2437 2651 2549 +3 2437 2730 2554 +3 2438 2625 2611 +3 2438 2652 2571 +3 2438 2762 2625 +3 2439 2593 2562 +3 2439 2613 2593 +3 2439 2627 2613 +3 2439 2761 2567 +3 2439 2768 2627 +3 2440 2671 2523 +3 2440 2729 2617 +3 2440 2757 2555 +3 2441 2582 2527 +3 2441 2659 2463 +3 2441 2681 2582 +3 2441 2709 2575 +3 2442 2641 2581 +3 2442 2649 2641 +3 2442 2697 2626 +3 2442 2799 2697 +3 2443 2693 2638 +3 2443 2752 2633 +3 2444 2698 2535 +3 2444 2714 2698 +3 2444 2767 2714 +3 2445 2743 2540 +3 2445 2746 2708 +3 2446 2648 2521 +3 2446 2728 2548 +3 2446 2795 2728 +3 2447 2608 2542 +3 2447 2643 2608 +3 2447 2759 2553 +3 2447 2789 2643 +3 2448 2748 2674 +3 2448 2751 2656 +3 2449 2699 2560 +3 2449 2733 2699 +3 2449 2754 2691 +3 2450 2601 2561 +3 2450 2710 2556 +3 2450 2765 2544 +3 2451 2705 2686 +3 2451 2747 2555 +3 2451 2758 2747 +3 2452 2623 2598 +3 2452 2706 2640 +3 2452 2794 2623 +3 2453 2701 2532 +3 2453 2780 2668 +3 2453 2796 2701 +3 2454 2646 2582 +3 2454 2650 2537 +3 2454 2680 2567 +3 2455 2564 2536 +3 2455 2660 2564 +3 2455 2790 2660 +3 2456 2615 2557 +3 2456 2658 2541 +3 2456 2685 2520 +3 2456 2783 2615 +3 2457 2630 2542 +3 2457 2763 2610 +3 2458 2669 2550 +3 2458 2738 2484 +3 2459 2671 2597 +3 2459 2726 2569 +3 2460 2594 2531 +3 2460 2749 2581 +3 2460 2784 2576 +3 2461 2587 2529 +3 2461 2712 2611 +3 2461 2782 2609 +3 2461 2801 2587 +3 2462 2575 2554 +3 2462 2659 2575 +3 2462 2715 2528 +3 2462 2730 2572 +3 2463 2681 2441 +3 2463 2792 2579 +3 2464 2583 2571 +3 2464 2657 2583 +3 2464 2675 2657 +3 2464 2723 2621 +3 2465 2624 2553 +3 2465 2666 2433 +3 2465 2727 2516 +3 2466 2612 2550 +3 2466 2689 2572 +3 2466 2730 2437 +3 2467 2601 2544 +3 2467 2624 2601 +3 2467 2789 2624 +3 2468 2625 2545 +3 2468 2629 2530 +3 2468 2719 2605 +3 2469 2634 2600 +3 2469 2685 2541 +3 2469 2778 2534 +3 2469 2787 2520 +3 2470 2770 2623 +3 2470 2781 2562 +3 2471 2595 2536 +3 2471 2599 2524 +3 2471 2656 2578 +3 2471 2725 2595 +3 2472 2603 2548 +3 2472 2628 2603 +3 2472 2728 2547 +3 2472 2750 2559 +3 2473 2648 2620 +3 2473 2703 2591 +3 2473 2802 2703 +3 2474 2762 2571 +3 2475 2622 2529 +3 2475 2679 2556 +3 2475 2736 2622 +3 2476 2570 2569 +3 2476 2580 2570 +3 2476 2774 2580 +3 2476 2800 2565 +3 2477 2637 2573 +3 2477 2788 2696 +3 2477 2795 2637 +3 2478 2627 2588 +3 2478 2642 2539 +3 2478 2668 2613 +3 2479 2663 2596 +3 2479 2681 2663 +3 2479 2791 2589 +3 2480 2646 2567 +3 2480 2684 2527 +3 2480 2761 2562 +3 2481 2675 2554 +3 2481 2773 2657 +3 2482 2673 2577 +3 2482 2674 2566 +3 2482 2729 2674 +3 2483 2670 2603 +3 2483 2765 2664 +3 2484 2516 2458 +3 2484 2666 2516 +3 2484 2711 2525 +3 2484 2738 2711 +3 2485 2568 2523 +3 2485 2671 2639 +3 2485 2678 2568 +3 2486 2680 2607 +3 2486 2731 2588 +3 2486 2768 2680 +3 2487 2638 2543 +3 2487 2707 2563 +3 2487 2721 2662 +3 2488 2677 2535 +3 2488 2720 2564 +3 2489 2692 2535 +3 2489 2713 2655 +3 2490 2609 2580 +3 2490 2616 2587 +3 2490 2688 2616 +3 2490 2801 2609 +3 2491 2653 2552 +3 2491 2701 2586 +3 2491 2714 2701 +3 2492 2663 2579 +3 2492 2737 2654 +3 2492 2753 2596 +3 2493 2592 2584 +3 2493 2643 2592 +3 2493 2734 2608 +3 2494 2617 2577 +3 2494 2676 2551 +3 2494 2705 2555 +3 2494 2757 2617 +3 2495 2594 2581 +3 2495 2647 2594 +3 2495 2746 2647 +3 2496 2706 2661 +3 2496 2719 2545 +3 2496 2755 2640 +3 2497 2638 2563 +3 2497 2700 2560 +3 2497 2722 2638 +3 2498 2756 2610 +3 2498 2763 2533 +3 2498 2778 2600 +3 2498 2803 2756 +3 2499 2652 2611 +3 2499 2695 2652 +3 2499 2712 2622 +3 2500 2708 2641 +3 2500 2741 2683 +3 2500 2743 2708 +3 2501 2688 2580 +3 2501 2746 2688 +3 2501 2774 2636 +3 2502 2597 2555 +3 2502 2726 2597 +3 2502 2747 2645 +3 2502 2772 2726 +3 2503 2619 2593 +3 2503 2777 2619 +3 2503 2780 2777 +3 2504 2752 2538 +3 2504 2758 2633 +3 2505 2770 2667 +3 2505 2776 2598 +3 2506 2660 2618 +3 2506 2677 2660 +3 2506 2767 2677 +3 2507 2629 2605 +3 2507 2678 2639 +3 2507 2717 2629 +3 2508 2749 2672 +3 2508 2799 2749 +3 2509 2744 2691 +3 2509 2754 2632 +3 2509 2784 2744 +3 2510 2686 2631 +3 2510 2693 2633 +3 2511 2651 2621 +3 2511 2695 2651 +3 2511 2723 2652 +3 2512 2724 2615 +3 2512 2788 2604 +3 2513 2716 2568 +3 2513 2735 2578 +3 2513 2751 2716 +3 2514 2682 2661 +3 2514 2706 2598 +3 2514 2735 2682 +3 2514 2776 2735 +3 2515 2727 2553 +3 2515 2779 2727 +3 2516 2602 2458 +3 2516 2666 2465 +3 2516 2727 2558 +3 2517 2626 2620 +3 2517 2649 2626 +3 2517 2741 2649 +3 2517 2775 2741 +3 2518 2670 2664 +3 2518 2683 2670 +3 2518 2745 2540 +3 2519 2733 2691 +3 2519 2771 2565 +3 2519 2798 2614 +3 2520 2574 2456 +3 2520 2685 2469 +3 2520 2718 2574 +3 2520 2787 2718 +3 2521 2637 2446 +3 2521 2648 2591 +3 2521 2766 2573 +3 2522 2667 2618 +3 2522 2704 2667 +3 2522 2725 2704 +3 2522 2790 2595 +3 2523 2671 2485 +3 2523 2716 2674 +3 2523 2729 2440 +3 2524 2656 2471 +3 2524 2739 2566 +3 2524 2748 2656 +3 2525 2561 2433 +3 2525 2666 2484 +3 2525 2736 2561 +3 2526 2585 2426 +3 2526 2781 2623 +3 2526 2794 2585 +3 2527 2646 2480 +3 2527 2709 2441 +3 2527 2773 2709 +3 2528 2659 2462 +3 2528 2715 264 +3 2528 2792 2659 +3 2529 2587 2425 +3 2529 2679 2475 +3 2529 2712 2461 +3 2530 2625 2468 +3 2530 2629 2436 +3 2530 2782 2625 +3 2531 2744 2460 +3 2531 2771 2691 +3 2532 2590 2453 +3 2532 2690 2590 +3 2532 2767 2690 +3 2533 2734 2584 +3 2533 2763 2734 +3 2533 2778 2498 +3 2533 2786 2534 +3 2534 2778 2533 +3 2534 2787 2469 +3 2535 2644 2488 +3 2535 2677 2444 +3 2535 2692 283 +3 2535 2698 2489 +3 2536 2595 2455 +3 2536 2599 2471 +3 2536 2732 2599 +3 2537 2650 2589 +3 2537 2680 2454 +3 2537 2797 2607 +3 2538 2614 2504 +3 2538 2722 2699 +3 2538 2733 2614 +3 2538 2752 2722 +3 2539 2668 2478 +3 2539 2796 2668 +3 2540 2616 2445 +3 2540 2683 2518 +3 2540 2743 2683 +3 2540 2745 2425 +3 2541 2634 2469 +3 2541 2658 248 +3 2541 2685 2456 +3 2542 2606 2447 +3 2542 2608 2457 +3 2542 2630 255 +3 2543 2665 270 +3 2543 2693 2665 +3 2543 2721 2487 +3 2544 2592 2467 +3 2544 2601 2450 +3 2544 2628 2435 +3 2544 2765 2628 +3 2545 2719 2468 +3 2545 2755 2496 +3 2545 2762 2755 +3 2546 2687 238 +3 2546 2697 2687 +3 2546 2802 2697 +3 2547 2696 2434 +3 2547 2750 2472 +3 2547 2795 2696 +3 2548 2603 2427 +3 2548 2620 2446 +3 2548 2728 2472 +3 2548 2775 2620 +3 2549 2612 2437 +3 2549 2651 2423 +3 2549 2738 2612 +3 2550 2612 2458 +3 2550 2689 2466 +3 2550 2764 2689 +3 2551 2676 273 +3 2551 2705 2494 +3 2552 2653 40 +3 2552 2713 2698 +3 2552 2714 2491 +3 2553 2727 2465 +3 2553 2759 2515 +3 2553 2789 2447 +3 2554 2575 2481 +3 2554 2621 2437 +3 2554 2675 2621 +3 2554 2730 2462 +3 2555 2597 2440 +3 2555 2705 2451 +3 2555 2747 2502 +3 2555 2757 2494 +3 2556 2664 2450 +3 2556 2710 2475 +3 2556 2745 2664 +3 2557 2658 2456 +3 2557 2804 247 +3 2558 2602 2516 +3 2558 2740 2602 +3 2558 2779 2740 +3 2559 2628 2472 +3 2559 2718 2432 +3 2559 2750 2434 +3 2559 2785 2435 +3 2560 2699 2497 +3 2560 2700 244 +3 2560 2754 2449 +3 2561 2601 2433 +3 2561 2710 2450 +3 2561 2736 2710 +3 2562 2593 2470 +3 2562 2635 2480 +3 2562 2761 2439 +3 2562 2781 2635 +3 2563 2638 2487 +3 2563 2700 2497 +3 2563 2707 13 +3 2564 2660 2488 +3 2564 2702 2536 +3 2564 2720 281 +3 2565 2636 2476 +3 2565 2771 2431 +3 2565 2798 2519 +3 2565 2800 2798 +3 2566 2673 2482 +3 2566 2739 277 +3 2566 2748 2524 +3 2567 2646 2454 +3 2567 2761 2480 +3 2567 2768 2439 +3 2568 2678 2428 +3 2568 2682 2513 +3 2568 2716 2523 +3 2569 2570 2459 +3 2569 2772 2429 +3 2569 2800 2476 +3 2570 2580 2436 +3 2570 2639 2459 +3 2570 2717 2639 +3 2571 2583 2474 +3 2571 2723 2464 +3 2571 2762 2438 +3 2572 2689 263 +3 2572 2715 2462 +3 2572 2730 2466 +3 2573 2604 2477 +3 2573 2637 2521 +3 2573 2766 235 +3 2574 2718 2434 +3 2574 2783 2456 +3 2574 2788 2783 +3 2575 2659 2441 +3 2575 2709 2481 +3 2576 2694 241 +3 2576 2749 2460 +3 2576 2784 2694 +3 2577 2617 2482 +3 2577 2673 275 +3 2577 2676 2494 +3 2578 2725 2471 +3 2578 2735 2424 +3 2578 2751 2513 +3 2579 2663 2463 +3 2579 2737 2492 +3 2579 2792 2528 +3 2580 2609 2436 +3 2580 2688 2490 +3 2580 2774 2501 +3 2581 2594 2460 +3 2581 2641 2495 +3 2581 2799 2442 +3 2582 2646 2527 +3 2582 2650 2454 +3 2582 2681 2650 +3 2583 2585 2474 +3 2583 2657 2426 +3 2584 2592 2435 +3 2584 2734 2493 +3 2584 2785 2432 +3 2584 2786 2533 +3 2585 2640 2474 +3 2585 2794 2640 +3 2586 2653 2491 +3 2586 2742 42 +3 2586 2796 2742 +3 2587 2616 2425 +3 2587 2801 2490 +3 2588 2627 2486 +3 2588 2642 2478 +3 2588 2731 45 +3 2588 2793 2642 +3 2589 2650 2479 +3 2589 2791 49 +3 2589 2797 2537 +3 2590 2690 2430 +3 2590 2780 2453 +3 2591 2648 2473 +3 2591 2703 237 +3 2591 2766 2521 +3 2592 2643 2467 +3 2593 2613 2503 +3 2593 2619 2470 +3 2594 2647 2431 +3 2594 2771 2531 +3 2595 2725 2522 +3 2595 2790 2455 +3 2596 2663 2492 +3 2596 2753 50 +3 2596 2791 2479 +3 2597 2671 2440 +3 2597 2726 2459 +3 2598 2623 2505 +3 2598 2706 2452 +3 2598 2776 2514 +3 2599 2732 279 +3 2599 2739 2524 +3 2600 2634 250 +3 2600 2778 2469 +3 2600 2803 2498 +3 2601 2624 2433 +3 2602 2669 2458 +3 2602 2740 260 +3 2603 2628 2483 +3 2603 2670 2427 +3 2604 2724 2512 +3 2604 2788 2477 +3 2605 2629 2468 +3 2605 2678 2507 +3 2605 2719 2428 +3 2606 2759 2447 +3 2606 2760 2759 +3 2607 2680 2537 +3 2607 2731 2486 +3 2607 2797 47 +3 2608 2643 2493 +3 2608 2734 2457 +3 2609 2782 2530 +3 2609 2801 2461 +3 2610 2630 2457 +3 2610 2756 253 +3 2610 2763 2498 +3 2611 2652 2438 +3 2611 2712 2499 +3 2611 2782 2461 +3 2612 2738 2458 +3 2613 2627 2478 +3 2613 2780 2503 +3 2614 2645 2504 +3 2614 2733 2519 +3 2614 2798 2429 +3 2615 2724 232 +3 2615 2783 2512 +3 2615 2804 2557 +3 2616 2688 2445 +3 2617 2729 2482 +3 2617 2757 2440 +3 2618 2667 2430 +3 2618 2690 2506 +3 2618 2790 2522 +3 2619 2770 2470 +3 2619 2777 2430 +3 2620 2626 2473 +3 2620 2648 2446 +3 2620 2775 2517 +3 2621 2651 2437 +3 2621 2675 2464 +3 2621 2723 2511 +3 2622 2695 2499 +3 2622 2712 2529 +3 2622 2736 2423 +3 2623 2770 2505 +3 2623 2781 2470 +3 2623 2794 2526 +3 2624 2789 2553 +3 2625 2762 2545 +3 2625 2782 2611 +3 2626 2649 2442 +3 2626 2802 2473 +3 2627 2768 2486 +3 2628 2765 2483 +3 2629 2717 2436 +3 2631 2665 2510 +3 2631 2686 2551 +3 2632 2694 2509 +3 2632 2754 2560 +3 2633 2686 2510 +3 2633 2693 2443 +3 2633 2752 2504 +3 2633 2758 2686 +3 2635 2684 2480 +3 2635 2781 2526 +3 2636 2647 2501 +3 2636 2774 2476 +3 2637 2795 2446 +3 2638 2693 2543 +3 2638 2722 2443 +3 2639 2671 2459 +3 2639 2678 2485 +3 2639 2717 2507 +3 2640 2706 2496 +3 2640 2755 2474 +3 2640 2794 2452 +3 2641 2649 2500 +3 2641 2708 2495 +3 2642 2742 2539 +3 2642 2793 44 +3 2643 2789 2467 +3 2644 2720 2488 +3 2645 2747 2504 +3 2645 2772 2502 +3 2647 2746 2501 +3 2649 2741 2500 +3 2650 2681 2479 +3 2651 2695 2423 +3 2652 2695 2511 +3 2652 2723 2571 +3 2654 2737 267 +3 2654 2753 2492 +3 2655 2692 2489 +3 2655 2713 38 +3 2656 2748 2448 +3 2656 2751 2578 +3 2657 2675 2481 +3 2657 2773 2426 +3 2659 2792 2463 +3 2660 2677 2488 +3 2660 2790 2618 +3 2661 2682 2428 +3 2661 2706 2514 +3 2661 2719 2496 +3 2662 2707 2487 +3 2662 2721 268 +3 2662 2769 246 +3 2663 2681 2463 +3 2664 2670 2483 +3 2664 2745 2518 +3 2664 2765 2450 +3 2665 2693 2510 +3 2667 2704 2505 +3 2667 2770 2430 +3 2668 2780 2613 +3 2668 2796 2453 +3 2669 2764 2550 +3 2670 2683 2427 +3 2672 2687 2508 +3 2672 2749 2576 +3 2674 2716 2448 +3 2674 2729 2523 +3 2674 2748 2566 +3 2677 2767 2444 +3 2679 2745 2556 +3 2680 2768 2567 +3 2682 2735 2513 +3 2683 2741 2427 +3 2683 2743 2500 +3 2684 2773 2527 +3 2686 2705 2551 +3 2686 2758 2451 +3 2687 2697 2508 +3 2688 2746 2445 +3 2689 2764 262 +3 2690 2767 2506 +3 2691 2733 2449 +3 2691 2744 2531 +3 2691 2754 2509 +3 2691 2771 2519 +3 2694 2784 2509 +3 2696 2788 2574 +3 2696 2795 2477 +3 2697 2799 2508 +3 2697 2802 2626 +3 2698 2713 2489 +3 2698 2714 2552 +3 2699 2722 2497 +3 2699 2733 2538 +3 2701 2714 2532 +3 2701 2796 2586 +3 2702 2732 2536 +3 2703 2802 2546 +3 2704 2725 2424 +3 2704 2776 2505 +3 2708 2743 2445 +3 2708 2746 2495 +3 2709 2773 2481 +3 2710 2736 2475 +3 2711 2736 2525 +3 2711 2738 2549 +3 2714 2767 2532 +3 2716 2751 2448 +3 2718 2787 2432 +3 2722 2752 2443 +3 2726 2772 2569 +3 2727 2779 2558 +3 2728 2795 2547 +3 2734 2763 2457 +3 2735 2776 2424 +3 2740 2779 259 +3 2741 2775 2427 +3 2742 2796 2539 +3 2744 2784 2460 +3 2747 2758 2504 +3 2749 2799 2581 +3 2755 2762 2474 +3 2756 2803 252 +3 2759 2760 2515 +3 2760 2779 2515 +3 2777 2780 2590 +3 2783 2788 2512 +3 2786 2787 2534 +3 2798 2800 2429 +3 2805 3035 2830 +3 2805 3077 3035 +3 2805 3127 2837 +3 2805 3134 2976 +3 2806 3049 2973 +3 2806 3087 2924 +3 2806 3163 3049 +3 2807 3005 2918 +3 2807 3100 2811 +3 2807 3116 3100 +3 2808 3147 3045 +3 2808 3169 2997 +3 2808 3197 3051 +3 2809 3092 3018 +3 2809 3136 2992 +3 2809 3196 3092 +3 2809 3208 3075 +3 2810 3096 3019 +3 2810 3148 2940 +3 2810 3167 3148 +3 2810 3172 3096 +3 2811 3005 2807 +3 2811 3132 2972 +3 2811 3162 3005 +3 2812 3070 2975 +3 2812 3082 2967 +3 2813 2941 2822 +3 2813 3024 2941 +3 2813 3089 2999 +3 2813 3139 3089 +3 2814 3032 2953 +3 2814 3083 3032 +3 2814 3186 2993 +3 2815 3093 2970 +3 2815 3105 3093 +3 2815 3166 3105 +3 2816 3194 2979 +3 2816 3198 2968 +3 2817 2986 2917 +3 2817 3117 2986 +3 2817 3140 3117 +3 2818 2982 2915 +3 2818 2994 2931 +3 2818 3203 2982 +3 2818 3209 3038 +3 2819 3010 2946 +3 2819 3042 3030 +3 2819 3066 3010 +3 2820 3036 2964 +3 2820 3112 2984 +3 2820 3202 3007 +3 2821 3022 2965 +3 2821 3025 2950 +3 2821 3074 2956 +3 2821 3095 3025 +3 2822 2941 2871 +3 2822 3139 2813 +3 2823 3062 2919 +3 2823 3071 2977 +3 2823 3146 3012 +3 2823 3159 3062 +3 2824 3115 2971 +3 2824 3128 2929 +3 2824 3204 3091 +3 2825 3081 2934 +3 2825 3191 2939 +3 2826 3044 2983 +3 2826 3114 2987 +3 2826 3125 3028 +3 2827 3027 2978 +3 2827 3040 2963 +3 2827 3090 3040 +3 2827 3113 2958 +3 2828 3079 2943 +3 2828 3149 3026 +3 2829 3143 3118 +3 2829 3144 2944 +3 2830 3127 2805 +3 2830 3143 3127 +3 2831 3160 3056 +3 2831 3181 3013 +3 2831 3210 3181 +3 2832 2945 2932 +3 2832 3046 2945 +3 2832 3058 2934 +3 2833 3024 2999 +3 2833 3137 3024 +3 2833 3175 3082 +3 2834 3059 2924 +3 2834 3072 3059 +3 2834 3153 3072 +3 2835 3047 2887 +3 2835 3094 2948 +3 2835 3165 2939 +3 2836 3120 2976 +3 2836 3171 3120 +3 2836 3195 3110 +3 2837 3127 2944 +3 2837 3134 2805 +3 2838 2980 2906 +3 2838 3078 2917 +3 2838 3156 3078 +3 2839 3001 2916 +3 2839 3145 3065 +3 2839 3168 2921 +3 2840 3097 2924 +3 2840 3154 2925 +3 2840 3157 3097 +3 2841 3002 2935 +3 2841 3060 2923 +3 2841 3107 3006 +3 2841 3158 3002 +3 2842 3176 2953 +3 2843 3069 2942 +3 2843 3098 2950 +3 2843 3199 3013 +3 2844 3120 2912 +3 2844 3126 2908 +3 2844 3187 2951 +3 2845 3032 2946 +3 2845 3104 2936 +3 2845 3123 2953 +3 2846 3030 2971 +3 2846 3066 3030 +3 2846 3115 2959 +3 2846 3151 3066 +3 2847 2990 2975 +3 2847 3095 2956 +3 2847 3155 3095 +3 2847 3177 3155 +3 2848 3034 2970 +3 2848 3164 2982 +3 2848 3173 2940 +3 2849 2980 2917 +3 2849 3124 2980 +3 2849 3205 2972 +3 2850 3023 2918 +3 2850 3090 2958 +3 2850 3182 2965 +3 2850 3188 3023 +3 2851 3070 2967 +3 2851 3184 2962 +3 2851 3201 3070 +3 2852 2996 2905 +3 2852 3003 2955 +3 2852 3112 3003 +3 2853 3004 2981 +3 2853 3138 3004 +3 2853 3204 3036 +3 2854 2977 2933 +3 2854 2988 2920 +3 2854 2998 2957 +3 2854 3146 2977 +3 2855 3040 2918 +3 2855 3044 2963 +3 2855 3178 2983 +3 2856 3034 2911 +3 2856 3060 3006 +3 2856 3131 2970 +3 2857 3089 3047 +3 2857 3103 2968 +3 2857 3191 3103 +3 2858 3121 3094 +3 2858 3200 2954 +3 2859 2964 2929 +3 2859 3009 2943 +3 2859 3052 2964 +3 2859 3196 2992 +3 2860 3079 2904 +3 2860 3088 2910 +3 2860 3202 2943 +3 2861 3000 2961 +3 2861 3001 2921 +3 2861 3149 3001 +3 2862 2966 2939 +3 2862 3063 2949 +3 2862 3141 3063 +3 2862 3165 2948 +3 2863 2990 2956 +3 2863 3015 2990 +3 2863 3051 3015 +3 2863 3147 3051 +3 2864 2985 2969 +3 2864 3054 2937 +3 2864 3065 2985 +3 2865 2922 2919 +3 2865 3124 2972 +3 2865 3132 2922 +3 2866 3027 2963 +3 2866 3028 3019 +3 2866 3044 3028 +3 2866 3096 3027 +3 2867 3048 2933 +3 2867 3056 2928 +3 2867 3071 3056 +3 2867 3130 3048 +3 2868 3053 2974 +3 2868 3133 2930 +3 2868 3161 3014 +3 2869 3075 2931 +3 2869 3087 2973 +3 2870 2991 2927 +3 2870 3107 2935 +3 2870 3110 2991 +3 2871 2951 2822 +3 2871 3126 2951 +3 2872 3084 2941 +3 2872 3137 2997 +3 2872 3169 2913 +3 2873 3029 2946 +3 2873 3038 3029 +3 2873 3083 2911 +3 2873 3203 3038 +3 2874 2966 2949 +3 2874 3081 2966 +3 2874 3174 2945 +3 2875 3042 3018 +3 2875 3092 2929 +3 2875 3128 2971 +3 2876 3025 3017 +3 2876 3067 2942 +3 2876 3069 2950 +3 2877 3009 2992 +3 2877 3050 3009 +3 2877 3136 2973 +3 2878 3086 2986 +3 2878 3117 2925 +3 2878 3180 3086 +3 2879 3012 2920 +3 2879 3057 3033 +3 2879 3080 2906 +3 2879 3159 3012 +3 2880 3021 2974 +3 2880 3053 2953 +3 2880 3123 3021 +3 2881 3020 3016 +3 2881 3104 3010 +3 2881 3151 3020 +3 2882 2989 2969 +3 2882 3156 3039 +3 2882 3183 2989 +3 2883 3113 2978 +3 2883 3119 3045 +3 2883 3144 3118 +3 2884 3031 2944 +3 2884 3064 2940 +3 2884 3105 3031 +3 2885 3058 2960 +3 2885 3068 2962 +3 2885 3184 2979 +3 2886 3042 3029 +3 2886 3208 3018 +3 2886 3209 3208 +3 2887 3094 2835 +3 2887 3200 3094 +3 2888 3125 3059 +3 2888 3167 3019 +3 2889 3111 2930 +3 2889 3129 3002 +3 2889 3158 3111 +3 2890 3022 2950 +3 2890 3116 3023 +3 2890 3188 3022 +3 2891 3091 2981 +3 2891 3115 3091 +3 2891 3150 3037 +3 2892 3134 3031 +3 2892 3166 2991 +3 2892 3195 2976 +3 2893 3109 2952 +3 2893 3177 2975 +3 2893 3201 2995 +3 2894 3074 2965 +3 2894 3147 3074 +3 2894 3182 2958 +3 2895 3144 2978 +3 2895 3172 2944 +3 2896 3140 2985 +3 2896 3145 2916 +3 2896 3157 2925 +3 2897 3050 3049 +3 2897 3149 3050 +3 2897 3163 3001 +3 2898 3082 3015 +3 2898 3137 3082 +3 2898 3197 2997 +3 2899 2954 2951 +3 2899 3055 2954 +3 2899 3102 257 +3 2899 3187 3102 +3 2900 3160 3013 +3 2900 3199 3041 +3 2901 3178 3162 +3 2901 3180 2983 +3 2901 3205 3086 +3 2902 3085 3017 +3 2902 3155 3085 +3 2903 3164 3148 +3 2903 3167 3072 +3 2904 3008 2860 +3 2904 3026 2961 +3 2904 3079 3026 +3 2904 3142 3008 +3 2905 2984 2852 +3 2905 3138 2984 +3 2905 3179 3004 +3 2906 3080 2838 +3 2906 3124 3062 +3 2906 3159 2879 +3 2907 3098 3013 +3 2907 3116 3098 +3 2907 3181 3100 +3 2908 3077 2976 +3 2908 3120 2844 +3 2908 3126 3077 +3 2909 3175 2968 +3 2909 3198 2967 +3 2910 3007 2860 +3 2910 3088 283 +3 2910 3112 3007 +3 2911 2993 2856 +3 2911 3034 2982 +3 2911 3083 2993 +3 2911 3203 2873 +3 2912 3011 2844 +3 2912 3171 3108 +3 2912 3193 3011 +3 2913 3084 2872 +3 2913 3119 3118 +3 2913 3143 3084 +3 2913 3169 3119 +3 2914 3122 3059 +3 2914 3125 2987 +3 2914 3154 3122 +3 2915 2994 2818 +3 2915 3152 2994 +3 2915 3153 3152 +3 2915 3164 3153 +3 2916 3145 2839 +3 2916 3157 2896 +3 2916 3163 3097 +3 2917 2969 2817 +3 2917 2980 2838 +3 2917 2986 2849 +3 2917 3078 2969 +3 2918 3005 2855 +3 2918 3023 2807 +3 2918 3090 2850 +3 2919 3062 2865 +3 2919 3071 2823 +3 2919 3210 3056 +3 2920 2988 270 +3 2920 3057 2879 +3 2920 3146 2854 +3 2921 3000 2861 +3 2921 3001 2839 +3 2921 3170 278 +3 2922 3132 3100 +3 2922 3210 2919 +3 2923 3158 2841 +3 2923 3176 3111 +3 2923 3186 3176 +3 2924 3076 2834 +3 2924 3087 3076 +3 2924 3097 2806 +3 2924 3122 2840 +3 2925 2987 2878 +3 2925 3140 2896 +3 2925 3154 2987 +3 2925 3157 2840 +3 2926 3106 2948 +3 2926 3121 255 +3 2927 3107 2870 +3 2927 3131 3006 +3 2927 3166 3131 +3 2928 3101 73 +3 2928 3130 2867 +3 2928 3160 3101 +3 2929 2964 2824 +3 2929 3128 2875 +3 2929 3196 2859 +3 2930 3053 2868 +3 2930 3111 3053 +3 2930 3129 2889 +3 2930 3133 266 +3 2931 2994 2869 +3 2931 3209 2818 +3 2932 2960 2832 +3 2932 3135 247 +3 2932 3207 2960 +3 2933 2977 2867 +3 2933 2998 2854 +3 2933 3048 71 +3 2934 3046 2832 +3 2934 3081 3046 +3 2934 3103 2825 +3 2934 3194 3103 +3 2935 3002 263 +3 2935 3043 2870 +3 2935 3099 3043 +3 2935 3107 2841 +3 2936 3016 290 +3 2936 3104 3016 +3 2936 3123 2845 +3 2937 3054 276 +3 2937 3065 2864 +3 2937 3168 3065 +3 2937 3170 3168 +3 2938 3033 272 +3 2938 3080 3033 +3 2938 3156 3080 +3 2939 2966 2825 +3 2939 3047 2835 +3 2939 3165 2862 +3 2939 3191 3047 +3 2940 3064 2810 +3 2940 3093 2884 +3 2940 3148 2848 +3 2940 3173 3093 +3 2941 3024 2872 +3 2941 3035 2871 +3 2941 3084 3035 +3 2942 3067 76 +3 2942 3069 2876 +3 2942 3199 2843 +3 2943 3009 2828 +3 2943 3052 2859 +3 2943 3079 2860 +3 2943 3202 3052 +3 2944 3031 2837 +3 2944 3064 2884 +3 2944 3127 2829 +3 2944 3144 2895 +3 2944 3172 3064 +3 2945 3046 2874 +3 2945 3135 2932 +3 2945 3174 248 +3 2946 3010 2845 +3 2946 3029 2819 +3 2946 3032 2873 +3 2947 3043 261 +3 2947 3110 3043 +3 2947 3171 3110 +3 2948 3094 2926 +3 2948 3141 2862 +3 2948 3165 2835 +3 2949 2966 2862 +3 2949 3063 251 +3 2949 3073 2874 +3 2950 3022 2821 +3 2950 3025 2876 +3 2950 3069 2843 +3 2950 3098 2890 +3 2951 2954 2822 +3 2951 3126 2844 +3 2951 3187 2899 +3 2952 3109 80 +3 2952 3177 2893 +3 2953 3032 2845 +3 2953 3053 2842 +3 2953 3123 2880 +3 2953 3176 2814 +3 2954 3055 2858 +3 2954 3139 2822 +3 2954 3200 3139 +3 2955 2996 2852 +3 2955 3190 2996 +3 2955 3192 3061 +3 2956 2990 2847 +3 2956 3074 2863 +3 2956 3095 2821 +3 2957 2988 2854 +3 2957 3189 268 +3 2958 3045 2894 +3 2958 3090 2827 +3 2958 3113 3045 +3 2958 3182 2850 +3 2959 3037 293 +3 2959 3115 3037 +3 2959 3151 2846 +3 2960 3058 2832 +3 2960 3068 2885 +3 2960 3207 84 +3 2961 3000 279 +3 2961 3026 2861 +3 2961 3142 2904 +3 2962 2995 2851 +3 2962 3068 83 +3 2962 3184 2885 +3 2963 3027 2827 +3 2963 3040 2855 +3 2963 3044 2866 +3 2964 3052 2820 +3 2964 3204 2824 +3 2965 3022 2850 +3 2965 3074 2821 +3 2965 3182 2894 +3 2966 3081 2825 +3 2967 2979 2851 +3 2967 3070 2812 +3 2967 3082 2909 +3 2967 3198 2979 +3 2968 2999 2857 +3 2968 3103 2816 +3 2968 3175 2999 +3 2968 3198 2909 +3 2969 2985 2817 +3 2969 2989 2864 +3 2969 3078 2882 +3 2970 3034 2856 +3 2970 3131 2815 +3 2970 3173 2848 +3 2971 3030 2875 +3 2971 3115 2846 +3 2971 3128 2824 +3 2972 3124 2849 +3 2972 3132 2865 +3 2972 3162 2811 +3 2972 3205 3162 +3 2973 3049 2877 +3 2973 3075 2869 +3 2973 3087 2806 +3 2973 3136 3075 +3 2974 3021 288 +3 2974 3053 2880 +3 2974 3161 2868 +3 2975 2990 2812 +3 2975 3177 2847 +3 2975 3201 2893 +3 2976 3077 2805 +3 2976 3120 2908 +3 2976 3134 2892 +3 2976 3195 2836 +3 2977 3071 2867 +3 2977 3146 2823 +3 2978 3027 2895 +3 2978 3113 2827 +3 2978 3144 2883 +3 2979 3058 2885 +3 2979 3184 2851 +3 2979 3194 3058 +3 2979 3198 2816 +3 2980 3124 2906 +3 2981 3004 295 +3 2981 3091 2853 +3 2981 3150 2891 +3 2982 3034 2848 +3 2982 3164 2915 +3 2982 3203 2911 +3 2983 3044 2855 +3 2983 3114 2826 +3 2983 3178 2901 +3 2983 3180 3114 +3 2984 3036 2820 +3 2984 3112 2852 +3 2984 3138 3036 +3 2985 3140 2817 +3 2985 3145 2896 +3 2986 3086 2849 +3 2986 3117 2878 +3 2987 3114 2878 +3 2987 3125 2826 +3 2987 3154 2914 +3 2989 3054 2864 +3 2989 3183 275 +3 2990 3015 2812 +3 2991 3166 2927 +3 2991 3195 2892 +3 2992 3009 2859 +3 2992 3136 2877 +3 2992 3196 2809 +3 2993 3060 2856 +3 2993 3083 2814 +3 2993 3186 3060 +3 2994 3076 2869 +3 2994 3152 3076 +3 2995 3109 2893 +3 2995 3201 2851 +3 2996 3179 2905 +3 2996 3190 298 +3 2997 3137 2898 +3 2997 3169 2872 +3 2997 3197 2808 +3 2998 3185 2957 +3 2999 3024 2813 +3 2999 3089 2857 +3 2999 3175 2833 +3 3001 3149 2897 +3 3001 3163 2916 +3 3002 3129 264 +3 3002 3158 2889 +3 3003 3112 2910 +3 3003 3192 2955 +3 3004 3138 2905 +3 3004 3179 296 +3 3005 3178 2855 +3 3006 3060 2841 +3 3006 3107 2927 +3 3006 3131 2856 +3 3007 3112 2820 +3 3007 3202 2860 +3 3008 3088 2860 +3 3008 3142 281 +3 3009 3050 2828 +3 3010 3066 2881 +3 3010 3104 2845 +3 3011 3187 2844 +3 3011 3193 259 +3 3012 3146 2920 +3 3012 3159 2823 +3 3013 3098 2843 +3 3013 3160 2831 +3 3013 3181 2907 +3 3013 3199 2900 +3 3014 3133 2868 +3 3014 3161 286 +3 3015 3051 2898 +3 3015 3082 2812 +3 3016 3020 291 +3 3016 3104 2881 +3 3017 3025 2902 +3 3017 3067 2876 +3 3017 3085 78 +3 3018 3042 2886 +3 3018 3092 2875 +3 3018 3208 2809 +3 3019 3028 2888 +3 3019 3096 2866 +3 3019 3167 2810 +3 3020 3151 2959 +3 3021 3123 2936 +3 3022 3188 2850 +3 3023 3116 2807 +3 3023 3188 2890 +3 3024 3137 2872 +3 3025 3095 2902 +3 3026 3079 2828 +3 3026 3149 2861 +3 3027 3096 2895 +3 3028 3044 2826 +3 3028 3125 2888 +3 3029 3038 2886 +3 3029 3042 2819 +3 3030 3042 2875 +3 3030 3066 2819 +3 3031 3105 2892 +3 3031 3134 2837 +3 3032 3083 2873 +3 3033 3057 271 +3 3033 3080 2879 +3 3035 3077 2871 +3 3035 3084 2830 +3 3036 3138 2853 +3 3036 3204 2964 +3 3037 3115 2891 +3 3037 3150 294 +3 3038 3203 2818 +3 3038 3209 2886 +3 3039 3156 2938 +3 3039 3183 2882 +3 3040 3090 2918 +3 3041 3101 2900 +3 3041 3199 2942 +3 3043 3099 262 +3 3043 3110 2870 +3 3045 3113 2883 +3 3045 3119 2808 +3 3045 3147 2894 +3 3046 3081 2874 +3 3047 3089 2887 +3 3047 3191 2857 +3 3048 3130 72 +3 3049 3050 2877 +3 3049 3163 2897 +3 3050 3149 2828 +3 3051 3147 2808 +3 3051 3197 2898 +3 3052 3202 2820 +3 3053 3111 2842 +3 3055 3121 2858 +3 3056 3071 2919 +3 3056 3160 2928 +3 3056 3210 2831 +3 3058 3194 2934 +3 3059 3072 2888 +3 3059 3122 2924 +3 3059 3125 2914 +3 3060 3186 2923 +3 3061 3190 2955 +3 3061 3192 285 +3 3062 3124 2865 +3 3062 3159 2906 +3 3063 3141 252 +3 3064 3172 2810 +3 3065 3145 2985 +3 3065 3168 2839 +3 3066 3151 2881 +3 3070 3201 2975 +3 3072 3153 2903 +3 3072 3167 2888 +3 3073 3174 2874 +3 3074 3147 2863 +3 3075 3136 2809 +3 3075 3208 2931 +3 3076 3087 2869 +3 3076 3152 2834 +3 3077 3126 2871 +3 3078 3156 2882 +3 3080 3156 2838 +3 3082 3137 2833 +3 3082 3175 2909 +3 3084 3143 2830 +3 3085 3155 2952 +3 3086 3180 2901 +3 3086 3205 2849 +3 3089 3139 2887 +3 3091 3115 2824 +3 3091 3204 2853 +3 3092 3196 2929 +3 3093 3105 2884 +3 3093 3173 2970 +3 3094 3121 2926 +3 3094 3200 2858 +3 3095 3155 2902 +3 3096 3172 2895 +3 3097 3157 2916 +3 3097 3163 2806 +3 3098 3116 2890 +3 3100 3116 2907 +3 3100 3132 2811 +3 3100 3181 2922 +3 3101 3160 2900 +3 3102 3187 3011 +3 3103 3191 2825 +3 3103 3194 2816 +3 3105 3166 2892 +3 3106 3141 2948 +3 3108 3171 2947 +3 3108 3193 2912 +3 3110 3171 2836 +3 3110 3195 2991 +3 3111 3158 2923 +3 3111 3176 2842 +3 3114 3180 2878 +3 3117 3140 2925 +3 3118 3119 2883 +3 3118 3143 2913 +3 3118 3144 2829 +3 3119 3169 2808 +3 3120 3171 2912 +3 3122 3154 2840 +3 3127 3143 2829 +3 3131 3166 2815 +3 3139 3200 2887 +3 3148 3164 2848 +3 3148 3167 2903 +3 3152 3153 2834 +3 3153 3164 2903 +3 3155 3177 2952 +3 3162 3178 3005 +3 3162 3205 2901 +3 3168 3170 2921 +3 3176 3186 2814 +3 3181 3210 2922 +3 3185 3189 2957 +3 3206 3207 2932 +3 3208 3209 2931 +3 3211 3314 3290 +3 3211 3315 3285 +3 3211 3358 3315 +3 3212 3313 3284 +3 3212 3318 3291 +3 3212 3354 3313 +3 3213 3283 3271 +3 3213 3289 3266 +3 3213 3371 3265 +3 3214 3286 3264 +3 3214 3296 3276 +3 3214 3372 3288 +3 3214 3373 3263 +3 3215 3331 3274 +3 3215 3333 3292 +3 3215 3361 3312 +3 3215 3366 3333 +3 3216 3356 3293 +3 3216 3365 3311 +3 3217 3357 3294 +3 3217 3368 3310 +3 3218 3332 3275 +3 3218 3336 3295 +3 3218 3362 3309 +3 3218 3367 3336 +3 3219 3323 3319 +3 3219 3352 3265 +3 3220 3324 3264 +3 3220 3328 3320 +3 3220 3353 3328 +3 3221 3316 3256 +3 3221 3329 3316 +3 3221 3338 3266 +3 3221 3355 3329 +3 3222 3337 3255 +3 3222 3347 3263 +3 3223 3359 3274 +3 3223 3364 3272 +3 3223 3369 3364 +3 3224 3360 3273 +3 3224 3363 3275 +3 3224 3370 3258 +3 3225 3276 3271 +3 3225 3283 3249 +3 3225 3285 3248 +3 3225 3286 3276 +3 3226 3284 3247 +3 3226 3289 3271 +3 3226 3296 3250 +3 3227 3287 3278 +3 3227 3371 3287 +3 3228 3308 3277 +3 3228 3324 3308 +3 3228 3372 3324 +3 3229 3342 3306 +3 3229 3344 3267 +3 3229 3368 3342 +3 3230 3309 3268 +3 3230 3343 3305 +3 3230 3367 3309 +3 3231 3312 3269 +3 3231 3346 3304 +3 3231 3366 3312 +3 3232 3339 3303 +3 3232 3345 3270 +3 3232 3365 3339 +3 3233 3301 3260 +3 3233 3319 3279 +3 3233 3327 3319 +3 3233 3334 3293 +3 3234 3302 3280 +3 3234 3328 3292 +3 3234 3333 3259 +3 3235 3299 3282 +3 3235 3329 3295 +3 3235 3336 3261 +3 3236 3300 3262 +3 3236 3317 3281 +3 3236 3330 3317 +3 3236 3335 3294 +3 3237 3288 3277 +3 3237 3321 3255 +3 3237 3373 3288 +3 3238 3287 3266 +3 3238 3322 3278 +3 3238 3338 3256 +3 3239 3327 3293 +3 3239 3352 3327 +3 3239 3356 3290 +3 3240 3331 3292 +3 3240 3353 3315 +3 3240 3358 3331 +3 3241 3332 3295 +3 3241 3354 3332 +3 3241 3355 3313 +3 3242 3330 3294 +3 3242 3347 3330 +3 3242 3357 3291 +3 3243 3348 3269 +3 3243 3359 3298 +3 3243 3361 3359 +3 3244 3311 3270 +3 3244 3325 3311 +3 3244 3349 3272 +3 3244 3364 3325 +3 3245 3310 3267 +3 3245 3326 3310 +3 3245 3350 3297 +3 3245 3360 3326 +3 3246 3351 3268 +3 3246 3363 3273 +3 3247 3289 3226 +3 3247 3355 3266 +3 3248 3286 3225 +3 3248 3353 3264 +3 3249 3283 3265 +3 3249 3285 3225 +3 3249 3314 3285 +3 3249 3352 3314 +3 3250 3284 3226 +3 3250 3296 3263 +3 3250 3318 3284 +3 3250 3347 3318 +3 3251 3358 3290 +3 3251 3369 3274 +3 3252 3354 3291 +3 3252 3370 3275 +3 3253 3307 305 +3 3253 3323 3307 +3 3254 3280 290 +3 3254 3320 3280 +3 3254 3324 3320 +3 3255 3317 3222 +3 3255 3321 294 +3 3255 3337 3237 +3 3256 3282 309 +3 3256 3316 3282 +3 3256 3322 3238 +3 3256 3338 3221 +3 3257 3356 3325 +3 3257 3369 3290 +3 3258 3326 3224 +3 3258 3357 3326 +3 3258 3370 3291 +3 3259 3302 3234 +3 3259 3340 288 +3 3259 3366 3340 +3 3260 3301 302 +3 3260 3334 3233 +3 3260 3365 3334 +3 3261 3299 3235 +3 3261 3341 311 +3 3261 3367 3341 +3 3262 3300 297 +3 3262 3335 3236 +3 3262 3368 3335 +3 3263 3296 3214 +3 3263 3337 3222 +3 3263 3347 3250 +3 3263 3373 3337 +3 3264 3286 3248 +3 3264 3353 3220 +3 3264 3372 3214 +3 3265 3283 3213 +3 3265 3323 3219 +3 3265 3352 3249 +3 3265 3371 3323 +3 3266 3287 3213 +3 3266 3289 3247 +3 3266 3338 3238 +3 3266 3355 3221 +3 3267 3310 3229 +3 3267 3344 35 +3 3267 3350 3245 +3 3268 3309 3246 +3 3268 3343 3230 +3 3268 3351 30 +3 3269 3312 3243 +3 3269 3346 3231 +3 3269 3348 58 +3 3270 3311 3232 +3 3270 3345 53 +3 3270 3349 3244 +3 3271 3276 3226 +3 3271 3283 3225 +3 3271 3289 3213 +3 3272 3349 55 +3 3272 3359 3223 +3 3272 3364 3244 +3 3273 3297 32 +3 3273 3351 3246 +3 3273 3360 3297 +3 3273 3363 3224 +3 3274 3331 3251 +3 3274 3361 3215 +3 3274 3369 3223 +3 3275 3332 3252 +3 3275 3362 3218 +3 3275 3363 3362 +3 3275 3370 3224 +3 3276 3286 3214 +3 3276 3296 3226 +3 3277 3288 3228 +3 3277 3308 292 +3 3277 3321 3237 +3 3278 3287 3238 +3 3278 3307 3227 +3 3278 3322 307 +3 3279 3301 3233 +3 3279 3319 3253 +3 3280 3302 289 +3 3280 3320 3234 +3 3281 3300 3236 +3 3281 3317 3255 +3 3282 3299 310 +3 3282 3316 3235 +3 3284 3313 3247 +3 3284 3318 3212 +3 3285 3314 3211 +3 3285 3315 3248 +3 3287 3371 3213 +3 3288 3372 3228 +3 3288 3373 3214 +3 3290 3314 3239 +3 3290 3356 3257 +3 3290 3358 3211 +3 3290 3369 3251 +3 3291 3318 3242 +3 3291 3354 3212 +3 3291 3357 3258 +3 3291 3370 3252 +3 3292 3328 3240 +3 3292 3331 3215 +3 3292 3333 3234 +3 3293 3327 3233 +3 3293 3334 3216 +3 3293 3356 3239 +3 3294 3330 3236 +3 3294 3335 3217 +3 3294 3357 3242 +3 3295 3329 3241 +3 3295 3332 3218 +3 3295 3336 3235 +3 3297 3350 33 +3 3297 3360 3245 +3 3298 3348 3243 +3 3298 3359 3272 +3 3303 3339 300 +3 3303 3345 3232 +3 3304 3340 3231 +3 3304 3346 60 +3 3305 3341 3230 +3 3305 3343 28 +3 3306 3342 299 +3 3306 3344 3229 +3 3307 3323 3227 +3 3308 3324 3254 +3 3309 3362 3246 +3 3309 3367 3218 +3 3310 3326 3217 +3 3310 3368 3229 +3 3311 3325 3216 +3 3311 3365 3232 +3 3312 3361 3243 +3 3312 3366 3215 +3 3313 3354 3241 +3 3313 3355 3247 +3 3314 3352 3239 +3 3315 3353 3248 +3 3315 3358 3240 +3 3316 3329 3235 +3 3317 3330 3222 +3 3318 3347 3242 +3 3319 3323 3253 +3 3319 3327 3219 +3 3320 3324 3220 +3 3320 3328 3234 +3 3323 3371 3227 +3 3324 3372 3264 +3 3325 3356 3216 +3 3325 3364 3257 +3 3326 3357 3217 +3 3326 3360 3224 +3 3327 3352 3219 +3 3328 3353 3240 +3 3329 3355 3241 +3 3330 3347 3222 +3 3331 3358 3251 +3 3332 3354 3252 +3 3333 3366 3259 +3 3334 3365 3216 +3 3335 3368 3217 +3 3336 3367 3261 +3 3337 3373 3237 +3 3339 3365 3260 +3 3340 3366 3231 +3 3341 3367 3230 +3 3342 3368 3262 +3 3359 3361 3274 +3 3362 3363 3246 +3 3364 3369 3257 +3 3374 3436 3397 +3 3374 3439 3436 +3 3374 3450 3439 +3 3375 3421 3415 +3 3375 3449 3416 +3 3376 3422 3413 +3 3376 3429 3414 +3 3376 3430 3429 +3 3377 3405 3397 +3 3377 3438 3405 +3 3377 3452 3438 +3 3377 3457 3410 +3 3378 3409 3396 +3 3378 3451 3409 +3 3379 3403 3401 +3 3379 3444 3414 +3 3379 3447 3444 +3 3379 3453 3403 +3 3380 3446 3402 +3 3380 3454 3413 +3 3381 3407 3391 +3 3381 3411 3407 +3 3381 3415 3409 +3 3381 3455 3411 +3 3382 3416 3392 +3 3382 3456 3410 +3 3383 3433 3419 +3 3383 3447 3401 +3 3384 3434 3402 +3 3384 3438 3420 +3 3384 3446 3438 +3 3385 3429 3417 +3 3385 3431 3403 +3 3385 3453 3414 +3 3386 3430 3413 +3 3386 3432 3418 +3 3386 3454 3404 +3 3387 3416 3410 +3 3387 3421 3416 +3 3387 3436 3421 +3 3387 3457 3436 +3 3388 3439 3409 +3 3389 3435 3397 +3 3389 3445 3413 +3 3390 3422 3414 +3 3390 3435 3422 +3 3390 3450 3435 +3 3391 3415 3381 +3 3391 3427 3426 +3 3391 3448 3415 +3 3392 3408 3382 +3 3392 3428 3408 +3 3392 3449 3425 +3 3393 3440 3411 +3 3393 3451 3423 +3 3393 3455 3451 +3 3394 3441 3424 +3 3394 3456 3412 +3 3395 3418 306 +3 3395 3430 3418 +3 3396 3406 3378 +3 3396 3444 3406 +3 3396 3450 3444 +3 3397 3435 3374 +3 3397 3445 3389 +3 3397 3457 3377 +3 3398 3424 27 +3 3398 3452 3424 +3 3399 3419 0 +3 3399 3437 3419 +3 3399 3451 3437 +3 3400 3426 20 +3 3400 3448 3426 +3 3400 3449 3448 +3 3401 3433 3383 +3 3401 3442 311 +3 3401 3447 3379 +3 3402 3404 3380 +3 3402 3434 301 +3 3402 3443 3404 +3 3402 3446 3384 +3 3403 3431 309 +3 3403 3442 3401 +3 3403 3453 3385 +3 3404 3432 3386 +3 3404 3443 303 +3 3404 3454 3380 +3 3405 3445 3397 +3 3405 3446 3445 +3 3406 3437 3378 +3 3406 3447 3437 +3 3407 3411 17 +3 3407 3427 3391 +3 3408 3412 3382 +3 3408 3428 23 +3 3409 3415 3388 +3 3409 3439 3396 +3 3409 3455 3381 +3 3410 3416 3382 +3 3410 3452 3377 +3 3410 3456 3452 +3 3410 3457 3387 +3 3411 3440 16 +3 3411 3455 3393 +3 3412 3441 3394 +3 3412 3456 3382 +3 3413 3422 3389 +3 3413 3430 3376 +3 3413 3445 3380 +3 3413 3454 3386 +3 3414 3422 3376 +3 3414 3429 3385 +3 3414 3444 3390 +3 3414 3453 3379 +3 3415 3421 3388 +3 3415 3448 3375 +3 3416 3421 3375 +3 3416 3449 3392 +3 3417 3429 3395 +3 3417 3431 3385 +3 3418 3430 3386 +3 3418 3432 305 +3 3419 3433 313 +3 3419 3437 3383 +3 3420 3434 3384 +3 3420 3438 3398 +3 3421 3436 3388 +3 3422 3435 3389 +3 3423 3440 3393 +3 3423 3451 3399 +3 3424 3441 26 +3 3424 3452 3394 +3 3425 3428 3392 +3 3425 3449 3400 +3 3426 3427 19 +3 3426 3448 3391 +3 3429 3430 3395 +3 3435 3450 3374 +3 3436 3439 3388 +3 3436 3457 3397 +3 3437 3447 3383 +3 3437 3451 3378 +3 3438 3446 3405 +3 3438 3452 3398 +3 3439 3450 3396 +3 3444 3447 3406 +3 3444 3450 3390 +3 3445 3446 3380 +3 3448 3449 3375 +3 3451 3455 3409 +3 3452 3456 3394 + +CELL_TYPES 7232 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 + +POINT_DATA 3458 +SCALARS scalars double +LOOKUP_TABLE default +1.6755246382 0.9791806223 0.9791806223 0.97594938187 0.12925491957 0.32674332908 0.2776476709 0.26537269646 0.54790553034 +-0.21848899462 -0.21871453724 -0.21891455992 0.84665342709 -0.17856744253 1.6242536107 1.5541884277 1.4657434756 1.3621923503 +1.2494702901 1.1352956356 1.0279120984 0.93487312743 0.86221409821 0.81414061254 0.79312421951 0.80015646774 0.83491193657 +0.89569004477 1.6314269455 1.5802975714 1.5225587782 1.4586874133 1.3892109713 1.3147032374 1.2357795488 1.1530917128 +1.0673226235 0.97756806161 0.87230841844 0.75258544172 0.62351150851 0.49302670378 0.36915058044 0.25873103277 0.16650020876 +0.094748228714 0.043676133967 0.012239424449 -0.00085049056056 0.0036947002414 0.026134812423 0.067560414732 0.88939364767 0.79870322351 +0.707858335 0.617609243 0.52870128787 0.44186873392 0.35782870532 0.27727526364 0.20087367574 0.30551630372 0.26085193696 +0.33248261206 0.40221609491 0.474164333 0.49090946769 0.43492101536 0.38013531824 -0.21860483282 -0.21999990002 -0.20935679925 +-0.19002571784 -0.16111227699 -0.12290209694 -0.075772635406 -0.02018945884 0.043298356616 0.11406364917 0.19140736677 0.27456547266 +0.36271649289 0.45498963119 0.55047337116 0.64822448055 0.74727732904 0.92700938405 1.0064051127 1.0843220202 1.1602511728 +1.2336966205 1.3041786361 1.3712368488 1.4344332513 1.4933550605 1.547617414 1.5968658838 1.6407787913 1.6790693085 +1.7114873312 1.7378211132 1.7578986488 1.7715887966 1.778802136 1.7794915513 1.7736525394 1.7613232392 1.7425841827 +1.7175577686 1.6864074632 1.6493367325 1.606587713 1.5584396307 1.5052069767 1.4472374533 1.3849097028 1.3186308344 +1.248833765 1.1759743914 1.1005286129 1.0229892221 0.94386268688 0.86366584185 0.7829225126 0.70216009423 0.62190610654 +0.54268474835 0.46501347365 0.38939961165 0.31633705305 0.2463030241 0.17975496944 0.11712756421 0.058829874861 0.0052426872228 +-0.043283980687 -0.086433164889 -0.12392302578 -0.15550868901 -0.180983845 -0.20018209643 -0.21297804515 -0.21928811126 -0.21907107899 +-0.21232836594 -0.19910401381 -0.17948440074 -0.15359767711 -0.12161292848 -0.083739071172 -0.040223487689 0.0086495891313 0.062560932655 +0.12115840756 0.18405926988 0.25085266704 0.32110232136 0.3943493798 0.47011541101 -0.20807267878 -0.18785742448 -0.15804382837 +-0.11892755494 -0.070896524324 -0.014427065188 0.049920809018 0.12150895379 0.19962742213 0.28350150513 0.37229941487 0.46514053332 +0.56110414555 0.65923857053 0.75857059904 0.85811514514 0.95688501528 1.0539006985 1.1482000803 1.2388479839 1.3249454448 +1.4056386256 1.4801272836 1.5476727072 1.6076050415 1.6593299313 1.7023344156 1.7361920144 1.7605669584 1.7752175189 +1.7799984047 1.7748622033 1.7598598509 1.7351401274 1.7009481808 1.6576230962 1.6055945329 1.5453784635 1.4775720571 +1.4028477567 1.3219466109 1.2356709247 1.144876303 1.0504631654 0.95336781667 0.85455316148 0.75499915491 0.65569308429 +0.55761977817 0.46175183962 0.36904000087 0.28040369479 0.19672193674 0.11882460736 0.047484222473 -0.01659172796 -0.072767796139 +-0.12048687821 -0.15927573911 -0.18874970572 -0.20861648166 -0.21867904609 -0.2188376075 -0.20909059342 -0.18953466601 -0.16036376341 +-0.12186717646 -0.074426679786 -0.018512745681 0.045320121609 0.11643888496 0.19413825227 0.76241422949 0.67829990008 0.59490769465 +0.51282974156 0.43264883727 0.3549343082 0.28023796823 0.2090902005 0.14199619143 0.079432343644 0.021842893229 -0.030363244546 +-0.076815378752 -0.1171836749 -0.15118149694 -0.20430773504 0.79987406568 0.74521915938 0.68109670552 0.60583329596 0.51822873301 +0.41876520742 0.3110804081 0.20190534345 0.098508562201 0.0062048589826 -0.071983637658 -0.13448442589 -0.18039364864 -0.20905411933 +-0.21991103435 -0.21257264778 -0.18707791994 -0.1443875336 -0.086957367726 -0.018911605271 0.054700304845 -0.21898841526 -0.21012065805 +-0.19219107636 -0.16536255105 -0.12987956477 -0.086065983105 -0.034322102404 0.024879005766 0.090995821162 0.16342333305 0.2414985847 +0.32450675189 0.41168770058 0.50224296338 0.59534306942 0.69013516017 0.78575082394 0.88131407132 0.21195574355 0.31433274552 +0.43280230545 0.56140042231 0.69246486262 0.81780410665 0.92995124339 1.0230844378 1.093366893 1.1387199261 1.1582627095 +1.1517427525 1.1192352923 1.0612474234 1.0802545292 1.1920461437 1.3065231906 1.4155401339 1.5121272707 1.591608462 +1.6521627887 1.6946460237 1.7217590881 1.7368564596 1.7427529387 1.7408274774 1.7306086293 1.7099146759 0.86687326153 +0.361144653 0.36673175754 0.6942875803 0.92589838003 0.1975067245 1.291299307 0.55452226136 0.18577761785 0.57040169005 +1.0033974887 0.59517018306 1.1960344919 0.39043213832 0.62067619447 0.44840245598 0.32031309912 0.8987292909 0.71379076294 +0.95987196479 0.67128308005 0.10483555049 0.63726617945 1.2502533541 0.15161858362 1.4949202081 0.18954169396 0.76001543195 +0.80473955548 0.23403135997 1.0716163497 0.48573338641 1.1578969598 1.3725148243 0.31325240746 0.54329988893 0.48977838326 +0.80745467835 0.62218079451 0.3198406734 1.0052556193 0.32429958483 0.40621048039 1.1272052982 0.10435016451 0.72428193257 +1.1638563283 0.43406795708 0.083102279045 1.4028043917 0.75927866652 0.69340229586 0.28280024781 0.46666823295 0.8355583309 +0.61701301468 0.66395380037 1.108205709 1.4783862114 0.25344355635 0.58071180237 1.2809597459 1.060862375 0.42273671824 +0.29926980744 0.47470945647 0.19641615201 0.89240580146 0.50841190057 1.2277235732 0.71571823772 0.06034723537 0.70965533009 +0.38924947134 0.74611739694 0.52892902976 0.29263750932 0.7666175091 0.5461917549 1.0259716759 0.39595072208 0.79850519537 +0.17136487756 1.2056125059 0.55292226657 0.37162212621 0.047937225353 1.368065989 0.51537080392 1.3411203028 0.13550107661 +0.71735362804 1.5829955967 0.97139543078 0.60811823746 0.8194158338 1.0066092537 0.28647581874 0.20674785042 1.4124822932 +1.0149499226 0.61876937867 0.44250461463 0.73348485006 0.92998653117 0.11926367298 0.63820354149 0.29060362974 0.65588171292 +1.0987528699 0.11624837386 0.82894394466 0.42839546936 0.96451374261 0.17809352216 0.55577006473 0.2407679354 1.2869349416 +0.49931562787 0.90540097344 1.0955679242 0.8174626293 0.13682195105 1.3252501597 0.6159407388 0.083203590137 0.19657561309 +1.5095885771 0.66255791331 0.8433570505 0.76001760909 0.53495478381 0.75465469384 0.66265403578 1.0556619548 0.19996695446 +1.5465750616 0.24087382873 1.4494218456 0.35248135204 1.2246286365 0.95088624831 0.61179621044 0.51734248648 1.1820750787 +0.4874918602 0.87636366667 0.29913767987 1.3119392503 0.47476945249 0.97285883603 1.0540826331 0.25660827822 1.1641797053 +0.34205604159 0.57081213946 0.13893174208 1.4169274193 0.89461644693 0.65774840097 1.1197436846 0.37632522956 0.36229441535 +0.81767966727 0.24906107837 0.32462157616 0.29323135309 0.71013711515 1.3736946587 1.7254596243 1.7445162662 1.4920135658 +1.0562887221 0.091019742036 0.75836733523 0.63796587338 0.74614686152 1.3372442562 1.7227443468 0.22757806246 1.3814269582 +1.75160456 1.7433942612 1.1614945482 0.28908435961 -0.040680764072 -0.19712242798 1.7389735177 1.6305131831 1.4847030175 +1.0008674262 1.7798502555 0.30078946569 1.0741026301 1.4636451775 -0.2181982889 0.61655407578 -0.16241170212 1.5408439441 +1.6126629393 0.78021256649 1.7775634908 1.1537000623 1.0240237488 -0.030690288698 0.26395039273 0.042257147609 1.2346987235 +1.5515737875 0.023271924651 -0.13497574145 0.40722560575 1.6648755632 0.55478116338 1.1215008653 1.5934508245 0.7835423385 +1.4447115535 -0.16003076697 0.39104289995 0.63632677859 1.0241558206 0.67374111655 1.7791074084 1.7530563221 1.0408588855 +0.39812748569 0.20897892604 0.13114612235 1.3000060199 0.66210977117 1.7799230739 -0.071774297163 1.3074156194 1.422165108 +0.39273142557 1.599103998 1.6045260176 1.7272606498 1.0939205417 1.6968399539 0.041872610997 0.074075455077 -0.21962421153 +1.5882557871 0.86865045064 1.7797624851 1.3125922888 1.6390889538 1.3141891734 1.6123954824 1.7092950553 0.42431944633 +-0.19137405751 -0.10544439672 0.97812541812 0.4059977216 1.4459627025 1.7794553734 1.032319404 1.6904970083 0.51082441871 +0.10235142258 0.87586165911 -0.16859146456 1.3570230331 1.7546490697 1.7799999968 1.2736172599 1.6364507411 0.88056726549 +1.2384737382 1.7299552819 1.7693654674 -0.096377971322 -0.21597352977 1.7622988608 1.6947815613 0.18880755439 -0.0527216022 +1.0162750161 0.2886798176 0.81018970005 1.6220761446 0.81322767245 1.5176354225 0.89293342411 0.097541128502 1.6904501513 +1.4399080082 0.2208956263 1.2826670046 -0.21193883752 -0.14863448728 0.52702414235 -0.12344628885 1.7598706414 0.50207265734 +0.45079170699 1.6625490968 0.56284128412 1.7616743194 0.75779708398 -0.11200536353 1.2652547551 1.0154676941 1.4906892197 +0.1073093101 0.19691407093 -0.20255952197 1.765068477 -0.19482770843 1.5966683845 0.40842139555 0.22682590264 1.0955695198 +0.68546672779 1.2449847075 0.69752921811 0.82277096307 1.5376456976 1.1877105153 0.074539377375 -0.099946779704 0.2020624201 +1.4821984033 1.5357843652 1.7541365471 -0.21334866373 0.83073721956 1.2118188724 1.77965962 1.1952412986 -0.015530618908 +1.3952439587 -0.0077818623677 0.98283025508 0.6002521502 0.8290108813 0.78342439278 1.4778188827 0.67291396727 0.93958377947 +1.2087109638 1.682859554 0.8851646931 1.4533011829 0.81594409043 0.10593941505 0.62711322033 1.0821948532 0.19046104279 +0.95697400523 -0.036303770216 0.42995824863 0.78359014514 1.4705249808 0.43620795997 1.4942899184 1.4995803164 1.7607095384 +-0.026684309788 -0.14945186721 0.27181311959 1.6346079349 1.2997959442 1.11992624 1.7782899869 1.6479872336 1.760139185 +1.7680241883 0.24776023528 0.33631241687 1.2091193492 0.44992719522 1.7399092641 0.58514577468 0.06163434235 -0.10608409811 +-0.18124769639 0.047065681674 1.0701396779 1.1399168616 -0.1676330393 1.2626083239 0.28445109692 1.3118664044 0.39957458065 +-0.21958366702 0.85095515697 0.60868822891 -0.1789837912 -0.2022020427 0.38119666578 1.6439421786 1.6708218985 1.3443741379 +0.15164495668 1.4871192108 1.6829600817 0.011563812066 1.7704294813 0.63716013592 0.56554316844 1.6294048372 1.5974310352 +1.4147345055 1.3001896892 1.7337495873 1.1705709575 -0.21860754384 1.7058949995 1.7103069957 0.45549492458 0.57252355865 +0.2544333845 1.7659498956 0.61381502061 -0.080885742132 1.6851723305 1.534597402 0.73194437084 0.23528466225 0.078865697569 +1.7137698041 1.6216704718 1.7611162882 1.3490289581 0.24681976957 1.7784724657 1.7024557104 0.9373766395 0.035681248645 +1.0922926632 1.7664777929 -0.051334187588 0.24285795416 0.4033819057 1.5596017406 1.0386431033 1.1584974663 1.5706858676 +0.87941738727 1.2002016425 0.093909324102 1.7735916078 1.0150200706 -0.062459760119 -0.20630454949 1.0084284917 -0.20732187482 +0.8726355579 0.10380791408 0.87028100538 0.15837742763 1.430804563 -0.10930476298 0.10707249237 1.259558845 1.7798352388 +-0.038782504916 1.3788081563 1.6890141058 1.6784341576 -0.11311473697 1.7055906275 1.7614944333 1.4235397045 1.4392062943 +0.52740057832 0.52587950731 1.6023625863 0.95060003397 1.5617898946 1.587339682 1.5715198291 -0.2036740987 1.6023404104 +1.7197585677 0.74448618549 1.7789736983 -0.17968280311 1.6860644902 1.7659687446 -0.046161284492 1.2452130093 -0.14399826085 +1.3829313502 1.6986880185 1.1636918092 1.7633708528 1.4097538333 0.31495939504 1.5323214565 1.4454200624 1.7361145589 +1.4266794009 1.6233079352 1.0119338174 1.7702552372 1.1563335703 1.1201487786 1.7729140803 1.6033166511 0.87855449706 +1.4182608424 -0.14846752299 -0.18374611389 0.84123086168 0.081755907296 1.4894827513 1.3777832562 1.0629108518 -0.11310653369 +0.49984618238 0.28001571554 0.9472433727 1.7601266798 -0.0037715413904 0.52613216577 1.3905472038 -0.11935534778 0.68391527795 +1.5401021595 1.5551909256 1.7239018646 -0.15319704272 -0.012933632469 1.6819075417 -0.21632990576 -0.10330645719 1.7791215255 +1.7731597902 1.753761523 1.1973259287 1.7149136845 1.2690237177 0.071872164964 0.18451100394 1.328232889 1.6077289714 +1.4927281036 -0.21742792002 1.6942180964 0.50407282381 1.7467536854 1.589644059 1.1328062428 1.1661460294 1.6676504833 +0.92529746874 -0.17010271758 -0.029280544744 1.5378673272 0.79549679584 0.50488036314 0.96805635336 1.7499157341 0.95703770126 +0.39247905807 0.52762662412 -0.21901125173 1.7799372939 0.4296683867 0.21704289523 1.5492646168 1.7701514989 1.7383670214 +1.2686460121 1.22379058 1.5336362869 1.7745253992 0.6173631366 0.23672532107 0.98283636458 0.020636747071 -0.21838404083 +1.7301020173 0.66964628644 0.90278800394 1.7365028195 1.7482636903 0.6457405172 -0.21047063169 0.9505461941 -0.21507236035 +1.6658683375 1.1388498516 1.7783990674 1.5516196057 0.22127190456 -0.17893733546 -0.18343453226 1.7765721059 0.38580226132 +1.448298304 1.0791421693 -0.0039868873598 0.79605811743 0.0023885524726 0.98969091989 0.67104753584 0.52908911704 0.76135850708 +0.7702314165 0.32421467036 0.7385386547 0.44879223799 0.89892923772 -0.21675853532 1.7731495756 0.39609129019 0.20691547209 +0.33263708079 1.3121303888 1.6396311702 1.2120342934 -0.11845608694 1.6916451151 0.026841992084 -0.2013323477 1.2640520841 +0.2902257033 0.75892529467 1.3703440591 1.0969312878 1.7159775372 1.6763556495 1.7778596361 0.48913148431 0.49154644047 +0.29601893273 0.10687915059 1.0468691959 1.2342539398 1.5191029858 1.1223322831 0.10832982802 1.7790662252 1.4844257184 +0.86651828984 -0.041235438944 0.33942310987 0.051238572631 0.53210660698 -0.18974889055 0.72610216302 0.29430436733 -0.19734286956 +1.2407978527 1.7530697702 0.64499765087 0.79828934 -0.070721277822 0.19219712539 1.2492611119 1.748740283 -0.21997212081 +0.91315452616 1.765595559 1.670814651 1.4668430255 0.86202628698 1.7735318605 1.7279755804 0.0125843294 0.18138202845 +1.7795539058 1.0164938102 1.1124852629 0.27508110685 -0.172412307 0.025385244399 1.5215837828 1.3724109274 1.106480058 +0.15871722587 -0.20991885942 0.57308245517 0.15399029035 -0.20308565205 1.2952704862 0.22553705843 0.53601198812 1.3184020908 +0.76586725756 0.99763940465 -0.21868281924 -0.16910496773 1.7358706319 1.1642573472 0.90445772792 0.56514971541 1.6170335203 +0.84950348045 1.5999846424 0.60075645552 0.11151611351 1.6628073184 -0.16356942164 1.688535221 -0.14000159756 1.4504005062 +0.34262808168 0.37824356168 0.7266836159 0.33530920633 -0.08055825165 0.26172590648 1.3187820895 -0.10225555796 0.90995215144 +-0.19068297401 1.3885412553 -0.11575822738 1.6682058318 1.5037164826 0.41641991648 0.77715761274 0.66357351997 1.6906603609 +0.12700479644 0.12489404998 1.2458110483 1.1608760771 0.32054496692 0.49117955189 1.2856918719 0.032489847438 1.736544688 +1.5986989399 0.4149991446 1.3311110815 1.3039491509 1.1399028704 1.3634103586 1.7441986019 0.55130438777 0.20967269361 +1.4118956484 0.72966547046 0.69813216218 -0.025904313027 1.7737038915 1.6460070679 0.74641094673 0.16324744643 1.370902486 +0.48231216933 0.30242796524 -0.092968069243 -0.044276399272 0.67260638099 1.6221492087 1.6591685283 1.2971381416 -0.099188808917 +0.70370402653 1.6360946983 0.62780037533 0.1805811952 1.3314181341 0.29404335576 0.16058271317 -0.060204754176 1.4828111351 +1.5603089349 -0.2100077428 1.7707094081 -0.20281262313 -0.1650600756 0.89753660211 0.37367440714 0.20289462996 0.83877684404 +0.32705187271 1.3443814497 1.5804702733 -0.057211514835 0.13097557682 1.5156182285 1.6343043527 1.6373962702 -0.056011568781 +0.5678606335 -0.21788728903 1.7738151566 -0.095266717003 -0.056421531835 1.0224514796 -0.11192307015 0.14516326204 1.7689397741 +0.89772062456 0.64399121054 0.02864753864 -0.094638479426 1.3078539287 1.4909355969 0.0080326733447 0.17994657822 1.7785035092 +1.7412777025 1.7376994232 0.53241861213 1.771824114 0.20596196443 0.031357842015 0.14879858121 -0.15770564632 1.4632007661 +1.631821323 1.2111372335 1.5335025607 1.2681187473 1.4861467968 1.0131554309 0.67468799408 0.32108115585 1.6495696767 +0.92430191175 -0.14403803425 1.5628909661 1.1637807452 1.2044651142 1.7770988333 1.1692557255 0.84446549414 -0.20438753126 +-0.055216437558 1.3891576864 1.7790938032 1.0476355754 1.4081977285 1.0124007729 0.053451057288 0.62525061106 0.16370914806 +1.2406903071 1.4576529163 1.6916694509 1.1326584561 0.79053485683 0.10901880923 0.96690109341 0.036679990866 -0.10285618183 +1.6004876007 1.352712764 1.7775800733 0.75811352467 1.4615411293 0.78278342116 1.0540244004 -0.20087323074 0.68110834583 +1.6269759841 0.3591540863 1.6480879291 0.56574842741 0.92863217082 -0.14885257941 1.2268611254 0.52729453172 0.33903483423 +0.2221208743 0.029026413278 1.6539378649 1.7784616283 1.6480991214 0.27775509643 1.0880610498 1.7202270392 1.7443598813 +-0.19083465586 0.85627385177 1.2269923476 0.94609700487 -0.16218185243 0.98447743264 0.67762924276 1.2431905366 1.1474503055 +0.73267512334 0.059833499161 1.7553440602 -0.046638643361 1.7674968952 1.0584487317 0.026305088158 1.4068083113 1.1307259697 +1.6234469029 1.4285157471 0.91112709271 0.98431814407 -0.070422345332 1.1302881139 -0.21841364861 1.7558192736 0.38740220715 +-0.033664335228 0.87176406197 1.4047861781 1.5568070635 1.7234343536 1.4382259013 1.0627470344 0.82638482129 1.3665523381 +0.28520134604 1.4716795898 0.21172271486 1.7336224382 1.6690514316 1.7676637181 0.48648081885 1.5592785343 1.4069418566 +1.0358580114 -0.20622776426 1.5109418697 1.7769990915 0.48646727716 1.5501972339 1.0799039804 0.86194205356 1.3966271049 +-0.10565312258 0.080678086833 1.725264937 1.241247656 0.69240613201 1.4198353864 1.0881633918 1.6451470084 -0.14611216463 +1.0342224414 0.96835063646 -0.18530636988 1.6330988649 1.7295416144 1.5186444548 1.6998796345 1.7131446464 1.0978830834 +0.8494702414 0.92202054683 1.7307836136 0.11503641718 1.5333146213 0.70526485253 1.2672412058 0.30844224688 1.341498555 +1.3670323087 -0.070333391814 1.7568254367 1.0560148231 -0.1452120341 1.4559893685 1.6841615181 0.62309392999 0.78593622608 +1.5508636382 -0.026973832346 0.055983239914 0.32596422949 0.070854591456 0.91997209675 1.2636988442 0.87141263115 0.1212806758 +1.2816917788 0.37273705039 1.7720782603 0.50604452156 0.60985425522 0.30904864028 1.7147156809 -0.21736587628 0.72339210408 +1.77678964 1.6824484587 0.52490537935 1.1550374101 0.61850326028 -0.015182355902 1.7789753585 0.42945221137 0.39012665711 +0.43421435271 0.076846011155 0.17296684624 1.7679610905 1.1101644035 1.1429404362 0.96892860936 1.4762803395 0.28732485658 +0.88131456167 0.37279108443 1.7744585957 -0.049839931413 0.10463662165 1.7740717287 1.7799017319 1.6357817798 1.7737607401 +1.3248346728 0.61535384199 -0.0039225790335 0.44746370199 1.4851787605 -0.14281760828 1.5170360761 -0.14544784491 1.5767418426 +0.48657906819 0.92994004836 -0.1790047211 1.7566998836 1.6769517424 1.5229828197 0.69385042514 0.1632496455 1.3580393159 +1.5558738401 -0.17968245899 1.6600898606 -0.16498529581 1.7619316813 1.3204344761 0.052523227926 1.5890223573 1.7354598797 +0.80214162223 0.28451138829 0.28872157695 1.6965785348 -0.19983748648 1.1810474025 1.662149043 0.59662699162 0.64853448386 +1.7465465263 0.5866275319 0.1992510737 -0.21423173783 1.3926429396 0.099282548046 1.1429058762 1.7671731314 0.61613120655 +1.7040790621 1.3259864997 0.32618052762 1.5265727495 -0.0086062731139 0.42006807001 1.7793985615 1.1653809827 1.5810006771 +0.40345136365 -0.20315370463 1.1369668769 0.17873372718 0.66310108948 1.7764046037 0.78932368744 0.028479130002 -0.13115081742 +1.0065836595 1.1501925842 1.7494673828 1.2432059497 1.7124019707 -0.20737154344 0.36878978442 0.14156065809 1.6701636411 +1.7769052177 1.5406284763 1.7130973656 -0.1829011747 1.6879513723 1.3298152253 -0.21185773556 0.55943310058 1.5634093572 +1.5244016267 1.3750124929 0.38501715325 1.7779664675 1.7101481791 1.3259612324 1.5337484828 0.51687946293 -0.19093232855 +-0.15784682402 1.7353218853 0.47393868949 0.40916795645 0.66342699007 0.32586460462 1.4085056078 1.19268836 0.0027036458021 +1.6063940036 0.30710342426 1.4464636332 1.7249058999 1.7596599896 1.7281067143 -0.21961297526 1.483617813 1.7484157233 +1.3812963996 0.080391420306 0.61442852068 -0.054161694738 1.6672969555 -0.1358612559 1.6072972403 1.6975691655 -0.1810132403 +-0.038708236303 0.033243815321 -0.21897772059 1.0435547906 1.5994356921 -0.21805014996 0.22059993104 0.72317577147 0.93777351966 +0.26134783518 1.753487433 1.5822963635 0.56832985514 -0.21396198043 -0.14558549543 1.5822142271 1.207673445 0.44207484636 +0.8536909213 1.4607842272 1.7517575851 1.7103118946 1.3928034583 0.98064430351 0.83990997193 0.55663742546 0.90898455266 +1.4076455313 0.24681094623 1.7388447738 0.16923123113 1.4937544279 1.7416654512 1.7705585549 1.2126625795 -0.062100436716 +-0.2074347989 1.6955821558 1.6675098381 1.4458061224 0.41309758823 0.42923243044 1.1662203388 1.7766235358 1.0312108783 +1.3646276706 -0.21353076455 -0.1436269495 0.56868982005 1.5868572165 1.6379229659 0.82950212482 1.7770400623 1.2663888311 +0.91374004228 -0.0087182031084 0.22360240731 0.0097846382281 1.1958012778 1.6199576673 1.5936673521 -0.019382374575 0.45588149721 +1.1658845402 0.7466267921 1.4741225627 0.52382703397 -0.17317794513 0.72597314234 1.6285065367 0.54743533097 1.134832459 +0.16715673472 0.85756377264 0.59595436006 1.7690613651 1.7617925445 0.36090698229 1.1783844695 0.16628210813 0.13544867044 +0.78568333716 1.1921326465 0.18580450456 1.7797611048 -0.11290316633 1.4853439641 1.4147813921 1.6430142173 1.5489603055 +1.7139267065 1.2697278377 1.7626086849 1.6729502069 0.049378231065 -0.21783838587 1.779085559 0.74920472144 1.6240515259 +1.2315990791 1.4699985635 1.6965190709 1.757720448 -0.12198209177 -0.20723694676 0.51830372134 1.423914199 0.98531120993 +1.7620679088 0.31057854021 1.0639480409 1.7738141222 1.2578959466 1.3697280447 -0.1575862331 1.7095678318 1.771707428 +1.5985324393 1.2483745988 0.79949055053 1.0235017278 1.706878498 0.012649585888 0.31626809849 -0.2067227952 1.0142076864 +1.7326225967 0.59037705099 0.98804722831 1.7181679685 -0.034728373667 0.69340028653 1.7366653411 0.31891351599 0.83845616206 +0.79282030671 1.5354061463 1.437572707 0.62904138253 1.2130431769 1.6465226854 0.34546551722 0.030591081923 1.3882094304 +-0.11839224318 0.2435380957 -0.21327589759 -0.15840135318 0.38030559071 1.6017652317 0.92963557916 0.54894544786 1.6005726244 +1.7579639867 1.0534387468 1.1759255893 1.3815970903 0.13025903112 1.6075819586 0.32371499102 1.6989285857 -0.18672097487 +0.38516499937 0.013353136648 -0.13807354022 0.20543798963 1.010802549 0.7528615912 1.7124529251 0.12338263277 1.121729717 +0.6137714365 -0.086004066017 1.535924714 0.027077738019 0.98787127097 1.4675442675 1.7736212064 0.78509317842 -0.21946383929 +1.3202829012 0.18105263713 1.7754649939 0.36794793473 0.93979176561 1.3194944109 1.2868338951 1.106356649 1.7799825132 +0.78958529292 1.5203934366 0.033898469863 1.00691238 1.3269063004 1.5294549189 0.72950583364 0.65834810115 1.7617678832 +0.992127944 1.5489705525 0.57364114796 1.7081194902 1.0790838406 1.0392008351 0.67620728821 0.088090584143 0.95174484845 +0.2394426106 -0.053964259812 0.37621032627 1.5104065713 1.5620946156 0.59168772101 1.7785868205 0.66743930604 0.21900724892 +-0.16966078809 -0.079593540459 1.3193114733 1.7614084604 0.69844976734 1.531549371 1.0873662204 0.40915687499 1.2289591228 +1.7694675645 0.72253764595 0.10911815749 1.7738132963 0.90029696962 1.6351903092 -0.11632343722 1.6731716252 0.058885198581 +1.7312906724 1.7158227931 1.3141367 -0.18580671063 1.3664264635 1.4059709339 1.0280821168 0.41927792203 0.31755630569 +0.49021162559 -0.21869586856 1.241168095 -0.18522299406 0.29168447373 0.84190171443 1.608291126 1.2729305086 1.5495714978 +0.61661462562 1.6745114176 0.50848769006 -0.21998781574 0.059245204475 -0.079005150598 1.7033568667 1.773635675 1.685297685 +0.56757773117 1.7799902493 1.6697274736 0.18170903376 0.76696222755 0.29330061725 -0.11085015701 1.7786453117 1.3989591277 +1.5295063897 1.6967702585 0.46615021976 0.022476591375 0.14690619616 1.7369337207 1.4331082872 1.7055236511 1.7475903764 +1.7606118111 0.26550276052 1.7776752916 0.05362404829 1.1537652161 0.26157153623 -0.029784906761 1.6329111326 0.22801372431 +1.2340551739 0.66693979468 1.2717065667 1.752241381 1.5290634005 0.83511710246 1.4997508759 0.058761159973 0.88245488975 +1.7760261059 0.88105005777 -0.20980880082 0.92114695593 1.2478859865 -0.19622928632 1.160709345 -0.072320407877 1.7147580199 +0.14716438006 1.3109835707 1.364580101 -0.065742031085 -0.13319502659 1.4753386308 1.7510680011 1.7630701317 1.6885106246 +0.19252930898 1.7647671477 1.3402293873 1.6397731148 0.059412071192 1.1182245812 1.5801065106 1.153518494 0.32667707224 +0.46868510366 1.7086126756 1.4911380186 1.5099307821 1.5725909444 1.3228454998 1.6219163347 -0.20207019269 1.6664156055 +1.6593028231 0.85875678923 -0.19730413871 1.7797228733 1.5642060423 -0.16930223944 -0.099169161663 1.7762335449 1.1201006275 +1.4500056499 1.6253104435 1.726857563 1.751182189 1.3809773122 1.2917980715 0.59532506087 1.5862897958 0.99184696139 +1.3486393699 1.7474954787 1.5221128603 0.78493676706 1.2960646974 1.4419341833 0.85653287125 1.3662841476 1.0441881958 +-0.18016928835 -0.20475698422 -0.10543701646 1.7144276012 1.0784015249 1.5093121445 1.7526881254 0.47991308086 1.7264253742 +0.62910639905 -0.013987738005 1.6733354861 0.44954290641 1.2871200426 0.43825262102 1.6573458711 -0.14643462901 -0.06595111985 +-0.060214402993 1.1539031297 0.23449919634 -0.21182334504 -0.2194473513 1.7658361312 0.11346385673 1.7773537359 0.39250713183 +1.33640112 1.7654164155 1.5888896826 0.1479612715 1.0936695093 0.45796115526 1.4129905829 1.6713763845 1.6556910075 +0.94375862638 1.1798645977 -0.17370726264 0.79099959597 1.5800746927 0.3925718247 1.1627700056 1.4423629441 -0.018698007446 +0.97416226448 0.85259345158 1.1079140113 0.61741172353 0.56323700584 -0.21371100184 1.7799924627 1.769836652 0.18928660834 +1.746657146 1.7044398628 0.41367132454 1.6143888071 0.29083223055 0.94601158286 1.484124278 1.0840783434 0.053044886223 +-0.21945886404 0.65547027567 1.6959282003 0.08633197403 -0.1340985416 -0.16418658208 1.3893429107 -0.21653476612 1.513173927 +-0.219577957 1.1330047375 0.66417559073 -0.19351311411 1.7609138517 1.4540330534 1.7771005211 -0.05949540756 1.099646929 +0.69952630528 1.1166262638 1.5574039769 1.7522390081 0.90836645018 0.71131282889 1.0787876239 0.99974360785 0.70627775668 +0.51398172789 0.65846947401 0.60814658119 1.7414642574 1.6069585856 1.1452346596 1.0787833705 1.2448661617 0.9101458861 +0.29649227999 0.099853300443 0.22034861201 0.36976196827 1.0195813924 0.86201284753 1.6618430483 1.7493524059 0.41330204906 +0.38928972709 0.32742365379 0.035538742151 0.93055328268 -0.096458409696 1.6562464134 0.34766558096 1.6945966746 0.93166768878 +1.4308377055 1.0014406217 1.6528404445 0.71292649346 -0.19309966399 1.7757371247 1.7709381189 0.2839077017 0.25001306982 +1.4268589261 0.68380165143 0.095713842342 0.34253588607 0.89974785752 1.7310224613 0.23114009191 -0.16616130426 0.9095356468 +1.1386395341 0.48073085408 0.93212247658 0.017467950727 0.50007183709 -0.18333663365 1.2227605695 -0.18169576449 0.74197616947 +1.206283569 0.037097036222 1.3390656998 0.71039729951 1.6479610951 1.0387425079 -0.2198277741 0.82009545215 1.7773139843 +0.1041425768 1.7333763034 1.5578284904 1.0821565181 0.13576461298 0.80426614915 1.4955207659 0.18449263508 1.302718915 +0.93476649283 0.41024126361 0.060437726586 1.687771325 1.6740562219 -0.20766365188 0.9008180048 1.1187946593 0.49088237729 +1.499270788 1.7375663094 0.283528099 -0.035458862219 -0.1517332479 0.71639624004 1.3302081989 0.87981429782 0.53189486731 +0.098554517074 -0.21053660903 1.3024704173 0.57644930646 1.3061098011 0.63098638154 1.6032522424 -0.037708066788 0.82146166918 +1.7677394494 1.5863612629 0.90964648751 1.2325308142 1.6342184885 1.7218369472 0.96034442989 0.32340299348 0.64287275755 +0.22478074074 -0.10633833883 1.7798226554 0.96371373949 1.3977850308 0.35109519019 0.74510614709 0.66103138179 1.5365568359 +0.63361262371 0.64265051371 0.13669659397 1.1851670467 1.1540073856 0.2593033238 0.23363137943 1.5907536076 1.2877374373 +1.5240560185 1.1030004049 1.7376011747 1.2631064023 0.56762744291 0.75663998336 0.89947942016 0.18244407932 -0.082785556023 +0.87637257235 0.05575307456 0.74451995582 1.526037049 0.44616921209 1.5467615699 0.06523740012 1.5550120927 1.5967950391 +1.3495958744 0.46258980067 1.2880025846 1.7798949598 1.5762794106 0.077279259249 0.56495160878 0.26196182619 1.5676909413 +1.0025212053 0.29862876797 1.2965378413 1.4493346596 -0.08043799089 0.41604297425 0.18646660501 1.7639055457 -0.072467864766 +0.00072005141861 -0.16090142459 1.7147913195 1.7462297365 0.24867612975 0.34607842852 1.7759750573 -0.142073909 -0.21029634045 +1.5072387666 1.5237417203 1.5759305004 1.5932547266 -0.14114945904 1.7246521699 -0.066210774914 0.24063679701 1.1903503737 +-0.087552995724 -0.031609316976 1.7795477072 1.7740164601 1.7788889828 0.13609814631 0.53041832137 1.3716194167 1.6567556365 +-0.0087622933679 1.7779749458 -0.13409162119 -0.00074993073561 0.81094714242 1.6751175347 0.61617353047 0.16090919421 0.3502656872 +1.7428041566 -0.14070148481 -0.12681315126 1.1430558779 1.7718047105 1.2452632256 1.7694412058 1.4573123334 -0.13081956001 +0.53545353699 1.5699709552 0.15329391281 0.023394312011 1.0584896759 1.655061848 1.2477815813 1.4330934421 0.61302942823 +1.5777135996 1.7144247341 1.2661207089 0.93707140352 1.6241696995 0.4770848077 -0.048979442605 1.7794189245 1.4152579926 +1.5737239143 0.25510017244 1.4545765622 0.094330550005 1.7343880459 1.7573936918 1.7756605053 -0.20645102878 1.2053078809 +1.3263997219 1.4418184518 1.4060691548 0.58849870319 1.0720570046 1.4033842722 1.7792428445 1.6198240395 1.2015456341 +0.7117140069 -0.11658963173 1.7796158947 0.1781628831 0.79364870032 -0.15968181546 0.090723617803 1.7729714169 -0.033488196031 +1.192770075 0.99352816542 1.0244704127 1.1260773233 1.3657334072 1.7590638624 1.3682427528 0.11081857225 1.4166048983 +1.7357278513 0.68551308187 -0.21514817083 0.61625839346 1.7197336944 -0.0090949506751 0.32648581014 0.45903903794 1.1053606585 +0.87154906752 9.2416546433e-05 0.64473275143 -0.18735713433 0.77330851077 1.0321013947 0.85726814405 -0.070490762357 0.19097617691 +0.14976141968 1.7465235308 0.80521064209 1.0808520389 1.7559958322 1.4170120271 -0.10550132162 -0.0096466360926 0.8186665014 +1.7077710465 1.7799974095 -0.19350706397 1.0695020027 0.7748168017 -0.056094820155 0.36288947295 0.84858463321 -0.016079908619 +0.51283254531 1.4877126265 0.25863904024 1.6932106892 -0.21919366408 1.6205433846 1.2423235305 0.34148275586 1.4571581973 +1.1685506253 1.1730517928 0.9809212897 1.7532594897 1.3347569547 1.2212235061 1.5371842919 0.24193669368 0.93328337387 +1.3994583882 0.77419828634 1.7798377479 1.5245449151 0.52920567812 1.2353803019 1.7731954568 1.7371472496 0.49777192511 +1.6973440473 1.0256847699 1.6835227091 0.328506047 1.3751769123 1.056254107 1.0383299979 1.2755850847 1.4795294067 +1.2419639059 0.99932434005 1.4315324861 1.7653358552 0.69024060822 -0.030892503812 1.6221322231 1.4390055679 0.06163491324 +1.6713710707 -0.21497647152 -0.13622944566 1.7293775068 1.766780445 0.62056515533 1.6693449485 1.3696777981 -0.15050319585 +0.7151981309 0.84361238433 0.94147313788 0.94624060884 1.0110603803 0.84545190958 1.060093109 1.7700495588 1.657001778 +1.6598092445 1.7516640239 1.276730816 1.6849860686 1.7081902191 0.25685392257 0.77394966629 1.4686012074 -0.18993230502 +1.7161980261 1.6560552843 1.4228120232 -0.080895628618 1.6198850142 0.28264359764 1.5850770935 1.0139210254 0.057765613119 +0.81521913062 1.5140852782 1.7403806388 0.76003793956 0.17539888465 1.6033797067 0.39906155972 0.28164773477 0.75182180961 +-0.067221879635 1.7561255295 -0.21885829242 1.0148287978 0.42608734795 1.5056817464 0.49982629198 0.38216226964 0.3965788163 +0.14397488604 1.1379179908 0.34178599192 1.4937687899 0.11097498337 1.4878199345 0.80904494772 1.7774504825 0.30683382295 +1.5339162469 0.19365679465 1.2439329782 1.5692316513 1.0763534987 -0.083348023385 0.10795128236 0.82322957373 0.10207370606 +1.3399538941 1.3365892205 1.6748428264 0.54416253222 0.33256959622 -0.19426800255 1.7797861632 -0.020260005876 0.43899904265 +1.7557583022 0.63271448413 1.6807417682 0.45207560574 1.7662997759 0.75734556578 1.7321350967 -0.20063316559 1.7700703158 +0.22090050823 1.7296522896 1.6531031752 1.2405260048 -0.040934078011 0.54107646093 1.6348782951 1.5387387499 1.6283412027 +0.5371164482 -0.16695845887 0.7950747156 1.7453310929 -0.16520359857 1.4671741846 1.1577136778 0.139011402 0.020665972951 +1.7424471153 1.7797676972 1.4219688382 1.5288704804 -0.21315469922 1.0383395998 1.3041646905 0.31812591674 0.56422563529 +0.58952441512 1.1356891128 0.68969681712 0.07763245414 1.4977503379 1.1602606827 0.41621202855 -0.17049948489 -0.13948651298 +-0.16443558752 -0.21482415793 0.023894517482 0.57240670881 1.777097887 -0.19229023419 0.096581964774 1.6769548491 1.7047288305 +1.75082118 1.7728452925 1.7534803329 1.7338903245 1.7760529283 1.7237704616 -0.043851938397 0.26327628304 -0.19679819295 +0.995327842 1.7753007463 1.6256608051 1.4046572839 1.335100831 1.4516685395 0.48345344425 0.5508903146 1.4731959047 +1.084102237 -0.21999923867 0.84001086751 -0.09893894076 0.094433932585 1.1842070692 0.012238900704 1.7706934746 0.31598877871 +-0.036872546131 -0.20689376962 1.7732867066 -0.17784263079 1.3590673073 1.2909452452 -0.21916750595 1.7042686117 1.6856572097 +1.6423210792 1.6573586331 0.0094001769094 -0.10893884756 1.6426796715 1.5845389914 1.5363097641 0.63170702081 0.85709597317 +1.7115166716 1.6298933247 -0.17754509637 1.7076806529 0.16340541404 0.31348291541 1.7791189052 0.48317015431 1.1100087924 +1.47149867 -0.2160678648 -0.18174182671 -0.052159837881 -0.11608144841 -0.19231869779 0.059376663176 -0.18480888019 -0.21263483449 +0.040946289997 -0.14944523205 0.30475360237 -0.086757638735 0.33258002712 0.16484621606 -0.21260634945 -0.21775611087 -0.21682524633 +-0.062259781381 -0.17165962796 -0.16088257355 0.02282615391 -0.21571923183 0.413947393 -0.10454343827 0.23938928367 0.044921583108 +-0.050698198645 -0.15645532786 -0.025434252165 -0.20863934053 -0.15957881981 0.16423440245 -0.10069743359 0.22439780456 0.5616988141 +0.218161985 -0.19508366293 -0.21861877676 -0.048278863341 -0.18842449065 -0.20366909396 -0.13740466753 -0.21933646785 -0.090262069251 +-0.21999532029 0.034671405243 -0.21938378337 0.47687820615 -0.092976229494 0.0825869318 0.19042032614 0.17886799075 -0.21319132159 +-0.12678978191 -0.20136479543 0.39461620417 0.0563627531 -0.076156533506 -0.14574515008 -0.20717620792 -0.07094124419 0.049218648487 +-0.16481923138 -0.18386787659 -0.024856908547 -0.21530465942 0.41454667343 0.65398429297 -0.17021241756 0.38285413189 -0.050671476868 +0.14981668474 -0.15204805895 -0.078486110846 -0.20174074329 -0.18378789393 0.36313425664 -0.19139433749 -0.019170230121 -0.15604288511 +-0.21776847795 0.013076728993 -0.21896664543 -0.07304501455 0.23173906336 -0.21779132987 0.050116741514 -0.086361642069 -0.21275415313 +-0.21170506856 0.52851884393 -0.10195595647 -0.14309185893 -0.068585861561 -0.14311815875 0.079872647417 -0.030451876781 -0.17735349689 +0.4419437623 0.30352279761 0.058445339757 -0.14717186161 0.07592616585 -0.12890118352 -0.15938137484 -0.1718277248 -0.15791450354 +-0.15518191223 -0.21537071803 -0.11080288077 0.21673316524 0.28136134296 0.38505908832 0.54553316717 0.23730325776 -0.058553837781 +-0.20172573751 0.17061231996 -0.075406075797 0.59895863124 0.10772862789 -0.21827427889 0.056154089849 -0.21805222132 0.14078742016 +0.27791858113 0.14447718976 -0.19885288494 -0.21785383268 -0.1620997136 0.53623097647 -0.026100597038 -0.21743381052 -0.19652836217 +-0.074814669584 0.68457559399 -0.1398389521 0.24073312173 -0.13603558621 -0.079357484839 -0.11387004734 -0.19078902675 0.36235252491 +-0.18539515904 0.032023731856 -0.10214340094 -0.15739803913 -0.21668554193 -0.21747057774 -0.21998441815 -0.21033890684 0.40111161417 +0.43869870256 -0.19634120413 -0.0013135909185 -0.074995383961 -0.029918044065 -0.10208969419 -0.19208870847 -0.031117450413 -0.13542353995 +-0.21190750166 0.22450315158 -0.19355102068 0.33122974363 -0.15832124621 0.041866903466 -0.043595968785 0.11587064155 0.26922240138 +0.10677399097 -0.052314379642 -0.10299563825 0.12430052801 -0.040381450646 -0.20908668293 -0.1220073794 0.19090731185 0.48055271538 +-0.019784793036 -0.18564395885 0.095471826739 0.49577306496 -0.2103691024 0.0060457188508 -0.017469060186 0.12969115903 -0.19952678573 +0.28177792275 -0.20534968116 -0.21132727221 0.010843977344 -0.20464691959 0.63674154885 -0.12803495949 -0.13108760542 0.12724772373 +-0.023122697487 0.15141200712 -0.21936177242 -0.16973077451 -0.12734033363 -0.028920630698 -0.21802666523 0.090187772396 -0.014856184219 +0.1210449594 -0.21963564928 0.19031710572 -0.18213849948 -0.089851373086 -0.21994563622 0.57081625661 -0.16047780729 -0.17172158816 +0.33246611322 -0.21160306946 -0.21497991472 -0.19469050008 -0.028752045778 0.13523528849 0.078224690419 0.54450603042 -0.21948052647 +-0.13449587726 -0.1286692459 0.22832434096 0.027252419746 -0.093220134025 -0.20746634716 -0.2108421016 0.47662046901 0.012578199377 +0.79960150083 0.0084577369193 -0.21050901873 0.67326052585 -0.1755100305 0.2582360687 -0.18188485289 -0.21721415178 -0.098327907387 +-0.017770342386 -0.20283042538 -0.12424557694 0.0020763413087 0.10659347773 -0.21189999468 0.026146071867 -0.19792141358 0.06188278123 +-0.0017677228345 -0.07232122105 -0.21723927036 -0.10650000268 0.35881612447 -0.19976690018 -0.11070294536 -0.063301867092 -0.12408569247 +-0.14664163363 -0.010068111517 -0.17693529423 0.52271080456 -0.2061651097 0.11558540774 -0.1480714442 -0.21734071485 0.1679341964 +-0.13447107874 0.68768446449 -0.21995328359 -0.040395985532 -0.19676497357 0.37786269741 0.077095632981 0.52767635343 -0.17942231304 +-0.15787660544 0.26333706312 0.36470681425 0.20983614231 -0.024425886009 -0.18539014654 -0.17274005076 -0.20322739797 -0.072621585884 +-0.18709465569 -0.094075431658 -0.16784958648 -0.18295715776 0.68227375454 0.37320477815 -0.18294197982 -0.10030235045 -0.21993741591 +0.35616354122 -0.20955669638 0.48872222058 -0.21914070853 -0.20192215143 -0.21851708466 0.58920952116 0.0184927582 -0.21967437886 +-0.094666614369 0.22330496164 -0.12166670548 -0.21830697851 0.023039612579 0.30890546003 -0.18057378222 0.21055438782 -0.10063864726 +-0.14082441911 -0.025701558184 -0.19215558357 0.14123558075 -0.17366554203 0.037569925211 0.25813667382 -0.059449578892 -0.085057000628 +-0.075506651055 -0.11773480004 -0.21687675943 -0.0080833440881 0.008859270033 0.26111956275 -0.058125046508 -0.21476985122 0.0016526432137 +-0.12031435055 -0.21183120358 0.36442161778 -0.16574546164 -0.21770198442 -0.016836686274 -0.069079127938 -0.10791648032 -0.21987779658 +0.28561031371 -0.21994407711 0.027353704261 0.35375291235 0.29149225537 -0.059069363728 -0.2178370487 -0.05754991439 -0.1489440685 +-0.2194401514 -0.19482987542 -0.1835913425 0.092257793029 -0.091482062376 0.040708976317 0.41071097022 -0.12567429493 0.079064453919 +-0.13048545753 -0.20750446878 0.52155288716 -0.049215082615 0.23598600454 0.31600562611 0.38112271964 0.44702496189 0.022421452024 +0.15361191795 -0.030266183824 -0.14621168979 0.10315835503 -0.17179759323 0.31268578033 0.21819543717 -0.023601650384 -0.19675501541 +0.023700105878 -0.2057068343 -0.18206862152 0.12547710369 0.42851258872 0.7530645186 -0.21932592041 0.21595419072 -0.21999376999 +-0.16283473844 0.46029035215 -0.14270303613 -0.21419538645 0.037796358287 -0.07458194502 0.1762583829 -0.12565293658 0.20381413209 +-0.029142426969 0.20311309263 0.5233043934 0.79932662876 -0.11742621911 -0.11512924462 -0.20709222738 0.7884183211 0.26583527586 +-0.12312425904 -0.21883663604 0.49354260372 -0.21993231861 -0.21248640088 -0.2134260935 0.5010868184 -0.038323633883 0.055131388807 +0.12193176078 -0.21781060608 -0.2167021895 -0.1144954997 0.2026642073 0.06455878366 -0.086372164328 0.14656706467 -0.16546561005 +-0.18998599668 0.42765998509 0.74981256569 0.023498011478 -0.024330578265 -0.15044873215 -0.20697463176 0.25679044595 0.93522907709 +0.94475282733 -0.21079132692 -0.20299912935 0.0077263285971 0.089072697291 -0.0067783975398 0.6185983847 0.66617435091 0.35596569174 +0.30461621439 -0.094815429603 0.082398032348 -0.20716471588 -0.17350993504 -0.21767146975 0.14269887555 0.22684549211 -0.18166772827 +-0.17368497499 -0.15930267308 0.27788123414 0.48051065685 0.59627817998 -0.080917709148 0.40624082224 -0.095505146338 -0.15926836384 +0.30971917613 0.66512553778 -0.012463943741 -0.2168075545 -0.17104331731 0.41453957019 0.38922580923 0.029243937482 -0.085801114852 +-0.04592760674 -0.19564587077 0.9439951103 -0.19768768349 0.18296777764 -0.18302602999 -0.20272861891 0.072768032998 0.32488464179 +-0.082618257523 -0.10475450304 -0.17220169062 -0.17455765172 0.014323764606 -0.044211875491 0.52968147469 1.0046398837 -0.16928039585 +-0.21134043834 -0.21397161429 0.05852798268 0.77710928449 0.12532904247 -0.20996486964 -0.1962851867 -0.027340013519 0.090331916264 +0.17073351706 -0.087159909856 -0.21993742205 -0.21730329457 -0.1826172619 0.27562928974 -0.21913510701 0.020658467865 0.11212052706 +-0.0076733688104 0.12460676756 -0.13660949888 -0.19717793713 0.64490999311 0.016963221753 0.2737119916 0.65638089678 -0.2198618601 +0.34913876149 -0.16423276189 0.53104972182 0.15730369856 -0.083595811248 0.20471874705 -0.1088371448 -0.15158215888 -0.10201359153 +0.61775303729 -0.20439063366 0.59207640752 0.40293866625 -0.21773543349 0.21283620102 0.44987853711 -0.14759586957 -0.14933307706 +0.16281311731 0.25315823689 -0.070875581042 0.96215817669 -0.063847047837 -0.21457228517 -0.21323421047 0.87265492998 0.54798382243 +0.42857615977 0.38478792598 -0.20141420689 0.75742391305 -0.17055584907 0.34080372141 0.12938359405 0.099569803066 0.00031411212961 +-0.051683727529 0.72113556831 -0.19359723397 0.30100585022 0.28980310423 0.094538514352 -0.21937018327 -0.21680345631 -0.21816575668 +0.27190617425 -0.14483519582 1.0242641232 0.085152485986 -0.16411412036 0.90419742488 0.054108593849 -0.096947676022 -0.066838148324 +-0.20069294557 0.047701071758 -0.015866950944 -0.18542851922 0.49848385747 0.099743278183 0.17759917272 0.30395047831 1.050683066 +-0.13669529607 -0.21951263577 -0.0065840191222 0.33740754938 0.2805877623 -0.11670226899 0.84441234282 1.0539730856 -0.21291722912 +-0.078308711221 0.76268327596 0.59501824109 0.51041468415 0.54217500543 -0.17855002944 -0.18819346279 -0.19523800905 0.13259625664 +-0.05028136856 0.674997199 0.0077400723165 0.48125931197 -0.13420014069 0.79541293827 0.42022550309 -0.17818666471 -0.21562385023 +-0.097754777612 -0.065790936516 0.46161202283 -0.20497518982 -0.1332085152 0.39935439944 0.62972585131 -0.1992811513 0.29224377845 +-0.12389144808 0.031464561006 -0.19566126181 0.86569003287 0.96887959975 0.28828597723 -0.035890927104 -0.21624688501 -0.13695132774 +0.50697820068 -0.20845939489 -0.17093818277 -0.19743987 0.44866674704 0.093727458579 -0.21073674742 0.31277529066 0.40834585662 +-0.11651463907 0.6998507791 0.1697886845 0.09840887375 -0.03996086032 -0.21735377189 -0.15704290833 0.39551415367 -0.0039209729235 +0.0065791910072 0.97563532121 -0.19783755132 0.40050982112 -0.17120614694 0.13870940094 0.65007033361 -0.032360908858 0.51177747604 +-0.12902704977 0.14394527798 -0.21948165162 -0.028977571211 0.56198778522 -0.12991127902 0.33938210657 0.13755527067 -0.20994354271 +-0.0619730642 0.57421148889 -0.12205314647 0.37279610257 -0.001973444181 0.19530729553 -0.19381356095 0.10106097153 -0.1400393967 +0.1999575772 0.67737914099 0.0037684744224 -0.21940706755 0.89974010408 0.5407618403 -0.12717333379 0.067694677453 -0.026342903142 +-0.17568550283 0.15037700542 -0.19316333014 -0.19557307149 -0.21996343847 -0.16649366963 -0.12979028441 0.20192501304 0.57201946284 +-0.16662404154 0.23202340884 -0.14259572754 -0.21793655579 0.25813705897 -0.2068858078 0.053270163027 0.84572828734 -0.21896535619 +-0.11848100196 0.84024191357 -0.2134933998 -0.04725263389 -0.21597242562 -0.19744151075 -0.21835825561 0.038907304685 0.025553628605 +0.39972997623 -0.18070038733 -0.085700913572 -0.19387929177 -0.21991763785 0.68928116469 -0.087420269467 -0.19820056816 -0.088623867737 +-0.2128957919 0.0629610285 -0.21489154293 0.69500140521 0.39853489311 -0.085265054184 0.95842280703 -0.044895966525 0.010259042094 +0.31980405248 0.50282115617 -0.21390116304 -0.21723258321 0.1245041787 -0.20348380634 -0.14904657371 -0.086918308848 0.38117224594 +1.0378917636 0.7493126584 0.097906044404 0.024686848861 -0.0062889509399 0.061267199471 -0.066692322821 0.095275963644 -0.041411343564 +-0.18474167398 -0.19791447284 0.22306767661 -0.19739319286 0.244532783 0.005070416052 0.20842480131 -0.15404006053 -0.088765629401 +0.20477912245 -0.1747428203 0.21316991374 -0.2199928277 -0.18019325553 -0.077754440583 0.60975740473 0.030680850177 0.10659976713 +0.10436011765 -0.19471404395 1.0886245569 -0.14359722368 -0.21724302107 -0.19844214629 0.0045363296545 0.3312523384 -0.21934442133 +0.08022196781 -0.15542240172 -0.20237625284 -0.21878394256 1.0423585602 0.17679592852 0.88217360282 -0.20354323236 0.29096576896 +-0.20700764571 0.55562366351 -0.1281102006 0.13774039598 -0.15832572146 -0.0082420494568 0.2107003863 0.71031175273 0.19489893955 +0.85402838203 -0.17285103632 0.74691218289 0.66309887613 0.37491224778 0.30841666101 -0.2196659276 1.0887572799 1.5201330498 +1.506866141 1.2492483061 0.64392299629 1.0427047416 1.3679372928 1.6337429783 1.3638115134 0.95487787268 1.640911964 +1.3341168575 0.75173680524 1.4982269221 1.3120591845 1.4456703687 1.5496556095 1.0583567537 1.2304963813 1.6608732987 +0.39241934082 0.99078414031 1.2677560557 0.69162207487 1.6895795502 1.297785376 1.1887274218 1.6387435865 1.1633057461 +0.8844951557 1.6092971799 1.429067185 0.53363306785 0.79333390909 1.3772354617 1.555588336 1.5510490839 1.1438035838 +1.3106965905 1.4181923858 0.88444655351 1.5480586305 1.4818417446 0.82644181059 1.2211203954 1.6897018178 0.94356669832 +1.4647872955 0.51289637218 1.1831783155 1.7019604385 1.2486296216 1.3221070154 1.128329585 1.4191391289 1.5822010606 +1.2746075664 1.5978289181 0.41561980316 0.84722693425 1.4290418767 0.65651876266 1.4735555197 0.72647977071 1.5650714446 +1.3417808708 1.0644737384 1.634007317 1.4043191394 0.71686121389 1.2287387153 1.7137185907 1.3949601758 1.4972971855 +1.201215677 1.234496149 1.5696171303 1.1827038557 1.5136464335 1.0259681512 1.4941941868 0.74126329156 1.1569940282 +1.3692613629 1.6501168822 1.3707103212 1.4001118508 0.5542639644 1.7199907384 1.2272805508 1.314859149 0.58686973209 +0.98634154465 0.27296819036 1.6717451647 1.1337851063 1.5737755102 0.95159426711 1.6287071048 1.3137327827 0.94543677644 +0.49653968284 1.5712005089 1.1849108649 1.0277668473 1.6814104914 1.2969679296 1.4598163342 1.3847806411 0.85662439197 +1.1248412231 1.6827259106 1.4692296602 0.99380186224 0.89533380142 1.4131260604 1.2589766957 0.85970045259 1.6474377434 +1.3671847113 0.79500131902 1.6053285956 0.60575102877 1.1340330147 1.3161379212 1.6724048678 1.2741623963 1.637153726 +1.1122685329 0.37744174204 1.7023197883 1.1886949687 1.6299193024 1.1936032332 0.89786902084 0.32597258955 1.3998193298 +0.45365794261 0.72033040243 1.3196825186 1.5264998156 1.2855833734 1.0073435634 1.5639893664 1.6031260812 1.0532937777 +1.4228692575 0.95849441517 0.63795548685 1.4327902794 0.60370667369 1.5945312249 1.5397916055 0.80401626948 1.0630314456 +0.49545043184 1.6702308589 1.2800150998 0.85443131312 1.5088315235 1.5146511292 1.1346590679 1.2443253987 1.3888615476 +1.1950238119 1.5530205563 1.2035655176 1.5319512956 1.6318476534 1.3739548327 1.369216393 1.0440920074 1.6517857002 +1.2072916406 1.658163878 1.5133157538 1.222135959 1.3581799069 1.4231376034 1.520350106 1.2428702623 1.0178157656 +1.5044062049 0.99411558047 1.6344608241 1.4966713078 1.3188322198 1.0301077486 1.616171492 1.0639004691 1.6906163682 +1.2985132371 1.694155533 1.4298639508 1.2754805207 1.5695918806 1.3146979329 0.91878146884 1.4349635804 1.1490441769 +1.4266149886 0.93060946745 1.4709433172 1.5917298841 1.2939274231 1.1325626547 1.6744797636 1.5838923439 1.6608700472 +1.1054163417 1.2670805584 1.5022744706 1.5666642509 0.95922678642 0.977749964 1.1362736448 1.2203507846 0.91603176496 +1.6159607704 1.5596527133 1.6996940632 1.5289979623 1.6921669413 1.1749886487 1.4404760186 1.3154613055 1.6040152873 +1.1724727671 1.412255004 1.5028023512 0.90199838935 1.7195428518 1.364231313 1.5657305707 1.3666951307 1.2842746014 +1.6249380954 1.173353261 1.0945018898 1.4733808455 1.5333603701 1.0820481704 1.646431429 1.4486097581 1.4524372855 +1.0526078653 1.2369870533 diff --git a/examples/mapping_tester/run.sh b/examples/mapping_tester/run.sh new file mode 100755 index 00000000..62b2c4e6 --- /dev/null +++ b/examples/mapping_tester/run.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +set -e -x + +# Get the test location +TEST_LOCATION="$(pwd)" +export TEST_LOCATION + +# The mapping-tester location +MAPPING_TESTER="${TEST_LOCATION}"/../../tools/mapping-tester/ + +# The case directory +TEST_CASE_LOCATION="${TEST_LOCATION}"/case + +# Generate the run scripts +python3 "${MAPPING_TESTER}"/generate.py --setup "${TEST_LOCATION}"/setup-test.json --outdir "${TEST_CASE_LOCATION}" --template "${MAPPING_TESTER}"/config-template.xml + +# Prepare the meshes +python3 "${MAPPING_TESTER}"/preparemeshes.py --setup "${TEST_LOCATION}"/setup-test.json --outdir "${TEST_CASE_LOCATION}" --force + +export ASTE_A_MPIARGS="" +export ASTE_B_MPIARGS="" + +# Run the actual cases +cd "${TEST_CASE_LOCATION}" && bash ./runall.sh + +# Postprocess the test cases +bash ./postprocessall.sh + +cd "${TEST_LOCATION}" + +# Gather the generated statistics +python3 "${MAPPING_TESTER}"/gatherstats.py --outdir "${TEST_CASE_LOCATION}" --file test-statistics.csv diff --git a/examples/mapping_tester/setup-test.json b/examples/mapping_tester/setup-test.json new file mode 100644 index 00000000..8644f0a5 --- /dev/null +++ b/examples/mapping_tester/setup-test.json @@ -0,0 +1,48 @@ +{ + "general": { + "function": "0.78 + cos(10*(x+y+z))", + "ranks": { + "A": [ + 2 + ], + "B": [ + 2 + ] + }, + "syncmode": false, + "meshes": { + "A": { + "coarse_mesh": "${TEST_LOCATION}/coarse_mesh.vtk" + }, + "B": { + "fine_mesh": "${TEST_LOCATION}/fine_mesh.vtk" + } + } + }, + "groups": [ + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "tps": { + "kind": "rbf-thin-plate-splines", + "options": "use-qr-decomposition=\"1\"" + }, + "np": { + "kind": "nearest-projection" + } + } + }, + "meshes": { + "A": [ + "coarse_mesh" + ], + "B": [ + "fine_mesh" + ] + } + } + ] +} diff --git a/examples/nn/clean.sh b/examples/nn/clean.sh new file mode 100755 index 00000000..eb71aca8 --- /dev/null +++ b/examples/nn/clean.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -e -x + +rm -f -r precice-run +rm -f precice-*-events*.json +rm -f *.log +rm -f map*.vtk +rm -f fine_mesh_*.vtk diff --git a/examples/nn/precice-config.xml b/examples/nn/precice-config.xml new file mode 100644 index 00000000..f5e6bea0 --- /dev/null +++ b/examples/nn/precice-config.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/nn/run.sh b/examples/nn/run.sh new file mode 100755 index 00000000..b7cb0296 --- /dev/null +++ b/examples/nn/run.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -e -x + +# Calculate franke function on fine mesh +precice-aste-evaluate -m ../fine_mesh.vtk -f "franke3d" -d "Franke Function" -o "fine_mesh_nn.vtk" + +# Map from the finer mesh to coarser mesh +precice-aste-run -v -p A --mesh fine_mesh_nn --data "Franke Function" & +precice-aste-run -v -p B --mesh ../coarse_mesh --output map_nn --data "InterpolatedData" + +# Calculate statistics +precice-aste-evaluate -m map_nn.vtk -f "franke3d" -d difference --diffdata "InterpolatedData" --diff diff --git a/examples/nng_scalar/clean.sh b/examples/nng_scalar/clean.sh new file mode 100755 index 00000000..eb71aca8 --- /dev/null +++ b/examples/nng_scalar/clean.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -e -x + +rm -f -r precice-run +rm -f precice-*-events*.json +rm -f *.log +rm -f map*.vtk +rm -f fine_mesh_*.vtk diff --git a/examples/nng_scalar/precice-config.xml b/examples/nng_scalar/precice-config.xml new file mode 100644 index 00000000..5e730150 --- /dev/null +++ b/examples/nng_scalar/precice-config.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/nng_scalar/run.sh b/examples/nng_scalar/run.sh new file mode 100755 index 00000000..e141f93c --- /dev/null +++ b/examples/nng_scalar/run.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -e -x + +# Calculate distance from origin on fine mesh +precice-aste-evaluate -m ../fine_mesh.vtk -f "sqrt(x^2+y^2+z^2)" -d "Distance" -o "fine_mesh_nng.vtk" --gradient + +# Map from the finer mesh to coarser mesh +precice-aste-run -v -p A --mesh fine_mesh_nng --data "Distance" & +precice-aste-run -v -p B --mesh ../coarse_mesh --output map_nng --data "InterpolatedData" + +# Calculate statistics +precice-aste-evaluate -m map_nng.vtk -f "sqrt(x^2+y^2+z^2)" -d difference --diffdata "InterpolatedData" --diff diff --git a/examples/nng_vector/clean.sh b/examples/nng_vector/clean.sh new file mode 100755 index 00000000..eb71aca8 --- /dev/null +++ b/examples/nng_vector/clean.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -e -x + +rm -f -r precice-run +rm -f precice-*-events*.json +rm -f *.log +rm -f map*.vtk +rm -f fine_mesh_*.vtk diff --git a/examples/nng_vector/precice-config.xml b/examples/nng_vector/precice-config.xml new file mode 100644 index 00000000..2a05e7a1 --- /dev/null +++ b/examples/nng_vector/precice-config.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/nng_vector/run.sh b/examples/nng_vector/run.sh new file mode 100755 index 00000000..d652f531 --- /dev/null +++ b/examples/nng_vector/run.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -e -x + +# Calculate distance from origin on fine mesh +precice-aste-evaluate -m ../fine_mesh.vtk -f "sin(x)*iHat+cos(y)*jHat+z^2*kHat" -d "MyFunction" -o "fine_mesh_nng.vtk" --gradient + +# Map from the finer mesh to coarser mesh +precice-aste-run -v -p A --mesh fine_mesh_nng --data "MyFunction" --vector & +precice-aste-run -v -p B --mesh ../coarse_mesh --output map_nng --data "InterpolatedData" --vector + +# Calculate statistics +precice-aste-evaluate -m map_nng.vtk -f "sin(x)*iHat+cos(y)*jHat+z^2*kHat" -d difference --diffdata "InterpolatedData" --diff diff --git a/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt1.vtu b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt1.vtu new file mode 100644 index 00000000..a300e9dd --- /dev/null +++ b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt1.vtu @@ -0,0 +1,66 @@ + + + + + + + 0 -0.005 0 + 0 0.005 0 + 0.00714286 -0.01 0 + 0.0214286 -0.01 0 + 0.0357143 -0.01 0 + 0.05 -0.01 0 + 0.0642857 -0.01 0 + 0.0785714 -0.01 0 + 0.0928571 -0.01 0 + 0.107143 -0.01 0 + 0.121429 -0.01 0 + 0.135714 -0.01 0 + 0.15 -0.01 0 + 0.164286 -0.01 0 + 0.178571 -0.01 0 + 0.192857 -0.01 0 + 0.00714286 0.01 0 + 0.0214286 0.01 0 + 0.0357143 0.01 0 + 0.05 0.01 0 + 0.0642857 0.01 0 + 0.0785714 0.01 0 + 0.0928571 0.01 0 + 0.107143 0.01 0 + 0.121429 0.01 0 + 0.135714 0.01 0 + 0.15 0.01 0 + 0.164286 0.01 0 + 0.178571 0.01 0 + 0.192857 0.01 0 + 0.2 -0.005 0 + 0.2 0.005 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + 54.1519 0.00192 0.0 54.1571 -0.00346487 0.0 0.53834 72.1138 0.0 0.490154 70.3374 0.0 0.465314 68.7152 0.0 0.462388 66.8928 0.0 0.466386 64.9996 0.0 0.468251 63.1042 0.0 0.46933 61.2094 0.0 0.470676 59.3081 0.0 0.472606 57.3978 0.0 0.475533 55.4752 0.0 0.480258 53.5332 0.0 0.488401 51.5577 0.0 0.504943 49.5186 0.0 0.523778 47.3253 0.0 0.538546 -72.1593 0.0 0.491245 -70.3727 0.0 0.466672 -68.7402 0.0 0.46384 -66.9117 0.0 0.46778 -65.0128 0.0 0.469638 -63.1117 0.0 0.470703 -61.2112 0.0 0.471996 -59.3045 0.0 0.473825 -57.3892 0.0 0.476591 -55.4624 0.0 0.481089 -53.5171 0.0 0.48893 -51.5398 0.0 0.505046 -49.5005 0.0 0.523306 -47.3099 0.0 -30.6978 -0.0416951 0.0 -30.6992 0.0417191 0.0 + + + -5.70125e-08 0 0.0 5.70125e-08 0 0.0 -1.14025e-07 -8.14458e-08 0.0 -1.14026e-07 -2.44339e-07 0.0 -1.14027e-07 -4.07232e-07 0.0 -1.14028e-07 -5.70125e-07 0.0 -1.14029e-07 -7.33017e-07 0.0 -1.1403e-07 -8.9591e-07 0.0 -1.14031e-07 -1.0588e-06 0.0 -1.14032e-07 -1.2217e-06 0.0 -1.14033e-07 -1.38459e-06 0.0 -1.14034e-07 -1.54748e-06 0.0 -1.14035e-07 -1.71037e-06 0.0 -1.14036e-07 -1.87327e-06 0.0 -1.14037e-07 -2.03616e-06 0.0 -1.14038e-07 -2.19905e-06 0.0 1.14025e-07 -8.14471e-08 0.0 1.14024e-07 -2.4434e-07 0.0 1.14023e-07 -4.07233e-07 0.0 1.14022e-07 -5.70126e-07 0.0 1.14021e-07 -7.33019e-07 0.0 1.1402e-07 -8.95912e-07 0.0 1.14019e-07 -1.0588e-06 0.0 1.14018e-07 -1.2217e-06 0.0 1.14017e-07 -1.38459e-06 0.0 1.14016e-07 -1.54748e-06 0.0 1.14015e-07 -1.71038e-06 0.0 1.14014e-07 -1.87327e-06 0.0 1.14013e-07 -2.03616e-06 0.0 1.14012e-07 -2.19905e-06 0.0 -5.70255e-08 -2.2805e-06 0.0 5.69995e-08 -2.2805e-06 0.0 + + + + + diff --git a/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt10.vtu b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt10.vtu new file mode 100644 index 00000000..2a66b2a5 --- /dev/null +++ b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt10.vtu @@ -0,0 +1,66 @@ + + + + + + + 0 -0.005 0 + 0 0.005 0 + 0.00714286 -0.01 0 + 0.0214286 -0.01 0 + 0.0357143 -0.01 0 + 0.05 -0.01 0 + 0.0642857 -0.01 0 + 0.0785714 -0.01 0 + 0.0928571 -0.01 0 + 0.107143 -0.01 0 + 0.121429 -0.01 0 + 0.135714 -0.01 0 + 0.15 -0.01 0 + 0.164286 -0.01 0 + 0.178571 -0.01 0 + 0.192857 -0.01 0 + 0.00714286 0.01 0 + 0.0214286 0.01 0 + 0.0357143 0.01 0 + 0.05 0.01 0 + 0.0642857 0.01 0 + 0.0785714 0.01 0 + 0.0928571 0.01 0 + 0.107143 0.01 0 + 0.121429 0.01 0 + 0.135714 0.01 0 + 0.15 0.01 0 + 0.164286 0.01 0 + 0.178571 0.01 0 + 0.192857 0.01 0 + 0.2 -0.005 0 + 0.2 0.005 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + 2.05494 0.019783 0.0 2.07429 -0.027611 0.0 0.43293 0.0861433 0.0 0.295646 -0.00314185 0.0 0.213799 0.126627 0.0 0.191495 0.189129 0.0 0.177529 0.187875 0.0 0.17322 0.18953 0.0 0.173483 0.180875 0.0 0.176361 0.156998 0.0 0.180688 0.122102 0.0 0.186233 0.0786987 0.0 0.193552 0.0276778 0.0 0.203129 -0.0317309 0.0 0.215858 -0.102118 0.0 0.222201 -0.174018 0.0 0.445741 -0.304019 0.0 0.31258 -0.191238 0.0 0.229289 -0.266459 0.0 0.200283 -0.298626 0.0 0.18828 -0.297146 0.0 0.18218 -0.283586 0.0 0.181442 -0.261033 0.0 0.183438 -0.227024 0.0 0.18731 -0.183607 0.0 0.192676 -0.132148 0.0 0.200002 -0.0728117 0.0 0.209781 -0.00423168 0.0 0.222894 0.0767767 0.0 0.229982 0.161495 0.0 0.324234 -0.0178598 0.0 0.331416 0.0202628 0.0 + + + 4.50389e-06 2.02851e-09 0.0 -4.50389e-06 -2.02851e-09 0.0 9.00489e-06 6.43819e-06 0.0 8.99909e-06 1.93065e-05 0.0 8.9933e-06 3.21747e-05 0.0 8.9875e-06 4.5043e-05 0.0 8.98171e-06 5.79113e-05 0.0 8.97591e-06 7.07795e-05 0.0 8.97012e-06 8.36478e-05 0.0 8.96432e-06 9.65161e-05 0.0 8.95852e-06 0.000109384 0.0 8.95273e-06 0.000122253 0.0 8.94693e-06 0.000135121 0.0 8.94114e-06 0.000147989 0.0 8.93534e-06 0.000160857 0.0 8.92955e-06 0.000173726 0.0 -9.01069e-06 6.43008e-06 0.0 -9.01648e-06 1.92983e-05 0.0 -9.02228e-06 3.21666e-05 0.0 -9.02807e-06 4.50349e-05 0.0 -9.03387e-06 5.79032e-05 0.0 -9.03966e-06 7.07714e-05 0.0 -9.04546e-06 8.36397e-05 0.0 -9.05126e-06 9.6508e-05 0.0 -9.05705e-06 0.000109376 0.0 -9.06285e-06 0.000122244 0.0 -9.06864e-06 0.000135113 0.0 -9.07444e-06 0.000147981 0.0 -9.08023e-06 0.000160849 0.0 -9.08603e-06 0.000173718 0.0 4.42275e-06 0.000180158 0.0 -4.58503e-06 0.000180154 0.0 + + + + + diff --git a/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt2.vtu b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt2.vtu new file mode 100644 index 00000000..ab7cdd15 --- /dev/null +++ b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt2.vtu @@ -0,0 +1,66 @@ + + + + + + + 0 -0.005 0 + 0 0.005 0 + 0.00714286 -0.01 0 + 0.0214286 -0.01 0 + 0.0357143 -0.01 0 + 0.05 -0.01 0 + 0.0642857 -0.01 0 + 0.0785714 -0.01 0 + 0.0928571 -0.01 0 + 0.107143 -0.01 0 + 0.121429 -0.01 0 + 0.135714 -0.01 0 + 0.15 -0.01 0 + 0.164286 -0.01 0 + 0.178571 -0.01 0 + 0.192857 -0.01 0 + 0.00714286 0.01 0 + 0.0214286 0.01 0 + 0.0357143 0.01 0 + 0.05 0.01 0 + 0.0642857 0.01 0 + 0.0785714 0.01 0 + 0.0928571 0.01 0 + 0.107143 0.01 0 + 0.121429 0.01 0 + 0.135714 0.01 0 + 0.15 0.01 0 + 0.164286 0.01 0 + 0.178571 0.01 0 + 0.192857 0.01 0 + 0.2 -0.005 0 + 0.2 0.005 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + -22.7601 -0.00273501 0.0 -22.7555 0.00130573 0.0 0.523404 -33.9643 0.0 0.40329 -32.9048 0.0 0.343319 -31.6636 0.0 0.338924 -30.7161 0.0 0.348185 -29.8721 0.0 0.353993 -29.0324 0.0 0.357719 -28.2042 0.0 0.360939 -27.3921 0.0 0.364277 -26.591 0.0 0.368272 -25.7967 0.0 0.373832 -25.0085 0.0 0.38255 -24.2265 0.0 0.399838 -23.4527 0.0 0.412589 -22.6986 0.0 0.525162 33.9205 0.0 0.406684 32.8763 0.0 0.346698 31.6491 0.0 0.342085 30.7074 0.0 0.351012 29.8675 0.0 0.3566 29.0309 0.0 0.360166 28.205 0.0 0.363225 27.3944 0.0 0.366375 26.5944 0.0 0.370138 25.8006 0.0 0.375402 25.0126 0.0 0.383725 24.2305 0.0 0.400472 23.4559 0.0 0.41233 22.6997 0.0 15.7177 -0.0204011 0.0 15.7136 0.0198947 0.0 + + + -1.1547e-07 0 0.0 1.1547e-07 0 0.0 -2.30942e-07 -1.64954e-07 0.0 -2.30946e-07 -4.94869e-07 0.0 -2.3095e-07 -8.24783e-07 0.0 -2.30953e-07 -1.1547e-06 0.0 -2.30957e-07 -1.48461e-06 0.0 -2.30961e-07 -1.81453e-06 0.0 -2.30965e-07 -2.14444e-06 0.0 -2.30969e-07 -2.47436e-06 0.0 -2.30972e-07 -2.80427e-06 0.0 -2.30976e-07 -3.13418e-06 0.0 -2.3098e-07 -3.4641e-06 0.0 -2.30984e-07 -3.79401e-06 0.0 -2.30988e-07 -4.12393e-06 0.0 -2.30991e-07 -4.45384e-06 0.0 2.30938e-07 -1.6496e-07 0.0 2.30934e-07 -4.94874e-07 0.0 2.30931e-07 -8.24789e-07 0.0 2.30927e-07 -1.1547e-06 0.0 2.30923e-07 -1.48462e-06 0.0 2.30919e-07 -1.81453e-06 0.0 2.30915e-07 -2.14445e-06 0.0 2.30911e-07 -2.47436e-06 0.0 2.30908e-07 -2.80427e-06 0.0 2.30904e-07 -3.13419e-06 0.0 2.309e-07 -3.4641e-06 0.0 2.30896e-07 -3.79402e-06 0.0 2.30892e-07 -4.12393e-06 0.0 2.30889e-07 -4.45385e-06 0.0 -1.15523e-07 -4.6188e-06 0.0 1.15417e-07 -4.6188e-06 0.0 + + + + + diff --git a/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt3.vtu b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt3.vtu new file mode 100644 index 00000000..68d1df2d --- /dev/null +++ b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt3.vtu @@ -0,0 +1,66 @@ + + + + + + + 0 -0.005 0 + 0 0.005 0 + 0.00714286 -0.01 0 + 0.0214286 -0.01 0 + 0.0357143 -0.01 0 + 0.05 -0.01 0 + 0.0642857 -0.01 0 + 0.0785714 -0.01 0 + 0.0928571 -0.01 0 + 0.107143 -0.01 0 + 0.121429 -0.01 0 + 0.135714 -0.01 0 + 0.15 -0.01 0 + 0.164286 -0.01 0 + 0.178571 -0.01 0 + 0.192857 -0.01 0 + 0.00714286 0.01 0 + 0.0214286 0.01 0 + 0.0357143 0.01 0 + 0.05 0.01 0 + 0.0642857 0.01 0 + 0.0785714 0.01 0 + 0.0928571 0.01 0 + 0.107143 0.01 0 + 0.121429 0.01 0 + 0.135714 0.01 0 + 0.15 0.01 0 + 0.164286 0.01 0 + 0.178571 0.01 0 + 0.192857 0.01 0 + 0.2 -0.005 0 + 0.2 0.005 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + 2.4704 0.0103563 0.0 2.47623 -0.0131132 0.0 0.467496 0.707295 0.0 0.352181 0.659928 0.0 0.272942 0.889487 0.0 0.263273 0.991035 0.0 0.270957 0.989203 0.0 0.279595 0.97438 0.0 0.286236 0.9428 0.0 0.291861 0.888499 0.0 0.297113 0.817441 0.0 0.302574 0.734435 0.0 0.309407 0.639832 0.0 0.319137 0.530531 0.0 0.336076 0.400258 0.0 0.348053 0.240381 0.0 0.471038 -0.772256 0.0 0.35593 -0.711887 0.0 0.277218 -0.925248 0.0 0.266749 -1.0148 0.0 0.273972 -1.00638 0.0 0.282044 -0.986037 0.0 0.288425 -0.950904 0.0 0.29383 -0.893572 0.0 0.298857 -0.819953 0.0 0.304062 -0.734899 0.0 0.310581 -0.638758 0.0 0.31992 -0.528479 0.0 0.336339 -0.397921 0.0 0.347607 -0.238898 0.0 0.352356 -0.0173365 0.0 0.347613 0.0165112 0.0 + + + -1.29384e-07 0 0.0 1.29384e-07 0 0.0 -2.58769e-07 -1.8483e-07 0.0 -2.58774e-07 -5.54498e-07 0.0 -2.58779e-07 -9.24165e-07 0.0 -2.58784e-07 -1.29383e-06 0.0 -2.58789e-07 -1.6635e-06 0.0 -2.58793e-07 -2.03317e-06 0.0 -2.58798e-07 -2.40283e-06 0.0 -2.58803e-07 -2.7725e-06 0.0 -2.58808e-07 -3.14217e-06 0.0 -2.58813e-07 -3.51184e-06 0.0 -2.58817e-07 -3.8815e-06 0.0 -2.58822e-07 -4.25117e-06 0.0 -2.58827e-07 -4.62084e-06 0.0 -2.58832e-07 -4.9905e-06 0.0 2.58765e-07 -1.84837e-07 0.0 2.5876e-07 -5.54504e-07 0.0 2.58755e-07 -9.24171e-07 0.0 2.5875e-07 -1.29384e-06 0.0 2.58746e-07 -1.66351e-06 0.0 2.58741e-07 -2.03317e-06 0.0 2.58736e-07 -2.40284e-06 0.0 2.58731e-07 -2.77251e-06 0.0 2.58726e-07 -3.14217e-06 0.0 2.58722e-07 -3.51184e-06 0.0 2.58717e-07 -3.88151e-06 0.0 2.58712e-07 -4.25118e-06 0.0 2.58707e-07 -4.62084e-06 0.0 2.58702e-07 -4.99051e-06 0.0 -1.2945e-07 -5.17534e-06 0.0 1.29317e-07 -5.17534e-06 0.0 + + + + + diff --git a/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt4.vtu b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt4.vtu new file mode 100644 index 00000000..283aaa3c --- /dev/null +++ b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt4.vtu @@ -0,0 +1,66 @@ + + + + + + + 0 -0.005 0 + 0 0.005 0 + 0.00714286 -0.01 0 + 0.0214286 -0.01 0 + 0.0357143 -0.01 0 + 0.05 -0.01 0 + 0.0642857 -0.01 0 + 0.0785714 -0.01 0 + 0.0928571 -0.01 0 + 0.107143 -0.01 0 + 0.121429 -0.01 0 + 0.135714 -0.01 0 + 0.15 -0.01 0 + 0.164286 -0.01 0 + 0.178571 -0.01 0 + 0.192857 -0.01 0 + 0.00714286 0.01 0 + 0.0214286 0.01 0 + 0.0357143 0.01 0 + 0.05 0.01 0 + 0.0642857 0.01 0 + 0.0785714 0.01 0 + 0.0928571 0.01 0 + 0.107143 0.01 0 + 0.121429 0.01 0 + 0.135714 0.01 0 + 0.15 0.01 0 + 0.164286 0.01 0 + 0.178571 0.01 0 + 0.192857 0.01 0 + 0.2 -0.005 0 + 0.2 0.005 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + 2.33787 0.0176547 0.0 2.34497 -0.0215011 0.0 0.447391 0.522153 0.0 0.321321 0.408082 0.0 0.239597 0.562105 0.0 0.221768 0.658219 0.0 0.223731 0.683062 0.0 0.2319 0.690314 0.0 0.240033 0.683628 0.0 0.24818 0.649813 0.0 0.255511 0.596092 0.0 0.262502 0.528945 0.0 0.270477 0.449205 0.0 0.280973 0.355381 0.0 0.297011 0.243569 0.0 0.307601 0.117856 0.0 0.452956 -0.605201 0.0 0.32681 -0.476777 0.0 0.245321 -0.610537 0.0 0.226919 -0.691573 0.0 0.227766 -0.707198 0.0 0.235014 -0.708904 0.0 0.242994 -0.697757 0.0 0.250696 -0.660164 0.0 0.257671 -0.60316 0.0 0.264356 -0.533133 0.0 0.271991 -0.451148 0.0 0.282085 -0.355649 0.0 0.297661 -0.242711 0.0 0.307571 -0.116498 0.0 0.301869 -0.0184142 0.0 0.299088 0.0175387 0.0 + + + -6.63212e-08 0 0.0 6.63212e-08 0 0.0 -1.32643e-07 -9.47437e-08 0.0 -1.32644e-07 -2.84233e-07 0.0 -1.32646e-07 -4.73722e-07 0.0 -1.32647e-07 -6.63211e-07 0.0 -1.32648e-07 -8.527e-07 0.0 -1.32649e-07 -1.04219e-06 0.0 -1.32651e-07 -1.23168e-06 0.0 -1.32652e-07 -1.42117e-06 0.0 -1.32653e-07 -1.61066e-06 0.0 -1.32654e-07 -1.80015e-06 0.0 -1.32656e-07 -1.98964e-06 0.0 -1.32657e-07 -2.17912e-06 0.0 -1.32658e-07 -2.36861e-06 0.0 -1.32659e-07 -2.5581e-06 0.0 1.32642e-07 -9.47455e-08 0.0 1.32641e-07 -2.84235e-07 0.0 1.32639e-07 -4.73724e-07 0.0 1.32638e-07 -6.63213e-07 0.0 1.32637e-07 -8.52702e-07 0.0 1.32635e-07 -1.04219e-06 0.0 1.32634e-07 -1.23168e-06 0.0 1.32633e-07 -1.42117e-06 0.0 1.32632e-07 -1.61066e-06 0.0 1.3263e-07 -1.80015e-06 0.0 1.32629e-07 -1.98964e-06 0.0 1.32628e-07 -2.17913e-06 0.0 1.32627e-07 -2.36862e-06 0.0 1.32625e-07 -2.5581e-06 0.0 -6.63388e-08 -2.65285e-06 0.0 6.63036e-08 -2.65285e-06 0.0 + + + + + diff --git a/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt5.vtu b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt5.vtu new file mode 100644 index 00000000..e78db590 --- /dev/null +++ b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt5.vtu @@ -0,0 +1,66 @@ + + + + + + + 0 -0.005 0 + 0 0.005 0 + 0.00714286 -0.01 0 + 0.0214286 -0.01 0 + 0.0357143 -0.01 0 + 0.05 -0.01 0 + 0.0642857 -0.01 0 + 0.0785714 -0.01 0 + 0.0928571 -0.01 0 + 0.107143 -0.01 0 + 0.121429 -0.01 0 + 0.135714 -0.01 0 + 0.15 -0.01 0 + 0.164286 -0.01 0 + 0.178571 -0.01 0 + 0.192857 -0.01 0 + 0.00714286 0.01 0 + 0.0214286 0.01 0 + 0.0357143 0.01 0 + 0.05 0.01 0 + 0.0642857 0.01 0 + 0.0785714 0.01 0 + 0.0928571 0.01 0 + 0.107143 0.01 0 + 0.121429 0.01 0 + 0.135714 0.01 0 + 0.15 0.01 0 + 0.164286 0.01 0 + 0.178571 0.01 0 + 0.192857 0.01 0 + 0.2 -0.005 0 + 0.2 0.005 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + 2.23002 0.0199313 0.0 2.23919 -0.0249124 0.0 0.441734 0.385826 0.0 0.308061 0.277911 0.0 0.226629 0.388505 0.0 0.201777 0.461535 0.0 0.197892 0.48898 0.0 0.202966 0.502242 0.0 0.211075 0.504504 0.0 0.219921 0.485362 0.0 0.228571 0.445276 0.0 0.23687 0.3902 0.0 0.245822 0.321731 0.0 0.256863 0.239015 0.0 0.272253 0.138777 0.0 0.281588 0.029782 0.0 0.448897 -0.489933 0.0 0.316698 -0.366521 0.0 0.234564 -0.444659 0.0 0.20505 -0.490184 0.0 0.202557 -0.517266 0.0 0.206713 -0.529339 0.0 0.21453 -0.52708 0.0 0.223039 -0.50327 0.0 0.2313 -0.458995 0.0 0.239256 -0.40015 0.0 0.247853 -0.328453 0.0 0.258502 -0.243057 0.0 0.273438 -0.140588 0.0 0.282214 -0.0297573 0.0 0.292997 -0.0194383 0.0 0.291969 0.0188551 0.0 + + + 1.08843e-07 0 0.0 -1.08843e-07 0 0.0 2.17684e-07 1.55492e-07 0.0 2.1768e-07 4.66471e-07 0.0 2.17677e-07 7.7745e-07 0.0 2.17674e-07 1.08843e-06 0.0 2.1767e-07 1.39941e-06 0.0 2.17667e-07 1.71039e-06 0.0 2.17663e-07 2.02137e-06 0.0 2.1766e-07 2.33235e-06 0.0 2.17657e-07 2.64333e-06 0.0 2.17653e-07 2.9543e-06 0.0 2.1765e-07 3.26528e-06 0.0 2.17647e-07 3.57626e-06 0.0 2.17643e-07 3.88724e-06 0.0 2.1764e-07 4.19822e-06 0.0 -2.17687e-07 1.55487e-07 0.0 -2.17691e-07 4.66466e-07 0.0 -2.17694e-07 7.77446e-07 0.0 -2.17697e-07 1.08842e-06 0.0 -2.17701e-07 1.3994e-06 0.0 -2.17704e-07 1.71038e-06 0.0 -2.17707e-07 2.02136e-06 0.0 -2.17711e-07 2.33234e-06 0.0 -2.17714e-07 2.64332e-06 0.0 -2.17718e-07 2.9543e-06 0.0 -2.17721e-07 3.26528e-06 0.0 -2.17724e-07 3.57626e-06 0.0 -2.17728e-07 3.88724e-06 0.0 -2.17731e-07 4.19822e-06 0.0 1.08795e-07 4.35371e-06 0.0 -1.0889e-07 4.35371e-06 0.0 + + + + + diff --git a/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt6.vtu b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt6.vtu new file mode 100644 index 00000000..df0f8246 --- /dev/null +++ b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt6.vtu @@ -0,0 +1,66 @@ + + + + + + + 0 -0.005 0 + 0 0.005 0 + 0.00714286 -0.01 0 + 0.0214286 -0.01 0 + 0.0357143 -0.01 0 + 0.05 -0.01 0 + 0.0642857 -0.01 0 + 0.0785714 -0.01 0 + 0.0928571 -0.01 0 + 0.107143 -0.01 0 + 0.121429 -0.01 0 + 0.135714 -0.01 0 + 0.15 -0.01 0 + 0.164286 -0.01 0 + 0.178571 -0.01 0 + 0.192857 -0.01 0 + 0.00714286 0.01 0 + 0.0214286 0.01 0 + 0.0357143 0.01 0 + 0.05 0.01 0 + 0.0642857 0.01 0 + 0.0785714 0.01 0 + 0.0928571 0.01 0 + 0.107143 0.01 0 + 0.121429 0.01 0 + 0.135714 0.01 0 + 0.15 0.01 0 + 0.164286 0.01 0 + 0.178571 0.01 0 + 0.192857 0.01 0 + 0.2 -0.005 0 + 0.2 0.005 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + 2.15845 0.0203216 0.0 2.16982 -0.0263426 0.0 0.438029 0.283846 0.0 0.303175 0.188135 0.0 0.222236 0.287531 0.0 0.192735 0.343394 0.0 0.185909 0.370909 0.0 0.186735 0.380071 0.0 0.192959 0.380542 0.0 0.201165 0.367228 0.0 0.210033 0.336426 0.0 0.219082 0.289968 0.0 0.228706 0.230017 0.0 0.240111 0.156044 0.0 0.255151 0.0650037 0.0 0.263792 -0.0333011 0.0 0.446389 -0.411078 0.0 0.31403 -0.300546 0.0 0.231727 -0.370129 0.0 0.200597 -0.392089 0.0 0.189712 -0.401096 0.0 0.190768 -0.411561 0.0 0.196619 -0.411106 0.0 0.204765 -0.393758 0.0 0.213397 -0.358277 0.0 0.222132 -0.307259 0.0 0.231426 -0.24301 0.0 0.242477 -0.165088 0.0 0.257124 -0.0703863 0.0 0.265312 0.0314084 0.0 0.299176 -0.0198192 0.0 0.29966 0.0196432 0.0 + + + 4.42526e-07 0 0.0 -4.42526e-07 0 0.0 8.85024e-07 6.32219e-07 0.0 8.84968e-07 1.89658e-06 0.0 8.84912e-07 3.16094e-06 0.0 8.84856e-07 4.4253e-06 0.0 8.848e-07 5.68966e-06 0.0 8.84744e-07 6.95402e-06 0.0 8.84688e-07 8.21838e-06 0.0 8.84632e-07 9.48274e-06 0.0 8.84576e-07 1.07471e-05 0.0 8.8452e-07 1.20115e-05 0.0 8.84464e-07 1.32758e-05 0.0 8.84408e-07 1.45402e-05 0.0 8.84352e-07 1.58045e-05 0.0 8.84296e-07 1.70689e-05 0.0 -8.8508e-07 6.3214e-07 0.0 -8.85136e-07 1.8965e-06 0.0 -8.85192e-07 3.16086e-06 0.0 -8.85248e-07 4.42522e-06 0.0 -8.85304e-07 5.68958e-06 0.0 -8.85359e-07 6.95394e-06 0.0 -8.85415e-07 8.2183e-06 0.0 -8.85471e-07 9.48266e-06 0.0 -8.85527e-07 1.0747e-05 0.0 -8.85583e-07 1.20114e-05 0.0 -8.85639e-07 1.32757e-05 0.0 -8.85695e-07 1.45401e-05 0.0 -8.85751e-07 1.58045e-05 0.0 -8.85807e-07 1.70688e-05 0.0 4.41743e-07 1.77011e-05 0.0 -4.43309e-07 1.7701e-05 0.0 + + + + + diff --git a/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt7.vtu b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt7.vtu new file mode 100644 index 00000000..3574037b --- /dev/null +++ b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt7.vtu @@ -0,0 +1,66 @@ + + + + + + + 0 -0.005 0 + 0 0.005 0 + 0.00714286 -0.01 0 + 0.0214286 -0.01 0 + 0.0357143 -0.01 0 + 0.05 -0.01 0 + 0.0642857 -0.01 0 + 0.0785714 -0.01 0 + 0.0928571 -0.01 0 + 0.107143 -0.01 0 + 0.121429 -0.01 0 + 0.135714 -0.01 0 + 0.15 -0.01 0 + 0.164286 -0.01 0 + 0.178571 -0.01 0 + 0.192857 -0.01 0 + 0.00714286 0.01 0 + 0.0214286 0.01 0 + 0.0357143 0.01 0 + 0.05 0.01 0 + 0.0642857 0.01 0 + 0.0785714 0.01 0 + 0.0928571 0.01 0 + 0.107143 0.01 0 + 0.121429 0.01 0 + 0.135714 0.01 0 + 0.15 0.01 0 + 0.164286 0.01 0 + 0.178571 0.01 0 + 0.192857 0.01 0 + 0.2 -0.005 0 + 0.2 0.005 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + 2.11476 0.0202189 0.0 2.12821 -0.0270695 0.0 0.435228 0.20991 0.0 0.300477 0.118987 0.0 0.220209 0.224893 0.0 0.191916 0.274054 0.0 0.180661 0.292654 0.0 0.178591 0.299677 0.0 0.182257 0.296499 0.0 0.189068 0.282123 0.0 0.197072 0.254144 0.0 0.20601 0.213262 0.0 0.215817 0.159522 0.0 0.227335 0.0925734 0.0 0.24209 0.00939097 0.0 0.250333 -0.0802768 0.0 0.444881 -0.361188 0.0 0.312241 -0.252972 0.0 0.230133 -0.331236 0.0 0.201527 -0.35507 0.0 0.186811 -0.34666 0.0 0.183699 -0.344722 0.0 0.186805 -0.33756 0.0 0.193262 -0.318495 0.0 0.201101 -0.285359 0.0 0.209804 -0.239186 0.0 0.21936 -0.180159 0.0 0.230612 -0.107898 0.0 0.245079 -0.0193223 0.0 0.253044 0.0759251 0.0 0.306884 -0.0196803 0.0 0.308822 0.0199908 0.0 + + + 9.98036e-07 0 0.0 -9.98036e-07 0 0.0 1.99593e-06 1.42597e-06 0.0 1.99565e-06 4.2775e-06 0.0 1.99536e-06 7.12903e-06 0.0 1.99508e-06 9.98056e-06 0.0 1.99479e-06 1.28321e-05 0.0 1.99451e-06 1.56836e-05 0.0 1.99422e-06 1.85352e-05 0.0 1.99394e-06 2.13867e-05 0.0 1.99365e-06 2.42382e-05 0.0 1.99337e-06 2.70898e-05 0.0 1.99308e-06 2.99413e-05 0.0 1.9928e-06 3.27928e-05 0.0 1.99252e-06 3.56444e-05 0.0 1.99223e-06 3.84959e-05 0.0 -1.99622e-06 1.42557e-06 0.0 -1.9965e-06 4.2771e-06 0.0 -1.99678e-06 7.12863e-06 0.0 -1.99707e-06 9.98016e-06 0.0 -1.99735e-06 1.28317e-05 0.0 -1.99764e-06 1.56832e-05 0.0 -1.99792e-06 1.85348e-05 0.0 -1.99821e-06 2.13863e-05 0.0 -1.99849e-06 2.42378e-05 0.0 -1.99878e-06 2.70894e-05 0.0 -1.99906e-06 2.99409e-05 0.0 -1.99935e-06 3.27924e-05 0.0 -1.99963e-06 3.5644e-05 0.0 -1.99991e-06 3.84955e-05 0.0 9.94052e-07 3.99216e-05 0.0 -1.00202e-06 3.99214e-05 0.0 + + + + + diff --git a/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt8.vtu b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt8.vtu new file mode 100644 index 00000000..1fec60c9 --- /dev/null +++ b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt8.vtu @@ -0,0 +1,66 @@ + + + + + + + 0 -0.005 0 + 0 0.005 0 + 0.00714286 -0.01 0 + 0.0214286 -0.01 0 + 0.0357143 -0.01 0 + 0.05 -0.01 0 + 0.0642857 -0.01 0 + 0.0785714 -0.01 0 + 0.0928571 -0.01 0 + 0.107143 -0.01 0 + 0.121429 -0.01 0 + 0.135714 -0.01 0 + 0.15 -0.01 0 + 0.164286 -0.01 0 + 0.178571 -0.01 0 + 0.192857 -0.01 0 + 0.00714286 0.01 0 + 0.0214286 0.01 0 + 0.0357143 0.01 0 + 0.05 0.01 0 + 0.0642857 0.01 0 + 0.0785714 0.01 0 + 0.0928571 0.01 0 + 0.107143 0.01 0 + 0.121429 0.01 0 + 0.135714 0.01 0 + 0.15 0.01 0 + 0.164286 0.01 0 + 0.178571 0.01 0 + 0.192857 0.01 0 + 0.2 -0.005 0 + 0.2 0.005 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + 2.08676 0.0200311 0.0 2.10217 -0.0274478 0.0 0.433754 0.156485 0.0 0.298335 0.0662749 0.0 0.218174 0.182601 0.0 0.192548 0.233693 0.0 0.178501 0.240971 0.0 0.175225 0.247121 0.0 0.176825 0.240824 0.0 0.181891 0.222466 0.0 0.18849 0.193048 0.0 0.196491 0.153252 0.0 0.205866 0.103131 0.0 0.217122 0.0411024 0.0 0.231476 -0.0357013 0.0 0.239274 -0.117755 0.0 0.444716 -0.330801 0.0 0.311419 -0.219494 0.0 0.229037 -0.299779 0.0 0.201659 -0.332799 0.0 0.187232 -0.324562 0.0 0.181902 -0.312488 0.0 0.182471 -0.295766 0.0 0.18693 -0.270506 0.0 0.193288 -0.234902 0.0 0.201101 -0.188957 0.0 0.210323 -0.132541 0.0 0.221458 -0.0638603 0.0 0.235702 0.0202329 0.0 0.2435 0.110428 0.0 0.313505 -0.0192155 0.0 0.317125 0.0201303 0.0 + + + 1.83707e-06 0 0.0 -1.83707e-06 0 0.0 3.67366e-06 2.62506e-06 0.0 3.67269e-06 7.87383e-06 0.0 3.67173e-06 1.31226e-05 0.0 3.67076e-06 1.83714e-05 0.0 3.6698e-06 2.36201e-05 0.0 3.66883e-06 2.88689e-05 0.0 3.66787e-06 3.41177e-05 0.0 3.66691e-06 3.93664e-05 0.0 3.66594e-06 4.46152e-05 0.0 3.66498e-06 4.9864e-05 0.0 3.66401e-06 5.51127e-05 0.0 3.66305e-06 6.03615e-05 0.0 3.66208e-06 6.56103e-05 0.0 3.66112e-06 7.0859e-05 0.0 -3.67462e-06 2.62371e-06 0.0 -3.67558e-06 7.87248e-06 0.0 -3.67655e-06 1.31212e-05 0.0 -3.67751e-06 1.837e-05 0.0 -3.67848e-06 2.36188e-05 0.0 -3.67944e-06 2.88676e-05 0.0 -3.68041e-06 3.41163e-05 0.0 -3.68137e-06 3.93651e-05 0.0 -3.68233e-06 4.46139e-05 0.0 -3.6833e-06 4.98626e-05 0.0 -3.68426e-06 5.51114e-05 0.0 -3.68523e-06 6.03602e-05 0.0 -3.68619e-06 6.56089e-05 0.0 -3.68716e-06 7.08577e-05 0.0 1.82357e-06 7.34831e-05 0.0 -1.85057e-06 7.34824e-05 0.0 + + + + + diff --git a/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt9.vtu b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt9.vtu new file mode 100644 index 00000000..a080f54e --- /dev/null +++ b/examples/replay_mode/Fluid/Fluid-Mesh-Fluid.dt9.vtu @@ -0,0 +1,66 @@ + + + + + + + 0 -0.005 0 + 0 0.005 0 + 0.00714286 -0.01 0 + 0.0214286 -0.01 0 + 0.0357143 -0.01 0 + 0.05 -0.01 0 + 0.0642857 -0.01 0 + 0.0785714 -0.01 0 + 0.0928571 -0.01 0 + 0.107143 -0.01 0 + 0.121429 -0.01 0 + 0.135714 -0.01 0 + 0.15 -0.01 0 + 0.164286 -0.01 0 + 0.178571 -0.01 0 + 0.192857 -0.01 0 + 0.00714286 0.01 0 + 0.0214286 0.01 0 + 0.0357143 0.01 0 + 0.05 0.01 0 + 0.0642857 0.01 0 + 0.0785714 0.01 0 + 0.0928571 0.01 0 + 0.107143 0.01 0 + 0.121429 0.01 0 + 0.135714 0.01 0 + 0.15 0.01 0 + 0.164286 0.01 0 + 0.178571 0.01 0 + 0.192857 0.01 0 + 0.2 -0.005 0 + 0.2 0.005 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + 2.06796 0.019872 0.0 2.08527 -0.0275982 0.0 0.433177 0.117064 0.0 0.296715 0.0271301 0.0 0.216079 0.152023 0.0 0.192676 0.209347 0.0 0.178 0.20898 0.0 0.173798 0.213207 0.0 0.174421 0.204956 0.0 0.178118 0.183068 0.0 0.18338 0.150518 0.0 0.190094 0.109168 0.0 0.198523 0.059363 0.0 0.209078 -0.000272397 0.0 0.222758 -0.0727549 0.0 0.229925 -0.148728 0.0 0.445197 -0.313188 0.0 0.311756 -0.200262 0.0 0.228812 -0.277521 0.0 0.200762 -0.31254 0.0 0.187883 -0.309087 0.0 0.181802 -0.295092 0.0 0.181364 -0.273402 0.0 0.184093 -0.242276 0.0 0.18906 -0.20256 0.0 0.195588 -0.154273 0.0 0.203953 -0.0971958 0.0 0.214554 -0.0296373 0.0 0.228364 0.0518636 0.0 0.235891 0.13846 0.0 0.319258 -0.0185701 0.0 0.324611 0.0201865 0.0 + + + 2.99888e-06 0 0.0 -2.99888e-06 0 0.0 5.99647e-06 4.28591e-06 0.0 5.9939e-06 1.28541e-05 0.0 5.99133e-06 2.14224e-05 0.0 5.98876e-06 2.99906e-05 0.0 5.98619e-06 3.85588e-05 0.0 5.98362e-06 4.7127e-05 0.0 5.98105e-06 5.56953e-05 0.0 5.97849e-06 6.42635e-05 0.0 5.97592e-06 7.28317e-05 0.0 5.97335e-06 8.13999e-05 0.0 5.97078e-06 8.99681e-05 0.0 5.96821e-06 9.85364e-05 0.0 5.96564e-06 0.000107105 0.0 5.96307e-06 0.000115673 0.0 -5.99904e-06 4.28231e-06 0.0 -6.00161e-06 1.28505e-05 0.0 -6.00418e-06 2.14188e-05 0.0 -6.00675e-06 2.9987e-05 0.0 -6.00932e-06 3.85552e-05 0.0 -6.01189e-06 4.71234e-05 0.0 -6.01446e-06 5.56917e-05 0.0 -6.01703e-06 6.42599e-05 0.0 -6.0196e-06 7.28281e-05 0.0 -6.02217e-06 8.13963e-05 0.0 -6.02474e-06 8.99645e-05 0.0 -6.02731e-06 9.85328e-05 0.0 -6.02988e-06 0.000107101 0.0 -6.03244e-06 0.000115669 0.0 2.96291e-06 0.000119956 0.0 -3.03485e-06 0.000119954 0.0 + + + + + diff --git a/examples/replay_mode/Solid/Solid-Mesh-Solid.dt1.vtu b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt1.vtu new file mode 100644 index 00000000..255a73f5 --- /dev/null +++ b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt1.vtu @@ -0,0 +1,70 @@ + + + + + + + 0 -0.01 0 + 0 -0.00666667 0 + 0 -0.00333333 0 + 0 0 0 + 0 0.00333333 0 + 0 0.00666667 0 + 0 0.01 0 + 0.2 -0.01 0 + 0.2 -0.00666667 0 + 0.2 -0.00333333 0 + 0.2 0 0 + 0.2 0.00333333 0 + 0.2 0.00666667 0 + 0.2 0.01 0 + 0.0166667 -0.01 0 + 0.0333333 -0.01 0 + 0.05 -0.01 0 + 0.0666667 -0.01 0 + 0.0833333 -0.01 0 + 0.1 -0.01 0 + 0.116667 -0.01 0 + 0.133333 -0.01 0 + 0.15 -0.01 0 + 0.166667 -0.01 0 + 0.183333 -0.01 0 + 0.0166667 0.01 0 + 0.0333333 0.01 0 + 0.05 0.01 0 + 0.0666667 0.01 0 + 0.0833333 0.01 0 + 0.1 0.01 0 + 0.116667 0.01 0 + 0.133333 0.01 0 + 0.15 0.01 0 + 0.166667 0.01 0 + 0.183333 0.01 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + -1.14025e-07 6.50086e-13 0.0 -7.60167e-08 4.3339e-13 0.0 -3.80083e-08 2.16695e-13 0.0 0 0 0.0 3.80083e-08 -2.16695e-13 0.0 7.60167e-08 -4.3339e-13 0.0 1.14025e-07 -6.50086e-13 0.0 -1.14038e-07 -2.2805e-06 0.0 -7.60297e-08 -2.2805e-06 0.0 -3.80213e-08 -2.2805e-06 0.0 -1.30017e-11 -2.2805e-06 0.0 3.79953e-08 -2.2805e-06 0.0 7.60037e-08 -2.2805e-06 0.0 1.14012e-07 -2.2805e-06 0.0 -1.14026e-07 -1.90041e-07 0.0 -1.14027e-07 -3.80083e-07 0.0 -1.14028e-07 -5.70125e-07 0.0 -1.14029e-07 -7.60166e-07 0.0 -1.1403e-07 -9.50208e-07 0.0 -1.14032e-07 -1.14025e-06 0.0 -1.14033e-07 -1.33029e-06 0.0 -1.14034e-07 -1.52033e-06 0.0 -1.14035e-07 -1.71037e-06 0.0 -1.14036e-07 -1.90042e-06 0.0 -1.14037e-07 -2.09046e-06 0.0 1.14024e-07 -1.90042e-07 0.0 1.14023e-07 -3.80084e-07 0.0 1.14022e-07 -5.70126e-07 0.0 1.14021e-07 -7.60168e-07 0.0 1.1402e-07 -9.50209e-07 0.0 1.14019e-07 -1.14025e-06 0.0 1.14017e-07 -1.33029e-06 0.0 1.14016e-07 -1.52033e-06 0.0 1.14015e-07 -1.71038e-06 0.0 1.14014e-07 -1.90042e-06 0.0 1.14013e-07 -2.09046e-06 0.0 + + + 1.75419 -16.7231 0.0 -12.8568 -1.26992 0.0 -13.3145 -1.58881 0.0 3.80658 0.000221714 0.0 -13.3097 1.58679 0.0 -12.8529 1.26528 0.0 1.75287 16.7073 0.0 -0.951461 -11.1804 0.0 8.95315 -0.803505 0.0 9.2165 -1.05921 0.0 -2.63545 2.36502e-06 0.0 9.2122 1.05889 0.0 8.94969 0.802955 0.0 -0.949674 11.1814 0.0 0.592857 -40.6271 0.0 0.396418 -36.868 0.0 0.401757 -36.7624 0.0 0.406549 -34.6273 0.0 0.414373 -33.1951 0.0 0.418923 -32.0136 0.0 0.423452 -31.0337 0.0 0.427428 -30.2491 0.0 0.443495 -29.9355 0.0 0.436974 -27.8752 0.0 0.539763 -28.1788 0.0 0.596456 40.5803 0.0 0.400433 36.8498 0.0 0.405495 36.752 0.0 0.409789 34.6226 0.0 0.417365 33.1944 0.0 0.42165 32.0155 0.0 0.425909 31.0372 0.0 0.429662 30.2535 0.0 0.445399 29.9404 0.0 0.438239 27.8798 0.0 0.539879 28.1816 0.0 + + + + + diff --git a/examples/replay_mode/Solid/Solid-Mesh-Solid.dt10.vtu b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt10.vtu new file mode 100644 index 00000000..1125f418 --- /dev/null +++ b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt10.vtu @@ -0,0 +1,70 @@ + + + + + + + 0 -0.01 0 + 0 -0.00666667 0 + 0 -0.00333333 0 + 0 0 0 + 0 0.00333333 0 + 0 0.00666667 0 + 0 0.01 0 + 0.2 -0.01 0 + 0.2 -0.00666667 0 + 0.2 -0.00333333 0 + 0.2 0 0 + 0.2 0.00333333 0 + 0.2 0.00666667 0 + 0.2 0.01 0 + 0.0166667 -0.01 0 + 0.0333333 -0.01 0 + 0.05 -0.01 0 + 0.0666667 -0.01 0 + 0.0833333 -0.01 0 + 0.1 -0.01 0 + 0.116667 -0.01 0 + 0.133333 -0.01 0 + 0.15 -0.01 0 + 0.166667 -0.01 0 + 0.183333 -0.01 0 + 0.0166667 0.01 0 + 0.0333333 0.01 0 + 0.05 0.01 0 + 0.0666667 0.01 0 + 0.0833333 0.01 0 + 0.1 0.01 0 + 0.116667 0.01 0 + 0.133333 0.01 0 + 0.15 0.01 0 + 0.166667 0.01 0 + 0.183333 0.01 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + 9.00779e-06 4.05701e-09 0.0 6.00519e-06 2.70468e-09 0.0 3.0026e-06 1.35234e-09 0.0 0 0 0.0 -3.0026e-06 -1.35234e-09 0.0 -6.00519e-06 -2.70468e-09 0.0 -9.00779e-06 -4.05701e-09 0.0 8.92665e-06 0.00018016 0.0 5.92405e-06 0.000180158 0.0 2.92146e-06 0.000180157 0.0 -8.11403e-08 0.000180156 0.0 -3.08374e-06 0.000180154 0.0 -6.08633e-06 0.000180153 0.0 -9.08893e-06 0.000180152 0.0 9.00103e-06 1.5017e-05 0.0 8.99426e-06 3.003e-05 0.0 8.9875e-06 4.5043e-05 0.0 8.98074e-06 6.0056e-05 0.0 8.97398e-06 7.5069e-05 0.0 8.96722e-06 9.00819e-05 0.0 8.96046e-06 0.000105095 0.0 8.95369e-06 0.000120108 0.0 8.94693e-06 0.000135121 0.0 8.94017e-06 0.000150134 0.0 8.93341e-06 0.000165147 0.0 -9.01455e-06 1.50089e-05 0.0 -9.02131e-06 3.00219e-05 0.0 -9.02807e-06 4.50349e-05 0.0 -9.03483e-06 6.00479e-05 0.0 -9.0416e-06 7.50608e-05 0.0 -9.04836e-06 9.00738e-05 0.0 -9.05512e-06 0.000105087 0.0 -9.06188e-06 0.0001201 0.0 -9.06864e-06 0.000135113 0.0 -9.0754e-06 0.000150126 0.0 -9.08217e-06 0.000165139 0.0 + + + 0.011112 0.0503634 0.0 1.19926 0.00895312 0.0 1.21045 0.0177812 0.0 -0.346307 0.000875932 0.0 1.22281 -0.0278234 0.0 1.21182 -0.0336935 0.0 0.0163147 -0.134431 0.0 0.0477095 -0.0919381 0.0 0.205822 -0.0204384 0.0 0.197718 -0.0191897 0.0 -0.0549592 -0.000193952 0.0 0.20317 0.0206267 0.0 0.211241 0.0193441 0.0 0.052025 0.0902418 0.0 0.470567 -0.0103398 0.0 0.24735 0.0870547 0.0 0.225705 0.202051 0.0 0.204424 0.198423 0.0 0.201135 0.194741 0.0 0.203084 0.17494 0.0 0.207662 0.134478 0.0 0.213174 0.0789722 0.0 0.225743 0.00755764 0.0 0.229375 -0.0757334 0.0 0.281966 -0.187631 0.0 0.490865 -0.290661 0.0 0.26824 -0.279397 0.0 0.239029 -0.350416 0.0 0.217667 -0.335731 0.0 0.212127 -0.312243 0.0 0.21286 -0.274996 0.0 0.216444 -0.221025 0.0 0.221915 -0.152842 0.0 0.234926 -0.069332 0.0 0.238512 0.0296655 0.0 0.29271 0.15717 0.0 + + + + + diff --git a/examples/replay_mode/Solid/Solid-Mesh-Solid.dt2.vtu b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt2.vtu new file mode 100644 index 00000000..8f0f301c --- /dev/null +++ b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt2.vtu @@ -0,0 +1,70 @@ + + + + + + + 0 -0.01 0 + 0 -0.00666667 0 + 0 -0.00333333 0 + 0 0 0 + 0 0.00333333 0 + 0 0.00666667 0 + 0 0.01 0 + 0.2 -0.01 0 + 0.2 -0.00666667 0 + 0.2 -0.00333333 0 + 0.2 0 0 + 0.2 0.00333333 0 + 0.2 0.00666667 0 + 0.2 0.01 0 + 0.0166667 -0.01 0 + 0.0333333 -0.01 0 + 0.05 -0.01 0 + 0.0666667 -0.01 0 + 0.0833333 -0.01 0 + 0.1 -0.01 0 + 0.116667 -0.01 0 + 0.133333 -0.01 0 + 0.15 -0.01 0 + 0.166667 -0.01 0 + 0.183333 -0.01 0 + 0.0166667 0.01 0 + 0.0333333 0.01 0 + 0.05 0.01 0 + 0.0666667 0.01 0 + 0.0833333 0.01 0 + 0.1 0.01 0 + 0.116667 0.01 0 + 0.133333 0.01 0 + 0.15 0.01 0 + 0.166667 0.01 0 + 0.183333 0.01 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + -2.3094e-07 2.66667e-12 0.0 -1.5396e-07 1.77778e-12 0.0 -7.698e-08 8.88889e-13 0.0 0 0 0.0 7.698e-08 -8.88889e-13 0.0 1.5396e-07 -1.77778e-12 0.0 2.3094e-07 -2.66667e-12 0.0 -2.30993e-07 -4.6188e-06 0.0 -1.54013e-07 -4.6188e-06 0.0 -7.70334e-08 -4.6188e-06 0.0 -5.33333e-11 -4.6188e-06 0.0 7.69267e-08 -4.6188e-06 0.0 1.53907e-07 -4.6188e-06 0.0 2.30887e-07 -4.6188e-06 0.0 -2.30944e-07 -3.84897e-07 0.0 -2.30949e-07 -7.69798e-07 0.0 -2.30953e-07 -1.1547e-06 0.0 -2.30958e-07 -1.5396e-06 0.0 -2.30962e-07 -1.9245e-06 0.0 -2.30967e-07 -2.3094e-06 0.0 -2.30971e-07 -2.6943e-06 0.0 -2.30976e-07 -3.0792e-06 0.0 -2.3098e-07 -3.4641e-06 0.0 -2.30984e-07 -3.849e-06 0.0 -2.30989e-07 -4.2339e-06 0.0 2.30936e-07 -3.84903e-07 0.0 2.30931e-07 -7.69803e-07 0.0 2.30927e-07 -1.1547e-06 0.0 2.30922e-07 -1.5396e-06 0.0 2.30918e-07 -1.9245e-06 0.0 2.30913e-07 -2.3094e-06 0.0 2.30909e-07 -2.6943e-06 0.0 2.30904e-07 -3.0792e-06 0.0 2.309e-07 -3.4641e-06 0.0 2.30896e-07 -3.849e-06 0.0 2.30891e-07 -4.2339e-06 0.0 + + + -0.010454 0.35667 0.0 1.44817 0.0299931 0.0 1.45597 0.040197 0.0 -0.410766 0.000247394 0.0 1.45572 -0.0433357 0.0 1.44949 -0.0370206 0.0 -0.00643233 -0.379647 0.0 0.0948169 0.117868 0.0 0.228084 -0.00589869 0.0 0.212771 -0.000143941 0.0 -0.0554763 5.10941e-05 0.0 0.213281 -0.000369175 0.0 0.226979 0.00499607 0.0 0.0921805 -0.116468 0.0 0.533227 0.811591 0.0 0.316666 0.972408 0.0 0.312397 1.18286 0.0 0.317112 1.15037 0.0 0.329014 1.11396 0.0 0.336844 1.05631 0.0 0.344267 0.973788 0.0 0.350967 0.875483 0.0 0.366779 0.765216 0.0 0.366897 0.590638 0.0 0.449403 0.406929 0.0 0.537706 -0.887893 0.0 0.321931 -1.01579 0.0 0.316451 -1.21132 0.0 0.320031 -1.16897 0.0 0.331666 -1.12603 0.0 0.339606 -1.06396 0.0 0.346553 -0.977682 0.0 0.352524 -0.87643 0.0 0.367989 -0.763976 0.0 0.367866 -0.588122 0.0 0.449845 -0.404592 0.0 + + + + + diff --git a/examples/replay_mode/Solid/Solid-Mesh-Solid.dt3.vtu b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt3.vtu new file mode 100644 index 00000000..116641fc --- /dev/null +++ b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt3.vtu @@ -0,0 +1,70 @@ + + + + + + + 0 -0.01 0 + 0 -0.00666667 0 + 0 -0.00333333 0 + 0 0 0 + 0 0.00333333 0 + 0 0.00666667 0 + 0 0.01 0 + 0.2 -0.01 0 + 0.2 -0.00666667 0 + 0.2 -0.00333333 0 + 0.2 0 0 + 0.2 0.00333333 0 + 0.2 0.00666667 0 + 0.2 0.01 0 + 0.0166667 -0.01 0 + 0.0333333 -0.01 0 + 0.05 -0.01 0 + 0.0666667 -0.01 0 + 0.0833333 -0.01 0 + 0.1 -0.01 0 + 0.116667 -0.01 0 + 0.133333 -0.01 0 + 0.15 -0.01 0 + 0.166667 -0.01 0 + 0.183333 -0.01 0 + 0.0166667 0.01 0 + 0.0333333 0.01 0 + 0.05 0.01 0 + 0.0666667 0.01 0 + 0.0833333 0.01 0 + 0.1 0.01 0 + 0.116667 0.01 0 + 0.133333 0.01 0 + 0.15 0.01 0 + 0.166667 0.01 0 + 0.183333 0.01 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + -2.58767e-07 3.34802e-12 0.0 -1.72511e-07 2.23201e-12 0.0 -8.62557e-08 1.11601e-12 0.0 0 0 0.0 8.62557e-08 -1.11601e-12 0.0 1.72511e-07 -2.23201e-12 0.0 2.58767e-07 -3.34802e-12 0.0 -2.58834e-07 -5.17534e-06 0.0 -1.72578e-07 -5.17534e-06 0.0 -8.63226e-08 -5.17534e-06 0.0 -6.69604e-11 -5.17534e-06 0.0 8.61887e-08 -5.17534e-06 0.0 1.72444e-07 -5.17534e-06 0.0 2.587e-07 -5.17534e-06 0.0 -2.58773e-07 -4.31275e-07 0.0 -2.58778e-07 -8.62554e-07 0.0 -2.58784e-07 -1.29383e-06 0.0 -2.58789e-07 -1.72511e-06 0.0 -2.58795e-07 -2.15639e-06 0.0 -2.58801e-07 -2.58767e-06 0.0 -2.58806e-07 -3.01895e-06 0.0 -2.58812e-07 -3.45022e-06 0.0 -2.58817e-07 -3.8815e-06 0.0 -2.58823e-07 -4.31278e-06 0.0 -2.58828e-07 -4.74406e-06 0.0 2.58761e-07 -4.31282e-07 0.0 2.58756e-07 -8.6256e-07 0.0 2.5875e-07 -1.29384e-06 0.0 2.58745e-07 -1.72512e-06 0.0 2.58739e-07 -2.1564e-06 0.0 2.58734e-07 -2.58767e-06 0.0 2.58728e-07 -3.01895e-06 0.0 2.58722e-07 -3.45023e-06 0.0 2.58717e-07 -3.88151e-06 0.0 2.58711e-07 -4.31279e-06 0.0 2.58706e-07 -4.74407e-06 0.0 + + + -0.00667829 0.268147 0.0 1.36822 0.0281206 0.0 1.38208 0.0364872 0.0 -0.392931 0.000392881 0.0 1.3827 -0.0406859 0.0 1.3705 -0.0373311 0.0 -0.00142876 -0.297361 0.0 0.0839473 0.0583014 0.0 0.196237 -0.010145 0.0 0.183419 -0.00613215 0.0 -0.0482527 4.64955e-05 0.0 0.183542 0.0055855 0.0 0.195515 0.00908554 0.0 0.0827451 -0.0566625 0.0 0.498858 0.539117 0.0 0.278878 0.607773 0.0 0.26325 0.785798 0.0 0.261685 0.798528 0.0 0.273738 0.795966 0.0 0.284625 0.770014 0.0 0.295223 0.711289 0.0 0.303817 0.632376 0.0 0.320716 0.537113 0.0 0.323316 0.390614 0.0 0.397564 0.232801 0.0 0.505238 -0.638336 0.0 0.285445 -0.666476 0.0 0.269361 -0.825518 0.0 0.266149 -0.825179 0.0 0.277238 -0.815827 0.0 0.287783 -0.784214 0.0 0.297843 -0.72079 0.0 0.306059 -0.637838 0.0 0.322537 -0.539431 0.0 0.324514 -0.390673 0.0 0.398148 -0.231661 0.0 + + + + + diff --git a/examples/replay_mode/Solid/Solid-Mesh-Solid.dt4.vtu b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt4.vtu new file mode 100644 index 00000000..10ec8e1e --- /dev/null +++ b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt4.vtu @@ -0,0 +1,70 @@ + + + + + + + 0 -0.01 0 + 0 -0.00666667 0 + 0 -0.00333333 0 + 0 0 0 + 0 0.00333333 0 + 0 0.00666667 0 + 0 0.01 0 + 0.2 -0.01 0 + 0.2 -0.00666667 0 + 0.2 -0.00333333 0 + 0.2 0 0 + 0.2 0.00333333 0 + 0.2 0.00666667 0 + 0.2 0.01 0 + 0.0166667 -0.01 0 + 0.0333333 -0.01 0 + 0.05 -0.01 0 + 0.0666667 -0.01 0 + 0.0833333 -0.01 0 + 0.1 -0.01 0 + 0.116667 -0.01 0 + 0.133333 -0.01 0 + 0.15 -0.01 0 + 0.166667 -0.01 0 + 0.183333 -0.01 0 + 0.0166667 0.01 0 + 0.0333333 0.01 0 + 0.05 0.01 0 + 0.0666667 0.01 0 + 0.0833333 0.01 0 + 0.1 0.01 0 + 0.116667 0.01 0 + 0.133333 0.01 0 + 0.15 0.01 0 + 0.166667 0.01 0 + 0.183333 0.01 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + -1.32642e-07 8.79701e-13 0.0 -8.84283e-08 5.86468e-13 0.0 -4.42141e-08 2.93234e-13 0.0 0 0 0.0 4.42141e-08 -2.93234e-13 0.0 8.84283e-08 -5.86468e-13 0.0 1.32642e-07 -8.79701e-13 0.0 -1.3266e-07 -2.65285e-06 0.0 -8.84459e-08 -2.65285e-06 0.0 -4.42317e-08 -2.65285e-06 0.0 -1.7594e-11 -2.65285e-06 0.0 4.41965e-08 -2.65285e-06 0.0 8.84107e-08 -2.65285e-06 0.0 1.32625e-07 -2.65285e-06 0.0 -1.32644e-07 -2.2107e-07 0.0 -1.32645e-07 -4.4214e-07 0.0 -1.32647e-07 -6.63211e-07 0.0 -1.32648e-07 -8.84282e-07 0.0 -1.3265e-07 -1.10535e-06 0.0 -1.32651e-07 -1.32642e-06 0.0 -1.32653e-07 -1.54749e-06 0.0 -1.32654e-07 -1.76856e-06 0.0 -1.32656e-07 -1.98964e-06 0.0 -1.32657e-07 -2.21071e-06 0.0 -1.32659e-07 -2.43178e-06 0.0 1.32641e-07 -2.21072e-07 0.0 1.32639e-07 -4.42142e-07 0.0 1.32638e-07 -6.63213e-07 0.0 1.32637e-07 -8.84284e-07 0.0 1.32635e-07 -1.10535e-06 0.0 1.32634e-07 -1.32642e-06 0.0 1.32632e-07 -1.5475e-06 0.0 1.32631e-07 -1.76857e-06 0.0 1.32629e-07 -1.98964e-06 0.0 1.32628e-07 -2.21071e-06 0.0 1.32626e-07 -2.43178e-06 0.0 + + + -0.00122525 0.201593 0.0 1.30715 0.0240705 0.0 1.31889 0.0315638 0.0 -0.374422 0.000550151 0.0 1.31964 -0.0369031 0.0 1.31006 -0.0357321 0.0 0.00550594 -0.238004 0.0 0.0749019 0.0154164 0.0 0.189578 -0.0135426 0.0 0.177999 -0.010635 0.0 -0.0468549 1.90785e-05 0.0 0.17812 0.0102184 0.0 0.189326 0.0124005 0.0 0.0747206 -0.0139519 0.0 0.485679 0.378772 0.0 0.26358 0.417821 0.0 0.239946 0.55177 0.0 0.230639 0.573495 0.0 0.239808 0.58193 0.0 0.25123 0.57189 0.0 0.263253 0.53175 0.0 0.273761 0.46798 0.0 0.291545 0.384561 0.0 0.295801 0.257921 0.0 0.364448 0.113374 0.0 0.495098 -0.5055 0.0 0.272997 -0.487958 0.0 0.24445 -0.587174 0.0 0.235807 -0.606021 0.0 0.243964 -0.612041 0.0 0.254993 -0.595429 0.0 0.266588 -0.549362 0.0 0.276603 -0.480342 0.0 0.293952 -0.392532 0.0 0.297609 -0.262143 0.0 0.365681 -0.114997 0.0 + + + + + diff --git a/examples/replay_mode/Solid/Solid-Mesh-Solid.dt5.vtu b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt5.vtu new file mode 100644 index 00000000..2da85221 --- /dev/null +++ b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt5.vtu @@ -0,0 +1,70 @@ + + + + + + + 0 -0.01 0 + 0 -0.00666667 0 + 0 -0.00333333 0 + 0 0 0 + 0 0.00333333 0 + 0 0.00666667 0 + 0 0.01 0 + 0.2 -0.01 0 + 0.2 -0.00666667 0 + 0.2 -0.00333333 0 + 0.2 0 0 + 0.2 0.00333333 0 + 0.2 0.00666667 0 + 0.2 0.01 0 + 0.0166667 -0.01 0 + 0.0333333 -0.01 0 + 0.05 -0.01 0 + 0.0666667 -0.01 0 + 0.0833333 -0.01 0 + 0.1 -0.01 0 + 0.116667 -0.01 0 + 0.133333 -0.01 0 + 0.15 -0.01 0 + 0.166667 -0.01 0 + 0.183333 -0.01 0 + 0.0166667 0.01 0 + 0.0333333 0.01 0 + 0.05 0.01 0 + 0.0666667 0.01 0 + 0.0833333 0.01 0 + 0.1 0.01 0 + 0.116667 0.01 0 + 0.133333 0.01 0 + 0.15 0.01 0 + 0.166667 0.01 0 + 0.183333 0.01 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + 2.17685e-07 2.36935e-12 0.0 1.45124e-07 1.57957e-12 0.0 7.25618e-08 7.89783e-13 0.0 0 0 0.0 -7.25618e-08 -7.89783e-13 0.0 -1.45124e-07 -1.57957e-12 0.0 -2.17685e-07 -2.36935e-12 0.0 2.17638e-07 4.35371e-06 0.0 1.45076e-07 4.35371e-06 0.0 7.25144e-08 4.35371e-06 0.0 -4.7387e-11 4.35371e-06 0.0 -7.26092e-08 4.35371e-06 0.0 -1.45171e-07 4.35371e-06 0.0 -2.17733e-07 4.35371e-06 0.0 2.17682e-07 3.62811e-07 0.0 2.17678e-07 7.25621e-07 0.0 2.17674e-07 1.08843e-06 0.0 2.1767e-07 1.45124e-06 0.0 2.17666e-07 1.81405e-06 0.0 2.17662e-07 2.17686e-06 0.0 2.17658e-07 2.53967e-06 0.0 2.17654e-07 2.90248e-06 0.0 2.1765e-07 3.26528e-06 0.0 2.17646e-07 3.62809e-06 0.0 2.17642e-07 3.9909e-06 0.0 -2.17689e-07 3.62807e-07 0.0 -2.17693e-07 7.25616e-07 0.0 -2.17697e-07 1.08842e-06 0.0 -2.17701e-07 1.45123e-06 0.0 -2.17705e-07 1.81404e-06 0.0 -2.17709e-07 2.17685e-06 0.0 -2.17713e-07 2.53966e-06 0.0 -2.17717e-07 2.90247e-06 0.0 -2.17721e-07 3.26528e-06 0.0 -2.17725e-07 3.62809e-06 0.0 -2.17729e-07 3.9909e-06 0.0 + + + 0.00192077 0.152305 0.0 1.26714 0.0199705 0.0 1.27656 0.0271712 0.0 -0.36161 0.000695282 0.0 1.27741 -0.0336457 0.0 1.27069 -0.0341961 0.0 0.00999139 -0.196662 0.0 0.0677683 -0.0152358 0.0 0.192108 -0.015859 0.0 0.181408 -0.0136648 0.0 -0.0479181 -1.17356e-05 0.0 0.181613 0.0134298 0.0 0.192316 0.0146318 0.0 0.068594 0.0163571 0.0 0.479895 0.263197 0.0 0.258509 0.304476 0.0 0.229608 0.41182 0.0 0.215656 0.435057 0.0 0.219933 0.439634 0.0 0.229605 0.431807 0.0 0.241513 0.402182 0.0 0.252878 0.349255 0.0 0.27129 0.274831 0.0 0.276676 0.163621 0.0 0.341726 0.0287939 0.0 0.491458 -0.420453 0.0 0.26999 -0.404794 0.0 0.238658 -0.469975 0.0 0.220102 -0.469606 0.0 0.224414 -0.476526 0.0 0.233763 -0.465332 0.0 0.245493 -0.429526 0.0 0.256507 -0.370352 0.0 0.274514 -0.290219 0.0 0.279333 -0.17336 0.0 0.343881 -0.034171 0.0 + + + + + diff --git a/examples/replay_mode/Solid/Solid-Mesh-Solid.dt6.vtu b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt6.vtu new file mode 100644 index 00000000..6947b4c4 --- /dev/null +++ b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt6.vtu @@ -0,0 +1,70 @@ + + + + + + + 0 -0.01 0 + 0 -0.00666667 0 + 0 -0.00333333 0 + 0 0 0 + 0 0.00333333 0 + 0 0.00666667 0 + 0 0.01 0 + 0.2 -0.01 0 + 0.2 -0.00666667 0 + 0.2 -0.00333333 0 + 0.2 0 0 + 0.2 0.00333333 0 + 0.2 0.00666667 0 + 0.2 0.01 0 + 0.0166667 -0.01 0 + 0.0333333 -0.01 0 + 0.05 -0.01 0 + 0.0666667 -0.01 0 + 0.0833333 -0.01 0 + 0.1 -0.01 0 + 0.116667 -0.01 0 + 0.133333 -0.01 0 + 0.15 -0.01 0 + 0.166667 -0.01 0 + 0.183333 -0.01 0 + 0.0166667 0.01 0 + 0.0333333 0.01 0 + 0.05 0.01 0 + 0.0666667 0.01 0 + 0.0833333 0.01 0 + 0.1 0.01 0 + 0.116667 0.01 0 + 0.133333 0.01 0 + 0.15 0.01 0 + 0.166667 0.01 0 + 0.183333 0.01 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + 8.85052e-07 3.91658e-11 0.0 5.90034e-07 2.61106e-11 0.0 2.95017e-07 1.30553e-11 0.0 0 0 0.0 -2.95017e-07 -1.30553e-11 0.0 -5.90034e-07 -2.61106e-11 0.0 -8.85052e-07 -3.91658e-11 0.0 8.84268e-07 1.77011e-05 0.0 5.89251e-07 1.77011e-05 0.0 2.94234e-07 1.7701e-05 0.0 -7.83317e-10 1.7701e-05 0.0 -2.95801e-07 1.7701e-05 0.0 -5.90818e-07 1.7701e-05 0.0 -8.85835e-07 1.7701e-05 0.0 8.84986e-07 1.47513e-06 0.0 8.84921e-07 2.95021e-06 0.0 8.84856e-07 4.4253e-06 0.0 8.84791e-07 5.90038e-06 0.0 8.84725e-07 7.37547e-06 0.0 8.8466e-07 8.85056e-06 0.0 8.84595e-07 1.03256e-05 0.0 8.8453e-07 1.18007e-05 0.0 8.84464e-07 1.32758e-05 0.0 8.84399e-07 1.47509e-05 0.0 8.84334e-07 1.6226e-05 0.0 -8.85117e-07 1.47505e-06 0.0 -8.85182e-07 2.95013e-06 0.0 -8.85248e-07 4.42522e-06 0.0 -8.85313e-07 5.90031e-06 0.0 -8.85378e-07 7.37539e-06 0.0 -8.85443e-07 8.85048e-06 0.0 -8.85509e-07 1.03256e-05 0.0 -8.85574e-07 1.18007e-05 0.0 -8.85639e-07 1.32757e-05 0.0 -8.85705e-07 1.47508e-05 0.0 -8.8577e-07 1.62259e-05 0.0 + + + 0.00340644 0.117106 0.0 1.24304 0.0171472 0.0 1.25033 0.023985 0.0 -0.353342 0.000189956 0.0 1.25149 -0.03112 0.0 1.24734 -0.0332041 0.0 0.0127368 -0.170355 0.0 0.0620892 -0.0378994 0.0 0.195827 -0.017483 0.0 0.185731 -0.0156338 0.0 -0.0492004 4.33928e-05 0.0 0.18612 0.015579 0.0 0.196534 0.0160725 0.0 0.0639827 0.0385594 0.0 0.476276 0.175263 0.0 0.256118 0.231131 0.0 0.228234 0.328786 0.0 0.208998 0.343236 0.0 0.209311 0.345326 0.0 0.21622 0.333996 0.0 0.226686 0.305693 0.0 0.237635 0.258498 0.0 0.256033 0.190579 0.0 0.262062 0.091647 0.0 0.324477 -0.0346825 0.0 0.489077 -0.362029 0.0 0.268155 -0.357745 0.0 0.239318 -0.424267 0.0 0.215896 -0.40323 0.0 0.214907 -0.396152 0.0 0.221211 -0.379263 0.0 0.231376 -0.344167 0.0 0.242114 -0.289819 0.0 0.260245 -0.215006 0.0 0.265779 -0.108333 0.0 0.327883 0.0245246 0.0 + + + + + diff --git a/examples/replay_mode/Solid/Solid-Mesh-Solid.dt7.vtu b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt7.vtu new file mode 100644 index 00000000..afa15128 --- /dev/null +++ b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt7.vtu @@ -0,0 +1,70 @@ + + + + + + + 0 -0.01 0 + 0 -0.00666667 0 + 0 -0.00333333 0 + 0 0 0 + 0 0.00333333 0 + 0 0.00666667 0 + 0 0.01 0 + 0.2 -0.01 0 + 0.2 -0.00666667 0 + 0.2 -0.00333333 0 + 0.2 0 0 + 0.2 0.00333333 0 + 0.2 0.00666667 0 + 0.2 0.01 0 + 0.0166667 -0.01 0 + 0.0333333 -0.01 0 + 0.05 -0.01 0 + 0.0666667 -0.01 0 + 0.0833333 -0.01 0 + 0.1 -0.01 0 + 0.116667 -0.01 0 + 0.133333 -0.01 0 + 0.15 -0.01 0 + 0.166667 -0.01 0 + 0.183333 -0.01 0 + 0.0166667 0.01 0 + 0.0333333 0.01 0 + 0.05 0.01 0 + 0.0666667 0.01 0 + 0.0833333 0.01 0 + 0.1 0.01 0 + 0.116667 0.01 0 + 0.133333 0.01 0 + 0.15 0.01 0 + 0.166667 0.01 0 + 0.183333 0.01 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + 1.99607e-06 1.99215e-10 0.0 1.33072e-06 1.3281e-10 0.0 6.65358e-07 6.64051e-11 0.0 0 0 0.0 -6.65358e-07 -6.64051e-11 0.0 -1.33072e-06 -1.3281e-10 0.0 -1.99607e-06 -1.99215e-10 0.0 1.99209e-06 3.99217e-05 0.0 1.32673e-06 3.99216e-05 0.0 6.61373e-07 3.99215e-05 0.0 -3.98431e-09 3.99215e-05 0.0 -6.69342e-07 3.99214e-05 0.0 -1.3347e-06 3.99213e-05 0.0 -2.00006e-06 3.99213e-05 0.0 1.99574e-06 3.32699e-06 0.0 1.99541e-06 6.65378e-06 0.0 1.99508e-06 9.98056e-06 0.0 1.99474e-06 1.33074e-05 0.0 1.99441e-06 1.66341e-05 0.0 1.99408e-06 1.99609e-05 0.0 1.99375e-06 2.32877e-05 0.0 1.99342e-06 2.66145e-05 0.0 1.99308e-06 2.99413e-05 0.0 1.99275e-06 3.32681e-05 0.0 1.99242e-06 3.65949e-05 0.0 -1.9964e-06 3.32659e-06 0.0 -1.99674e-06 6.65338e-06 0.0 -1.99707e-06 9.98016e-06 0.0 -1.9974e-06 1.3307e-05 0.0 -1.99773e-06 1.66337e-05 0.0 -1.99806e-06 1.99605e-05 0.0 -1.9984e-06 2.32873e-05 0.0 -1.99873e-06 2.66141e-05 0.0 -1.99906e-06 2.99409e-05 0.0 -1.99939e-06 3.32677e-05 0.0 -1.99973e-06 3.65945e-05 0.0 + + + 0.00430197 0.0925028 0.0 1.22801 0.0145441 0.0 1.23313 0.0216477 0.0 -0.347567 0.000327171 0.0 1.2347 -0.0296776 0.0 1.23306 -0.0329706 0.0 0.0147695 -0.153771 0.0 0.0572777 -0.0558379 0.0 0.199157 -0.0185973 0.0 0.189472 -0.0169885 0.0 -0.0502951 -1.35893e-05 0.0 0.190146 0.0172233 0.0 0.200474 0.0171741 0.0 0.0604118 0.0557762 0.0 0.473873 0.10903 0.0 0.25373 0.180244 0.0 0.22848 0.279553 0.0 0.206367 0.282552 0.0 0.204588 0.283516 0.0 0.208837 0.26744 0.0 0.21719 0.235441 0.0 0.226708 0.188201 0.0 0.244256 0.123194 0.0 0.250327 0.0332666 0.0 0.310415 -0.0859077 0.0 0.488225 -0.323751 0.0 0.266901 -0.320213 0.0 0.239437 -0.396892 0.0 0.216057 -0.375631 0.0 0.211758 -0.354899 0.0 0.214912 -0.327236 0.0 0.222803 -0.286674 0.0 0.232111 -0.231088 0.0 0.249552 -0.157995 0.0 0.255294 -0.0582283 0.0 0.315408 0.0699575 0.0 + + + + + diff --git a/examples/replay_mode/Solid/Solid-Mesh-Solid.dt8.vtu b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt8.vtu new file mode 100644 index 00000000..31a8b8b9 --- /dev/null +++ b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt8.vtu @@ -0,0 +1,70 @@ + + + + + + + 0 -0.01 0 + 0 -0.00666667 0 + 0 -0.00333333 0 + 0 0 0 + 0 0.00333333 0 + 0 0.00666667 0 + 0 0.01 0 + 0.2 -0.01 0 + 0.2 -0.00666667 0 + 0.2 -0.00333333 0 + 0.2 0 0 + 0.2 0.00333333 0 + 0.2 0.00666667 0 + 0.2 0.01 0 + 0.0166667 -0.01 0 + 0.0333333 -0.01 0 + 0.05 -0.01 0 + 0.0666667 -0.01 0 + 0.0833333 -0.01 0 + 0.1 -0.01 0 + 0.116667 -0.01 0 + 0.133333 -0.01 0 + 0.15 -0.01 0 + 0.166667 -0.01 0 + 0.183333 -0.01 0 + 0.0166667 0.01 0 + 0.0333333 0.01 0 + 0.05 0.01 0 + 0.0666667 0.01 0 + 0.0833333 0.01 0 + 0.1 0.01 0 + 0.116667 0.01 0 + 0.133333 0.01 0 + 0.15 0.01 0 + 0.166667 0.01 0 + 0.183333 0.01 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + 3.67414e-06 6.74964e-10 0.0 2.44943e-06 4.49976e-10 0.0 1.22471e-06 2.24988e-10 0.0 0 0 0.0 -1.22471e-06 -2.24988e-10 0.0 -2.44943e-06 -4.49976e-10 0.0 -3.67414e-06 -6.74964e-10 0.0 3.66064e-06 7.34834e-05 0.0 2.43593e-06 7.34832e-05 0.0 1.21121e-06 7.3483e-05 0.0 -1.34993e-08 7.34828e-05 0.0 -1.23821e-06 7.34825e-05 0.0 -2.46292e-06 7.34823e-05 0.0 -3.68764e-06 7.34821e-05 0.0 3.67301e-06 6.12424e-06 0.0 3.67189e-06 1.22478e-05 0.0 3.67076e-06 1.83714e-05 0.0 3.66964e-06 2.44949e-05 0.0 3.66851e-06 3.06185e-05 0.0 3.66739e-06 3.67421e-05 0.0 3.66626e-06 4.28656e-05 0.0 3.66514e-06 4.89892e-05 0.0 3.66401e-06 5.51127e-05 0.0 3.66289e-06 6.12363e-05 0.0 3.66176e-06 6.73599e-05 0.0 -3.67526e-06 6.12289e-06 0.0 -3.67639e-06 1.22465e-05 0.0 -3.67751e-06 1.837e-05 0.0 -3.67864e-06 2.44936e-05 0.0 -3.67976e-06 3.06171e-05 0.0 -3.68089e-06 3.67407e-05 0.0 -3.68201e-06 4.28643e-05 0.0 -3.68314e-06 4.89878e-05 0.0 -3.68426e-06 5.51114e-05 0.0 -3.68539e-06 6.1235e-05 0.0 -3.68651e-06 6.73585e-05 0.0 + + + 0.00958785 0.0747744 0.0 1.21194 0.0124231 0.0 1.22335 0.019973 0.0 -0.349554 0.000498698 0.0 1.23304 -0.0287452 0.0 1.22187 -0.0330058 0.0 0.0145528 -0.1435 0.0 0.0534893 -0.0705857 0.0 0.201744 -0.0194187 0.0 0.19284 -0.0179599 0.0 -0.0531724 -7.37197e-05 0.0 0.196049 0.0185427 0.0 0.20496 0.018041 0.0 0.0562626 0.0697914 0.0 0.47202 0.0596837 0.0 0.251206 0.143138 0.0 0.228488 0.249483 0.0 0.205631 0.244717 0.0 0.202438 0.243532 0.0 0.205333 0.224104 0.0 0.211697 0.187461 0.0 0.219659 0.137085 0.0 0.235293 0.07098 0.0 0.241149 -0.0138697 0.0 0.298637 -0.12814 0.0 0.489122 -0.302347 0.0 0.266726 -0.294745 0.0 0.238563 -0.372687 0.0 0.216716 -0.357445 0.0 0.21134 -0.333097 0.0 0.212768 -0.298097 0.0 0.218162 -0.250857 0.0 0.226132 -0.191091 0.0 0.241953 -0.115736 0.0 0.247451 -0.0190777 0.0 0.305483 0.106499 0.0 + + + + + diff --git a/examples/replay_mode/Solid/Solid-Mesh-Solid.dt9.vtu b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt9.vtu new file mode 100644 index 00000000..cd537926 --- /dev/null +++ b/examples/replay_mode/Solid/Solid-Mesh-Solid.dt9.vtu @@ -0,0 +1,70 @@ + + + + + + + 0 -0.01 0 + 0 -0.00666667 0 + 0 -0.00333333 0 + 0 0 0 + 0 0.00333333 0 + 0 0.00666667 0 + 0 0.01 0 + 0.2 -0.01 0 + 0.2 -0.00666667 0 + 0.2 -0.00333333 0 + 0.2 0 0 + 0.2 0.00333333 0 + 0.2 0.00666667 0 + 0.2 0.01 0 + 0.0166667 -0.01 0 + 0.0333333 -0.01 0 + 0.05 -0.01 0 + 0.0666667 -0.01 0 + 0.0833333 -0.01 0 + 0.1 -0.01 0 + 0.116667 -0.01 0 + 0.133333 -0.01 0 + 0.15 -0.01 0 + 0.166667 -0.01 0 + 0.183333 -0.01 0 + 0.0166667 0.01 0 + 0.0333333 0.01 0 + 0.05 0.01 0 + 0.0666667 0.01 0 + 0.0833333 0.01 0 + 0.1 0.01 0 + 0.116667 0.01 0 + 0.133333 0.01 0 + 0.15 0.01 0 + 0.166667 0.01 0 + 0.183333 0.01 0 + + + + + + + + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + 5.99776e-06 1.79865e-09 0.0 3.9985e-06 1.1991e-09 0.0 1.99925e-06 5.99551e-10 0.0 0 0 0.0 -1.99925e-06 -5.99551e-10 0.0 -3.9985e-06 -1.1991e-09 0.0 -5.99776e-06 -1.79865e-09 0.0 5.96178e-06 0.000119957 0.0 3.96253e-06 0.000119956 0.0 1.96328e-06 0.000119956 0.0 -3.59731e-08 0.000119955 0.0 -2.03523e-06 0.000119955 0.0 -4.03448e-06 0.000119954 0.0 -6.03373e-06 0.000119953 0.0 5.99476e-06 9.99806e-06 0.0 5.99176e-06 1.99943e-05 0.0 5.98876e-06 2.99906e-05 0.0 5.98577e-06 3.99868e-05 0.0 5.98277e-06 4.99831e-05 0.0 5.97977e-06 5.99794e-05 0.0 5.97677e-06 6.99756e-05 0.0 5.97377e-06 7.99719e-05 0.0 5.97078e-06 8.99681e-05 0.0 5.96778e-06 9.99644e-05 0.0 5.96478e-06 0.000109961 0.0 -6.00075e-06 9.99446e-06 0.0 -6.00375e-06 1.99907e-05 0.0 -6.00675e-06 2.9987e-05 0.0 -6.00975e-06 3.99832e-05 0.0 -6.01275e-06 4.99795e-05 0.0 -6.01574e-06 5.99758e-05 0.0 -6.01874e-06 6.9972e-05 0.0 -6.02174e-06 7.99683e-05 0.0 -6.02474e-06 8.99645e-05 0.0 -6.02773e-06 9.99608e-05 0.0 -6.03073e-06 0.000109957 0.0 + + + 0.0104184 0.0612314 0.0 1.20458 0.0105723 0.0 1.21568 0.0187286 0.0 -0.347458 0.000717265 0.0 1.22648 -0.0281695 0.0 1.21567 -0.0332424 0.0 0.0156219 -0.137332 0.0 0.0502557 -0.0826316 0.0 0.204011 -0.0200042 0.0 0.195546 -0.018682 0.0 -0.0541169 -0.000135293 0.0 0.19984 0.019677 0.0 0.20832 0.0187557 0.0 0.0538509 0.081335 0.0 0.471159 0.0212239 0.0 0.248765 0.112753 0.0 0.227013 0.225028 0.0 0.205103 0.219545 0.0 0.201662 0.215873 0.0 0.203804 0.195268 0.0 0.208963 0.155531 0.0 0.215416 0.102025 0.0 0.229378 0.0331818 0.0 0.234183 -0.0499804 0.0 0.289181 -0.162015 0.0 0.490006 -0.292438 0.0 0.267371 -0.282279 0.0 0.238125 -0.356284 0.0 0.217212 -0.343611 0.0 0.211695 -0.319714 0.0 0.212485 -0.282419 0.0 0.216561 -0.230512 0.0 0.222991 -0.16596 0.0 0.237283 -0.086563 0.0 0.241879 0.0103 0.0 0.297946 0.13579 0.0 + + + + + diff --git a/examples/replay_mode/aste-config-fluid.json b/examples/replay_mode/aste-config-fluid.json new file mode 100644 index 00000000..313b00ab --- /dev/null +++ b/examples/replay_mode/aste-config-fluid.json @@ -0,0 +1,23 @@ +{ + "participant": "Fluid", + "startdt": "1", + "meshes": [ + { + "mesh": "Fluid-Mesh", + "meshfileprefix": "./Fluid/Fluid-Mesh-Fluid", + "read-data": { + "vector": [ + "Displacement" + ], + "scalar": [ ] + }, + "write-data": { + "vector": [ + "Force" + ], + "scalar": [ ] + } + } + ], + "precice-config": "./precice-config.xml" +} diff --git a/examples/replay_mode/aste-config-solid.json b/examples/replay_mode/aste-config-solid.json new file mode 100644 index 00000000..4b4bfb83 --- /dev/null +++ b/examples/replay_mode/aste-config-solid.json @@ -0,0 +1,23 @@ +{ + "participant": "Solid", + "startdt": "1", + "meshes": [ + { + "mesh": "Solid-Mesh", + "meshfileprefix": "./Solid/Solid-Mesh-Solid", + "read-data": { + "vector": [ + "Force" + ], + "scalar": [ ] + }, + "write-data": { + "vector": [ + "Displacement" + ], + "scalar": [ ] + } + } + ], + "precice-config": "./precice-config.xml" +} diff --git a/examples/replay_mode/clean.sh b/examples/replay_mode/clean.sh new file mode 100755 index 00000000..296cf47e --- /dev/null +++ b/examples/replay_mode/clean.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -e -u + +# Remove log and json records +rm -f precice*.json +rm -f precice*.log +# Remove precice-run directory +rm -rf precice-run diff --git a/examples/replay_mode/precice-config.xml b/examples/replay_mode/precice-config.xml new file mode 100644 index 00000000..5ef30fc5 --- /dev/null +++ b/examples/replay_mode/precice-config.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/replay_mode/run.sh b/examples/replay_mode/run.sh new file mode 100755 index 00000000..c6ec46e0 --- /dev/null +++ b/examples/replay_mode/run.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +set -e -u + + +# Run Fluid Side +precice-aste-run --aste-config aste-config-fluid.json & + +# Run Solid Side +precice-aste-run --aste-config aste-config-solid.json diff --git a/examples/run-all.sh b/examples/run-all.sh new file mode 100755 index 00000000..f73ab420 --- /dev/null +++ b/examples/run-all.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -e -u + +# Print the problmatic case and increase error count +detect_error(){ + echo "Error while running case ${array[1]}" + err_count=$((err_count + 1)) +} + +echo "- Running all examples cases..." +test_cases=$(find . -maxdepth 2 -mindepth 2 -name run.sh) +number_of_cases=$(echo "$test_cases" | wc -w) +echo "- There are $number_of_cases case(s) found..." + +# Initial directory and error count +run_all_dir=$(pwd) +err_count=0 + +# Run all cases +for testcase in $test_cases; do + array=($(echo "$testcase" | tr "/" "\n")) + cd "${array[1]}" + echo "- Running test case ${array[1]}..." + ./run.sh || detect_error + cd "$run_all_dir" +done + +if [ $err_count -eq 0 ]; then + echo "All tests passed" +else + echo "$err_count out of $number_of_cases failed" + exit 1 +fi diff --git a/plotting/plot_preallocation.py b/plotting/plot_preallocation.py deleted file mode 100644 index 2d3be5dc..00000000 --- a/plotting/plot_preallocation.py +++ /dev/null @@ -1,70 +0,0 @@ -import json, pandas, sys -import numpy as np -import matplotlib.pyplot as plt -import matplotlib - -publication = True - -if publication: - import plot_helper - plot_helper.set_save_fig_params() - - -fields = ["PetRBF.fillA", "PetRBF.fillC", "PetRBF.preallocA", "PetRBF.preallocC"] -colors = {f : c for (f, c) in zip(fields, - matplotlib.cm.get_cmap()(np.linspace(0, 1, len(fields)))) } -labels = {"PetRBF.fillA" : "Filling evaluation", - "PetRBF.fillC" : "Filling interpolation", - "PetRBF.preallocA" : "Preallocation evaluation", - "PetRBF.preallocC" : "Preallocation interpolation" } - -ticks_labels = {"off" : "No preallocation", - "compute" : "Explicitly computed", - "saved" : "Computed and saved", - "tree" : "Using of spatial tree" } - - -run_name = sys.argv[1] # like 2018-02-12T16:45:25.141337_testeins -participant = "B" - -f_timings = "{run}-{participant}.timings".format(run = run_name, participant = participant) -info = json.load(open(run_name + ".meta")) - -df = pandas.read_csv(f_timings, index_col = [0], comment = "#", parse_dates = [0]) - -ticks = [] -x_locs = [] -x = -1 - -for idx, time in enumerate(df.index.unique()): - x += 1 - if idx == 4: x += 0.3 - cdf = df.loc[time] - y_bottom = 0 - for f in fields: - y = cdf[(cdf.Name == f)].Avg.max() - if np.isnan(y): y = 0 # When there is no Prealloc field - plt.bar(x, y, bottom = y_bottom, color = colors[f], label = labels[f] if idx==0 else "") - y_bottom += y - - x_locs.append(x) - ticks.append(ticks_labels[info["preallocation"][idx]]) - - -plt.ylabel("Time [ms]") -plt.xticks(x_locs, ticks, rotation = 20) -plt.legend() -plt.gca().yaxis.grid() - - -if publication: - plot_helper.set_save_fig_params() - # plt.gca().tick_params(axis='x', which='major', pad=15) - plt.subplots_adjust(bottom=0.15) - plt.savefig("preallocation_timings.pdf") -else: - plt.show() - - - - diff --git a/plotting/plot_time_over_ranks.py b/plotting/plot_time_over_ranks.py deleted file mode 100644 index b758e0fd..00000000 --- a/plotting/plot_time_over_ranks.py +++ /dev/null @@ -1,36 +0,0 @@ -import json, os, sys, pandas -import matplotlib.pyplot as plt -from ipdb import set_trace - -fields = ["PetRBF.fillA", "PetRBF.fillC", "PetRBF.preallocA", "PetRBF.preallocC"] - -labels = {"_GLOBAL" : "Total", - "PetRBF.fillA" : "Filling evaluation", - "PetRBF.fillC" : "Filling interpolation", - "PetRBF.preallocA" : "Preallocation evaluation", - "PetRBF.preallocC" : "Preallocation interpolation" } - - -run_name = sys.argv[1] # like 2018-02-12T16:45:25.141337_testeins -participant = "B" - -f_timings = "{run}-{participant}.timings".format(run = run_name, participant = participant) - -info = json.load(open(run_name + ".meta")) - -df = pandas.read_csv(f_timings, comment = "#") - -for field in fields: - ys = [] - for ts in df["Timestamp"].unique(): - ys.append( df[(df.Timestamp == ts) & (df.Name == field)].Avg.max() ) # Find the maximum time across all ranks - - plt.plot(info["ranks" + participant], ys, label = labels[field]) - - -plt.grid() -plt.xlabel("Processors") -plt.ylabel("Time [ms]") - -plt.legend() -plt.show() diff --git a/precice.xml b/precice.xml deleted file mode 100644 index 8107db32..00000000 --- a/precice.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..acdb8be4 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +numpy +sympy>=1.9 diff --git a/src/common.cpp b/src/common.cpp index e0932180..91377e7b 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -1,7 +1,3 @@ -#include -#include -#include -#include "easylogging++.h" #include "common.hpp" using namespace std; @@ -9,36 +5,54 @@ using namespace std; OptionMap getOptions(int argc, char *argv[]) { namespace po = boost::program_options; - using std::cout; using std::endl; + po::options_description desc("ASTE: Artificial solver emulation tool"); - desc.add_options() - ("help,h", "produce help") - ("precice-config,c", po::value()->default_value("precice.xml"), "preCICE configuratio file") - ("participant,p", po::value()->required(), "Participant Name") - ("runName", po::value()->default_value(""), "Name of the run") - ("mesh", po::value()->required(), "Mesh directory. For each timestep i there will be .dti (e.g. .dt4) appended to the directory name") - ("output", po::value()->default_value("output"), "Output file name.") - ("verbose,v", po::bool_switch(), "Enable verbose output") // not explicitely used, handled by easylogging -; - - po::variables_map vm; + desc.add_options()("help,h", "Print this help message")("aste-config", po::value(), "ASTE Configuration file for replay mode")( + "precice-config,c", + po::value()->default_value("precice-config.xml"), + "preCICE configuratio file")( + "participant,p", + po::value(), + "Participant Name")( + "data", po::value(), + "Name of Data Array to be Mapped")( + "mesh", po::value(), + "Mesh prefix (i.e. mesh name without the format extension such as '.vtk' or '.vtu'). " + "Example: solution.vtk has the prefix 'solution'. " + "precice-aste-run will look for timeseries as well as distributed meshes (e.g. from preCICE exports) " + "automatically and load them if required.")( + "output", po::value(), + "Output file name.")( + "vector", po::bool_switch(), + "Distinguish between vector valued data and scalar data")("verbose,v", po::bool_switch(), "Enable verbose output"); // not explicitly used, handled by easylogging + + po::variables_map vm; try { po::store(parse_command_line(argc, argv, desc), vm); - + if (vm.count("help")) { - std::cout << desc << std::endl; - std::exit(-1); + ASTE_INFO << desc << std::endl; + std::exit(EXIT_SUCCESS); } - if (vm["participant"].as() != "A" && vm["participant"].as() != "B") - throw runtime_error("Invalid participant, must be either 'A' or 'B'"); + + // Needs to be called before we look for participants po::notify(vm); + + if (!vm.count("aste-config") && vm["participant"].as() != "A" && + vm["participant"].as() != "B") + throw runtime_error("Invalid participant, must be either 'A' or 'B'"); + + if (!(vm.count("participant") || vm.count("data") || vm.count("mesh") || vm.count("output") || vm.count("vector")) && vm.count("aste-config")) + throw runtime_error("Replay mode can only be combined with logging options"); + + if ((vm.count("aste-config") == 0) && not(vm.count("participant") && vm.count("data") && vm.count("mesh"))) + throw runtime_error("One of the following arguments is missing \"--participant\" \"--data\" \"--mesh\""); + + } catch (const std::exception &e) { + ASTE_ERROR << "ERROR: " << e.what() << "\n"; + ASTE_ERROR << desc << std::endl; + std::exit(EXIT_FAILURE); } - catch(const std::exception& e) { - LOG(ERROR) << "ERROR: " << e.what() << "\n"; - LOG(ERROR) << desc << std::endl; - std::exit(-1); - } - return vm; + return vm; } - diff --git a/src/common.hpp b/src/common.hpp index 47b79f78..c6e08035 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -1,7 +1,12 @@ #pragma once + +#include + #include + #include -#include + +#include "logger.hpp" using DistVertex = std::vector; @@ -20,18 +25,16 @@ void printOptions(const OptionMap &options); void printMesh(const DistMesh &mesh, const Data &data, bool verbose); // Partitions range in equal chunks -template -std::vector partition(T& range, int num) +template +std::vector partition(T &range, int num) { - int partSize = range.size() / num; + int partSize = range.size() / num; std::vector partitions; for (int i = 0; i < num; i++) { - if (i==num-1) - partitions.emplace_back(range.begin()+(i*partSize), range.end()); + if (i == num - 1) + partitions.emplace_back(range.begin() + (i * partSize), range.end()); else - partitions.emplace_back(range.begin()+(i*partSize), range.begin()+((i+1)*partSize)); - + partitions.emplace_back(range.begin() + (i * partSize), range.begin() + ((i + 1) * partSize)); } return partitions; - } diff --git a/src/configreader.cpp b/src/configreader.cpp new file mode 100644 index 00000000..42ad50c7 --- /dev/null +++ b/src/configreader.cpp @@ -0,0 +1,105 @@ +#include "configreader.hpp" + +namespace aste { +void asteConfig::load(const std::string &asteConfigFile) +{ + + std::ifstream ifs(asteConfigFile); + json config = json::parse(ifs); + + try { + preciceConfigFilename = config["precice-config"].get(); + } catch (nlohmann::detail::parse_error &) { + ASTE_ERROR << "Error while parsing ASTE configuration file \"precice-config\" is missing"; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } catch (nlohmann::detail::type_error &) { + ASTE_ERROR << "Error while parsing ASTE configuration file \"precice-config\" is missing"; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + + try { + participantName = config["participant"].get(); + } catch (nlohmann::detail::parse_error &) { + ASTE_ERROR << "Error while parsing ASTE configuration file \"participant\" is missing"; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } catch (nlohmann::detail::type_error &) { + ASTE_ERROR << "Error while parsing ASTE configuration file \"participant\" is missing"; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + + try { + startdt = config["startdt"].get(); + } catch (nlohmann::detail::type_error &) { + try { + startdt = std::stoi(config["startdt"].get()); + } catch (nlohmann::detail::type_error &) { + ASTE_ERROR << "Error while parsing ASTE configuration file \"startdt\" is missing or has a wrong type, it must be an integer or integer convertible string."; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } catch (std::invalid_argument &) { + ASTE_ERROR << "Error while parsing startdt from ASTE configuration file it must be an integer or integer convertible string."; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + } + + if (startdt < 1) { + ASTE_ERROR << "Start dt cannot be smaller than 1, please check your ASTE configuration file."; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + + const int numInterfaces = config["meshes"].size(); + + if (numInterfaces == 0) { + ASTE_ERROR << "ASTE configuration should contain at least 1 mesh. Please check your ASTE configuration file."; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + + for (auto i = 0; i < numInterfaces; i++) { + asteInterface interface; + try { + interface.meshName = config["meshes"][i]["mesh"].get(); + } catch (nlohmann::detail::parse_error &) { + ASTE_ERROR << "Error while parsing ASTE configuration file \"mesh\" is missing"; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } catch (nlohmann::detail::type_error &) { + ASTE_ERROR << "Error while parsing ASTE configuration file \"mesh\" is missing or not a string"; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + + try { + interface.meshFilePrefix = config["meshes"][i]["meshfileprefix"]; + } catch (nlohmann::detail::parse_error &) { + ASTE_ERROR << "Error while parsing ASTE configuration file \"meshfileprefix\" is missing"; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } catch (nlohmann::detail::type_error &) { + ASTE_ERROR << "Error while parsing ASTE configuration file \"meshfileprefix\" is missing or not a string"; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + + const auto readScalarSize = config["meshes"][i]["read-data"]["scalar"].size(); + const auto readVectorSize = config["meshes"][i]["read-data"]["vector"].size(); + const auto writeScalarSize = config["meshes"][i]["write-data"]["scalar"].size(); + const auto writeVectorSize = config["meshes"][i]["write-data"]["vector"].size(); + + for (std::size_t k = 0; k < readScalarSize; k++) { + const auto scalarName = config["meshes"][i]["read-data"]["scalar"][k]; + interface.readScalarNames.push_back(scalarName); + } + for (std::size_t k = 0; k < readVectorSize; k++) { + const auto vectorName = config["meshes"][i]["read-data"]["vector"][k]; + interface.readVectorNames.push_back(vectorName); + } + for (std::size_t k = 0; k < writeScalarSize; k++) { + const auto scalarName = config["meshes"][i]["write-data"]["scalar"][k]; + interface.writeScalarNames.push_back(scalarName); + } + for (std::size_t k = 0; k < writeVectorSize; k++) { + const auto vectorName = config["meshes"][i]["write-data"]["vector"][k]; + interface.writeVectorNames.push_back(vectorName); + } + asteInterfaces.push_back(interface); + } + + return; +}; + +} // namespace aste diff --git a/src/configreader.hpp b/src/configreader.hpp new file mode 100644 index 00000000..4c393c2a --- /dev/null +++ b/src/configreader.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include +#include +#include +#include + +#include + +#include "json.hpp" +#include "logger.hpp" +#include "mesh.hpp" + +#include "precice/SolverInterface.hpp" + +using json = nlohmann::json; + +namespace aste { +/** + * @brief ASTE Interface is used for store meshes and related data about a mesh. + * + */ +struct asteInterface { + std::string meshName; // Meshname in preCICE config + std::string meshFilePrefix; // Meshfile (.vtk/vtu) prefix + std::vector writeVectorNames; // Datanames of write type vectors + std::vector readVectorNames; // Datanames of read type vectors + std::vector writeScalarNames; // Datanames of write type scalars + std::vector readScalarNames; // Datanames of read type scalars + std::vector meshes; // A list of meshfiles + int meshID; // MeshID of this mesh in preCICE + Mesh mesh; // Mesh data structure in ASTE +}; + +/** + * @brief ASTE Configuration class which contain current configuration for ASTE + * + */ +class asteConfig { +public: + /** + * @brief Parser for ASTE config file + * + * @param asteConfigFile + */ + void load(const std::string &asteConfigFile); + std::string preciceConfigFilename; // preCICE config file + std::vector asteInterfaces; // Vector of ASTE interfaces(meshes) + std::string participantName; // The name of participant in preCICE config + int startdt; +}; + +} // namespace aste diff --git a/src/easylogging++.cc b/src/easylogging++.cc deleted file mode 100644 index d763ee72..00000000 --- a/src/easylogging++.cc +++ /dev/null @@ -1,3112 +0,0 @@ -// -// Bismillah ar-Rahmaan ar-Raheem -// -// Easylogging++ v9.96.7 -// Cross-platform logging library for C++ applications -// -// Copyright (c) 2012-2018 Zuhd Web Services -// Copyright (c) 2012-2018 @abumusamq -// -// This library is released under the MIT Licence. -// https://github.com/zuhd-org/easyloggingpp/blob/master/LICENSE -// -// https://zuhd.org -// http://muflihun.com -// - -#include "easylogging++.h" - -#if defined(AUTO_INITIALIZE_EASYLOGGINGPP) -INITIALIZE_EASYLOGGINGPP -#endif - -namespace el { - -// el::base -namespace base { -// el::base::consts -namespace consts { - -// Level log values - These are values that are replaced in place of %level format specifier -// Extra spaces after format specifiers are only for readability purposes in log files -static const base::type::char_t* kInfoLevelLogValue = ELPP_LITERAL("INFO"); -static const base::type::char_t* kDebugLevelLogValue = ELPP_LITERAL("DEBUG"); -static const base::type::char_t* kWarningLevelLogValue = ELPP_LITERAL("WARNING"); -static const base::type::char_t* kErrorLevelLogValue = ELPP_LITERAL("ERROR"); -static const base::type::char_t* kFatalLevelLogValue = ELPP_LITERAL("FATAL"); -static const base::type::char_t* kVerboseLevelLogValue = - ELPP_LITERAL("VERBOSE"); // will become VERBOSE-x where x = verbose level -static const base::type::char_t* kTraceLevelLogValue = ELPP_LITERAL("TRACE"); -static const base::type::char_t* kInfoLevelShortLogValue = ELPP_LITERAL("I"); -static const base::type::char_t* kDebugLevelShortLogValue = ELPP_LITERAL("D"); -static const base::type::char_t* kWarningLevelShortLogValue = ELPP_LITERAL("W"); -static const base::type::char_t* kErrorLevelShortLogValue = ELPP_LITERAL("E"); -static const base::type::char_t* kFatalLevelShortLogValue = ELPP_LITERAL("F"); -static const base::type::char_t* kVerboseLevelShortLogValue = ELPP_LITERAL("V"); -static const base::type::char_t* kTraceLevelShortLogValue = ELPP_LITERAL("T"); -// Format specifiers - These are used to define log format -static const base::type::char_t* kAppNameFormatSpecifier = ELPP_LITERAL("%app"); -static const base::type::char_t* kLoggerIdFormatSpecifier = ELPP_LITERAL("%logger"); -static const base::type::char_t* kThreadIdFormatSpecifier = ELPP_LITERAL("%thread"); -static const base::type::char_t* kSeverityLevelFormatSpecifier = ELPP_LITERAL("%level"); -static const base::type::char_t* kSeverityLevelShortFormatSpecifier = ELPP_LITERAL("%levshort"); -static const base::type::char_t* kDateTimeFormatSpecifier = ELPP_LITERAL("%datetime"); -static const base::type::char_t* kLogFileFormatSpecifier = ELPP_LITERAL("%file"); -static const base::type::char_t* kLogFileBaseFormatSpecifier = ELPP_LITERAL("%fbase"); -static const base::type::char_t* kLogLineFormatSpecifier = ELPP_LITERAL("%line"); -static const base::type::char_t* kLogLocationFormatSpecifier = ELPP_LITERAL("%loc"); -static const base::type::char_t* kLogFunctionFormatSpecifier = ELPP_LITERAL("%func"); -static const base::type::char_t* kCurrentUserFormatSpecifier = ELPP_LITERAL("%user"); -static const base::type::char_t* kCurrentHostFormatSpecifier = ELPP_LITERAL("%host"); -static const base::type::char_t* kMessageFormatSpecifier = ELPP_LITERAL("%msg"); -static const base::type::char_t* kVerboseLevelFormatSpecifier = ELPP_LITERAL("%vlevel"); -static const char* kDateTimeFormatSpecifierForFilename = "%datetime"; -// Date/time -static const char* kDays[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; -static const char* kDaysAbbrev[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; -static const char* kMonths[12] = { "January", "February", "March", "Apri", "May", "June", "July", "August", - "September", "October", "November", "December" - }; -static const char* kMonthsAbbrev[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; -static const char* kDefaultDateTimeFormat = "%Y-%M-%d %H:%m:%s,%g"; -static const char* kDefaultDateTimeFormatInFilename = "%Y-%M-%d_%H-%m"; -static const int kYearBase = 1900; -static const char* kAm = "AM"; -static const char* kPm = "PM"; -// Miscellaneous constants - -static const char* kNullPointer = "nullptr"; -#if ELPP_VARIADIC_TEMPLATES_SUPPORTED -#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED -static const base::type::VerboseLevel kMaxVerboseLevel = 9; -static const char* kUnknownUser = "user"; -static const char* kUnknownHost = "unknown-host"; - - -//---------------- DEFAULT LOG FILE ----------------------- - -#if defined(ELPP_NO_DEFAULT_LOG_FILE) -# if ELPP_OS_UNIX -static const char* kDefaultLogFile = "/dev/null"; -# elif ELPP_OS_WINDOWS -static const char* kDefaultLogFile = "nul"; -# endif // ELPP_OS_UNIX -#elif defined(ELPP_DEFAULT_LOG_FILE) -static const char* kDefaultLogFile = ELPP_DEFAULT_LOG_FILE; -#else -static const char* kDefaultLogFile = "myeasylog.log"; -#endif // defined(ELPP_NO_DEFAULT_LOG_FILE) - - -#if !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) -static const char* kDefaultLogFileParam = "--default-log-file"; -#endif // !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) -#if defined(ELPP_LOGGING_FLAGS_FROM_ARG) -static const char* kLoggingFlagsParam = "--logging-flags"; -#endif // defined(ELPP_LOGGING_FLAGS_FROM_ARG) -static const char* kValidLoggerIdSymbols = - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._"; -static const char* kConfigurationComment = "##"; -static const char* kConfigurationLevel = "*"; -static const char* kConfigurationLoggerId = "--"; -} -// el::base::utils -namespace utils { - -/// @brief Aborts application due with user-defined status -static void abort(int status, const std::string& reason) { - // Both status and reason params are there for debugging with tools like gdb etc - ELPP_UNUSED(status); - ELPP_UNUSED(reason); -#if defined(ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG) - // Ignore msvc critical error dialog - break instead (on debug mode) - _asm int 3 -#else - ::abort(); -#endif // defined(ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG) -} - -} // namespace utils -} // namespace base - -// el - -// LevelHelper - -const char* LevelHelper::convertToString(Level level) { - // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet. - if (level == Level::Global) return "GLOBAL"; - if (level == Level::Debug) return "DEBUG"; - if (level == Level::Info) return "INFO"; - if (level == Level::Warning) return "WARNING"; - if (level == Level::Error) return "ERROR"; - if (level == Level::Fatal) return "FATAL"; - if (level == Level::Verbose) return "VERBOSE"; - if (level == Level::Trace) return "TRACE"; - return "UNKNOWN"; -} - -struct StringToLevelItem { - const char* levelString; - Level level; -}; - -static struct StringToLevelItem stringToLevelMap[] = { - { "global", Level::Global }, - { "debug", Level::Debug }, - { "info", Level::Info }, - { "warning", Level::Warning }, - { "error", Level::Error }, - { "fatal", Level::Fatal }, - { "verbose", Level::Verbose }, - { "trace", Level::Trace } -}; - -Level LevelHelper::convertFromString(const char* levelStr) { - for (auto& item : stringToLevelMap) { - if (base::utils::Str::cStringCaseEq(levelStr, item.levelString)) { - return item.level; - } - } - return Level::Unknown; -} - -void LevelHelper::forEachLevel(base::type::EnumType* startIndex, const std::function& fn) { - base::type::EnumType lIndexMax = LevelHelper::kMaxValid; - do { - if (fn()) { - break; - } - *startIndex = static_cast(*startIndex << 1); - } while (*startIndex <= lIndexMax); -} - -// ConfigurationTypeHelper - -const char* ConfigurationTypeHelper::convertToString(ConfigurationType configurationType) { - // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet. - if (configurationType == ConfigurationType::Enabled) return "ENABLED"; - if (configurationType == ConfigurationType::Filename) return "FILENAME"; - if (configurationType == ConfigurationType::Format) return "FORMAT"; - if (configurationType == ConfigurationType::ToFile) return "TO_FILE"; - if (configurationType == ConfigurationType::ToStandardOutput) return "TO_STANDARD_OUTPUT"; - if (configurationType == ConfigurationType::SubsecondPrecision) return "SUBSECOND_PRECISION"; - if (configurationType == ConfigurationType::PerformanceTracking) return "PERFORMANCE_TRACKING"; - if (configurationType == ConfigurationType::MaxLogFileSize) return "MAX_LOG_FILE_SIZE"; - if (configurationType == ConfigurationType::LogFlushThreshold) return "LOG_FLUSH_THRESHOLD"; - return "UNKNOWN"; -} - -struct ConfigurationStringToTypeItem { - const char* configString; - ConfigurationType configType; -}; - -static struct ConfigurationStringToTypeItem configStringToTypeMap[] = { - { "enabled", ConfigurationType::Enabled }, - { "to_file", ConfigurationType::ToFile }, - { "to_standard_output", ConfigurationType::ToStandardOutput }, - { "format", ConfigurationType::Format }, - { "filename", ConfigurationType::Filename }, - { "subsecond_precision", ConfigurationType::SubsecondPrecision }, - { "milliseconds_width", ConfigurationType::MillisecondsWidth }, - { "performance_tracking", ConfigurationType::PerformanceTracking }, - { "max_log_file_size", ConfigurationType::MaxLogFileSize }, - { "log_flush_threshold", ConfigurationType::LogFlushThreshold }, -}; - -ConfigurationType ConfigurationTypeHelper::convertFromString(const char* configStr) { - for (auto& item : configStringToTypeMap) { - if (base::utils::Str::cStringCaseEq(configStr, item.configString)) { - return item.configType; - } - } - return ConfigurationType::Unknown; -} - -void ConfigurationTypeHelper::forEachConfigType(base::type::EnumType* startIndex, const std::function& fn) { - base::type::EnumType cIndexMax = ConfigurationTypeHelper::kMaxValid; - do { - if (fn()) { - break; - } - *startIndex = static_cast(*startIndex << 1); - } while (*startIndex <= cIndexMax); -} - -// Configuration - -Configuration::Configuration(const Configuration& c) : - m_level(c.m_level), - m_configurationType(c.m_configurationType), - m_value(c.m_value) { -} - -Configuration& Configuration::operator=(const Configuration& c) { - if (&c != this) { - m_level = c.m_level; - m_configurationType = c.m_configurationType; - m_value = c.m_value; - } - return *this; -} - -/// @brief Full constructor used to sets value of configuration -Configuration::Configuration(Level level, ConfigurationType configurationType, const std::string& value) : - m_level(level), - m_configurationType(configurationType), - m_value(value) { -} - -void Configuration::log(el::base::type::ostream_t& os) const { - os << LevelHelper::convertToString(m_level) - << ELPP_LITERAL(" ") << ConfigurationTypeHelper::convertToString(m_configurationType) - << ELPP_LITERAL(" = ") << m_value.c_str(); -} - -/// @brief Used to find configuration from configuration (pointers) repository. Avoid using it. -Configuration::Predicate::Predicate(Level level, ConfigurationType configurationType) : - m_level(level), - m_configurationType(configurationType) { -} - -bool Configuration::Predicate::operator()(const Configuration* conf) const { - return ((conf != nullptr) && (conf->level() == m_level) && (conf->configurationType() == m_configurationType)); -} - -// Configurations - -Configurations::Configurations(void) : - m_configurationFile(std::string()), - m_isFromFile(false) { -} - -Configurations::Configurations(const std::string& configurationFile, bool useDefaultsForRemaining, - Configurations* base) : - m_configurationFile(configurationFile), - m_isFromFile(false) { - parseFromFile(configurationFile, base); - if (useDefaultsForRemaining) { - setRemainingToDefault(); - } -} - -bool Configurations::parseFromFile(const std::string& configurationFile, Configurations* base) { - // We initial assertion with true because if we have assertion diabled, we want to pass this - // check and if assertion is enabled we will have values re-assigned any way. - bool assertionPassed = true; - ELPP_ASSERT((assertionPassed = base::utils::File::pathExists(configurationFile.c_str(), true)) == true, - "Configuration file [" << configurationFile << "] does not exist!"); - if (!assertionPassed) { - return false; - } - bool success = Parser::parseFromFile(configurationFile, this, base); - m_isFromFile = success; - return success; -} - -bool Configurations::parseFromText(const std::string& configurationsString, Configurations* base) { - bool success = Parser::parseFromText(configurationsString, this, base); - if (success) { - m_isFromFile = false; - } - return success; -} - -void Configurations::setFromBase(Configurations* base) { - if (base == nullptr || base == this) { - return; - } - base::threading::ScopedLock scopedLock(base->lock()); - for (Configuration*& conf : base->list()) { - set(conf); - } -} - -bool Configurations::hasConfiguration(ConfigurationType configurationType) { - base::type::EnumType lIndex = LevelHelper::kMinValid; - bool result = false; - LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { - if (hasConfiguration(LevelHelper::castFromInt(lIndex), configurationType)) { - result = true; - } - return result; - }); - return result; -} - -bool Configurations::hasConfiguration(Level level, ConfigurationType configurationType) { - base::threading::ScopedLock scopedLock(lock()); -#if ELPP_COMPILER_INTEL - // We cant specify template types here, Intel C++ throws compilation error - // "error: type name is not allowed" - return RegistryWithPred::get(level, configurationType) != nullptr; -#else - return RegistryWithPred::get(level, configurationType) != nullptr; -#endif // ELPP_COMPILER_INTEL -} - -void Configurations::set(Level level, ConfigurationType configurationType, const std::string& value) { - base::threading::ScopedLock scopedLock(lock()); - unsafeSet(level, configurationType, value); // This is not unsafe anymore as we have locked mutex - if (level == Level::Global) { - unsafeSetGlobally(configurationType, value, false); // Again this is not unsafe either - } -} - -void Configurations::set(Configuration* conf) { - if (conf == nullptr) { - return; - } - set(conf->level(), conf->configurationType(), conf->value()); -} - -void Configurations::setToDefault(void) { - setGlobally(ConfigurationType::Enabled, std::string("true"), true); - setGlobally(ConfigurationType::Filename, std::string(base::consts::kDefaultLogFile), true); -#if defined(ELPP_NO_LOG_TO_FILE) - setGlobally(ConfigurationType::ToFile, std::string("false"), true); -#else - setGlobally(ConfigurationType::ToFile, std::string("true"), true); -#endif // defined(ELPP_NO_LOG_TO_FILE) - setGlobally(ConfigurationType::ToStandardOutput, std::string("true"), true); - setGlobally(ConfigurationType::SubsecondPrecision, std::string("3"), true); - setGlobally(ConfigurationType::PerformanceTracking, std::string("true"), true); - setGlobally(ConfigurationType::MaxLogFileSize, std::string("0"), true); - setGlobally(ConfigurationType::LogFlushThreshold, std::string("0"), true); - - setGlobally(ConfigurationType::Format, std::string("%datetime %level [%logger] %msg"), true); - set(Level::Debug, ConfigurationType::Format, - std::string("%datetime %level [%logger] [%user@%host] [%func] [%loc] %msg")); - // INFO and WARNING are set to default by Level::Global - set(Level::Error, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); - set(Level::Fatal, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); - set(Level::Verbose, ConfigurationType::Format, std::string("%datetime %level-%vlevel [%logger] %msg")); - set(Level::Trace, ConfigurationType::Format, std::string("%datetime %level [%logger] [%func] [%loc] %msg")); -} - -void Configurations::setRemainingToDefault(void) { - base::threading::ScopedLock scopedLock(lock()); -#if defined(ELPP_NO_LOG_TO_FILE) - unsafeSetIfNotExist(Level::Global, ConfigurationType::Enabled, std::string("false")); -#else - unsafeSetIfNotExist(Level::Global, ConfigurationType::Enabled, std::string("true")); -#endif // defined(ELPP_NO_LOG_TO_FILE) - unsafeSetIfNotExist(Level::Global, ConfigurationType::Filename, std::string(base::consts::kDefaultLogFile)); - unsafeSetIfNotExist(Level::Global, ConfigurationType::ToStandardOutput, std::string("true")); - unsafeSetIfNotExist(Level::Global, ConfigurationType::SubsecondPrecision, std::string("3")); - unsafeSetIfNotExist(Level::Global, ConfigurationType::PerformanceTracking, std::string("true")); - unsafeSetIfNotExist(Level::Global, ConfigurationType::MaxLogFileSize, std::string("0")); - unsafeSetIfNotExist(Level::Global, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); - unsafeSetIfNotExist(Level::Debug, ConfigurationType::Format, - std::string("%datetime %level [%logger] [%user@%host] [%func] [%loc] %msg")); - // INFO and WARNING are set to default by Level::Global - unsafeSetIfNotExist(Level::Error, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); - unsafeSetIfNotExist(Level::Fatal, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); - unsafeSetIfNotExist(Level::Verbose, ConfigurationType::Format, std::string("%datetime %level-%vlevel [%logger] %msg")); - unsafeSetIfNotExist(Level::Trace, ConfigurationType::Format, - std::string("%datetime %level [%logger] [%func] [%loc] %msg")); -} - -bool Configurations::Parser::parseFromFile(const std::string& configurationFile, Configurations* sender, - Configurations* base) { - sender->setFromBase(base); - std::ifstream fileStream_(configurationFile.c_str(), std::ifstream::in); - ELPP_ASSERT(fileStream_.is_open(), "Unable to open configuration file [" << configurationFile << "] for parsing."); - bool parsedSuccessfully = false; - std::string line = std::string(); - Level currLevel = Level::Unknown; - std::string currConfigStr = std::string(); - std::string currLevelStr = std::string(); - while (fileStream_.good()) { - std::getline(fileStream_, line); - parsedSuccessfully = parseLine(&line, &currConfigStr, &currLevelStr, &currLevel, sender); - ELPP_ASSERT(parsedSuccessfully, "Unable to parse configuration line: " << line); - } - return parsedSuccessfully; -} - -bool Configurations::Parser::parseFromText(const std::string& configurationsString, Configurations* sender, - Configurations* base) { - sender->setFromBase(base); - bool parsedSuccessfully = false; - std::stringstream ss(configurationsString); - std::string line = std::string(); - Level currLevel = Level::Unknown; - std::string currConfigStr = std::string(); - std::string currLevelStr = std::string(); - while (std::getline(ss, line)) { - parsedSuccessfully = parseLine(&line, &currConfigStr, &currLevelStr, &currLevel, sender); - ELPP_ASSERT(parsedSuccessfully, "Unable to parse configuration line: " << line); - } - return parsedSuccessfully; -} - -void Configurations::Parser::ignoreComments(std::string* line) { - std::size_t foundAt = 0; - std::size_t quotesStart = line->find("\""); - std::size_t quotesEnd = std::string::npos; - if (quotesStart != std::string::npos) { - quotesEnd = line->find("\"", quotesStart + 1); - while (quotesEnd != std::string::npos && line->at(quotesEnd - 1) == '\\') { - // Do not erase slash yet - we will erase it in parseLine(..) while loop - quotesEnd = line->find("\"", quotesEnd + 2); - } - } - if ((foundAt = line->find(base::consts::kConfigurationComment)) != std::string::npos) { - if (foundAt < quotesEnd) { - foundAt = line->find(base::consts::kConfigurationComment, quotesEnd + 1); - } - *line = line->substr(0, foundAt); - } -} - -bool Configurations::Parser::isLevel(const std::string& line) { - return base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationLevel)); -} - -bool Configurations::Parser::isComment(const std::string& line) { - return base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationComment)); -} - -bool Configurations::Parser::isConfig(const std::string& line) { - std::size_t assignment = line.find('='); - return line != "" && - ((line[0] >= 'A' && line[0] <= 'Z') || (line[0] >= 'a' && line[0] <= 'z')) && - (assignment != std::string::npos) && - (line.size() > assignment); -} - -bool Configurations::Parser::parseLine(std::string* line, std::string* currConfigStr, std::string* currLevelStr, - Level* currLevel, - Configurations* conf) { - ConfigurationType currConfig = ConfigurationType::Unknown; - std::string currValue = std::string(); - *line = base::utils::Str::trim(*line); - if (isComment(*line)) return true; - ignoreComments(line); - *line = base::utils::Str::trim(*line); - if (line->empty()) { - // Comment ignored - return true; - } - if (isLevel(*line)) { - if (line->size() <= 2) { - return true; - } - *currLevelStr = line->substr(1, line->size() - 2); - *currLevelStr = base::utils::Str::toUpper(*currLevelStr); - *currLevelStr = base::utils::Str::trim(*currLevelStr); - *currLevel = LevelHelper::convertFromString(currLevelStr->c_str()); - return true; - } - if (isConfig(*line)) { - std::size_t assignment = line->find('='); - *currConfigStr = line->substr(0, assignment); - *currConfigStr = base::utils::Str::toUpper(*currConfigStr); - *currConfigStr = base::utils::Str::trim(*currConfigStr); - currConfig = ConfigurationTypeHelper::convertFromString(currConfigStr->c_str()); - currValue = line->substr(assignment + 1); - currValue = base::utils::Str::trim(currValue); - std::size_t quotesStart = currValue.find("\"", 0); - std::size_t quotesEnd = std::string::npos; - if (quotesStart != std::string::npos) { - quotesEnd = currValue.find("\"", quotesStart + 1); - while (quotesEnd != std::string::npos && currValue.at(quotesEnd - 1) == '\\') { - currValue = currValue.erase(quotesEnd - 1, 1); - quotesEnd = currValue.find("\"", quotesEnd + 2); - } - } - if (quotesStart != std::string::npos && quotesEnd != std::string::npos) { - // Quote provided - check and strip if valid - ELPP_ASSERT((quotesStart < quotesEnd), "Configuration error - No ending quote found in [" - << currConfigStr << "]"); - ELPP_ASSERT((quotesStart + 1 != quotesEnd), "Empty configuration value for [" << currConfigStr << "]"); - if ((quotesStart != quotesEnd) && (quotesStart + 1 != quotesEnd)) { - // Explicit check in case if assertion is disabled - currValue = currValue.substr(quotesStart + 1, quotesEnd - 1); - } - } - } - ELPP_ASSERT(*currLevel != Level::Unknown, "Unrecognized severity level [" << *currLevelStr << "]"); - ELPP_ASSERT(currConfig != ConfigurationType::Unknown, "Unrecognized configuration [" << *currConfigStr << "]"); - if (*currLevel == Level::Unknown || currConfig == ConfigurationType::Unknown) { - return false; // unrecognizable level or config - } - conf->set(*currLevel, currConfig, currValue); - return true; -} - -void Configurations::unsafeSetIfNotExist(Level level, ConfigurationType configurationType, const std::string& value) { - Configuration* conf = RegistryWithPred::get(level, configurationType); - if (conf == nullptr) { - unsafeSet(level, configurationType, value); - } -} - -void Configurations::unsafeSet(Level level, ConfigurationType configurationType, const std::string& value) { - Configuration* conf = RegistryWithPred::get(level, configurationType); - if (conf == nullptr) { - registerNew(new Configuration(level, configurationType, value)); - } else { - conf->setValue(value); - } - if (level == Level::Global) { - unsafeSetGlobally(configurationType, value, false); - } -} - -void Configurations::setGlobally(ConfigurationType configurationType, const std::string& value, - bool includeGlobalLevel) { - if (includeGlobalLevel) { - set(Level::Global, configurationType, value); - } - base::type::EnumType lIndex = LevelHelper::kMinValid; - LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { - set(LevelHelper::castFromInt(lIndex), configurationType, value); - return false; // Do not break lambda function yet as we need to set all levels regardless - }); -} - -void Configurations::unsafeSetGlobally(ConfigurationType configurationType, const std::string& value, - bool includeGlobalLevel) { - if (includeGlobalLevel) { - unsafeSet(Level::Global, configurationType, value); - } - base::type::EnumType lIndex = LevelHelper::kMinValid; - LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { - unsafeSet(LevelHelper::castFromInt(lIndex), configurationType, value); - return false; // Do not break lambda function yet as we need to set all levels regardless - }); -} - -// LogBuilder - -void LogBuilder::convertToColoredOutput(base::type::string_t* logLine, Level level) { - if (!m_termSupportsColor) return; - const base::type::char_t* resetColor = ELPP_LITERAL("\x1b[0m"); - if (level == Level::Error || level == Level::Fatal) - *logLine = ELPP_LITERAL("\x1b[31m") + *logLine + resetColor; - else if (level == Level::Warning) - *logLine = ELPP_LITERAL("\x1b[33m") + *logLine + resetColor; - else if (level == Level::Debug) - *logLine = ELPP_LITERAL("\x1b[32m") + *logLine + resetColor; - else if (level == Level::Info) - *logLine = ELPP_LITERAL("\x1b[36m") + *logLine + resetColor; - else if (level == Level::Trace) - *logLine = ELPP_LITERAL("\x1b[35m") + *logLine + resetColor; -} - -// Logger - -Logger::Logger(const std::string& id, base::LogStreamsReferenceMap* logStreamsReference) : - m_id(id), - m_typedConfigurations(nullptr), - m_parentApplicationName(std::string()), - m_isConfigured(false), - m_logStreamsReference(logStreamsReference) { - initUnflushedCount(); -} - -Logger::Logger(const std::string& id, const Configurations& configurations, - base::LogStreamsReferenceMap* logStreamsReference) : - m_id(id), - m_typedConfigurations(nullptr), - m_parentApplicationName(std::string()), - m_isConfigured(false), - m_logStreamsReference(logStreamsReference) { - initUnflushedCount(); - configure(configurations); -} - -Logger::Logger(const Logger& logger) { - base::utils::safeDelete(m_typedConfigurations); - m_id = logger.m_id; - m_typedConfigurations = logger.m_typedConfigurations; - m_parentApplicationName = logger.m_parentApplicationName; - m_isConfigured = logger.m_isConfigured; - m_configurations = logger.m_configurations; - m_unflushedCount = logger.m_unflushedCount; - m_logStreamsReference = logger.m_logStreamsReference; -} - -Logger& Logger::operator=(const Logger& logger) { - if (&logger != this) { - base::utils::safeDelete(m_typedConfigurations); - m_id = logger.m_id; - m_typedConfigurations = logger.m_typedConfigurations; - m_parentApplicationName = logger.m_parentApplicationName; - m_isConfigured = logger.m_isConfigured; - m_configurations = logger.m_configurations; - m_unflushedCount = logger.m_unflushedCount; - m_logStreamsReference = logger.m_logStreamsReference; - } - return *this; -} - -void Logger::configure(const Configurations& configurations) { - m_isConfigured = false; // we set it to false in case if we fail - initUnflushedCount(); - if (m_typedConfigurations != nullptr) { - Configurations* c = const_cast(m_typedConfigurations->configurations()); - if (c->hasConfiguration(Level::Global, ConfigurationType::Filename)) { - flush(); - } - } - base::threading::ScopedLock scopedLock(lock()); - if (m_configurations != configurations) { - m_configurations.setFromBase(const_cast(&configurations)); - } - base::utils::safeDelete(m_typedConfigurations); - m_typedConfigurations = new base::TypedConfigurations(&m_configurations, m_logStreamsReference); - resolveLoggerFormatSpec(); - m_isConfigured = true; -} - -void Logger::reconfigure(void) { - ELPP_INTERNAL_INFO(1, "Reconfiguring logger [" << m_id << "]"); - configure(m_configurations); -} - -bool Logger::isValidId(const std::string& id) { - for (std::string::const_iterator it = id.begin(); it != id.end(); ++it) { - if (!base::utils::Str::contains(base::consts::kValidLoggerIdSymbols, *it)) { - return false; - } - } - return true; -} - -void Logger::flush(void) { - ELPP_INTERNAL_INFO(3, "Flushing logger [" << m_id << "] all levels"); - base::threading::ScopedLock scopedLock(lock()); - base::type::EnumType lIndex = LevelHelper::kMinValid; - LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { - flush(LevelHelper::castFromInt(lIndex), nullptr); - return false; - }); -} - -void Logger::flush(Level level, base::type::fstream_t* fs) { - if (fs == nullptr && m_typedConfigurations->toFile(level)) { - fs = m_typedConfigurations->fileStream(level); - } - if (fs != nullptr) { - fs->flush(); - std::unordered_map::iterator iter = m_unflushedCount.find(level); - if (iter != m_unflushedCount.end()) { - iter->second = 0; - } - Helpers::validateFileRolling(this, level); - } -} - -void Logger::initUnflushedCount(void) { - m_unflushedCount.clear(); - base::type::EnumType lIndex = LevelHelper::kMinValid; - LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { - m_unflushedCount.insert(std::make_pair(LevelHelper::castFromInt(lIndex), 0)); - return false; - }); -} - -void Logger::resolveLoggerFormatSpec(void) const { - base::type::EnumType lIndex = LevelHelper::kMinValid; - LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { - base::LogFormat* logFormat = - const_cast(&m_typedConfigurations->logFormat(LevelHelper::castFromInt(lIndex))); - base::utils::Str::replaceFirstWithEscape(logFormat->m_format, base::consts::kLoggerIdFormatSpecifier, m_id); - return false; - }); -} - -// el::base -namespace base { - -// el::base::utils -namespace utils { - -// File - -base::type::fstream_t* File::newFileStream(const std::string& filename) { - base::type::fstream_t *fs = new base::type::fstream_t(filename.c_str(), - base::type::fstream_t::out -#if !defined(ELPP_FRESH_LOG_FILE) - | base::type::fstream_t::app -#endif - ); -#if defined(ELPP_UNICODE) - std::locale elppUnicodeLocale(""); -# if ELPP_OS_WINDOWS - std::locale elppUnicodeLocaleWindows(elppUnicodeLocale, new std::codecvt_utf8_utf16); - elppUnicodeLocale = elppUnicodeLocaleWindows; -# endif // ELPP_OS_WINDOWS - fs->imbue(elppUnicodeLocale); -#endif // defined(ELPP_UNICODE) - if (fs->is_open()) { - fs->flush(); - } else { - base::utils::safeDelete(fs); - ELPP_INTERNAL_ERROR("Bad file [" << filename << "]", true); - } - return fs; -} - -std::size_t File::getSizeOfFile(base::type::fstream_t* fs) { - if (fs == nullptr) { - return 0; - } - // Since the file stream is appended to or truncated, the current - // offset is the file size. - std::size_t size = static_cast(fs->tellg()); - return size; -} - -bool File::pathExists(const char* path, bool considerFile) { - if (path == nullptr) { - return false; - } -#if ELPP_OS_UNIX - ELPP_UNUSED(considerFile); - struct stat st; - return (stat(path, &st) == 0); -#elif ELPP_OS_WINDOWS - DWORD fileType = GetFileAttributesA(path); - if (fileType == INVALID_FILE_ATTRIBUTES) { - return false; - } - return considerFile ? true : ((fileType & FILE_ATTRIBUTE_DIRECTORY) == 0 ? false : true); -#endif // ELPP_OS_UNIX -} - -bool File::createPath(const std::string& path) { - if (path.empty()) { - return false; - } - if (base::utils::File::pathExists(path.c_str())) { - return true; - } - int status = -1; - - char* currPath = const_cast(path.c_str()); - std::string builtPath = std::string(); -#if ELPP_OS_UNIX - if (path[0] == '/') { - builtPath = "/"; - } - currPath = STRTOK(currPath, base::consts::kFilePathSeperator, 0); -#elif ELPP_OS_WINDOWS - // Use secure functions API - char* nextTok_ = nullptr; - currPath = STRTOK(currPath, base::consts::kFilePathSeperator, &nextTok_); - ELPP_UNUSED(nextTok_); -#endif // ELPP_OS_UNIX - while (currPath != nullptr) { - builtPath.append(currPath); - builtPath.append(base::consts::kFilePathSeperator); -#if ELPP_OS_UNIX - status = mkdir(builtPath.c_str(), ELPP_LOG_PERMS); - currPath = STRTOK(nullptr, base::consts::kFilePathSeperator, 0); -#elif ELPP_OS_WINDOWS - status = _mkdir(builtPath.c_str()); - currPath = STRTOK(nullptr, base::consts::kFilePathSeperator, &nextTok_); -#endif // ELPP_OS_UNIX - } - if (status == -1) { - ELPP_INTERNAL_ERROR("Error while creating path [" << path << "]", true); - return false; - } - return true; -} - -std::string File::extractPathFromFilename(const std::string& fullPath, const char* separator) { - if ((fullPath == "") || (fullPath.find(separator) == std::string::npos)) { - return fullPath; - } - std::size_t lastSlashAt = fullPath.find_last_of(separator); - if (lastSlashAt == 0) { - return std::string(separator); - } - return fullPath.substr(0, lastSlashAt + 1); -} - -void File::buildStrippedFilename(const char* filename, char buff[], std::size_t limit) { - std::size_t sizeOfFilename = strlen(filename); - if (sizeOfFilename >= limit) { - filename += (sizeOfFilename - limit); - if (filename[0] != '.' && filename[1] != '.') { // prepend if not already - filename += 3; // 3 = '..' - STRCAT(buff, "..", limit); - } - } - STRCAT(buff, filename, limit); -} - -void File::buildBaseFilename(const std::string& fullPath, char buff[], std::size_t limit, const char* separator) { - const char *filename = fullPath.c_str(); - std::size_t lastSlashAt = fullPath.find_last_of(separator); - filename += lastSlashAt ? lastSlashAt+1 : 0; - std::size_t sizeOfFilename = strlen(filename); - if (sizeOfFilename >= limit) { - filename += (sizeOfFilename - limit); - if (filename[0] != '.' && filename[1] != '.') { // prepend if not already - filename += 3; // 3 = '..' - STRCAT(buff, "..", limit); - } - } - STRCAT(buff, filename, limit); -} - -// Str - -bool Str::wildCardMatch(const char* str, const char* pattern) { - while (*pattern) { - switch (*pattern) { - case '?': - if (!*str) - return false; - ++str; - ++pattern; - break; - case '*': - if (wildCardMatch(str, pattern + 1)) - return true; - if (*str && wildCardMatch(str + 1, pattern)) - return true; - return false; - default: - if (*str++ != *pattern++) - return false; - break; - } - } - return !*str && !*pattern; -} - -std::string& Str::ltrim(std::string& str) { - str.erase(str.begin(), std::find_if(str.begin(), str.end(), [](char c) { - return !std::isspace(c); - } )); - return str; -} - -std::string& Str::rtrim(std::string& str) { - str.erase(std::find_if(str.rbegin(), str.rend(), [](char c) { - return !std::isspace(c); - }).base(), str.end()); - return str; -} - -std::string& Str::trim(std::string& str) { - return ltrim(rtrim(str)); -} - -bool Str::startsWith(const std::string& str, const std::string& start) { - return (str.length() >= start.length()) && (str.compare(0, start.length(), start) == 0); -} - -bool Str::endsWith(const std::string& str, const std::string& end) { - return (str.length() >= end.length()) && (str.compare(str.length() - end.length(), end.length(), end) == 0); -} - -std::string& Str::replaceAll(std::string& str, char replaceWhat, char replaceWith) { - std::replace(str.begin(), str.end(), replaceWhat, replaceWith); - return str; -} - -std::string& Str::replaceAll(std::string& str, const std::string& replaceWhat, - const std::string& replaceWith) { - if (replaceWhat == replaceWith) - return str; - std::size_t foundAt = std::string::npos; - while ((foundAt = str.find(replaceWhat, foundAt + 1)) != std::string::npos) { - str.replace(foundAt, replaceWhat.length(), replaceWith); - } - return str; -} - -void Str::replaceFirstWithEscape(base::type::string_t& str, const base::type::string_t& replaceWhat, - const base::type::string_t& replaceWith) { - std::size_t foundAt = base::type::string_t::npos; - while ((foundAt = str.find(replaceWhat, foundAt + 1)) != base::type::string_t::npos) { - if (foundAt > 0 && str[foundAt - 1] == base::consts::kFormatSpecifierChar) { - str.erase(foundAt - 1, 1); - ++foundAt; - } else { - str.replace(foundAt, replaceWhat.length(), replaceWith); - return; - } - } -} -#if defined(ELPP_UNICODE) -void Str::replaceFirstWithEscape(base::type::string_t& str, const base::type::string_t& replaceWhat, - const std::string& replaceWith) { - replaceFirstWithEscape(str, replaceWhat, base::type::string_t(replaceWith.begin(), replaceWith.end())); -} -#endif // defined(ELPP_UNICODE) - -std::string& Str::toUpper(std::string& str) { - std::transform(str.begin(), str.end(), str.begin(), - [](char c) { - return static_cast(::toupper(c)); - }); - return str; -} - -bool Str::cStringEq(const char* s1, const char* s2) { - if (s1 == nullptr && s2 == nullptr) return true; - if (s1 == nullptr || s2 == nullptr) return false; - return strcmp(s1, s2) == 0; -} - -bool Str::cStringCaseEq(const char* s1, const char* s2) { - if (s1 == nullptr && s2 == nullptr) return true; - if (s1 == nullptr || s2 == nullptr) return false; - - // With thanks to cygwin for this code - int d = 0; - - while (true) { - const int c1 = toupper(*s1++); - const int c2 = toupper(*s2++); - - if (((d = c1 - c2) != 0) || (c2 == '\0')) { - break; - } - } - - return d == 0; -} - -bool Str::contains(const char* str, char c) { - for (; *str; ++str) { - if (*str == c) - return true; - } - return false; -} - -char* Str::convertAndAddToBuff(std::size_t n, int len, char* buf, const char* bufLim, bool zeroPadded) { - char localBuff[10] = ""; - char* p = localBuff + sizeof(localBuff) - 2; - if (n > 0) { - for (; n > 0 && p > localBuff && len > 0; n /= 10, --len) - *--p = static_cast(n % 10 + '0'); - } else { - *--p = '0'; - --len; - } - if (zeroPadded) - while (p > localBuff && len-- > 0) *--p = static_cast('0'); - return addToBuff(p, buf, bufLim); -} - -char* Str::addToBuff(const char* str, char* buf, const char* bufLim) { - while ((buf < bufLim) && ((*buf = *str++) != '\0')) - ++buf; - return buf; -} - -char* Str::clearBuff(char buff[], std::size_t lim) { - STRCPY(buff, "", lim); - ELPP_UNUSED(lim); // For *nix we dont have anything using lim in above STRCPY macro - return buff; -} - -/// @brief Converst wchar* to char* -/// NOTE: Need to free return value after use! -char* Str::wcharPtrToCharPtr(const wchar_t* line) { - std::size_t len_ = wcslen(line) + 1; - char* buff_ = static_cast(malloc(len_ + 1)); -# if ELPP_OS_UNIX || (ELPP_OS_WINDOWS && !ELPP_CRT_DBG_WARNINGS) - std::wcstombs(buff_, line, len_); -# elif ELPP_OS_WINDOWS - std::size_t convCount_ = 0; - mbstate_t mbState_; - ::memset(static_cast(&mbState_), 0, sizeof(mbState_)); - wcsrtombs_s(&convCount_, buff_, len_, &line, len_, &mbState_); -# endif // ELPP_OS_UNIX || (ELPP_OS_WINDOWS && !ELPP_CRT_DBG_WARNINGS) - return buff_; -} - -// OS - -#if ELPP_OS_WINDOWS -/// @brief Gets environment variables for Windows based OS. -/// We are not using getenv(const char*) because of CRT deprecation -/// @param varname Variable name to get environment variable value for -/// @return If variable exist the value of it otherwise nullptr -const char* OS::getWindowsEnvironmentVariable(const char* varname) { - const DWORD bufferLen = 50; - static char buffer[bufferLen]; - if (GetEnvironmentVariableA(varname, buffer, bufferLen)) { - return buffer; - } - return nullptr; -} -#endif // ELPP_OS_WINDOWS -#if ELPP_OS_ANDROID -std::string OS::getProperty(const char* prop) { - char propVal[PROP_VALUE_MAX + 1]; - int ret = __system_property_get(prop, propVal); - return ret == 0 ? std::string() : std::string(propVal); -} - -std::string OS::getDeviceName(void) { - std::stringstream ss; - std::string manufacturer = getProperty("ro.product.manufacturer"); - std::string model = getProperty("ro.product.model"); - if (manufacturer.empty() || model.empty()) { - return std::string(); - } - ss << manufacturer << "-" << model; - return ss.str(); -} -#endif // ELPP_OS_ANDROID - -const std::string OS::getBashOutput(const char* command) { -#if (ELPP_OS_UNIX && !ELPP_OS_ANDROID && !ELPP_CYGWIN) - if (command == nullptr) { - return std::string(); - } - FILE* proc = nullptr; - if ((proc = popen(command, "r")) == nullptr) { - ELPP_INTERNAL_ERROR("\nUnable to run command [" << command << "]", true); - return std::string(); - } - char hBuff[4096]; - if (fgets(hBuff, sizeof(hBuff), proc) != nullptr) { - pclose(proc); - const std::size_t buffLen = strlen(hBuff); - if (buffLen > 0 && hBuff[buffLen - 1] == '\n') { - hBuff[buffLen - 1] = '\0'; - } - return std::string(hBuff); - } else { - pclose(proc); - } - return std::string(); -#else - ELPP_UNUSED(command); - return std::string(); -#endif // (ELPP_OS_UNIX && !ELPP_OS_ANDROID && !ELPP_CYGWIN) -} - -std::string OS::getEnvironmentVariable(const char* variableName, const char* defaultVal, - const char* alternativeBashCommand) { -#if ELPP_OS_UNIX - const char* val = getenv(variableName); -#elif ELPP_OS_WINDOWS - const char* val = getWindowsEnvironmentVariable(variableName); -#endif // ELPP_OS_UNIX - if ((val == nullptr) || ((strcmp(val, "") == 0))) { -#if ELPP_OS_UNIX && defined(ELPP_FORCE_ENV_VAR_FROM_BASH) - // Try harder on unix-based systems - std::string valBash = base::utils::OS::getBashOutput(alternativeBashCommand); - if (valBash.empty()) { - return std::string(defaultVal); - } else { - return valBash; - } -#elif ELPP_OS_WINDOWS || ELPP_OS_UNIX - ELPP_UNUSED(alternativeBashCommand); - return std::string(defaultVal); -#endif // ELPP_OS_UNIX && defined(ELPP_FORCE_ENV_VAR_FROM_BASH) - } - return std::string(val); -} - -std::string OS::currentUser(void) { -#if ELPP_OS_UNIX && !ELPP_OS_ANDROID - return getEnvironmentVariable("USER", base::consts::kUnknownUser, "whoami"); -#elif ELPP_OS_WINDOWS - return getEnvironmentVariable("USERNAME", base::consts::kUnknownUser); -#elif ELPP_OS_ANDROID - ELPP_UNUSED(base::consts::kUnknownUser); - return std::string("android"); -#else - return std::string(); -#endif // ELPP_OS_UNIX && !ELPP_OS_ANDROID -} - -std::string OS::currentHost(void) { -#if ELPP_OS_UNIX && !ELPP_OS_ANDROID - return getEnvironmentVariable("HOSTNAME", base::consts::kUnknownHost, "hostname"); -#elif ELPP_OS_WINDOWS - return getEnvironmentVariable("COMPUTERNAME", base::consts::kUnknownHost); -#elif ELPP_OS_ANDROID - ELPP_UNUSED(base::consts::kUnknownHost); - return getDeviceName(); -#else - return std::string(); -#endif // ELPP_OS_UNIX && !ELPP_OS_ANDROID -} - -bool OS::termSupportsColor(void) { - std::string term = getEnvironmentVariable("TERM", ""); - return term == "xterm" || term == "xterm-color" || term == "xterm-256color" - || term == "screen" || term == "linux" || term == "cygwin" - || term == "screen-256color"; -} - -// DateTime - -void DateTime::gettimeofday(struct timeval* tv) { -#if ELPP_OS_WINDOWS - if (tv != nullptr) { -# if ELPP_COMPILER_MSVC || defined(_MSC_EXTENSIONS) - const unsigned __int64 delta_ = 11644473600000000Ui64; -# else - const unsigned __int64 delta_ = 11644473600000000ULL; -# endif // ELPP_COMPILER_MSVC || defined(_MSC_EXTENSIONS) - const double secOffSet = 0.000001; - const unsigned long usecOffSet = 1000000; - FILETIME fileTime; - GetSystemTimeAsFileTime(&fileTime); - unsigned __int64 present = 0; - present |= fileTime.dwHighDateTime; - present = present << 32; - present |= fileTime.dwLowDateTime; - present /= 10; // mic-sec - // Subtract the difference - present -= delta_; - tv->tv_sec = static_cast(present * secOffSet); - tv->tv_usec = static_cast(present % usecOffSet); - } -#else - ::gettimeofday(tv, nullptr); -#endif // ELPP_OS_WINDOWS -} - -std::string DateTime::getDateTime(const char* format, const base::SubsecondPrecision* ssPrec) { - struct timeval currTime; - gettimeofday(&currTime); - return timevalToString(currTime, format, ssPrec); -} - -std::string DateTime::timevalToString(struct timeval tval, const char* format, - const el::base::SubsecondPrecision* ssPrec) { - struct ::tm timeInfo; - buildTimeInfo(&tval, &timeInfo); - const int kBuffSize = 30; - char buff_[kBuffSize] = ""; - parseFormat(buff_, kBuffSize, format, &timeInfo, static_cast(tval.tv_usec / ssPrec->m_offset), - ssPrec); - return std::string(buff_); -} - -base::type::string_t DateTime::formatTime(unsigned long long time, base::TimestampUnit timestampUnit) { - base::type::EnumType start = static_cast(timestampUnit); - const base::type::char_t* unit = base::consts::kTimeFormats[start].unit; - for (base::type::EnumType i = start; i < base::consts::kTimeFormatsCount - 1; ++i) { - if (time <= base::consts::kTimeFormats[i].value) { - break; - } - if (base::consts::kTimeFormats[i].value == 1000.0f && time / 1000.0f < 1.9f) { - break; - } - time /= static_cast(base::consts::kTimeFormats[i].value); - unit = base::consts::kTimeFormats[i + 1].unit; - } - base::type::stringstream_t ss; - ss << time << " " << unit; - return ss.str(); -} - -unsigned long long DateTime::getTimeDifference(const struct timeval& endTime, const struct timeval& startTime, - base::TimestampUnit timestampUnit) { - if (timestampUnit == base::TimestampUnit::Microsecond) { - return static_cast(static_cast(1000000 * endTime.tv_sec + endTime.tv_usec) - - static_cast(1000000 * startTime.tv_sec + startTime.tv_usec)); - } - // milliseconds - auto conv = [](const struct timeval& tim) { - return static_cast((tim.tv_sec * 1000) + (tim.tv_usec / 1000)); - }; - return static_cast(conv(endTime) - conv(startTime)); -} - -struct ::tm* DateTime::buildTimeInfo(struct timeval* currTime, struct ::tm* timeInfo) { -#if ELPP_OS_UNIX - time_t rawTime = currTime->tv_sec; - ::elpptime_r(&rawTime, timeInfo); - return timeInfo; -#else -# if ELPP_COMPILER_MSVC - ELPP_UNUSED(currTime); - time_t t; -# if defined(_USE_32BIT_TIME_T) - _time32(&t); -# else - _time64(&t); -# endif - elpptime_s(timeInfo, &t); - return timeInfo; -# else - // For any other compilers that don't have CRT warnings issue e.g, MinGW or TDM GCC- we use different method - time_t rawTime = currTime->tv_sec; - struct tm* tmInf = elpptime(&rawTime); - *timeInfo = *tmInf; - return timeInfo; -# endif // ELPP_COMPILER_MSVC -#endif // ELPP_OS_UNIX -} - -char* DateTime::parseFormat(char* buf, std::size_t bufSz, const char* format, const struct tm* tInfo, - std::size_t msec, const base::SubsecondPrecision* ssPrec) { - const char* bufLim = buf + bufSz; - for (; *format; ++format) { - if (*format == base::consts::kFormatSpecifierChar) { - switch (*++format) { - case base::consts::kFormatSpecifierChar: // Escape - break; - case '\0': // End - --format; - break; - case 'd': // Day - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_mday, 2, buf, bufLim); - continue; - case 'a': // Day of week (short) - buf = base::utils::Str::addToBuff(base::consts::kDaysAbbrev[tInfo->tm_wday], buf, bufLim); - continue; - case 'A': // Day of week (long) - buf = base::utils::Str::addToBuff(base::consts::kDays[tInfo->tm_wday], buf, bufLim); - continue; - case 'M': // month - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_mon + 1, 2, buf, bufLim); - continue; - case 'b': // month (short) - buf = base::utils::Str::addToBuff(base::consts::kMonthsAbbrev[tInfo->tm_mon], buf, bufLim); - continue; - case 'B': // month (long) - buf = base::utils::Str::addToBuff(base::consts::kMonths[tInfo->tm_mon], buf, bufLim); - continue; - case 'y': // year (two digits) - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_year + base::consts::kYearBase, 2, buf, bufLim); - continue; - case 'Y': // year (four digits) - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_year + base::consts::kYearBase, 4, buf, bufLim); - continue; - case 'h': // hour (12-hour) - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_hour % 12, 2, buf, bufLim); - continue; - case 'H': // hour (24-hour) - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_hour, 2, buf, bufLim); - continue; - case 'm': // minute - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_min, 2, buf, bufLim); - continue; - case 's': // second - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_sec, 2, buf, bufLim); - continue; - case 'z': // subsecond part - case 'g': - buf = base::utils::Str::convertAndAddToBuff(msec, ssPrec->m_width, buf, bufLim); - continue; - case 'F': // AM/PM - buf = base::utils::Str::addToBuff((tInfo->tm_hour >= 12) ? base::consts::kPm : base::consts::kAm, buf, bufLim); - continue; - default: - continue; - } - } - if (buf == bufLim) break; - *buf++ = *format; - } - return buf; -} - -// CommandLineArgs - -void CommandLineArgs::setArgs(int argc, char** argv) { - m_params.clear(); - m_paramsWithValue.clear(); - if (argc == 0 || argv == nullptr) { - return; - } - m_argc = argc; - m_argv = argv; - for (int i = 1; i < m_argc; ++i) { - const char* v = (strstr(m_argv[i], "=")); - if (v != nullptr && strlen(v) > 0) { - std::string key = std::string(m_argv[i]); - key = key.substr(0, key.find_first_of('=')); - if (hasParamWithValue(key.c_str())) { - ELPP_INTERNAL_INFO(1, "Skipping [" << key << "] arg since it already has value [" - << getParamValue(key.c_str()) << "]"); - } else { - m_paramsWithValue.insert(std::make_pair(key, std::string(v + 1))); - } - } - if (v == nullptr) { - if (hasParam(m_argv[i])) { - ELPP_INTERNAL_INFO(1, "Skipping [" << m_argv[i] << "] arg since it already exists"); - } else { - m_params.push_back(std::string(m_argv[i])); - } - } - } -} - -bool CommandLineArgs::hasParamWithValue(const char* paramKey) const { - return m_paramsWithValue.find(std::string(paramKey)) != m_paramsWithValue.end(); -} - -const char* CommandLineArgs::getParamValue(const char* paramKey) const { - std::unordered_map::const_iterator iter = m_paramsWithValue.find(std::string(paramKey)); - return iter != m_paramsWithValue.end() ? iter->second.c_str() : ""; -} - -bool CommandLineArgs::hasParam(const char* paramKey) const { - return std::find(m_params.begin(), m_params.end(), std::string(paramKey)) != m_params.end(); -} - -bool CommandLineArgs::empty(void) const { - return m_params.empty() && m_paramsWithValue.empty(); -} - -std::size_t CommandLineArgs::size(void) const { - return m_params.size() + m_paramsWithValue.size(); -} - -base::type::ostream_t& operator<<(base::type::ostream_t& os, const CommandLineArgs& c) { - for (int i = 1; i < c.m_argc; ++i) { - os << ELPP_LITERAL("[") << c.m_argv[i] << ELPP_LITERAL("]"); - if (i < c.m_argc - 1) { - os << ELPP_LITERAL(" "); - } - } - return os; -} - -} // namespace utils - -// el::base::threading -namespace threading { - -#if ELPP_THREADING_ENABLED -# if ELPP_USE_STD_THREADING -# if ELPP_ASYNC_LOGGING -static void msleep(int ms) { - // Only when async logging enabled - this is because async is strict on compiler -# if defined(ELPP_NO_SLEEP_FOR) - usleep(ms * 1000); -# else - std::this_thread::sleep_for(std::chrono::milliseconds(ms)); -# endif // defined(ELPP_NO_SLEEP_FOR) -} -# endif // ELPP_ASYNC_LOGGING -# endif // !ELPP_USE_STD_THREADING -#endif // ELPP_THREADING_ENABLED - -} // namespace threading - -// el::base - -// SubsecondPrecision - -void SubsecondPrecision::init(int width) { - if (width < 1 || width > 6) { - width = base::consts::kDefaultSubsecondPrecision; - } - m_width = width; - switch (m_width) { - case 3: - m_offset = 1000; - break; - case 4: - m_offset = 100; - break; - case 5: - m_offset = 10; - break; - case 6: - m_offset = 1; - break; - default: - m_offset = 1000; - break; - } -} - -// LogFormat - -LogFormat::LogFormat(void) : - m_level(Level::Unknown), - m_userFormat(base::type::string_t()), - m_format(base::type::string_t()), - m_dateTimeFormat(std::string()), - m_flags(0x0), - m_currentUser(base::utils::OS::currentUser()), - m_currentHost(base::utils::OS::currentHost()) { -} - -LogFormat::LogFormat(Level level, const base::type::string_t& format) - : m_level(level), m_userFormat(format), m_currentUser(base::utils::OS::currentUser()), - m_currentHost(base::utils::OS::currentHost()) { - parseFromFormat(m_userFormat); -} - -LogFormat::LogFormat(const LogFormat& logFormat): - m_level(logFormat.m_level), - m_userFormat(logFormat.m_userFormat), - m_format(logFormat.m_format), - m_dateTimeFormat(logFormat.m_dateTimeFormat), - m_flags(logFormat.m_flags), - m_currentUser(logFormat.m_currentUser), - m_currentHost(logFormat.m_currentHost) { -} - -LogFormat::LogFormat(LogFormat&& logFormat) { - m_level = std::move(logFormat.m_level); - m_userFormat = std::move(logFormat.m_userFormat); - m_format = std::move(logFormat.m_format); - m_dateTimeFormat = std::move(logFormat.m_dateTimeFormat); - m_flags = std::move(logFormat.m_flags); - m_currentUser = std::move(logFormat.m_currentUser); - m_currentHost = std::move(logFormat.m_currentHost); -} - -LogFormat& LogFormat::operator=(const LogFormat& logFormat) { - if (&logFormat != this) { - m_level = logFormat.m_level; - m_userFormat = logFormat.m_userFormat; - m_dateTimeFormat = logFormat.m_dateTimeFormat; - m_flags = logFormat.m_flags; - m_currentUser = logFormat.m_currentUser; - m_currentHost = logFormat.m_currentHost; - } - return *this; -} - -bool LogFormat::operator==(const LogFormat& other) { - return m_level == other.m_level && m_userFormat == other.m_userFormat && m_format == other.m_format && - m_dateTimeFormat == other.m_dateTimeFormat && m_flags == other.m_flags; -} - -/// @brief Updates format to be used while logging. -/// @param userFormat User provided format -void LogFormat::parseFromFormat(const base::type::string_t& userFormat) { - // We make copy because we will be changing the format - // i.e, removing user provided date format from original format - // and then storing it. - base::type::string_t formatCopy = userFormat; - m_flags = 0x0; - auto conditionalAddFlag = [&](const base::type::char_t* specifier, base::FormatFlags flag) { - std::size_t foundAt = base::type::string_t::npos; - while ((foundAt = formatCopy.find(specifier, foundAt + 1)) != base::type::string_t::npos) { - if (foundAt > 0 && formatCopy[foundAt - 1] == base::consts::kFormatSpecifierChar) { - if (hasFlag(flag)) { - // If we already have flag we remove the escape chars so that '%%' is turned to '%' - // even after specifier resolution - this is because we only replaceFirst specifier - formatCopy.erase(foundAt - 1, 1); - ++foundAt; - } - } else { - if (!hasFlag(flag)) addFlag(flag); - } - } - }; - conditionalAddFlag(base::consts::kAppNameFormatSpecifier, base::FormatFlags::AppName); - conditionalAddFlag(base::consts::kSeverityLevelFormatSpecifier, base::FormatFlags::Level); - conditionalAddFlag(base::consts::kSeverityLevelShortFormatSpecifier, base::FormatFlags::LevelShort); - conditionalAddFlag(base::consts::kLoggerIdFormatSpecifier, base::FormatFlags::LoggerId); - conditionalAddFlag(base::consts::kThreadIdFormatSpecifier, base::FormatFlags::ThreadId); - conditionalAddFlag(base::consts::kLogFileFormatSpecifier, base::FormatFlags::File); - conditionalAddFlag(base::consts::kLogFileBaseFormatSpecifier, base::FormatFlags::FileBase); - conditionalAddFlag(base::consts::kLogLineFormatSpecifier, base::FormatFlags::Line); - conditionalAddFlag(base::consts::kLogLocationFormatSpecifier, base::FormatFlags::Location); - conditionalAddFlag(base::consts::kLogFunctionFormatSpecifier, base::FormatFlags::Function); - conditionalAddFlag(base::consts::kCurrentUserFormatSpecifier, base::FormatFlags::User); - conditionalAddFlag(base::consts::kCurrentHostFormatSpecifier, base::FormatFlags::Host); - conditionalAddFlag(base::consts::kMessageFormatSpecifier, base::FormatFlags::LogMessage); - conditionalAddFlag(base::consts::kVerboseLevelFormatSpecifier, base::FormatFlags::VerboseLevel); - // For date/time we need to extract user's date format first - std::size_t dateIndex = std::string::npos; - if ((dateIndex = formatCopy.find(base::consts::kDateTimeFormatSpecifier)) != std::string::npos) { - while (dateIndex > 0 && formatCopy[dateIndex - 1] == base::consts::kFormatSpecifierChar) { - dateIndex = formatCopy.find(base::consts::kDateTimeFormatSpecifier, dateIndex + 1); - } - if (dateIndex != std::string::npos) { - addFlag(base::FormatFlags::DateTime); - updateDateFormat(dateIndex, formatCopy); - } - } - m_format = formatCopy; - updateFormatSpec(); -} - -void LogFormat::updateDateFormat(std::size_t index, base::type::string_t& currFormat) { - if (hasFlag(base::FormatFlags::DateTime)) { - index += ELPP_STRLEN(base::consts::kDateTimeFormatSpecifier); - } - const base::type::char_t* ptr = currFormat.c_str() + index; - if ((currFormat.size() > index) && (ptr[0] == '{')) { - // User has provided format for date/time - ++ptr; - int count = 1; // Start by 1 in order to remove starting brace - std::stringstream ss; - for (; *ptr; ++ptr, ++count) { - if (*ptr == '}') { - ++count; // In order to remove ending brace - break; - } - ss << static_cast(*ptr); - } - currFormat.erase(index, count); - m_dateTimeFormat = ss.str(); - } else { - // No format provided, use default - if (hasFlag(base::FormatFlags::DateTime)) { - m_dateTimeFormat = std::string(base::consts::kDefaultDateTimeFormat); - } - } -} - -void LogFormat::updateFormatSpec(void) { - // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet. - if (m_level == Level::Debug) { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kDebugLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kDebugLevelShortLogValue); - } else if (m_level == Level::Info) { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kInfoLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kInfoLevelShortLogValue); - } else if (m_level == Level::Warning) { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kWarningLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kWarningLevelShortLogValue); - } else if (m_level == Level::Error) { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kErrorLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kErrorLevelShortLogValue); - } else if (m_level == Level::Fatal) { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kFatalLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kFatalLevelShortLogValue); - } else if (m_level == Level::Verbose) { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kVerboseLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kVerboseLevelShortLogValue); - } else if (m_level == Level::Trace) { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kTraceLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kTraceLevelShortLogValue); - } - if (hasFlag(base::FormatFlags::User)) { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kCurrentUserFormatSpecifier, - m_currentUser); - } - if (hasFlag(base::FormatFlags::Host)) { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kCurrentHostFormatSpecifier, - m_currentHost); - } - // Ignore Level::Global and Level::Unknown -} - -// TypedConfigurations - -TypedConfigurations::TypedConfigurations(Configurations* configurations, - base::LogStreamsReferenceMap* logStreamsReference) { - m_configurations = configurations; - m_logStreamsReference = logStreamsReference; - build(m_configurations); -} - -TypedConfigurations::TypedConfigurations(const TypedConfigurations& other) { - this->m_configurations = other.m_configurations; - this->m_logStreamsReference = other.m_logStreamsReference; - build(m_configurations); -} - -bool TypedConfigurations::enabled(Level level) { - return getConfigByVal(level, &m_enabledMap, "enabled"); -} - -bool TypedConfigurations::toFile(Level level) { - return getConfigByVal(level, &m_toFileMap, "toFile"); -} - -const std::string& TypedConfigurations::filename(Level level) { - return getConfigByRef(level, &m_filenameMap, "filename"); -} - -bool TypedConfigurations::toStandardOutput(Level level) { - return getConfigByVal(level, &m_toStandardOutputMap, "toStandardOutput"); -} - -const base::LogFormat& TypedConfigurations::logFormat(Level level) { - return getConfigByRef(level, &m_logFormatMap, "logFormat"); -} - -const base::SubsecondPrecision& TypedConfigurations::subsecondPrecision(Level level) { - return getConfigByRef(level, &m_subsecondPrecisionMap, "subsecondPrecision"); -} - -const base::MillisecondsWidth& TypedConfigurations::millisecondsWidth(Level level) { - return getConfigByRef(level, &m_subsecondPrecisionMap, "millisecondsWidth"); -} - -bool TypedConfigurations::performanceTracking(Level level) { - return getConfigByVal(level, &m_performanceTrackingMap, "performanceTracking"); -} - -base::type::fstream_t* TypedConfigurations::fileStream(Level level) { - return getConfigByRef(level, &m_fileStreamMap, "fileStream").get(); -} - -std::size_t TypedConfigurations::maxLogFileSize(Level level) { - return getConfigByVal(level, &m_maxLogFileSizeMap, "maxLogFileSize"); -} - -std::size_t TypedConfigurations::logFlushThreshold(Level level) { - return getConfigByVal(level, &m_logFlushThresholdMap, "logFlushThreshold"); -} - -void TypedConfigurations::build(Configurations* configurations) { - base::threading::ScopedLock scopedLock(lock()); - auto getBool = [] (std::string boolStr) -> bool { // Pass by value for trimming - base::utils::Str::trim(boolStr); - return (boolStr == "TRUE" || boolStr == "true" || boolStr == "1"); - }; - std::vector withFileSizeLimit; - for (Configurations::const_iterator it = configurations->begin(); it != configurations->end(); ++it) { - Configuration* conf = *it; - // We cannot use switch on strong enums because Intel C++ dont support them yet - if (conf->configurationType() == ConfigurationType::Enabled) { - setValue(conf->level(), getBool(conf->value()), &m_enabledMap); - } else if (conf->configurationType() == ConfigurationType::ToFile) { - setValue(conf->level(), getBool(conf->value()), &m_toFileMap); - } else if (conf->configurationType() == ConfigurationType::ToStandardOutput) { - setValue(conf->level(), getBool(conf->value()), &m_toStandardOutputMap); - } else if (conf->configurationType() == ConfigurationType::Filename) { - // We do not yet configure filename but we will configure in another - // loop. This is because if file cannot be created, we will force ToFile - // to be false. Because configuring logger is not necessarily performance - // sensative operation, we can live with another loop; (by the way this loop - // is not very heavy either) - } else if (conf->configurationType() == ConfigurationType::Format) { - setValue(conf->level(), base::LogFormat(conf->level(), - base::type::string_t(conf->value().begin(), conf->value().end())), &m_logFormatMap); - } else if (conf->configurationType() == ConfigurationType::SubsecondPrecision) { - setValue(Level::Global, - base::SubsecondPrecision(static_cast(getULong(conf->value()))), &m_subsecondPrecisionMap); - } else if (conf->configurationType() == ConfigurationType::PerformanceTracking) { - setValue(Level::Global, getBool(conf->value()), &m_performanceTrackingMap); - } else if (conf->configurationType() == ConfigurationType::MaxLogFileSize) { - auto v = getULong(conf->value()); - setValue(conf->level(), static_cast(v), &m_maxLogFileSizeMap); - if (v != 0) { - withFileSizeLimit.push_back(conf); - } - } else if (conf->configurationType() == ConfigurationType::LogFlushThreshold) { - setValue(conf->level(), static_cast(getULong(conf->value())), &m_logFlushThresholdMap); - } - } - // As mentioned earlier, we will now set filename configuration in separate loop to deal with non-existent files - for (Configurations::const_iterator it = configurations->begin(); it != configurations->end(); ++it) { - Configuration* conf = *it; - if (conf->configurationType() == ConfigurationType::Filename) { - insertFile(conf->level(), conf->value()); - } - } - for (std::vector::iterator conf = withFileSizeLimit.begin(); - conf != withFileSizeLimit.end(); ++conf) { - // This is not unsafe as mutex is locked in currect scope - unsafeValidateFileRolling((*conf)->level(), base::defaultPreRollOutCallback); - } -} - -unsigned long TypedConfigurations::getULong(std::string confVal) { - bool valid = true; - base::utils::Str::trim(confVal); - valid = !confVal.empty() && std::find_if(confVal.begin(), confVal.end(), - [](char c) { - return !base::utils::Str::isDigit(c); - }) == confVal.end(); - if (!valid) { - valid = false; - ELPP_ASSERT(valid, "Configuration value not a valid integer [" << confVal << "]"); - return 0; - } - return atol(confVal.c_str()); -} - -std::string TypedConfigurations::resolveFilename(const std::string& filename) { - std::string resultingFilename = filename; - std::size_t dateIndex = std::string::npos; - std::string dateTimeFormatSpecifierStr = std::string(base::consts::kDateTimeFormatSpecifierForFilename); - if ((dateIndex = resultingFilename.find(dateTimeFormatSpecifierStr.c_str())) != std::string::npos) { - while (dateIndex > 0 && resultingFilename[dateIndex - 1] == base::consts::kFormatSpecifierChar) { - dateIndex = resultingFilename.find(dateTimeFormatSpecifierStr.c_str(), dateIndex + 1); - } - if (dateIndex != std::string::npos) { - const char* ptr = resultingFilename.c_str() + dateIndex; - // Goto end of specifier - ptr += dateTimeFormatSpecifierStr.size(); - std::string fmt; - if ((resultingFilename.size() > dateIndex) && (ptr[0] == '{')) { - // User has provided format for date/time - ++ptr; - int count = 1; // Start by 1 in order to remove starting brace - std::stringstream ss; - for (; *ptr; ++ptr, ++count) { - if (*ptr == '}') { - ++count; // In order to remove ending brace - break; - } - ss << *ptr; - } - resultingFilename.erase(dateIndex + dateTimeFormatSpecifierStr.size(), count); - fmt = ss.str(); - } else { - fmt = std::string(base::consts::kDefaultDateTimeFormatInFilename); - } - base::SubsecondPrecision ssPrec(3); - std::string now = base::utils::DateTime::getDateTime(fmt.c_str(), &ssPrec); - base::utils::Str::replaceAll(now, '/', '-'); // Replace path element since we are dealing with filename - base::utils::Str::replaceAll(resultingFilename, dateTimeFormatSpecifierStr, now); - } - } - return resultingFilename; -} - -void TypedConfigurations::insertFile(Level level, const std::string& fullFilename) { - std::string resolvedFilename = resolveFilename(fullFilename); - if (resolvedFilename.empty()) { - std::cerr << "Could not load empty file for logging, please re-check your configurations for level [" - << LevelHelper::convertToString(level) << "]"; - } - std::string filePath = base::utils::File::extractPathFromFilename(resolvedFilename, base::consts::kFilePathSeperator); - if (filePath.size() < resolvedFilename.size()) { - base::utils::File::createPath(filePath); - } - auto create = [&](Level level) { - base::LogStreamsReferenceMap::iterator filestreamIter = m_logStreamsReference->find(resolvedFilename); - base::type::fstream_t* fs = nullptr; - if (filestreamIter == m_logStreamsReference->end()) { - // We need a completely new stream, nothing to share with - fs = base::utils::File::newFileStream(resolvedFilename); - m_filenameMap.insert(std::make_pair(level, resolvedFilename)); - m_fileStreamMap.insert(std::make_pair(level, base::FileStreamPtr(fs))); - m_logStreamsReference->insert(std::make_pair(resolvedFilename, base::FileStreamPtr(m_fileStreamMap.at(level)))); - } else { - // Woops! we have an existing one, share it! - m_filenameMap.insert(std::make_pair(level, filestreamIter->first)); - m_fileStreamMap.insert(std::make_pair(level, base::FileStreamPtr(filestreamIter->second))); - fs = filestreamIter->second.get(); - } - if (fs == nullptr) { - // We display bad file error from newFileStream() - ELPP_INTERNAL_ERROR("Setting [TO_FILE] of [" - << LevelHelper::convertToString(level) << "] to FALSE", false); - setValue(level, false, &m_toFileMap); - } - }; - // If we dont have file conf for any level, create it for Level::Global first - // otherwise create for specified level - create(m_filenameMap.empty() && m_fileStreamMap.empty() ? Level::Global : level); -} - -bool TypedConfigurations::unsafeValidateFileRolling(Level level, const PreRollOutCallback& preRollOutCallback) { - base::type::fstream_t* fs = unsafeGetConfigByRef(level, &m_fileStreamMap, "fileStream").get(); - if (fs == nullptr) { - return true; - } - std::size_t maxLogFileSize = unsafeGetConfigByVal(level, &m_maxLogFileSizeMap, "maxLogFileSize"); - std::size_t currFileSize = base::utils::File::getSizeOfFile(fs); - if (maxLogFileSize != 0 && currFileSize >= maxLogFileSize) { - std::string fname = unsafeGetConfigByRef(level, &m_filenameMap, "filename"); - ELPP_INTERNAL_INFO(1, "Truncating log file [" << fname << "] as a result of configurations for level [" - << LevelHelper::convertToString(level) << "]"); - fs->close(); - preRollOutCallback(fname.c_str(), currFileSize); - fs->open(fname, std::fstream::out | std::fstream::trunc); - return true; - } - return false; -} - -// RegisteredHitCounters - -bool RegisteredHitCounters::validateEveryN(const char* filename, base::type::LineNumber lineNumber, std::size_t n) { - base::threading::ScopedLock scopedLock(lock()); - base::HitCounter* counter = get(filename, lineNumber); - if (counter == nullptr) { - registerNew(counter = new base::HitCounter(filename, lineNumber)); - } - counter->validateHitCounts(n); - bool result = (n >= 1 && counter->hitCounts() != 0 && counter->hitCounts() % n == 0); - return result; -} - -/// @brief Validates counter for hits >= N, i.e, registers new if does not exist otherwise updates original one -/// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned -bool RegisteredHitCounters::validateAfterN(const char* filename, base::type::LineNumber lineNumber, std::size_t n) { - base::threading::ScopedLock scopedLock(lock()); - base::HitCounter* counter = get(filename, lineNumber); - if (counter == nullptr) { - registerNew(counter = new base::HitCounter(filename, lineNumber)); - } - // Do not use validateHitCounts here since we do not want to reset counter here - // Note the >= instead of > because we are incrementing - // after this check - if (counter->hitCounts() >= n) - return true; - counter->increment(); - return false; -} - -/// @brief Validates counter for hits are <= n, i.e, registers new if does not exist otherwise updates original one -/// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned -bool RegisteredHitCounters::validateNTimes(const char* filename, base::type::LineNumber lineNumber, std::size_t n) { - base::threading::ScopedLock scopedLock(lock()); - base::HitCounter* counter = get(filename, lineNumber); - if (counter == nullptr) { - registerNew(counter = new base::HitCounter(filename, lineNumber)); - } - counter->increment(); - // Do not use validateHitCounts here since we do not want to reset counter here - if (counter->hitCounts() <= n) - return true; - return false; -} - -// RegisteredLoggers - -RegisteredLoggers::RegisteredLoggers(const LogBuilderPtr& defaultLogBuilder) : - m_defaultLogBuilder(defaultLogBuilder) { - m_defaultConfigurations.setToDefault(); -} - -Logger* RegisteredLoggers::get(const std::string& id, bool forceCreation) { - base::threading::ScopedLock scopedLock(lock()); - Logger* logger_ = base::utils::Registry::get(id); - if (logger_ == nullptr && forceCreation) { - bool validId = Logger::isValidId(id); - if (!validId) { - ELPP_ASSERT(validId, "Invalid logger ID [" << id << "]. Not registering this logger."); - return nullptr; - } - logger_ = new Logger(id, m_defaultConfigurations, &m_logStreamsReference); - logger_->m_logBuilder = m_defaultLogBuilder; - registerNew(id, logger_); - LoggerRegistrationCallback* callback = nullptr; - for (const std::pair& h - : m_loggerRegistrationCallbacks) { - callback = h.second.get(); - if (callback != nullptr && callback->enabled()) { - callback->handle(logger_); - } - } - } - return logger_; -} - -bool RegisteredLoggers::remove(const std::string& id) { - if (id == base::consts::kDefaultLoggerId) { - return false; - } - // get has internal lock - Logger* logger = base::utils::Registry::get(id); - if (logger != nullptr) { - // unregister has internal lock - unregister(logger); - } - return true; -} - -void RegisteredLoggers::unsafeFlushAll(void) { - ELPP_INTERNAL_INFO(1, "Flushing all log files"); - for (base::LogStreamsReferenceMap::iterator it = m_logStreamsReference.begin(); - it != m_logStreamsReference.end(); ++it) { - if (it->second.get() == nullptr) continue; - it->second->flush(); - } -} - -// VRegistry - -VRegistry::VRegistry(base::type::VerboseLevel level, base::type::EnumType* pFlags) : m_level(level), m_pFlags(pFlags) { -} - -/// @brief Sets verbose level. Accepted range is 0-9 -void VRegistry::setLevel(base::type::VerboseLevel level) { - base::threading::ScopedLock scopedLock(lock()); - if (level > 9) - m_level = base::consts::kMaxVerboseLevel; - else - m_level = level; -} - -void VRegistry::setModules(const char* modules) { - base::threading::ScopedLock scopedLock(lock()); - auto addSuffix = [](std::stringstream& ss, const char* sfx, const char* prev) { - if (prev != nullptr && base::utils::Str::endsWith(ss.str(), std::string(prev))) { - std::string chr(ss.str().substr(0, ss.str().size() - strlen(prev))); - ss.str(std::string("")); - ss << chr; - } - if (base::utils::Str::endsWith(ss.str(), std::string(sfx))) { - std::string chr(ss.str().substr(0, ss.str().size() - strlen(sfx))); - ss.str(std::string("")); - ss << chr; - } - ss << sfx; - }; - auto insert = [&](std::stringstream& ss, base::type::VerboseLevel level) { - if (!base::utils::hasFlag(LoggingFlag::DisableVModulesExtensions, *m_pFlags)) { - addSuffix(ss, ".h", nullptr); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".c", ".h"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".cpp", ".c"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".cc", ".cpp"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".cxx", ".cc"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".-inl.h", ".cxx"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".hxx", ".-inl.h"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".hpp", ".hxx"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".hh", ".hpp"); - } - m_modules.insert(std::make_pair(ss.str(), level)); - }; - bool isMod = true; - bool isLevel = false; - std::stringstream ss; - int level = -1; - for (; *modules; ++modules) { - switch (*modules) { - case '=': - isLevel = true; - isMod = false; - break; - case ',': - isLevel = false; - isMod = true; - if (!ss.str().empty() && level != -1) { - insert(ss, static_cast(level)); - ss.str(std::string("")); - level = -1; - } - break; - default: - if (isMod) { - ss << *modules; - } else if (isLevel) { - if (isdigit(*modules)) { - level = static_cast(*modules) - 48; - } - } - break; - } - } - if (!ss.str().empty() && level != -1) { - insert(ss, static_cast(level)); - } -} - -bool VRegistry::allowed(base::type::VerboseLevel vlevel, const char* file) { - base::threading::ScopedLock scopedLock(lock()); - if (m_modules.empty() || file == nullptr) { - return vlevel <= m_level; - } else { - char baseFilename[base::consts::kSourceFilenameMaxLength] = ""; - base::utils::File::buildBaseFilename(file, baseFilename); - std::unordered_map::iterator it = m_modules.begin(); - for (; it != m_modules.end(); ++it) { - if (base::utils::Str::wildCardMatch(baseFilename, it->first.c_str())) { - return vlevel <= it->second; - } - } - if (base::utils::hasFlag(LoggingFlag::AllowVerboseIfModuleNotSpecified, *m_pFlags)) { - return true; - } - return false; - } -} - -void VRegistry::setFromArgs(const base::utils::CommandLineArgs* commandLineArgs) { - if (commandLineArgs->hasParam("-v") || commandLineArgs->hasParam("--verbose") || - commandLineArgs->hasParam("-V") || commandLineArgs->hasParam("--VERBOSE")) { - setLevel(base::consts::kMaxVerboseLevel); - } else if (commandLineArgs->hasParamWithValue("--v")) { - setLevel(static_cast(atoi(commandLineArgs->getParamValue("--v")))); - } else if (commandLineArgs->hasParamWithValue("--V")) { - setLevel(static_cast(atoi(commandLineArgs->getParamValue("--V")))); - } else if ((commandLineArgs->hasParamWithValue("-vmodule")) && vModulesEnabled()) { - setModules(commandLineArgs->getParamValue("-vmodule")); - } else if (commandLineArgs->hasParamWithValue("-VMODULE") && vModulesEnabled()) { - setModules(commandLineArgs->getParamValue("-VMODULE")); - } -} - -#if !defined(ELPP_DEFAULT_LOGGING_FLAGS) -# define ELPP_DEFAULT_LOGGING_FLAGS 0x0 -#endif // !defined(ELPP_DEFAULT_LOGGING_FLAGS) -// Storage -#if ELPP_ASYNC_LOGGING -Storage::Storage(const LogBuilderPtr& defaultLogBuilder, base::IWorker* asyncDispatchWorker) : -#else -Storage::Storage(const LogBuilderPtr& defaultLogBuilder) : -#endif // ELPP_ASYNC_LOGGING - m_registeredHitCounters(new base::RegisteredHitCounters()), - m_registeredLoggers(new base::RegisteredLoggers(defaultLogBuilder)), - m_flags(ELPP_DEFAULT_LOGGING_FLAGS), - m_vRegistry(new base::VRegistry(0, &m_flags)), - -#if ELPP_ASYNC_LOGGING - m_asyncLogQueue(new base::AsyncLogQueue()), - m_asyncDispatchWorker(asyncDispatchWorker), -#endif // ELPP_ASYNC_LOGGING - - m_preRollOutCallback(base::defaultPreRollOutCallback) { - // Register default logger - m_registeredLoggers->get(std::string(base::consts::kDefaultLoggerId)); - // We register default logger anyway (worse case it's not going to register) just in case - m_registeredLoggers->get("default"); - -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) - // Register performance logger and reconfigure format - Logger* performanceLogger = m_registeredLoggers->get(std::string(base::consts::kPerformanceLoggerId)); - m_registeredLoggers->get("performance"); - performanceLogger->configurations()->setGlobally(ConfigurationType::Format, std::string("%datetime %level %msg")); - performanceLogger->reconfigure(); -#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) - -#if defined(ELPP_SYSLOG) - // Register syslog logger and reconfigure format - Logger* sysLogLogger = m_registeredLoggers->get(std::string(base::consts::kSysLogLoggerId)); - sysLogLogger->configurations()->setGlobally(ConfigurationType::Format, std::string("%level: %msg")); - sysLogLogger->reconfigure(); -#endif // defined(ELPP_SYSLOG) - addFlag(LoggingFlag::AllowVerboseIfModuleNotSpecified); -#if ELPP_ASYNC_LOGGING - installLogDispatchCallback(std::string("AsyncLogDispatchCallback")); -#else - installLogDispatchCallback(std::string("DefaultLogDispatchCallback")); -#endif // ELPP_ASYNC_LOGGING -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) - installPerformanceTrackingCallback - (std::string("DefaultPerformanceTrackingCallback")); -#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) - ELPP_INTERNAL_INFO(1, "Easylogging++ has been initialized"); -#if ELPP_ASYNC_LOGGING - m_asyncDispatchWorker->start(); -#endif // ELPP_ASYNC_LOGGING -} - -Storage::~Storage(void) { - ELPP_INTERNAL_INFO(4, "Destroying storage"); -#if ELPP_ASYNC_LOGGING - ELPP_INTERNAL_INFO(5, "Replacing log dispatch callback to synchronous"); - uninstallLogDispatchCallback(std::string("AsyncLogDispatchCallback")); - installLogDispatchCallback(std::string("DefaultLogDispatchCallback")); - ELPP_INTERNAL_INFO(5, "Destroying asyncDispatchWorker"); - base::utils::safeDelete(m_asyncDispatchWorker); - ELPP_INTERNAL_INFO(5, "Destroying asyncLogQueue"); - base::utils::safeDelete(m_asyncLogQueue); -#endif // ELPP_ASYNC_LOGGING - ELPP_INTERNAL_INFO(5, "Destroying registeredHitCounters"); - base::utils::safeDelete(m_registeredHitCounters); - ELPP_INTERNAL_INFO(5, "Destroying registeredLoggers"); - base::utils::safeDelete(m_registeredLoggers); - ELPP_INTERNAL_INFO(5, "Destroying vRegistry"); - base::utils::safeDelete(m_vRegistry); -} - -bool Storage::hasCustomFormatSpecifier(const char* formatSpecifier) { - base::threading::ScopedLock scopedLock(customFormatSpecifiersLock()); - return std::find(m_customFormatSpecifiers.begin(), m_customFormatSpecifiers.end(), - formatSpecifier) != m_customFormatSpecifiers.end(); -} - -void Storage::installCustomFormatSpecifier(const CustomFormatSpecifier& customFormatSpecifier) { - if (hasCustomFormatSpecifier(customFormatSpecifier.formatSpecifier())) { - return; - } - base::threading::ScopedLock scopedLock(customFormatSpecifiersLock()); - m_customFormatSpecifiers.push_back(customFormatSpecifier); -} - -bool Storage::uninstallCustomFormatSpecifier(const char* formatSpecifier) { - base::threading::ScopedLock scopedLock(customFormatSpecifiersLock()); - std::vector::iterator it = std::find(m_customFormatSpecifiers.begin(), - m_customFormatSpecifiers.end(), formatSpecifier); - if (it != m_customFormatSpecifiers.end() && strcmp(formatSpecifier, it->formatSpecifier()) == 0) { - m_customFormatSpecifiers.erase(it); - return true; - } - return false; -} - -void Storage::setApplicationArguments(int argc, char** argv) { - m_commandLineArgs.setArgs(argc, argv); - m_vRegistry->setFromArgs(commandLineArgs()); - // default log file -#if !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) - if (m_commandLineArgs.hasParamWithValue(base::consts::kDefaultLogFileParam)) { - Configurations c; - c.setGlobally(ConfigurationType::Filename, - std::string(m_commandLineArgs.getParamValue(base::consts::kDefaultLogFileParam))); - registeredLoggers()->setDefaultConfigurations(c); - for (base::RegisteredLoggers::iterator it = registeredLoggers()->begin(); - it != registeredLoggers()->end(); ++it) { - it->second->configure(c); - } - } -#endif // !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) -#if defined(ELPP_LOGGING_FLAGS_FROM_ARG) - if (m_commandLineArgs.hasParamWithValue(base::consts::kLoggingFlagsParam)) { - int userInput = atoi(m_commandLineArgs.getParamValue(base::consts::kLoggingFlagsParam)); - if (ELPP_DEFAULT_LOGGING_FLAGS == 0x0) { - m_flags = userInput; - } else { - base::utils::addFlag(userInput, &m_flags); - } - } -#endif // defined(ELPP_LOGGING_FLAGS_FROM_ARG) -} - -} // namespace base - -// LogDispatchCallback -void LogDispatchCallback::handle(const LogDispatchData* data) { -#if defined(ELPP_THREAD_SAFE) - base::threading::ScopedLock scopedLock(m_fileLocksMapLock); - std::string filename = data->logMessage()->logger()->typedConfigurations()->filename(data->logMessage()->level()); - auto lock = m_fileLocks.find(filename); - if (lock == m_fileLocks.end()) { - m_fileLocks.emplace(std::make_pair(filename, std::unique_ptr(new base::threading::Mutex))); - } -#endif -} - -base::threading::Mutex& LogDispatchCallback::fileHandle(const LogDispatchData* data) { - auto it = m_fileLocks.find(data->logMessage()->logger()->typedConfigurations()->filename(data->logMessage()->level())); - return *(it->second.get()); -} - -namespace base { -// DefaultLogDispatchCallback - -void DefaultLogDispatchCallback::handle(const LogDispatchData* data) { -#if defined(ELPP_THREAD_SAFE) - LogDispatchCallback::handle(data); - base::threading::ScopedLock scopedLock(fileHandle(data)); -#endif - m_data = data; - dispatch(m_data->logMessage()->logger()->logBuilder()->build(m_data->logMessage(), - m_data->dispatchAction() == base::DispatchAction::NormalLog)); -} - -void DefaultLogDispatchCallback::dispatch(base::type::string_t&& logLine) { - if (m_data->dispatchAction() == base::DispatchAction::NormalLog) { - if (m_data->logMessage()->logger()->m_typedConfigurations->toFile(m_data->logMessage()->level())) { - base::type::fstream_t* fs = m_data->logMessage()->logger()->m_typedConfigurations->fileStream( - m_data->logMessage()->level()); - if (fs != nullptr) { - fs->write(logLine.c_str(), logLine.size()); - if (fs->fail()) { - ELPP_INTERNAL_ERROR("Unable to write log to file [" - << m_data->logMessage()->logger()->m_typedConfigurations->filename(m_data->logMessage()->level()) << "].\n" - << "Few possible reasons (could be something else):\n" << " * Permission denied\n" - << " * Disk full\n" << " * Disk is not writable", true); - } else { - if (ELPP->hasFlag(LoggingFlag::ImmediateFlush) - || (m_data->logMessage()->logger()->isFlushNeeded(m_data->logMessage()->level()))) { - m_data->logMessage()->logger()->flush(m_data->logMessage()->level(), fs); - } - } - } else { - ELPP_INTERNAL_ERROR("Log file for [" << LevelHelper::convertToString(m_data->logMessage()->level()) << "] " - << "has not been configured but [TO_FILE] is configured to TRUE. [Logger ID: " - << m_data->logMessage()->logger()->id() << "]", false); - } - } - if (m_data->logMessage()->logger()->m_typedConfigurations->toStandardOutput(m_data->logMessage()->level())) { - if (ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput)) - m_data->logMessage()->logger()->logBuilder()->convertToColoredOutput(&logLine, m_data->logMessage()->level()); - ELPP_COUT << ELPP_COUT_LINE(logLine); - } - } -#if defined(ELPP_SYSLOG) - else if (m_data->dispatchAction() == base::DispatchAction::SysLog) { - // Determine syslog priority - int sysLogPriority = 0; - if (m_data->logMessage()->level() == Level::Fatal) - sysLogPriority = LOG_EMERG; - else if (m_data->logMessage()->level() == Level::Error) - sysLogPriority = LOG_ERR; - else if (m_data->logMessage()->level() == Level::Warning) - sysLogPriority = LOG_WARNING; - else if (m_data->logMessage()->level() == Level::Info) - sysLogPriority = LOG_INFO; - else if (m_data->logMessage()->level() == Level::Debug) - sysLogPriority = LOG_DEBUG; - else - sysLogPriority = LOG_NOTICE; -# if defined(ELPP_UNICODE) - char* line = base::utils::Str::wcharPtrToCharPtr(logLine.c_str()); - syslog(sysLogPriority, "%s", line); - free(line); -# else - syslog(sysLogPriority, "%s", logLine.c_str()); -# endif - } -#endif // defined(ELPP_SYSLOG) -} - -#if ELPP_ASYNC_LOGGING - -// AsyncLogDispatchCallback - -void AsyncLogDispatchCallback::handle(const LogDispatchData* data) { - base::type::string_t logLine = data->logMessage()->logger()->logBuilder()->build(data->logMessage(), - data->dispatchAction() == base::DispatchAction::NormalLog); - if (data->dispatchAction() == base::DispatchAction::NormalLog - && data->logMessage()->logger()->typedConfigurations()->toStandardOutput(data->logMessage()->level())) { - if (ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput)) - data->logMessage()->logger()->logBuilder()->convertToColoredOutput(&logLine, data->logMessage()->level()); - ELPP_COUT << ELPP_COUT_LINE(logLine); - } - // Save resources and only queue if we want to write to file otherwise just ignore handler - if (data->logMessage()->logger()->typedConfigurations()->toFile(data->logMessage()->level())) { - ELPP->asyncLogQueue()->push(AsyncLogItem(*(data->logMessage()), *data, logLine)); - } -} - -// AsyncDispatchWorker -AsyncDispatchWorker::AsyncDispatchWorker() { - setContinueRunning(false); -} - -AsyncDispatchWorker::~AsyncDispatchWorker() { - setContinueRunning(false); - ELPP_INTERNAL_INFO(6, "Stopping dispatch worker - Cleaning log queue"); - clean(); - ELPP_INTERNAL_INFO(6, "Log queue cleaned"); -} - -bool AsyncDispatchWorker::clean(void) { - std::mutex m; - std::unique_lock lk(m); - cv.wait(lk, [] { return !ELPP->asyncLogQueue()->empty(); }); - emptyQueue(); - lk.unlock(); - cv.notify_one(); - return ELPP->asyncLogQueue()->empty(); -} - -void AsyncDispatchWorker::emptyQueue(void) { - while (!ELPP->asyncLogQueue()->empty()) { - AsyncLogItem data = ELPP->asyncLogQueue()->next(); - handle(&data); - base::threading::msleep(100); - } -} - -void AsyncDispatchWorker::start(void) { - base::threading::msleep(5000); // 5s (why?) - setContinueRunning(true); - std::thread t1(&AsyncDispatchWorker::run, this); - t1.join(); -} - -void AsyncDispatchWorker::handle(AsyncLogItem* logItem) { - LogDispatchData* data = logItem->data(); - LogMessage* logMessage = logItem->logMessage(); - Logger* logger = logMessage->logger(); - base::TypedConfigurations* conf = logger->typedConfigurations(); - base::type::string_t logLine = logItem->logLine(); - if (data->dispatchAction() == base::DispatchAction::NormalLog) { - if (conf->toFile(logMessage->level())) { - base::type::fstream_t* fs = conf->fileStream(logMessage->level()); - if (fs != nullptr) { - fs->write(logLine.c_str(), logLine.size()); - if (fs->fail()) { - ELPP_INTERNAL_ERROR("Unable to write log to file [" - << conf->filename(logMessage->level()) << "].\n" - << "Few possible reasons (could be something else):\n" << " * Permission denied\n" - << " * Disk full\n" << " * Disk is not writable", true); - } else { - if (ELPP->hasFlag(LoggingFlag::ImmediateFlush) || (logger->isFlushNeeded(logMessage->level()))) { - logger->flush(logMessage->level(), fs); - } - } - } else { - ELPP_INTERNAL_ERROR("Log file for [" << LevelHelper::convertToString(logMessage->level()) << "] " - << "has not been configured but [TO_FILE] is configured to TRUE. [Logger ID: " << logger->id() << "]", false); - } - } - } -# if defined(ELPP_SYSLOG) - else if (data->dispatchAction() == base::DispatchAction::SysLog) { - // Determine syslog priority - int sysLogPriority = 0; - if (logMessage->level() == Level::Fatal) - sysLogPriority = LOG_EMERG; - else if (logMessage->level() == Level::Error) - sysLogPriority = LOG_ERR; - else if (logMessage->level() == Level::Warning) - sysLogPriority = LOG_WARNING; - else if (logMessage->level() == Level::Info) - sysLogPriority = LOG_INFO; - else if (logMessage->level() == Level::Debug) - sysLogPriority = LOG_DEBUG; - else - sysLogPriority = LOG_NOTICE; -# if defined(ELPP_UNICODE) - char* line = base::utils::Str::wcharPtrToCharPtr(logLine.c_str()); - syslog(sysLogPriority, "%s", line); - free(line); -# else - syslog(sysLogPriority, "%s", logLine.c_str()); -# endif - } -# endif // defined(ELPP_SYSLOG) -} - -void AsyncDispatchWorker::run(void) { - while (continueRunning()) { - emptyQueue(); - base::threading::msleep(10); // 10ms - } -} -#endif // ELPP_ASYNC_LOGGING - -// DefaultLogBuilder - -base::type::string_t DefaultLogBuilder::build(const LogMessage* logMessage, bool appendNewLine) const { - base::TypedConfigurations* tc = logMessage->logger()->typedConfigurations(); - const base::LogFormat* logFormat = &tc->logFormat(logMessage->level()); - base::type::string_t logLine = logFormat->format(); - char buff[base::consts::kSourceFilenameMaxLength + base::consts::kSourceLineMaxLength] = ""; - const char* bufLim = buff + sizeof(buff); - if (logFormat->hasFlag(base::FormatFlags::AppName)) { - // App name - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kAppNameFormatSpecifier, - logMessage->logger()->parentApplicationName()); - } - if (logFormat->hasFlag(base::FormatFlags::ThreadId)) { - // Thread ID - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kThreadIdFormatSpecifier, - ELPP->getThreadName(base::threading::getCurrentThreadId())); - } - if (logFormat->hasFlag(base::FormatFlags::DateTime)) { - // DateTime - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kDateTimeFormatSpecifier, - base::utils::DateTime::getDateTime(logFormat->dateTimeFormat().c_str(), - &tc->subsecondPrecision(logMessage->level()))); - } - if (logFormat->hasFlag(base::FormatFlags::Function)) { - // Function - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFunctionFormatSpecifier, logMessage->func()); - } - if (logFormat->hasFlag(base::FormatFlags::File)) { - // File - base::utils::Str::clearBuff(buff, base::consts::kSourceFilenameMaxLength); - base::utils::File::buildStrippedFilename(logMessage->file().c_str(), buff); - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFileFormatSpecifier, std::string(buff)); - } - if (logFormat->hasFlag(base::FormatFlags::FileBase)) { - // FileBase - base::utils::Str::clearBuff(buff, base::consts::kSourceFilenameMaxLength); - base::utils::File::buildBaseFilename(logMessage->file(), buff); - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFileBaseFormatSpecifier, std::string(buff)); - } - if (logFormat->hasFlag(base::FormatFlags::Line)) { - // Line - char* buf = base::utils::Str::clearBuff(buff, base::consts::kSourceLineMaxLength); - buf = base::utils::Str::convertAndAddToBuff(logMessage->line(), base::consts::kSourceLineMaxLength, buf, bufLim, false); - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogLineFormatSpecifier, std::string(buff)); - } - if (logFormat->hasFlag(base::FormatFlags::Location)) { - // Location - char* buf = base::utils::Str::clearBuff(buff, - base::consts::kSourceFilenameMaxLength + base::consts::kSourceLineMaxLength); - base::utils::File::buildStrippedFilename(logMessage->file().c_str(), buff); - buf = base::utils::Str::addToBuff(buff, buf, bufLim); - buf = base::utils::Str::addToBuff(":", buf, bufLim); - buf = base::utils::Str::convertAndAddToBuff(logMessage->line(), base::consts::kSourceLineMaxLength, buf, bufLim, - false); - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogLocationFormatSpecifier, std::string(buff)); - } - if (logMessage->level() == Level::Verbose && logFormat->hasFlag(base::FormatFlags::VerboseLevel)) { - // Verbose level - char* buf = base::utils::Str::clearBuff(buff, 1); - buf = base::utils::Str::convertAndAddToBuff(logMessage->verboseLevel(), 1, buf, bufLim, false); - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kVerboseLevelFormatSpecifier, std::string(buff)); - } - if (logFormat->hasFlag(base::FormatFlags::LogMessage)) { - // Log message - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kMessageFormatSpecifier, logMessage->message()); - } -#if !defined(ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS) - el::base::threading::ScopedLock lock_(ELPP->customFormatSpecifiersLock()); - ELPP_UNUSED(lock_); - for (std::vector::const_iterator it = ELPP->customFormatSpecifiers()->begin(); - it != ELPP->customFormatSpecifiers()->end(); ++it) { - std::string fs(it->formatSpecifier()); - base::type::string_t wcsFormatSpecifier(fs.begin(), fs.end()); - base::utils::Str::replaceFirstWithEscape(logLine, wcsFormatSpecifier, it->resolver()(logMessage)); - } -#endif // !defined(ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS) - if (appendNewLine) logLine += ELPP_LITERAL("\n"); - return logLine; -} - -// LogDispatcher - -void LogDispatcher::dispatch(void) { - if (m_proceed && m_dispatchAction == base::DispatchAction::None) { - m_proceed = false; - } - if (!m_proceed) { - return; - } -#ifndef ELPP_NO_GLOBAL_LOCK - // see https://github.com/muflihun/easyloggingpp/issues/580 - // global lock is turned off by default unless - // ELPP_NO_GLOBAL_LOCK is defined - base::threading::ScopedLock scopedLock(ELPP->lock()); -#endif - base::TypedConfigurations* tc = m_logMessage->logger()->m_typedConfigurations; - if (ELPP->hasFlag(LoggingFlag::StrictLogFileSizeCheck)) { - tc->validateFileRolling(m_logMessage->level(), ELPP->preRollOutCallback()); - } - LogDispatchCallback* callback = nullptr; - LogDispatchData data; - for (const std::pair& h - : ELPP->m_logDispatchCallbacks) { - callback = h.second.get(); - if (callback != nullptr && callback->enabled()) { - data.setLogMessage(m_logMessage); - data.setDispatchAction(m_dispatchAction); - callback->handle(&data); - } - } -} - -// MessageBuilder - -void MessageBuilder::initialize(Logger* logger) { - m_logger = logger; - m_containerLogSeperator = ELPP->hasFlag(LoggingFlag::NewLineForContainer) ? - ELPP_LITERAL("\n ") : ELPP_LITERAL(", "); -} - -MessageBuilder& MessageBuilder::operator<<(const wchar_t* msg) { - if (msg == nullptr) { - m_logger->stream() << base::consts::kNullPointer; - return *this; - } -# if defined(ELPP_UNICODE) - m_logger->stream() << msg; -# else - char* buff_ = base::utils::Str::wcharPtrToCharPtr(msg); - m_logger->stream() << buff_; - free(buff_); -# endif - if (ELPP->hasFlag(LoggingFlag::AutoSpacing)) { - m_logger->stream() << " "; - } - return *this; -} - -// Writer - -Writer& Writer::construct(Logger* logger, bool needLock) { - m_logger = logger; - initializeLogger(logger->id(), false, needLock); - m_messageBuilder.initialize(m_logger); - return *this; -} - -Writer& Writer::construct(int count, const char* loggerIds, ...) { - if (ELPP->hasFlag(LoggingFlag::MultiLoggerSupport)) { - va_list loggersList; - va_start(loggersList, loggerIds); - const char* id = loggerIds; - m_loggerIds.reserve(count); - for (int i = 0; i < count; ++i) { - m_loggerIds.push_back(std::string(id)); - id = va_arg(loggersList, const char*); - } - va_end(loggersList); - initializeLogger(m_loggerIds.at(0)); - } else { - initializeLogger(std::string(loggerIds)); - } - m_messageBuilder.initialize(m_logger); - return *this; -} - -void Writer::initializeLogger(const std::string& loggerId, bool lookup, bool needLock) { - if (lookup) { - m_logger = ELPP->registeredLoggers()->get(loggerId, ELPP->hasFlag(LoggingFlag::CreateLoggerAutomatically)); - } - if (m_logger == nullptr) { - { - if (!ELPP->registeredLoggers()->has(std::string(base::consts::kDefaultLoggerId))) { - // Somehow default logger has been unregistered. Not good! Register again - ELPP->registeredLoggers()->get(std::string(base::consts::kDefaultLoggerId)); - } - } - Writer(Level::Debug, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId) - << "Logger [" << loggerId << "] is not registered yet!"; - m_proceed = false; - } else { - if (needLock) { - m_logger->acquireLock(); // This should not be unlocked by checking m_proceed because - // m_proceed can be changed by lines below - } - if (ELPP->hasFlag(LoggingFlag::HierarchicalLogging)) { - m_proceed = m_level == Level::Verbose ? m_logger->enabled(m_level) : - LevelHelper::castToInt(m_level) >= LevelHelper::castToInt(ELPP->m_loggingLevel); - } else { - m_proceed = m_logger->enabled(m_level); - } - } -} - -void Writer::processDispatch() { -#if ELPP_LOGGING_ENABLED - if (ELPP->hasFlag(LoggingFlag::MultiLoggerSupport)) { - bool firstDispatched = false; - base::type::string_t logMessage; - std::size_t i = 0; - do { - if (m_proceed) { - if (firstDispatched) { - m_logger->stream() << logMessage; - } else { - firstDispatched = true; - if (m_loggerIds.size() > 1) { - logMessage = m_logger->stream().str(); - } - } - triggerDispatch(); - } else if (m_logger != nullptr) { - m_logger->stream().str(ELPP_LITERAL("")); - m_logger->releaseLock(); - } - if (i + 1 < m_loggerIds.size()) { - initializeLogger(m_loggerIds.at(i + 1)); - } - } while (++i < m_loggerIds.size()); - } else { - if (m_proceed) { - triggerDispatch(); - } else if (m_logger != nullptr) { - m_logger->stream().str(ELPP_LITERAL("")); - m_logger->releaseLock(); - } - } -#else - if (m_logger != nullptr) { - m_logger->stream().str(ELPP_LITERAL("")); - m_logger->releaseLock(); - } -#endif // ELPP_LOGGING_ENABLED -} - -void Writer::triggerDispatch(void) { - if (m_proceed) { - if (m_msg == nullptr) { - LogMessage msg(m_level, m_file, m_line, m_func, m_verboseLevel, - m_logger); - base::LogDispatcher(m_proceed, &msg, m_dispatchAction).dispatch(); - } else { - base::LogDispatcher(m_proceed, m_msg, m_dispatchAction).dispatch(); - } - } - if (m_logger != nullptr) { - m_logger->stream().str(ELPP_LITERAL("")); - m_logger->releaseLock(); - } - if (m_proceed && m_level == Level::Fatal - && !ELPP->hasFlag(LoggingFlag::DisableApplicationAbortOnFatalLog)) { - base::Writer(Level::Warning, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId) - << "Aborting application. Reason: Fatal log at [" << m_file << ":" << m_line << "]"; - std::stringstream reasonStream; - reasonStream << "Fatal log at [" << m_file << ":" << m_line << "]" - << " If you wish to disable 'abort on fatal log' please use " - << "el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog)"; - base::utils::abort(1, reasonStream.str()); - } - m_proceed = false; -} - -// PErrorWriter - -PErrorWriter::~PErrorWriter(void) { - if (m_proceed) { -#if ELPP_COMPILER_MSVC - char buff[256]; - strerror_s(buff, 256, errno); - m_logger->stream() << ": " << buff << " [" << errno << "]"; -#else - m_logger->stream() << ": " << strerror(errno) << " [" << errno << "]"; -#endif - } -} - -// PerformanceTracker - -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) - -PerformanceTracker::PerformanceTracker(const std::string& blockName, - base::TimestampUnit timestampUnit, - const std::string& loggerId, - bool scopedLog, Level level) : - m_blockName(blockName), m_timestampUnit(timestampUnit), m_loggerId(loggerId), m_scopedLog(scopedLog), - m_level(level), m_hasChecked(false), m_lastCheckpointId(std::string()), m_enabled(false) { -#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED - // We store it locally so that if user happen to change configuration by the end of scope - // or before calling checkpoint, we still depend on state of configuraton at time of construction - el::Logger* loggerPtr = ELPP->registeredLoggers()->get(loggerId, false); - m_enabled = loggerPtr != nullptr && loggerPtr->m_typedConfigurations->performanceTracking(m_level); - if (m_enabled) { - base::utils::DateTime::gettimeofday(&m_startTime); - } -#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED -} - -PerformanceTracker::~PerformanceTracker(void) { -#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED - if (m_enabled) { - base::threading::ScopedLock scopedLock(lock()); - if (m_scopedLog) { - base::utils::DateTime::gettimeofday(&m_endTime); - base::type::string_t formattedTime = getFormattedTimeTaken(); - PerformanceTrackingData data(PerformanceTrackingData::DataType::Complete); - data.init(this); - data.m_formattedTimeTaken = formattedTime; - PerformanceTrackingCallback* callback = nullptr; - for (const std::pair& h - : ELPP->m_performanceTrackingCallbacks) { - callback = h.second.get(); - if (callback != nullptr && callback->enabled()) { - callback->handle(&data); - } - } - } - } -#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) -} - -void PerformanceTracker::checkpoint(const std::string& id, const char* file, base::type::LineNumber line, - const char* func) { -#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED - if (m_enabled) { - base::threading::ScopedLock scopedLock(lock()); - base::utils::DateTime::gettimeofday(&m_endTime); - base::type::string_t formattedTime = m_hasChecked ? getFormattedTimeTaken(m_lastCheckpointTime) : ELPP_LITERAL(""); - PerformanceTrackingData data(PerformanceTrackingData::DataType::Checkpoint); - data.init(this); - data.m_checkpointId = id; - data.m_file = file; - data.m_line = line; - data.m_func = func; - data.m_formattedTimeTaken = formattedTime; - PerformanceTrackingCallback* callback = nullptr; - for (const std::pair& h - : ELPP->m_performanceTrackingCallbacks) { - callback = h.second.get(); - if (callback != nullptr && callback->enabled()) { - callback->handle(&data); - } - } - base::utils::DateTime::gettimeofday(&m_lastCheckpointTime); - m_hasChecked = true; - m_lastCheckpointId = id; - } -#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED - ELPP_UNUSED(id); - ELPP_UNUSED(file); - ELPP_UNUSED(line); - ELPP_UNUSED(func); -} - -const base::type::string_t PerformanceTracker::getFormattedTimeTaken(struct timeval startTime) const { - if (ELPP->hasFlag(LoggingFlag::FixedTimeFormat)) { - base::type::stringstream_t ss; - ss << base::utils::DateTime::getTimeDifference(m_endTime, - startTime, m_timestampUnit) << " " << base::consts::kTimeFormats[static_cast - (m_timestampUnit)].unit; - return ss.str(); - } - return base::utils::DateTime::formatTime(base::utils::DateTime::getTimeDifference(m_endTime, - startTime, m_timestampUnit), m_timestampUnit); -} - -#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) - -namespace debug { -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) - -// StackTrace - -StackTrace::StackTraceEntry::StackTraceEntry(std::size_t index, const std::string& loc, const std::string& demang, - const std::string& hex, - const std::string& addr) : - m_index(index), - m_location(loc), - m_demangled(demang), - m_hex(hex), - m_addr(addr) { -} - -std::ostream& operator<<(std::ostream& ss, const StackTrace::StackTraceEntry& si) { - ss << "[" << si.m_index << "] " << si.m_location << (si.m_hex.empty() ? "" : "+") << si.m_hex << " " << si.m_addr << - (si.m_demangled.empty() ? "" : ":") << si.m_demangled; - return ss; -} - -std::ostream& operator<<(std::ostream& os, const StackTrace& st) { - std::vector::const_iterator it = st.m_stack.begin(); - while (it != st.m_stack.end()) { - os << " " << *it++ << "\n"; - } - return os; -} - -void StackTrace::generateNew(void) { -#if ELPP_STACKTRACE - m_stack.clear(); - void* stack[kMaxStack]; - unsigned int size = backtrace(stack, kMaxStack); - char** strings = backtrace_symbols(stack, size); - if (size > kStackStart) { // Skip StackTrace c'tor and generateNew - for (std::size_t i = kStackStart; i < size; ++i) { - std::string mangName; - std::string location; - std::string hex; - std::string addr; - - // entry: 2 crash.cpp.bin 0x0000000101552be5 _ZN2el4base5debug10StackTraceC1Ev + 21 - const std::string line(strings[i]); - auto p = line.find("_"); - if (p != std::string::npos) { - mangName = line.substr(p); - mangName = mangName.substr(0, mangName.find(" +")); - } - p = line.find("0x"); - if (p != std::string::npos) { - addr = line.substr(p); - addr = addr.substr(0, addr.find("_")); - } - // Perform demangling if parsed properly - if (!mangName.empty()) { - int status = 0; - char* demangName = abi::__cxa_demangle(mangName.data(), 0, 0, &status); - // if demangling is successful, output the demangled function name - if (status == 0) { - // Success (see http://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html) - StackTraceEntry entry(i - 1, location, demangName, hex, addr); - m_stack.push_back(entry); - } else { - // Not successful - we will use mangled name - StackTraceEntry entry(i - 1, location, mangName, hex, addr); - m_stack.push_back(entry); - } - free(demangName); - } else { - StackTraceEntry entry(i - 1, line); - m_stack.push_back(entry); - } - } - } - free(strings); -#else - ELPP_INTERNAL_INFO(1, "Stacktrace generation not supported for selected compiler"); -#endif // ELPP_STACKTRACE -} - -// Static helper functions - -static std::string crashReason(int sig) { - std::stringstream ss; - bool foundReason = false; - for (int i = 0; i < base::consts::kCrashSignalsCount; ++i) { - if (base::consts::kCrashSignals[i].numb == sig) { - ss << "Application has crashed due to [" << base::consts::kCrashSignals[i].name << "] signal"; - if (ELPP->hasFlag(el::LoggingFlag::LogDetailedCrashReason)) { - ss << std::endl << - " " << base::consts::kCrashSignals[i].brief << std::endl << - " " << base::consts::kCrashSignals[i].detail; - } - foundReason = true; - } - } - if (!foundReason) { - ss << "Application has crashed due to unknown signal [" << sig << "]"; - } - return ss.str(); -} -/// @brief Logs reason of crash from sig -static void logCrashReason(int sig, bool stackTraceIfAvailable, Level level, const char* logger) { - if (sig == SIGINT && ELPP->hasFlag(el::LoggingFlag::IgnoreSigInt)) { - return; - } - std::stringstream ss; - ss << "CRASH HANDLED; "; - ss << crashReason(sig); -#if ELPP_STACKTRACE - if (stackTraceIfAvailable) { - ss << std::endl << " ======= Backtrace: =========" << std::endl << base::debug::StackTrace(); - } -#else - ELPP_UNUSED(stackTraceIfAvailable); -#endif // ELPP_STACKTRACE - ELPP_WRITE_LOG(el::base::Writer, level, base::DispatchAction::NormalLog, logger) << ss.str(); -} - -static inline void crashAbort(int sig) { - base::utils::abort(sig, std::string()); -} - -/// @brief Default application crash handler -/// -/// @detail This function writes log using 'default' logger, prints stack trace for GCC based compilers and aborts program. -static inline void defaultCrashHandler(int sig) { - base::debug::logCrashReason(sig, true, Level::Fatal, base::consts::kDefaultLoggerId); - base::debug::crashAbort(sig); -} - -// CrashHandler - -CrashHandler::CrashHandler(bool useDefault) { - if (useDefault) { - setHandler(defaultCrashHandler); - } -} - -void CrashHandler::setHandler(const Handler& cHandler) { - m_handler = cHandler; -#if defined(ELPP_HANDLE_SIGABRT) - int i = 0; // SIGABRT is at base::consts::kCrashSignals[0] -#else - int i = 1; -#endif // defined(ELPP_HANDLE_SIGABRT) - for (; i < base::consts::kCrashSignalsCount; ++i) { - m_handler = signal(base::consts::kCrashSignals[i].numb, cHandler); - } -} - -#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) -} // namespace debug -} // namespace base - -// el - -// Helpers - -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) - -void Helpers::crashAbort(int sig, const char* sourceFile, unsigned int long line) { - std::stringstream ss; - ss << base::debug::crashReason(sig).c_str(); - ss << " - [Called el::Helpers::crashAbort(" << sig << ")]"; - if (sourceFile != nullptr && strlen(sourceFile) > 0) { - ss << " - Source: " << sourceFile; - if (line > 0) - ss << ":" << line; - else - ss << " (line number not specified)"; - } - base::utils::abort(sig, ss.str()); -} - -void Helpers::logCrashReason(int sig, bool stackTraceIfAvailable, Level level, const char* logger) { - el::base::debug::logCrashReason(sig, stackTraceIfAvailable, level, logger); -} - -#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) - -// Loggers - -Logger* Loggers::getLogger(const std::string& identity, bool registerIfNotAvailable) { - return ELPP->registeredLoggers()->get(identity, registerIfNotAvailable); -} - -void Loggers::setDefaultLogBuilder(el::LogBuilderPtr& logBuilderPtr) { - ELPP->registeredLoggers()->setDefaultLogBuilder(logBuilderPtr); -} - -bool Loggers::unregisterLogger(const std::string& identity) { - return ELPP->registeredLoggers()->remove(identity); -} - -bool Loggers::hasLogger(const std::string& identity) { - return ELPP->registeredLoggers()->has(identity); -} - -Logger* Loggers::reconfigureLogger(Logger* logger, const Configurations& configurations) { - if (!logger) return nullptr; - logger->configure(configurations); - return logger; -} - -Logger* Loggers::reconfigureLogger(const std::string& identity, const Configurations& configurations) { - return Loggers::reconfigureLogger(Loggers::getLogger(identity), configurations); -} - -Logger* Loggers::reconfigureLogger(const std::string& identity, ConfigurationType configurationType, - const std::string& value) { - Logger* logger = Loggers::getLogger(identity); - if (logger == nullptr) { - return nullptr; - } - logger->configurations()->set(Level::Global, configurationType, value); - logger->reconfigure(); - return logger; -} - -void Loggers::reconfigureAllLoggers(const Configurations& configurations) { - for (base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->begin(); - it != ELPP->registeredLoggers()->end(); ++it) { - Loggers::reconfigureLogger(it->second, configurations); - } -} - -void Loggers::reconfigureAllLoggers(Level level, ConfigurationType configurationType, - const std::string& value) { - for (base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->begin(); - it != ELPP->registeredLoggers()->end(); ++it) { - Logger* logger = it->second; - logger->configurations()->set(level, configurationType, value); - logger->reconfigure(); - } -} - -void Loggers::setDefaultConfigurations(const Configurations& configurations, bool reconfigureExistingLoggers) { - ELPP->registeredLoggers()->setDefaultConfigurations(configurations); - if (reconfigureExistingLoggers) { - Loggers::reconfigureAllLoggers(configurations); - } -} - -const Configurations* Loggers::defaultConfigurations(void) { - return ELPP->registeredLoggers()->defaultConfigurations(); -} - -const base::LogStreamsReferenceMap* Loggers::logStreamsReference(void) { - return ELPP->registeredLoggers()->logStreamsReference(); -} - -base::TypedConfigurations Loggers::defaultTypedConfigurations(void) { - return base::TypedConfigurations( - ELPP->registeredLoggers()->defaultConfigurations(), - ELPP->registeredLoggers()->logStreamsReference()); -} - -std::vector* Loggers::populateAllLoggerIds(std::vector* targetList) { - targetList->clear(); - for (base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->list().begin(); - it != ELPP->registeredLoggers()->list().end(); ++it) { - targetList->push_back(it->first); - } - return targetList; -} - -void Loggers::configureFromGlobal(const char* globalConfigurationFilePath) { - std::ifstream gcfStream(globalConfigurationFilePath, std::ifstream::in); - ELPP_ASSERT(gcfStream.is_open(), "Unable to open global configuration file [" << globalConfigurationFilePath - << "] for parsing."); - std::string line = std::string(); - std::stringstream ss; - Logger* logger = nullptr; - auto configure = [&](void) { - ELPP_INTERNAL_INFO(8, "Configuring logger: '" << logger->id() << "' with configurations \n" << ss.str() - << "\n--------------"); - Configurations c; - c.parseFromText(ss.str()); - logger->configure(c); - }; - while (gcfStream.good()) { - std::getline(gcfStream, line); - ELPP_INTERNAL_INFO(1, "Parsing line: " << line); - base::utils::Str::trim(line); - if (Configurations::Parser::isComment(line)) continue; - Configurations::Parser::ignoreComments(&line); - base::utils::Str::trim(line); - if (line.size() > 2 && base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationLoggerId))) { - if (!ss.str().empty() && logger != nullptr) { - configure(); - } - ss.str(std::string("")); - line = line.substr(2); - base::utils::Str::trim(line); - if (line.size() > 1) { - ELPP_INTERNAL_INFO(1, "Getting logger: '" << line << "'"); - logger = getLogger(line); - } - } else { - ss << line << "\n"; - } - } - if (!ss.str().empty() && logger != nullptr) { - configure(); - } -} - -bool Loggers::configureFromArg(const char* argKey) { -#if defined(ELPP_DISABLE_CONFIGURATION_FROM_PROGRAM_ARGS) - ELPP_UNUSED(argKey); -#else - if (!Helpers::commandLineArgs()->hasParamWithValue(argKey)) { - return false; - } - configureFromGlobal(Helpers::commandLineArgs()->getParamValue(argKey)); -#endif // defined(ELPP_DISABLE_CONFIGURATION_FROM_PROGRAM_ARGS) - return true; -} - -void Loggers::flushAll(void) { - ELPP->registeredLoggers()->flushAll(); -} - -void Loggers::setVerboseLevel(base::type::VerboseLevel level) { - ELPP->vRegistry()->setLevel(level); -} - -base::type::VerboseLevel Loggers::verboseLevel(void) { - return ELPP->vRegistry()->level(); -} - -void Loggers::setVModules(const char* modules) { - if (ELPP->vRegistry()->vModulesEnabled()) { - ELPP->vRegistry()->setModules(modules); - } -} - -void Loggers::clearVModules(void) { - ELPP->vRegistry()->clearModules(); -} - -// VersionInfo - -const std::string VersionInfo::version(void) { - return std::string("9.96.7"); -} -/// @brief Release date of current version -const std::string VersionInfo::releaseDate(void) { - return std::string("24-11-2018 0728hrs"); -} - -} // namespace el diff --git a/src/easylogging++.h b/src/easylogging++.h deleted file mode 100644 index 688d5377..00000000 --- a/src/easylogging++.h +++ /dev/null @@ -1,4569 +0,0 @@ -// -// Bismillah ar-Rahmaan ar-Raheem -// -// Easylogging++ v9.96.7 -// Single-header only, cross-platform logging library for C++ applications -// -// Copyright (c) 2012-2018 Zuhd Web Services -// Copyright (c) 2012-2018 @abumusamq -// -// This library is released under the MIT Licence. -// https://github.com/zuhd-org/easyloggingpp/blob/master/LICENSE -// -// https://zuhd.org -// http://muflihun.com -// - -#ifndef EASYLOGGINGPP_H -#define EASYLOGGINGPP_H -// Compilers and C++0x/C++11 Evaluation -#if __cplusplus >= 201103L -# define ELPP_CXX11 1 -#endif // __cplusplus >= 201103L -#if (defined(__GNUC__)) -# define ELPP_COMPILER_GCC 1 -#else -# define ELPP_COMPILER_GCC 0 -#endif -#if ELPP_COMPILER_GCC -# define ELPP_GCC_VERSION (__GNUC__ * 10000 \ -+ __GNUC_MINOR__ * 100 \ -+ __GNUC_PATCHLEVEL__) -# if defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ELPP_CXX0X 1 -# endif -#endif -// Visual C++ -#if defined(_MSC_VER) -# define ELPP_COMPILER_MSVC 1 -#else -# define ELPP_COMPILER_MSVC 0 -#endif -#define ELPP_CRT_DBG_WARNINGS ELPP_COMPILER_MSVC -#if ELPP_COMPILER_MSVC -# if (_MSC_VER == 1600) -# define ELPP_CXX0X 1 -# elif(_MSC_VER >= 1700) -# define ELPP_CXX11 1 -# endif -#endif -// Clang++ -#if (defined(__clang__) && (__clang__ == 1)) -# define ELPP_COMPILER_CLANG 1 -#else -# define ELPP_COMPILER_CLANG 0 -#endif -#if ELPP_COMPILER_CLANG -# if __has_include() -# include // Make __GLIBCXX__ defined when using libstdc++ -# if !defined(__GLIBCXX__) || __GLIBCXX__ >= 20150426 -# define ELPP_CLANG_SUPPORTS_THREAD -# endif // !defined(__GLIBCXX__) || __GLIBCXX__ >= 20150426 -# endif // __has_include() -#endif -#if (defined(__MINGW32__) || defined(__MINGW64__)) -# define ELPP_MINGW 1 -#else -# define ELPP_MINGW 0 -#endif -#if (defined(__CYGWIN__) && (__CYGWIN__ == 1)) -# define ELPP_CYGWIN 1 -#else -# define ELPP_CYGWIN 0 -#endif -#if (defined(__INTEL_COMPILER)) -# define ELPP_COMPILER_INTEL 1 -#else -# define ELPP_COMPILER_INTEL 0 -#endif -// Operating System Evaluation -// Windows -#if (defined(_WIN32) || defined(_WIN64)) -# define ELPP_OS_WINDOWS 1 -#else -# define ELPP_OS_WINDOWS 0 -#endif -// Linux -#if (defined(__linux) || defined(__linux__)) -# define ELPP_OS_LINUX 1 -#else -# define ELPP_OS_LINUX 0 -#endif -#if (defined(__APPLE__)) -# define ELPP_OS_MAC 1 -#else -# define ELPP_OS_MAC 0 -#endif -#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) -# define ELPP_OS_FREEBSD 1 -#else -# define ELPP_OS_FREEBSD 0 -#endif -#if (defined(__sun)) -# define ELPP_OS_SOLARIS 1 -#else -# define ELPP_OS_SOLARIS 0 -#endif -#if (defined(_AIX)) -# define ELPP_OS_AIX 1 -#else -# define ELPP_OS_AIX 0 -#endif -#if (defined(__NetBSD__)) -# define ELPP_OS_NETBSD 1 -#else -# define ELPP_OS_NETBSD 0 -#endif -#if defined(__EMSCRIPTEN__) -# define ELPP_OS_EMSCRIPTEN 1 -#else -# define ELPP_OS_EMSCRIPTEN 0 -#endif -// Unix -#if ((ELPP_OS_LINUX || ELPP_OS_MAC || ELPP_OS_FREEBSD || ELPP_OS_NETBSD || ELPP_OS_SOLARIS || ELPP_OS_AIX || ELPP_OS_EMSCRIPTEN) && (!ELPP_OS_WINDOWS)) -# define ELPP_OS_UNIX 1 -#else -# define ELPP_OS_UNIX 0 -#endif -#if (defined(__ANDROID__)) -# define ELPP_OS_ANDROID 1 -#else -# define ELPP_OS_ANDROID 0 -#endif -// Evaluating Cygwin as *nix OS -#if !ELPP_OS_UNIX && !ELPP_OS_WINDOWS && ELPP_CYGWIN -# undef ELPP_OS_UNIX -# undef ELPP_OS_LINUX -# define ELPP_OS_UNIX 1 -# define ELPP_OS_LINUX 1 -#endif // !ELPP_OS_UNIX && !ELPP_OS_WINDOWS && ELPP_CYGWIN -#if !defined(ELPP_INTERNAL_DEBUGGING_OUT_INFO) -# define ELPP_INTERNAL_DEBUGGING_OUT_INFO std::cout -#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) -#if !defined(ELPP_INTERNAL_DEBUGGING_OUT_ERROR) -# define ELPP_INTERNAL_DEBUGGING_OUT_ERROR std::cerr -#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) -#if !defined(ELPP_INTERNAL_DEBUGGING_ENDL) -# define ELPP_INTERNAL_DEBUGGING_ENDL std::endl -#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) -#if !defined(ELPP_INTERNAL_DEBUGGING_MSG) -# define ELPP_INTERNAL_DEBUGGING_MSG(msg) msg -#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) -// Internal Assertions and errors -#if !defined(ELPP_DISABLE_ASSERT) -# if (defined(ELPP_DEBUG_ASSERT_FAILURE)) -# define ELPP_ASSERT(expr, msg) if (!(expr)) { \ -std::stringstream internalInfoStream; internalInfoStream << msg; \ -ELPP_INTERNAL_DEBUGGING_OUT_ERROR \ -<< "EASYLOGGING++ ASSERTION FAILED (LINE: " << __LINE__ << ") [" #expr << "] WITH MESSAGE \"" \ -<< ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << "\"" << ELPP_INTERNAL_DEBUGGING_ENDL; base::utils::abort(1, \ -"ELPP Assertion failure, please define ELPP_DEBUG_ASSERT_FAILURE"); } -# else -# define ELPP_ASSERT(expr, msg) if (!(expr)) { \ -std::stringstream internalInfoStream; internalInfoStream << msg; \ -ELPP_INTERNAL_DEBUGGING_OUT_ERROR\ -<< "ASSERTION FAILURE FROM EASYLOGGING++ (LINE: " \ -<< __LINE__ << ") [" #expr << "] WITH MESSAGE \"" << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << "\"" \ -<< ELPP_INTERNAL_DEBUGGING_ENDL; } -# endif // (defined(ELPP_DEBUG_ASSERT_FAILURE)) -#else -# define ELPP_ASSERT(x, y) -#endif //(!defined(ELPP_DISABLE_ASSERT) -#if ELPP_COMPILER_MSVC -# define ELPP_INTERNAL_DEBUGGING_WRITE_PERROR \ -{ char buff[256]; strerror_s(buff, 256, errno); \ -ELPP_INTERNAL_DEBUGGING_OUT_ERROR << ": " << buff << " [" << errno << "]";} (void)0 -#else -# define ELPP_INTERNAL_DEBUGGING_WRITE_PERROR \ -ELPP_INTERNAL_DEBUGGING_OUT_ERROR << ": " << strerror(errno) << " [" << errno << "]"; (void)0 -#endif // ELPP_COMPILER_MSVC -#if defined(ELPP_DEBUG_ERRORS) -# if !defined(ELPP_INTERNAL_ERROR) -# define ELPP_INTERNAL_ERROR(msg, pe) { \ -std::stringstream internalInfoStream; internalInfoStream << " " << msg; \ -ELPP_INTERNAL_DEBUGGING_OUT_ERROR \ -<< "ERROR FROM EASYLOGGING++ (LINE: " << __LINE__ << ") " \ -<< ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << ELPP_INTERNAL_DEBUGGING_ENDL; \ -if (pe) { ELPP_INTERNAL_DEBUGGING_OUT_ERROR << " "; ELPP_INTERNAL_DEBUGGING_WRITE_PERROR; }} (void)0 -# endif -#else -# undef ELPP_INTERNAL_INFO -# define ELPP_INTERNAL_ERROR(msg, pe) -#endif // defined(ELPP_DEBUG_ERRORS) -#if (defined(ELPP_DEBUG_INFO)) -# if !(defined(ELPP_INTERNAL_INFO_LEVEL)) -# define ELPP_INTERNAL_INFO_LEVEL 9 -# endif // !(defined(ELPP_INTERNAL_INFO_LEVEL)) -# if !defined(ELPP_INTERNAL_INFO) -# define ELPP_INTERNAL_INFO(lvl, msg) { if (lvl <= ELPP_INTERNAL_INFO_LEVEL) { \ -std::stringstream internalInfoStream; internalInfoStream << " " << msg; \ -ELPP_INTERNAL_DEBUGGING_OUT_INFO << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) \ -<< ELPP_INTERNAL_DEBUGGING_ENDL; }} -# endif -#else -# undef ELPP_INTERNAL_INFO -# define ELPP_INTERNAL_INFO(lvl, msg) -#endif // (defined(ELPP_DEBUG_INFO)) -#if (defined(ELPP_FEATURE_ALL)) || (defined(ELPP_FEATURE_CRASH_LOG)) -# if (ELPP_COMPILER_GCC && !ELPP_MINGW && !ELPP_OS_ANDROID && !ELPP_OS_EMSCRIPTEN) -# define ELPP_STACKTRACE 1 -# else -# if ELPP_COMPILER_MSVC -# pragma message("Stack trace not available for this compiler") -# else -# warning "Stack trace not available for this compiler"; -# endif // ELPP_COMPILER_MSVC -# define ELPP_STACKTRACE 0 -# endif // ELPP_COMPILER_GCC -#else -# define ELPP_STACKTRACE 0 -#endif // (defined(ELPP_FEATURE_ALL)) || (defined(ELPP_FEATURE_CRASH_LOG)) -// Miscellaneous macros -#define ELPP_UNUSED(x) (void)x -#if ELPP_OS_UNIX -// Log file permissions for unix-based systems -# define ELPP_LOG_PERMS S_IRUSR | S_IWUSR | S_IXUSR | S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IXOTH -#endif // ELPP_OS_UNIX -#if defined(ELPP_AS_DLL) && ELPP_COMPILER_MSVC -# if defined(ELPP_EXPORT_SYMBOLS) -# define ELPP_EXPORT __declspec(dllexport) -# else -# define ELPP_EXPORT __declspec(dllimport) -# endif // defined(ELPP_EXPORT_SYMBOLS) -#else -# define ELPP_EXPORT -#endif // defined(ELPP_AS_DLL) && ELPP_COMPILER_MSVC -// Some special functions that are VC++ specific -#undef STRTOK -#undef STRERROR -#undef STRCAT -#undef STRCPY -#if ELPP_CRT_DBG_WARNINGS -# define STRTOK(a, b, c) strtok_s(a, b, c) -# define STRERROR(a, b, c) strerror_s(a, b, c) -# define STRCAT(a, b, len) strcat_s(a, len, b) -# define STRCPY(a, b, len) strcpy_s(a, len, b) -#else -# define STRTOK(a, b, c) strtok(a, b) -# define STRERROR(a, b, c) strerror(c) -# define STRCAT(a, b, len) strcat(a, b) -# define STRCPY(a, b, len) strcpy(a, b) -#endif -// Compiler specific support evaluations -#if (ELPP_MINGW && !defined(ELPP_FORCE_USE_STD_THREAD)) -# define ELPP_USE_STD_THREADING 0 -#else -# if ((ELPP_COMPILER_CLANG && defined(ELPP_CLANG_SUPPORTS_THREAD)) || \ - (!ELPP_COMPILER_CLANG && defined(ELPP_CXX11)) || \ - defined(ELPP_FORCE_USE_STD_THREAD)) -# define ELPP_USE_STD_THREADING 1 -# else -# define ELPP_USE_STD_THREADING 0 -# endif -#endif -#undef ELPP_FINAL -#if ELPP_COMPILER_INTEL || (ELPP_GCC_VERSION < 40702) -# define ELPP_FINAL -#else -# define ELPP_FINAL final -#endif // ELPP_COMPILER_INTEL || (ELPP_GCC_VERSION < 40702) -#if defined(ELPP_EXPERIMENTAL_ASYNC) -# define ELPP_ASYNC_LOGGING 1 -#else -# define ELPP_ASYNC_LOGGING 0 -#endif // defined(ELPP_EXPERIMENTAL_ASYNC) -#if defined(ELPP_THREAD_SAFE) || ELPP_ASYNC_LOGGING -# define ELPP_THREADING_ENABLED 1 -#else -# define ELPP_THREADING_ENABLED 0 -#endif // defined(ELPP_THREAD_SAFE) || ELPP_ASYNC_LOGGING -// Function macro ELPP_FUNC -#undef ELPP_FUNC -#if ELPP_COMPILER_MSVC // Visual C++ -# define ELPP_FUNC __FUNCSIG__ -#elif ELPP_COMPILER_GCC // GCC -# define ELPP_FUNC __PRETTY_FUNCTION__ -#elif ELPP_COMPILER_INTEL // Intel C++ -# define ELPP_FUNC __PRETTY_FUNCTION__ -#elif ELPP_COMPILER_CLANG // Clang++ -# define ELPP_FUNC __PRETTY_FUNCTION__ -#else -# if defined(__func__) -# define ELPP_FUNC __func__ -# else -# define ELPP_FUNC "" -# endif // defined(__func__) -#endif // defined(_MSC_VER) -#undef ELPP_VARIADIC_TEMPLATES_SUPPORTED -// Keep following line commented until features are fixed -#define ELPP_VARIADIC_TEMPLATES_SUPPORTED \ -(ELPP_COMPILER_GCC || ELPP_COMPILER_CLANG || ELPP_COMPILER_INTEL || (ELPP_COMPILER_MSVC && _MSC_VER >= 1800)) -// Logging Enable/Disable macros -#if defined(ELPP_DISABLE_LOGS) -#define ELPP_LOGGING_ENABLED 0 -#else -#define ELPP_LOGGING_ENABLED 1 -#endif -#if (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED)) -# define ELPP_DEBUG_LOG 1 -#else -# define ELPP_DEBUG_LOG 0 -#endif // (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED)) -#if (!defined(ELPP_DISABLE_INFO_LOGS) && (ELPP_LOGGING_ENABLED)) -# define ELPP_INFO_LOG 1 -#else -# define ELPP_INFO_LOG 0 -#endif // (!defined(ELPP_DISABLE_INFO_LOGS) && (ELPP_LOGGING_ENABLED)) -#if (!defined(ELPP_DISABLE_WARNING_LOGS) && (ELPP_LOGGING_ENABLED)) -# define ELPP_WARNING_LOG 1 -#else -# define ELPP_WARNING_LOG 0 -#endif // (!defined(ELPP_DISABLE_WARNING_LOGS) && (ELPP_LOGGING_ENABLED)) -#if (!defined(ELPP_DISABLE_ERROR_LOGS) && (ELPP_LOGGING_ENABLED)) -# define ELPP_ERROR_LOG 1 -#else -# define ELPP_ERROR_LOG 0 -#endif // (!defined(ELPP_DISABLE_ERROR_LOGS) && (ELPP_LOGGING_ENABLED)) -#if (!defined(ELPP_DISABLE_FATAL_LOGS) && (ELPP_LOGGING_ENABLED)) -# define ELPP_FATAL_LOG 1 -#else -# define ELPP_FATAL_LOG 0 -#endif // (!defined(ELPP_DISABLE_FATAL_LOGS) && (ELPP_LOGGING_ENABLED)) -#if (!defined(ELPP_DISABLE_TRACE_LOGS) && (ELPP_LOGGING_ENABLED)) -# define ELPP_TRACE_LOG 1 -#else -# define ELPP_TRACE_LOG 0 -#endif // (!defined(ELPP_DISABLE_TRACE_LOGS) && (ELPP_LOGGING_ENABLED)) -#if (!defined(ELPP_DISABLE_VERBOSE_LOGS) && (ELPP_LOGGING_ENABLED)) -# define ELPP_VERBOSE_LOG 1 -#else -# define ELPP_VERBOSE_LOG 0 -#endif // (!defined(ELPP_DISABLE_VERBOSE_LOGS) && (ELPP_LOGGING_ENABLED)) -#if (!(ELPP_CXX0X || ELPP_CXX11)) -# error "C++0x (or higher) support not detected! (Is `-std=c++11' missing?)" -#endif // (!(ELPP_CXX0X || ELPP_CXX11)) -// Headers -#if defined(ELPP_SYSLOG) -# include -#endif // defined(ELPP_SYSLOG) -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(ELPP_UNICODE) -# include -# if ELPP_OS_WINDOWS -# include -# endif // ELPP_OS_WINDOWS -#endif // defined(ELPP_UNICODE) -#if ELPP_STACKTRACE -# include -# include -#endif // ELPP_STACKTRACE -#if ELPP_OS_ANDROID -# include -#endif // ELPP_OS_ANDROID -#if ELPP_OS_UNIX -# include -# include -#elif ELPP_OS_WINDOWS -# include -# include -# if defined(WIN32_LEAN_AND_MEAN) -# if defined(ELPP_WINSOCK2) -# include -# else -# include -# endif // defined(ELPP_WINSOCK2) -# endif // defined(WIN32_LEAN_AND_MEAN) -#endif // ELPP_OS_UNIX -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if ELPP_THREADING_ENABLED -# if ELPP_USE_STD_THREADING -# include -# include -# else -# if ELPP_OS_UNIX -# include -# endif // ELPP_OS_UNIX -# endif // ELPP_USE_STD_THREADING -#endif // ELPP_THREADING_ENABLED -#if ELPP_ASYNC_LOGGING -# if defined(ELPP_NO_SLEEP_FOR) -# include -# endif // defined(ELPP_NO_SLEEP_FOR) -# include -# include -# include -#endif // ELPP_ASYNC_LOGGING -#if defined(ELPP_STL_LOGGING) -// For logging STL based templates -# include -# include -# include -# include -# include -# include -# if defined(ELPP_LOG_STD_ARRAY) -# include -# endif // defined(ELPP_LOG_STD_ARRAY) -# if defined(ELPP_LOG_UNORDERED_SET) -# include -# endif // defined(ELPP_UNORDERED_SET) -#endif // defined(ELPP_STL_LOGGING) -#if defined(ELPP_QT_LOGGING) -// For logging Qt based classes & templates -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -#endif // defined(ELPP_QT_LOGGING) -#if defined(ELPP_BOOST_LOGGING) -// For logging boost based classes & templates -# include -# include -# include -# include -# include -# include -# include -# include -#endif // defined(ELPP_BOOST_LOGGING) -#if defined(ELPP_WXWIDGETS_LOGGING) -// For logging wxWidgets based classes & templates -# include -#endif // defined(ELPP_WXWIDGETS_LOGGING) -#if defined(ELPP_UTC_DATETIME) -# define elpptime_r gmtime_r -# define elpptime_s gmtime_s -# define elpptime gmtime -#else -# define elpptime_r localtime_r -# define elpptime_s localtime_s -# define elpptime localtime -#endif // defined(ELPP_UTC_DATETIME) -// Forward declarations -namespace el { -class Logger; -class LogMessage; -class PerformanceTrackingData; -class Loggers; -class Helpers; -template class Callback; -class LogDispatchCallback; -class PerformanceTrackingCallback; -class LoggerRegistrationCallback; -class LogDispatchData; -namespace base { -class Storage; -class RegisteredLoggers; -class PerformanceTracker; -class MessageBuilder; -class Writer; -class PErrorWriter; -class LogDispatcher; -class DefaultLogBuilder; -class DefaultLogDispatchCallback; -#if ELPP_ASYNC_LOGGING -class AsyncLogDispatchCallback; -class AsyncDispatchWorker; -#endif // ELPP_ASYNC_LOGGING -class DefaultPerformanceTrackingCallback; -} // namespace base -} // namespace el -/// @brief Easylogging++ entry namespace -namespace el { -/// @brief Namespace containing base/internal functionality used by Easylogging++ -namespace base { -/// @brief Data types used by Easylogging++ -namespace type { -#undef ELPP_LITERAL -#undef ELPP_STRLEN -#undef ELPP_COUT -#if defined(ELPP_UNICODE) -# define ELPP_LITERAL(txt) L##txt -# define ELPP_STRLEN wcslen -# if defined ELPP_CUSTOM_COUT -# define ELPP_COUT ELPP_CUSTOM_COUT -# else -# define ELPP_COUT std::wcout -# endif // defined ELPP_CUSTOM_COUT -typedef wchar_t char_t; -typedef std::wstring string_t; -typedef std::wstringstream stringstream_t; -typedef std::wfstream fstream_t; -typedef std::wostream ostream_t; -#else -# define ELPP_LITERAL(txt) txt -# define ELPP_STRLEN strlen -# if defined ELPP_CUSTOM_COUT -# define ELPP_COUT ELPP_CUSTOM_COUT -# else -# define ELPP_COUT std::cout -# endif // defined ELPP_CUSTOM_COUT -typedef char char_t; -typedef std::string string_t; -typedef std::stringstream stringstream_t; -typedef std::fstream fstream_t; -typedef std::ostream ostream_t; -#endif // defined(ELPP_UNICODE) -#if defined(ELPP_CUSTOM_COUT_LINE) -# define ELPP_COUT_LINE(logLine) ELPP_CUSTOM_COUT_LINE(logLine) -#else -# define ELPP_COUT_LINE(logLine) logLine << std::flush -#endif // defined(ELPP_CUSTOM_COUT_LINE) -typedef unsigned int EnumType; -typedef unsigned short VerboseLevel; -typedef unsigned long int LineNumber; -typedef std::shared_ptr StoragePointer; -typedef std::shared_ptr LogDispatchCallbackPtr; -typedef std::shared_ptr PerformanceTrackingCallbackPtr; -typedef std::shared_ptr LoggerRegistrationCallbackPtr; -typedef std::unique_ptr PerformanceTrackerPtr; -} // namespace type -/// @brief Internal helper class that prevent copy constructor for class -/// -/// @detail When using this class simply inherit it privately -class NoCopy { - protected: - NoCopy(void) {} - private: - NoCopy(const NoCopy&); - NoCopy& operator=(const NoCopy&); -}; -/// @brief Internal helper class that makes all default constructors private. -/// -/// @detail This prevents initializing class making it static unless an explicit constructor is declared. -/// When using this class simply inherit it privately -class StaticClass { - private: - StaticClass(void); - StaticClass(const StaticClass&); - StaticClass& operator=(const StaticClass&); -}; -} // namespace base -/// @brief Represents enumeration for severity level used to determine level of logging -/// -/// @detail With Easylogging++, developers may disable or enable any level regardless of -/// what the severity is. Or they can choose to log using hierarchical logging flag -enum class Level : base::type::EnumType { - /// @brief Generic level that represents all the levels. Useful when setting global configuration for all levels - Global = 1, - /// @brief Information that can be useful to back-trace certain events - mostly useful than debug logs. - Trace = 2, - /// @brief Informational events most useful for developers to debug application - Debug = 4, - /// @brief Severe error information that will presumably abort application - Fatal = 8, - /// @brief Information representing errors in application but application will keep running - Error = 16, - /// @brief Useful when application has potentially harmful situtaions - Warning = 32, - /// @brief Information that can be highly useful and vary with verbose logging level. - Verbose = 64, - /// @brief Mainly useful to represent current progress of application - Info = 128, - /// @brief Represents unknown level - Unknown = 1010 -}; -} // namespace el -namespace std { -template<> struct hash { - public: - std::size_t operator()(const el::Level& l) const { - return hash {}(static_cast(l)); - } -}; -} -namespace el { -/// @brief Static class that contains helper functions for el::Level -class LevelHelper : base::StaticClass { - public: - /// @brief Represents minimum valid level. Useful when iterating through enum. - static const base::type::EnumType kMinValid = static_cast(Level::Trace); - /// @brief Represents maximum valid level. This is used internally and you should not need it. - static const base::type::EnumType kMaxValid = static_cast(Level::Info); - /// @brief Casts level to int, useful for iterating through enum. - static base::type::EnumType castToInt(Level level) { - return static_cast(level); - } - /// @brief Casts int(ushort) to level, useful for iterating through enum. - static Level castFromInt(base::type::EnumType l) { - return static_cast(l); - } - /// @brief Converts level to associated const char* - /// @return Upper case string based level. - static const char* convertToString(Level level); - /// @brief Converts from levelStr to Level - /// @param levelStr Upper case string based level. - /// Lower case is also valid but providing upper case is recommended. - static Level convertFromString(const char* levelStr); - /// @brief Applies specified function to each level starting from startIndex - /// @param startIndex initial value to start the iteration from. This is passed as pointer and - /// is left-shifted so this can be used inside function (fn) to represent current level. - /// @param fn function to apply with each level. This bool represent whether or not to stop iterating through levels. - static void forEachLevel(base::type::EnumType* startIndex, const std::function& fn); -}; -/// @brief Represents enumeration of ConfigurationType used to configure or access certain aspect -/// of logging -enum class ConfigurationType : base::type::EnumType { - /// @brief Determines whether or not corresponding level and logger of logging is enabled - /// You may disable all logs by using el::Level::Global - Enabled = 1, - /// @brief Whether or not to write corresponding log to log file - ToFile = 2, - /// @brief Whether or not to write corresponding level and logger log to standard output. - /// By standard output meaning termnal, command prompt etc - ToStandardOutput = 4, - /// @brief Determines format of logging corresponding level and logger. - Format = 8, - /// @brief Determines log file (full path) to write logs to for correponding level and logger - Filename = 16, - /// @brief Specifies precision of the subsecond part. It should be within range (1-6). - SubsecondPrecision = 32, - /// @brief Alias of SubsecondPrecision (for backward compatibility) - MillisecondsWidth = SubsecondPrecision, - /// @brief Determines whether or not performance tracking is enabled. - /// - /// @detail This does not depend on logger or level. Performance tracking always uses 'performance' logger - PerformanceTracking = 64, - /// @brief Specifies log file max size. - /// - /// @detail If file size of corresponding log file (for corresponding level) is >= specified size, log file will - /// be truncated and re-initiated. - MaxLogFileSize = 128, - /// @brief Specifies number of log entries to hold until we flush pending log data - LogFlushThreshold = 256, - /// @brief Represents unknown configuration - Unknown = 1010 -}; -/// @brief Static class that contains helper functions for el::ConfigurationType -class ConfigurationTypeHelper : base::StaticClass { - public: - /// @brief Represents minimum valid configuration type. Useful when iterating through enum. - static const base::type::EnumType kMinValid = static_cast(ConfigurationType::Enabled); - /// @brief Represents maximum valid configuration type. This is used internally and you should not need it. - static const base::type::EnumType kMaxValid = static_cast(ConfigurationType::MaxLogFileSize); - /// @brief Casts configuration type to int, useful for iterating through enum. - static base::type::EnumType castToInt(ConfigurationType configurationType) { - return static_cast(configurationType); - } - /// @brief Casts int(ushort) to configurationt type, useful for iterating through enum. - static ConfigurationType castFromInt(base::type::EnumType c) { - return static_cast(c); - } - /// @brief Converts configuration type to associated const char* - /// @returns Upper case string based configuration type. - static const char* convertToString(ConfigurationType configurationType); - /// @brief Converts from configStr to ConfigurationType - /// @param configStr Upper case string based configuration type. - /// Lower case is also valid but providing upper case is recommended. - static ConfigurationType convertFromString(const char* configStr); - /// @brief Applies specified function to each configuration type starting from startIndex - /// @param startIndex initial value to start the iteration from. This is passed by pointer and is left-shifted - /// so this can be used inside function (fn) to represent current configuration type. - /// @param fn function to apply with each configuration type. - /// This bool represent whether or not to stop iterating through configurations. - static inline void forEachConfigType(base::type::EnumType* startIndex, const std::function& fn); -}; -/// @brief Flags used while writing logs. This flags are set by user -enum class LoggingFlag : base::type::EnumType { - /// @brief Makes sure we have new line for each container log entry - NewLineForContainer = 1, - /// @brief Makes sure if -vmodule is used and does not specifies a module, then verbose - /// logging is allowed via that module. - AllowVerboseIfModuleNotSpecified = 2, - /// @brief When handling crashes by default, detailed crash reason will be logged as well - LogDetailedCrashReason = 4, - /// @brief Allows to disable application abortion when logged using FATAL level - DisableApplicationAbortOnFatalLog = 8, - /// @brief Flushes log with every log-entry (performance sensative) - Disabled by default - ImmediateFlush = 16, - /// @brief Enables strict file rolling - StrictLogFileSizeCheck = 32, - /// @brief Make terminal output colorful for supported terminals - ColoredTerminalOutput = 64, - /// @brief Supports use of multiple logging in same macro, e.g, CLOG(INFO, "default", "network") - MultiLoggerSupport = 128, - /// @brief Disables comparing performance tracker's checkpoints - DisablePerformanceTrackingCheckpointComparison = 256, - /// @brief Disable VModules - DisableVModules = 512, - /// @brief Disable VModules extensions - DisableVModulesExtensions = 1024, - /// @brief Enables hierarchical logging - HierarchicalLogging = 2048, - /// @brief Creates logger automatically when not available - CreateLoggerAutomatically = 4096, - /// @brief Adds spaces b/w logs that separated by left-shift operator - AutoSpacing = 8192, - /// @brief Preserves time format and does not convert it to sec, hour etc (performance tracking only) - FixedTimeFormat = 16384, - // @brief Ignore SIGINT or crash - IgnoreSigInt = 32768, -}; -namespace base { -/// @brief Namespace containing constants used internally. -namespace consts { -static const char kFormatSpecifierCharValue = 'v'; -static const char kFormatSpecifierChar = '%'; -static const unsigned int kMaxLogPerCounter = 100000; -static const unsigned int kMaxLogPerContainer = 100; -static const unsigned int kDefaultSubsecondPrecision = 3; - -#ifdef ELPP_DEFAULT_LOGGER -static const char* kDefaultLoggerId = ELPP_DEFAULT_LOGGER; -#else -static const char* kDefaultLoggerId = "default"; -#endif - -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) -#ifdef ELPP_DEFAULT_PERFORMANCE_LOGGER -static const char* kPerformanceLoggerId = ELPP_DEFAULT_PERFORMANCE_LOGGER; -#else -static const char* kPerformanceLoggerId = "performance"; -#endif // ELPP_DEFAULT_PERFORMANCE_LOGGER -#endif - -#if defined(ELPP_SYSLOG) -static const char* kSysLogLoggerId = "syslog"; -#endif // defined(ELPP_SYSLOG) - -#if ELPP_OS_WINDOWS -static const char* kFilePathSeperator = "\\"; -#else -static const char* kFilePathSeperator = "/"; -#endif // ELPP_OS_WINDOWS - -static const std::size_t kSourceFilenameMaxLength = 100; -static const std::size_t kSourceLineMaxLength = 10; -static const Level kPerformanceTrackerDefaultLevel = Level::Info; -const struct { - double value; - const base::type::char_t* unit; -} kTimeFormats[] = { - { 1000.0f, ELPP_LITERAL("us") }, - { 1000.0f, ELPP_LITERAL("ms") }, - { 60.0f, ELPP_LITERAL("seconds") }, - { 60.0f, ELPP_LITERAL("minutes") }, - { 24.0f, ELPP_LITERAL("hours") }, - { 7.0f, ELPP_LITERAL("days") } -}; -static const int kTimeFormatsCount = sizeof(kTimeFormats) / sizeof(kTimeFormats[0]); -const struct { - int numb; - const char* name; - const char* brief; - const char* detail; -} kCrashSignals[] = { - // NOTE: Do not re-order, if you do please check CrashHandler(bool) constructor and CrashHandler::setHandler(..) - { - SIGABRT, "SIGABRT", "Abnormal termination", - "Program was abnormally terminated." - }, - { - SIGFPE, "SIGFPE", "Erroneous arithmetic operation", - "Arithemetic operation issue such as division by zero or operation resulting in overflow." - }, - { - SIGILL, "SIGILL", "Illegal instruction", - "Generally due to a corruption in the code or to an attempt to execute data." - }, - { - SIGSEGV, "SIGSEGV", "Invalid access to memory", - "Program is trying to read an invalid (unallocated, deleted or corrupted) or inaccessible memory." - }, - { - SIGINT, "SIGINT", "Interactive attention signal", - "Interruption generated (generally) by user or operating system." - }, -}; -static const int kCrashSignalsCount = sizeof(kCrashSignals) / sizeof(kCrashSignals[0]); -} // namespace consts -} // namespace base -typedef std::function PreRollOutCallback; -namespace base { -static inline void defaultPreRollOutCallback(const char*, std::size_t) {} -/// @brief Enum to represent timestamp unit -enum class TimestampUnit : base::type::EnumType { - Microsecond = 0, Millisecond = 1, Second = 2, Minute = 3, Hour = 4, Day = 5 -}; -/// @brief Format flags used to determine specifiers that are active for performance improvements. -enum class FormatFlags : base::type::EnumType { - DateTime = 1 << 1, - LoggerId = 1 << 2, - File = 1 << 3, - Line = 1 << 4, - Location = 1 << 5, - Function = 1 << 6, - User = 1 << 7, - Host = 1 << 8, - LogMessage = 1 << 9, - VerboseLevel = 1 << 10, - AppName = 1 << 11, - ThreadId = 1 << 12, - Level = 1 << 13, - FileBase = 1 << 14, - LevelShort = 1 << 15 -}; -/// @brief A subsecond precision class containing actual width and offset of the subsecond part -class SubsecondPrecision { - public: - SubsecondPrecision(void) { - init(base::consts::kDefaultSubsecondPrecision); - } - explicit SubsecondPrecision(int width) { - init(width); - } - bool operator==(const SubsecondPrecision& ssPrec) { - return m_width == ssPrec.m_width && m_offset == ssPrec.m_offset; - } - int m_width; - unsigned int m_offset; - private: - void init(int width); -}; -/// @brief Type alias of SubsecondPrecision -typedef SubsecondPrecision MillisecondsWidth; -/// @brief Namespace containing utility functions/static classes used internally -namespace utils { -/// @brief Deletes memory safely and points to null -template -static -typename std::enable_if::value, void>::type -safeDelete(T*& pointer) { - if (pointer == nullptr) - return; - delete pointer; - pointer = nullptr; -} -/// @brief Bitwise operations for C++11 strong enum class. This casts e into Flag_T and returns value after bitwise operation -/// Use these function as
flag = bitwise::Or(MyEnum::val1, flag);
-namespace bitwise { -template -static inline base::type::EnumType And(Enum e, base::type::EnumType flag) { - return static_cast(flag) & static_cast(e); -} -template -static inline base::type::EnumType Not(Enum e, base::type::EnumType flag) { - return static_cast(flag) & ~(static_cast(e)); -} -template -static inline base::type::EnumType Or(Enum e, base::type::EnumType flag) { - return static_cast(flag) | static_cast(e); -} -} // namespace bitwise -template -static inline void addFlag(Enum e, base::type::EnumType* flag) { - *flag = base::utils::bitwise::Or(e, *flag); -} -template -static inline void removeFlag(Enum e, base::type::EnumType* flag) { - *flag = base::utils::bitwise::Not(e, *flag); -} -template -static inline bool hasFlag(Enum e, base::type::EnumType flag) { - return base::utils::bitwise::And(e, flag) > 0x0; -} -} // namespace utils -namespace threading { -#if ELPP_THREADING_ENABLED -# if !ELPP_USE_STD_THREADING -namespace internal { -/// @brief A mutex wrapper for compiler that dont yet support std::recursive_mutex -class Mutex : base::NoCopy { - public: - Mutex(void) { -# if ELPP_OS_UNIX - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&m_underlyingMutex, &attr); - pthread_mutexattr_destroy(&attr); -# elif ELPP_OS_WINDOWS - InitializeCriticalSection(&m_underlyingMutex); -# endif // ELPP_OS_UNIX - } - - virtual ~Mutex(void) { -# if ELPP_OS_UNIX - pthread_mutex_destroy(&m_underlyingMutex); -# elif ELPP_OS_WINDOWS - DeleteCriticalSection(&m_underlyingMutex); -# endif // ELPP_OS_UNIX - } - - inline void lock(void) { -# if ELPP_OS_UNIX - pthread_mutex_lock(&m_underlyingMutex); -# elif ELPP_OS_WINDOWS - EnterCriticalSection(&m_underlyingMutex); -# endif // ELPP_OS_UNIX - } - - inline bool try_lock(void) { -# if ELPP_OS_UNIX - return (pthread_mutex_trylock(&m_underlyingMutex) == 0); -# elif ELPP_OS_WINDOWS - return TryEnterCriticalSection(&m_underlyingMutex); -# endif // ELPP_OS_UNIX - } - - inline void unlock(void) { -# if ELPP_OS_UNIX - pthread_mutex_unlock(&m_underlyingMutex); -# elif ELPP_OS_WINDOWS - LeaveCriticalSection(&m_underlyingMutex); -# endif // ELPP_OS_UNIX - } - - private: -# if ELPP_OS_UNIX - pthread_mutex_t m_underlyingMutex; -# elif ELPP_OS_WINDOWS - CRITICAL_SECTION m_underlyingMutex; -# endif // ELPP_OS_UNIX -}; -/// @brief Scoped lock for compiler that dont yet support std::lock_guard -template -class ScopedLock : base::NoCopy { - public: - explicit ScopedLock(M& mutex) { - m_mutex = &mutex; - m_mutex->lock(); - } - - virtual ~ScopedLock(void) { - m_mutex->unlock(); - } - private: - M* m_mutex; - ScopedLock(void); -}; -} // namespace internal -typedef base::threading::internal::Mutex Mutex; -typedef base::threading::internal::ScopedLock ScopedLock; -# else -typedef std::recursive_mutex Mutex; -typedef std::lock_guard ScopedLock; -# endif // !ELPP_USE_STD_THREADING -#else -namespace internal { -/// @brief Mutex wrapper used when multi-threading is disabled. -class NoMutex : base::NoCopy { - public: - NoMutex(void) {} - inline void lock(void) {} - inline bool try_lock(void) { - return true; - } - inline void unlock(void) {} -}; -/// @brief Lock guard wrapper used when multi-threading is disabled. -template -class NoScopedLock : base::NoCopy { - public: - explicit NoScopedLock(Mutex&) { - } - virtual ~NoScopedLock(void) { - } - private: - NoScopedLock(void); -}; -} // namespace internal -typedef base::threading::internal::NoMutex Mutex; -typedef base::threading::internal::NoScopedLock ScopedLock; -#endif // ELPP_THREADING_ENABLED -/// @brief Base of thread safe class, this class is inheritable-only -class ThreadSafe { - public: - virtual inline void acquireLock(void) ELPP_FINAL { m_mutex.lock(); } - virtual inline void releaseLock(void) ELPP_FINAL { m_mutex.unlock(); } - virtual inline base::threading::Mutex& lock(void) ELPP_FINAL { return m_mutex; } - protected: - ThreadSafe(void) {} - virtual ~ThreadSafe(void) {} - private: - base::threading::Mutex m_mutex; -}; - -#if ELPP_THREADING_ENABLED -# if !ELPP_USE_STD_THREADING -/// @brief Gets ID of currently running threading in windows systems. On unix, nothing is returned. -static std::string getCurrentThreadId(void) { - std::stringstream ss; -# if (ELPP_OS_WINDOWS) - ss << GetCurrentThreadId(); -# endif // (ELPP_OS_WINDOWS) - return ss.str(); -} -# else -/// @brief Gets ID of currently running threading using std::this_thread::get_id() -static std::string getCurrentThreadId(void) { - std::stringstream ss; - ss << std::this_thread::get_id(); - return ss.str(); -} -# endif // !ELPP_USE_STD_THREADING -#else -static inline std::string getCurrentThreadId(void) { - return std::string(); -} -#endif // ELPP_THREADING_ENABLED -} // namespace threading -namespace utils { -class File : base::StaticClass { - public: - /// @brief Creates new out file stream for specified filename. - /// @return Pointer to newly created fstream or nullptr - static base::type::fstream_t* newFileStream(const std::string& filename); - - /// @brief Gets size of file provided in stream - static std::size_t getSizeOfFile(base::type::fstream_t* fs); - - /// @brief Determines whether or not provided path exist in current file system - static bool pathExists(const char* path, bool considerFile = false); - - /// @brief Creates specified path on file system - /// @param path Path to create. - static bool createPath(const std::string& path); - /// @brief Extracts path of filename with leading slash - static std::string extractPathFromFilename(const std::string& fullPath, - const char* seperator = base::consts::kFilePathSeperator); - /// @brief builds stripped filename and puts it in buff - static void buildStrippedFilename(const char* filename, char buff[], - std::size_t limit = base::consts::kSourceFilenameMaxLength); - /// @brief builds base filename and puts it in buff - static void buildBaseFilename(const std::string& fullPath, char buff[], - std::size_t limit = base::consts::kSourceFilenameMaxLength, - const char* seperator = base::consts::kFilePathSeperator); -}; -/// @brief String utilities helper class used internally. You should not use it. -class Str : base::StaticClass { - public: - /// @brief Checks if character is digit. Dont use libc implementation of it to prevent locale issues. - static inline bool isDigit(char c) { - return c >= '0' && c <= '9'; - } - - /// @brief Matches wildcards, '*' and '?' only supported. - static bool wildCardMatch(const char* str, const char* pattern); - - static std::string& ltrim(std::string& str); - static std::string& rtrim(std::string& str); - static std::string& trim(std::string& str); - - /// @brief Determines whether or not str starts with specified string - /// @param str String to check - /// @param start String to check against - /// @return Returns true if starts with specified string, false otherwise - static bool startsWith(const std::string& str, const std::string& start); - - /// @brief Determines whether or not str ends with specified string - /// @param str String to check - /// @param end String to check against - /// @return Returns true if ends with specified string, false otherwise - static bool endsWith(const std::string& str, const std::string& end); - - /// @brief Replaces all instances of replaceWhat with 'replaceWith'. Original variable is changed for performance. - /// @param [in,out] str String to replace from - /// @param replaceWhat Character to replace - /// @param replaceWith Character to replace with - /// @return Modified version of str - static std::string& replaceAll(std::string& str, char replaceWhat, char replaceWith); - - /// @brief Replaces all instances of 'replaceWhat' with 'replaceWith'. (String version) Replaces in place - /// @param str String to replace from - /// @param replaceWhat Character to replace - /// @param replaceWith Character to replace with - /// @return Modified (original) str - static std::string& replaceAll(std::string& str, const std::string& replaceWhat, - const std::string& replaceWith); - - static void replaceFirstWithEscape(base::type::string_t& str, const base::type::string_t& replaceWhat, - const base::type::string_t& replaceWith); -#if defined(ELPP_UNICODE) - static void replaceFirstWithEscape(base::type::string_t& str, const base::type::string_t& replaceWhat, - const std::string& replaceWith); -#endif // defined(ELPP_UNICODE) - /// @brief Converts string to uppercase - /// @param str String to convert - /// @return Uppercase string - static std::string& toUpper(std::string& str); - - /// @brief Compares cstring equality - uses strcmp - static bool cStringEq(const char* s1, const char* s2); - - /// @brief Compares cstring equality (case-insensitive) - uses toupper(char) - /// Dont use strcasecmp because of CRT (VC++) - static bool cStringCaseEq(const char* s1, const char* s2); - - /// @brief Returns true if c exist in str - static bool contains(const char* str, char c); - - static char* convertAndAddToBuff(std::size_t n, int len, char* buf, const char* bufLim, bool zeroPadded = true); - static char* addToBuff(const char* str, char* buf, const char* bufLim); - static char* clearBuff(char buff[], std::size_t lim); - - /// @brief Converst wchar* to char* - /// NOTE: Need to free return value after use! - static char* wcharPtrToCharPtr(const wchar_t* line); -}; -/// @brief Operating System helper static class used internally. You should not use it. -class OS : base::StaticClass { - public: -#if ELPP_OS_WINDOWS - /// @brief Gets environment variables for Windows based OS. - /// We are not using getenv(const char*) because of CRT deprecation - /// @param varname Variable name to get environment variable value for - /// @return If variable exist the value of it otherwise nullptr - static const char* getWindowsEnvironmentVariable(const char* varname); -#endif // ELPP_OS_WINDOWS -#if ELPP_OS_ANDROID - /// @brief Reads android property value - static std::string getProperty(const char* prop); - - /// @brief Reads android device name - static std::string getDeviceName(void); -#endif // ELPP_OS_ANDROID - - /// @brief Runs command on terminal and returns the output. - /// - /// @detail This is applicable only on unix based systems, for all other OS, an empty string is returned. - /// @param command Bash command - /// @return Result of bash output or empty string if no result found. - static const std::string getBashOutput(const char* command); - - /// @brief Gets environment variable. This is cross-platform and CRT safe (for VC++) - /// @param variableName Environment variable name - /// @param defaultVal If no environment variable or value found the value to return by default - /// @param alternativeBashCommand If environment variable not found what would be alternative bash command - /// in order to look for value user is looking for. E.g, for 'user' alternative command will 'whoami' - static std::string getEnvironmentVariable(const char* variableName, const char* defaultVal, - const char* alternativeBashCommand = nullptr); - /// @brief Gets current username. - static std::string currentUser(void); - - /// @brief Gets current host name or computer name. - /// - /// @detail For android systems this is device name with its manufacturer and model seperated by hyphen - static std::string currentHost(void); - /// @brief Whether or not terminal supports colors - static bool termSupportsColor(void); -}; -/// @brief Contains utilities for cross-platform date/time. This class make use of el::base::utils::Str -class DateTime : base::StaticClass { - public: - /// @brief Cross platform gettimeofday for Windows and unix platform. This can be used to determine current microsecond. - /// - /// @detail For unix system it uses gettimeofday(timeval*, timezone*) and for Windows, a seperate implementation is provided - /// @param [in,out] tv Pointer that gets updated - static void gettimeofday(struct timeval* tv); - - /// @brief Gets current date and time with a subsecond part. - /// @param format User provided date/time format - /// @param ssPrec A pointer to base::SubsecondPrecision from configuration (non-null) - /// @returns string based date time in specified format. - static std::string getDateTime(const char* format, const base::SubsecondPrecision* ssPrec); - - /// @brief Converts timeval (struct from ctime) to string using specified format and subsecond precision - static std::string timevalToString(struct timeval tval, const char* format, - const el::base::SubsecondPrecision* ssPrec); - - /// @brief Formats time to get unit accordingly, units like second if > 1000 or minutes if > 60000 etc - static base::type::string_t formatTime(unsigned long long time, base::TimestampUnit timestampUnit); - - /// @brief Gets time difference in milli/micro second depending on timestampUnit - static unsigned long long getTimeDifference(const struct timeval& endTime, const struct timeval& startTime, - base::TimestampUnit timestampUnit); - - - static struct ::tm* buildTimeInfo(struct timeval* currTime, struct ::tm* timeInfo); - private: - static char* parseFormat(char* buf, std::size_t bufSz, const char* format, const struct tm* tInfo, - std::size_t msec, const base::SubsecondPrecision* ssPrec); -}; -/// @brief Command line arguments for application if specified using el::Helpers::setArgs(..) or START_EASYLOGGINGPP(..) -class CommandLineArgs { - public: - CommandLineArgs(void) { - setArgs(0, static_cast(nullptr)); - } - CommandLineArgs(int argc, const char** argv) { - setArgs(argc, argv); - } - CommandLineArgs(int argc, char** argv) { - setArgs(argc, argv); - } - virtual ~CommandLineArgs(void) {} - /// @brief Sets arguments and parses them - inline void setArgs(int argc, const char** argv) { - setArgs(argc, const_cast(argv)); - } - /// @brief Sets arguments and parses them - void setArgs(int argc, char** argv); - /// @brief Returns true if arguments contain paramKey with a value (seperated by '=') - bool hasParamWithValue(const char* paramKey) const; - /// @brief Returns value of arguments - /// @see hasParamWithValue(const char*) - const char* getParamValue(const char* paramKey) const; - /// @brief Return true if arguments has a param (not having a value) i,e without '=' - bool hasParam(const char* paramKey) const; - /// @brief Returns true if no params available. This exclude argv[0] - bool empty(void) const; - /// @brief Returns total number of arguments. This exclude argv[0] - std::size_t size(void) const; - friend base::type::ostream_t& operator<<(base::type::ostream_t& os, const CommandLineArgs& c); - - private: - int m_argc; - char** m_argv; - std::unordered_map m_paramsWithValue; - std::vector m_params; -}; -/// @brief Abstract registry (aka repository) that provides basic interface for pointer repository specified by T_Ptr type. -/// -/// @detail Most of the functions are virtual final methods but anything implementing this abstract class should implement -/// unregisterAll() and deepCopy(const AbstractRegistry&) and write registerNew() method according to container -/// and few more methods; get() to find element, unregister() to unregister single entry. -/// Please note that this is thread-unsafe and should also implement thread-safety mechanisms in implementation. -template -class AbstractRegistry : public base::threading::ThreadSafe { - public: - typedef typename Container::iterator iterator; - typedef typename Container::const_iterator const_iterator; - - /// @brief Default constructor - AbstractRegistry(void) {} - - /// @brief Move constructor that is useful for base classes - AbstractRegistry(AbstractRegistry&& sr) { - if (this == &sr) { - return; - } - unregisterAll(); - m_list = std::move(sr.m_list); - } - - bool operator==(const AbstractRegistry& other) { - if (size() != other.size()) { - return false; - } - for (std::size_t i = 0; i < m_list.size(); ++i) { - if (m_list.at(i) != other.m_list.at(i)) { - return false; - } - } - return true; - } - - bool operator!=(const AbstractRegistry& other) { - if (size() != other.size()) { - return true; - } - for (std::size_t i = 0; i < m_list.size(); ++i) { - if (m_list.at(i) != other.m_list.at(i)) { - return true; - } - } - return false; - } - - /// @brief Assignment move operator - AbstractRegistry& operator=(AbstractRegistry&& sr) { - if (this == &sr) { - return *this; - } - unregisterAll(); - m_list = std::move(sr.m_list); - return *this; - } - - virtual ~AbstractRegistry(void) { - } - - /// @return Iterator pointer from start of repository - virtual inline iterator begin(void) ELPP_FINAL { - return m_list.begin(); - } - - /// @return Iterator pointer from end of repository - virtual inline iterator end(void) ELPP_FINAL { - return m_list.end(); - } - - - /// @return Constant iterator pointer from start of repository - virtual inline const_iterator cbegin(void) const ELPP_FINAL { - return m_list.cbegin(); - } - - /// @return End of repository - virtual inline const_iterator cend(void) const ELPP_FINAL { - return m_list.cend(); - } - - /// @return Whether or not repository is empty - virtual inline bool empty(void) const ELPP_FINAL { - return m_list.empty(); - } - - /// @return Size of repository - virtual inline std::size_t size(void) const ELPP_FINAL { - return m_list.size(); - } - - /// @brief Returns underlying container by reference - virtual inline Container& list(void) ELPP_FINAL { - return m_list; - } - - /// @brief Returns underlying container by constant reference. - virtual inline const Container& list(void) const ELPP_FINAL { - return m_list; - } - - /// @brief Unregisters all the pointers from current repository. - virtual void unregisterAll(void) = 0; - - protected: - virtual void deepCopy(const AbstractRegistry&) = 0; - void reinitDeepCopy(const AbstractRegistry& sr) { - unregisterAll(); - deepCopy(sr); - } - - private: - Container m_list; -}; - -/// @brief A pointer registry mechanism to manage memory and provide search functionalities. (non-predicate version) -/// -/// @detail NOTE: This is thread-unsafe implementation (although it contains lock function, it does not use these functions) -/// of AbstractRegistry. Any implementation of this class should be -/// explicitly (by using lock functions) -template -class Registry : public AbstractRegistry> { - public: - typedef typename Registry::iterator iterator; - typedef typename Registry::const_iterator const_iterator; - - Registry(void) {} - - /// @brief Copy constructor that is useful for base classes. Try to avoid this constructor, use move constructor. - Registry(const Registry& sr) : AbstractRegistry>() { - if (this == &sr) { - return; - } - this->reinitDeepCopy(sr); - } - - /// @brief Assignment operator that unregisters all the existing registeries and deeply copies each of repo element - /// @see unregisterAll() - /// @see deepCopy(const AbstractRegistry&) - Registry& operator=(const Registry& sr) { - if (this == &sr) { - return *this; - } - this->reinitDeepCopy(sr); - return *this; - } - - virtual ~Registry(void) { - unregisterAll(); - } - - protected: - virtual void unregisterAll(void) ELPP_FINAL { - if (!this->empty()) { - for (auto&& curr : this->list()) { - base::utils::safeDelete(curr.second); - } - this->list().clear(); - } - } - -/// @brief Registers new registry to repository. - virtual void registerNew(const T_Key& uniqKey, T_Ptr* ptr) ELPP_FINAL { - unregister(uniqKey); - this->list().insert(std::make_pair(uniqKey, ptr)); - } - -/// @brief Unregisters single entry mapped to specified unique key - void unregister(const T_Key& uniqKey) { - T_Ptr* existing = get(uniqKey); - if (existing != nullptr) { - this->list().erase(uniqKey); - base::utils::safeDelete(existing); - } - } - -/// @brief Gets pointer from repository. If none found, nullptr is returned. - T_Ptr* get(const T_Key& uniqKey) { - iterator it = this->list().find(uniqKey); - return it == this->list().end() - ? nullptr - : it->second; - } - - private: - virtual void deepCopy(const AbstractRegistry>& sr) ELPP_FINAL { - for (const_iterator it = sr.cbegin(); it != sr.cend(); ++it) { - registerNew(it->first, new T_Ptr(*it->second)); - } - } -}; - -/// @brief A pointer registry mechanism to manage memory and provide search functionalities. (predicate version) -/// -/// @detail NOTE: This is thread-unsafe implementation of AbstractRegistry. Any implementation of this class -/// should be made thread-safe explicitly -template -class RegistryWithPred : public AbstractRegistry> { - public: - typedef typename RegistryWithPred::iterator iterator; - typedef typename RegistryWithPred::const_iterator const_iterator; - - RegistryWithPred(void) { - } - - virtual ~RegistryWithPred(void) { - unregisterAll(); - } - - /// @brief Copy constructor that is useful for base classes. Try to avoid this constructor, use move constructor. - RegistryWithPred(const RegistryWithPred& sr) : AbstractRegistry>() { - if (this == &sr) { - return; - } - this->reinitDeepCopy(sr); - } - - /// @brief Assignment operator that unregisters all the existing registeries and deeply copies each of repo element - /// @see unregisterAll() - /// @see deepCopy(const AbstractRegistry&) - RegistryWithPred& operator=(const RegistryWithPred& sr) { - if (this == &sr) { - return *this; - } - this->reinitDeepCopy(sr); - return *this; - } - - friend base::type::ostream_t& operator<<(base::type::ostream_t& os, const RegistryWithPred& sr) { - for (const_iterator it = sr.list().begin(); it != sr.list().end(); ++it) { - os << ELPP_LITERAL(" ") << **it << ELPP_LITERAL("\n"); - } - return os; - } - - protected: - virtual void unregisterAll(void) ELPP_FINAL { - if (!this->empty()) { - for (auto&& curr : this->list()) { - base::utils::safeDelete(curr); - } - this->list().clear(); - } - } - - virtual void unregister(T_Ptr*& ptr) ELPP_FINAL { - if (ptr) { - iterator iter = this->begin(); - for (; iter != this->end(); ++iter) { - if (ptr == *iter) { - break; - } - } - if (iter != this->end() && *iter != nullptr) { - this->list().erase(iter); - base::utils::safeDelete(*iter); - } - } - } - - virtual inline void registerNew(T_Ptr* ptr) ELPP_FINAL { - this->list().push_back(ptr); - } - -/// @brief Gets pointer from repository with speicifed arguments. Arguments are passed to predicate -/// in order to validate pointer. - template - T_Ptr* get(const T& arg1, const T2 arg2) { - iterator iter = std::find_if(this->list().begin(), this->list().end(), Pred(arg1, arg2)); - if (iter != this->list().end() && *iter != nullptr) { - return *iter; - } - return nullptr; - } - - private: - virtual void deepCopy(const AbstractRegistry>& sr) { - for (const_iterator it = sr.list().begin(); it != sr.list().end(); ++it) { - registerNew(new T_Ptr(**it)); - } - } -}; -class Utils { - public: - template - static bool installCallback(const std::string& id, std::unordered_map* mapT) { - if (mapT->find(id) == mapT->end()) { - mapT->insert(std::make_pair(id, TPtr(new T()))); - return true; - } - return false; - } - - template - static void uninstallCallback(const std::string& id, std::unordered_map* mapT) { - if (mapT->find(id) != mapT->end()) { - mapT->erase(id); - } - } - - template - static T* callback(const std::string& id, std::unordered_map* mapT) { - typename std::unordered_map::iterator iter = mapT->find(id); - if (iter != mapT->end()) { - return static_cast(iter->second.get()); - } - return nullptr; - } -}; -} // namespace utils -} // namespace base -/// @brief Base of Easylogging++ friendly class -/// -/// @detail After inheriting this class publicly, implement pure-virtual function `void log(std::ostream&) const` -class Loggable { - public: - virtual ~Loggable(void) {} - virtual void log(el::base::type::ostream_t&) const = 0; - private: - friend inline el::base::type::ostream_t& operator<<(el::base::type::ostream_t& os, const Loggable& loggable) { - loggable.log(os); - return os; - } -}; -namespace base { -/// @brief Represents log format containing flags and date format. This is used internally to start initial log -class LogFormat : public Loggable { - public: - LogFormat(void); - LogFormat(Level level, const base::type::string_t& format); - LogFormat(const LogFormat& logFormat); - LogFormat(LogFormat&& logFormat); - LogFormat& operator=(const LogFormat& logFormat); - virtual ~LogFormat(void) {} - bool operator==(const LogFormat& other); - - /// @brief Updates format to be used while logging. - /// @param userFormat User provided format - void parseFromFormat(const base::type::string_t& userFormat); - - inline Level level(void) const { - return m_level; - } - - inline const base::type::string_t& userFormat(void) const { - return m_userFormat; - } - - inline const base::type::string_t& format(void) const { - return m_format; - } - - inline const std::string& dateTimeFormat(void) const { - return m_dateTimeFormat; - } - - inline base::type::EnumType flags(void) const { - return m_flags; - } - - inline bool hasFlag(base::FormatFlags flag) const { - return base::utils::hasFlag(flag, m_flags); - } - - virtual void log(el::base::type::ostream_t& os) const { - os << m_format; - } - - protected: - /// @brief Updates date time format if available in currFormat. - /// @param index Index where %datetime, %date or %time was found - /// @param [in,out] currFormat current format that is being used to format - virtual void updateDateFormat(std::size_t index, base::type::string_t& currFormat) ELPP_FINAL; - - /// @brief Updates %level from format. This is so that we dont have to do it at log-writing-time. It uses m_format and m_level - virtual void updateFormatSpec(void) ELPP_FINAL; - - inline void addFlag(base::FormatFlags flag) { - base::utils::addFlag(flag, &m_flags); - } - - private: - Level m_level; - base::type::string_t m_userFormat; - base::type::string_t m_format; - std::string m_dateTimeFormat; - base::type::EnumType m_flags; - std::string m_currentUser; - std::string m_currentHost; - friend class el::Logger; // To resolve loggerId format specifier easily -}; -} // namespace base -/// @brief Resolving function for format specifier -typedef std::function FormatSpecifierValueResolver; -/// @brief User-provided custom format specifier -/// @see el::Helpers::installCustomFormatSpecifier -/// @see FormatSpecifierValueResolver -class CustomFormatSpecifier { - public: - CustomFormatSpecifier(const char* formatSpecifier, const FormatSpecifierValueResolver& resolver) : - m_formatSpecifier(formatSpecifier), m_resolver(resolver) {} - inline const char* formatSpecifier(void) const { - return m_formatSpecifier; - } - inline const FormatSpecifierValueResolver& resolver(void) const { - return m_resolver; - } - inline bool operator==(const char* formatSpecifier) { - return strcmp(m_formatSpecifier, formatSpecifier) == 0; - } - - private: - const char* m_formatSpecifier; - FormatSpecifierValueResolver m_resolver; -}; -/// @brief Represents single configuration that has representing level, configuration type and a string based value. -/// -/// @detail String based value means any value either its boolean, integer or string itself, it will be embedded inside quotes -/// and will be parsed later. -/// -/// Consider some examples below: -/// * el::Configuration confEnabledInfo(el::Level::Info, el::ConfigurationType::Enabled, "true"); -/// * el::Configuration confMaxLogFileSizeInfo(el::Level::Info, el::ConfigurationType::MaxLogFileSize, "2048"); -/// * el::Configuration confFilenameInfo(el::Level::Info, el::ConfigurationType::Filename, "/var/log/my.log"); -class Configuration : public Loggable { - public: - Configuration(const Configuration& c); - Configuration& operator=(const Configuration& c); - - virtual ~Configuration(void) { - } - - /// @brief Full constructor used to sets value of configuration - Configuration(Level level, ConfigurationType configurationType, const std::string& value); - - /// @brief Gets level of current configuration - inline Level level(void) const { - return m_level; - } - - /// @brief Gets configuration type of current configuration - inline ConfigurationType configurationType(void) const { - return m_configurationType; - } - - /// @brief Gets string based configuration value - inline const std::string& value(void) const { - return m_value; - } - - /// @brief Set string based configuration value - /// @param value Value to set. Values have to be std::string; For boolean values use "true", "false", for any integral values - /// use them in quotes. They will be parsed when configuring - inline void setValue(const std::string& value) { - m_value = value; - } - - virtual void log(el::base::type::ostream_t& os) const; - - /// @brief Used to find configuration from configuration (pointers) repository. Avoid using it. - class Predicate { - public: - Predicate(Level level, ConfigurationType configurationType); - - bool operator()(const Configuration* conf) const; - - private: - Level m_level; - ConfigurationType m_configurationType; - }; - - private: - Level m_level; - ConfigurationType m_configurationType; - std::string m_value; -}; - -/// @brief Thread-safe Configuration repository -/// -/// @detail This repository represents configurations for all the levels and configuration type mapped to a value. -class Configurations : public base::utils::RegistryWithPred { - public: - /// @brief Default constructor with empty repository - Configurations(void); - - /// @brief Constructor used to set configurations using configuration file. - /// @param configurationFile Full path to configuration file - /// @param useDefaultsForRemaining Lets you set the remaining configurations to default. - /// @param base If provided, this configuration will be based off existing repository that this argument is pointing to. - /// @see parseFromFile(const std::string&, Configurations* base) - /// @see setRemainingToDefault() - Configurations(const std::string& configurationFile, bool useDefaultsForRemaining = true, - Configurations* base = nullptr); - - virtual ~Configurations(void) { - } - - /// @brief Parses configuration from file. - /// @param configurationFile Full path to configuration file - /// @param base Configurations to base new configuration repository off. This value is used when you want to use - /// existing Configurations to base all the values and then set rest of configuration via configuration file. - /// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you - /// do not proceed without successful parse. - bool parseFromFile(const std::string& configurationFile, Configurations* base = nullptr); - - /// @brief Parse configurations from configuration string. - /// - /// @detail This configuration string has same syntax as configuration file contents. Make sure all the necessary - /// new line characters are provided. - /// @param base Configurations to base new configuration repository off. This value is used when you want to use - /// existing Configurations to base all the values and then set rest of configuration via configuration text. - /// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you - /// do not proceed without successful parse. - bool parseFromText(const std::string& configurationsString, Configurations* base = nullptr); - - /// @brief Sets configuration based-off an existing configurations. - /// @param base Pointer to existing configurations. - void setFromBase(Configurations* base); - - /// @brief Determines whether or not specified configuration type exists in the repository. - /// - /// @detail Returns as soon as first level is found. - /// @param configurationType Type of configuration to check existence for. - bool hasConfiguration(ConfigurationType configurationType); - - /// @brief Determines whether or not specified configuration type exists for specified level - /// @param level Level to check - /// @param configurationType Type of configuration to check existence for. - bool hasConfiguration(Level level, ConfigurationType configurationType); - - /// @brief Sets value of configuration for specified level. - /// - /// @detail Any existing configuration for specified level will be replaced. Also note that configuration types - /// ConfigurationType::SubsecondPrecision and ConfigurationType::PerformanceTracking will be ignored if not set for - /// Level::Global because these configurations are not dependant on level. - /// @param level Level to set configuration for (el::Level). - /// @param configurationType Type of configuration (el::ConfigurationType) - /// @param value A string based value. Regardless of what the data type of configuration is, it will always be string - /// from users' point of view. This is then parsed later to be used internally. - /// @see Configuration::setValue(const std::string& value) - /// @see el::Level - /// @see el::ConfigurationType - void set(Level level, ConfigurationType configurationType, const std::string& value); - - /// @brief Sets single configuration based on other single configuration. - /// @see set(Level level, ConfigurationType configurationType, const std::string& value) - void set(Configuration* conf); - - inline Configuration* get(Level level, ConfigurationType configurationType) { - base::threading::ScopedLock scopedLock(lock()); - return RegistryWithPred::get(level, configurationType); - } - - /// @brief Sets configuration for all levels. - /// @param configurationType Type of configuration - /// @param value String based value - /// @see Configurations::set(Level level, ConfigurationType configurationType, const std::string& value) - inline void setGlobally(ConfigurationType configurationType, const std::string& value) { - setGlobally(configurationType, value, false); - } - - /// @brief Clears repository so that all the configurations are unset - inline void clear(void) { - base::threading::ScopedLock scopedLock(lock()); - unregisterAll(); - } - - /// @brief Gets configuration file used in parsing this configurations. - /// - /// @detail If this repository was set manually or by text this returns empty string. - inline const std::string& configurationFile(void) const { - return m_configurationFile; - } - - /// @brief Sets configurations to "factory based" configurations. - void setToDefault(void); - - /// @brief Lets you set the remaining configurations to default. - /// - /// @detail By remaining, it means that the level/type a configuration does not exist for. - /// This function is useful when you want to minimize chances of failures, e.g, if you have a configuration file that sets - /// configuration for all the configurations except for Enabled or not, we use this so that ENABLED is set to default i.e, - /// true. If you dont do this explicitly (either by calling this function or by using second param in Constructor - /// and try to access a value, an error is thrown - void setRemainingToDefault(void); - - /// @brief Parser used internally to parse configurations from file or text. - /// - /// @detail This class makes use of base::utils::Str. - /// You should not need this unless you are working on some tool for Easylogging++ - class Parser : base::StaticClass { - public: - /// @brief Parses configuration from file. - /// @param configurationFile Full path to configuration file - /// @param sender Sender configurations pointer. Usually 'this' is used from calling class - /// @param base Configurations to base new configuration repository off. This value is used when you want to use - /// existing Configurations to base all the values and then set rest of configuration via configuration file. - /// @return True if successfully parsed, false otherwise. You may define '_STOP_ON_FIRSTELPP_ASSERTION' to make sure you - /// do not proceed without successful parse. - static bool parseFromFile(const std::string& configurationFile, Configurations* sender, - Configurations* base = nullptr); - - /// @brief Parse configurations from configuration string. - /// - /// @detail This configuration string has same syntax as configuration file contents. Make sure all the necessary - /// new line characters are provided. You may define '_STOP_ON_FIRSTELPP_ASSERTION' to make sure you - /// do not proceed without successful parse (This is recommended) - /// @param configurationsString the configuration in plain text format - /// @param sender Sender configurations pointer. Usually 'this' is used from calling class - /// @param base Configurations to base new configuration repository off. This value is used when you want to use - /// existing Configurations to base all the values and then set rest of configuration via configuration text. - /// @return True if successfully parsed, false otherwise. - static bool parseFromText(const std::string& configurationsString, Configurations* sender, - Configurations* base = nullptr); - - private: - friend class el::Loggers; - static void ignoreComments(std::string* line); - static bool isLevel(const std::string& line); - static bool isComment(const std::string& line); - static inline bool isConfig(const std::string& line); - static bool parseLine(std::string* line, std::string* currConfigStr, std::string* currLevelStr, Level* currLevel, - Configurations* conf); - }; - - private: - std::string m_configurationFile; - bool m_isFromFile; - friend class el::Loggers; - - /// @brief Unsafely sets configuration if does not already exist - void unsafeSetIfNotExist(Level level, ConfigurationType configurationType, const std::string& value); - - /// @brief Thread unsafe set - void unsafeSet(Level level, ConfigurationType configurationType, const std::string& value); - - /// @brief Sets configurations for all levels including Level::Global if includeGlobalLevel is true - /// @see Configurations::setGlobally(ConfigurationType configurationType, const std::string& value) - void setGlobally(ConfigurationType configurationType, const std::string& value, bool includeGlobalLevel); - - /// @brief Sets configurations (Unsafely) for all levels including Level::Global if includeGlobalLevel is true - /// @see Configurations::setGlobally(ConfigurationType configurationType, const std::string& value) - void unsafeSetGlobally(ConfigurationType configurationType, const std::string& value, bool includeGlobalLevel); -}; - -namespace base { -typedef std::shared_ptr FileStreamPtr; -typedef std::unordered_map LogStreamsReferenceMap; -/// @brief Configurations with data types. -/// -/// @detail el::Configurations have string based values. This is whats used internally in order to read correct configurations. -/// This is to perform faster while writing logs using correct configurations. -/// -/// This is thread safe and final class containing non-virtual destructor (means nothing should inherit this class) -class TypedConfigurations : public base::threading::ThreadSafe { - public: - /// @brief Constructor to initialize (construct) the object off el::Configurations - /// @param configurations Configurations pointer/reference to base this typed configurations off. - /// @param logStreamsReference Use ELPP->registeredLoggers()->logStreamsReference() - TypedConfigurations(Configurations* configurations, base::LogStreamsReferenceMap* logStreamsReference); - - TypedConfigurations(const TypedConfigurations& other); - - virtual ~TypedConfigurations(void) { - } - - const Configurations* configurations(void) const { - return m_configurations; - } - - bool enabled(Level level); - bool toFile(Level level); - const std::string& filename(Level level); - bool toStandardOutput(Level level); - const base::LogFormat& logFormat(Level level); - const base::SubsecondPrecision& subsecondPrecision(Level level = Level::Global); - const base::MillisecondsWidth& millisecondsWidth(Level level = Level::Global); - bool performanceTracking(Level level = Level::Global); - base::type::fstream_t* fileStream(Level level); - std::size_t maxLogFileSize(Level level); - std::size_t logFlushThreshold(Level level); - - private: - Configurations* m_configurations; - std::unordered_map m_enabledMap; - std::unordered_map m_toFileMap; - std::unordered_map m_filenameMap; - std::unordered_map m_toStandardOutputMap; - std::unordered_map m_logFormatMap; - std::unordered_map m_subsecondPrecisionMap; - std::unordered_map m_performanceTrackingMap; - std::unordered_map m_fileStreamMap; - std::unordered_map m_maxLogFileSizeMap; - std::unordered_map m_logFlushThresholdMap; - base::LogStreamsReferenceMap* m_logStreamsReference; - - friend class el::Helpers; - friend class el::base::MessageBuilder; - friend class el::base::Writer; - friend class el::base::DefaultLogDispatchCallback; - friend class el::base::LogDispatcher; - - template - inline Conf_T getConfigByVal(Level level, const std::unordered_map* confMap, const char* confName) { - base::threading::ScopedLock scopedLock(lock()); - return unsafeGetConfigByVal(level, confMap, confName); // This is not unsafe anymore - mutex locked in scope - } - - template - inline Conf_T& getConfigByRef(Level level, std::unordered_map* confMap, const char* confName) { - base::threading::ScopedLock scopedLock(lock()); - return unsafeGetConfigByRef(level, confMap, confName); // This is not unsafe anymore - mutex locked in scope - } - - template - Conf_T unsafeGetConfigByVal(Level level, const std::unordered_map* confMap, const char* confName) { - ELPP_UNUSED(confName); - typename std::unordered_map::const_iterator it = confMap->find(level); - if (it == confMap->end()) { - try { - return confMap->at(Level::Global); - } catch (...) { - ELPP_INTERNAL_ERROR("Unable to get configuration [" << confName << "] for level [" - << LevelHelper::convertToString(level) << "]" - << std::endl << "Please ensure you have properly configured logger.", false); - return Conf_T(); - } - } - return it->second; - } - - template - Conf_T& unsafeGetConfigByRef(Level level, std::unordered_map* confMap, const char* confName) { - ELPP_UNUSED(confName); - typename std::unordered_map::iterator it = confMap->find(level); - if (it == confMap->end()) { - try { - return confMap->at(Level::Global); - } catch (...) { - ELPP_INTERNAL_ERROR("Unable to get configuration [" << confName << "] for level [" - << LevelHelper::convertToString(level) << "]" - << std::endl << "Please ensure you have properly configured logger.", false); - } - } - return it->second; - } - - template - void setValue(Level level, const Conf_T& value, std::unordered_map* confMap, - bool includeGlobalLevel = true) { - // If map is empty and we are allowed to add into generic level (Level::Global), do it! - if (confMap->empty() && includeGlobalLevel) { - confMap->insert(std::make_pair(Level::Global, value)); - return; - } - // If same value exist in generic level already, dont add it to explicit level - typename std::unordered_map::iterator it = confMap->find(Level::Global); - if (it != confMap->end() && it->second == value) { - return; - } - // Now make sure we dont double up values if we really need to add it to explicit level - it = confMap->find(level); - if (it == confMap->end()) { - // Value not found for level, add new - confMap->insert(std::make_pair(level, value)); - } else { - // Value found, just update value - confMap->at(level) = value; - } - } - - void build(Configurations* configurations); - unsigned long getULong(std::string confVal); - std::string resolveFilename(const std::string& filename); - void insertFile(Level level, const std::string& fullFilename); - bool unsafeValidateFileRolling(Level level, const PreRollOutCallback& preRollOutCallback); - - inline bool validateFileRolling(Level level, const PreRollOutCallback& preRollOutCallback) { - base::threading::ScopedLock scopedLock(lock()); - return unsafeValidateFileRolling(level, preRollOutCallback); - } -}; -/// @brief Class that keeps record of current line hit for occasional logging -class HitCounter { - public: - HitCounter(void) : - m_filename(""), - m_lineNumber(0), - m_hitCounts(0) { - } - - HitCounter(const char* filename, base::type::LineNumber lineNumber) : - m_filename(filename), - m_lineNumber(lineNumber), - m_hitCounts(0) { - } - - HitCounter(const HitCounter& hitCounter) : - m_filename(hitCounter.m_filename), - m_lineNumber(hitCounter.m_lineNumber), - m_hitCounts(hitCounter.m_hitCounts) { - } - - HitCounter& operator=(const HitCounter& hitCounter) { - if (&hitCounter != this) { - m_filename = hitCounter.m_filename; - m_lineNumber = hitCounter.m_lineNumber; - m_hitCounts = hitCounter.m_hitCounts; - } - return *this; - } - - virtual ~HitCounter(void) { - } - - /// @brief Resets location of current hit counter - inline void resetLocation(const char* filename, base::type::LineNumber lineNumber) { - m_filename = filename; - m_lineNumber = lineNumber; - } - - /// @brief Validates hit counts and resets it if necessary - inline void validateHitCounts(std::size_t n) { - if (m_hitCounts >= base::consts::kMaxLogPerCounter) { - m_hitCounts = (n >= 1 ? base::consts::kMaxLogPerCounter % n : 0); - } - ++m_hitCounts; - } - - inline const char* filename(void) const { - return m_filename; - } - - inline base::type::LineNumber lineNumber(void) const { - return m_lineNumber; - } - - inline std::size_t hitCounts(void) const { - return m_hitCounts; - } - - inline void increment(void) { - ++m_hitCounts; - } - - class Predicate { - public: - Predicate(const char* filename, base::type::LineNumber lineNumber) - : m_filename(filename), - m_lineNumber(lineNumber) { - } - inline bool operator()(const HitCounter* counter) { - return ((counter != nullptr) && - (strcmp(counter->m_filename, m_filename) == 0) && - (counter->m_lineNumber == m_lineNumber)); - } - - private: - const char* m_filename; - base::type::LineNumber m_lineNumber; - }; - - private: - const char* m_filename; - base::type::LineNumber m_lineNumber; - std::size_t m_hitCounts; -}; -/// @brief Repository for hit counters used across the application -class RegisteredHitCounters : public base::utils::RegistryWithPred { - public: - /// @brief Validates counter for every N, i.e, registers new if does not exist otherwise updates original one - /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned - bool validateEveryN(const char* filename, base::type::LineNumber lineNumber, std::size_t n); - - /// @brief Validates counter for hits >= N, i.e, registers new if does not exist otherwise updates original one - /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned - bool validateAfterN(const char* filename, base::type::LineNumber lineNumber, std::size_t n); - - /// @brief Validates counter for hits are <= n, i.e, registers new if does not exist otherwise updates original one - /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned - bool validateNTimes(const char* filename, base::type::LineNumber lineNumber, std::size_t n); - - /// @brief Gets hit counter registered at specified position - inline const base::HitCounter* getCounter(const char* filename, base::type::LineNumber lineNumber) { - base::threading::ScopedLock scopedLock(lock()); - return get(filename, lineNumber); - } -}; -/// @brief Action to be taken for dispatching -enum class DispatchAction : base::type::EnumType { - None = 1, NormalLog = 2, SysLog = 4 -}; -} // namespace base -template -class Callback : protected base::threading::ThreadSafe { - public: - Callback(void) : m_enabled(true) {} - inline bool enabled(void) const { - return m_enabled; - } - inline void setEnabled(bool enabled) { - base::threading::ScopedLock scopedLock(lock()); - m_enabled = enabled; - } - protected: - virtual void handle(const T* handlePtr) = 0; - private: - bool m_enabled; -}; -class LogDispatchData { - public: - LogDispatchData() : m_logMessage(nullptr), m_dispatchAction(base::DispatchAction::None) {} - inline const LogMessage* logMessage(void) const { - return m_logMessage; - } - inline base::DispatchAction dispatchAction(void) const { - return m_dispatchAction; - } - inline void setLogMessage(LogMessage* logMessage) { - m_logMessage = logMessage; - } - inline void setDispatchAction(base::DispatchAction dispatchAction) { - m_dispatchAction = dispatchAction; - } - private: - LogMessage* m_logMessage; - base::DispatchAction m_dispatchAction; - friend class base::LogDispatcher; - -}; -class LogDispatchCallback : public Callback { - protected: - virtual void handle(const LogDispatchData* data); - base::threading::Mutex& fileHandle(const LogDispatchData* data); - private: - friend class base::LogDispatcher; - std::unordered_map> m_fileLocks; - base::threading::Mutex m_fileLocksMapLock; -}; -class PerformanceTrackingCallback : public Callback { - private: - friend class base::PerformanceTracker; -}; -class LoggerRegistrationCallback : public Callback { - private: - friend class base::RegisteredLoggers; -}; -class LogBuilder : base::NoCopy { - public: - LogBuilder() : m_termSupportsColor(base::utils::OS::termSupportsColor()) {} - virtual ~LogBuilder(void) { - ELPP_INTERNAL_INFO(3, "Destroying log builder...") - } - virtual base::type::string_t build(const LogMessage* logMessage, bool appendNewLine) const = 0; - void convertToColoredOutput(base::type::string_t* logLine, Level level); - private: - bool m_termSupportsColor; - friend class el::base::DefaultLogDispatchCallback; -}; -typedef std::shared_ptr LogBuilderPtr; -/// @brief Represents a logger holding ID and configurations we need to write logs -/// -/// @detail This class does not write logs itself instead its used by writer to read configuations from. -class Logger : public base::threading::ThreadSafe, public Loggable { - public: - Logger(const std::string& id, base::LogStreamsReferenceMap* logStreamsReference); - Logger(const std::string& id, const Configurations& configurations, base::LogStreamsReferenceMap* logStreamsReference); - Logger(const Logger& logger); - Logger& operator=(const Logger& logger); - - virtual ~Logger(void) { - base::utils::safeDelete(m_typedConfigurations); - } - - virtual inline void log(el::base::type::ostream_t& os) const { - os << m_id.c_str(); - } - - /// @brief Configures the logger using specified configurations. - void configure(const Configurations& configurations); - - /// @brief Reconfigures logger using existing configurations - void reconfigure(void); - - inline const std::string& id(void) const { - return m_id; - } - - inline const std::string& parentApplicationName(void) const { - return m_parentApplicationName; - } - - inline void setParentApplicationName(const std::string& parentApplicationName) { - m_parentApplicationName = parentApplicationName; - } - - inline Configurations* configurations(void) { - return &m_configurations; - } - - inline base::TypedConfigurations* typedConfigurations(void) { - return m_typedConfigurations; - } - - static bool isValidId(const std::string& id); - - /// @brief Flushes logger to sync all log files for all levels - void flush(void); - - void flush(Level level, base::type::fstream_t* fs); - - inline bool isFlushNeeded(Level level) { - return ++m_unflushedCount.find(level)->second >= m_typedConfigurations->logFlushThreshold(level); - } - - inline LogBuilder* logBuilder(void) const { - return m_logBuilder.get(); - } - - inline void setLogBuilder(const LogBuilderPtr& logBuilder) { - m_logBuilder = logBuilder; - } - - inline bool enabled(Level level) const { - return m_typedConfigurations->enabled(level); - } - -#if ELPP_VARIADIC_TEMPLATES_SUPPORTED -# define LOGGER_LEVEL_WRITERS_SIGNATURES(FUNCTION_NAME)\ -template \ -inline void FUNCTION_NAME(const char*, const T&, const Args&...);\ -template \ -inline void FUNCTION_NAME(const T&); - - template - inline void verbose(int, const char*, const T&, const Args&...); - - template - inline void verbose(int, const T&); - - LOGGER_LEVEL_WRITERS_SIGNATURES(info) - LOGGER_LEVEL_WRITERS_SIGNATURES(debug) - LOGGER_LEVEL_WRITERS_SIGNATURES(warn) - LOGGER_LEVEL_WRITERS_SIGNATURES(error) - LOGGER_LEVEL_WRITERS_SIGNATURES(fatal) - LOGGER_LEVEL_WRITERS_SIGNATURES(trace) -# undef LOGGER_LEVEL_WRITERS_SIGNATURES -#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED - private: - std::string m_id; - base::TypedConfigurations* m_typedConfigurations; - base::type::stringstream_t m_stream; - std::string m_parentApplicationName; - bool m_isConfigured; - Configurations m_configurations; - std::unordered_map m_unflushedCount; - base::LogStreamsReferenceMap* m_logStreamsReference; - LogBuilderPtr m_logBuilder; - - friend class el::LogMessage; - friend class el::Loggers; - friend class el::Helpers; - friend class el::base::RegisteredLoggers; - friend class el::base::DefaultLogDispatchCallback; - friend class el::base::MessageBuilder; - friend class el::base::Writer; - friend class el::base::PErrorWriter; - friend class el::base::Storage; - friend class el::base::PerformanceTracker; - friend class el::base::LogDispatcher; - - Logger(void); - -#if ELPP_VARIADIC_TEMPLATES_SUPPORTED - template - void log_(Level, int, const char*, const T&, const Args&...); - - template - inline void log_(Level, int, const T&); - - template - void log(Level, const char*, const T&, const Args&...); - - template - inline void log(Level, const T&); -#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED - - void initUnflushedCount(void); - - inline base::type::stringstream_t& stream(void) { - return m_stream; - } - - void resolveLoggerFormatSpec(void) const; -}; -namespace base { -/// @brief Loggers repository -class RegisteredLoggers : public base::utils::Registry { - public: - explicit RegisteredLoggers(const LogBuilderPtr& defaultLogBuilder); - - virtual ~RegisteredLoggers(void) { - unsafeFlushAll(); - } - - inline void setDefaultConfigurations(const Configurations& configurations) { - base::threading::ScopedLock scopedLock(lock()); - m_defaultConfigurations.setFromBase(const_cast(&configurations)); - } - - inline Configurations* defaultConfigurations(void) { - return &m_defaultConfigurations; - } - - Logger* get(const std::string& id, bool forceCreation = true); - - template - inline bool installLoggerRegistrationCallback(const std::string& id) { - return base::utils::Utils::installCallback(id, - &m_loggerRegistrationCallbacks); - } - - template - inline void uninstallLoggerRegistrationCallback(const std::string& id) { - base::utils::Utils::uninstallCallback(id, &m_loggerRegistrationCallbacks); - } - - template - inline T* loggerRegistrationCallback(const std::string& id) { - return base::utils::Utils::callback(id, &m_loggerRegistrationCallbacks); - } - - bool remove(const std::string& id); - - inline bool has(const std::string& id) { - return get(id, false) != nullptr; - } - - inline void unregister(Logger*& logger) { - base::threading::ScopedLock scopedLock(lock()); - base::utils::Registry::unregister(logger->id()); - } - - inline base::LogStreamsReferenceMap* logStreamsReference(void) { - return &m_logStreamsReference; - } - - inline void flushAll(void) { - base::threading::ScopedLock scopedLock(lock()); - unsafeFlushAll(); - } - - inline void setDefaultLogBuilder(LogBuilderPtr& logBuilderPtr) { - base::threading::ScopedLock scopedLock(lock()); - m_defaultLogBuilder = logBuilderPtr; - } - - private: - LogBuilderPtr m_defaultLogBuilder; - Configurations m_defaultConfigurations; - base::LogStreamsReferenceMap m_logStreamsReference; - std::unordered_map m_loggerRegistrationCallbacks; - friend class el::base::Storage; - - void unsafeFlushAll(void); -}; -/// @brief Represents registries for verbose logging -class VRegistry : base::NoCopy, public base::threading::ThreadSafe { - public: - explicit VRegistry(base::type::VerboseLevel level, base::type::EnumType* pFlags); - - /// @brief Sets verbose level. Accepted range is 0-9 - void setLevel(base::type::VerboseLevel level); - - inline base::type::VerboseLevel level(void) const { - return m_level; - } - - inline void clearModules(void) { - base::threading::ScopedLock scopedLock(lock()); - m_modules.clear(); - } - - void setModules(const char* modules); - - bool allowed(base::type::VerboseLevel vlevel, const char* file); - - inline const std::unordered_map& modules(void) const { - return m_modules; - } - - void setFromArgs(const base::utils::CommandLineArgs* commandLineArgs); - - /// @brief Whether or not vModules enabled - inline bool vModulesEnabled(void) { - return !base::utils::hasFlag(LoggingFlag::DisableVModules, *m_pFlags); - } - - private: - base::type::VerboseLevel m_level; - base::type::EnumType* m_pFlags; - std::unordered_map m_modules; -}; -} // namespace base -class LogMessage { - public: - LogMessage(Level level, const std::string& file, base::type::LineNumber line, const std::string& func, - base::type::VerboseLevel verboseLevel, Logger* logger) : - m_level(level), m_file(file), m_line(line), m_func(func), - m_verboseLevel(verboseLevel), m_logger(logger), m_message(logger->stream().str()) { - } - inline Level level(void) const { - return m_level; - } - inline const std::string& file(void) const { - return m_file; - } - inline base::type::LineNumber line(void) const { - return m_line; - } - inline const std::string& func(void) const { - return m_func; - } - inline base::type::VerboseLevel verboseLevel(void) const { - return m_verboseLevel; - } - inline Logger* logger(void) const { - return m_logger; - } - inline const base::type::string_t& message(void) const { - return m_message; - } - private: - Level m_level; - std::string m_file; - base::type::LineNumber m_line; - std::string m_func; - base::type::VerboseLevel m_verboseLevel; - Logger* m_logger; - base::type::string_t m_message; -}; -namespace base { -#if ELPP_ASYNC_LOGGING -class AsyncLogItem { - public: - explicit AsyncLogItem(const LogMessage& logMessage, const LogDispatchData& data, const base::type::string_t& logLine) - : m_logMessage(logMessage), m_dispatchData(data), m_logLine(logLine) {} - virtual ~AsyncLogItem() {} - inline LogMessage* logMessage(void) { - return &m_logMessage; - } - inline LogDispatchData* data(void) { - return &m_dispatchData; - } - inline base::type::string_t logLine(void) { - return m_logLine; - } - private: - LogMessage m_logMessage; - LogDispatchData m_dispatchData; - base::type::string_t m_logLine; -}; -class AsyncLogQueue : public base::threading::ThreadSafe { - public: - virtual ~AsyncLogQueue() { - ELPP_INTERNAL_INFO(6, "~AsyncLogQueue"); - } - - inline AsyncLogItem next(void) { - base::threading::ScopedLock scopedLock(lock()); - AsyncLogItem result = m_queue.front(); - m_queue.pop(); - return result; - } - - inline void push(const AsyncLogItem& item) { - base::threading::ScopedLock scopedLock(lock()); - m_queue.push(item); - } - inline void pop(void) { - base::threading::ScopedLock scopedLock(lock()); - m_queue.pop(); - } - inline AsyncLogItem front(void) { - base::threading::ScopedLock scopedLock(lock()); - return m_queue.front(); - } - inline bool empty(void) { - base::threading::ScopedLock scopedLock(lock()); - return m_queue.empty(); - } - private: - std::queue m_queue; -}; -class IWorker { - public: - virtual ~IWorker() {} - virtual void start() = 0; -}; -#endif // ELPP_ASYNC_LOGGING -/// @brief Easylogging++ management storage -class Storage : base::NoCopy, public base::threading::ThreadSafe { - public: -#if ELPP_ASYNC_LOGGING - Storage(const LogBuilderPtr& defaultLogBuilder, base::IWorker* asyncDispatchWorker); -#else - explicit Storage(const LogBuilderPtr& defaultLogBuilder); -#endif // ELPP_ASYNC_LOGGING - - virtual ~Storage(void); - - inline bool validateEveryNCounter(const char* filename, base::type::LineNumber lineNumber, std::size_t occasion) { - return hitCounters()->validateEveryN(filename, lineNumber, occasion); - } - - inline bool validateAfterNCounter(const char* filename, base::type::LineNumber lineNumber, std::size_t n) { - return hitCounters()->validateAfterN(filename, lineNumber, n); - } - - inline bool validateNTimesCounter(const char* filename, base::type::LineNumber lineNumber, std::size_t n) { - return hitCounters()->validateNTimes(filename, lineNumber, n); - } - - inline base::RegisteredHitCounters* hitCounters(void) const { - return m_registeredHitCounters; - } - - inline base::RegisteredLoggers* registeredLoggers(void) const { - return m_registeredLoggers; - } - - inline base::VRegistry* vRegistry(void) const { - return m_vRegistry; - } - -#if ELPP_ASYNC_LOGGING - inline base::AsyncLogQueue* asyncLogQueue(void) const { - return m_asyncLogQueue; - } -#endif // ELPP_ASYNC_LOGGING - - inline const base::utils::CommandLineArgs* commandLineArgs(void) const { - return &m_commandLineArgs; - } - - inline void addFlag(LoggingFlag flag) { - base::utils::addFlag(flag, &m_flags); - } - - inline void removeFlag(LoggingFlag flag) { - base::utils::removeFlag(flag, &m_flags); - } - - inline bool hasFlag(LoggingFlag flag) const { - return base::utils::hasFlag(flag, m_flags); - } - - inline base::type::EnumType flags(void) const { - return m_flags; - } - - inline void setFlags(base::type::EnumType flags) { - m_flags = flags; - } - - inline void setPreRollOutCallback(const PreRollOutCallback& callback) { - m_preRollOutCallback = callback; - } - - inline void unsetPreRollOutCallback(void) { - m_preRollOutCallback = base::defaultPreRollOutCallback; - } - - inline PreRollOutCallback& preRollOutCallback(void) { - return m_preRollOutCallback; - } - - bool hasCustomFormatSpecifier(const char* formatSpecifier); - void installCustomFormatSpecifier(const CustomFormatSpecifier& customFormatSpecifier); - bool uninstallCustomFormatSpecifier(const char* formatSpecifier); - - const std::vector* customFormatSpecifiers(void) const { - return &m_customFormatSpecifiers; - } - - base::threading::Mutex& customFormatSpecifiersLock() { - return m_customFormatSpecifiersLock; - } - - inline void setLoggingLevel(Level level) { - m_loggingLevel = level; - } - - template - inline bool installLogDispatchCallback(const std::string& id) { - return base::utils::Utils::installCallback(id, &m_logDispatchCallbacks); - } - - template - inline void uninstallLogDispatchCallback(const std::string& id) { - base::utils::Utils::uninstallCallback(id, &m_logDispatchCallbacks); - } - template - inline T* logDispatchCallback(const std::string& id) { - return base::utils::Utils::callback(id, &m_logDispatchCallbacks); - } - -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) - template - inline bool installPerformanceTrackingCallback(const std::string& id) { - return base::utils::Utils::installCallback(id, - &m_performanceTrackingCallbacks); - } - - template - inline void uninstallPerformanceTrackingCallback(const std::string& id) { - base::utils::Utils::uninstallCallback(id, - &m_performanceTrackingCallbacks); - } - - template - inline T* performanceTrackingCallback(const std::string& id) { - return base::utils::Utils::callback(id, &m_performanceTrackingCallbacks); - } -#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) - - /// @brief Sets thread name for current thread. Requires std::thread - inline void setThreadName(const std::string& name) { - if (name.empty()) return; - base::threading::ScopedLock scopedLock(m_threadNamesLock); - m_threadNames[base::threading::getCurrentThreadId()] = name; - } - - inline std::string getThreadName(const std::string& threadId) { - base::threading::ScopedLock scopedLock(m_threadNamesLock); - std::unordered_map::const_iterator it = m_threadNames.find(threadId); - if (it == m_threadNames.end()) { - return threadId; - } - return it->second; - } - private: - base::RegisteredHitCounters* m_registeredHitCounters; - base::RegisteredLoggers* m_registeredLoggers; - base::type::EnumType m_flags; - base::VRegistry* m_vRegistry; -#if ELPP_ASYNC_LOGGING - base::AsyncLogQueue* m_asyncLogQueue; - base::IWorker* m_asyncDispatchWorker; -#endif // ELPP_ASYNC_LOGGING - base::utils::CommandLineArgs m_commandLineArgs; - PreRollOutCallback m_preRollOutCallback; - std::unordered_map m_logDispatchCallbacks; - std::unordered_map m_performanceTrackingCallbacks; - std::unordered_map m_threadNames; - std::vector m_customFormatSpecifiers; - base::threading::Mutex m_customFormatSpecifiersLock; - base::threading::Mutex m_threadNamesLock; - Level m_loggingLevel; - - friend class el::Helpers; - friend class el::base::DefaultLogDispatchCallback; - friend class el::LogBuilder; - friend class el::base::MessageBuilder; - friend class el::base::Writer; - friend class el::base::PerformanceTracker; - friend class el::base::LogDispatcher; - - void setApplicationArguments(int argc, char** argv); - - inline void setApplicationArguments(int argc, const char** argv) { - setApplicationArguments(argc, const_cast(argv)); - } -}; -extern ELPP_EXPORT base::type::StoragePointer elStorage; -#define ELPP el::base::elStorage -class DefaultLogDispatchCallback : public LogDispatchCallback { - protected: - void handle(const LogDispatchData* data); - private: - const LogDispatchData* m_data; - void dispatch(base::type::string_t&& logLine); -}; -#if ELPP_ASYNC_LOGGING -class AsyncLogDispatchCallback : public LogDispatchCallback { - protected: - void handle(const LogDispatchData* data); -}; -class AsyncDispatchWorker : public base::IWorker, public base::threading::ThreadSafe { - public: - AsyncDispatchWorker(); - virtual ~AsyncDispatchWorker(); - - bool clean(void); - void emptyQueue(void); - virtual void start(void); - void handle(AsyncLogItem* logItem); - void run(void); - - void setContinueRunning(bool value) { - base::threading::ScopedLock scopedLock(m_continueRunningLock); - m_continueRunning = value; - } - - bool continueRunning(void) const { - return m_continueRunning; - } - private: - std::condition_variable cv; - bool m_continueRunning; - base::threading::Mutex m_continueRunningLock; -}; -#endif // ELPP_ASYNC_LOGGING -} // namespace base -namespace base { -class DefaultLogBuilder : public LogBuilder { - public: - base::type::string_t build(const LogMessage* logMessage, bool appendNewLine) const; -}; -/// @brief Dispatches log messages -class LogDispatcher : base::NoCopy { - public: - LogDispatcher(bool proceed, LogMessage* logMessage, base::DispatchAction dispatchAction) : - m_proceed(proceed), - m_logMessage(logMessage), - m_dispatchAction(std::move(dispatchAction)) { - } - - void dispatch(void); - - private: - bool m_proceed; - LogMessage* m_logMessage; - base::DispatchAction m_dispatchAction; -}; -#if defined(ELPP_STL_LOGGING) -/// @brief Workarounds to write some STL logs -/// -/// @detail There is workaround needed to loop through some stl containers. In order to do that, we need iterable containers -/// of same type and provide iterator interface and pass it on to writeIterator(). -/// Remember, this is passed by value in constructor so that we dont change original containers. -/// This operation is as expensive as Big-O(std::min(class_.size(), base::consts::kMaxLogPerContainer)) -namespace workarounds { -/// @brief Abstract IterableContainer template that provides interface for iterable classes of type T -template -class IterableContainer { - public: - typedef typename Container::iterator iterator; - typedef typename Container::const_iterator const_iterator; - IterableContainer(void) {} - virtual ~IterableContainer(void) {} - iterator begin(void) { - return getContainer().begin(); - } - iterator end(void) { - return getContainer().end(); - } - private: - virtual Container& getContainer(void) = 0; -}; -/// @brief Implements IterableContainer and provides iterable std::priority_queue class -template, typename Comparator = std::less> -class IterablePriorityQueue : public IterableContainer, - public std::priority_queue { - public: - IterablePriorityQueue(std::priority_queue queue_) { - std::size_t count_ = 0; - while (++count_ < base::consts::kMaxLogPerContainer && !queue_.empty()) { - this->push(queue_.top()); - queue_.pop(); - } - } - private: - inline Container& getContainer(void) { - return this->c; - } -}; -/// @brief Implements IterableContainer and provides iterable std::queue class -template> -class IterableQueue : public IterableContainer, public std::queue { - public: - IterableQueue(std::queue queue_) { - std::size_t count_ = 0; - while (++count_ < base::consts::kMaxLogPerContainer && !queue_.empty()) { - this->push(queue_.front()); - queue_.pop(); - } - } - private: - inline Container& getContainer(void) { - return this->c; - } -}; -/// @brief Implements IterableContainer and provides iterable std::stack class -template> -class IterableStack : public IterableContainer, public std::stack { - public: - IterableStack(std::stack stack_) { - std::size_t count_ = 0; - while (++count_ < base::consts::kMaxLogPerContainer && !stack_.empty()) { - this->push(stack_.top()); - stack_.pop(); - } - } - private: - inline Container& getContainer(void) { - return this->c; - } -}; -} // namespace workarounds -#endif // defined(ELPP_STL_LOGGING) -// Log message builder -class MessageBuilder { - public: - MessageBuilder(void) : m_logger(nullptr), m_containerLogSeperator(ELPP_LITERAL("")) {} - void initialize(Logger* logger); - -# define ELPP_SIMPLE_LOG(LOG_TYPE)\ -MessageBuilder& operator<<(LOG_TYPE msg) {\ -m_logger->stream() << msg;\ -if (ELPP->hasFlag(LoggingFlag::AutoSpacing)) {\ -m_logger->stream() << " ";\ -}\ -return *this;\ -} - - inline MessageBuilder& operator<<(const std::string& msg) { - return operator<<(msg.c_str()); - } - ELPP_SIMPLE_LOG(char) - ELPP_SIMPLE_LOG(bool) - ELPP_SIMPLE_LOG(signed short) - ELPP_SIMPLE_LOG(unsigned short) - ELPP_SIMPLE_LOG(signed int) - ELPP_SIMPLE_LOG(unsigned int) - ELPP_SIMPLE_LOG(signed long) - ELPP_SIMPLE_LOG(unsigned long) - ELPP_SIMPLE_LOG(float) - ELPP_SIMPLE_LOG(double) - ELPP_SIMPLE_LOG(char*) - ELPP_SIMPLE_LOG(const char*) - ELPP_SIMPLE_LOG(const void*) - ELPP_SIMPLE_LOG(long double) - inline MessageBuilder& operator<<(const std::wstring& msg) { - return operator<<(msg.c_str()); - } - MessageBuilder& operator<<(const wchar_t* msg); - // ostream manipulators - inline MessageBuilder& operator<<(std::ostream& (*OStreamMani)(std::ostream&)) { - m_logger->stream() << OStreamMani; - return *this; - } -#define ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(temp) \ -template \ -inline MessageBuilder& operator<<(const temp& template_inst) { \ -return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ -} -#define ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(temp) \ -template \ -inline MessageBuilder& operator<<(const temp& template_inst) { \ -return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ -} -#define ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(temp) \ -template \ -inline MessageBuilder& operator<<(const temp& template_inst) { \ -return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ -} -#define ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(temp) \ -template \ -inline MessageBuilder& operator<<(const temp& template_inst) { \ -return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ -} -#define ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(temp) \ -template \ -inline MessageBuilder& operator<<(const temp& template_inst) { \ -return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ -} - -#if defined(ELPP_STL_LOGGING) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::vector) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::list) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::deque) - ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(std::set) - ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(std::multiset) - ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::map) - ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::multimap) - template - inline MessageBuilder& operator<<(const std::queue& queue_) { - base::workarounds::IterableQueue iterableQueue_ = - static_cast >(queue_); - return writeIterator(iterableQueue_.begin(), iterableQueue_.end(), iterableQueue_.size()); - } - template - inline MessageBuilder& operator<<(const std::stack& stack_) { - base::workarounds::IterableStack iterableStack_ = - static_cast >(stack_); - return writeIterator(iterableStack_.begin(), iterableStack_.end(), iterableStack_.size()); - } - template - inline MessageBuilder& operator<<(const std::priority_queue& priorityQueue_) { - base::workarounds::IterablePriorityQueue iterablePriorityQueue_ = - static_cast >(priorityQueue_); - return writeIterator(iterablePriorityQueue_.begin(), iterablePriorityQueue_.end(), iterablePriorityQueue_.size()); - } - template - MessageBuilder& operator<<(const std::pair& pair_) { - m_logger->stream() << ELPP_LITERAL("("); - operator << (static_cast(pair_.first)); - m_logger->stream() << ELPP_LITERAL(", "); - operator << (static_cast(pair_.second)); - m_logger->stream() << ELPP_LITERAL(")"); - return *this; - } - template - MessageBuilder& operator<<(const std::bitset& bitset_) { - m_logger->stream() << ELPP_LITERAL("["); - operator << (bitset_.to_string()); - m_logger->stream() << ELPP_LITERAL("]"); - return *this; - } -# if defined(ELPP_LOG_STD_ARRAY) - template - inline MessageBuilder& operator<<(const std::array& array) { - return writeIterator(array.begin(), array.end(), array.size()); - } -# endif // defined(ELPP_LOG_STD_ARRAY) -# if defined(ELPP_LOG_UNORDERED_MAP) - ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(std::unordered_map) - ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(std::unordered_multimap) -# endif // defined(ELPP_LOG_UNORDERED_MAP) -# if defined(ELPP_LOG_UNORDERED_SET) - ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::unordered_set) - ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::unordered_multiset) -# endif // defined(ELPP_LOG_UNORDERED_SET) -#endif // defined(ELPP_STL_LOGGING) -#if defined(ELPP_QT_LOGGING) - inline MessageBuilder& operator<<(const QString& msg) { -# if defined(ELPP_UNICODE) - m_logger->stream() << msg.toStdWString(); -# else - m_logger->stream() << msg.toStdString(); -# endif // defined(ELPP_UNICODE) - return *this; - } - inline MessageBuilder& operator<<(const QByteArray& msg) { - return operator << (QString(msg)); - } - inline MessageBuilder& operator<<(const QStringRef& msg) { - return operator<<(msg.toString()); - } - inline MessageBuilder& operator<<(qint64 msg) { -# if defined(ELPP_UNICODE) - m_logger->stream() << QString::number(msg).toStdWString(); -# else - m_logger->stream() << QString::number(msg).toStdString(); -# endif // defined(ELPP_UNICODE) - return *this; - } - inline MessageBuilder& operator<<(quint64 msg) { -# if defined(ELPP_UNICODE) - m_logger->stream() << QString::number(msg).toStdWString(); -# else - m_logger->stream() << QString::number(msg).toStdString(); -# endif // defined(ELPP_UNICODE) - return *this; - } - inline MessageBuilder& operator<<(QChar msg) { - m_logger->stream() << msg.toLatin1(); - return *this; - } - inline MessageBuilder& operator<<(const QLatin1String& msg) { - m_logger->stream() << msg.latin1(); - return *this; - } - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QList) - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QVector) - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QQueue) - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QSet) - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QLinkedList) - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QStack) - template - MessageBuilder& operator<<(const QPair& pair_) { - m_logger->stream() << ELPP_LITERAL("("); - operator << (static_cast(pair_.first)); - m_logger->stream() << ELPP_LITERAL(", "); - operator << (static_cast(pair_.second)); - m_logger->stream() << ELPP_LITERAL(")"); - return *this; - } - template - MessageBuilder& operator<<(const QMap& map_) { - m_logger->stream() << ELPP_LITERAL("["); - QList keys = map_.keys(); - typename QList::const_iterator begin = keys.begin(); - typename QList::const_iterator end = keys.end(); - int max_ = static_cast(base::consts::kMaxLogPerContainer); // to prevent warning - for (int index_ = 0; begin != end && index_ < max_; ++index_, ++begin) { - m_logger->stream() << ELPP_LITERAL("("); - operator << (static_cast(*begin)); - m_logger->stream() << ELPP_LITERAL(", "); - operator << (static_cast(map_.value(*begin))); - m_logger->stream() << ELPP_LITERAL(")"); - m_logger->stream() << ((index_ < keys.size() -1) ? m_containerLogSeperator : ELPP_LITERAL("")); - } - if (begin != end) { - m_logger->stream() << ELPP_LITERAL("..."); - } - m_logger->stream() << ELPP_LITERAL("]"); - return *this; - } - template - inline MessageBuilder& operator<<(const QMultiMap& map_) { - operator << (static_cast>(map_)); - return *this; - } - template - MessageBuilder& operator<<(const QHash& hash_) { - m_logger->stream() << ELPP_LITERAL("["); - QList keys = hash_.keys(); - typename QList::const_iterator begin = keys.begin(); - typename QList::const_iterator end = keys.end(); - int max_ = static_cast(base::consts::kMaxLogPerContainer); // prevent type warning - for (int index_ = 0; begin != end && index_ < max_; ++index_, ++begin) { - m_logger->stream() << ELPP_LITERAL("("); - operator << (static_cast(*begin)); - m_logger->stream() << ELPP_LITERAL(", "); - operator << (static_cast(hash_.value(*begin))); - m_logger->stream() << ELPP_LITERAL(")"); - m_logger->stream() << ((index_ < keys.size() -1) ? m_containerLogSeperator : ELPP_LITERAL("")); - } - if (begin != end) { - m_logger->stream() << ELPP_LITERAL("..."); - } - m_logger->stream() << ELPP_LITERAL("]"); - return *this; - } - template - inline MessageBuilder& operator<<(const QMultiHash& multiHash_) { - operator << (static_cast>(multiHash_)); - return *this; - } -#endif // defined(ELPP_QT_LOGGING) -#if defined(ELPP_BOOST_LOGGING) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::vector) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::stable_vector) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::list) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::deque) - ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(boost::container::map) - ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(boost::container::flat_map) - ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(boost::container::set) - ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(boost::container::flat_set) -#endif // defined(ELPP_BOOST_LOGGING) - - /// @brief Macro used internally that can be used externally to make containers easylogging++ friendly - /// - /// @detail This macro expands to write an ostream& operator<< for container. This container is expected to - /// have begin() and end() methods that return respective iterators - /// @param ContainerType Type of container e.g, MyList from WX_DECLARE_LIST(int, MyList); in wxwidgets - /// @param SizeMethod Method used to get size of container. - /// @param ElementInstance Instance of element to be fed out. Insance name is "elem". See WXELPP_ENABLED macro - /// for an example usage -#define MAKE_CONTAINERELPP_FRIENDLY(ContainerType, SizeMethod, ElementInstance) \ -el::base::type::ostream_t& operator<<(el::base::type::ostream_t& ss, const ContainerType& container) {\ -const el::base::type::char_t* sep = ELPP->hasFlag(el::LoggingFlag::NewLineForContainer) ? \ -ELPP_LITERAL("\n ") : ELPP_LITERAL(", ");\ -ContainerType::const_iterator elem = container.begin();\ -ContainerType::const_iterator endElem = container.end();\ -std::size_t size_ = container.SizeMethod; \ -ss << ELPP_LITERAL("[");\ -for (std::size_t i = 0; elem != endElem && i < el::base::consts::kMaxLogPerContainer; ++i, ++elem) { \ -ss << ElementInstance;\ -ss << ((i < size_ - 1) ? sep : ELPP_LITERAL(""));\ -}\ -if (elem != endElem) {\ -ss << ELPP_LITERAL("...");\ -}\ -ss << ELPP_LITERAL("]");\ -return ss;\ -} -#if defined(ELPP_WXWIDGETS_LOGGING) - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(wxVector) -# define ELPP_WX_PTR_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), *(*elem)) -# define ELPP_WX_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), (*elem)) -# define ELPP_WX_HASH_MAP_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), \ -ELPP_LITERAL("(") << elem->first << ELPP_LITERAL(", ") << elem->second << ELPP_LITERAL(")") -#else -# define ELPP_WX_PTR_ENABLED(ContainerType) -# define ELPP_WX_ENABLED(ContainerType) -# define ELPP_WX_HASH_MAP_ENABLED(ContainerType) -#endif // defined(ELPP_WXWIDGETS_LOGGING) - // Other classes - template - ELPP_SIMPLE_LOG(const Class&) -#undef ELPP_SIMPLE_LOG -#undef ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG -#undef ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG -#undef ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG -#undef ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG -#undef ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG - private: - Logger* m_logger; - const base::type::char_t* m_containerLogSeperator; - - template - MessageBuilder& writeIterator(Iterator begin_, Iterator end_, std::size_t size_) { - m_logger->stream() << ELPP_LITERAL("["); - for (std::size_t i = 0; begin_ != end_ && i < base::consts::kMaxLogPerContainer; ++i, ++begin_) { - operator << (*begin_); - m_logger->stream() << ((i < size_ - 1) ? m_containerLogSeperator : ELPP_LITERAL("")); - } - if (begin_ != end_) { - m_logger->stream() << ELPP_LITERAL("..."); - } - m_logger->stream() << ELPP_LITERAL("]"); - if (ELPP->hasFlag(LoggingFlag::AutoSpacing)) { - m_logger->stream() << " "; - } - return *this; - } -}; -/// @brief Writes nothing - Used when certain log is disabled -class NullWriter : base::NoCopy { - public: - NullWriter(void) {} - - // Null manipulator - inline NullWriter& operator<<(std::ostream& (*)(std::ostream&)) { - return *this; - } - - template - inline NullWriter& operator<<(const T&) { - return *this; - } - - inline operator bool() { - return true; - } -}; -/// @brief Main entry point of each logging -class Writer : base::NoCopy { - public: - Writer(Level level, const char* file, base::type::LineNumber line, - const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog, - base::type::VerboseLevel verboseLevel = 0) : - m_msg(nullptr), m_level(level), m_file(file), m_line(line), m_func(func), m_verboseLevel(verboseLevel), - m_logger(nullptr), m_proceed(false), m_dispatchAction(dispatchAction) { - } - - Writer(LogMessage* msg, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog) : - m_msg(msg), m_level(msg != nullptr ? msg->level() : Level::Unknown), - m_line(0), m_logger(nullptr), m_proceed(false), m_dispatchAction(dispatchAction) { - } - - virtual ~Writer(void) { - processDispatch(); - } - - template - inline Writer& operator<<(const T& log) { -#if ELPP_LOGGING_ENABLED - if (m_proceed) { - m_messageBuilder << log; - } -#endif // ELPP_LOGGING_ENABLED - return *this; - } - - inline Writer& operator<<(std::ostream& (*log)(std::ostream&)) { -#if ELPP_LOGGING_ENABLED - if (m_proceed) { - m_messageBuilder << log; - } -#endif // ELPP_LOGGING_ENABLED - return *this; - } - - inline operator bool() { - return true; - } - - Writer& construct(Logger* logger, bool needLock = true); - Writer& construct(int count, const char* loggerIds, ...); - protected: - LogMessage* m_msg; - Level m_level; - const char* m_file; - const base::type::LineNumber m_line; - const char* m_func; - base::type::VerboseLevel m_verboseLevel; - Logger* m_logger; - bool m_proceed; - base::MessageBuilder m_messageBuilder; - base::DispatchAction m_dispatchAction; - std::vector m_loggerIds; - friend class el::Helpers; - - void initializeLogger(const std::string& loggerId, bool lookup = true, bool needLock = true); - void processDispatch(); - void triggerDispatch(void); -}; -class PErrorWriter : public base::Writer { - public: - PErrorWriter(Level level, const char* file, base::type::LineNumber line, - const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog, - base::type::VerboseLevel verboseLevel = 0) : - base::Writer(level, file, line, func, dispatchAction, verboseLevel) { - } - - virtual ~PErrorWriter(void); -}; -} // namespace base -// Logging from Logger class. Why this is here? Because we have Storage and Writer class available -#if ELPP_VARIADIC_TEMPLATES_SUPPORTED -template -void Logger::log_(Level level, int vlevel, const char* s, const T& value, const Args&... args) { - base::MessageBuilder b; - b.initialize(this); - while (*s) { - if (*s == base::consts::kFormatSpecifierChar) { - if (*(s + 1) == base::consts::kFormatSpecifierChar) { - ++s; - } else { - if (*(s + 1) == base::consts::kFormatSpecifierCharValue) { - ++s; - b << value; - log_(level, vlevel, ++s, args...); - return; - } - } - } - b << *s++; - } - ELPP_INTERNAL_ERROR("Too many arguments provided. Unable to handle. Please provide more format specifiers", false); -} -template -void Logger::log_(Level level, int vlevel, const T& log) { - if (level == Level::Verbose) { - if (ELPP->vRegistry()->allowed(vlevel, __FILE__)) { - base::Writer(Level::Verbose, "FILE", 0, "FUNCTION", - base::DispatchAction::NormalLog, vlevel).construct(this, false) << log; - } else { - stream().str(ELPP_LITERAL("")); - releaseLock(); - } - } else { - base::Writer(level, "FILE", 0, "FUNCTION").construct(this, false) << log; - } -} -template -inline void Logger::log(Level level, const char* s, const T& value, const Args&... args) { - acquireLock(); // released in Writer! - log_(level, 0, s, value, args...); -} -template -inline void Logger::log(Level level, const T& log) { - acquireLock(); // released in Writer! - log_(level, 0, log); -} -# if ELPP_VERBOSE_LOG -template -inline void Logger::verbose(int vlevel, const char* s, const T& value, const Args&... args) { - acquireLock(); // released in Writer! - log_(el::Level::Verbose, vlevel, s, value, args...); -} -template -inline void Logger::verbose(int vlevel, const T& log) { - acquireLock(); // released in Writer! - log_(el::Level::Verbose, vlevel, log); -} -# else -template -inline void Logger::verbose(int, const char*, const T&, const Args&...) { - return; -} -template -inline void Logger::verbose(int, const T&) { - return; -} -# endif // ELPP_VERBOSE_LOG -# define LOGGER_LEVEL_WRITERS(FUNCTION_NAME, LOG_LEVEL)\ -template \ -inline void Logger::FUNCTION_NAME(const char* s, const T& value, const Args&... args) {\ -log(LOG_LEVEL, s, value, args...);\ -}\ -template \ -inline void Logger::FUNCTION_NAME(const T& value) {\ -log(LOG_LEVEL, value);\ -} -# define LOGGER_LEVEL_WRITERS_DISABLED(FUNCTION_NAME, LOG_LEVEL)\ -template \ -inline void Logger::FUNCTION_NAME(const char*, const T&, const Args&...) {\ -return;\ -}\ -template \ -inline void Logger::FUNCTION_NAME(const T&) {\ -return;\ -} - -# if ELPP_INFO_LOG -LOGGER_LEVEL_WRITERS(info, Level::Info) -# else -LOGGER_LEVEL_WRITERS_DISABLED(info, Level::Info) -# endif // ELPP_INFO_LOG -# if ELPP_DEBUG_LOG -LOGGER_LEVEL_WRITERS(debug, Level::Debug) -# else -LOGGER_LEVEL_WRITERS_DISABLED(debug, Level::Debug) -# endif // ELPP_DEBUG_LOG -# if ELPP_WARNING_LOG -LOGGER_LEVEL_WRITERS(warn, Level::Warning) -# else -LOGGER_LEVEL_WRITERS_DISABLED(warn, Level::Warning) -# endif // ELPP_WARNING_LOG -# if ELPP_ERROR_LOG -LOGGER_LEVEL_WRITERS(error, Level::Error) -# else -LOGGER_LEVEL_WRITERS_DISABLED(error, Level::Error) -# endif // ELPP_ERROR_LOG -# if ELPP_FATAL_LOG -LOGGER_LEVEL_WRITERS(fatal, Level::Fatal) -# else -LOGGER_LEVEL_WRITERS_DISABLED(fatal, Level::Fatal) -# endif // ELPP_FATAL_LOG -# if ELPP_TRACE_LOG -LOGGER_LEVEL_WRITERS(trace, Level::Trace) -# else -LOGGER_LEVEL_WRITERS_DISABLED(trace, Level::Trace) -# endif // ELPP_TRACE_LOG -# undef LOGGER_LEVEL_WRITERS -# undef LOGGER_LEVEL_WRITERS_DISABLED -#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED -#if ELPP_COMPILER_MSVC -# define ELPP_VARIADIC_FUNC_MSVC(variadicFunction, variadicArgs) variadicFunction variadicArgs -# define ELPP_VARIADIC_FUNC_MSVC_RUN(variadicFunction, ...) ELPP_VARIADIC_FUNC_MSVC(variadicFunction, (__VA_ARGS__)) -# define el_getVALength(...) ELPP_VARIADIC_FUNC_MSVC_RUN(el_resolveVALength, 0, ## __VA_ARGS__,\ -10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) -#else -# if ELPP_COMPILER_CLANG -# define el_getVALength(...) el_resolveVALength(0, __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) -# else -# define el_getVALength(...) el_resolveVALength(0, ## __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) -# endif // ELPP_COMPILER_CLANG -#endif // ELPP_COMPILER_MSVC -#define el_resolveVALength(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N -#define ELPP_WRITE_LOG(writer, level, dispatchAction, ...) \ -writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#define ELPP_WRITE_LOG_IF(writer, condition, level, dispatchAction, ...) if (condition) \ -writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#define ELPP_WRITE_LOG_EVERY_N(writer, occasion, level, dispatchAction, ...) \ -ELPP->validateEveryNCounter(__FILE__, __LINE__, occasion) && \ -writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#define ELPP_WRITE_LOG_AFTER_N(writer, n, level, dispatchAction, ...) \ -ELPP->validateAfterNCounter(__FILE__, __LINE__, n) && \ -writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#define ELPP_WRITE_LOG_N_TIMES(writer, n, level, dispatchAction, ...) \ -ELPP->validateNTimesCounter(__FILE__, __LINE__, n) && \ -writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) -class PerformanceTrackingData { - public: - enum class DataType : base::type::EnumType { - Checkpoint = 1, Complete = 2 - }; - // Do not use constructor, will run into multiple definition error, use init(PerformanceTracker*) - explicit PerformanceTrackingData(DataType dataType) : m_performanceTracker(nullptr), - m_dataType(dataType), m_firstCheckpoint(false), m_file(""), m_line(0), m_func("") {} - inline const std::string* blockName(void) const; - inline const struct timeval* startTime(void) const; - inline const struct timeval* endTime(void) const; - inline const struct timeval* lastCheckpointTime(void) const; - inline const base::PerformanceTracker* performanceTracker(void) const { - return m_performanceTracker; - } - inline PerformanceTrackingData::DataType dataType(void) const { - return m_dataType; - } - inline bool firstCheckpoint(void) const { - return m_firstCheckpoint; - } - inline std::string checkpointId(void) const { - return m_checkpointId; - } - inline const char* file(void) const { - return m_file; - } - inline base::type::LineNumber line(void) const { - return m_line; - } - inline const char* func(void) const { - return m_func; - } - inline const base::type::string_t* formattedTimeTaken() const { - return &m_formattedTimeTaken; - } - inline const std::string& loggerId(void) const; - private: - base::PerformanceTracker* m_performanceTracker; - base::type::string_t m_formattedTimeTaken; - PerformanceTrackingData::DataType m_dataType; - bool m_firstCheckpoint; - std::string m_checkpointId; - const char* m_file; - base::type::LineNumber m_line; - const char* m_func; - inline void init(base::PerformanceTracker* performanceTracker, bool firstCheckpoint = false) { - m_performanceTracker = performanceTracker; - m_firstCheckpoint = firstCheckpoint; - } - - friend class el::base::PerformanceTracker; -}; -namespace base { -/// @brief Represents performanceTracker block of code that conditionally adds performance status to log -/// either when goes outside the scope of when checkpoint() is called -class PerformanceTracker : public base::threading::ThreadSafe, public Loggable { - public: - PerformanceTracker(const std::string& blockName, - base::TimestampUnit timestampUnit = base::TimestampUnit::Millisecond, - const std::string& loggerId = std::string(el::base::consts::kPerformanceLoggerId), - bool scopedLog = true, Level level = base::consts::kPerformanceTrackerDefaultLevel); - /// @brief Copy constructor - PerformanceTracker(const PerformanceTracker& t) : - m_blockName(t.m_blockName), m_timestampUnit(t.m_timestampUnit), m_loggerId(t.m_loggerId), m_scopedLog(t.m_scopedLog), - m_level(t.m_level), m_hasChecked(t.m_hasChecked), m_lastCheckpointId(t.m_lastCheckpointId), m_enabled(t.m_enabled), - m_startTime(t.m_startTime), m_endTime(t.m_endTime), m_lastCheckpointTime(t.m_lastCheckpointTime) { - } - virtual ~PerformanceTracker(void); - /// @brief A checkpoint for current performanceTracker block. - void checkpoint(const std::string& id = std::string(), const char* file = __FILE__, - base::type::LineNumber line = __LINE__, - const char* func = ""); - inline Level level(void) const { - return m_level; - } - private: - std::string m_blockName; - base::TimestampUnit m_timestampUnit; - std::string m_loggerId; - bool m_scopedLog; - Level m_level; - bool m_hasChecked; - std::string m_lastCheckpointId; - bool m_enabled; - struct timeval m_startTime, m_endTime, m_lastCheckpointTime; - - PerformanceTracker(void); - - friend class el::PerformanceTrackingData; - friend class base::DefaultPerformanceTrackingCallback; - - const inline base::type::string_t getFormattedTimeTaken() const { - return getFormattedTimeTaken(m_startTime); - } - - const base::type::string_t getFormattedTimeTaken(struct timeval startTime) const; - - virtual inline void log(el::base::type::ostream_t& os) const { - os << getFormattedTimeTaken(); - } -}; -class DefaultPerformanceTrackingCallback : public PerformanceTrackingCallback { - protected: - void handle(const PerformanceTrackingData* data) { - m_data = data; - base::type::stringstream_t ss; - if (m_data->dataType() == PerformanceTrackingData::DataType::Complete) { - ss << ELPP_LITERAL("Executed [") << m_data->blockName()->c_str() << ELPP_LITERAL("] in [") << - *m_data->formattedTimeTaken() << ELPP_LITERAL("]"); - } else { - ss << ELPP_LITERAL("Performance checkpoint"); - if (!m_data->checkpointId().empty()) { - ss << ELPP_LITERAL(" [") << m_data->checkpointId().c_str() << ELPP_LITERAL("]"); - } - ss << ELPP_LITERAL(" for block [") << m_data->blockName()->c_str() << ELPP_LITERAL("] : [") << - *m_data->performanceTracker(); - if (!ELPP->hasFlag(LoggingFlag::DisablePerformanceTrackingCheckpointComparison) - && m_data->performanceTracker()->m_hasChecked) { - ss << ELPP_LITERAL(" ([") << *m_data->formattedTimeTaken() << ELPP_LITERAL("] from "); - if (m_data->performanceTracker()->m_lastCheckpointId.empty()) { - ss << ELPP_LITERAL("last checkpoint"); - } else { - ss << ELPP_LITERAL("checkpoint '") << m_data->performanceTracker()->m_lastCheckpointId.c_str() << ELPP_LITERAL("'"); - } - ss << ELPP_LITERAL(")]"); - } else { - ss << ELPP_LITERAL("]"); - } - } - el::base::Writer(m_data->performanceTracker()->level(), m_data->file(), m_data->line(), m_data->func()).construct(1, - m_data->loggerId().c_str()) << ss.str(); - } - private: - const PerformanceTrackingData* m_data; -}; -} // namespace base -inline const std::string* PerformanceTrackingData::blockName() const { - return const_cast(&m_performanceTracker->m_blockName); -} -inline const struct timeval* PerformanceTrackingData::startTime() const { - return const_cast(&m_performanceTracker->m_startTime); -} -inline const struct timeval* PerformanceTrackingData::endTime() const { - return const_cast(&m_performanceTracker->m_endTime); -} -inline const struct timeval* PerformanceTrackingData::lastCheckpointTime() const { - return const_cast(&m_performanceTracker->m_lastCheckpointTime); -} -inline const std::string& PerformanceTrackingData::loggerId(void) const { - return m_performanceTracker->m_loggerId; -} -#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) -namespace base { -/// @brief Contains some internal debugging tools like crash handler and stack tracer -namespace debug { -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) -class StackTrace : base::NoCopy { - public: - static const unsigned int kMaxStack = 64; - static const unsigned int kStackStart = 2; // We want to skip c'tor and StackTrace::generateNew() - class StackTraceEntry { - public: - StackTraceEntry(std::size_t index, const std::string& loc, const std::string& demang, const std::string& hex, - const std::string& addr); - StackTraceEntry(std::size_t index, const std::string& loc) : - m_index(index), - m_location(loc) { - } - std::size_t m_index; - std::string m_location; - std::string m_demangled; - std::string m_hex; - std::string m_addr; - friend std::ostream& operator<<(std::ostream& ss, const StackTraceEntry& si); - - private: - StackTraceEntry(void); - }; - - StackTrace(void) { - generateNew(); - } - - virtual ~StackTrace(void) { - } - - inline std::vector& getLatestStack(void) { - return m_stack; - } - - friend std::ostream& operator<<(std::ostream& os, const StackTrace& st); - - private: - std::vector m_stack; - - void generateNew(void); -}; -/// @brief Handles unexpected crashes -class CrashHandler : base::NoCopy { - public: - typedef void (*Handler)(int); - - explicit CrashHandler(bool useDefault); - explicit CrashHandler(const Handler& cHandler) { - setHandler(cHandler); - } - void setHandler(const Handler& cHandler); - - private: - Handler m_handler; -}; -#else -class CrashHandler { - public: - explicit CrashHandler(bool) {} -}; -#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) -} // namespace debug -} // namespace base -extern base::debug::CrashHandler elCrashHandler; -#define MAKE_LOGGABLE(ClassType, ClassInstance, OutputStreamInstance) \ -el::base::type::ostream_t& operator<<(el::base::type::ostream_t& OutputStreamInstance, const ClassType& ClassInstance) -/// @brief Initializes syslog with process ID, options and facility. calls closelog() on d'tor -class SysLogInitializer { - public: - SysLogInitializer(const char* processIdent, int options = 0, int facility = 0) { -#if defined(ELPP_SYSLOG) - openlog(processIdent, options, facility); -#else - ELPP_UNUSED(processIdent); - ELPP_UNUSED(options); - ELPP_UNUSED(facility); -#endif // defined(ELPP_SYSLOG) - } - virtual ~SysLogInitializer(void) { -#if defined(ELPP_SYSLOG) - closelog(); -#endif // defined(ELPP_SYSLOG) - } -}; -#define ELPP_INITIALIZE_SYSLOG(id, opt, fac) el::SysLogInitializer elSyslogInit(id, opt, fac) -/// @brief Static helpers for developers -class Helpers : base::StaticClass { - public: - /// @brief Shares logging repository (base::Storage) - static inline void setStorage(base::type::StoragePointer storage) { - ELPP = storage; - } - /// @return Main storage repository - static inline base::type::StoragePointer storage() { - return ELPP; - } - /// @brief Sets application arguments and figures out whats active for logging and whats not. - static inline void setArgs(int argc, char** argv) { - ELPP->setApplicationArguments(argc, argv); - } - /// @copydoc setArgs(int argc, char** argv) - static inline void setArgs(int argc, const char** argv) { - ELPP->setApplicationArguments(argc, const_cast(argv)); - } - /// @brief Sets thread name for current thread. Requires std::thread - static inline void setThreadName(const std::string& name) { - ELPP->setThreadName(name); - } - static inline std::string getThreadName() { - return ELPP->getThreadName(base::threading::getCurrentThreadId()); - } -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) - /// @brief Overrides default crash handler and installs custom handler. - /// @param crashHandler A functor with no return type that takes single int argument. - /// Handler is a typedef with specification: void (*Handler)(int) - static inline void setCrashHandler(const el::base::debug::CrashHandler::Handler& crashHandler) { - el::elCrashHandler.setHandler(crashHandler); - } - /// @brief Abort due to crash with signal in parameter - /// @param sig Crash signal - static void crashAbort(int sig, const char* sourceFile = "", unsigned int long line = 0); - /// @brief Logs reason of crash as per sig - /// @param sig Crash signal - /// @param stackTraceIfAvailable Includes stack trace if available - /// @param level Logging level - /// @param logger Logger to use for logging - static void logCrashReason(int sig, bool stackTraceIfAvailable = false, - Level level = Level::Fatal, const char* logger = base::consts::kDefaultLoggerId); -#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) - /// @brief Installs pre rollout callback, this callback is triggered when log file is about to be rolled out - /// (can be useful for backing up) - static inline void installPreRollOutCallback(const PreRollOutCallback& callback) { - ELPP->setPreRollOutCallback(callback); - } - /// @brief Uninstalls pre rollout callback - static inline void uninstallPreRollOutCallback(void) { - ELPP->unsetPreRollOutCallback(); - } - /// @brief Installs post log dispatch callback, this callback is triggered when log is dispatched - template - static inline bool installLogDispatchCallback(const std::string& id) { - return ELPP->installLogDispatchCallback(id); - } - /// @brief Uninstalls log dispatch callback - template - static inline void uninstallLogDispatchCallback(const std::string& id) { - ELPP->uninstallLogDispatchCallback(id); - } - template - static inline T* logDispatchCallback(const std::string& id) { - return ELPP->logDispatchCallback(id); - } -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) - /// @brief Installs post performance tracking callback, this callback is triggered when performance tracking is finished - template - static inline bool installPerformanceTrackingCallback(const std::string& id) { - return ELPP->installPerformanceTrackingCallback(id); - } - /// @brief Uninstalls post performance tracking handler - template - static inline void uninstallPerformanceTrackingCallback(const std::string& id) { - ELPP->uninstallPerformanceTrackingCallback(id); - } - template - static inline T* performanceTrackingCallback(const std::string& id) { - return ELPP->performanceTrackingCallback(id); - } -#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) - /// @brief Converts template to std::string - useful for loggable classes to log containers within log(std::ostream&) const - template - static std::string convertTemplateToStdString(const T& templ) { - el::Logger* logger = - ELPP->registeredLoggers()->get(el::base::consts::kDefaultLoggerId); - if (logger == nullptr) { - return std::string(); - } - base::MessageBuilder b; - b.initialize(logger); - logger->acquireLock(); - b << templ; -#if defined(ELPP_UNICODE) - std::string s = std::string(logger->stream().str().begin(), logger->stream().str().end()); -#else - std::string s = logger->stream().str(); -#endif // defined(ELPP_UNICODE) - logger->stream().str(ELPP_LITERAL("")); - logger->releaseLock(); - return s; - } - /// @brief Returns command line arguments (pointer) provided to easylogging++ - static inline const el::base::utils::CommandLineArgs* commandLineArgs(void) { - return ELPP->commandLineArgs(); - } - /// @brief Reserve space for custom format specifiers for performance - /// @see std::vector::reserve - static inline void reserveCustomFormatSpecifiers(std::size_t size) { - ELPP->m_customFormatSpecifiers.reserve(size); - } - /// @brief Installs user defined format specifier and handler - static inline void installCustomFormatSpecifier(const CustomFormatSpecifier& customFormatSpecifier) { - ELPP->installCustomFormatSpecifier(customFormatSpecifier); - } - /// @brief Uninstalls user defined format specifier and handler - static inline bool uninstallCustomFormatSpecifier(const char* formatSpecifier) { - return ELPP->uninstallCustomFormatSpecifier(formatSpecifier); - } - /// @brief Returns true if custom format specifier is installed - static inline bool hasCustomFormatSpecifier(const char* formatSpecifier) { - return ELPP->hasCustomFormatSpecifier(formatSpecifier); - } - static inline void validateFileRolling(Logger* logger, Level level) { - if (ELPP == nullptr || logger == nullptr) return; - logger->m_typedConfigurations->validateFileRolling(level, ELPP->preRollOutCallback()); - } -}; -/// @brief Static helpers to deal with loggers and their configurations -class Loggers : base::StaticClass { - public: - /// @brief Gets existing or registers new logger - static Logger* getLogger(const std::string& identity, bool registerIfNotAvailable = true); - /// @brief Changes default log builder for future loggers - static void setDefaultLogBuilder(el::LogBuilderPtr& logBuilderPtr); - /// @brief Installs logger registration callback, this callback is triggered when new logger is registered - template - static inline bool installLoggerRegistrationCallback(const std::string& id) { - return ELPP->registeredLoggers()->installLoggerRegistrationCallback(id); - } - /// @brief Uninstalls log dispatch callback - template - static inline void uninstallLoggerRegistrationCallback(const std::string& id) { - ELPP->registeredLoggers()->uninstallLoggerRegistrationCallback(id); - } - template - static inline T* loggerRegistrationCallback(const std::string& id) { - return ELPP->registeredLoggers()->loggerRegistrationCallback(id); - } - /// @brief Unregisters logger - use it only when you know what you are doing, you may unregister - /// loggers initialized / used by third-party libs. - static bool unregisterLogger(const std::string& identity); - /// @brief Whether or not logger with id is registered - static bool hasLogger(const std::string& identity); - /// @brief Reconfigures specified logger with new configurations - static Logger* reconfigureLogger(Logger* logger, const Configurations& configurations); - /// @brief Reconfigures logger with new configurations after looking it up using identity - static Logger* reconfigureLogger(const std::string& identity, const Configurations& configurations); - /// @brief Reconfigures logger's single configuration - static Logger* reconfigureLogger(const std::string& identity, ConfigurationType configurationType, - const std::string& value); - /// @brief Reconfigures all the existing loggers with new configurations - static void reconfigureAllLoggers(const Configurations& configurations); - /// @brief Reconfigures single configuration for all the loggers - static inline void reconfigureAllLoggers(ConfigurationType configurationType, const std::string& value) { - reconfigureAllLoggers(Level::Global, configurationType, value); - } - /// @brief Reconfigures single configuration for all the loggers for specified level - static void reconfigureAllLoggers(Level level, ConfigurationType configurationType, - const std::string& value); - /// @brief Sets default configurations. This configuration is used for future (and conditionally for existing) loggers - static void setDefaultConfigurations(const Configurations& configurations, - bool reconfigureExistingLoggers = false); - /// @brief Returns current default - static const Configurations* defaultConfigurations(void); - /// @brief Returns log stream reference pointer if needed by user - static const base::LogStreamsReferenceMap* logStreamsReference(void); - /// @brief Default typed configuration based on existing defaultConf - static base::TypedConfigurations defaultTypedConfigurations(void); - /// @brief Populates all logger IDs in current repository. - /// @param [out] targetList List of fill up. - static std::vector* populateAllLoggerIds(std::vector* targetList); - /// @brief Sets configurations from global configuration file. - static void configureFromGlobal(const char* globalConfigurationFilePath); - /// @brief Configures loggers using command line arg. Ensure you have already set command line args, - /// @return False if invalid argument or argument with no value provided, true if attempted to configure logger. - /// If true is returned that does not mean it has been configured successfully, it only means that it - /// has attempeted to configure logger using configuration file provided in argument - static bool configureFromArg(const char* argKey); - /// @brief Flushes all loggers for all levels - Be careful if you dont know how many loggers are registered - static void flushAll(void); - /// @brief Adds logging flag used internally. - static inline void addFlag(LoggingFlag flag) { - ELPP->addFlag(flag); - } - /// @brief Removes logging flag used internally. - static inline void removeFlag(LoggingFlag flag) { - ELPP->removeFlag(flag); - } - /// @brief Determines whether or not certain flag is active - static inline bool hasFlag(LoggingFlag flag) { - return ELPP->hasFlag(flag); - } - /// @brief Adds flag and removes it when scope goes out - class ScopedAddFlag { - public: - ScopedAddFlag(LoggingFlag flag) : m_flag(flag) { - Loggers::addFlag(m_flag); - } - ~ScopedAddFlag(void) { - Loggers::removeFlag(m_flag); - } - private: - LoggingFlag m_flag; - }; - /// @brief Removes flag and add it when scope goes out - class ScopedRemoveFlag { - public: - ScopedRemoveFlag(LoggingFlag flag) : m_flag(flag) { - Loggers::removeFlag(m_flag); - } - ~ScopedRemoveFlag(void) { - Loggers::addFlag(m_flag); - } - private: - LoggingFlag m_flag; - }; - /// @brief Sets hierarchy for logging. Needs to enable logging flag (HierarchicalLogging) - static void setLoggingLevel(Level level) { - ELPP->setLoggingLevel(level); - } - /// @brief Sets verbose level on the fly - static void setVerboseLevel(base::type::VerboseLevel level); - /// @brief Gets current verbose level - static base::type::VerboseLevel verboseLevel(void); - /// @brief Sets vmodules as specified (on the fly) - static void setVModules(const char* modules); - /// @brief Clears vmodules - static void clearVModules(void); -}; -class VersionInfo : base::StaticClass { - public: - /// @brief Current version number - static const std::string version(void); - - /// @brief Release date of current version - static const std::string releaseDate(void); -}; -} // namespace el -#undef VLOG_IS_ON -/// @brief Determines whether verbose logging is on for specified level current file. -#define VLOG_IS_ON(verboseLevel) (ELPP->vRegistry()->allowed(verboseLevel, __FILE__)) -#undef TIMED_BLOCK -#undef TIMED_SCOPE -#undef TIMED_SCOPE_IF -#undef TIMED_FUNC -#undef TIMED_FUNC_IF -#undef ELPP_MIN_UNIT -#if defined(ELPP_PERFORMANCE_MICROSECONDS) -# define ELPP_MIN_UNIT el::base::TimestampUnit::Microsecond -#else -# define ELPP_MIN_UNIT el::base::TimestampUnit::Millisecond -#endif // (defined(ELPP_PERFORMANCE_MICROSECONDS)) -/// @brief Performance tracked scope. Performance gets written when goes out of scope using -/// 'performance' logger. -/// -/// @detail Please note in order to check the performance at a certain time you can use obj->checkpoint(); -/// @see el::base::PerformanceTracker -/// @see el::base::PerformanceTracker::checkpoint -// Note: Do not surround this definition with null macro because of obj instance -#define TIMED_SCOPE_IF(obj, blockname, condition) el::base::type::PerformanceTrackerPtr obj( condition ? \ - new el::base::PerformanceTracker(blockname, ELPP_MIN_UNIT) : nullptr ) -#define TIMED_SCOPE(obj, blockname) TIMED_SCOPE_IF(obj, blockname, true) -#define TIMED_BLOCK(obj, blockName) for (struct { int i; el::base::type::PerformanceTrackerPtr timer; } obj = { 0, \ - el::base::type::PerformanceTrackerPtr(new el::base::PerformanceTracker(blockName, ELPP_MIN_UNIT)) }; obj.i < 1; ++obj.i) -/// @brief Performance tracked function. Performance gets written when goes out of scope using -/// 'performance' logger. -/// -/// @detail Please note in order to check the performance at a certain time you can use obj->checkpoint(); -/// @see el::base::PerformanceTracker -/// @see el::base::PerformanceTracker::checkpoint -#define TIMED_FUNC_IF(obj,condition) TIMED_SCOPE_IF(obj, ELPP_FUNC, condition) -#define TIMED_FUNC(obj) TIMED_SCOPE(obj, ELPP_FUNC) -#undef PERFORMANCE_CHECKPOINT -#undef PERFORMANCE_CHECKPOINT_WITH_ID -#define PERFORMANCE_CHECKPOINT(obj) obj->checkpoint(std::string(), __FILE__, __LINE__, ELPP_FUNC) -#define PERFORMANCE_CHECKPOINT_WITH_ID(obj, id) obj->checkpoint(id, __FILE__, __LINE__, ELPP_FUNC) -#undef ELPP_COUNTER -#undef ELPP_COUNTER_POS -/// @brief Gets hit counter for file/line -#define ELPP_COUNTER (ELPP->hitCounters()->getCounter(__FILE__, __LINE__)) -/// @brief Gets hit counter position for file/line, -1 if not registered yet -#define ELPP_COUNTER_POS (ELPP_COUNTER == nullptr ? -1 : ELPP_COUNTER->hitCounts()) -// Undef levels to support LOG(LEVEL) -#undef INFO -#undef WARNING -#undef DEBUG -#undef ERROR -#undef FATAL -#undef TRACE -#undef VERBOSE -// Undef existing -#undef CINFO -#undef CWARNING -#undef CDEBUG -#undef CFATAL -#undef CERROR -#undef CTRACE -#undef CVERBOSE -#undef CINFO_IF -#undef CWARNING_IF -#undef CDEBUG_IF -#undef CERROR_IF -#undef CFATAL_IF -#undef CTRACE_IF -#undef CVERBOSE_IF -#undef CINFO_EVERY_N -#undef CWARNING_EVERY_N -#undef CDEBUG_EVERY_N -#undef CERROR_EVERY_N -#undef CFATAL_EVERY_N -#undef CTRACE_EVERY_N -#undef CVERBOSE_EVERY_N -#undef CINFO_AFTER_N -#undef CWARNING_AFTER_N -#undef CDEBUG_AFTER_N -#undef CERROR_AFTER_N -#undef CFATAL_AFTER_N -#undef CTRACE_AFTER_N -#undef CVERBOSE_AFTER_N -#undef CINFO_N_TIMES -#undef CWARNING_N_TIMES -#undef CDEBUG_N_TIMES -#undef CERROR_N_TIMES -#undef CFATAL_N_TIMES -#undef CTRACE_N_TIMES -#undef CVERBOSE_N_TIMES -// Normal logs -#if ELPP_INFO_LOG -# define CINFO(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Info, dispatchAction, __VA_ARGS__) -#else -# define CINFO(writer, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_INFO_LOG -#if ELPP_WARNING_LOG -# define CWARNING(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Warning, dispatchAction, __VA_ARGS__) -#else -# define CWARNING(writer, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_WARNING_LOG -#if ELPP_DEBUG_LOG -# define CDEBUG(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Debug, dispatchAction, __VA_ARGS__) -#else -# define CDEBUG(writer, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_DEBUG_LOG -#if ELPP_ERROR_LOG -# define CERROR(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Error, dispatchAction, __VA_ARGS__) -#else -# define CERROR(writer, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_ERROR_LOG -#if ELPP_FATAL_LOG -# define CFATAL(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Fatal, dispatchAction, __VA_ARGS__) -#else -# define CFATAL(writer, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_FATAL_LOG -#if ELPP_TRACE_LOG -# define CTRACE(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Trace, dispatchAction, __VA_ARGS__) -#else -# define CTRACE(writer, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_TRACE_LOG -#if ELPP_VERBOSE_LOG -# define CVERBOSE(writer, vlevel, dispatchAction, ...) if (VLOG_IS_ON(vlevel)) writer(\ -el::Level::Verbose, __FILE__, __LINE__, ELPP_FUNC, dispatchAction, vlevel).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#else -# define CVERBOSE(writer, vlevel, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_VERBOSE_LOG -// Conditional logs -#if ELPP_INFO_LOG -# define CINFO_IF(writer, condition_, dispatchAction, ...) \ -ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Info, dispatchAction, __VA_ARGS__) -#else -# define CINFO_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_INFO_LOG -#if ELPP_WARNING_LOG -# define CWARNING_IF(writer, condition_, dispatchAction, ...)\ -ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Warning, dispatchAction, __VA_ARGS__) -#else -# define CWARNING_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_WARNING_LOG -#if ELPP_DEBUG_LOG -# define CDEBUG_IF(writer, condition_, dispatchAction, ...)\ -ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Debug, dispatchAction, __VA_ARGS__) -#else -# define CDEBUG_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_DEBUG_LOG -#if ELPP_ERROR_LOG -# define CERROR_IF(writer, condition_, dispatchAction, ...)\ -ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Error, dispatchAction, __VA_ARGS__) -#else -# define CERROR_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_ERROR_LOG -#if ELPP_FATAL_LOG -# define CFATAL_IF(writer, condition_, dispatchAction, ...)\ -ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Fatal, dispatchAction, __VA_ARGS__) -#else -# define CFATAL_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_FATAL_LOG -#if ELPP_TRACE_LOG -# define CTRACE_IF(writer, condition_, dispatchAction, ...)\ -ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Trace, dispatchAction, __VA_ARGS__) -#else -# define CTRACE_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_TRACE_LOG -#if ELPP_VERBOSE_LOG -# define CVERBOSE_IF(writer, condition_, vlevel, dispatchAction, ...) if (VLOG_IS_ON(vlevel) && (condition_)) writer( \ -el::Level::Verbose, __FILE__, __LINE__, ELPP_FUNC, dispatchAction, vlevel).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#else -# define CVERBOSE_IF(writer, condition_, vlevel, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_VERBOSE_LOG -// Occasional logs -#if ELPP_INFO_LOG -# define CINFO_EVERY_N(writer, occasion, dispatchAction, ...)\ -ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Info, dispatchAction, __VA_ARGS__) -#else -# define CINFO_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_INFO_LOG -#if ELPP_WARNING_LOG -# define CWARNING_EVERY_N(writer, occasion, dispatchAction, ...)\ -ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Warning, dispatchAction, __VA_ARGS__) -#else -# define CWARNING_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_WARNING_LOG -#if ELPP_DEBUG_LOG -# define CDEBUG_EVERY_N(writer, occasion, dispatchAction, ...)\ -ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Debug, dispatchAction, __VA_ARGS__) -#else -# define CDEBUG_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_DEBUG_LOG -#if ELPP_ERROR_LOG -# define CERROR_EVERY_N(writer, occasion, dispatchAction, ...)\ -ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Error, dispatchAction, __VA_ARGS__) -#else -# define CERROR_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_ERROR_LOG -#if ELPP_FATAL_LOG -# define CFATAL_EVERY_N(writer, occasion, dispatchAction, ...)\ -ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Fatal, dispatchAction, __VA_ARGS__) -#else -# define CFATAL_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_FATAL_LOG -#if ELPP_TRACE_LOG -# define CTRACE_EVERY_N(writer, occasion, dispatchAction, ...)\ -ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Trace, dispatchAction, __VA_ARGS__) -#else -# define CTRACE_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_TRACE_LOG -#if ELPP_VERBOSE_LOG -# define CVERBOSE_EVERY_N(writer, occasion, vlevel, dispatchAction, ...)\ -CVERBOSE_IF(writer, ELPP->validateEveryNCounter(__FILE__, __LINE__, occasion), vlevel, dispatchAction, __VA_ARGS__) -#else -# define CVERBOSE_EVERY_N(writer, occasion, vlevel, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_VERBOSE_LOG -// After N logs -#if ELPP_INFO_LOG -# define CINFO_AFTER_N(writer, n, dispatchAction, ...)\ -ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__) -#else -# define CINFO_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_INFO_LOG -#if ELPP_WARNING_LOG -# define CWARNING_AFTER_N(writer, n, dispatchAction, ...)\ -ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__) -#else -# define CWARNING_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_WARNING_LOG -#if ELPP_DEBUG_LOG -# define CDEBUG_AFTER_N(writer, n, dispatchAction, ...)\ -ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__) -#else -# define CDEBUG_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_DEBUG_LOG -#if ELPP_ERROR_LOG -# define CERROR_AFTER_N(writer, n, dispatchAction, ...)\ -ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__) -#else -# define CERROR_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_ERROR_LOG -#if ELPP_FATAL_LOG -# define CFATAL_AFTER_N(writer, n, dispatchAction, ...)\ -ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__) -#else -# define CFATAL_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_FATAL_LOG -#if ELPP_TRACE_LOG -# define CTRACE_AFTER_N(writer, n, dispatchAction, ...)\ -ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__) -#else -# define CTRACE_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_TRACE_LOG -#if ELPP_VERBOSE_LOG -# define CVERBOSE_AFTER_N(writer, n, vlevel, dispatchAction, ...)\ -CVERBOSE_IF(writer, ELPP->validateAfterNCounter(__FILE__, __LINE__, n), vlevel, dispatchAction, __VA_ARGS__) -#else -# define CVERBOSE_AFTER_N(writer, n, vlevel, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_VERBOSE_LOG -// N Times logs -#if ELPP_INFO_LOG -# define CINFO_N_TIMES(writer, n, dispatchAction, ...)\ -ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__) -#else -# define CINFO_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_INFO_LOG -#if ELPP_WARNING_LOG -# define CWARNING_N_TIMES(writer, n, dispatchAction, ...)\ -ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__) -#else -# define CWARNING_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_WARNING_LOG -#if ELPP_DEBUG_LOG -# define CDEBUG_N_TIMES(writer, n, dispatchAction, ...)\ -ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__) -#else -# define CDEBUG_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_DEBUG_LOG -#if ELPP_ERROR_LOG -# define CERROR_N_TIMES(writer, n, dispatchAction, ...)\ -ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__) -#else -# define CERROR_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_ERROR_LOG -#if ELPP_FATAL_LOG -# define CFATAL_N_TIMES(writer, n, dispatchAction, ...)\ -ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__) -#else -# define CFATAL_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_FATAL_LOG -#if ELPP_TRACE_LOG -# define CTRACE_N_TIMES(writer, n, dispatchAction, ...)\ -ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__) -#else -# define CTRACE_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_TRACE_LOG -#if ELPP_VERBOSE_LOG -# define CVERBOSE_N_TIMES(writer, n, vlevel, dispatchAction, ...)\ -CVERBOSE_IF(writer, ELPP->validateNTimesCounter(__FILE__, __LINE__, n), vlevel, dispatchAction, __VA_ARGS__) -#else -# define CVERBOSE_N_TIMES(writer, n, vlevel, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_VERBOSE_LOG -// -// Custom Loggers - Requires (level, dispatchAction, loggerId/s) -// -// undef existing -#undef CLOG -#undef CLOG_VERBOSE -#undef CVLOG -#undef CLOG_IF -#undef CLOG_VERBOSE_IF -#undef CVLOG_IF -#undef CLOG_EVERY_N -#undef CVLOG_EVERY_N -#undef CLOG_AFTER_N -#undef CVLOG_AFTER_N -#undef CLOG_N_TIMES -#undef CVLOG_N_TIMES -// Normal logs -#define CLOG(LEVEL, ...)\ -C##LEVEL(el::base::Writer, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CVLOG(vlevel, ...) CVERBOSE(el::base::Writer, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) -// Conditional logs -#define CLOG_IF(condition, LEVEL, ...)\ -C##LEVEL##_IF(el::base::Writer, condition, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CVLOG_IF(condition, vlevel, ...)\ -CVERBOSE_IF(el::base::Writer, condition, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) -// Hit counts based logs -#define CLOG_EVERY_N(n, LEVEL, ...)\ -C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CVLOG_EVERY_N(n, vlevel, ...)\ -CVERBOSE_EVERY_N(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CLOG_AFTER_N(n, LEVEL, ...)\ -C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CVLOG_AFTER_N(n, vlevel, ...)\ -CVERBOSE_AFTER_N(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CLOG_N_TIMES(n, LEVEL, ...)\ -C##LEVEL##_N_TIMES(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CVLOG_N_TIMES(n, vlevel, ...)\ -CVERBOSE_N_TIMES(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) -// -// Default Loggers macro using CLOG(), CLOG_VERBOSE() and CVLOG() macros -// -// undef existing -#undef LOG -#undef VLOG -#undef LOG_IF -#undef VLOG_IF -#undef LOG_EVERY_N -#undef VLOG_EVERY_N -#undef LOG_AFTER_N -#undef VLOG_AFTER_N -#undef LOG_N_TIMES -#undef VLOG_N_TIMES -#undef ELPP_CURR_FILE_LOGGER_ID -#if defined(ELPP_DEFAULT_LOGGER) -# define ELPP_CURR_FILE_LOGGER_ID ELPP_DEFAULT_LOGGER -#else -# define ELPP_CURR_FILE_LOGGER_ID el::base::consts::kDefaultLoggerId -#endif -#undef ELPP_TRACE -#define ELPP_TRACE CLOG(TRACE, ELPP_CURR_FILE_LOGGER_ID) -// Normal logs -#define LOG(LEVEL) CLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define VLOG(vlevel) CVLOG(vlevel, ELPP_CURR_FILE_LOGGER_ID) -// Conditional logs -#define LOG_IF(condition, LEVEL) CLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define VLOG_IF(condition, vlevel) CVLOG_IF(condition, vlevel, ELPP_CURR_FILE_LOGGER_ID) -// Hit counts based logs -#define LOG_EVERY_N(n, LEVEL) CLOG_EVERY_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define VLOG_EVERY_N(n, vlevel) CVLOG_EVERY_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) -#define LOG_AFTER_N(n, LEVEL) CLOG_AFTER_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define VLOG_AFTER_N(n, vlevel) CVLOG_AFTER_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) -#define LOG_N_TIMES(n, LEVEL) CLOG_N_TIMES(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define VLOG_N_TIMES(n, vlevel) CVLOG_N_TIMES(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) -// Generic PLOG() -#undef CPLOG -#undef CPLOG_IF -#undef PLOG -#undef PLOG_IF -#undef DCPLOG -#undef DCPLOG_IF -#undef DPLOG -#undef DPLOG_IF -#define CPLOG(LEVEL, ...)\ -C##LEVEL(el::base::PErrorWriter, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CPLOG_IF(condition, LEVEL, ...)\ -C##LEVEL##_IF(el::base::PErrorWriter, condition, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define DCPLOG(LEVEL, ...)\ -if (ELPP_DEBUG_LOG) C##LEVEL(el::base::PErrorWriter, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define DCPLOG_IF(condition, LEVEL, ...)\ -C##LEVEL##_IF(el::base::PErrorWriter, (ELPP_DEBUG_LOG) && (condition), el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define PLOG(LEVEL) CPLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define PLOG_IF(condition, LEVEL) CPLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DPLOG(LEVEL) DCPLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DPLOG_IF(condition, LEVEL) DCPLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -// Generic SYSLOG() -#undef CSYSLOG -#undef CSYSLOG_IF -#undef CSYSLOG_EVERY_N -#undef CSYSLOG_AFTER_N -#undef CSYSLOG_N_TIMES -#undef SYSLOG -#undef SYSLOG_IF -#undef SYSLOG_EVERY_N -#undef SYSLOG_AFTER_N -#undef SYSLOG_N_TIMES -#undef DCSYSLOG -#undef DCSYSLOG_IF -#undef DCSYSLOG_EVERY_N -#undef DCSYSLOG_AFTER_N -#undef DCSYSLOG_N_TIMES -#undef DSYSLOG -#undef DSYSLOG_IF -#undef DSYSLOG_EVERY_N -#undef DSYSLOG_AFTER_N -#undef DSYSLOG_N_TIMES -#if defined(ELPP_SYSLOG) -# define CSYSLOG(LEVEL, ...)\ -C##LEVEL(el::base::Writer, el::base::DispatchAction::SysLog, __VA_ARGS__) -# define CSYSLOG_IF(condition, LEVEL, ...)\ -C##LEVEL##_IF(el::base::Writer, condition, el::base::DispatchAction::SysLog, __VA_ARGS__) -# define CSYSLOG_EVERY_N(n, LEVEL, ...) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) -# define CSYSLOG_AFTER_N(n, LEVEL, ...) C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) -# define CSYSLOG_N_TIMES(n, LEVEL, ...) C##LEVEL##_N_TIMES(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) -# define SYSLOG(LEVEL) CSYSLOG(LEVEL, el::base::consts::kSysLogLoggerId) -# define SYSLOG_IF(condition, LEVEL) CSYSLOG_IF(condition, LEVEL, el::base::consts::kSysLogLoggerId) -# define SYSLOG_EVERY_N(n, LEVEL) CSYSLOG_EVERY_N(n, LEVEL, el::base::consts::kSysLogLoggerId) -# define SYSLOG_AFTER_N(n, LEVEL) CSYSLOG_AFTER_N(n, LEVEL, el::base::consts::kSysLogLoggerId) -# define SYSLOG_N_TIMES(n, LEVEL) CSYSLOG_N_TIMES(n, LEVEL, el::base::consts::kSysLogLoggerId) -# define DCSYSLOG(LEVEL, ...) if (ELPP_DEBUG_LOG) C##LEVEL(el::base::Writer, el::base::DispatchAction::SysLog, __VA_ARGS__) -# define DCSYSLOG_IF(condition, LEVEL, ...)\ -C##LEVEL##_IF(el::base::Writer, (ELPP_DEBUG_LOG) && (condition), el::base::DispatchAction::SysLog, __VA_ARGS__) -# define DCSYSLOG_EVERY_N(n, LEVEL, ...)\ -if (ELPP_DEBUG_LOG) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) -# define DCSYSLOG_AFTER_N(n, LEVEL, ...)\ -if (ELPP_DEBUG_LOG) C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) -# define DCSYSLOG_N_TIMES(n, LEVEL, ...)\ -if (ELPP_DEBUG_LOG) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) -# define DSYSLOG(LEVEL) DCSYSLOG(LEVEL, el::base::consts::kSysLogLoggerId) -# define DSYSLOG_IF(condition, LEVEL) DCSYSLOG_IF(condition, LEVEL, el::base::consts::kSysLogLoggerId) -# define DSYSLOG_EVERY_N(n, LEVEL) DCSYSLOG_EVERY_N(n, LEVEL, el::base::consts::kSysLogLoggerId) -# define DSYSLOG_AFTER_N(n, LEVEL) DCSYSLOG_AFTER_N(n, LEVEL, el::base::consts::kSysLogLoggerId) -# define DSYSLOG_N_TIMES(n, LEVEL) DCSYSLOG_N_TIMES(n, LEVEL, el::base::consts::kSysLogLoggerId) -#else -# define CSYSLOG(LEVEL, ...) el::base::NullWriter() -# define CSYSLOG_IF(condition, LEVEL, ...) el::base::NullWriter() -# define CSYSLOG_EVERY_N(n, LEVEL, ...) el::base::NullWriter() -# define CSYSLOG_AFTER_N(n, LEVEL, ...) el::base::NullWriter() -# define CSYSLOG_N_TIMES(n, LEVEL, ...) el::base::NullWriter() -# define SYSLOG(LEVEL) el::base::NullWriter() -# define SYSLOG_IF(condition, LEVEL) el::base::NullWriter() -# define SYSLOG_EVERY_N(n, LEVEL) el::base::NullWriter() -# define SYSLOG_AFTER_N(n, LEVEL) el::base::NullWriter() -# define SYSLOG_N_TIMES(n, LEVEL) el::base::NullWriter() -# define DCSYSLOG(LEVEL, ...) el::base::NullWriter() -# define DCSYSLOG_IF(condition, LEVEL, ...) el::base::NullWriter() -# define DCSYSLOG_EVERY_N(n, LEVEL, ...) el::base::NullWriter() -# define DCSYSLOG_AFTER_N(n, LEVEL, ...) el::base::NullWriter() -# define DCSYSLOG_N_TIMES(n, LEVEL, ...) el::base::NullWriter() -# define DSYSLOG(LEVEL) el::base::NullWriter() -# define DSYSLOG_IF(condition, LEVEL) el::base::NullWriter() -# define DSYSLOG_EVERY_N(n, LEVEL) el::base::NullWriter() -# define DSYSLOG_AFTER_N(n, LEVEL) el::base::NullWriter() -# define DSYSLOG_N_TIMES(n, LEVEL) el::base::NullWriter() -#endif // defined(ELPP_SYSLOG) -// -// Custom Debug Only Loggers - Requires (level, loggerId/s) -// -// undef existing -#undef DCLOG -#undef DCVLOG -#undef DCLOG_IF -#undef DCVLOG_IF -#undef DCLOG_EVERY_N -#undef DCVLOG_EVERY_N -#undef DCLOG_AFTER_N -#undef DCVLOG_AFTER_N -#undef DCLOG_N_TIMES -#undef DCVLOG_N_TIMES -// Normal logs -#define DCLOG(LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG(LEVEL, __VA_ARGS__) -#define DCLOG_VERBOSE(vlevel, ...) if (ELPP_DEBUG_LOG) CLOG_VERBOSE(vlevel, __VA_ARGS__) -#define DCVLOG(vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG(vlevel, __VA_ARGS__) -// Conditional logs -#define DCLOG_IF(condition, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_IF(condition, LEVEL, __VA_ARGS__) -#define DCVLOG_IF(condition, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_IF(condition, vlevel, __VA_ARGS__) -// Hit counts based logs -#define DCLOG_EVERY_N(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_EVERY_N(n, LEVEL, __VA_ARGS__) -#define DCVLOG_EVERY_N(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_EVERY_N(n, vlevel, __VA_ARGS__) -#define DCLOG_AFTER_N(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_AFTER_N(n, LEVEL, __VA_ARGS__) -#define DCVLOG_AFTER_N(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_AFTER_N(n, vlevel, __VA_ARGS__) -#define DCLOG_N_TIMES(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_N_TIMES(n, LEVEL, __VA_ARGS__) -#define DCVLOG_N_TIMES(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_N_TIMES(n, vlevel, __VA_ARGS__) -// -// Default Debug Only Loggers macro using CLOG(), CLOG_VERBOSE() and CVLOG() macros -// -#if !defined(ELPP_NO_DEBUG_MACROS) -// undef existing -#undef DLOG -#undef DVLOG -#undef DLOG_IF -#undef DVLOG_IF -#undef DLOG_EVERY_N -#undef DVLOG_EVERY_N -#undef DLOG_AFTER_N -#undef DVLOG_AFTER_N -#undef DLOG_N_TIMES -#undef DVLOG_N_TIMES -// Normal logs -#define DLOG(LEVEL) DCLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DVLOG(vlevel) DCVLOG(vlevel, ELPP_CURR_FILE_LOGGER_ID) -// Conditional logs -#define DLOG_IF(condition, LEVEL) DCLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DVLOG_IF(condition, vlevel) DCVLOG_IF(condition, vlevel, ELPP_CURR_FILE_LOGGER_ID) -// Hit counts based logs -#define DLOG_EVERY_N(n, LEVEL) DCLOG_EVERY_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DVLOG_EVERY_N(n, vlevel) DCVLOG_EVERY_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) -#define DLOG_AFTER_N(n, LEVEL) DCLOG_AFTER_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DVLOG_AFTER_N(n, vlevel) DCVLOG_AFTER_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) -#define DLOG_N_TIMES(n, LEVEL) DCLOG_N_TIMES(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DVLOG_N_TIMES(n, vlevel) DCVLOG_N_TIMES(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) -#endif // defined(ELPP_NO_DEBUG_MACROS) -#if !defined(ELPP_NO_CHECK_MACROS) -// Check macros -#undef CCHECK -#undef CPCHECK -#undef CCHECK_EQ -#undef CCHECK_NE -#undef CCHECK_LT -#undef CCHECK_GT -#undef CCHECK_LE -#undef CCHECK_GE -#undef CCHECK_BOUNDS -#undef CCHECK_NOTNULL -#undef CCHECK_STRCASEEQ -#undef CCHECK_STRCASENE -#undef CHECK -#undef PCHECK -#undef CHECK_EQ -#undef CHECK_NE -#undef CHECK_LT -#undef CHECK_GT -#undef CHECK_LE -#undef CHECK_GE -#undef CHECK_BOUNDS -#undef CHECK_NOTNULL -#undef CHECK_STRCASEEQ -#undef CHECK_STRCASENE -#define CCHECK(condition, ...) CLOG_IF(!(condition), FATAL, __VA_ARGS__) << "Check failed: [" << #condition << "] " -#define CPCHECK(condition, ...) CPLOG_IF(!(condition), FATAL, __VA_ARGS__) << "Check failed: [" << #condition << "] " -#define CHECK(condition) CCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) -#define PCHECK(condition) CPCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) -#define CCHECK_EQ(a, b, ...) CCHECK(a == b, __VA_ARGS__) -#define CCHECK_NE(a, b, ...) CCHECK(a != b, __VA_ARGS__) -#define CCHECK_LT(a, b, ...) CCHECK(a < b, __VA_ARGS__) -#define CCHECK_GT(a, b, ...) CCHECK(a > b, __VA_ARGS__) -#define CCHECK_LE(a, b, ...) CCHECK(a <= b, __VA_ARGS__) -#define CCHECK_GE(a, b, ...) CCHECK(a >= b, __VA_ARGS__) -#define CCHECK_BOUNDS(val, min, max, ...) CCHECK(val >= min && val <= max, __VA_ARGS__) -#define CHECK_EQ(a, b) CCHECK_EQ(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_NE(a, b) CCHECK_NE(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_LT(a, b) CCHECK_LT(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_GT(a, b) CCHECK_GT(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_LE(a, b) CCHECK_LE(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_GE(a, b) CCHECK_GE(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_BOUNDS(val, min, max) CCHECK_BOUNDS(val, min, max, ELPP_CURR_FILE_LOGGER_ID) -#define CCHECK_NOTNULL(ptr, ...) CCHECK((ptr) != nullptr, __VA_ARGS__) -#define CCHECK_STREQ(str1, str2, ...) CLOG_IF(!el::base::utils::Str::cStringEq(str1, str2), FATAL, __VA_ARGS__) \ -<< "Check failed: [" << #str1 << " == " << #str2 << "] " -#define CCHECK_STRNE(str1, str2, ...) CLOG_IF(el::base::utils::Str::cStringEq(str1, str2), FATAL, __VA_ARGS__) \ -<< "Check failed: [" << #str1 << " != " << #str2 << "] " -#define CCHECK_STRCASEEQ(str1, str2, ...) CLOG_IF(!el::base::utils::Str::cStringCaseEq(str1, str2), FATAL, __VA_ARGS__) \ -<< "Check failed: [" << #str1 << " == " << #str2 << "] " -#define CCHECK_STRCASENE(str1, str2, ...) CLOG_IF(el::base::utils::Str::cStringCaseEq(str1, str2), FATAL, __VA_ARGS__) \ -<< "Check failed: [" << #str1 << " != " << #str2 << "] " -#define CHECK_NOTNULL(ptr) CCHECK_NOTNULL((ptr), ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_STREQ(str1, str2) CCHECK_STREQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_STRNE(str1, str2) CCHECK_STRNE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_STRCASEEQ(str1, str2) CCHECK_STRCASEEQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_STRCASENE(str1, str2) CCHECK_STRCASENE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#undef DCCHECK -#undef DCCHECK_EQ -#undef DCCHECK_NE -#undef DCCHECK_LT -#undef DCCHECK_GT -#undef DCCHECK_LE -#undef DCCHECK_GE -#undef DCCHECK_BOUNDS -#undef DCCHECK_NOTNULL -#undef DCCHECK_STRCASEEQ -#undef DCCHECK_STRCASENE -#undef DCPCHECK -#undef DCHECK -#undef DCHECK_EQ -#undef DCHECK_NE -#undef DCHECK_LT -#undef DCHECK_GT -#undef DCHECK_LE -#undef DCHECK_GE -#undef DCHECK_BOUNDS_ -#undef DCHECK_NOTNULL -#undef DCHECK_STRCASEEQ -#undef DCHECK_STRCASENE -#undef DPCHECK -#define DCCHECK(condition, ...) if (ELPP_DEBUG_LOG) CCHECK(condition, __VA_ARGS__) -#define DCCHECK_EQ(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_EQ(a, b, __VA_ARGS__) -#define DCCHECK_NE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_NE(a, b, __VA_ARGS__) -#define DCCHECK_LT(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_LT(a, b, __VA_ARGS__) -#define DCCHECK_GT(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_GT(a, b, __VA_ARGS__) -#define DCCHECK_LE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_LE(a, b, __VA_ARGS__) -#define DCCHECK_GE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_GE(a, b, __VA_ARGS__) -#define DCCHECK_BOUNDS(val, min, max, ...) if (ELPP_DEBUG_LOG) CCHECK_BOUNDS(val, min, max, __VA_ARGS__) -#define DCCHECK_NOTNULL(ptr, ...) if (ELPP_DEBUG_LOG) CCHECK_NOTNULL((ptr), __VA_ARGS__) -#define DCCHECK_STREQ(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STREQ(str1, str2, __VA_ARGS__) -#define DCCHECK_STRNE(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRNE(str1, str2, __VA_ARGS__) -#define DCCHECK_STRCASEEQ(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRCASEEQ(str1, str2, __VA_ARGS__) -#define DCCHECK_STRCASENE(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRCASENE(str1, str2, __VA_ARGS__) -#define DCPCHECK(condition, ...) if (ELPP_DEBUG_LOG) CPCHECK(condition, __VA_ARGS__) -#define DCHECK(condition) DCCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_EQ(a, b) DCCHECK_EQ(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_NE(a, b) DCCHECK_NE(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_LT(a, b) DCCHECK_LT(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_GT(a, b) DCCHECK_GT(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_LE(a, b) DCCHECK_LE(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_GE(a, b) DCCHECK_GE(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_BOUNDS(val, min, max) DCCHECK_BOUNDS(val, min, max, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_NOTNULL(ptr) DCCHECK_NOTNULL((ptr), ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_STREQ(str1, str2) DCCHECK_STREQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_STRNE(str1, str2) DCCHECK_STRNE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_STRCASEEQ(str1, str2) DCCHECK_STRCASEEQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_STRCASENE(str1, str2) DCCHECK_STRCASENE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define DPCHECK(condition) DCPCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) -#endif // defined(ELPP_NO_CHECK_MACROS) -#if defined(ELPP_DISABLE_DEFAULT_CRASH_HANDLING) -# define ELPP_USE_DEF_CRASH_HANDLER false -#else -# define ELPP_USE_DEF_CRASH_HANDLER true -#endif // defined(ELPP_DISABLE_DEFAULT_CRASH_HANDLING) -#define ELPP_CRASH_HANDLER_INIT -#define ELPP_INIT_EASYLOGGINGPP(val) \ -namespace el { \ -namespace base { \ -el::base::type::StoragePointer elStorage(val); \ -} \ -el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER); \ -} - -#if ELPP_ASYNC_LOGGING -# define INITIALIZE_EASYLOGGINGPP ELPP_INIT_EASYLOGGINGPP(new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder()),\ -new el::base::AsyncDispatchWorker())) -#else -# define INITIALIZE_EASYLOGGINGPP ELPP_INIT_EASYLOGGINGPP(new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder()))) -#endif // ELPP_ASYNC_LOGGING -#define INITIALIZE_NULL_EASYLOGGINGPP \ -namespace el {\ -namespace base {\ -el::base::type::StoragePointer elStorage;\ -}\ -el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\ -} -#define SHARE_EASYLOGGINGPP(initializedStorage)\ -namespace el {\ -namespace base {\ -el::base::type::StoragePointer elStorage(initializedStorage);\ -}\ -el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\ -} - -#if defined(ELPP_UNICODE) -# define START_EASYLOGGINGPP(argc, argv) el::Helpers::setArgs(argc, argv); std::locale::global(std::locale("")) -#else -# define START_EASYLOGGINGPP(argc, argv) el::Helpers::setArgs(argc, argv) -#endif // defined(ELPP_UNICODE) -#endif // EASYLOGGINGPP_H diff --git a/src/eval_mesh.py b/src/eval_mesh.py deleted file mode 100755 index e46547f6..00000000 --- a/src/eval_mesh.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python3 -import argparse, logging, math -import numpy as np -from mesh_io import read_mesh, write_mesh - - -def main(): - args = parse_args() - logging.basicConfig(level=getattr(logging, args.logging)) - points, cells, cell_types, _ = read_mesh(args.in_meshname) - points = np.array(points) - values = user_func(points, args.function) - write_mesh(args.out_meshname, points, cells, cell_types, values) - - -def user_func(points, f_str): - points = np.array(points) - vals = np.zeros(points.shape[0]) - for i, (x, y, z) in enumerate(points): - loc_dict = {"x": x, "y": y, "z": z, "math": math, "np": np} - vals[i] = eval(f_str, globals(), loc_dict) - logging.debug("Evaluating {} on ({}, {}, {}) = {}".format(f_str, x, y, z, vals[i])) - - logging.info("Evaluated {} on {} vertices".format(f_str, len(vals))) - return vals - - -def parse_args(): - parser = argparse.ArgumentParser(description="Evaluate a function on a given mesh") - parser.add_argument("in_meshname", metavar="inputmesh", help="The mesh used as input") - parser.add_argument("function", - help="""The function to evalutate on the mesh. - Points are given in the form \"(x, y, z)\". An example for a function would be - \"math.sin(x) + math.exp(z)\".""") - parser.add_argument("--out", "-o", dest="out_meshname", help="""The output meshname. - Default is the same as for the input mesh""") - parser.add_argument("--log", "-l", dest="logging", default="INFO", - choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], help="""Set the log level. - Default is INFO""") - - args = parser.parse_args() - args.out_meshname = args.out_meshname or args.in_meshname - return args - - -if __name__ == "__main__": - main() diff --git a/src/join_mesh.py b/src/join_mesh.py deleted file mode 100755 index 55318216..00000000 --- a/src/join_mesh.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python3 -import argparse -import logging -import os -import numpy as np -from mesh_io import read_txt, write_mesh - - -def main(): - args = parse_args() - logging.basicConfig(level=getattr(logging, args.logging)) - points, cells, cell_types, values = read_mesh(args.in_meshname, args.numparts) - out_meshname = args.out_meshname if args.out_meshname else args.in_meshname + ".vtk" - write_mesh(out_meshname, points, cells, cell_types, values) - - -def read_mesh(dirname, length = None): - """ - Reads a mesh from the given directory. If length is given, only the first length parts are read, - else length is inferred from the files. - """ - if not length: - length = 0 - while os.path.isfile(os.path.join(dirname, str(length))): - length += 1 - dirname = os.path.abspath(dirname) - if not os.path.exists(dirname): - raise Exception("Directory not found") - all_points = [] - all_values = [] - all_cells = [] - all_cell_types = [] - for i in range(length): - points, cells, cell_types, values = read_txt(os.path.join(dirname, str(i))) - offset = len(all_points) - all_points += points - all_values += values - all_cells += [ - tuple(map(lambda idx: idx+offset, cell)) - for cell in cells - ] - all_cell_types += cell_types - return all_points, all_cells, all_cell_types, all_values - - -def parse_args(): - parser = argparse.ArgumentParser(description="""Read a partitioned mesh - and join it into a .vtk or .txt file.""") - parser.add_argument("in_meshname", metavar="inputmesh", help="The partitioned mesh used as input") - parser.add_argument("--out", "-o", dest="out_meshname", help="The output mesh. Can be vtk or txt.") - parser.add_argument("--numparts", "-n", dest="numparts", type=int, - help="The number of parts to read from the input mesh. By default the entire mesh is read.") - parser.add_argument("--log", "-l", dest="logging", default="INFO", - choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], help="Set the log level. Default is INFO") - return parser.parse_args() - - -if __name__ == "__main__": - main() diff --git a/src/logger.cpp b/src/logger.cpp new file mode 100644 index 00000000..13cbf668 --- /dev/null +++ b/src/logger.cpp @@ -0,0 +1,18 @@ +#include "logger.hpp" + +namespace attrs = boost::log::attributes; +namespace expr = boost::log::expressions; +namespace logging = boost::log; + +// Defines a global logger initialization routine +BOOST_LOG_GLOBAL_LOGGER_INIT(my_logger, src::severity_logger_mt) +{ + src::severity_logger_mt lg; + logging::add_common_attributes(); + auto format = expr::stream << "---[ASTE] " << expr::message; + logging::add_console_log(std::clog, keywords::format = format); + logging::core::get()->set_filter( + logging::trivial::severity >= logging::trivial::info); + + return lg; +} diff --git a/src/logger.hpp b/src/logger.hpp new file mode 100644 index 00000000..5c571cf9 --- /dev/null +++ b/src/logger.hpp @@ -0,0 +1,40 @@ +#pragma once + +/* + * Copyright Andrey Semashev 2007 - 2015. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ + +#define BOOST_ALL_DYN_LINK + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace logging = boost::log; +namespace sinks = boost::log::sinks; +namespace attrs = boost::log::attributes; +namespace src = boost::log::sources; +namespace expr = boost::log::expressions; +namespace keywords = boost::log::keywords; + +using boost::shared_ptr; + +// Narrow-char thread-safe logger. +typedef boost::log::sources::severity_logger_mt logger_t; + +// declares a global logger with a custom initialization +BOOST_LOG_GLOBAL_LOGGER(my_logger, logger_t) + +#define ASTE_DEBUG BOOST_LOG_SEV(my_logger::get(), boost::log::trivial::severity_level::debug) +#define ASTE_INFO BOOST_LOG_SEV(my_logger::get(), boost::log::trivial::severity_level::info) +#define ASTE_WARNING BOOST_LOG_SEV(my_loggermy_logger::get(), boost::log::trivial::severity_level::warning) +#define ASTE_ERROR BOOST_LOG_SEV(my_logger::get(), boost::log::trivial::severity_level::error) diff --git a/src/make_mesh.py b/src/make_mesh.py deleted file mode 100755 index 588e17ac..00000000 --- a/src/make_mesh.py +++ /dev/null @@ -1,143 +0,0 @@ -#!/usr/bin/env python3 - -import argparse, itertools, logging, os -import mesh -import numpy as np - - -def gauss_pulse(xx, yy, zz = 0): - rho_0 = 1.225 - rho_pulse = 2 - d = 0.2 - x_0 = y_0 = 0 - return rho_0 + rho_pulse * np.exp( -(np.power(xx + x_0, 2) + np.power(yy + y_0, 2))) / d + np.log(2) - -def lookup_from_coords(x, y, table): - return table[table[0]==x][table[1]==y] - -def read_data(directory, geometry = (0,2), val_col_offset = 1): - """ Reads data from directory - geometry: Colums that hold 2D geometry information. - val_col_offset: Offset from geometry col to value col - - Returns coords, vals and analytical solution (from fun) - in meshgrid like notation, """ - - usecols = geometry + (val_col_offset + geometry[-1], ) - out = np.empty((0, len(usecols))) - - if os.path.isdir(directory): - for file in sorted(os.listdir(directory)): - print("Read from", file) - out = np.vstack((out, - np.loadtxt(os.path.join(directory, file), usecols = usecols))) - elif os.path.isfile(directory): - print("Read from", directory) - out = np.vstack((out, - np.loadtxt(directory, usecols = usecols))) - - cidx = range(len(geometry)) # Indizes of coordinates in out - # Unscramble the array - out = out[np.lexsort(np.fliplr( out[:,cidx] ).T)] - - size = int(np.sqrt(len(out))) - out = out.reshape(size, size, -1) - coords = [] - for i in cidx: - coords.append(out[..., i]) - - vals = out[..., -1] - - return coords, vals - - -def rmse(indata, outdata): - return np.sqrt( ((outdata.flatten() - indata.flatten())**2).mean() ) - -def gen_data(x0, x1, nx, y0, y1, ny): - """ Generates an 2d, quadratic mesh on [start, end]² on points² """ - logging.info("Generate mesh on [{},{}] x [{},{}] with {} x {} points.".format(x0, x1, y0, y1, nx, ny)) - x = np.linspace(x0, x1, nx) - y = np.linspace(y0, y1, ny) - xx, yy = np.meshgrid(x, y) - return xx, yy - -def gen_data_GC(order, element_size, domain_size, domain_start = 0): - xx, yy = mesh.GaussChebyshev_3D(order, element_size, domain_size, domain_start) - return xx, yy - - -def write_mesh(filename, xx, yy): - with open(filename, "w") as f: - for fx, fy in zip(xx.flatten(), yy.flatten()): - str = "{!s} {!s} {!s} 0".format(0, fx, fy) - print(str, file = f) - -def write_mesh_connectivity(filename, connectivity, xn, yn): - def idx(x, y): - return x + xn*y - - if connectivity == "Triangles": - with open(filename, "w") as f: - fmt = "{} {} {}" - for y, x in itertools.product(range(yn-1), range(xn-1)): - print(fmt.format(idx(x, y), idx(x+1,y), idx(x,y+1)), file=f) - print(fmt.format(idx(x+1,y), idx(x+1,y+1), idx(x,y+1)), file=f) - - elif connectivity == "Edges": - with open(filename, "w") as f: - fmt = "{} {}" - for y, x in itertools.product(range(yn-1), range(xn-1)): - print(fmt.format(idx(x,y), idx(x+1,y)), file=f) - print(fmt.format(idx(x,y), idx(x,y+1)), file=f) - - for x in range(xn-1): - print(fmt.format(idx(x,yn-1), idx(x+1,yn-1)), file=f) - - for y in range(yn-1): - print(fmt.format(idx(xn-1,y), idx(xn-1,y+1)), file=f) - - else: - assert(connectivity is None) - - -def parse_args(): - parser = argparse.ArgumentParser(description="Create a mesh", - formatter_class=argparse.ArgumentDefaultsHelpFormatter) - parser.add_argument("out_mesh", metavar="outmesh", help="Name of output mesh file") - parser.add_argument("--x0", type = int, default = 0, help="Start coordinate in x-dimension") - parser.add_argument("--x1", type = int, default = 1, help="End coordinate in x-dimension") - parser.add_argument("--nx", type = int, default = 100, help="Number of elements in x-direction") - parser.add_argument("--y0", type = int, default = 0, help="Start coordinate in y-dimension") - parser.add_argument("--y1", type = int, default = 1, help="End coordinate in y-dimension") - parser.add_argument("--ny", type = int, default = 100, help="Number of elements in y-direction") - - parser.add_argument("-c", "--connectivity", default=None, choices=[None, "Edges", "Triangles"], help="The additional connectivity information to generate.") - - parser.add_argument("--log", "-l", dest="logging", default="INFO", - choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], - help="Log level") - return parser.parse_args() - - - -def main(): - args = parse_args() - logging.basicConfig(level=getattr(logging, args.logging)) - - GC = False - - if GC: - write_mesh("inMeshGC.txt", *gen_data_GC(4, 0.5, 4, domain_start = -2, value_function = gauss_pulse)) - write_mesh("outMeshGC.txt", *gen_data_GC(10, 0.5, 4, domain_start = -2, value_function = gauss_pulse)) - - else: - write_mesh(args.out_mesh + ".txt", *gen_data(args.x0, args.x1, args.nx, args.y0, args.y1, args.ny)) - write_mesh_connectivity(args.out_mesh + ".conn.txt", args.connectivity, args.nx, args.ny) - logging.info("Wrote mesh to %s", args.out_mesh + ".txt") - if args.connectivity: - logging.info("Wrote mesh connectivity to %s", args.out_mesh + ".conn.txt") - - -if __name__== "__main__": - main() diff --git a/src/mesh.cpp b/src/mesh.cpp new file mode 100644 index 00000000..a9df6587 --- /dev/null +++ b/src/mesh.cpp @@ -0,0 +1,510 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace aste { + +// --- MeshName + +std::string MeshName::filename() const +{ + return _mname + _ext; +} + +Mesh::VID vtkToPos(vtkIdType id) +{ + assert(id >= 0); + return static_cast(id); +} + +// Read vertices and mesh connectivity +void readMesh(Mesh &mesh, const std::string &filename, const int dim, const bool requireConnectivity) +{ + if (!fs::is_regular_file(filename)) { + ASTE_ERROR << "The mesh file does not exist: " << filename; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + + mesh.fname = filename; // Store data loaded from which mesh + auto ext = fs::path(filename).extension(); + vtkSmartPointer grid; + + if (ext == ".vtk") { + vtkSmartPointer reader = vtkSmartPointer::New(); + reader->SetFileName(filename.c_str()); + reader->Update(); + grid = reader->GetOutput(); + } else if (ext == ".vtu") { + vtkSmartPointer reader = vtkSmartPointer::New(); + reader->SetFileName(filename.c_str()); + reader->Update(); + grid = reader->GetOutput(); + } else { + ASTE_ERROR << "Unknown File Extension for file " << filename << "Extension should be .vtk or .vtu"; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + + // Get Points + vtkPoints *Points = grid->GetPoints(); + vtkIdType NumPoints = grid->GetNumberOfPoints(); + for (vtkIdType point = 0; point < NumPoints; point++) { + std::array vertexPosArr; + Points->GetPoint(point, vertexPosArr.data()); + std::vector vertexLoc(dim); + std::copy(vertexPosArr.begin(), vertexPosArr.begin() + dim, vertexLoc.begin()); + mesh.positions.push_back(vertexLoc); + } + + if (requireConnectivity) { + for (int i = 0; i < grid->GetNumberOfCells(); i++) { + int cellType = grid->GetCell(i)->GetCellType(); + + // Here we use static cast since VTK library returns a long long unsigned int however preCICE uses int for PointId's + if (cellType == VTK_TRIANGLE) { + vtkCell *cell = grid->GetCell(i); + std::array elem{vtkToPos(cell->GetPointId(0)), vtkToPos(cell->GetPointId(1)), vtkToPos(cell->GetPointId(2))}; + mesh.triangles.push_back(elem); + } else if (cellType == VTK_LINE) { + vtkCell *cell = grid->GetCell(i); + std::array elem{vtkToPos(cell->GetPointId(0)), vtkToPos(cell->GetPointId(1))}; + mesh.edges.push_back(elem); + } else if (cellType == VTK_QUAD) { + vtkCell *cell = grid->GetCell(i); + std::array elem{vtkToPos(cell->GetPointId(0)), vtkToPos(cell->GetPointId(1)), vtkToPos(cell->GetPointId(2)), vtkToPos(cell->GetPointId(3))}; + mesh.quadrilaterals.push_back(elem); + } else if (cellType == VTK_TETRA) { + if (dim == 3) { + vtkCell *cell = grid->GetCell(i); + std::array elem{vtkToPos(cell->GetPointId(0)), vtkToPos(cell->GetPointId(1)), vtkToPos(cell->GetPointId(2)), vtkToPos(cell->GetPointId(3))}; + mesh.tetrahedra.push_back(elem); + } + } else if (cellType == VTK_VERTEX) { + // Skip the VTK_VERTEX type, @TODO: Print out a warning when the logger works properly + } else { + ASTE_ERROR << "Invalid cell type in VTK file. Valid cell types are, VTK_LINE, VTK_TRIANGLE, and VTK_QUAD."; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + } + } else { + ASTE_INFO << "Connectivity information for mesh \"" << mesh.fname << "\" skipped since connectivity is not required.\n"; + } +}; + +// Read required data from mesh file +void readData(Mesh &mesh, const std::string &filename) +{ + if (!fs::is_regular_file(filename)) { + ASTE_ERROR << "The mesh file does not exist: " << filename; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + + mesh.fname = filename; // Store data loaded from which mesh + auto ext = fs::path(filename).extension(); + vtkSmartPointer grid; + + if (ext == ".vtk") { + vtkSmartPointer reader = vtkSmartPointer::New(); + reader->SetFileName(filename.c_str()); + reader->ReadAllScalarsOn(); + reader->ReadAllVectorsOn(); + reader->ReadAllFieldsOn(); + reader->Update(); + grid = reader->GetOutput(); + } else if (ext == ".vtu") { + vtkSmartPointer reader = vtkSmartPointer::New(); + reader->SetFileName(filename.c_str()); + reader->Update(); + grid = reader->GetOutput(); + } else { + ASTE_ERROR << "Unknown File Extension for file " << filename << "Extension should be .vtk or .vtu"; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + + vtkIdType NumPoints = grid->GetNumberOfPoints(); + // Get Point Data + vtkPointData *PD = grid->GetPointData(); + // Check it has data array + for (auto &data : mesh.meshdata) { + auto dataname = data.name; + auto datatype = data.type; + if ((PD->HasArray(dataname.c_str()) == 1) && (datatype == aste::datatype::WRITE)) { + // Get Data and Add to Mesh + vtkDataArray *ArrayData = PD->GetArray(dataname.c_str()); + int NumComp = ArrayData->GetNumberOfComponents(); + + assert(NumComp >= data.numcomp); // 3D case it should match 2D case it match or less + data.dataVector.reserve(NumComp * NumPoints); + + switch (NumComp) { + case 1: // Scalar Data + assert(data.numcomp == 1); + for (vtkIdType tupleIdx = 0; tupleIdx < NumPoints; tupleIdx++) { + const double scalar = ArrayData->GetTuple1(tupleIdx); + data.dataVector.push_back(scalar); + } + break; + case 2: // Vector Data with 2 component + assert(data.numcomp == 2); + double *vector2ref; + for (vtkIdType tupleIdx = 0; tupleIdx < NumPoints; tupleIdx++) { + vector2ref = ArrayData->GetTuple2(tupleIdx); + std::copy_n(vector2ref, 2, std::back_inserter(data.dataVector)); + } + break; + case 3: // Vector Data with 3 component + double *vector3ref; + for (vtkIdType tupleIdx = 0; tupleIdx < NumPoints; tupleIdx++) { + vector3ref = ArrayData->GetTuple3(tupleIdx); + std::copy_n(vector3ref, data.numcomp, std::back_inserter(data.dataVector)); + } + break; + default: // Unknown number of component + ASTE_ERROR << std::string("Please check your VTK file there is/are ").append(std::string(std::to_string(NumComp))).append(" component for data ").append(dataname); + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + break; + } + } else if (datatype == aste::datatype::GRADIENT) { + const std::string dataname = data.name; + const int dataDim = data.numcomp; + + const int gradDim = data.gradDimension; // Number of components of gradient + // Get Data and Add to Mesh + vtkDataArray *gradX; + vtkDataArray *gradY; + vtkDataArray *gradZ; + if (dataDim == 1) // Scalar data + { + const std::string gradName = dataname + "_gradient"; + (PD->HasArray(gradName.c_str())) ? gradX = PD->GetArray(gradName.c_str()) : gradX = nullptr; + gradY = nullptr; + gradZ = nullptr; + } else { // Vector data + const std::string gradNameX = dataname + "_dx"; + const std::string gradNameY = dataname + "_dy"; + const std::string gradNameZ = dataname + "_dz"; + (PD->HasArray(gradNameX.c_str())) ? gradX = PD->GetArray(gradNameX.c_str()) : gradX = nullptr; + (PD->HasArray(gradNameY.c_str())) ? gradY = PD->GetArray(gradNameY.c_str()) : gradY = nullptr; + (PD->HasArray(gradNameZ.c_str())) ? gradZ = PD->GetArray(gradNameZ.c_str()) : gradZ = nullptr; + } + + if (gradX == nullptr || (dataDim > 1 && gradY == nullptr) || (dataDim == 3 && gradZ == nullptr)) { + std::cerr << "Error while parsing gradient data for data called \"" << dataname << "\". ASTE searches in case of scalar data for \"" << dataname << "_gradient\", in case of vector-valued data for three gradient vectors called \"" << dataname << "_dx/dy/dz" + << "\". Please ensure that the required gradient data fields are available on your input mesh. If you use the \"precice-aste-evaluate\" tool, you can add the \"--gradient\" flag when generating data in order to automatically add gradient data on the corresponding mesh.\n"; + } + + // Safety checks + assert(gradX->GetNumberOfComponents() == 3); // Gradient should be 3D + if (gradY != nullptr) { // 2/3D Vector data + assert(gradY->GetNumberOfComponents() == 3); + } + if (dataDim == 3 && gradZ != nullptr) { // 3D Vector data + assert(gradZ->GetNumberOfComponents() == 3); + } + + data.dataVector.reserve(dataDim * gradDim * NumPoints); + + switch (dataDim) { + case 1: // Scalar Data + { + for (vtkIdType tupleIdx = 0; tupleIdx < NumPoints; tupleIdx++) { + double *grad = gradX->GetTuple3(tupleIdx); + std::copy_n(grad, gradDim, std::back_inserter(data.dataVector)); + } + } break; + case 2: // Vector Data with 2 component + { + double *x; + double *y; + for (vtkIdType tupleIdx = 0; tupleIdx < NumPoints; tupleIdx++) { + x = gradX->GetTuple3(tupleIdx); + std::copy_n(x, 2, std::back_inserter(data.dataVector)); + + y = gradY->GetTuple3(tupleIdx); + std::copy_n(y, 2, std::back_inserter(data.dataVector)); + } + } break; + case 3: // Vector Data with 3 component + { + double *x; + double *y; + double *z; + for (vtkIdType tupleIdx = 0; tupleIdx < NumPoints; tupleIdx++) { + x = gradX->GetTuple3(tupleIdx); + std::copy_n(x, 3, std::back_inserter(data.dataVector)); + + y = gradY->GetTuple3(tupleIdx); + std::copy_n(y, 3, std::back_inserter(data.dataVector)); + + z = gradZ->GetTuple3(tupleIdx); + std::copy_n(z, 3, std::back_inserter(data.dataVector)); + } + } break; + } + } + } +}; + +void MeshName::loadMesh(Mesh &mesh, const int dim, const bool requireConnectivity) +{ + readMesh(mesh, filename(), dim, requireConnectivity); +} + +void MeshName::loadData(Mesh &mesh) +{ + readData(mesh, filename()); +} + +void MeshName::resetData(Mesh &mesh) +{ + for (auto &data : mesh.meshdata) { + data.dataVector.clear(); + } +} + +void MeshName::createDirectories() const +{ + auto dir = fs::path(filename()).parent_path(); + if (!dir.empty()) { + fs::create_directories(dir); + } +} + +void MeshName::save(const Mesh &mesh, const std::string &outputFileName) const +{ + + auto ext = fs::path(mesh.fname).extension(); + vtkSmartPointer grid; + if (ext == ".vtk") { + vtkSmartPointer reader = vtkSmartPointer::New(); + reader->SetFileName(mesh.fname.c_str()); + reader->Update(); + grid = reader->GetOutput(); + } else if (ext == ".vtu") { + vtkSmartPointer reader = vtkSmartPointer::New(); + reader->SetFileName(mesh.fname.c_str()); + reader->Update(); + grid = reader->GetOutput(); + } else { + ASTE_ERROR << "Unknown File Extension for file " << mesh.fname << " Extension should be .vtk or .vtu"; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + + for (const auto &meshdata : mesh.meshdata) { + vtkSmartPointer + vtkdata = vtkDoubleArray::New(); + vtkdata->SetName(meshdata.name.c_str()); + vtkdata->SetNumberOfComponents(meshdata.numcomp); + + std::vector pointData; + pointData.reserve(3); + for (vtkIdType i = 0; i < grid->GetNumberOfPoints(); i++) { + for (int j = 0; j < meshdata.numcomp; j++) { + pointData.push_back(meshdata.dataVector[i * meshdata.numcomp + j]); + } + vtkdata->InsertNextTuple(pointData.data()); + pointData.clear(); + } + + grid->GetPointData()->AddArray(vtkdata); + } + + // Write file + if (_context.isParallel()) { + vtkSmartPointer writer = + vtkSmartPointer::New(); + writer->SetInputData(grid); + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + auto outputFileName_withCont = outputFileName + "_" + std::to_string(rank) + ext.string(); + writer->SetFileName(outputFileName_withCont.c_str()); + writer->Write(); + + } else { + vtkSmartPointer writer = + vtkSmartPointer::New(); + writer->SetInputData(grid); + auto outputFileName_withCont = outputFileName + ext.string(); + writer->SetFileName(outputFileName_withCont.c_str()); + writer->SetFileTypeToBinary(); + writer->Write(); + } +} + +std::ostream &operator<<(std::ostream &out, const MeshName &mname) +{ + return out << mname.filename(); +} + +// --- BaseName + +MeshName BaseName::with(const ExecutionContext &context) const +{ + if (context.isParallel()) { + return {_bname + "_" + std::to_string(context.rank), ".vtu", context}; + } else { + return {_bname, ".vtk", context}; + } +} + +std::vector BaseName::findAll(const ExecutionContext &context) const +{ + if (!context.isParallel()) { + // Check single timestep/meshfiles first + std::vector extensions{".vtk", ".vtu"}; + // Case: a single mesh + for (const auto &ext : extensions) { + if (fs::is_regular_file(_bname + ext)) { + return {MeshName{_bname, ext, context}}; + } + + // Check multiple timesteps + std::vector meshNames; + { + auto initMeshName = std::string{_bname + ".init"}; + if (fs::is_regular_file(initMeshName + ext)) + meshNames.emplace_back(initMeshName, ext, context); + } + for (int t = 1; true; ++t) { + std::string stepMeshName = _bname + ".dt" + std::to_string(t); + if (!fs::is_regular_file(stepMeshName + ext)) + break; + meshNames.emplace_back(stepMeshName, ext, context); + } + if (!meshNames.empty()) { + ASTE_INFO << "Total number of detected meshes: " << meshNames.size() << '\n'; + return meshNames; + } + } + + } else { // Parallel Case + // Check if there is a single mesh + std::string ext{".vtu"}; + std::string rankMeshName{_bname + "_" + std::to_string(context.rank)}; + if (fs::is_regular_file(rankMeshName + ext)) { + return {MeshName{rankMeshName, ext, context}}; + } + // Check multiple timesteps + std::vector meshNames; + { + auto initMeshName = std::string{_bname + ".init" + "_" + std::to_string(context.rank)}; + if (fs::is_regular_file(initMeshName + ext)) + meshNames.emplace_back(initMeshName, ext, context); + } + for (int t = 1; true; ++t) { + std::string rankMeshName{_bname + ".dt" + std::to_string(t) + "_" + std::to_string(context.rank)}; + if (!fs::is_regular_file(rankMeshName + ext)) + break; + meshNames.emplace_back(rankMeshName, ext, context); + } + ASTE_INFO << "Total number of detected meshes: " << meshNames.size() << '\n'; + return meshNames; + } + ASTE_ERROR << "Unable to handle basename " << _bname << " no meshes found"; + MPI_Finalize(); + std::exit(EXIT_FAILURE); +} + +std::string Mesh::previewData(std::size_t max) const +{ + + if (meshdata.empty() || max == 0) + return ""; + + std::stringstream oss; + for (const auto &data : meshdata) { + oss << data.name; + oss << data.dataVector.front(); + for (size_t i = 1; i < std::min(max, data.dataVector.size()); ++i) + oss << ", " << data.dataVector[i]; + oss << " ..."; + } + return oss.str(); +} + +std::string Mesh::previewData(const MeshData &data, std::size_t max) const +{ + + if (data.dataVector.empty() || max == 0) + return ""; + + std::stringstream oss; + oss << data.name << " "; + oss << data.dataVector.front(); + for (size_t i = 1; i < std::min(max, data.dataVector.size()); ++i) + oss << ", " << data.dataVector[i]; + oss << " ..."; + + return oss.str(); +} + +std::string Mesh::summary() const +{ + + std::stringstream oss; + oss << positions.size() << " Vertices, " << meshdata.size() << " Data arrays, " << edges.size() << " Edges, " << triangles.size() << " Triangles " << quadrilaterals.size() << " Quadrilaterals "; + return oss.str(); +} + +/// Creates a unique and element-wise ordered set of undirected edges. +std::vector gather_unique_edges(const Mesh &mesh) +{ + std::vector sorted; + sorted.reserve(mesh.edges.size() + 3 * mesh.triangles.size()); + + for (auto const &edge : mesh.edges) { + const auto a = edge[0]; + const auto b = edge[1]; + sorted.push_back(Mesh::Edge{std::min(a, b), std::max(a, b)}); + } + + for (auto const &triangle : mesh.triangles) { + const auto a = triangle[0]; + const auto b = triangle[1]; + const auto c = triangle[2]; + sorted.push_back(Mesh::Edge{std::min(a, b), std::max(a, b)}); + sorted.push_back(Mesh::Edge{std::min(a, c), std::max(a, c)}); + sorted.push_back(Mesh::Edge{std::min(b, c), std::max(b, c)}); + } + + for (auto const &quadrilateral : mesh.quadrilaterals) { + const auto a = quadrilateral[0]; + const auto b = quadrilateral[1]; + const auto c = quadrilateral[2]; + const auto d = quadrilateral[3]; + sorted.push_back(Mesh::Edge{std::min(a, b), std::max(a, b)}); + sorted.push_back(Mesh::Edge{std::min(a, d), std::max(a, d)}); + sorted.push_back(Mesh::Edge{std::min(b, c), std::max(b, c)}); + sorted.push_back(Mesh::Edge{std::min(c, d), std::max(c, d)}); + } + + std::sort(sorted.begin(), sorted.end(), EdgeCompare()); + auto end = std::unique(sorted.begin(), sorted.end()); + return std::vector(sorted.begin(), end); +} + +} // namespace aste diff --git a/src/mesh.hpp b/src/mesh.hpp new file mode 100644 index 00000000..a346c0f0 --- /dev/null +++ b/src/mesh.hpp @@ -0,0 +1,172 @@ +#pragma once + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "logger.hpp" + +namespace aste { + +namespace fs = boost::filesystem; +class BaseName; +struct Mesh; +class MeshName; +struct MeshData; + +class MeshException : public std::runtime_error { +public: + explicit MeshException(const std::string &what_arg) + : std::runtime_error(what_arg){}; +}; +/** + * @brief Information about current run MPI size and rank of the process + * + */ +struct ExecutionContext { + ExecutionContext() = default; + ExecutionContext(int rank, int size) + : rank(rank), size(size) + { + assert(0 <= rank && rank < size); + }; + int rank{0}; + int size{1}; + bool isParallel() const + { + return size > 1; + } +}; + +class MeshName { +public: + MeshName(std::string meshname, std::string extension, const ExecutionContext &context) + : _mname(std::move(meshname)), _ext(std::move(extension)), _context(context) {} + + std::string filename() const; + + void loadMesh(Mesh &mesh, const int dim, const bool requireConnectivity); + void loadData(Mesh &mesh); + void resetData(Mesh &mesh); + void save(const Mesh &mesh, const std::string &outputFilename) const; + +private: + void createDirectories() const; + + std::string _mname; + std::string _ext; + const ExecutionContext _context; + + friend BaseName; +}; + +/** + * @brief Whether data is read or write type + * + */ +enum datatype { READ, + WRITE, + GRADIENT, +}; +/** + * @brief Information about data in mesh. + * Contains whether data is write or read type + * Number of components of data + * Name of data + * Data context (dataVector) + * Data ID in preCICE + */ +struct MeshData { + MeshData(datatype type, int numcomp, std::string name, int dataID) + : type(type), numcomp(numcomp), name(std::move(name)), dataID(dataID){}; + MeshData(datatype type, int numcomp, std::string name, int dataID, int gradDimension) + : type(type), numcomp(numcomp), name(std::move(name)), dataID(dataID), gradDimension(gradDimension){}; + + datatype type; + int numcomp; + std::string name; // name of data + std::vector dataVector; + int dataID; // preCICE dataID + int gradDimension; // Dimensions for gradient data +}; + +std::ostream &operator<<(std::ostream &out, const MeshName &mname); + +class BaseName { +public: + BaseName(std::string basename) + : _bname(std::move(basename)) {} + + MeshName with(const ExecutionContext &context) const; + + std::vector findAll(const ExecutionContext &context) const; + +private: + std::string _bname; +}; + +/** + * @brief Datastructure for storing meshes in ASTE + * + */ +struct Mesh { + using Vertex = std::vector; + using VID = std::vector::size_type; + using Edge = std::array; + using Triangle = std::array; + using Quad = std::array; + using Tetra = std::array; + std::vector positions; + std::vector edges; + std::vector triangles; + std::vector quadrilaterals; + std::vector tetrahedra; + std::string fname; + std::vector meshdata; + + std::string previewData(std::size_t max = 10) const; + std::string previewData(const MeshData &data, std::size_t max = 10) const; + std::string summary() const; +}; + +struct EdgeCompare { + bool operator()(const Mesh::Edge &lhs, const Mesh::Edge &rhs) const + { + return lhs[0] < rhs[0] || (lhs[0] == rhs[0] && lhs[1] < rhs[1]); + } +}; + +std::vector gather_unique_edges(const Mesh &mesh); + +} // namespace aste diff --git a/src/mesh.py b/src/mesh.py deleted file mode 100644 index 72ab3a09..00000000 --- a/src/mesh.py +++ /dev/null @@ -1,49 +0,0 @@ -import numpy as np - -def GC(order, element_size, domain_size, domain_start = 0): - """ Returns coordinates for a 2d Gauss-Chebyshev mesh. """ - assert(domain_size % element_size == 0) - nodes = np.arange( 1, order + 1 ) - cheb = 0.5 * element_size * np.cos( np.pi * (2*nodes-1)/ (2*order) ) - coords = np.array([]) - for element in range(int(domain_size/element_size)): - coords = np.append(coords, cheb + ((0.5+element) * element_size)) - - coords += domain_start - np.ndarray.sort(coords) - print("Gauss-Chebyshev mesh with", len(coords), "points, h_max =", np.max(coords[1:] - coords[:-1])) - return coords - -def GaussChebyshev_1D(order, element_size, domain_size, domain_start = 0): - """ Returns coordinates for a 1d Gauss-Chebyshev mesh. """ - assert(domain_size % element_size == 0) - nodes = np.polynomial.chebyshev.chebgauss(order)[0] # Get GC points on [-1;1] - nodes *= element_size / 2 # Scale from [-1;1] to element_size - - coords = np.array([]) - for element in range(int(domain_size // element_size)): - coords = np.append(coords, nodes + (0.5 + element) * element_size) - - coords += domain_start - np.ndarray.sort(coords) - print("Gauss-Chebyshev mesh with", len(coords), "points, h_max =", np.max(coords[1:] - coords[:-1])) - return coords - - -def GaussChebyshev_2D(order, element_size, domain_size, domain_start = 0): - """ Returns a 2d quadratic Gauss-Chebyshev mesh grid """ - x = GaussChebyshev_1D(order, element_size, domain_size, domain_start) - y = GaussChebyshev_1D(order, element_size, domain_size, domain_start) - xx, yy = np.meshgrid(x,y) - return xx, yy - - - -if __name__ == "__main__": - import pdb; pdb.set_trace() - assert(np.all(GaussChebyshev_1D(4, 2, 2, 0) == GC(4, 2, 2, 0))) - assert(np.all(GaussChebyshev_1D(4, 2, 2, 5) == GC(4, 2, 2, 5))) - assert(np.all(GaussChebyshev_1D(10, 2, 2, 5) == GC(10, 2, 2, 5))) - assert(np.all(GaussChebyshev_1D(4, 1, 2, 0) == GC(4, 1, 2, 0))) - assert(np.all(GaussChebyshev_1D(6, 3, 9, 8) == GC(6, 3, 9, 8))) - diff --git a/src/mesh_io.py b/src/mesh_io.py deleted file mode 100644 index bd0ebfb9..00000000 --- a/src/mesh_io.py +++ /dev/null @@ -1,181 +0,0 @@ -""" -Mesh I/O utility script. One can read meshes from .vtk, .txt, .vtu, .vtp,... files - and save to .txt, .vtk and .vtu -""" - -import os -import logging - - -def read_mesh(filename, tag = None): - """ - Returns Mesh Points, Mesh Cells, Mesh Celltypes, - Mesh Pointdata in this order - """ - if os.path.splitext(filename)[1] == ".txt": - return read_txt(filename) - else: - return read_vtk(filename, tag) - - -def write_mesh(filename, points, cells = None, cell_types = None, values = None): - if os.path.splitext(filename)[1] == ".txt": - return write_txt(filename, points, cells, values) - else: - return write_vtk(filename, points, cells, cell_types, values) - - -def read_vtk(filename, tag = None): - import vtk - vtkmesh = read_dataset(filename) - points = [] - cells = [] - pointdata = [] - cell_types = [] - points = [vtkmesh.GetPoint(i) for i in range(vtkmesh.GetNumberOfPoints())] - for i in range(vtkmesh.GetNumberOfCells()): - cell = vtkmesh.GetCell(i) - cell_type = cell.GetCellType() - if cell_type not in [vtk.VTK_LINE, vtk.VTK_TRIANGLE]: - continue - cell_types.append(cell_type) - entry = () - for j in range(cell.GetNumberOfPoints()): - entry += (cell.GetPointId(j),) - cells.append(entry) - if not tag: - # vtk Python utility method. Same as tag=="scalars" - fieldData = vtkmesh.GetPointData().GetScalars() - else: - fieldData = vtkmesh.GetPointData().GetAbstractArray(tag) - if fieldData: - for i in range(vtkmesh.GetNumberOfPoints()): - pointdata.append(fieldData.GetTuple1(i)) - return points, cells, cell_types, pointdata - - -def read_dataset(filename): - import vtk - extension = os.path.splitext(filename)[1] - if (extension == ".vtk"): # VTK Legacy format - reader = vtk.vtkDataSetReader() - elif (extension == ".vtp"): # VTK XML Poly format - reader = vtk.vtkXMLPolyDataReader() - elif (extension == ".vtu"): # VTK XML Unstructured format - reader = vtk.vtkXMLUnstructuredGridReader() - elif (extension == ".stl"): # Stereolithography format - reader = vtk.vtkSTLReader() - elif (extension == ".ply"): # Stanford triangle format - reader = vtk.vtkPLYReader() - elif (extension == ".obj"): # Wavefront OBJ format - reader = vtk.vtkOBJReader() - elif (extension == ".pvtu"): - reader = vtk.vtkXMLPUnstructuredGridReader() # Parallel XML format - else: - raise Exception("Unkown File extension: " + extension) - reader.SetFileName(filename) - reader.Update() - return reader.GetOutput() - - -def read_conn(filename): - try: - import vtk - except ImportError: - VTK_LINE = 3 - VTK_TRIANGLE = 5 - else: - VTK_LINE = vtk.VTK_LINE - VTK_TRIANGLE = vtk.VTK_TRIANGLE - - with open(filename, "r") as fh: - cells, cell_types = [], [] - for line in fh: - coords = tuple([int(e) for e in line.split(" ")]) - assert(len(coords) in [2, 3]) - cells.append(coords) - cell_types.append({2: VTK_LINE, 3: VTK_TRIANGLE}[len(coords)]) - assert(len(cells) == len(cell_types)) - return cells, cell_types - - -def read_txt(filename): - points = [] - cells = [] - cell_types = [] - pointdata = [] - with open(filename, "r") as fh: - for line in fh: - point = () - parts = line.split(" ") - for i in range(3): - point += (float(parts[i]),) - points.append(point) - if len(parts) > 3: - pointdata.append(float(parts[3])) - base, ext = os.path.splitext(filename) - connFileName = base + ".conn" + ext - if os.path.exists(connFileName): - cells, cell_types = read_conn(connFileName) - - return points, cells, cell_types, pointdata - - -def write_vtk(filename, points, cells = None, cell_types = None, pointdata = None, tag = None): - import vtk - data = vtk.vtkUnstructuredGrid() # is also vtkDataSet - scalars = vtk.vtkDoubleArray() - if tag: - scalars.SetName(tag) - vtkpoints = vtk.vtkPoints() - for i, point in enumerate(points): - vtkpoints.InsertPoint(i, point) - if pointdata is not None and len(pointdata) > 0: - scalars.InsertTuple1(i, pointdata[i]) - data.SetPoints(vtkpoints) - if cells: - cellArray = vtk.vtkCellArray() - for i, cell in enumerate(cells): - vtkCell = vtk.vtkGenericCell() - vtkCell.SetCellType(cell_types[i]) - idList = vtk.vtkIdList() - for cellid in cell: - idList.InsertNextId(cellid) - vtkCell.SetPointIds(idList) - cellArray.InsertNextCell(vtkCell) - data.SetCells(cell_types, cellArray) - pointData = data.GetPointData() - pointData.SetScalars(scalars) - write_dataset(filename, data) - - writer = vtk.vtkUnstructuredGridWriter() - writer.SetFileName(filename) - writer.SetInputData(data) - writer.Write() - - -def write_dataset(filename, dataset): - import vtk - extension = os.path.splitext(filename)[1] - if (extension == ".vtk"): # VTK Legacy format - writer = vtk.vtkUnstructuredGridWriter() - elif (extension == ".vtu"): # VTK XML Unstructured Grid format - writer = vtk.vtkXMLUnstructuredGridWriter() - else: - raise Exception("Unkown File extension: " + extension) - writer.SetFileName(filename) - writer.SetInputData(dataset) - writer.Write() - -def write_txt(filename, points, cells = [], pointdata = None): - with open(filename, "w") as fh: - for i, point in enumerate(points): - entry = (str(point[0]), str(point[1]), str(point[2])) - if pointdata is not None and len(pointdata) > 0: - entry += (str(float(pointdata[i])),) - fh.write(" ".join(entry) + "\n") - - base, ext = os.path.splitext(filename) - connFileName = base + ".conn" + ext - with open(connFileName, "w") as fh: - fh.writelines([" ".join(map(str,cell))+"\n" for cell in cells]) diff --git a/src/metisAPI.cpp b/src/metisAPI.cpp index ecc5f1ee..d912d97b 100644 --- a/src/metisAPI.cpp +++ b/src/metisAPI.cpp @@ -1,19 +1,20 @@ -#include #include +#include #include -extern "C" void partitionMetis(idx_t cell_count, idx_t point_count, idx_t* cellptr, idx_t* celldata, idx_t nparts, idx_t* point_partition); -extern "C" int typewidth(); +extern "C" void partitionMetis(idx_t cell_count, idx_t point_count, idx_t *cellptr, idx_t *celldata, idx_t nparts, idx_t *point_partition); +extern "C" int typewidth(); -void partitionMetis(idx_t cell_count, idx_t point_count, idx_t* cellptr, idx_t* celldata, idx_t nparts, idx_t* point_partition) +void partitionMetis(idx_t cell_count, idx_t point_count, idx_t *cellptr, idx_t *celldata, idx_t nparts, idx_t *point_partition) { - idx_t options[METIS_NOPTIONS]; - METIS_SetDefaultOptions(options); - std::vector cell_partition(cell_count); - idx_t objval; - int result = METIS_PartMeshNodal(&cell_count, &point_count, cellptr, celldata, 0, 0, &nparts, 0, options, &objval, cell_partition.data(), point_partition); + idx_t options[METIS_NOPTIONS]; + METIS_SetDefaultOptions(options); + std::vector cell_partition(cell_count); + idx_t objval; + // TODO: Check return value of the function (and potentially add an assert) + METIS_PartMeshNodal(&cell_count, &point_count, cellptr, celldata, 0, 0, &nparts, 0, options, &objval, cell_partition.data(), point_partition); } int typewidth() { - return IDXTYPEWIDTH; + return IDXTYPEWIDTH; } diff --git a/src/modes.cpp b/src/modes.cpp new file mode 100644 index 00000000..b728b3ce --- /dev/null +++ b/src/modes.cpp @@ -0,0 +1,391 @@ +#include "modes.hpp" +#include +#include "logger.hpp" +#include "utilities.hpp" + +void aste::runReplayMode(const aste::ExecutionContext &context, const std::string &asteConfigName) +{ + aste::asteConfig asteConfiguration; + asteConfiguration.load(asteConfigName); + const std::string participantName = asteConfiguration.participantName; + + precice::SolverInterface preciceInterface(participantName, asteConfiguration.preciceConfigFilename, context.rank, context.size); + const int dim = preciceInterface.getDimensions(); + + size_t minMeshSize{0}; + std::vector vertexIDs; + double dt; + + for (auto &asteInterface : asteConfiguration.asteInterfaces) { + const std::string meshname = asteInterface.meshFilePrefix; + asteInterface.meshes = aste::BaseName(meshname).findAll(context); + if (asteInterface.meshes.empty()) { + ASTE_ERROR << "ERROR: Could not find meshes for name: " << meshname; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + asteInterface.meshID = preciceInterface.getMeshID(asteInterface.meshName); + + for (const auto &dataname : asteInterface.writeVectorNames) { + const int dataID = preciceInterface.getDataID(dataname, asteInterface.meshID); + asteInterface.mesh.meshdata.emplace_back(aste::datatype::WRITE, dim, dataname, dataID); + +#if PRECICE_VERSION_GREATER_EQUAL(2, 5, 0) + if (preciceInterface.isGradientDataRequired(dataID)) { + asteInterface.writeVectorNames.push_back(dataname + "_gradient"); + asteInterface.mesh.meshdata.emplace_back(aste::datatype::GRADIENT, dim, dataname, dataID, dim); + } +#endif + } + + for (const auto &dataname : asteInterface.readVectorNames) { + const int dataID = preciceInterface.getDataID(dataname, asteInterface.meshID); + asteInterface.mesh.meshdata.emplace_back(aste::datatype::READ, dim, dataname, dataID); + } + + for (const auto &dataname : asteInterface.writeScalarNames) { + const int dataID = preciceInterface.getDataID(dataname, asteInterface.meshID); + asteInterface.mesh.meshdata.emplace_back(aste::datatype::WRITE, 1, dataname, dataID); + +#if PRECICE_VERSION_GREATER_EQUAL(2, 5, 0) + if (preciceInterface.isGradientDataRequired(dataID)) { + asteInterface.writeVectorNames.push_back(dataname + "_gradient"); + asteInterface.mesh.meshdata.emplace_back(aste::datatype::GRADIENT, 1, dataname, dataID, dim); + } +#endif + } + for (const auto &dataname : asteInterface.readScalarNames) { + const int dataID = preciceInterface.getDataID(dataname, asteInterface.meshID); + asteInterface.mesh.meshdata.emplace_back(aste::datatype::READ, 1, dataname, dataID); + } + + ASTE_INFO << "Loading mesh from " << asteInterface.meshes.front().filename(); + const bool requireConnectivity = preciceInterface.isMeshConnectivityRequired(asteInterface.meshID); + asteInterface.meshes.front().loadMesh(asteInterface.mesh, dim, requireConnectivity); + ASTE_INFO << "The loaded mesh " << asteInterface.meshes.front().filename() << " contains: " << asteInterface.mesh.summary(); + vertexIDs = setupMesh(preciceInterface, asteInterface.mesh, asteInterface.meshID); + ASTE_DEBUG << "Mesh setup completed on Rank " << context.rank; + minMeshSize = std::max(minMeshSize, asteInterface.meshes.size()); + } + + dt = preciceInterface.initialize(); + std::size_t round{0}; + + ASTE_DEBUG << "Looking for dt = " << asteConfiguration.startdt; + for (const auto &mesh : asteConfiguration.asteInterfaces.front().meshes) { + if (mesh.filename().find(std::to_string(asteConfiguration.startdt)) == std::string::npos) + round++; + else + break; + } + ASTE_DEBUG << "Found in position " << round << "\n"; + ASTE_INFO << "ASTE Start mesh is " << asteConfiguration.asteInterfaces.front().meshes[round].filename(); + ASTE_INFO << "ASTE Final mesh is " << asteConfiguration.asteInterfaces.front().meshes.back().filename(); + + if (preciceInterface.isActionRequired(precice::constants::actionWriteInitialData())) { + if (round == 0) { + ASTE_ERROR << "Starting from dt = " << std::to_string(asteConfiguration.startdt) << " but previous timestep \".init\" or " << std::to_string(asteConfiguration.startdt - 1) << " was not found. Please make sure the relevant Mesh exists."; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + ASTE_INFO << "Write initial data for participant " << participantName; + for (auto &asteInterface : asteConfiguration.asteInterfaces) { + asteInterface.meshes[round - 1].loadData(asteInterface.mesh); + ASTE_INFO << "The mesh contains: " << asteInterface.mesh.summary(); + for (const auto &meshdata : asteInterface.mesh.meshdata) { + if (meshdata.type == aste::datatype::WRITE) { + switch (meshdata.numcomp) { + case 1: + assert(meshdata.dataVector.size() == vertexIDs.size()); + preciceInterface.writeBlockScalarData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + break; + default: + assert(meshdata.dataVector.size() == vertexIDs.size() * dim); + preciceInterface.writeBlockVectorData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + break; + } + } + } + ASTE_DEBUG << "Data written: " << asteInterface.mesh.previewData(); + } + preciceInterface.markActionFulfilled(precice::constants::actionWriteInitialData()); + } + + preciceInterface.initializeData(); + const std::string &coric = precice::constants::actionReadIterationCheckpoint(); + const std::string &cowic = precice::constants::actionWriteIterationCheckpoint(); + + while (preciceInterface.isCouplingOngoing() && (round < minMeshSize)) { + if (preciceInterface.isActionRequired(cowic)) { + ASTE_ERROR << "Implicit coupling schemes cannot be used with ASTE"; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + for (auto &asteInterface : asteConfiguration.asteInterfaces) { + ASTE_INFO << "Read mesh for t= " << round << " from " << asteInterface.meshes[round]; + asteInterface.meshes[round].resetData(asteInterface.mesh); + asteInterface.meshes[round].loadData(asteInterface.mesh); + ASTE_DEBUG << "This roundmesh contains: " << asteInterface.mesh.summary(); + + for (const auto &meshdata : asteInterface.mesh.meshdata) { + if (meshdata.type == aste::datatype::WRITE) { + switch (meshdata.numcomp) { + case 1: + assert(meshdata.dataVector.size() == vertexIDs.size()); + preciceInterface.writeBlockScalarData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + break; + default: + assert(meshdata.dataVector.size() == vertexIDs.size() * dim); + preciceInterface.writeBlockVectorData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + break; + } + } +#if PRECICE_VERSION_GREATER_EQUAL(2, 5, 0) + else if (meshdata.type == aste::datatype::GRADIENT) { + switch (meshdata.numcomp) { + case 1: + assert(meshdata.dataVector.size() == vertexIDs.size() * dim); + // preciceInterface.writeBlockScalarData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + preciceInterface.writeBlockScalarGradientData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + break; + default: + assert(meshdata.dataVector.size() == vertexIDs.size() * dim * dim); + preciceInterface.writeBlockVectorGradientData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + break; + } + } +#endif + ASTE_DEBUG << "Data written: " << asteInterface.mesh.previewData(meshdata); + } + } + dt = preciceInterface.advance(dt); + if (preciceInterface.isActionRequired(coric)) { + ASTE_ERROR << "Implicit coupling schemes cannot be used with ASTE"; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + for (auto &asteInterface : asteConfiguration.asteInterfaces) { + for (auto &meshdata : asteInterface.mesh.meshdata) { + if (meshdata.type == aste::datatype::READ) { + switch (meshdata.numcomp) { + case 1: + meshdata.dataVector.resize(vertexIDs.size()); + preciceInterface.readBlockScalarData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + break; + default: + meshdata.dataVector.resize(vertexIDs.size() * dim); + preciceInterface.readBlockVectorData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + break; + } + ASTE_DEBUG << "Data read: " << asteInterface.mesh.previewData(meshdata); + } + } + } + round++; + } + preciceInterface.finalize(); +}; + +void aste::runMapperMode(const aste::ExecutionContext &context, const OptionMap &options) +{ + const std::string meshname = options["mesh"].as(); + const std::string participantName = options["participant"].as(); + const std::string dataname = options["data"].as(); + const bool isVector = options["vector"].as(); + const std::string preciceConfig = options["precice-config"].as(); + + aste::asteConfig asteConfiguration; + + // Create and configure solver interface + precice::SolverInterface preciceInterface(participantName, preciceConfig, context.rank, context.size); + const int dim = preciceInterface.getDimensions(); + + if (participantName == "A") { + asteConfiguration.participantName = "A"; + asteConfiguration.preciceConfigFilename = preciceConfig; + aste::asteInterface asteInterface; + asteInterface.meshName = "A-Mesh"; + asteInterface.meshFilePrefix = meshname; + asteInterface.meshID = preciceInterface.getMeshID(asteInterface.meshName); + asteInterface.meshes = aste::BaseName(meshname).findAll(context); + + const int dataID = preciceInterface.getDataID("Data", asteInterface.meshID); + if (isVector) { + asteInterface.writeVectorNames.push_back(dataname); + asteInterface.mesh.meshdata.emplace_back(aste::datatype::WRITE, dim, dataname, dataID); + +#if PRECICE_VERSION_GREATER_EQUAL(2, 5, 0) + if (preciceInterface.isGradientDataRequired(dataID)) { + asteInterface.writeVectorNames.push_back(dataname + "_gradient"); + asteInterface.mesh.meshdata.emplace_back(aste::datatype::GRADIENT, dim, dataname, dataID, dim); + } +#endif + } else { + asteInterface.writeScalarNames.push_back(dataname); + asteInterface.mesh.meshdata.emplace_back(aste::datatype::WRITE, 1, dataname, dataID); + +#if PRECICE_VERSION_GREATER_EQUAL(2, 5, 0) + if (preciceInterface.isGradientDataRequired(dataID)) { + asteInterface.writeVectorNames.push_back(dataname + "_gradient"); + asteInterface.mesh.meshdata.emplace_back(aste::datatype::GRADIENT, 1, dataname, dataID, dim); + } +#endif + } + asteConfiguration.asteInterfaces.push_back(asteInterface); + } else if (participantName == "B") { + asteConfiguration.participantName = "B"; + asteConfiguration.preciceConfigFilename = preciceConfig; + aste::asteInterface asteInterface; + asteInterface.meshName = "B-Mesh"; + asteInterface.meshFilePrefix = meshname; + asteInterface.meshID = preciceInterface.getMeshID(asteInterface.meshName); + asteInterface.meshes = aste::BaseName(meshname).findAll(context); + + const int dataID = preciceInterface.getDataID("Data", asteInterface.meshID); + if (isVector) { + asteInterface.writeVectorNames.push_back(dataname); + asteInterface.mesh.meshdata.emplace_back(aste::datatype::READ, dim, dataname, dataID); + } else { + asteInterface.writeScalarNames.push_back(dataname); + asteInterface.mesh.meshdata.emplace_back(aste::datatype::READ, 1, dataname, dataID); + } + asteConfiguration.asteInterfaces.push_back(asteInterface); + } + + auto asteInterface = asteConfiguration.asteInterfaces.front(); + ASTE_INFO << "Loading mesh from " << asteInterface.meshes.front().filename(); + const bool requireConnectivity = preciceInterface.isMeshConnectivityRequired(asteInterface.meshID); + asteInterface.meshes.front().loadMesh(asteInterface.mesh, dim, requireConnectivity); + asteInterface.meshes.front().loadData(asteInterface.mesh); + ASTE_INFO << "The loaded mesh " << asteInterface.meshes.front().filename() << " contains: " << asteInterface.mesh.summary(); + auto vertexIDs = aste::setupMesh(preciceInterface, asteInterface.mesh, asteInterface.meshID); + ASTE_DEBUG << "Mesh setup completed on Rank " << context.rank; + double dt = preciceInterface.initialize(); + + if (preciceInterface.isActionRequired(precice::constants::actionWriteInitialData())) { + ASTE_DEBUG << "Write initial data for participant " << participantName; + for (auto const &asteInterface : asteConfiguration.asteInterfaces) { + for (const auto &meshdata : asteInterface.mesh.meshdata) { + if (meshdata.type == aste::datatype::WRITE) { + switch (meshdata.numcomp) { + case 1: + assert(meshdata.dataVector.size() == vertexIDs.size()); + preciceInterface.writeBlockScalarData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + break; + default: + assert(meshdata.dataVector.size() == vertexIDs.size() * dim); + preciceInterface.writeBlockVectorData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + break; + } + } +#if PRECICE_VERSION_GREATER_EQUAL(2, 5, 0) + else if (meshdata.type == aste::datatype::GRADIENT) { + switch (meshdata.numcomp) { + case 1: + assert(meshdata.dataVector.size() == vertexIDs.size() * dim); + // preciceInterface.writeBlockScalarData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + preciceInterface.writeBlockScalarGradientData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + break; + default: + assert(meshdata.dataVector.size() == vertexIDs.size() * dim * dim); + preciceInterface.writeBlockVectorGradientData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + break; + } + } +#endif + } + ASTE_DEBUG << "Data written: " << asteInterface.mesh.previewData(); + } + preciceInterface.markActionFulfilled(precice::constants::actionWriteInitialData()); + } + + preciceInterface.initializeData(); + + const std::string &coric = precice::constants::actionReadIterationCheckpoint(); + const std::string &cowic = precice::constants::actionWriteIterationCheckpoint(); + size_t round = 0; + + while (preciceInterface.isCouplingOngoing() && round < asteInterface.meshes.size()) { + if (preciceInterface.isActionRequired(cowic)) { + ASTE_ERROR << "Implicit coupling schemes cannot be used with ASTE"; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + for (auto &asteInterface : asteConfiguration.asteInterfaces) { + ASTE_INFO << "Read mesh for t=" << round << " from " << asteInterface.meshes[round]; + asteInterface.meshes[round].resetData(asteInterface.mesh); + asteInterface.meshes[round].loadData(asteInterface.mesh); + ASTE_DEBUG << "This roundmesh contains: " << asteInterface.mesh.summary(); + + for (const auto &meshdata : asteInterface.mesh.meshdata) { + if (meshdata.type == aste::datatype::WRITE) { + switch (meshdata.numcomp) { + case 1: + assert(meshdata.dataVector.size() == vertexIDs.size()); + preciceInterface.writeBlockScalarData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + break; + default: + assert(meshdata.dataVector.size() == vertexIDs.size() * dim); + preciceInterface.writeBlockVectorData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + break; + } + ASTE_DEBUG << "Data written: " << asteInterface.mesh.previewData(meshdata); + } +#if PRECICE_VERSION_GREATER_EQUAL(2, 5, 0) + else if (meshdata.type == aste::datatype::GRADIENT) { + switch (meshdata.numcomp) { + case 1: + assert(meshdata.dataVector.size() == vertexIDs.size() * dim); + preciceInterface.writeBlockScalarGradientData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + break; + default: + assert(meshdata.dataVector.size() == vertexIDs.size() * dim * dim); + preciceInterface.writeBlockVectorGradientData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + break; + } + ASTE_DEBUG << "Gradient data written: " << asteInterface.mesh.previewData(meshdata); + } +#endif + } + } + dt = preciceInterface.advance(dt); + if (preciceInterface.isActionRequired(coric)) { + ASTE_ERROR << "Implicit coupling schemes cannot be used with ASTE"; + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + for (auto &asteInterface : asteConfiguration.asteInterfaces) { + for (auto &meshdata : asteInterface.mesh.meshdata) { + if (meshdata.type == aste::datatype::READ) { + switch (meshdata.numcomp) { + case 1: + meshdata.dataVector.resize(vertexIDs.size()); + preciceInterface.readBlockScalarData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + break; + default: + meshdata.dataVector.resize(vertexIDs.size() * dim); + preciceInterface.readBlockVectorData(meshdata.dataID, vertexIDs.size(), vertexIDs.data(), meshdata.dataVector.data()); + break; + } + ASTE_DEBUG << "Data read: " << asteInterface.mesh.previewData(meshdata); + } + } + } + round++; + } + + // Write out results in same format as data was read + if (asteConfiguration.participantName == "B") { + auto meshname = asteConfiguration.asteInterfaces.front().meshes.front(); + auto filename = fs::path(options["output"].as()); + if (context.rank == 0 && fs::exists(filename)) { + if (context.isParallel() && !filename.parent_path().empty()) { + auto dir = filename.parent_path(); + fs::remove_all(dir); + fs::create_directory(dir); + } else if (!context.isParallel()) { + fs::remove(filename); + } + } + MPI_Barrier(MPI_COMM_WORLD); + // + ASTE_INFO << "Writing results to " << options["output"].as(); + meshname.save(asteConfiguration.asteInterfaces.front().mesh, options["output"].as()); + } + preciceInterface.finalize(); + return; +} diff --git a/src/modes.hpp b/src/modes.hpp new file mode 100644 index 00000000..7753c55a --- /dev/null +++ b/src/modes.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include + +#include "common.hpp" +#include "configreader.hpp" +#include "logger.hpp" +#include "mesh.hpp" +#include "utilities.hpp" + +#include "precice/SolverInterface.hpp" + +#ifndef PRECICE_VERSION_GREATER_EQUAL +// compatibility with older versions +#define PRECICE_VERSION_GREATER_EQUAL(x, y, z) FALSE +#endif + +namespace aste { +/** + * @brief The function runs ASTE in replay mode where aste simulates a participant in preCICE + * + * @param context + * @param asteConfigName ASTE configuration filename + */ +void runReplayMode(const aste::ExecutionContext &context, const std::string &asteConfigName); + +/** + * @brief The function runs ASTE in mapper mode in which a given data is mapped from participant A to B. + * + * @param context + * @param options + */ +void runMapperMode(const aste::ExecutionContext &context, const OptionMap &options); +} // namespace aste diff --git a/src/partition_mesh.py b/src/partition_mesh.py deleted file mode 100755 index 14755166..00000000 --- a/src/partition_mesh.py +++ /dev/null @@ -1,305 +0,0 @@ -#!/usr/bin/env python3 -import argparse, logging, math, os -import numpy as np -import shutil -from ctypes import * -import mesh_io - -def main(): - args = parse_args() - logging.basicConfig(level=getattr(logging, args.logging)) - if len(args.in_meshname) > 1 and args.out_meshname: - logging.warn("--out ignored") - mesh_names = args.in_meshname - for mesh_name in mesh_names: - assert os.path.isfile(mesh_name), ("Invalid filename: " + mesh_name) - algorithm = args.algorithm - if not algorithm: - logging.info("No algorithm given. Defaulting to \"meshfree\"") - algorithm = "meshfree" - rootmesh = read_mesh(mesh_names[0], args.tag) - if args.numparts > 1: - part = partition(rootmesh, args.numparts, algorithm) - else: - part = [0] * len(rootmesh.points) - - for mesh_name in mesh_names: - logging.info("Processing mesh " + mesh_name) - mesh = read_mesh(mesh_name, args.tag) - logging.debug("Checking if meshes are matching...") - assert mesh.points == rootmesh.points, ("Non-matching meshes detected!") - meshes = apply_partition(mesh, part, args.numparts) - if len(mesh_names) > 1 or not args.out_meshname: - out_meshname = os.path.splitext(mesh_name)[0] - logging.info("Writing output to: " + out_meshname) - # logging.info("No --out given. Setting output to: " + out_meshname) - else: - out_meshname = args.out_meshname - write_meshes(meshes, out_meshname) - - -class Mesh: - """ - A Mesh consists of: - - Points: A list of tuples of floats representing coordinates of points - - Cells: A list of tuples of ints representing mesh elements - - Pointdata: A list of floats representing data values at the respective point - """ - def __init__(self, points = None, cells = None, cell_types = None, pointdata = None): - if points is not None: - self.points = points - else: - self.points = [] - if cells is not None: - assert(cell_types is not None) - self.cells = cells - self.cell_types = cell_types - else: - self.cells = [] - self.cell_types = [] - if pointdata is not None: - self.pointdata = pointdata - else: - self.pointdata = [] - - def __str__(self): - return "Mesh with {} Points and {} Cells ({} Cell Types)".format(len(self.points), len(self.cells), len(self.cell_types)) - - -def read_mesh(filename, tag): - points, cells, cell_types, pointdata = mesh_io.read_mesh(filename, tag) - return Mesh(points, cells, cell_types, pointdata) - - - -def partition(mesh, numparts, algorithm): - """ - Partitions a mesh using METIS or kmeans. This does not call METIS directly, - but instead uses a small C++ Wrapper libmetisAPI.so for convenience. - This shared library must be provided if this function should be called. - """ - if algorithm == "meshfree": - return partition_kmeans(mesh, numparts) - elif algorithm == "topology": - return partition_metis(mesh, numparts) - elif algorithm == "uniform": - labels = partition_uniform(mesh, numparts) - if labels is None: - return partition(mesh, numparts, "meshfree") - return labels - - -def partition_kmeans(mesh, numparts): - """ Partitions a mesh using k-means. This is a meshfree algorithm and requires scipy""" - from scipy.cluster.vq import kmeans2 - points = np.copy(mesh.points) - points = reduce_dimension(points) - _, label = kmeans2(points, numparts) - return label - - -def reduce_dimension_simple(mesh): - """ - A simple, efficient algorithm for a dimension reduction for a mesh - with one or more "dead dimensions" - """ - testP = mesh[0] - dead_dims = np.argwhere(np.abs(np.array(testP)) < 1e-9) - for point in mesh: - current_dead_dims = np.argwhere(np.abs(np.array(point)) < 1e-9) - dead_dims = np.intersect1d(dead_dims, current_dead_dims) - if len(dead_dims) == 0: - return mesh - mesh = np.array(mesh) - full = np.array([0,1,2]) - mask = np.setdiff1d(full, dead_dims) - return mesh[:,mask] - - -def reduce_dimension(mesh): - """ - This function gets a list of points in 3d and if all of them are within one plane it - returns a list of 2d points in the plane, else the unmodified list is returned. - """ - pA, pB = mesh[:2] - pC = mesh[-1] - pA = np.array(pA) - AB = pB - pA - AC = pC - pA - n = np.cross(AB, AC) - # Every point x in the plane must fulfill (x - pA) * n = 0 - for x in mesh: - if not np.dot(x - pA, n) == 0: - return mesh - else: # All Points within plane - # Transform mesh so all points have form (0, y, z) - # Compute Euler-Rodrigues rotation matrix - n /= np.linalg.norm(n) # Normalize - zUnit = np.array((0,0,1)) - phi = math.acos(np.dot(n, zUnit)) - logging.info("Rotating mesh with phi = " + str(360 * phi/(2 * math.pi)) + " degrees.") - axis = np.cross(n, zUnit) - axis /= np.linalg.norm(axis) - a = math.cos(phi/2) - b = math.sin(phi/2) * axis[0] - c = math.sin(phi/2) * axis[1] - d = math.sin(phi/2) * axis[2] - rotMat = np.array(( - (a**2 + b**2 - c**2 - d**2, 2*(b*c - a*d), 2*(b*d + a*c)), - (2*(b*c + a*d), a**2 + c**2 - b**2 - d**2, 2*(c*d - a*b)), - (2*(b*d - a*c), 2*(c*d + a*b), a**2 + d**2 - b**2 - c**2))) - for i, x in enumerate(mesh): # Translate & Rotate - x -= pA - x = x @ rotMat - mesh[i] = x - return mesh[:,:-1] - - -def partition_metis(mesh, numparts): - """ - Partitions a mesh using METIS. This does not call METIS directly, - but instead uses a small C++ Wrapper libmetisAPI.so for convenience. - This shared library must be provided if this function should be called. - """ - cellPtr = [0] - cellData = [] - if len(mesh.cells) == 0: - logging.warning("No topology information provided. Partitioning with metis will likely provide bad partition"); - for i in range(len(mesh.cells)): - cell = mesh.cells[i] - cellData += list(cell) - cellPtr.append(cellPtr[-1] + len(cell)) - libmetis = cdll.LoadLibrary(os.path.abspath("libmetisAPI.so")) - idx_t = c_int if libmetis.typewidth() == 32 else c_longlong - cell_count = idx_t(len(mesh.cells)) - point_count = idx_t(len(mesh.points)) - num_parts = idx_t(numparts) - partition = (idx_t * len(mesh.points))() - cell_ptr = (idx_t * len(cellPtr))(*cellPtr) - cell_data = (idx_t * len(cellData))(*cellData) - libmetis.partitionMetis(cell_count, point_count, cell_ptr, cell_data, num_parts, partition) - arr = np.ctypeslib.as_array(partition) - return arr - -def partition_uniform(mesh, numparts): - """ - Partitions a mesh assuming it is uniform. It must be two-dimensional - but is allowed to be layed out anyhow in three dimensions. - """ - mesh = mesh.points[:] - mesh = reduce_dimension(np.array(mesh)) - if len(mesh[0]) == 3: - logging.warning("Mesh is not uniform. Falling back to meshfree method") - return None - min_point = np.amin(mesh, 0) - max_point = np.amax(mesh, 0) - big_dim = 0 if max_point[0] - min_point[0] >= max_point[1] - min_point[1] else 1 - small_dim = 1 - big_dim - - def prime_factors(n): - """ Straight from SO""" - i = 2 - factors = [] - while i * i <= n: - if n % i: - i += 1 - else: - n //= i - factors.append(i) - if n > 1: - factors.append(n) - return factors - - def greedy_choose(factors): - """ Greedily choose "best" divisors""" - small = big = 1 - for factor in reversed(factors): - if big <= small: - big *= factor - else: - small *= factor - return small, big - - small, big = greedy_choose(prime_factors(numparts)) - small_interval = (max_point[small_dim] - min_point[small_dim]) / small - big_interval = (max_point[big_dim] - min_point[big_dim]) / big - labels = [] - logging.info("Uniform partioning of mesh size {} into {} x {} partitions.".format( - len(mesh), small, big)) - for point in mesh: - small_offset = point[small_dim] - min_point[small_dim] - small_index = int(small_offset / small_interval) - small_index = min(small_index, small - 1) - big_offset = point[big_dim] - min_point[big_dim] - big_index = int(big_offset / big_interval) - big_index = min(big_index, big - 1) - partition_num = small_index * big + big_index - labels.append(partition_num) - return labels - - -def apply_partition(orig_mesh, part, numparts): - """ - Partitions a mesh into many meshes when given a partition and a mesh. - """ - meshes = [Mesh() for _ in range(numparts)] - mapping = {} # Maps global index to partition and local index - print(orig_mesh) - for i in range(len(orig_mesh.points)): - partition = part[i] - selected = meshes[partition] - mapping[i] = (partition, len(selected.points)) - selected.points.append(orig_mesh.points[i]) - if orig_mesh.pointdata: - selected.pointdata.append(orig_mesh.pointdata[i]) - - assert(len(mapping) == len(orig_mesh.points)) - assert(len(orig_mesh.cells) == len(orig_mesh.cell_types)) - for cell, type in zip(orig_mesh.cells, orig_mesh.cell_types): - partitions = list(map(lambda idx: mapping[idx][0], cell)) - if len(set(partitions)) == 1: - meshes[partitions[0]].cells.append(tuple([mapping[gidx][1] for gidx in cell])) - meshes[partitions[0]].cell_types.append(type) - - for m in meshes: - print(m) - - return meshes - - -def write_meshes(meshes, dirname): - """ - Writes meshes to given directory. - """ - dirname = os.path.abspath(dirname) - if os.path.exists(dirname): - shutil.rmtree(dirname) - os.mkdir(dirname) - for i in range(len(meshes)): - mesh = meshes[i] - mesh_io.write_txt(dirname + "/" + str(i), mesh.points, mesh.cells, mesh.pointdata) - - -def parse_args(): - parser = argparse.ArgumentParser(description= - "Read meshes, partition them and write them out in internal format.") - parser.add_argument("in_meshname", metavar="inputmesh", nargs="+", help="The meshes used as input") - parser.add_argument("--out", "-o", dest="out_meshname", help="The output mesh directory name. Only works if single in_mesh is given.") - parser.add_argument("--numparts", "-n", dest="numparts", default=1, type=int, - help="The number of parts to split into") - parser.add_argument("--tag", "-t", dest="tag", default=None, - help="The PointData tag for vtk meshes") - parser.add_argument("--algorithm", "-a", dest="algorithm", choices=["meshfree", "topology", "uniform"], - help="""Change the algorithm used for determining a partition. - A meshfree algorithm works on arbitrary meshes without needing topological information. - A topology-based algorithm needs topology information - and is therefore useless on point clouds. - - A uniform algorithm will assume a uniform 2d mesh layed out somehow in 3d and partition accordingly.""") - parser.add_argument("--log", "-l", dest="logging", default="INFO", - choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], - help="Set the log level. Default is INFO") - return parser.parse_args() - -if __name__ == "__main__": - main() diff --git a/src/precice-aste-evaluate b/src/precice-aste-evaluate new file mode 100755 index 00000000..fccefef4 --- /dev/null +++ b/src/precice-aste-evaluate @@ -0,0 +1,455 @@ +#!/usr/bin/env python3 +import argparse +import json +import logging +import os.path + +import numpy as np +import vtk +from vtk.util.numpy_support import numpy_to_vtk as n2v +from vtk.util.numpy_support import vtk_to_numpy as v2n + + +class ExtensionError(Exception): + pass + + +class MissingDataError(Exception): + pass + + +class Calculator: + """Calculator class provided 3 main functionality: + - Evaluates a given function (scalar or vector) on a given mesh + - Evaluates difference between a given function \"f\" and given data \"data\" (data-f) + - Calculate statistics for the difference mentioned above + - Use \"--help\" argument to see usage + """ + + def __init__(self) -> None: + args = Calculator.parse_args() + Calculator.create_logger(args.logging) + pre_def_functions = Calculator.create_predeffunctions() + Calculator.evaluate(args, pre_def_functions) + + @staticmethod + def create_logger(level): + logger = logging.getLogger("---[ASTE-Evaluate]") + logger.setLevel(getattr(logging, level)) + ch = logging.StreamHandler() + ch.setLevel(getattr(logging, level)) + formatter = logging.Formatter("%(name)s %(levelname)s : %(message)s") + ch.setFormatter(formatter) + logger.addHandler(ch) + + @staticmethod + def get_logger(): + return logging.getLogger("---[ASTE-Evaluate]") + + @staticmethod + def parse_args(): + parser = argparse.ArgumentParser(description=__doc__) + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument( + "--mesh", + "-m", + dest="in_meshname", + help="The mesh (VTK Unstructured Grid) used as input", + ) + parser.add_argument( + "--function", + "-f", + dest="function", + default="eggholder3d", + help="""The function to evaluate on the mesh. + Syntax is the same as used in the calculator object, coordinates are given as e.g. 'cos(x)+y'. + Alternatively, you can use predefined function + Default is Eggholder function in 3D (eggholder3d).""", + ) + group.add_argument( + "--list-functions", + dest="listfunctions", + action="store_true", + help="Prints list of predefined functions.", + ) + parser.add_argument( + "--output", + "-o", + dest="out_meshname", + default=None, + help="""The output meshname. + Default is the same as for the input mesh""", + ) + parser.add_argument( + "--data", "-d", dest="data", help="The name of output data." + ) + parser.add_argument( + "--diffdata", + "-diffd", + dest="diffdata", + help="""The name of difference data. + Required in diff mode.""", + ) + parser.add_argument( + "--log", + "-l", + dest="logging", + default="INFO", + choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], + help="""Set the log level. + Default is INFO""", + ) + parser.add_argument( + "--directory", + "-dir", + dest="directory", + default=None, + help="Directory for output files (optional)", + ) + parser.add_argument( + "--diff", + action="store_true", + help='Calculate the difference between "--diffdata" and the specified' + 'function "--function"', + ) + parser.add_argument( + "--gradient", + "-g", + action="store_true", + help="Adds array with gradient data", + ) + parser.add_argument( + "--stats", + "-s", + action="store_true", + help="Store stats of the difference calculation as the separate file inputmesh.stats.json", + ) + args, _ = parser.parse_known_args() + return args + + @staticmethod + def create_predeffunctions(): + twod_functions = { + "franke2d": "0.75*exp(-((9*{first}-2)^2+(9*{second}-2)^2)/4)" + "+0.75*exp(-((9*{first}+1)^2/49+(9*{second}+1)/10))" + "+0.5*exp(-((9*{first}-7)^2+(9*{second}-3)^2)/4)" + "-0.2*exp(-((9*{first}-4)^2+(9*{second}-7)^2))", + "eggholder2d": "-{first}*sin(sqrt(abs({first}-{second}-47)))" + "-({second}+47)*sin(sqrt(abs(0.5*{first}+{second}+47)))", + "rosenbrock2d": "(100*({second}-{first}^2)^2+({first}-1)^2)", + } + + pre_def2d_functions = { + f"{name}({arg})": twod_functions[name].format(first=arg[0], second=arg[1]) + for name in ["franke2d", "eggholder2d", "rosenbrock2d"] + for arg in ["xy", "xz", "yz"] + } + + pre_def_functions = { + "franke3d": "0.75*exp(-((9*x-2)^2+(9*y-2)^2+(9*z-2)^2)/4)" + "+0.75*exp(-((9*x+1)^2/49+(9*y+1)/10+(9*z+1)/10))" + "+0.5*exp(-((9*x-7)^2+(9*y-3)^2+(9*y-5)^2)/4)" + "-0.2*exp(-((9*x-4)^2+(9*y-7)^2+(9*z-5)^2))", + "eggholder3d": "-x*sin(sqrt(abs(x-y-47)))-(y+47)*sin(sqrt(abs(0.5*x+y+47)))" + "-y*sin(sqrt(abs(y-z-47)))-(z+47)*sin(sqrt(abs(0.5*y+z+47)))", + "rosenbrock3d": "(100*(y-x^2)^2+(x-1)^2)+(100*(z-y^2)^2+(y-1)^2)", + } + + pre_def_functions.update(pre_def2d_functions) + + return pre_def_functions + + @staticmethod + def get_function_defitinitions(): + function_definitions = { + "Franke": "Franke's function has two Gaussian peaks of different heights, and a smaller dip.", + "Eggholder": "A function has many local maxima. It is difficult to optimize.", + "Rosenbrock": "A function that is unimodal, and the global minimum lies" + " in a narrow, parabolic valley.", + } + return function_definitions + + @staticmethod + def print_predef_functions(pre_def_functions): + print("Available predefined functions are:") + longest = max(map(len, pre_def_functions.keys())) + for name, func in list(pre_def_functions.items()): + print(f"{name:{longest}} := {func}") + function_definitions = Calculator.get_function_defitinitions() + print("Definitions of functions are:") + longest = max(map(len, function_definitions.keys())) + for name, definition in list(function_definitions.items()): + print(f"{name:{longest}} := {definition}") + + @staticmethod + def evaluate(args, pre_def_functions): + logger = Calculator.get_logger() + if args.listfunctions: + Calculator.print_predef_functions(pre_def_functions) + return + assert os.path.isfile( + args.in_meshname + ), 'Input mesh file not found. Please check your input mesh "--mesh".' + assert ( + args.data + ), 'Dataname "--data" is missing. Please give an dataname for given input.' + + out_meshname = args.out_meshname + if args.out_meshname is None: + logger.info( + "No output mesh name is given {} will be used.".format(args.in_meshname) + ) + out_meshname = args.in_meshname + + if args.function in pre_def_functions: + inputfunc = pre_def_functions[args.function] + else: + inputfunc = args.function + + calc = Calculator.create_vtk_calculator() + if args.diff: + assert args.diffdata, """The \"--diffdata\" argument is required when running in difference mode (using the \"--diff\" argument). + Please add a valid \"--diffdata\" argument or type \"--help\" for more information.""" + + Calculator.calculate_difference(calc, inputfunc, args, out_meshname) + else: + Calculator.calculate_function(calc, inputfunc, args, out_meshname) + + @staticmethod + def create_vtk_calculator(): + calc = vtk.vtkArrayCalculator() + calc.AddCoordinateScalarVariable("x", 0) + calc.AddCoordinateScalarVariable("y", 1) + calc.AddCoordinateScalarVariable("z", 2) + return calc + + @staticmethod + def calculate_function(calc, inputfunc, args, out_meshname): + logger = Calculator.get_logger() + vtk_dataset = Calculator.read_mesh(args.in_meshname) + calc.SetInputData(vtk_dataset) + calc.SetFunction(inputfunc) + logger.info( + 'Evaluated "{}" on the input mesh "{}".'.format(inputfunc, args.in_meshname) + ) + calc.SetResultArrayName(args.data) + calc.Update() + vtk_dataset.GetPointData().AddArray( + calc.GetOutput().GetPointData().GetAbstractArray(args.data) + ) + logger.info( + f'Evaluated function saved to "{args.data}" variable on output mesh "{out_meshname}"' + ) + if args.gradient: + Calculator.add_gradient(calc, vtk_dataset, inputfunc, args.data) + + Calculator.write_mesh(vtk_dataset, out_meshname, args.directory) + + @staticmethod + def calculate_difference(calc, inputfunc, args, out_meshname): + logger = Calculator.get_logger() + vtk_dataset = Calculator.read_mesh(args.in_meshname) + calc.SetInputData(vtk_dataset) + diffdata = args.diffdata + if not vtk_dataset.GetPointData().HasArray(diffdata): + raise MissingDataError( + f'Given mesh "{args.in_meshname}" has no data with given name "{diffdata}"' + ) + else: + data = v2n(vtk_dataset.GetPointData().GetAbstractArray(diffdata)) + # Calculate given function on the mesh + calc.SetFunction(inputfunc) + calc.SetResultArrayName("function") + calc.Update() + func = v2n(calc.GetOutput().GetPointData().GetAbstractArray("function")) + difference = data - func + logger.info( + f'Evaluated "{diffdata}"-"({inputfunc})" on the mesh "{args.in_meshname}".' + ) + + Calculator.calculate_stats(vtk_dataset, difference, out_meshname, args.stats) + + diff_vtk = n2v(difference) + diff_vtk.SetName(args.data) + vtk_dataset.GetPointData().AddArray(diff_vtk) + Calculator.write_mesh(vtk_dataset, out_meshname, args.directory) + + @staticmethod + def calculate_stats(vtk_dataset, difference, out_meshname, stats=None): + logger = Calculator.get_logger() + # Calculate Statistics + abs_diff = np.absolute(difference) + num_points = vtk_dataset.GetNumberOfPoints() + cnt, abs_min, signed_min, abs_max, signed_max = ( + num_points, + np.nanmin(abs_diff), + np.nanmin(difference), + np.nanmax(abs_diff), + np.nanmax(difference), + ) + p99, p95, p90, median = np.percentile(abs_diff, [99, 95, 90, 50]) + relative = np.sqrt(np.nansum(np.square(abs_diff)) / abs_diff.size) + decorator = 15 * "*" + spaces = 5 * " " + logger.info(f"\n\n{decorator}{spaces}Statistics{spaces}{decorator}\n\n") + logger.info("Vertex count {}".format(cnt)) + logger.info("Relative l2 error {}".format(relative)) + logger.info("Maximum absolute error per vertex {}".format(abs_max)) + logger.info("Maximum signed error per vertex {}".format(signed_max)) + logger.info("Minimum absolute error per vertex {}".format(abs_min)) + logger.info("Minimum signed error per vertex {}".format(signed_min)) + logger.info("Median absolute error per vertex {}".format(median)) + logger.info("99th percentile of absolute error per vertex {}".format(p99)) + logger.info("95th percentile of absolute error per vertex {}".format(p95)) + logger.info("90th percentile of absolute error per vertex {}".format(p90)) + logger.info(f"\n\n{decorator}{spaces}End Statistic{spaces}{decorator}\n\n") + + if stats: + stat_file = os.path.splitext(out_meshname)[0] + ".stats.json" + logger.info('Saving stats data to "{}"'.format(stat_file)) + json.dump( + { + "count": cnt, + "abs_min": abs_min, + "abs_max": abs_max, + "signed_min:": signed_min, + "signed_max": signed_max, + "median(abs)": median, + "relative-l2": relative, + "99th percentile(abs)": p99, + "95th percentile(abs)": p95, + "90th percentile(abs)": p90, + }, + open(stat_file, "w"), + ) + + @staticmethod + def read_mesh(in_meshname): + logger = Calculator.get_logger() + logger.info(f'Reading input mesh "{in_meshname}"') + extension = os.path.splitext(in_meshname)[1] + if extension == ".vtu": + reader = vtk.vtkXMLUnstructuredGridReader() + elif extension == ".vtk": + reader = vtk.vtkUnstructuredGridReader() + reader.ReadAllScalarsOn() + reader.ReadAllVectorsOn() + reader.ReadAllFieldsOn() + else: + raise ExtensionError( + 'Unkown input file extension please check your input file or hype "--help" for more information.' + ) + reader.SetFileName(in_meshname) + reader.Update() + vtk_dataset = reader.GetOutput() + logger.info("Mesh contains {} points.".format(vtk_dataset.GetNumberOfPoints())) + return vtk_dataset + + @staticmethod + def write_mesh(vtk_dataset, out_meshname, directory=None): + logger = Calculator.get_logger() + # Create writer + if os.path.splitext(out_meshname)[1] == ".vtk": + writer = vtk.vtkUnstructuredGridWriter() + writer.SetFileTypeToBinary() + elif os.path.splitext(out_meshname)[1] == ".vtu": + writer = vtk.vtkXMLUnstructuredGridWriter() + else: + raise ExtensionError("Output mesh extension should be '.vtk' and '.vtu'") + + writer.SetInputData(vtk_dataset) + out_meshname = os.path.basename(os.path.normpath(out_meshname)) + # If directory needed create it + if directory: + directory = os.path.abspath(directory) + os.makedirs(directory, exist_ok=True) + out_meshname = os.path.join(directory, out_meshname) + + writer.SetFileName(out_meshname) + writer.Write() + logger.info(f'Written output to "{out_meshname}".') + + @staticmethod + def sympy_to_vtk(string): + return string.replace("**", "^") + + @staticmethod + def vtk_to_sympy(string): + return string.replace("^", "**") + + @staticmethod + def add_gradient(calc, vtk_dataset, inputfunc, dataname): + try: + import sympy + except ImportError: + raise ImportError( + 'For gradient calculations "sympy" is required please install the "sympy" package.' + ) + logger = Calculator.get_logger() + function_in_sympy = sympy.Matrix( + [sympy.parsing.parse_expr(Calculator.vtk_to_sympy(inputfunc))] + ) + variables = sympy.Matrix(sympy.symbols("x y z")) + if any( + x in str(function_in_sympy) for x in ["iHat", "kHat", "jHat"] + ): # Vector Data + gradient_name_list = [dataname + "_d" + i for i in ["x", "y", "z"]] + gradient_function = [] + derivatives = [] + # Find components of vector + unitvectors = sympy.Matrix(sympy.symbols("iHat jHat kHat")) + components = [x for x in function_in_sympy.jacobian(unitvectors)] + # Convert components to sympy + for component in components: + sympy_component = sympy.Matrix( + [sympy.parsing.parse_expr(str(component))] + ) + derivatives.append( + [ + Calculator.sympy_to_vtk(str(x)) + for x in sympy_component.jacobian(variables) + ] + ) + # Create gradient function + for i in range(3): + gradient_function.append( + str(derivatives[0][i]) + + "*iHat+" + + str(derivatives[1][i]) + + "*jHat+" + + str(derivatives[2][i]) + + "*kHat" + ) + else: # Scalar Data + gradients = [ + Calculator.sympy_to_vtk(str(x)) + for x in function_in_sympy.jacobian(variables) + ] + gradient_name_list = [dataname + "_gradient"] + gradient_function = [ + "(" + + str(gradients[0]) + + ")" + + "*iHat+" + + "(" + + str(gradients[1]) + + ")" + + "*jHat+" + + "(" + + str(gradients[2]) + + ")" + + "*kHat" + ] + # Add gradient function to vtk_dataset + for name, function in zip(gradient_name_list, gradient_function): + calc.SetFunction(function) + calc.SetResultArrayName(name) + calc.Update() + vtk_dataset.GetPointData().AddArray( + calc.GetOutput().GetPointData().GetAbstractArray(name) + ) + logger.info('Evaluated "{}" on the input mesh.'.format(name)) + + +if __name__ == "__main__": + Calculator() diff --git a/src/precice-aste-join b/src/precice-aste-join new file mode 100755 index 00000000..1949d40c --- /dev/null +++ b/src/precice-aste-join @@ -0,0 +1,365 @@ +#!/usr/bin/env python3 +import argparse +import json +import logging +import os +import os.path + +import vtk + + +class ExtensionError(Exception): + pass + + +class PartitionError(Exception): + pass + + +class MeshJoiner: + """MeshJoiner class joins meshes partitioned by MeshPartitioner class. + There are two possible ways of joining the meshes: + - Partition-wise (does not recover the original mesh order lacks of discarded cells) + - Recovery merge (maintain original mesh order and adds discarded cells) + - Use \"--help\" argument to see usage. + """ + + def __init__(self) -> None: + args = self.parse_args() + self.create_logger(args) + self.join(args) + + @staticmethod + def parse_args(): + parser = argparse.ArgumentParser( + description="Read a partitioned mesh and join it into a .vtk or .vtu file." + ) + parser.add_argument( + "--mesh", + "-m", + required=True, + dest="in_meshname", + help="""The partitioned mesh prefix used as input (only VTU format is accepted) + (Looking for _<#filerank>.vtu) """, + ) + parser.add_argument( + "--output", + "-o", + dest="out_meshname", + help="""The output mesh. Can be VTK or VTU format. + If it is not given _joined.vtk will be used.""", + ) + parser.add_argument( + "-r", + "--recovery", + dest="recovery", + help="The path to the recovery file to fully recover it's state.", + ) + parser.add_argument( + "--numparts", + "-n", + dest="numparts", + type=int, + help="The number of parts to read from the input mesh. By default the entire mesh is read.", + ) + parser.add_argument( + "--directory", + "-dir", + dest="directory", + default=None, + help="Directory for output files (optional)", + ) + parser.add_argument( + "--log", + "-l", + dest="logging", + default="INFO", + choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], + help="Set the log level. Default is INFO", + ) + args, _ = parser.parse_known_args() + return args + + @staticmethod + def create_logger(args): + logger = logging.getLogger("---[ASTE-Join]") + logger.setLevel(getattr(logging, args.logging)) + ch = logging.StreamHandler() + ch.setLevel(getattr(logging, args.logging)) + formatter = logging.Formatter("%(name)s %(levelname)s : %(message)s") + ch.setFormatter(formatter) + logger.addHandler(ch) + + @staticmethod + def get_logger(): + return logging.getLogger("---[ASTE-Join]") + + @staticmethod + def join(args): + if args.recovery: + recovery_file = args.recovery + else: + recovery_file = args.in_meshname + "_recovery.json" + out_meshname = ( + args.out_meshname if args.out_meshname else args.in_meshname + "_joined.vtk" + ) + joined_mesh = MeshJoiner.read_meshes( + args.in_meshname, args.numparts, recovery_file + ) + logger = MeshJoiner.get_logger() + num_points = joined_mesh.GetNumberOfPoints() + num_cells = joined_mesh.GetNumberOfCells() + logger.info(f"Final mesh contains {num_points} points, {num_cells} cells") + MeshJoiner.write_mesh(joined_mesh, out_meshname, args.directory) + + @staticmethod + def read_meshes(prefix: str, partitions=None, recovery_path=None): + """ + Reads meshes with given prefix. + """ + logger = MeshJoiner.get_logger() + if not partitions: + partitions = MeshJoiner.count_partitions(prefix) + logger.info( + "Detected " + str(partitions) + " partitions with prefix " + prefix + ) + if partitions == 0: + raise PartitionError("No partitions found") + + if os.path.exists(recovery_path): + logger.info("Recovery data found. Full recovery will be executed") + return MeshJoiner.join_mesh_recovery(prefix, partitions, recovery_path) + else: + logger.info("No recovery data found. Meshes will be joined partition-wise") + return MeshJoiner.join_mesh_partitionwise(prefix, partitions) + + @staticmethod + def join_mesh_partitionwise(prefix: str, partitions: int): + """ + Partition-wise load and append. + Does not recover missing cells. + Cells and points may be scrambled wrt original mesh. + """ + logger = MeshJoiner.get_logger() + logger.info("Starting partition-wise mesh merge") + joined_mesh = vtk.vtkUnstructuredGrid() + joined_points = vtk.vtkPoints() + joined_data_arrays = None + joined_cells = vtk.vtkCellArray() + joined_cell_types = [] + offset = 0 + + for i in range(partitions): + fname = prefix + "_" + str(i) + ".vtu" + logger.info(f"Merging mesh from {fname}") + reader = vtk.vtkXMLUnstructuredGridReader() + reader.SetFileName(fname) + reader.Update() + part_mesh = reader.GetOutput() + + logger.debug( + "File {} contains {} points".format( + fname, part_mesh.GetNumberOfPoints() + ) + ) + for i in range(part_mesh.GetNumberOfPoints()): + joined_points.InsertNextPoint(part_mesh.GetPoint(i)) + + part_point_data = part_mesh.GetPointData() + num_arrays = part_point_data.GetNumberOfArrays() + + if joined_data_arrays is None: + joined_data_arrays = [] + for j in range(num_arrays): + new_array = vtk.vtkDoubleArray() + new_array.SetName(part_point_data.GetArrayName(j)) + joined_data_arrays.append(new_array) + + for j in range(num_arrays): + array_name = part_point_data.GetArrayName(j) + logger.debug( + "Merging from file {} dataname {}".format(fname, array_name) + ) + array_data = part_point_data.GetArray(array_name) + join_arr = joined_data_arrays[j] + join_arr.SetNumberOfComponents(array_data.GetNumberOfComponents()) + join_arr.InsertTuples( + join_arr.GetNumberOfTuples(), + array_data.GetNumberOfTuples(), + 0, + array_data, + ) + + for i in range(part_mesh.GetNumberOfCells()): + cell = part_mesh.GetCell(i) + vtk_cell = vtk.vtkGenericCell() + vtk_cell.SetCellType(cell.GetCellType()) + id_list = vtk.vtkIdList() + for j in range(cell.GetNumberOfPoints()): + id_list.InsertNextId(cell.GetPointId(j) + offset) + vtk_cell.SetPointIds(id_list) + joined_cell_types.append(cell.GetCellType()) + joined_cells.InsertNextCell(vtk_cell) + + offset += part_mesh.GetNumberOfPoints() + + if len(joined_cell_types) != 0: + joined_mesh.SetCells(joined_cell_types, joined_cells) + joined_mesh.SetPoints(joined_points) + for data_array in joined_data_arrays: + joined_mesh.GetPointData().AddArray(data_array) + + return joined_mesh + + @staticmethod + def join_mesh_recovery(prefix: str, partitions: int, recovery_path: str): + """ + Partition merge with full recovery + + This recovers the original mesh. + """ + logger = MeshJoiner.get_logger() + logger.info("Starting full mesh recovery") + recovery = json.load(open(recovery_path, "r")) + cells = recovery["cells"] + size = recovery["size"] + cell_types = recovery["cell_types"] + + logger.info("Original mesh contains {} points".format(size)) + logger.info("{} Cells discarded during partitioning".format(len(cells))) + + # Initialize Joined Mesh + joined_mesh = vtk.vtkUnstructuredGrid() + joined_points = vtk.vtkPoints() + joined_points.SetNumberOfPoints(size) + joined_data_arrays = None + joined_cells = vtk.vtkCellArray() + joined_cell_types = [] + + for i in range(partitions): + global_ids = [] + + fname = prefix + "_" + str(i) + ".vtu" + logger.info(f"Merging mesh from {fname}") + reader = vtk.vtkXMLUnstructuredGridReader() + reader.SetFileName(fname) + reader.Update() + part_mesh = reader.GetOutput() + part_point_data = part_mesh.GetPointData() + num_arrays = part_point_data.GetNumberOfArrays() + + # Prepare DataArrays + if joined_data_arrays is None: + joined_data_arrays = [] + for j in range(num_arrays): + new_array = vtk.vtkDoubleArray() + new_array.SetName(part_point_data.GetArrayName(j)) + new_array.SetNumberOfTuples(size) + joined_data_arrays.append(new_array) + + # Extract Global IDs + array_data = part_point_data.GetArray("GlobalIDs") + # Check if GlobalIDs exist if not do partition-wise merge + if array_data is None: + logger.info( + "GlobalIDs were not found, a recovery merge is not possible." + ) + return MeshJoiner.join_mesh_partitionwise(prefix, partitions) + + for k in range(array_data.GetNumberOfTuples()): + global_ids.append(array_data.GetTuple(k)) + logger.debug( + "File {} contains {} points".format( + fname, part_mesh.GetNumberOfPoints() + ) + ) + for i in range(part_mesh.GetNumberOfPoints()): + joined_points.SetPoint(int(global_ids[i][0]), part_mesh.GetPoint(i)) + + # Append Point Data to Original Locations + for j in range(num_arrays): + array_name = part_point_data.GetArrayName(j) + logger.debug( + "Merging from file {} dataname {}".format(fname, array_name) + ) + array_data = part_point_data.GetArray(array_name) + join_arr = joined_data_arrays[j] + join_arr.SetNumberOfComponents(array_data.GetNumberOfComponents()) + join_arr.SetNumberOfTuples(size) + for k in range(array_data.GetNumberOfTuples()): + join_arr.SetTuple(int(global_ids[k][0]), array_data.GetTuple(k)) + + # Append Cells + for i in range(part_mesh.GetNumberOfCells()): + cell = part_mesh.GetCell(i) + vtk_cell = vtk.vtkGenericCell() + vtk_cell.SetCellType(cell.GetCellType()) + id_list = vtk.vtkIdList() + for j in range(cell.GetNumberOfPoints()): + id_list.InsertNextId(int(global_ids[cell.GetPointId(j)][0])) + vtk_cell.SetPointIds(id_list) + joined_cell_types.append(cell.GetCellType()) + joined_cells.InsertNextCell(vtk_cell) + + # Append Recovery Cells + for cell, cell_type in zip(cells, cell_types): + vtk_cell = vtk.vtkGenericCell() + vtk_cell.SetCellType(cell_type) + id_list = vtk.vtkIdList() + for pointid in cell: + id_list.InsertNextId(pointid) + vtk_cell.SetPointIds(id_list) + joined_cell_types.append(cell_type) + joined_cells.InsertNextCell(vtk_cell) + + # Set Points, Cells, Data on Grid + if len(joined_cell_types) != 0: + joined_mesh.SetCells(joined_cell_types, joined_cells) + joined_mesh.SetPoints(joined_points) + for data_array in joined_data_arrays: + joined_mesh.GetPointData().AddArray(data_array) + + return joined_mesh + + @staticmethod + def count_partitions(prefix: str) -> int: + """Count how many partitions available with given prefix + + Args: + prefix (str): prefix of mesh + + Returns: + int: number of partitions + """ + detected = 0 + while True: + partition_file = prefix + "_" + str(detected) + ".vtu" + if not os.path.isfile(partition_file): + break + detected += 1 + return detected + + @staticmethod + def write_mesh(meshfile, filename, directory=None): + + filename = os.path.basename(os.path.normpath(filename)) + if directory: + directory = os.path.abspath(directory) + os.makedirs(directory, exist_ok=True) + filename = os.path.join(directory, filename) + + extension = os.path.splitext(filename)[1] + if extension == ".vtk": # VTK Legacy format + writer = vtk.vtkUnstructuredGridWriter() + writer.SetFileTypeToBinary() + elif extension == ".vtu": # VTK XML Unstructured Grid format + writer = vtk.vtkXMLUnstructuredGridWriter() + else: + raise ExtensionError("Unknown File extension: " + extension) + writer.SetFileName(filename) + writer.SetInputData(meshfile) + writer.Write() + + +if __name__ == "__main__": + MeshJoiner() diff --git a/src/precice-aste-partition b/src/precice-aste-partition new file mode 100755 index 00000000..b9a88331 --- /dev/null +++ b/src/precice-aste-partition @@ -0,0 +1,618 @@ +#!/usr/bin/env python3 +import argparse +import json +import logging +import math +import os +import platform +import shutil +from ctypes import c_int, c_longlong, cdll + +import numpy as np +import vtk + + +class ExtensionError(Exception): + pass + + +class UnkownOSError(Exception): + pass + + +class LibraryError(Exception): + pass + + +class Mesh: + """ + A Mesh consists of: + - Points: A list of tuples of floats representing coordinates of points + - Cells: A list of tuples of ints representing mesh elements + - data_index: A list ints representing indexes of Points/Data in original mesh + - vtk_Dataset: VTK Unstructured Grid Object. + """ + + def __init__( + self, + points=None, + cells=None, + cell_types=None, + vtk_dataset=None, + data_index=None, + ): + if points is not None: + self.points = points + else: + self.points = [] + if cells is not None: + assert cell_types is not None + self.cells = cells + self.cell_types = cell_types + else: + self.cells = [] + self.cell_types = [] + + if data_index is not None: + self.data_index = data_index + else: + self.data_index = [] + + self.vtk_dataset = vtk_dataset + + def __str__(self): + return "Mesh with {} Points and {} Cells ({} Cell Types)".format( + len(self.points), len(self.cells), len(self.cell_types) + ) + + +class MeshPartitioner: + """MeshPartitioner class partition a given VTK unstuctured grid mesh to n partitions. + - Use \"--help\" argument to see usage. + """ + + def __init__(self) -> None: + args = self.parse_arguments() + self.create_logger(args) + assert os.path.isfile(args.in_meshname), ( + 'Input file cannot be found "' + + args.in_meshname + + '", please check your input.' + ) + self.run(args) + + @staticmethod + def run(args) -> None: + logger = MeshPartitioner.get_logger() + mesh_name = args.in_meshname + algorithm = args.algorithm + if not algorithm: + logger.info('No algorithm given. Defaulting to "meshfree"') + algorithm = "meshfree" + mesh = MeshPartitioner.read_mesh(mesh_name) + if args.numparts > 1: + part = MeshPartitioner.partition(mesh, args.numparts, algorithm) + else: + if args.directory: + # Get the absolute directory where we want to store the mesh + directory = os.path.abspath(args.directory) + os.makedirs(directory, exist_ok=True) + out_meshname = os.path.join(directory, args.out_meshname) + else: + out_meshname = args.out_meshname + extension = os.path.splitext(mesh_name)[1] + if extension == ".vtk": + shutil.copy(mesh_name, out_meshname + ".vtk") + return + elif extension == ".vtu": + MeshPartitioner.vtu2vtk(mesh_name, out_meshname) + return + else: + raise ExtensionError( + f"Unknown input file extension {extension} please check your input file." + ) + + logger.info("Processing mesh " + mesh_name) + meshes, recovery_info = MeshPartitioner.apply_partition( + mesh, part, args.numparts + ) + logger.info("Writing output to " + args.out_meshname) + MeshPartitioner.write_meshes( + meshes, recovery_info, args.out_meshname, mesh.vtk_dataset, args.directory + ) + + @staticmethod + def parse_arguments(): + parser = argparse.ArgumentParser( + description="Read meshes, partition them and write them out in VTU format." + ) + parser.add_argument( + "--mesh", + "-m", + required=True, + dest="in_meshname", + help="The mesh used as input", + ) + parser.add_argument( + "--output", + "-o", + dest="out_meshname", + default="partitioned_mesh", + help="The output mesh name.", + ) + parser.add_argument( + "--directory", + "-dir", + dest="directory", + default=None, + help="Directory for output files (optional)", + ) + parser.add_argument( + "--numparts", + "-n", + dest="numparts", + default=1, + type=int, + help="The number of parts to split into", + ) + parser.add_argument( + "--algorithm", + "-a", + dest="algorithm", + choices=["meshfree", "topology", "uniform"], + help="""Change the algorithm used for determining a partition. + A meshfree algorithm works on arbitrary meshes without needing topological information. + A topology-based algorithm needs topology information + and is therefore useless on point clouds. + A uniform algorithm will assume a uniform 2d mesh laid out somehow in 3d and partition accordingly.""", + ) + parser.add_argument( + "--log", + "-l", + dest="logging", + default="INFO", + choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], + help="Set the log level. Default is INFO", + ) + args, _ = parser.parse_known_args() + return args + + @staticmethod + def create_logger(args): + logger = logging.getLogger("---[ASTE-Partition]") + logger.setLevel(getattr(logging, args.logging)) + ch = logging.StreamHandler() + ch.setLevel(getattr(logging, args.logging)) + formatter = logging.Formatter("%(name)s %(levelname)s : %(message)s") + ch.setFormatter(formatter) + logger.addHandler(ch) + + @staticmethod + def get_logger(): + return logging.getLogger("---[ASTE-Partition]") + + @staticmethod + def partition(mesh: Mesh, numparts: int, algorithm): + """ + Partitions a mesh using METIS or kmeans. This does not call METIS directly, + but instead uses a small C++ Wrapper around shared library libmetisAPI for convenience. + This shared library must be provided if this function should be called. + """ + if algorithm == "meshfree": + return MeshPartitioner.partition_kmeans(mesh, numparts) + elif algorithm == "topology": + return MeshPartitioner.partition_metis(mesh, numparts) + elif algorithm == "uniform": + labels = MeshPartitioner.partition_uniform(mesh, numparts) + if labels is None: + return MeshPartitioner.partition(mesh, numparts, "meshfree") + return labels + + @staticmethod + def partition_kmeans(mesh: Mesh, numparts: int): + """Partitions a mesh using k-means. This is a meshfree algorithm and requires scipy""" + from scipy.cluster.vq import kmeans2 + + points = np.copy(mesh.points) + points = MeshPartitioner.reduce_dimension(points) + _, label = kmeans2(points, numparts) + return label + + @staticmethod + def reduce_dimension_simple(mesh: Mesh): + """ + A simple, efficient algorithm for a dimension reduction for a mesh + with one or more "dead dimensions" + """ + test_p = mesh[0] + dead_dims = np.argwhere(np.abs(np.array(test_p)) < 1e-9) + for point in mesh: + current_dead_dims = np.argwhere(np.abs(np.array(point)) < 1e-9) + dead_dims = np.intersect1d(dead_dims, current_dead_dims) + if len(dead_dims) == 0: + return mesh + mesh = np.array(mesh) + full = np.array([0, 1, 2]) + mask = np.setdiff1d(full, dead_dims) + return mesh[:, mask] + + @staticmethod + def reduce_dimension(mesh: Mesh): + """ + This function gets a list of points in 3d and if all of them are within one plane it + returns a list of 2d points in the plane, else the unmodified list is returned. + """ + logger = MeshPartitioner.get_logger() + pA, pB = mesh[:2] + pC = mesh[-1] + pA = np.array(pA) + AB = pB - pA + AC = pC - pA + n = np.cross(AB, AC) + # Every point x in the plane must fulfill (x - pA) * n = 0 + for x in mesh: + if np.dot(x - pA, n) != 0: + return mesh + else: # All Points within plane + # Transform mesh so all points have form (0, y, z) + # Compute Euler-Rodrigues rotation matrix + n /= np.linalg.norm(n) # Normalize + zUnit = np.array((0, 0, 1)) + phi = math.acos(np.dot(n, zUnit)) + logger.info( + "Rotating mesh with phi = " + + str(360 * phi / (2 * math.pi)) + + " degrees." + ) + axis = np.cross(n, zUnit) + axis /= np.linalg.norm(axis) + a = math.cos(phi / 2) + b = math.sin(phi / 2) * axis[0] + c = math.sin(phi / 2) * axis[1] + d = math.sin(phi / 2) * axis[2] + rotMat = np.array( + ( + ( + a**2 + b**2 - c**2 - d**2, + 2 * (b * c - a * d), + 2 * (b * d + a * c), + ), + ( + 2 * (b * c + a * d), + a**2 + c**2 - b**2 - d**2, + 2 * (c * d - a * b), + ), + ( + 2 * (b * d - a * c), + 2 * (c * d + a * b), + a**2 + d**2 - b**2 - c**2, + ), + ) + ) + for i, x in enumerate(mesh): # Translate & Rotate + x -= pA + x = x @ rotMat + mesh[i] = x + return mesh[:, :-1] + + @staticmethod + def partition_metis(mesh: Mesh, numparts: int): + """ + Partitions a mesh using METIS. This does not call METIS directly, + but instead uses a small C++ Wrapper libmetisAPI.so for convenience. + This shared library must be provided if this function should be called. + """ + logger = MeshPartitioner.get_logger() + cellPtr = [0] + cellData = [] + if len(mesh.cells) == 0: + logger.warning( + "No topology information provided. Partitioning with metis will likely provide bad partition" + ) + for i in range(len(mesh.cells)): + cell = mesh.cells[i] + cellData += list(cell) + cellPtr.append(cellPtr[-1] + len(cell)) + binpath = os.path.dirname(__file__) + libpath = os.path.normpath(os.path.join(binpath, "../lib")) + lib64path = os.path.normpath(os.path.join(binpath, "../lib64")) + os_type = platform.system() + if os_type == "Linux": + ext = ".so" + elif os_type == "Darwin": # MacOS + ext = ".dylib" + else: + raise UnkownOSError("Unknown OS type") + if os.path.isfile(os.path.join(binpath, "libmetisAPI" + ext)): + libmetispath = os.path.join(binpath, "libmetisAPI" + ext) + elif os.path.isfile(os.path.join(libpath, "libmetisAPI" + ext)): + libmetispath = os.path.join(libpath, "libmetisAPI" + ext) + elif os.path.isfile(os.path.join(lib64path, "libmetisAPI" + ext)): + libmetispath = os.path.join(lib64path, "libmetisAPI" + ext) + else: + raise LibraryError("libmetisAPI" + ext + " cannot found!") + libmetis = cdll.LoadLibrary(libmetispath) + idx_t = c_int if libmetis.typewidth() == 32 else c_longlong + cell_count = idx_t(len(mesh.cells)) + point_count = idx_t(len(mesh.points)) + num_parts = idx_t(numparts) + partition = (idx_t * len(mesh.points))() + cell_ptr = (idx_t * len(cellPtr))(*cellPtr) + cell_data = (idx_t * len(cellData))(*cellData) + libmetis.partitionMetis( + cell_count, point_count, cell_ptr, cell_data, num_parts, partition + ) + return np.ctypeslib.as_array(partition) + + @staticmethod + def partition_uniform(mesh: Mesh, numparts: int): + """ + Partitions a mesh assuming it is uniform. It must be two-dimensional + but is allowed to be laid out anyhow in three dimensions. + """ + logger = MeshPartitioner.get_logger() + mesh = mesh.points[:] + mesh = MeshPartitioner.reduce_dimension(np.array(mesh)) + if len(mesh[0]) == 3: + logger.warning("Mesh is not uniform. Falling back to meshfree method") + return None + min_point = np.amin(mesh, 0) + max_point = np.amax(mesh, 0) + big_dim = 0 if max_point[0] - min_point[0] >= max_point[1] - min_point[1] else 1 + small_dim = 1 - big_dim + + def prime_factors(n): + """Straight from SO""" + i = 2 + factors = [] + while i * i <= n: + if n % i: + i += 1 + else: + n //= i + factors.append(i) + if n > 1: + factors.append(n) + return factors + + def greedy_choose(factors): + """Greedily choose "best" divisors""" + small = big = 1 + for factor in reversed(factors): + if big <= small: + big *= factor + else: + small *= factor + return small, big + + small, big = greedy_choose(prime_factors(numparts)) + small_interval = (max_point[small_dim] - min_point[small_dim]) / small + big_interval = (max_point[big_dim] - min_point[big_dim]) / big + labels = [] + logger.info( + "Uniform partitioning, of mesh size {} into {} x {} partitions.".format( + len(mesh), small, big + ) + ) + for point in mesh: + small_offset = point[small_dim] - min_point[small_dim] + small_index = int(small_offset / small_interval) + small_index = min(small_index, small - 1) + big_offset = point[big_dim] - min_point[big_dim] + big_index = int(big_offset / big_interval) + big_index = min(big_index, big - 1) + partition_num = small_index * big + big_index + labels.append(partition_num) + return labels + + @staticmethod + def apply_partition(orig_mesh: Mesh, part, numparts: int): + """ + Partitions a mesh into many meshes when given a partition and a mesh. + """ + meshes = [Mesh() for _ in range(numparts)] + mapping = {} # Maps global index to partition and local index + for i, point in enumerate(orig_mesh.points): + partition = part[i] + selected = meshes[partition] + mapping[i] = (partition, len(selected.points)) + selected.points.append(point) + selected.data_index.append(i) + + assert len(mapping) == len(orig_mesh.points) + assert len(orig_mesh.cells) == len(orig_mesh.cell_types) + # Save discarded cells and their types to allow recovery + discarded_cells = [] + discarded_cell_types = [] + for cell, type in zip(orig_mesh.cells, orig_mesh.cell_types): + partitions = list(map(lambda idx: mapping[idx][0], cell)) + if len(set(partitions)) == 1: + meshes[partitions[0]].cells.append( + tuple([mapping[gidx][1] for gidx in cell]) + ) + meshes[partitions[0]].cell_types.append(type) + else: + discarded_cells.append(list(cell)) + discarded_cell_types.append(type) + + recovery_info = { + "size": len(orig_mesh.points), + "cells": discarded_cells, + "cell_types": discarded_cell_types, + } + + return meshes, recovery_info + + @staticmethod + def read_mesh(filename: str) -> Mesh: + extension = os.path.splitext(filename)[1] + if extension == ".vtu": + reader = vtk.vtkXMLUnstructuredGridReader() + elif extension == ".vtk": + reader = vtk.vtkUnstructuredGridReader() + else: + raise ExtensionError( + f"Unknown input file extension {extension}, please check your input." + ) + reader.SetFileName(filename) + reader.Update() + vtkmesh = reader.GetOutput() + points = [] + cells = [] + cell_types = [] + points = [vtkmesh.GetPoint(i) for i in range(vtkmesh.GetNumberOfPoints())] + for i in range(vtkmesh.GetNumberOfCells()): + cell = vtkmesh.GetCell(i) + cell_type = cell.GetCellType() + if cell_type not in [ + vtk.VTK_LINE, + vtk.VTK_TRIANGLE, + vtk.VTK_QUAD, + vtk.VTK_TETRA, + ]: + continue + cell_types.append(cell_type) + entry = () + for j in range(cell.GetNumberOfPoints()): + entry += (cell.GetPointId(j),) + cells.append(entry) + + assert len(cell_types) in [0, len(cells)] + return Mesh(points, cells, cell_types, vtkmesh) + + @staticmethod + def write_mesh( + filename: str, + points: list, + data_index: list, + cells=None, + cell_types=None, + orig_mesh=None, + ) -> None: + if cell_types is not None: + assert len(cell_types) in [0, len(cells)] + assert len(points) == len(data_index) + logger = MeshPartitioner.get_logger() + + vtk_grid = vtk.vtkUnstructuredGrid() + vtkpoints = vtk.vtkPoints() + vtkpoints.SetNumberOfPoints(len(points)) + for id, point in enumerate(points): + vtkpoints.SetPoint(id, point) + vtk_grid.SetPoints(vtkpoints) + + if cells: + cell_array = vtk.vtkCellArray() + for i, cell in enumerate(cells): + vtk_cell = vtk.vtkGenericCell() + vtk_cell.SetCellType(cell_types[i]) + id_list = vtk.vtkIdList() + for cellid in cell: + id_list.InsertNextId(cellid) + vtk_cell.SetPointIds(id_list) + cell_array.InsertNextCell(vtk_cell) + vtk_grid.SetCells(cell_types, cell_array) + + # Add GlobalIDs as a PointData + global_id_array = vtk.vtkDoubleArray() + global_id_array.SetNumberOfComponents(1) + global_id_array.SetName("GlobalIDs") + for j in data_index: + global_id_array.InsertNextTuple1(j) + vtk_grid.GetPointData().AddArray(global_id_array) + + if orig_mesh is not None: # Take PointDatas + point_data = orig_mesh.GetPointData() + # Iterate over PointData + for i in range(point_data.GetNumberOfArrays()): + array_name = point_data.GetArrayName(i) + old_array = point_data.GetAbstractArray(array_name) + new_array = vtk.vtkDoubleArray() + num_comp = old_array.GetNumberOfComponents() + new_array.SetNumberOfComponents(num_comp) + new_array.SetName(array_name) + if num_comp == 1: + for j in data_index: + data = old_array.GetTuple1(j) + new_array.InsertNextTuple1(data) + elif num_comp == 2: + for j in data_index: + data = old_array.GetTuple2(j) + new_array.InsertNextTuple2(data[0], data[1]) + elif num_comp == 3: + for j in data_index: + data = old_array.GetTuple3(j) + new_array.InsertNextTuple3(data[0], data[1], data[2]) + else: + logger.warning( + "Skipped data {} check dimension of data".format(array_name) + ) + vtk_grid.GetPointData().AddArray(new_array) + + extension = os.path.splitext(filename)[1] + if extension == ".vtk": # VTK Legacy format + writer = vtk.vtkUnstructuredGridWriter() + writer.SetFileTypeToBinary() + elif extension == ".vtu": # VTK XML Unstructured Grid format + writer = vtk.vtkXMLUnstructuredGridWriter() + else: + raise ExtensionError("Unknown File extension: " + extension) + writer.SetFileName(filename) + writer.SetInputData(vtk_grid) + writer.Write() + + @staticmethod + def write_meshes( + meshes, recovery_info, meshname: str, orig_mesh, directory=None + ) -> None: + """ + Writes meshes to given directory. + """ + # Strip off the mesh-prefix for the directory creation + mesh_prefix = os.path.basename(os.path.normpath(meshname)) + recovery_name = os.path.basename( + os.path.normpath(mesh_prefix + "_recovery.json") + ) + if directory: + # Get the absolute directory where we want to store the mesh + directory = os.path.abspath(directory) + recovery_name = os.path.join(directory, mesh_prefix + "_recovery.json") + os.makedirs(directory, exist_ok=True) + + for i in range(len(meshes)): + mesh = meshes[i] + if directory: + MeshPartitioner.write_mesh( + os.path.join(directory, mesh_prefix) + "_" + str(i) + ".vtu", + mesh.points, + mesh.data_index, + mesh.cells, + mesh.cell_types, + orig_mesh, + ) + else: + MeshPartitioner.write_mesh( + mesh_prefix + "_" + str(i) + ".vtu", + mesh.points, + mesh.data_index, + mesh.cells, + mesh.cell_types, + orig_mesh, + ) + json.dump(recovery_info, open(recovery_name, "w")) + + @staticmethod + def vtu2vtk(inmesh, outmesh): + reader = vtk.vtkXMLUnstructuredGridReader() + reader.SetFileName(inmesh) + reader.Update() + mesh = reader.GetOutput() + writer = vtk.vtkUnstructuredGridWriter() + writer.SetFileName(outmesh + ".vtk") + writer.SetInputData(mesh) + writer.SetFileTypeToBinary() + writer.Write() + + +if __name__ == "__main__": + MeshPartitioner() diff --git a/src/precice-aste-run.cpp b/src/precice-aste-run.cpp new file mode 100644 index 00000000..e25925c0 --- /dev/null +++ b/src/precice-aste-run.cpp @@ -0,0 +1,26 @@ +#include +#include +#include "logger.hpp" +#include "modes.hpp" +#include "utilities.hpp" + +int main(int argc, char *argv[]) +{ + auto context = aste::initializeMPI(argc, argv); + auto options = getOptions(argc, argv); + + if (options["verbose"].as()) { + boost::log::core::get()->set_filter(logging::trivial::severity >= logging::trivial::debug); + } + + if (options.count("aste-config")) { + ASTE_INFO << "ASTE Running on re-play mode"; + aste::runReplayMode(context, options["aste-config"].as()); + } else { + ASTE_INFO << "ASTE Running on mapping test mode"; + aste::runMapperMode(context, options); + } + ASTE_INFO << "Finalizing ASTE"; + MPI_Finalize(); + return EXIT_SUCCESS; +} diff --git a/src/preciceMap.cpp b/src/preciceMap.cpp deleted file mode 100644 index 6d96fd34..00000000 --- a/src/preciceMap.cpp +++ /dev/null @@ -1,310 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "precice/SolverInterface.hpp" -//#include "utils/EventUtils.hpp" -#include -#include -#include - -#include "common.hpp" -#include "easylogging++.h" - -INITIALIZE_EASYLOGGINGPP - -namespace fs = boost::filesystem; - - -/// Returns list of meshes matching meshname or meshname.dtN for the given rank -std::vector getMeshes(std::string basename, int rank) -{ - VLOG(1) << "Basename: " << basename; - std::vector meshes; - if (fs::is_directory(basename)) { - meshes.push_back(basename); - } - else { - int t = 0; - while (fs::is_directory(basename + ".dt" + std::to_string(t))) { - meshes.push_back(basename + ".dt" + std::to_string(t)); - ++t; - } - } - - // add the rank number - for (auto & mesh : meshes) { - std::string rankFile = mesh + "/" + std::to_string(rank); - if (fs::is_regular_file(rankFile)) - mesh = rankFile; - else - throw std::range_error("Mesh is not decomposed for requested rank, i.e. " + rankFile + " not found."); - } - - LOG(DEBUG) << "Meshes:" << [&]{ - std::ostringstream oss; - for(auto& mesh: meshes) - oss << ' ' << mesh; - return oss.str(); - }(); - return meshes; -} - -struct Mesh { - std::vector> positions; - std::vector> edges; - std::vector> triangles; - std::vector data; -}; - -using VertexID = int; -using EdgeID = int; - -struct Edge { - Edge(VertexID a, VertexID b) : vA(std::min(a,b)), vB(std::max(a,b)) {} - VertexID vA; - VertexID vB; -}; - -bool operator==(const Edge& lhs, const Edge& rhs) { - return (lhs.vA == rhs.vA) && (lhs.vB == rhs.vB); -} - -bool operator<(const Edge& lhs, const Edge& rhs) { - return (lhs.vA < rhs.vA) || ( (lhs.vA == rhs.vA) && (lhs.vB < rhs.vB) ); -} - -namespace std { - template<> struct hash { - using argument_type = Edge; - using result_type = std::size_t; - result_type operator()(argument_type const& e) const noexcept { - return std::hash{}(e.vA) ^ std::hash{}(e.vB); - } - }; -}; - -// Reads the main file containing the vertices and data -void readMainFile(Mesh& mesh, const std::string& filename, bool read_data) -{ - VLOG(1) << "Reading mesh vertices " << (read_data?"and data ":"") << "from file " << filename; - std::ifstream mainFile{filename}; - std::string line; - while (std::getline(mainFile, line)){ - double x, y, z, val; - std::istringstream iss(line); - iss >> x >> y >> z >> val; // split up by whitespace - std::array vertexPos{x, y, z}; - mesh.positions.push_back(vertexPos); - if (read_data) // val is ignored on B. - mesh.data.push_back(val); - } - if (not read_data) - mesh.data = std::vector(mesh.positions.size(), 0); -} - -// Reads the connectivity file containing the triangle and edge information -void readConnFile(Mesh& mesh, const std::string& filename) -{ - VLOG(1) << "Reading mesh connectivity information from file " << filename; - std::ifstream connFile{filename}; - std::string line; - while (std::getline(connFile, line)){ - std::vector parts; - boost::split(parts, line, [](char c){ return c == ' '; }); - std::vector indices(parts.size()); - std::transform(parts.begin(), parts.end(), indices.begin(), [](const std::string& s) -> size_t {return std::stol(s);}); - - if (indices.size() == 3) { - std::array elem{indices[0], indices[1], indices[2]}; - mesh.triangles.push_back(elem); - } else if (indices.size() == 2) { - std::array elem{indices[0], indices[1]}; - mesh.edges.push_back(elem); - } else { - throw std::runtime_error{std::string{"Invalid entry in connectivitiy file \""}.append(line).append("\"")}; - } - } -} - -/// Reads the mesh from the file. If not read_data, zeros are returned for data. -Mesh readMesh(const std::string& filename, bool read_data = true) -{ - Mesh mesh; - readMainFile(mesh, filename, read_data); - std::string connFile = filename + ".conn";// boost::filesystem::path(filename).replace_extension(".conn.txt").string(); - if (boost::filesystem::exists(connFile)) { - readConnFile(mesh, connFile); - } else { - VLOG(1) << "Skipped Reading mesh connectivity information from non-existent file " << filename; - } - return mesh; -} - -int main(int argc, char* argv[]) -{ - START_EASYLOGGINGPP(argc, argv); - MPI_Init(&argc, &argv); - auto options = getOptions(argc, argv); - const std::string meshname = options["mesh"].as(); - const std::string participant = options["participant"].as(); - - int MPIrank = 0, MPIsize = 0; - MPI_Comm_rank(MPI_COMM_WORLD, &MPIrank); - MPI_Comm_size(MPI_COMM_WORLD, &MPIsize); - - auto meshes = getMeshes(meshname, MPIrank); - - // Create and configure solver interface - precice::SolverInterface interface(participant, options["precice-config"].as(), MPIrank, MPIsize); - //precice::utils::EventRegistry::instance().runName = options["runName"].as(); - - const int meshID = interface.getMeshID( (participant == "A") ? "MeshA" : "MeshB" ); // participant = A => MeshID = MeshA - const int dataID = interface.getDataID("Data", meshID); - - // reads in mesh, 0 data for participant B - auto mesh = readMesh(meshes[0], participant == "A"); - VLOG(1) << "The mesh contains:\n " << mesh.positions.size() << " Vertices\n " << mesh.data.size() << " Data\n " << mesh.edges.size() << " Edges\n " << mesh.triangles.size() << " Triangles"; - - VLOG(1) << "Setting up Mesh:"; - VLOG(1) << "1) Setting up Vertices"; - // Feed vertices to preCICE - std::vector vertexIDs; - vertexIDs.reserve(mesh.positions.size()); - for (auto const & pos : mesh.positions) - vertexIDs.push_back(interface.setMeshVertex(meshID, pos.data())); - - boost::container::flat_map edgeMap; - edgeMap.reserve(mesh.edges.size() + 2*mesh.triangles.size()); - - VLOG(1) << " 2) Setting up Edges"; - for (auto const & edge : mesh.edges) { - const auto a = vertexIDs.at(edge[0]); - const auto b = vertexIDs.at(edge[1]); - assert(a != b); - - auto iter = edgeMap.find(Edge{a, b}); - if (iter == edgeMap.end()) { - EdgeID eid = interface.setMeshEdge(meshID, a, b); - edgeMap.emplace(Edge{a, b}, eid); - } - } - - VLOG(1) << " 3) Generate Triangle Edges"; - for (auto const & triangle : mesh.triangles) { - const auto a = vertexIDs.at(triangle[0]); - const auto b = vertexIDs.at(triangle[1]); - const auto c = vertexIDs.at(triangle[2]); - assert(a != b); - assert(b != c); - assert(c != a); - - const Edge ab{a, b}; - auto ab_pos = edgeMap.find(ab); - if (ab_pos == edgeMap.end()) { - EdgeID eid = interface.setMeshEdge(meshID, a, b); - edgeMap.emplace(ab, eid); - } - const Edge bc{b, c}; - auto bc_pos = edgeMap.find(bc); - if (bc_pos == edgeMap.end()) { - EdgeID eid = interface.setMeshEdge(meshID, b, c); - edgeMap.emplace(bc, eid); - } - const Edge ca{c, a}; - auto ca_pos = edgeMap.find(ca); - if (ca_pos == edgeMap.end()) { - EdgeID eid = interface.setMeshEdge(meshID, c, a); - edgeMap.emplace(ca, eid); - } - } - - VLOG(1) << " 4) Setting up Triangles"; - for (auto const & triangle : mesh.triangles) { - const auto a = vertexIDs[triangle[0]]; - const auto b = vertexIDs[triangle[1]]; - const auto c = vertexIDs[triangle[2]]; - - interface.setMeshTriangle( meshID, - edgeMap[Edge{a,b}], - edgeMap[Edge{b,c}], - edgeMap[Edge{c,a}] - ); - } - edgeMap.clear(); - VLOG(1) << "Mesh setup completed on Rank " << MPIrank; - - interface.initialize(); - - if (interface.isActionRequired(precice::constants::actionWriteInitialData())) { - VLOG(1) << "Write initial data for participant " << participant; - interface.writeBlockScalarData(dataID, mesh.data.size(), vertexIDs.data(), mesh.data.data()); - std::ostringstream oss; - for(size_t i = 0; i()); - if (MPIrank == 0) { - fs::remove_all(outdir); - fs::create_directory(outdir); - } - MPI_Barrier(MPI_COMM_WORLD); - - VLOG(1) << "Writing results to " << outdir; - std::ofstream ostream((outdir / std::to_string(MPIrank)).string(), std::ios::trunc); - ostream.precision(9); - auto const & positions = mesh.positions; - auto const & data = mesh.data; - for (size_t i = 0; i < mesh.positions.size(); i++) { - ostream << positions[i][0] << " " - << positions[i][1] << " " - << positions[i][2] << " " - << data[i] << '\n'; - } - ostream.close(); - } - - MPI_Finalize(); -} - diff --git a/src/utilities.cpp b/src/utilities.cpp new file mode 100644 index 00000000..bde1c686 --- /dev/null +++ b/src/utilities.cpp @@ -0,0 +1,155 @@ +#include "utilities.hpp" + +bool operator==(const Edge &lhs, const Edge &rhs) +{ + return (lhs.vA == rhs.vA) && (lhs.vB == rhs.vB); +} + +bool operator<(const Edge &lhs, const Edge &rhs) +{ + return (lhs.vA < rhs.vA) || ((lhs.vA == rhs.vA) && (lhs.vB < rhs.vB)); +} + +namespace std { +template <> +struct hash { + using argument_type = Edge; + using result_type = std::size_t; + result_type operator()(argument_type const &e) const noexcept + { + return std::hash{}(e.vA) ^ std::hash{}(e.vB); + } +}; +}; // namespace std + +aste::ExecutionContext aste::initializeMPI(int argc, char *argv[]) +{ + MPI_Init(&argc, &argv); + int rank = 0; + int size = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + return {rank, size}; +} + +std::vector aste::setupVertexIDs(precice::SolverInterface &interface, + const aste::Mesh &mesh, int meshID) +{ +#ifdef ASTE_SET_MESH_BLOCK + const auto dimension = interface.getDimensions(); + const auto nvertices = mesh.positions.size(); + std::vector posData(dimension * nvertices); + for (unsigned long i = 0; i < nvertices; ++i) { + const auto &pos = mesh.positions[i]; + assert(pos.size() == static_cast(dimension)); + std::copy(pos.begin(), pos.end(), &posData[i * dimension]); + } + + std::vector vertexIDs(nvertices); + interface.setMeshVertices(meshID, nvertices, posData.data(), vertexIDs.data()); + return vertexIDs; +#else + std::vector vertexIDs; + vertexIDs.reserve(mesh.positions.size()); + for (auto const &pos : mesh.positions) + vertexIDs.push_back(interface.setMeshVertex(meshID, pos.data())); + return vertexIDs; +#endif +} + +EdgeIdMap aste::setupEdgeIDs(precice::SolverInterface &interface, const aste::Mesh &mesh, int meshID, const std::vector &vertexIDs) +{ + ASTE_DEBUG << "Mesh Setup: 2.1) Gather Unique Edges"; + const auto unique_edges{gather_unique_edges(mesh)}; + + ASTE_DEBUG << "Mesh Setup: 2.2) Register Edges"; + boost::container::flat_map edgeMap; + edgeMap.reserve(unique_edges.size()); + + for (auto const &edge : unique_edges) { + const auto a = vertexIDs.at(edge[0]); + const auto b = vertexIDs.at(edge[1]); + assert(a != b); + EdgeID eid = interface.setMeshEdge(meshID, a, b); + edgeMap.emplace_hint(edgeMap.end(), Edge{a, b}, eid); + } + return edgeMap; +} + +std::vector aste::setupMesh(precice::SolverInterface &interface, const aste::Mesh &mesh, int meshID) +{ + auto tstart = std::chrono::steady_clock::now(); + + ASTE_DEBUG << "Mesh Setup started for mesh: " << mesh.fname; + ASTE_DEBUG << "Mesh Setup: 1) Vertices"; + const auto vertexIDs = setupVertexIDs(interface, mesh, meshID); + + auto tconnectivity = std::chrono::steady_clock::now(); + + if (interface.isMeshConnectivityRequired(meshID)) { + ASTE_DEBUG << "Mesh Setup: 2) Edges"; + const auto edgeMap = setupEdgeIDs(interface, mesh, meshID, vertexIDs); + ASTE_DEBUG << "Total " << edgeMap.size() << " edges are configured"; + if (!mesh.triangles.empty()) { + ASTE_DEBUG << "Mesh Setup: 3) " << mesh.triangles.size() << " Triangles"; + for (auto const &triangle : mesh.triangles) { + const auto a = vertexIDs[triangle[0]]; + const auto b = vertexIDs[triangle[1]]; + const auto c = vertexIDs[triangle[2]]; + + interface.setMeshTriangle(meshID, + edgeMap.at(Edge{a, b}), + edgeMap.at(Edge{b, c}), + edgeMap.at(Edge{c, a})); + } + } else { + ASTE_DEBUG << "Mesh Setup: 3) No Triangles are found/required. Skipped"; + } + if (!mesh.quadrilaterals.empty()) { + ASTE_DEBUG << "Mesh Setup: 4) " << mesh.quadrilaterals.size() << " Quadrilaterals"; + for (auto const &quadrilateral : mesh.quadrilaterals) { + const auto a = vertexIDs[quadrilateral[0]]; + const auto b = vertexIDs[quadrilateral[1]]; + const auto c = vertexIDs[quadrilateral[2]]; + const auto d = vertexIDs[quadrilateral[3]]; + + interface.setMeshQuad(meshID, + edgeMap.at(Edge{a, b}), + edgeMap.at(Edge{b, c}), + edgeMap.at(Edge{c, d}), + edgeMap.at(Edge{d, a})); + } + } else { + ASTE_DEBUG << "Mesh Setup: 4) No Quadrilaterals are found/required. Skipped"; + } + +#if PRECICE_VERSION_GREATER_EQUAL(2, 5, 0) + if (!mesh.tetrahedra.empty()) { + ASTE_DEBUG << "Mesh Setup: 5) " << mesh.tetrahedra.size() << " Tetrahedra"; + for (auto const &tetra : mesh.tetrahedra) { + const auto a = vertexIDs[tetra[0]]; + const auto b = vertexIDs[tetra[1]]; + const auto c = vertexIDs[tetra[2]]; + const auto d = vertexIDs[tetra[3]]; + + interface.setMeshTetrahedron(meshID, + a, b, c, d); + } + } else { + ASTE_DEBUG << "Mesh Setup: 5) No Tetrahedra are found/required. Skipped"; + } +#else + ASTE_DEBUG << "Mesh Setup: 5) Tetrahedra support was disabled."; +#endif + } else { + ASTE_DEBUG << "Mesh Setup: 2) Skipped connectivity information on mesh \"" << mesh.fname << "\" as it is not required."; + } + auto tend = std::chrono::steady_clock::now(); + + ASTE_DEBUG + << "Mesh Setup Took " + << std::chrono::duration_cast(tend - tstart).count() << "ms (" + << std::chrono::duration_cast(tconnectivity - tstart).count() << "ms for vertices, " + << std::chrono::duration_cast(tend - tconnectivity).count() << "ms for connectivity)"; + return vertexIDs; +} diff --git a/src/utilities.hpp b/src/utilities.hpp new file mode 100644 index 00000000..a29e7234 --- /dev/null +++ b/src/utilities.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "common.hpp" +#include "configreader.hpp" +#include "logger.hpp" +#include "mesh.hpp" +#include "modes.hpp" + +#include "precice/SolverInterface.hpp" + +namespace fs = boost::filesystem; + +using VertexID = int; +using EdgeID = int; + +struct Edge { + Edge(VertexID a, VertexID b) + : vA(std::min(a, b)), vB(std::max(a, b)) {} + VertexID vA; + VertexID vB; +}; + +using EdgeIdMap = boost::container::flat_map; + +namespace aste { +aste::ExecutionContext initializeMPI(int argc, char *argv[]); + +/** + * @brief Sets Vertices in preCICE and returns vertexIDs + * + * @param interface preCICE interface + * @param mesh Mesh in ASTE + * @param meshID Mesh ID of the Mesh in preCICE + * @return std::vector a vector of vertexIDs in preCICE + */ +std::vector setupVertexIDs(precice::SolverInterface &interface, + const aste::Mesh &mesh, int meshID); + +EdgeIdMap setupEdgeIDs(precice::SolverInterface &interface, const aste::Mesh &mesh, int meshID, const std::vector &vertexIDs); +/** + * @brief Setup mesh in preCICE (with connectivity information of provided). + * + * @param interface preCICE interface + * @param mesh Mesh in ASTE + * @param meshID ID of the Mesh in preCICE + * @return std::vector a vector of vertexIDs in preCICE + */ +std::vector setupMesh(precice::SolverInterface &interface, const aste::Mesh &mesh, int meshID); +} // namespace aste diff --git a/src/visualize_partition.py b/src/visualize_partition.py deleted file mode 100755 index 572b6373..00000000 --- a/src/visualize_partition.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env python3 -""" Small script to visualize a partition by adding the rank number as Point Data.""" - -import argparse -import os -from mesh_io import read_txt, write_vtk - -parser = argparse.ArgumentParser(description="Visualize partition of a mesh as pointData") -parser.add_argument("meshname", metavar="inputmesh", help="The mesh directory used as input") -parser.add_argument("--out", "-o", dest="out_meshname", help="The output mesh name") -args = parser.parse_args() - -dirname = args.meshname - -allpoints = [] -allcells = [] -allcell_types = [] -allvals = [] - -i = 0 -while os.path.isfile(dirname + "/" + str(i)): - filename = dirname + "/" + str(i) - points, cells, cell_types, _ = read_txt(filename) - assert(len(cells) == len(cell_types)) - - offset = len(allpoints) - allpoints.extend(points) - allcells.extend([ - tuple(map(lambda idx: idx+offset, cell)) - for cell in cells - ]) - allcell_types.extend(cell_types) - allvals.extend([i] * len(points)) - i += 1 - -assert(len(allpoints) == len(allvals)) -assert(len(allcells) == len(allcell_types)) -filename = args.out_meshname if args.out_meshname else dirname + ".vtk" -write_vtk(filename, allpoints, allcells, allcell_types, allvals) diff --git a/src/vtk_calculator.py b/src/vtk_calculator.py deleted file mode 100755 index 7d6a118c..00000000 --- a/src/vtk_calculator.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python3 -"""Evaluates a function on a given mesh, using the VTK Calculator.""" - -import argparse, logging, os.path -import mesh_io -import vtk - - -def parse_args(): - parser = argparse.ArgumentParser(description = __doc__) - parser.add_argument("in_meshname", metavar="inputmesh", help="The mesh used as input") - parser.add_argument("function", - help="""The function to evalutate on the mesh. - Syntax is the same as used in the calculator object, coordinates are given as e.g. 'coordX'.""") - parser.add_argument("--out", "-o", dest="out_meshname", help="""The output meshname. - Default is the same as for the input mesh""") - parser.add_argument("--log", "-l", dest="logging", default="INFO", - choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], help="""Set the log level. - Default is INFO""") - - args = parser.parse_args() - args.out_meshname = args.out_meshname or args.in_meshname - return args - -def main(): - args = parse_args() - logging.basicConfig(level = getattr(logging, args.logging)) - - assert os.path.isfile(args.in_meshname), "Input mesh file not found!" - data = mesh_io.read_dataset(args.in_meshname) - logging.info("Read in {} points.".format(data.GetNumberOfPoints())) - - calc = vtk.vtkArrayCalculator() - calc.SetInputData(data) - calc.AddCoordinateScalarVariable("coordsX", 0) - calc.AddCoordinateScalarVariable("coordsY", 1) - calc.AddCoordinateScalarVariable("coordsZ", 2) - calc.SetFunction(args.function) - calc.SetResultArrayName("scalars") - calc.Update() - logging.info("Evaluated '{}' on the mesh.".format(args.function)) - - writer = vtk.vtkUnstructuredGridWriter() - writer.SetInputData(calc.GetOutput()) - writer.SetFileName(args.out_meshname) - writer.Write() - logging.info("Written output to {}.".format(args.out_meshname)) - - - - -if __name__ == "__main__": - main() diff --git a/tests/read_test.cpp b/tests/read_test.cpp new file mode 100644 index 00000000..7c9690a2 --- /dev/null +++ b/tests/read_test.cpp @@ -0,0 +1,58 @@ +#include "testing.hpp" + +void readtest(const ReadCase ¤t_case) +{ + + auto read_test = aste::BaseName{current_case.fname}.with(aste::ExecutionContext()); + aste::Mesh mesh; + read_test.loadMesh(mesh, current_case.dim, current_case.connectivity); + + BOOST_TEST(mesh.positions.size() == 12); + if (current_case.connectivity) { + BOOST_TEST(mesh.edges.size() == 2); + } + if (current_case.dim == 3 && current_case.connectivity) { + BOOST_TEST(mesh.quadrilaterals.size() == 2); + BOOST_TEST(mesh.triangles.size() == 4); + } + // std::cout << "Number of mesh elements are correctly loaded\n"; + if (current_case.connectivity) { + BOOST_TEST(mesh.edges[1][0] == 10); + BOOST_TEST(mesh.edges[1][1] == 11); + } + // std::cout << "Edges loaded correctly\n"; + if (current_case.dim == 3 && current_case.connectivity) { + BOOST_TEST(mesh.triangles[0][0] == 0); + BOOST_TEST(mesh.triangles[0][1] == 1); + BOOST_TEST(mesh.triangles[0][2] == 3); + // std::cout << "Triangles loaded correctly\n"; + BOOST_TEST(mesh.quadrilaterals[1][0] == 4); + BOOST_TEST(mesh.quadrilaterals[1][1] == 5); + BOOST_TEST(mesh.quadrilaterals[1][2] == 8); + BOOST_TEST(mesh.quadrilaterals[1][3] == 7); + } + // std::cout << "Quads loaded correctly\n"; + aste::MeshData caseData(aste::datatype::WRITE, current_case.dim, current_case.dataname, 1); + mesh.meshdata.push_back(caseData); + read_test.loadData(mesh); + switch (current_case.dim) { + case 1: + BOOST_TEST(mesh.meshdata.front().dataVector.size() == 12); + break; + case 2: + BOOST_TEST(mesh.meshdata.front().dataVector.size() == 24); + break; + case 3: + BOOST_TEST(mesh.meshdata.front().dataVector.size() == 36); + break; + } + + std::vector testdata; + testdata.resize(mesh.meshdata.front().dataVector.size()); + + std::iota(testdata.begin(), testdata.end(), 0); + + for (size_t i = 0; i < mesh.meshdata.front().dataVector.size(); ++i) { + BOOST_TEST(mesh.meshdata.front().dataVector[i] == testdata[i]); + } +} diff --git a/tests/reference_scalars.vtk b/tests/reference_scalars.vtk new file mode 100644 index 00000000..25c8ab99 --- /dev/null +++ b/tests/reference_scalars.vtk @@ -0,0 +1,35 @@ +# vtk DataFile Version 4.1 +vtk output +ASCII +DATASET UNSTRUCTURED_GRID +POINTS 12 float +0 0 0 1 0 0 2 0 0 +0 1 0 1 1 0 2 1 0 +0 2 0 1 2 0 2 2 0 +4 0 0 5 0 0 6 0 0 + +CELLS 8 32 +4 3 4 7 6 +4 4 5 8 7 +3 0 1 3 +3 1 4 3 +3 1 2 4 +3 2 4 5 +2 9 10 +2 10 11 + +CELL_TYPES 8 +9 +9 +5 +5 +5 +5 +3 +3 + +POINT_DATA 12 +FIELD FieldData 1 +Scalars 1 12 double +0 1 2 3 4 5 6 7 8 +9 10 11 diff --git a/tests/reference_vector2d.vtk b/tests/reference_vector2d.vtk new file mode 100644 index 00000000..64689aa0 --- /dev/null +++ b/tests/reference_vector2d.vtk @@ -0,0 +1,36 @@ +# vtk DataFile Version 4.1 +vtk output +ASCII +DATASET UNSTRUCTURED_GRID +POINTS 12 float +0 0 0 1 0 0 2 0 0 +0 1 0 1 1 0 2 1 0 +0 2 0 1 2 0 2 2 0 +4 0 0 5 0 0 6 0 0 + +CELLS 8 32 +4 3 4 7 6 +4 4 5 8 7 +3 0 1 3 +3 1 4 3 +3 1 2 4 +3 2 4 5 +2 9 10 +2 10 11 + +CELL_TYPES 8 +9 +9 +5 +5 +5 +5 +3 +3 + +POINT_DATA 12 +FIELD FieldData 1 +Vector2D 2 12 double +0 1 2 3 4 5 6 7 8 +9 10 11 12 13 14 15 16 17 +18 19 20 21 22 23 diff --git a/tests/reference_vector3d.vtk b/tests/reference_vector3d.vtk new file mode 100644 index 00000000..339f1518 --- /dev/null +++ b/tests/reference_vector3d.vtk @@ -0,0 +1,37 @@ +# vtk DataFile Version 4.1 +vtk output +ASCII +DATASET UNSTRUCTURED_GRID +POINTS 12 float +0 0 0 1 0 0 2 0 0 +0 1 0 1 1 0 2 1 0 +0 2 0 1 2 0 2 2 0 +4 0 0 5 0 0 6 0 0 + +CELLS 8 32 +4 3 4 7 6 +4 4 5 8 7 +3 0 1 3 +3 1 4 3 +3 1 2 4 +3 2 4 5 +2 9 10 +2 10 11 + +CELL_TYPES 8 +9 +9 +5 +5 +5 +5 +3 +3 + +POINT_DATA 12 +FIELD FieldData 1 +Vector3D 3 12 double +0 1 2 3 4 5 6 7 8 +9 10 11 12 13 14 15 16 17 +18 19 20 21 22 23 24 25 26 +27 28 29 30 31 32 33 34 35 diff --git a/tests/testing.cpp b/tests/testing.cpp new file mode 100644 index 00000000..396f3827 --- /dev/null +++ b/tests/testing.cpp @@ -0,0 +1,67 @@ +#define BOOST_TEST_MODULE ASTE +#define BOOST_TEST_DYN_LINK +#include "testing.hpp" + +BOOST_AUTO_TEST_SUITE(read_write_tests) + +BOOST_AUTO_TEST_CASE(read_test_scalar_w_connectivity) +{ + readtest(ReadCase{"./reference_scalars", "Scalars", 1, true}); +} + +BOOST_AUTO_TEST_CASE(read_test_scalar_wo_connectivity) +{ + readtest(ReadCase{"./reference_scalars", "Scalars", 1, false}); +} + +BOOST_AUTO_TEST_CASE(read_test_2dvector_w_connectivity) +{ + readtest(ReadCase{"./reference_vector2d", "Vector2D", 2, true}); +} + +BOOST_AUTO_TEST_CASE(read_test_2dvector_wo_connectivity) +{ + readtest(ReadCase{"./reference_vector2d", "Vector2D", 2, false}); +} + +BOOST_AUTO_TEST_CASE(read_test_3dvector_w_connectivity) +{ + readtest(ReadCase{"./reference_vector3d", "Vector3D", 3, true}); +} + +BOOST_AUTO_TEST_CASE(read_test_3dvector_wo_connectivity) +{ + readtest(ReadCase{"./reference_vector3d", "Vector3D", 3, false}); +} + +BOOST_AUTO_TEST_CASE(write_test_scalar_w_connectivity) +{ + writetest(WriteCase{"./reference_scalars", "./scalar_write", "Scalars", 1, true}); +} + +BOOST_AUTO_TEST_CASE(write_test_scalar_wo_connectivity) +{ + writetest(WriteCase{"./reference_scalars", "./scalar_write", "Scalars", 1, false}); +} + +BOOST_AUTO_TEST_CASE(write_test_2dvector_w_connectivity) +{ + writetest(WriteCase{"./reference_vector2d", "./vector2d_write", "Vector2D", 2, true}); +} + +BOOST_AUTO_TEST_CASE(write_test_2dvector_wo_connectivity) +{ + writetest(WriteCase{"./reference_vector2d", "./vector2d_write", "Vector2D", 2, false}); +} + +BOOST_AUTO_TEST_CASE(write_test_3dvector_w_connectivity) +{ + writetest(WriteCase{"./reference_vector3d", "./vector3d_write", "Vector3D", 3, true}); +} + +BOOST_AUTO_TEST_CASE(write_test_3dvector_wo_connectivity) +{ + writetest(WriteCase{"./reference_vector3d", "./vector3d_write", "Vector3D", 3, false}); +} + +BOOST_AUTO_TEST_SUITE_END() // read_write_tests diff --git a/tests/testing.hpp b/tests/testing.hpp new file mode 100644 index 00000000..7e3f1f6e --- /dev/null +++ b/tests/testing.hpp @@ -0,0 +1,22 @@ +#include +#include +#include +#include + +struct ReadCase { + std::string fname{}; + std::string dataname{}; + int dim{}; + bool connectivity; +}; + +struct WriteCase { + std::string basename{}; + std::string fname{}; + std::string dataname{}; + int dim{}; + bool connectivity; +}; + +void writetest(const WriteCase ¤t_case); +void readtest(const ReadCase ¤t_case); diff --git a/tests/write_test.cpp b/tests/write_test.cpp new file mode 100644 index 00000000..14ca924d --- /dev/null +++ b/tests/write_test.cpp @@ -0,0 +1,73 @@ +#include +#include +#include + +#include "testing.hpp" + +namespace fs = boost::filesystem; + +void writetest(const WriteCase ¤t_case) +{ + + auto write_test = aste::BaseName{current_case.basename}.with(aste::ExecutionContext()); + aste::Mesh testMesh; + write_test.loadMesh(testMesh, current_case.dim, current_case.connectivity); + aste::MeshData caseData(aste::datatype::WRITE, current_case.dim, current_case.dataname, 1); + testMesh.meshdata.push_back(caseData); + write_test.loadData(testMesh); + + // Create a new data (mapped) and changeg with old one + // Use random starting point for a series of data + testMesh.meshdata.front().dataVector.resize(testMesh.positions.size() * current_case.dim); + std::iota(testMesh.meshdata.front().dataVector.begin(), testMesh.meshdata.front().dataVector.end(), rand()); + + auto scalar_test = aste::BaseName{"write_test"}.with(aste::ExecutionContext()); + scalar_test.save(testMesh, "write_test"); + + // Read written data and compare with created data + auto read = aste::BaseName{"write_test"}.with(aste::ExecutionContext()); + aste::Mesh testMeshRead; + read.loadMesh(testMeshRead, current_case.dim, current_case.connectivity); + testMeshRead.meshdata.push_back(caseData); + read.loadData(testMeshRead); + + // Check Elements are correctly written + BOOST_TEST(testMeshRead.positions.size() == testMesh.positions.size()); + if (current_case.connectivity) { + BOOST_TEST(testMeshRead.edges.size() == testMesh.edges.size()); + } + if (current_case.dim == 3 && current_case.connectivity) { + BOOST_TEST(testMeshRead.quadrilaterals.size() == testMesh.quadrilaterals.size()); + BOOST_TEST(testMeshRead.triangles.size() == testMesh.triangles.size()); + } + // Check Edges + if (current_case.connectivity) { + BOOST_TEST(testMeshRead.edges[1][0] == testMesh.edges[1][0]); + BOOST_TEST(testMeshRead.edges[1][1] == testMesh.edges[1][1]); + } + if (current_case.dim == 3 && current_case.connectivity) { + // Check Triangles + BOOST_TEST(testMeshRead.triangles[0][0] == testMesh.triangles[0][0]); + BOOST_TEST(testMeshRead.triangles[0][1] == testMesh.triangles[0][1]); + BOOST_TEST(testMeshRead.triangles[0][2] == testMesh.triangles[0][2]); + // Check Quads + BOOST_TEST(testMeshRead.quadrilaterals[1][0] == testMesh.quadrilaterals[1][0]); + BOOST_TEST(testMeshRead.quadrilaterals[1][1] == testMesh.quadrilaterals[1][1]); + BOOST_TEST(testMeshRead.quadrilaterals[1][2] == testMesh.quadrilaterals[1][2]); + BOOST_TEST(testMeshRead.quadrilaterals[1][3] == testMesh.quadrilaterals[1][3]); + } + // Check Datasize + BOOST_TEST(testMeshRead.meshdata.front().dataVector.size() == testMesh.meshdata.front().dataVector.size()); + // Check Data Values + for (size_t i = 0; i < testMeshRead.meshdata.front().dataVector.size(); ++i) { + BOOST_TEST(testMeshRead.meshdata.front().dataVector[i] == testMesh.meshdata.front().dataVector[i]); + } + + // Remove Artifacts + if (fs::is_regular_file(current_case.fname + ".vtk")) { + fs::remove(current_case.fname + ".vtk"); + } + if (fs::is_regular_file("write_test.vtk")) { + fs::remove("write_test.vtk"); + } +} diff --git a/thirdparty/json.hpp b/thirdparty/json.hpp new file mode 100644 index 00000000..05000fbb --- /dev/null +++ b/thirdparty/json.hpp @@ -0,0 +1,22111 @@ +/* + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ +| | |__ | | | | | | version 3.10.5 +|_____|_____|_____|_|___| https://github.com/nlohmann/json + +Licensed under the MIT License . +SPDX-License-Identifier: MIT +Copyright (c) 2013-2022 Niels Lohmann . + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/****************************************************************************\ + * Note on documentation: The source files contain links to the online * + * documentation of the public API at https://json.nlohmann.me. This URL * + * contains the most recent documentation and should also be applicable to * + * previous versions; documentation for deprecated functions is not * + * removed, but marked deprecated. See "Generate documentation" section in * + * file doc/README.md. * +\****************************************************************************/ + +#ifndef INCLUDE_NLOHMANN_JSON_HPP_ +#define INCLUDE_NLOHMANN_JSON_HPP_ + +#define NLOHMANN_JSON_VERSION_MAJOR 3 +#define NLOHMANN_JSON_VERSION_MINOR 10 +#define NLOHMANN_JSON_VERSION_PATCH 5 + +#include // all_of, find, for_each +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#ifndef JSON_NO_IO + #include // istream, ostream +#endif // JSON_NO_IO +#include // random_access_iterator_tag +#include // unique_ptr +#include // accumulate +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap +#include // vector + +// #include + + +#include +#include + +// #include + + +#include // transform +#include // array +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +// #include + + +#include // exception +#include // runtime_error +#include // to_string +#include // vector + +// #include + + +#include // array +#include // size_t +#include // uint8_t +#include // string + +namespace nlohmann +{ +namespace detail +{ +/////////////////////////// +// JSON type enumeration // +/////////////////////////// + +/*! +@brief the JSON type enumeration + +This enumeration collects the different JSON types. It is internally used to +distinguish the stored values, and the functions @ref basic_json::is_null(), +@ref basic_json::is_object(), @ref basic_json::is_array(), +@ref basic_json::is_string(), @ref basic_json::is_boolean(), +@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), +@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), +@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and +@ref basic_json::is_structured() rely on it. + +@note There are three enumeration entries (number_integer, number_unsigned, and +number_float), because the library distinguishes these three types for numbers: +@ref basic_json::number_unsigned_t is used for unsigned integers, +@ref basic_json::number_integer_t is used for signed integers, and +@ref basic_json::number_float_t is used for floating-point numbers or to +approximate integers which do not fit in the limits of their respective type. + +@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON +value with the default value for a given type + +@since version 1.0.0 +*/ +enum class value_t : std::uint8_t +{ + null, ///< null value + object, ///< object (unordered set of name/value pairs) + array, ///< array (ordered collection of values) + string, ///< string value + boolean, ///< boolean value + number_integer, ///< number value (signed integer) + number_unsigned, ///< number value (unsigned integer) + number_float, ///< number value (floating-point) + binary, ///< binary array (ordered collection of bytes) + discarded ///< discarded by the parser callback function +}; + +/*! +@brief comparison operator for JSON types + +Returns an ordering that is similar to Python: +- order: null < boolean < number < object < array < string < binary +- furthermore, each type is not smaller than itself +- discarded values are not comparable +- binary is represented as a b"" string in python and directly comparable to a + string; however, making a binary array directly comparable with a string would + be surprising behavior in a JSON file. + +@since version 1.0.0 +*/ +inline bool operator<(const value_t lhs, const value_t rhs) noexcept +{ + static constexpr std::array order = {{ + 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, + 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, + 6 /* binary */ + } + }; + + const auto l_index = static_cast(lhs); + const auto r_index = static_cast(rhs); + return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; +} +} // namespace detail +} // namespace nlohmann + +// #include + + +#include +// #include + + +#include // declval, pair +// #include + + +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to + * the public domain worldwide. This software is distributed without + * any warranty. + * + * For details, see . + * SPDX-License-Identifier: CC0-1.0 + */ + +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) +#if defined(JSON_HEDLEY_VERSION) + #undef JSON_HEDLEY_VERSION +#endif +#define JSON_HEDLEY_VERSION 15 + +#if defined(JSON_HEDLEY_STRINGIFY_EX) + #undef JSON_HEDLEY_STRINGIFY_EX +#endif +#define JSON_HEDLEY_STRINGIFY_EX(x) #x + +#if defined(JSON_HEDLEY_STRINGIFY) + #undef JSON_HEDLEY_STRINGIFY +#endif +#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) + +#if defined(JSON_HEDLEY_CONCAT_EX) + #undef JSON_HEDLEY_CONCAT_EX +#endif +#define JSON_HEDLEY_CONCAT_EX(a,b) a##b + +#if defined(JSON_HEDLEY_CONCAT) + #undef JSON_HEDLEY_CONCAT +#endif +#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) + +#if defined(JSON_HEDLEY_CONCAT3_EX) + #undef JSON_HEDLEY_CONCAT3_EX +#endif +#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c + +#if defined(JSON_HEDLEY_CONCAT3) + #undef JSON_HEDLEY_CONCAT3 +#endif +#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) + +#if defined(JSON_HEDLEY_VERSION_ENCODE) + #undef JSON_HEDLEY_VERSION_ENCODE +#endif +#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) + #undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) + #undef JSON_HEDLEY_VERSION_DECODE_MINOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) + #undef JSON_HEDLEY_VERSION_DECODE_REVISION +#endif +#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) + +#if defined(JSON_HEDLEY_GNUC_VERSION) + #undef JSON_HEDLEY_GNUC_VERSION +#endif +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) + #undef JSON_HEDLEY_GNUC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GNUC_VERSION) + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION) + #undef JSON_HEDLEY_MSVC_VERSION +#endif +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) + #undef JSON_HEDLEY_MSVC_VERSION_CHECK +#endif +#if !defined(JSON_HEDLEY_MSVC_VERSION) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION) + #undef JSON_HEDLEY_INTEL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_VERSION) + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #undef JSON_HEDLEY_INTEL_CL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) + #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION) + #undef JSON_HEDLEY_PGI_VERSION +#endif +#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) + #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) + #undef JSON_HEDLEY_PGI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #undef JSON_HEDLEY_SUNPRO_VERSION +#endif +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) + #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#endif +#if defined(__EMSCRIPTEN__) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION) + #undef JSON_HEDLEY_ARM_VERSION +#endif +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) + #undef JSON_HEDLEY_ARM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_ARM_VERSION) + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION) + #undef JSON_HEDLEY_IBM_VERSION +#endif +#if defined(__ibmxl__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) + #undef JSON_HEDLEY_IBM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IBM_VERSION) + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION) + #undef JSON_HEDLEY_TI_VERSION +#endif +#if \ + defined(__TI_COMPILER_VERSION__) && \ + ( \ + defined(__TMS470__) || defined(__TI_ARM__) || \ + defined(__MSP430__) || \ + defined(__TMS320C2000__) \ + ) +#if (__TI_COMPILER_VERSION__ >= 16000000) + #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif +#endif + +#if defined(JSON_HEDLEY_TI_VERSION_CHECK) + #undef JSON_HEDLEY_TI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_VERSION) + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #undef JSON_HEDLEY_TI_CL2000_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) + #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #undef JSON_HEDLEY_TI_CL430_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) + #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #undef JSON_HEDLEY_TI_ARMCL_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) + #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) + #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #undef JSON_HEDLEY_TI_CL6X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) + #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #undef JSON_HEDLEY_TI_CL7X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) + #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #undef JSON_HEDLEY_TI_CLPRU_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) + #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION) + #undef JSON_HEDLEY_CRAY_VERSION +#endif +#if defined(_CRAYC) + #if defined(_RELEASE_PATCHLEVEL) + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) + #else + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) + #undef JSON_HEDLEY_CRAY_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_CRAY_VERSION) + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION) + #undef JSON_HEDLEY_IAR_VERSION +#endif +#if defined(__IAR_SYSTEMS_ICC__) + #if __VER__ > 1000 + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) + #else + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) + #undef JSON_HEDLEY_IAR_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IAR_VERSION) + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION) + #undef JSON_HEDLEY_TINYC_VERSION +#endif +#if defined(__TINYC__) + #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) + #undef JSON_HEDLEY_TINYC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION) + #undef JSON_HEDLEY_DMC_VERSION +#endif +#if defined(__DMC__) + #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) + #undef JSON_HEDLEY_DMC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_DMC_VERSION) + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #undef JSON_HEDLEY_COMPCERT_VERSION +#endif +#if defined(__COMPCERT_VERSION__) + #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) + #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION) + #undef JSON_HEDLEY_PELLES_VERSION +#endif +#if defined(__POCC__) + #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) + #undef JSON_HEDLEY_PELLES_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PELLES_VERSION) + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #undef JSON_HEDLEY_MCST_LCC_VERSION +#endif +#if defined(__LCC__) && defined(__LCC_MINOR__) + #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) + #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION) + #undef JSON_HEDLEY_GCC_VERSION +#endif +#if \ + defined(JSON_HEDLEY_GNUC_VERSION) && \ + !defined(__clang__) && \ + !defined(JSON_HEDLEY_INTEL_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_CRAY_VERSION) && \ + !defined(JSON_HEDLEY_TI_VERSION) && \ + !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ + !defined(__COMPCERT__) && \ + !defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_ATTRIBUTE +#endif +#if \ + defined(__has_attribute) && \ + ( \ + (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ + ) +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#else +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#endif +#if \ + defined(__has_cpp_attribute) && \ + defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#elif \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_BUILTIN) + #undef JSON_HEDLEY_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else + #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) + #undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) + #undef JSON_HEDLEY_GCC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_FEATURE) + #undef JSON_HEDLEY_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#else + #define JSON_HEDLEY_HAS_FEATURE(feature) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) + #undef JSON_HEDLEY_GNUC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) + #undef JSON_HEDLEY_GCC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_EXTENSION) + #undef JSON_HEDLEY_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#else + #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) + #undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) + #undef JSON_HEDLEY_GCC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_WARNING) + #undef JSON_HEDLEY_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#else + #define JSON_HEDLEY_HAS_WARNING(warning) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) + #undef JSON_HEDLEY_GNUC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_WARNING) + #undef JSON_HEDLEY_GCC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) + #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_PRAGMA(value) __pragma(value) +#else + #define JSON_HEDLEY_PRAGMA(value) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) + #undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) + #undef JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) + #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_PUSH + #define JSON_HEDLEY_DIAGNOSTIC_POP +#endif + +/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") +# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# endif +#endif +#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + +#if defined(JSON_HEDLEY_CONST_CAST) + #undef JSON_HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif \ + JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_REINTERPRET_CAST) + #undef JSON_HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_STATIC_CAST) + #undef JSON_HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else + #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_CPP_CAST) + #undef JSON_HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ + ((T) (expr)) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("diag_suppress=Pe137") \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) +# endif +#else +# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif + +#if defined(JSON_HEDLEY_DEPRECATED) + #undef JSON_HEDLEY_DEPRECATED +#endif +#if defined(JSON_HEDLEY_DEPRECATED_FOR) + #undef JSON_HEDLEY_DEPRECATED_FOR +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) +#elif \ + (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif defined(__cplusplus) && (__cplusplus >= 201402L) + #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") +#else + #define JSON_HEDLEY_DEPRECATED(since) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) +#endif + +#if defined(JSON_HEDLEY_UNAVAILABLE) + #undef JSON_HEDLEY_UNAVAILABLE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) +#else + #define JSON_HEDLEY_UNAVAILABLE(available_since) +#endif + +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT +#endif +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) +#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#elif defined(_Check_return_) /* SAL */ + #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ +#else + #define JSON_HEDLEY_WARN_UNUSED_RESULT + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) +#endif + +#if defined(JSON_HEDLEY_SENTINEL) + #undef JSON_HEDLEY_SENTINEL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) +#else + #define JSON_HEDLEY_SENTINEL(position) +#endif + +#if defined(JSON_HEDLEY_NO_RETURN) + #undef JSON_HEDLEY_NO_RETURN +#endif +#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NO_RETURN __noreturn +#elif \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #define JSON_HEDLEY_NO_RETURN _Noreturn +#elif defined(__cplusplus) && (__cplusplus >= 201103L) + #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#else + #define JSON_HEDLEY_NO_RETURN +#endif + +#if defined(JSON_HEDLEY_NO_ESCAPE) + #undef JSON_HEDLEY_NO_ESCAPE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) + #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else + #define JSON_HEDLEY_NO_ESCAPE +#endif + +#if defined(JSON_HEDLEY_UNREACHABLE) + #undef JSON_HEDLEY_UNREACHABLE +#endif +#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) + #undef JSON_HEDLEY_UNREACHABLE_RETURN +#endif +#if defined(JSON_HEDLEY_ASSUME) + #undef JSON_HEDLEY_ASSUME +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_ASSUME(expr) __assume(expr) +#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) + #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) +#elif \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #if defined(__cplusplus) + #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) + #else + #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) + #endif +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif defined(JSON_HEDLEY_ASSUME) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif +#if !defined(JSON_HEDLEY_ASSUME) + #if defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) + #else + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) + #endif +#endif +#if defined(JSON_HEDLEY_UNREACHABLE) + #if \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) + #else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() + #endif +#else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) +#endif +#if !defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif + +JSON_HEDLEY_DIAGNOSTIC_PUSH +#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") + #pragma clang diagnostic ignored "-Wpedantic" +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) + #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) + #if defined(__clang__) + #pragma clang diagnostic ignored "-Wvariadic-macros" + #elif defined(JSON_HEDLEY_GCC_VERSION) + #pragma GCC diagnostic ignored "-Wvariadic-macros" + #endif +#endif +#if defined(JSON_HEDLEY_NON_NULL) + #undef JSON_HEDLEY_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else + #define JSON_HEDLEY_NON_NULL(...) +#endif +JSON_HEDLEY_DIAGNOSTIC_POP + +#if defined(JSON_HEDLEY_PRINTF_FORMAT) + #undef JSON_HEDLEY_PRINTF_FORMAT +#endif +#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) +#else + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) +#endif + +#if defined(JSON_HEDLEY_CONSTEXPR) + #undef JSON_HEDLEY_CONSTEXPR +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) + #endif +#endif +#if !defined(JSON_HEDLEY_CONSTEXPR) + #define JSON_HEDLEY_CONSTEXPR +#endif + +#if defined(JSON_HEDLEY_PREDICT) + #undef JSON_HEDLEY_PREDICT +#endif +#if defined(JSON_HEDLEY_LIKELY) + #undef JSON_HEDLEY_LIKELY +#endif +#if defined(JSON_HEDLEY_UNLIKELY) + #undef JSON_HEDLEY_UNLIKELY +#endif +#if defined(JSON_HEDLEY_UNPREDICTABLE) + #undef JSON_HEDLEY_UNPREDICTABLE +#endif +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) + #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) +#elif \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ + (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ + })) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ + })) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#else +# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) +# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) +#endif +#if !defined(JSON_HEDLEY_UNPREDICTABLE) + #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) +#endif + +#if defined(JSON_HEDLEY_MALLOC) + #undef JSON_HEDLEY_MALLOC +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_MALLOC __declspec(restrict) +#else + #define JSON_HEDLEY_MALLOC +#endif + +#if defined(JSON_HEDLEY_PURE) + #undef JSON_HEDLEY_PURE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ + ) +# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +#else +# define JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_CONST) + #undef JSON_HEDLEY_CONST +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_CONST __attribute__((__const__)) +#elif \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_CONST _Pragma("no_side_effect") +#else + #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_RESTRICT) + #undef JSON_HEDLEY_RESTRICT +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT restrict +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + defined(__clang__) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RESTRICT __restrict +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT _Restrict +#else + #define JSON_HEDLEY_RESTRICT +#endif + +#if defined(JSON_HEDLEY_INLINE) + #undef JSON_HEDLEY_INLINE +#endif +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) + #define JSON_HEDLEY_INLINE inline +#elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) + #define JSON_HEDLEY_INLINE __inline__ +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_INLINE __inline +#else + #define JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_ALWAYS_INLINE) + #undef JSON_HEDLEY_ALWAYS_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) +# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ + ) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +#else +# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_NEVER_INLINE) + #undef JSON_HEDLEY_NEVER_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#else + #define JSON_HEDLEY_NEVER_INLINE +#endif + +#if defined(JSON_HEDLEY_PRIVATE) + #undef JSON_HEDLEY_PRIVATE +#endif +#if defined(JSON_HEDLEY_PUBLIC) + #undef JSON_HEDLEY_PUBLIC +#endif +#if defined(JSON_HEDLEY_IMPORT) + #undef JSON_HEDLEY_IMPORT +#endif +#if defined(_WIN32) || defined(__CYGWIN__) +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC __declspec(dllexport) +# define JSON_HEDLEY_IMPORT __declspec(dllimport) +#else +# if \ + JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + ( \ + defined(__TI_EABI__) && \ + ( \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ + ) \ + ) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) +# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) +# else +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC +# endif +# define JSON_HEDLEY_IMPORT extern +#endif + +#if defined(JSON_HEDLEY_NO_THROW) + #undef JSON_HEDLEY_NO_THROW +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NO_THROW __declspec(nothrow) +#else + #define JSON_HEDLEY_NO_THROW +#endif + +#if defined(JSON_HEDLEY_FALL_THROUGH) + #undef JSON_HEDLEY_FALL_THROUGH +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ + #define JSON_HEDLEY_FALL_THROUGH __fallthrough +#else + #define JSON_HEDLEY_FALL_THROUGH +#endif + +#if defined(JSON_HEDLEY_RETURNS_NON_NULL) + #undef JSON_HEDLEY_RETURNS_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) +#elif defined(_Ret_notnull_) /* SAL */ + #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ +#else + #define JSON_HEDLEY_RETURNS_NON_NULL +#endif + +#if defined(JSON_HEDLEY_ARRAY_PARAM) + #undef JSON_HEDLEY_ARRAY_PARAM +#endif +#if \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__STDC_NO_VLA__) && \ + !defined(__cplusplus) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_ARRAY_PARAM(name) (name) +#else + #define JSON_HEDLEY_ARRAY_PARAM(name) +#endif + +#if defined(JSON_HEDLEY_IS_CONSTANT) + #undef JSON_HEDLEY_IS_CONSTANT +#endif +#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) + #undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#endif +/* JSON_HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #undef JSON_HEDLEY_IS_CONSTEXPR_ +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) +#endif +#if !defined(__cplusplus) +# if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) +#endif +# elif \ + ( \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ + !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION)) || \ + (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) +#endif +# elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + defined(JSON_HEDLEY_INTEL_VERSION) || \ + defined(JSON_HEDLEY_TINYC_VERSION) || \ + defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ + defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ + defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ + defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ + defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ + defined(__clang__) +# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ + sizeof(void) != \ + sizeof(*( \ + 1 ? \ + ((void*) ((expr) * 0L) ) : \ +((struct { char v[sizeof(void) * 2]; } *) 1) \ + ) \ + ) \ + ) +# endif +#endif +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) +#else + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) (0) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#endif + +#if defined(JSON_HEDLEY_BEGIN_C_DECLS) + #undef JSON_HEDLEY_BEGIN_C_DECLS +#endif +#if defined(JSON_HEDLEY_END_C_DECLS) + #undef JSON_HEDLEY_END_C_DECLS +#endif +#if defined(JSON_HEDLEY_C_DECL) + #undef JSON_HEDLEY_C_DECL +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { + #define JSON_HEDLEY_END_C_DECLS } + #define JSON_HEDLEY_C_DECL extern "C" +#else + #define JSON_HEDLEY_BEGIN_C_DECLS + #define JSON_HEDLEY_END_C_DECLS + #define JSON_HEDLEY_C_DECL +#endif + +#if defined(JSON_HEDLEY_STATIC_ASSERT) + #undef JSON_HEDLEY_STATIC_ASSERT +#endif +#if \ + !defined(__cplusplus) && ( \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + defined(_Static_assert) \ + ) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) +#else +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) +#endif + +#if defined(JSON_HEDLEY_NULL) + #undef JSON_HEDLEY_NULL +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) + #elif defined(NULL) + #define JSON_HEDLEY_NULL NULL + #else + #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) + #endif +#elif defined(NULL) + #define JSON_HEDLEY_NULL NULL +#else + #define JSON_HEDLEY_NULL ((void*) 0) +#endif + +#if defined(JSON_HEDLEY_MESSAGE) + #undef JSON_HEDLEY_MESSAGE +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_MESSAGE(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(message msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) +#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_WARNING) + #undef JSON_HEDLEY_WARNING +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_WARNING(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(clang warning msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_REQUIRE) + #undef JSON_HEDLEY_REQUIRE +#endif +#if defined(JSON_HEDLEY_REQUIRE_MSG) + #undef JSON_HEDLEY_REQUIRE_MSG +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) +# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") +# define JSON_HEDLEY_REQUIRE(expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) +# endif +#else +# define JSON_HEDLEY_REQUIRE(expr) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) +#endif + +#if defined(JSON_HEDLEY_FLAGS) + #undef JSON_HEDLEY_FLAGS +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) + #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#else + #define JSON_HEDLEY_FLAGS +#endif + +#if defined(JSON_HEDLEY_FLAGS_CAST) + #undef JSON_HEDLEY_FLAGS_CAST +#endif +#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) +# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("warning(disable:188)") \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) +#endif + +#if defined(JSON_HEDLEY_EMPTY_BASES) + #undef JSON_HEDLEY_EMPTY_BASES +#endif +#if \ + (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else + #define JSON_HEDLEY_EMPTY_BASES +#endif + +/* Remaining macros are deprecated. */ + +#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#endif +#if defined(__clang__) + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) +#else + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) + #undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#endif +#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) + +#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) + #undef JSON_HEDLEY_CLANG_HAS_FEATURE +#endif +#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) + +#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) + #undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#endif +#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) + +#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) + #undef JSON_HEDLEY_CLANG_HAS_WARNING +#endif +#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) + +#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ + +// #include + + +#include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; +} // namespace detail +} // namespace nlohmann + + +// https://en.cppreference.com/w/cpp/experimental/is_detected +namespace nlohmann +{ +namespace detail +{ +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template class Op, class... Args> +using is_detected = typename detector::value_t; + +template class Op, class... Args> +struct is_detected_lazy : is_detected { }; + +template class Op, class... Args> +using detected_t = typename detector::type; + +template class Op, class... Args> +using detected_or = detector; + +template class Op, class... Args> +using detected_or_t = typename detected_or::type; + +template class Op, class... Args> +using is_detected_exact = std::is_same>; + +template class Op, class... Args> +using is_detected_convertible = + std::is_convertible, To>; +} // namespace detail +} // namespace nlohmann + + +// This file contains all internal macro definitions +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// C++ language standard detection +// if the user manually specified the used c++ version this is skipped +#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) + #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 + #endif + // the cpp 11 flag is always specified because it is the minimal required version + #define JSON_HAS_CPP_11 +#endif + +#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) + #ifdef JSON_HAS_CPP_17 + #if defined(__cpp_lib_filesystem) + #define JSON_HAS_FILESYSTEM 1 + #elif defined(__cpp_lib_experimental_filesystem) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif !defined(__has_include) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #endif + + // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ + #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__clang_major__) && __clang_major__ < 7 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support + #if defined(_MSC_VER) && _MSC_VER < 1914 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before iOS 13 + #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before macOS Catalina + #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + #endif +#endif + +#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_FILESYSTEM + #define JSON_HAS_FILESYSTEM 0 +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdocumentation" + #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" +#endif + +// allow disabling exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #include + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +// allow overriding assert +#if !defined(JSON_ASSERT) + #include // assert + #define JSON_ASSERT(x) assert(x) +#endif + +// allow to access some private functions (needed by the test suite) +#if defined(JSON_TESTS_PRIVATE) + #define JSON_PRIVATE_UNLESS_TESTED public +#else + #define JSON_PRIVATE_UNLESS_TESTED private +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer, \ + class BinaryType> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + +// Macros to simplify conversion from/to types + +#define NLOHMANN_JSON_EXPAND( x ) x +#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME +#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ + NLOHMANN_JSON_PASTE64, \ + NLOHMANN_JSON_PASTE63, \ + NLOHMANN_JSON_PASTE62, \ + NLOHMANN_JSON_PASTE61, \ + NLOHMANN_JSON_PASTE60, \ + NLOHMANN_JSON_PASTE59, \ + NLOHMANN_JSON_PASTE58, \ + NLOHMANN_JSON_PASTE57, \ + NLOHMANN_JSON_PASTE56, \ + NLOHMANN_JSON_PASTE55, \ + NLOHMANN_JSON_PASTE54, \ + NLOHMANN_JSON_PASTE53, \ + NLOHMANN_JSON_PASTE52, \ + NLOHMANN_JSON_PASTE51, \ + NLOHMANN_JSON_PASTE50, \ + NLOHMANN_JSON_PASTE49, \ + NLOHMANN_JSON_PASTE48, \ + NLOHMANN_JSON_PASTE47, \ + NLOHMANN_JSON_PASTE46, \ + NLOHMANN_JSON_PASTE45, \ + NLOHMANN_JSON_PASTE44, \ + NLOHMANN_JSON_PASTE43, \ + NLOHMANN_JSON_PASTE42, \ + NLOHMANN_JSON_PASTE41, \ + NLOHMANN_JSON_PASTE40, \ + NLOHMANN_JSON_PASTE39, \ + NLOHMANN_JSON_PASTE38, \ + NLOHMANN_JSON_PASTE37, \ + NLOHMANN_JSON_PASTE36, \ + NLOHMANN_JSON_PASTE35, \ + NLOHMANN_JSON_PASTE34, \ + NLOHMANN_JSON_PASTE33, \ + NLOHMANN_JSON_PASTE32, \ + NLOHMANN_JSON_PASTE31, \ + NLOHMANN_JSON_PASTE30, \ + NLOHMANN_JSON_PASTE29, \ + NLOHMANN_JSON_PASTE28, \ + NLOHMANN_JSON_PASTE27, \ + NLOHMANN_JSON_PASTE26, \ + NLOHMANN_JSON_PASTE25, \ + NLOHMANN_JSON_PASTE24, \ + NLOHMANN_JSON_PASTE23, \ + NLOHMANN_JSON_PASTE22, \ + NLOHMANN_JSON_PASTE21, \ + NLOHMANN_JSON_PASTE20, \ + NLOHMANN_JSON_PASTE19, \ + NLOHMANN_JSON_PASTE18, \ + NLOHMANN_JSON_PASTE17, \ + NLOHMANN_JSON_PASTE16, \ + NLOHMANN_JSON_PASTE15, \ + NLOHMANN_JSON_PASTE14, \ + NLOHMANN_JSON_PASTE13, \ + NLOHMANN_JSON_PASTE12, \ + NLOHMANN_JSON_PASTE11, \ + NLOHMANN_JSON_PASTE10, \ + NLOHMANN_JSON_PASTE9, \ + NLOHMANN_JSON_PASTE8, \ + NLOHMANN_JSON_PASTE7, \ + NLOHMANN_JSON_PASTE6, \ + NLOHMANN_JSON_PASTE5, \ + NLOHMANN_JSON_PASTE4, \ + NLOHMANN_JSON_PASTE3, \ + NLOHMANN_JSON_PASTE2, \ + NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) +#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) +#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) +#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) +#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) +#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) +#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) +#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) +#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) +#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) +#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) +#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) +#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) +#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) +#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) +#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) +#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) +#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) +#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) +#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) +#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) +#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) +#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) +#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) +#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) +#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) +#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) +#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) +#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) +#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) +#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) +#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) +#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) +#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) +#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) +#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) +#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) +#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) +#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) +#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) +#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) +#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) +#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) +#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) +#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) +#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) +#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) +#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) +#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) +#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) +#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) +#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) +#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) +#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) +#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) +#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) +#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) +#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) +#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) +#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) +#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) +#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) +#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) +#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) + +#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; +#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + + +// inspired from https://stackoverflow.com/a/26745591 +// allows to call any std function as if (e.g. with begin): +// using std::begin; begin(x); +// +// it allows using the detected idiom to retrieve the return type +// of such an expression +#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ + namespace detail { \ + using std::std_name; \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + } \ + \ + namespace detail2 { \ + struct std_name##_tag \ + { \ + }; \ + \ + template \ + std_name##_tag std_name(T&&...); \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + \ + template \ + struct would_call_std_##std_name \ + { \ + static constexpr auto const value = ::nlohmann::detail:: \ + is_detected_exact::value; \ + }; \ + } /* namespace detail2 */ \ + \ + template \ + struct would_call_std_##std_name : detail2::would_call_std_##std_name \ + { \ + } + +#ifndef JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_USE_IMPLICIT_CONVERSIONS 1 +#endif + +#if JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_EXPLICIT +#else + #define JSON_EXPLICIT explicit +#endif + +#ifndef JSON_DIAGNOSTICS + #define JSON_DIAGNOSTICS 0 +#endif + + +namespace nlohmann +{ +namespace detail +{ + +/*! +@brief replace all occurrences of a substring by another string + +@param[in,out] s the string to manipulate; changed so that all + occurrences of @a f are replaced with @a t +@param[in] f the substring to replace with @a t +@param[in] t the string to replace @a f + +@pre The search string @a f must not be empty. **This precondition is +enforced with an assertion.** + +@since version 2.0.0 +*/ +inline void replace_substring(std::string& s, const std::string& f, + const std::string& t) +{ + JSON_ASSERT(!f.empty()); + for (auto pos = s.find(f); // find first occurrence of f + pos != std::string::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find next occurrence of f + {} +} + +/*! + * @brief string escaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to escape + * @return escaped string + * + * Note the order of escaping "~" to "~0" and "/" to "~1" is important. + */ +inline std::string escape(std::string s) +{ + replace_substring(s, "~", "~0"); + replace_substring(s, "/", "~1"); + return s; +} + +/*! + * @brief string unescaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to unescape + * @return unescaped string + * + * Note the order of escaping "~1" to "/" and "~0" to "~" is important. + */ +static void unescape(std::string& s) +{ + replace_substring(s, "~1", "/"); + replace_substring(s, "~0", "~"); +} + +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // size_t + +namespace nlohmann +{ +namespace detail +{ +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +} // namespace nlohmann + +// #include + + +namespace nlohmann +{ +namespace detail +{ +//////////////// +// exceptions // +//////////////// + +/// @brief general exception of the @ref basic_json class +/// @sa https://json.nlohmann.me/api/basic_json/exception/ +class exception : public std::exception +{ + public: + /// returns the explanatory string + const char* what() const noexcept override + { + return m.what(); + } + + /// the id of the exception + const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) + + protected: + JSON_HEDLEY_NON_NULL(3) + exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing) + + static std::string name(const std::string& ename, int id_) + { + return "[json.exception." + ename + "." + std::to_string(id_) + "] "; + } + + template + static std::string diagnostics(const BasicJsonType& leaf_element) + { +#if JSON_DIAGNOSTICS + std::vector tokens; + for (const auto* current = &leaf_element; current->m_parent != nullptr; current = current->m_parent) + { + switch (current->m_parent->type()) + { + case value_t::array: + { + for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i) + { + if (¤t->m_parent->m_value.array->operator[](i) == current) + { + tokens.emplace_back(std::to_string(i)); + break; + } + } + break; + } + + case value_t::object: + { + for (const auto& element : *current->m_parent->m_value.object) + { + if (&element.second == current) + { + tokens.emplace_back(element.first.c_str()); + break; + } + } + break; + } + + case value_t::null: // LCOV_EXCL_LINE + case value_t::string: // LCOV_EXCL_LINE + case value_t::boolean: // LCOV_EXCL_LINE + case value_t::number_integer: // LCOV_EXCL_LINE + case value_t::number_unsigned: // LCOV_EXCL_LINE + case value_t::number_float: // LCOV_EXCL_LINE + case value_t::binary: // LCOV_EXCL_LINE + case value_t::discarded: // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + break; // LCOV_EXCL_LINE + } + } + + if (tokens.empty()) + { + return ""; + } + + return "(" + std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, + [](const std::string & a, const std::string & b) + { + return a + "/" + detail::escape(b); + }) + ") "; +#else + static_cast(leaf_element); + return ""; +#endif + } + + private: + /// an exception object as storage for error messages + std::runtime_error m; +}; + +/// @brief exception indicating a parse error +/// @sa https://json.nlohmann.me/api/basic_json/parse_error/ +class parse_error : public exception +{ + public: + /*! + @brief create a parse error exception + @param[in] id_ the id of the exception + @param[in] pos the position where the error occurred (or with + chars_read_total=0 if the position cannot be + determined) + @param[in] what_arg the explanatory string + @return parse_error object + */ + template + static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const BasicJsonType& context) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + position_string(pos) + ": " + exception::diagnostics(context) + what_arg; + return {id_, pos.chars_read_total, w.c_str()}; + } + + template + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const BasicJsonType& context) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + + ": " + exception::diagnostics(context) + what_arg; + return {id_, byte_, w.c_str()}; + } + + /*! + @brief byte index of the parse error + + The byte index of the last read character in the input file. + + @note For an input with n bytes, 1 is the index of the first character and + n+1 is the index of the terminating null byte or the end of file. + This also holds true when reading a byte vector (CBOR or MessagePack). + */ + const std::size_t byte; + + private: + parse_error(int id_, std::size_t byte_, const char* what_arg) + : exception(id_, what_arg), byte(byte_) {} + + static std::string position_string(const position_t& pos) + { + return " at line " + std::to_string(pos.lines_read + 1) + + ", column " + std::to_string(pos.chars_read_current_line); + } +}; + +/// @brief exception indicating errors with iterators +/// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/ +class invalid_iterator : public exception +{ + public: + template + static invalid_iterator create(int id_, const std::string& what_arg, const BasicJsonType& context) + { + std::string w = exception::name("invalid_iterator", id_) + exception::diagnostics(context) + what_arg; + return {id_, w.c_str()}; + } + + private: + JSON_HEDLEY_NON_NULL(3) + invalid_iterator(int id_, const char* what_arg) + : exception(id_, what_arg) {} +}; + +/// @brief exception indicating executing a member function with a wrong type +/// @sa https://json.nlohmann.me/api/basic_json/type_error/ +class type_error : public exception +{ + public: + template + static type_error create(int id_, const std::string& what_arg, const BasicJsonType& context) + { + std::string w = exception::name("type_error", id_) + exception::diagnostics(context) + what_arg; + return {id_, w.c_str()}; + } + + private: + JSON_HEDLEY_NON_NULL(3) + type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/// @brief exception indicating access out of the defined range +/// @sa https://json.nlohmann.me/api/basic_json/out_of_range/ +class out_of_range : public exception +{ + public: + template + static out_of_range create(int id_, const std::string& what_arg, const BasicJsonType& context) + { + std::string w = exception::name("out_of_range", id_) + exception::diagnostics(context) + what_arg; + return {id_, w.c_str()}; + } + + private: + JSON_HEDLEY_NON_NULL(3) + out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/// @brief exception indicating other library errors +/// @sa https://json.nlohmann.me/api/basic_json/other_error/ +class other_error : public exception +{ + public: + template + static other_error create(int id_, const std::string& what_arg, const BasicJsonType& context) + { + std::string w = exception::name("other_error", id_) + exception::diagnostics(context) + what_arg; + return {id_, w.c_str()}; + } + + private: + JSON_HEDLEY_NON_NULL(3) + other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for + +// #include + + +namespace nlohmann +{ +namespace detail +{ + +template +using uncvref_t = typename std::remove_cv::type>::type; + +#ifdef JSON_HAS_CPP_14 + +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; + +#else + +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h +// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. + +//// START OF CODE FROM GOOGLE ABSEIL + +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::integer_sequence` is designed +// to be a drop-in replacement for C++14's `std::integer_sequence`. +// +// Example: +// +// template< class T, T... Ints > +// void user_function(integer_sequence); +// +// int main() +// { +// // user_function's `T` will be deduced to `int` and `Ints...` +// // will be deduced to `0, 1, 2, 3, 4`. +// user_function(make_integer_sequence()); +// } +template +struct integer_sequence +{ + using value_type = T; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +// index_sequence +// +// A helper template for an `integer_sequence` of `size_t`, +// `absl::index_sequence` is designed to be a drop-in replacement for C++14's +// `std::index_sequence`. +template +using index_sequence = integer_sequence; + +namespace utility_internal +{ + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; +}; + +template +struct Extend, SeqSize, 1> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; +}; + +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen +{ + using type = + typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; +}; + +template +struct Gen +{ + using type = integer_sequence; +}; + +} // namespace utility_internal + +// Compile-time sequences of integers + +// make_integer_sequence +// +// This template alias is equivalent to +// `integer_sequence`, and is designed to be a drop-in +// replacement for C++14's `std::make_integer_sequence`. +template +using make_integer_sequence = typename utility_internal::Gen::type; + +// make_index_sequence +// +// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, +// and is designed to be a drop-in replacement for C++14's +// `std::make_index_sequence`. +template +using make_index_sequence = make_integer_sequence; + +// index_sequence_for +// +// Converts a typename pack into an index sequence of the same length, and +// is designed to be a drop-in replacement for C++14's +// `std::index_sequence_for()` +template +using index_sequence_for = make_index_sequence; + +//// END OF CODE FROM GOOGLE ABSEIL + +#endif + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static constexpr T value{}; +}; + +template +constexpr T static_const::value; // NOLINT(readability-redundant-declaration) + +} // namespace detail +} // namespace nlohmann + +// #include + + +namespace nlohmann +{ +namespace detail +{ +// dispatching helper struct +template struct identity_tag {}; +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // numeric_limits +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval +#include // tuple + +// #include + + +// #include + + +#include // random_access_iterator_tag + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template +struct iterator_types {}; + +template +struct iterator_types < + It, + void_t> +{ + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// This is required as some compilers implement std::iterator_traits in a way that +// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. +template +struct iterator_traits +{ +}; + +template +struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> +{ + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; +} // namespace detail +} // namespace nlohmann + +// #include + + +// #include + + +namespace nlohmann +{ +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); +} // namespace nlohmann + +// #include + + +// #include + + +namespace nlohmann +{ +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); +} // namespace nlohmann + +// #include + +// #include + +// #include +#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ +#define INCLUDE_NLOHMANN_JSON_FWD_HPP_ + +#include // int64_t, uint64_t +#include // map +#include // allocator +#include // string +#include // vector + +/*! +@brief namespace for Niels Lohmann +@see https://github.com/nlohmann +@since version 1.0.0 +*/ +namespace nlohmann +{ +/*! +@brief default JSONSerializer template argument + +This serializer ignores the template arguments and uses ADL +([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) +for serialization. +*/ +template +struct adl_serializer; + +/// a class to store JSON values +/// @sa https://json.nlohmann.me/api/basic_json/ +template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector> +class basic_json; + +/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document +/// @sa https://json.nlohmann.me/api/json_pointer/ +template +class json_pointer; + +/*! +@brief default specialization +@sa https://json.nlohmann.me/api/json/ +*/ +using json = basic_json<>; + +/// @brief a minimal map-like container that preserves insertion order +/// @sa https://json.nlohmann.me/api/ordered_map/ +template +struct ordered_map; + +/// @brief specialization that maintains the insertion order of object keys +/// @sa https://json.nlohmann.me/api/ordered_json/ +using ordered_json = basic_json; + +} // namespace nlohmann + +#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + +namespace nlohmann +{ +/*! +@brief detail namespace with internal helper functions + +This namespace collects functions that should not be exposed, +implementations of some @ref basic_json methods, and meta-programming helpers. + +@since version 2.1.0 +*/ +namespace detail +{ +///////////// +// helpers // +///////////// + +// Note to maintainers: +// +// Every trait in this file expects a non CV-qualified type. +// The only exceptions are in the 'aliases for detected' section +// (i.e. those of the form: decltype(T::member_function(std::declval()))) +// +// In this case, T has to be properly CV-qualified to constraint the function arguments +// (e.g. to_json(BasicJsonType&, const T&)) + +template struct is_basic_json : std::false_type {}; + +NLOHMANN_BASIC_JSON_TPL_DECLARATION +struct is_basic_json : std::true_type {}; + +////////////////////// +// json_ref helpers // +////////////////////// + +template +class json_ref; + +template +struct is_json_ref : std::false_type {}; + +template +struct is_json_ref> : std::true_type {}; + +////////////////////////// +// aliases for detected // +////////////////////////// + +template +using mapped_type_t = typename T::mapped_type; + +template +using key_type_t = typename T::key_type; + +template +using value_type_t = typename T::value_type; + +template +using difference_type_t = typename T::difference_type; + +template +using pointer_t = typename T::pointer; + +template +using reference_t = typename T::reference; + +template +using iterator_category_t = typename T::iterator_category; + +template +using to_json_function = decltype(T::to_json(std::declval()...)); + +template +using from_json_function = decltype(T::from_json(std::declval()...)); + +template +using get_template_function = decltype(std::declval().template get()); + +// trait checking if JSONSerializer::from_json(json const&, udt&) exists +template +struct has_from_json : std::false_type {}; + +// trait checking if j.get is valid +// use this trait instead of std::is_constructible or std::is_convertible, +// both rely on, or make use of implicit conversions, and thus fail when T +// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) +template +struct is_getable +{ + static constexpr bool value = is_detected::value; +}; + +template +struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if JSONSerializer::from_json(json const&) exists +// this overload is used for non-default-constructible user-defined-types +template +struct has_non_default_from_json : std::false_type {}; + +template +struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if BasicJsonType::json_serializer::to_json exists +// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. +template +struct has_to_json : std::false_type {}; + +template +struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + + +/////////////////// +// is_ functions // +/////////////////// + +// https://en.cppreference.com/w/cpp/types/conjunction +template struct conjunction : std::true_type { }; +template struct conjunction : B1 { }; +template +struct conjunction +: std::conditional, B1>::type {}; + +// https://en.cppreference.com/w/cpp/types/negation +template struct negation : std::integral_constant < bool, !B::value > { }; + +// Reimplementation of is_constructible and is_default_constructible, due to them being broken for +// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). +// This causes compile errors in e.g. clang 3.5 or gcc 4.9. +template +struct is_default_constructible : std::is_default_constructible {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + + +template +struct is_constructible : std::is_constructible {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + + +template +struct is_iterator_traits : std::false_type {}; + +template +struct is_iterator_traits> +{ + private: + using traits = iterator_traits; + + public: + static constexpr auto value = + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value; +}; + +template +struct is_range +{ + private: + using t_ref = typename std::add_lvalue_reference::type; + + using iterator = detected_t; + using sentinel = detected_t; + + // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator + // and https://en.cppreference.com/w/cpp/iterator/sentinel_for + // but reimplementing these would be too much work, as a lot of other concepts are used underneath + static constexpr auto is_iterator_begin = + is_iterator_traits>::value; + + public: + static constexpr bool value = !std::is_same::value && !std::is_same::value && is_iterator_begin; +}; + +template +using iterator_t = enable_if_t::value, result_of_begin())>>; + +template +using range_value_t = value_type_t>>; + +// The following implementation of is_complete_type is taken from +// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ +// and is written by Xiang Fan who agreed to using it in this library. + +template +struct is_complete_type : std::false_type {}; + +template +struct is_complete_type : std::true_type {}; + +template +struct is_compatible_object_type_impl : std::false_type {}; + +template +struct is_compatible_object_type_impl < + BasicJsonType, CompatibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + // macOS's is_constructible does not play well with nonesuch... + static constexpr bool value = + is_constructible::value && + is_constructible::value; +}; + +template +struct is_compatible_object_type + : is_compatible_object_type_impl {}; + +template +struct is_constructible_object_type_impl : std::false_type {}; + +template +struct is_constructible_object_type_impl < + BasicJsonType, ConstructibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + static constexpr bool value = + (is_default_constructible::value && + (std::is_move_assignable::value || + std::is_copy_assignable::value) && + (is_constructible::value && + std::is_same < + typename object_t::mapped_type, + typename ConstructibleObjectType::mapped_type >::value)) || + (has_from_json::value || + has_non_default_from_json < + BasicJsonType, + typename ConstructibleObjectType::mapped_type >::value); +}; + +template +struct is_constructible_object_type + : is_constructible_object_type_impl {}; + +template +struct is_compatible_string_type +{ + static constexpr auto value = + is_constructible::value; +}; + +template +struct is_constructible_string_type +{ + static constexpr auto value = + is_constructible::value; +}; + +template +struct is_compatible_array_type_impl : std::false_type {}; + +template +struct is_compatible_array_type_impl < + BasicJsonType, CompatibleArrayType, + enable_if_t < + is_detected::value&& + is_iterator_traits>>::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 + !std::is_same>::value >> +{ + static constexpr bool value = + is_constructible>::value; +}; + +template +struct is_compatible_array_type + : is_compatible_array_type_impl {}; + +template +struct is_constructible_array_type_impl : std::false_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t::value >> + : std::true_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t < !std::is_same::value&& + !is_compatible_string_type::value&& + is_default_constructible::value&& +(std::is_move_assignable::value || + std::is_copy_assignable::value)&& +is_detected::value&& +is_iterator_traits>>::value&& +is_detected::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 +!std::is_same>::value&& + is_complete_type < + detected_t>::value >> +{ + using value_type = range_value_t; + + static constexpr bool value = + std::is_same::value || + has_from_json::value || + has_non_default_from_json < + BasicJsonType, + value_type >::value; +}; + +template +struct is_constructible_array_type + : is_constructible_array_type_impl {}; + +template +struct is_compatible_integer_type_impl : std::false_type {}; + +template +struct is_compatible_integer_type_impl < + RealIntegerType, CompatibleNumberIntegerType, + enable_if_t < std::is_integral::value&& + std::is_integral::value&& + !std::is_same::value >> +{ + // is there an assert somewhere on overflows? + using RealLimits = std::numeric_limits; + using CompatibleLimits = std::numeric_limits; + + static constexpr auto value = + is_constructible::value && + CompatibleLimits::is_integer && + RealLimits::is_signed == CompatibleLimits::is_signed; +}; + +template +struct is_compatible_integer_type + : is_compatible_integer_type_impl {}; + +template +struct is_compatible_type_impl: std::false_type {}; + +template +struct is_compatible_type_impl < + BasicJsonType, CompatibleType, + enable_if_t::value >> +{ + static constexpr bool value = + has_to_json::value; +}; + +template +struct is_compatible_type + : is_compatible_type_impl {}; + +template +struct is_constructible_tuple : std::false_type {}; + +template +struct is_constructible_tuple> : conjunction...> {}; + +// a naive helper to check if a type is an ordered_map (exploits the fact that +// ordered_map inherits capacity() from std::vector) +template +struct is_ordered_map +{ + using one = char; + + struct two + { + char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + }; + + template static one test( decltype(&C::capacity) ) ; + template static two test(...); + + enum { value = sizeof(test(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) +}; + +// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324) +template < typename T, typename U, enable_if_t < !std::is_same::value, int > = 0 > +T conditional_static_cast(U value) +{ + return static_cast(value); +} + +template::value, int> = 0> +T conditional_static_cast(U value) +{ + return value; +} + +} // namespace detail +} // namespace nlohmann + +// #include + + +#if JSON_HAS_EXPERIMENTAL_FILESYSTEM +#include +namespace nlohmann::detail +{ +namespace std_fs = std::experimental::filesystem; +} // namespace nlohmann::detail +#elif JSON_HAS_FILESYSTEM +#include +namespace nlohmann::detail +{ +namespace std_fs = std::filesystem; +} // namespace nlohmann::detail +#endif + +namespace nlohmann +{ +namespace detail +{ +template +void from_json(const BasicJsonType& j, typename std::nullptr_t& n) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_null())) + { + JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), j)); + } + n = nullptr; +} + +// overloads for basic_json template parameters +template < typename BasicJsonType, typename ArithmeticType, + enable_if_t < std::is_arithmetic::value&& + !std::is_same::value, + int > = 0 > +void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) +{ + switch (static_cast(j)) + { + case value_t::number_unsigned: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_integer: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_float: + { + val = static_cast(*j.template get_ptr()); + break; + } + + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::string: + case value_t::boolean: + case value_t::binary: + case value_t::discarded: + default: + JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j)); + } +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) + { + JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), j)); + } + b = *j.template get_ptr(); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_string())) + { + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); + } + s = *j.template get_ptr(); +} + +template < + typename BasicJsonType, typename ConstructibleStringType, + enable_if_t < + is_constructible_string_type::value&& + !std::is_same::value, + int > = 0 > +void from_json(const BasicJsonType& j, ConstructibleStringType& s) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_string())) + { + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); + } + + s = *j.template get_ptr(); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) +{ + get_arithmetic_value(j, val); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) +{ + get_arithmetic_value(j, val); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) +{ + get_arithmetic_value(j, val); +} + +template::value, int> = 0> +void from_json(const BasicJsonType& j, EnumType& e) +{ + typename std::underlying_type::type val; + get_arithmetic_value(j, val); + e = static_cast(val); +} + +// forward_list doesn't have an insert method +template::value, int> = 0> +void from_json(const BasicJsonType& j, std::forward_list& l) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + l.clear(); + std::transform(j.rbegin(), j.rend(), + std::front_inserter(l), [](const BasicJsonType & i) + { + return i.template get(); + }); +} + +// valarray doesn't have an insert method +template::value, int> = 0> +void from_json(const BasicJsonType& j, std::valarray& l) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + l.resize(j.size()); + std::transform(j.begin(), j.end(), std::begin(l), + [](const BasicJsonType & elem) + { + return elem.template get(); + }); +} + +template +auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +-> decltype(j.template get(), void()) +{ + for (std::size_t i = 0; i < N; ++i) + { + arr[i] = j.at(i).template get(); + } +} + +template +void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) +{ + arr = *j.template get_ptr(); +} + +template +auto from_json_array_impl(const BasicJsonType& j, std::array& arr, + priority_tag<2> /*unused*/) +-> decltype(j.template get(), void()) +{ + for (std::size_t i = 0; i < N; ++i) + { + arr[i] = j.at(i).template get(); + } +} + +template::value, + int> = 0> +auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/) +-> decltype( + arr.reserve(std::declval()), + j.template get(), + void()) +{ + using std::end; + + ConstructibleArrayType ret; + ret.reserve(j.size()); + std::transform(j.begin(), j.end(), + std::inserter(ret, end(ret)), [](const BasicJsonType & i) + { + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); + arr = std::move(ret); +} + +template::value, + int> = 0> +void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, + priority_tag<0> /*unused*/) +{ + using std::end; + + ConstructibleArrayType ret; + std::transform( + j.begin(), j.end(), std::inserter(ret, end(ret)), + [](const BasicJsonType & i) + { + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); + arr = std::move(ret); +} + +template < typename BasicJsonType, typename ConstructibleArrayType, + enable_if_t < + is_constructible_array_type::value&& + !is_constructible_object_type::value&& + !is_constructible_string_type::value&& + !std::is_same::value&& + !is_basic_json::value, + int > = 0 > +auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr) +-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), +j.template get(), +void()) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + + from_json_array_impl(j, arr, priority_tag<3> {}); +} + +template < typename BasicJsonType, typename T, std::size_t... Idx > +std::array from_json_inplace_array_impl(BasicJsonType&& j, + identity_tag> /*unused*/, index_sequence /*unused*/) +{ + return { { std::forward(j).at(Idx).template get()... } }; +} + +template < typename BasicJsonType, typename T, std::size_t N > +auto from_json(BasicJsonType&& j, identity_tag> tag) +-> decltype(from_json_inplace_array_impl(std::forward(j), tag, make_index_sequence {})) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + + return from_json_inplace_array_impl(std::forward(j), tag, make_index_sequence {}); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) + { + JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), j)); + } + + bin = *j.template get_ptr(); +} + +template::value, int> = 0> +void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_object())) + { + JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), j)); + } + + ConstructibleObjectType ret; + const auto* inner_object = j.template get_ptr(); + using value_type = typename ConstructibleObjectType::value_type; + std::transform( + inner_object->begin(), inner_object->end(), + std::inserter(ret, ret.begin()), + [](typename BasicJsonType::object_t::value_type const & p) + { + return value_type(p.first, p.second.template get()); + }); + obj = std::move(ret); +} + +// overload for arithmetic types, not chosen for basic_json template arguments +// (BooleanType, etc..); note: Is it really necessary to provide explicit +// overloads for boolean_t etc. in case of a custom BooleanType which is not +// an arithmetic type? +template < typename BasicJsonType, typename ArithmeticType, + enable_if_t < + std::is_arithmetic::value&& + !std::is_same::value&& + !std::is_same::value&& + !std::is_same::value&& + !std::is_same::value, + int > = 0 > +void from_json(const BasicJsonType& j, ArithmeticType& val) +{ + switch (static_cast(j)) + { + case value_t::number_unsigned: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_integer: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_float: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::boolean: + { + val = static_cast(*j.template get_ptr()); + break; + } + + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::string: + case value_t::binary: + case value_t::discarded: + default: + JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j)); + } +} + +template +std::tuple from_json_tuple_impl_base(BasicJsonType&& j, index_sequence /*unused*/) +{ + return std::make_tuple(std::forward(j).at(Idx).template get()...); +} + +template < typename BasicJsonType, class A1, class A2 > +std::pair from_json_tuple_impl(BasicJsonType&& j, identity_tag> /*unused*/, priority_tag<0> /*unused*/) +{ + return {std::forward(j).at(0).template get(), + std::forward(j).at(1).template get()}; +} + +template +void from_json_tuple_impl(BasicJsonType&& j, std::pair& p, priority_tag<1> /*unused*/) +{ + p = from_json_tuple_impl(std::forward(j), identity_tag> {}, priority_tag<0> {}); +} + +template +std::tuple from_json_tuple_impl(BasicJsonType&& j, identity_tag> /*unused*/, priority_tag<2> /*unused*/) +{ + return from_json_tuple_impl_base(std::forward(j), index_sequence_for {}); +} + +template +void from_json_tuple_impl(BasicJsonType&& j, std::tuple& t, priority_tag<3> /*unused*/) +{ + t = from_json_tuple_impl_base(std::forward(j), index_sequence_for {}); +} + +template +auto from_json(BasicJsonType&& j, TupleRelated&& t) +-> decltype(from_json_tuple_impl(std::forward(j), std::forward(t), priority_tag<3> {})) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + + return from_json_tuple_impl(std::forward(j), std::forward(t), priority_tag<3> {}); +} + +template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, + typename = enable_if_t < !std::is_constructible < + typename BasicJsonType::string_t, Key >::value >> +void from_json(const BasicJsonType& j, std::map& m) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + m.clear(); + for (const auto& p : j) + { + if (JSON_HEDLEY_UNLIKELY(!p.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j)); + } + m.emplace(p.at(0).template get(), p.at(1).template get()); + } +} + +template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator, + typename = enable_if_t < !std::is_constructible < + typename BasicJsonType::string_t, Key >::value >> +void from_json(const BasicJsonType& j, std::unordered_map& m) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + m.clear(); + for (const auto& p : j) + { + if (JSON_HEDLEY_UNLIKELY(!p.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j)); + } + m.emplace(p.at(0).template get(), p.at(1).template get()); + } +} + +#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM +template +void from_json(const BasicJsonType& j, std_fs::path& p) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_string())) + { + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); + } + p = *j.template get_ptr(); +} +#endif + +struct from_json_fn +{ + template + auto operator()(const BasicJsonType& j, T&& val) const + noexcept(noexcept(from_json(j, std::forward(val)))) + -> decltype(from_json(j, std::forward(val))) + { + return from_json(j, std::forward(val)); + } +}; +} // namespace detail + +/// namespace to hold default `from_json` function +/// to see why this is required: +/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html +namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) +{ +constexpr const auto& from_json = detail::static_const::value; // NOLINT(misc-definitions-in-headers) +} // namespace +} // namespace nlohmann + +// #include + + +#include // copy +#include // begin, end +#include // string +#include // tuple, get +#include // is_same, is_constructible, is_floating_point, is_enum, underlying_type +#include // move, forward, declval, pair +#include // valarray +#include // vector + +// #include + +// #include + + +#include // size_t +#include // input_iterator_tag +#include // string, to_string +#include // tuple_size, get, tuple_element +#include // move + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template +void int_to_string( string_type& target, std::size_t value ) +{ + // For ADL + using std::to_string; + target = to_string(value); +} +template class iteration_proxy_value +{ + public: + using difference_type = std::ptrdiff_t; + using value_type = iteration_proxy_value; + using pointer = value_type * ; + using reference = value_type & ; + using iterator_category = std::input_iterator_tag; + using string_type = typename std::remove_cv< typename std::remove_reference().key() ) >::type >::type; + + private: + /// the iterator + IteratorType anchor; + /// an index for arrays (used to create key names) + std::size_t array_index = 0; + /// last stringified array index + mutable std::size_t array_index_last = 0; + /// a string representation of the array index + mutable string_type array_index_str = "0"; + /// an empty string (to return a reference for primitive values) + const string_type empty_str{}; + + public: + explicit iteration_proxy_value(IteratorType it) noexcept + : anchor(std::move(it)) + {} + + /// dereference operator (needed for range-based for) + iteration_proxy_value& operator*() + { + return *this; + } + + /// increment operator (needed for range-based for) + iteration_proxy_value& operator++() + { + ++anchor; + ++array_index; + + return *this; + } + + /// equality operator (needed for InputIterator) + bool operator==(const iteration_proxy_value& o) const + { + return anchor == o.anchor; + } + + /// inequality operator (needed for range-based for) + bool operator!=(const iteration_proxy_value& o) const + { + return anchor != o.anchor; + } + + /// return key of the iterator + const string_type& key() const + { + JSON_ASSERT(anchor.m_object != nullptr); + + switch (anchor.m_object->type()) + { + // use integer array index as key + case value_t::array: + { + if (array_index != array_index_last) + { + int_to_string( array_index_str, array_index ); + array_index_last = array_index; + } + return array_index_str; + } + + // use key from the object + case value_t::object: + return anchor.key(); + + // use an empty key for all primitive types + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return empty_str; + } + } + + /// return value of the iterator + typename IteratorType::reference value() const + { + return anchor.value(); + } +}; + +/// proxy class for the items() function +template class iteration_proxy +{ + private: + /// the container to iterate + typename IteratorType::reference container; + + public: + /// construct iteration proxy from a container + explicit iteration_proxy(typename IteratorType::reference cont) noexcept + : container(cont) {} + + /// return iterator begin (needed for range-based for) + iteration_proxy_value begin() noexcept + { + return iteration_proxy_value(container.begin()); + } + + /// return iterator end (needed for range-based for) + iteration_proxy_value end() noexcept + { + return iteration_proxy_value(container.end()); + } +}; +// Structured Bindings Support +// For further reference see https://blog.tartanllama.xyz/structured-bindings/ +// And see https://github.com/nlohmann/json/pull/1391 +template = 0> +auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.key()) +{ + return i.key(); +} +// Structured Bindings Support +// For further reference see https://blog.tartanllama.xyz/structured-bindings/ +// And see https://github.com/nlohmann/json/pull/1391 +template = 0> +auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.value()) +{ + return i.value(); +} +} // namespace detail +} // namespace nlohmann + +// The Addition to the STD Namespace is required to add +// Structured Bindings Support to the iteration_proxy_value class +// For further reference see https://blog.tartanllama.xyz/structured-bindings/ +// And see https://github.com/nlohmann/json/pull/1391 +namespace std +{ +#if defined(__clang__) + // Fix: https://github.com/nlohmann/json/issues/1401 + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wmismatched-tags" +#endif +template +class tuple_size<::nlohmann::detail::iteration_proxy_value> + : public std::integral_constant {}; + +template +class tuple_element> +{ + public: + using type = decltype( + get(std::declval < + ::nlohmann::detail::iteration_proxy_value> ())); +}; +#if defined(__clang__) + #pragma clang diagnostic pop +#endif +} // namespace std + +// #include + +// #include + +// #include + + +#if JSON_HAS_EXPERIMENTAL_FILESYSTEM +#include +namespace nlohmann::detail +{ +namespace std_fs = std::experimental::filesystem; +} // namespace nlohmann::detail +#elif JSON_HAS_FILESYSTEM +#include +namespace nlohmann::detail +{ +namespace std_fs = std::filesystem; +} // namespace nlohmann::detail +#endif + +namespace nlohmann +{ +namespace detail +{ +////////////////// +// constructors // +////////////////// + +/* + * Note all external_constructor<>::construct functions need to call + * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an + * allocated value (e.g., a string). See bug issue + * https://github.com/nlohmann/json/issues/2865 for more information. + */ + +template struct external_constructor; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::boolean; + j.m_value = b; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::string; + j.m_value = s; + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::string; + j.m_value = std::move(s); + j.assert_invariant(); + } + + template < typename BasicJsonType, typename CompatibleStringType, + enable_if_t < !std::is_same::value, + int > = 0 > + static void construct(BasicJsonType& j, const CompatibleStringType& str) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::string; + j.m_value.string = j.template create(str); + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::binary; + j.m_value = typename BasicJsonType::binary_t(b); + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::binary; + j.m_value = typename BasicJsonType::binary_t(std::move(b)); + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::number_float; + j.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::number_unsigned; + j.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::number_integer; + j.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = arr; + j.set_parents(); + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = std::move(arr); + j.set_parents(); + j.assert_invariant(); + } + + template < typename BasicJsonType, typename CompatibleArrayType, + enable_if_t < !std::is_same::value, + int > = 0 > + static void construct(BasicJsonType& j, const CompatibleArrayType& arr) + { + using std::begin; + using std::end; + + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value.array = j.template create(begin(arr), end(arr)); + j.set_parents(); + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, const std::vector& arr) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = value_t::array; + j.m_value.array->reserve(arr.size()); + for (const bool x : arr) + { + j.m_value.array->push_back(x); + j.set_parent(j.m_value.array->back()); + } + j.assert_invariant(); + } + + template::value, int> = 0> + static void construct(BasicJsonType& j, const std::valarray& arr) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = value_t::array; + j.m_value.array->resize(arr.size()); + if (arr.size() > 0) + { + std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); + } + j.set_parents(); + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::object; + j.m_value = obj; + j.set_parents(); + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::object; + j.m_value = std::move(obj); + j.set_parents(); + j.assert_invariant(); + } + + template < typename BasicJsonType, typename CompatibleObjectType, + enable_if_t < !std::is_same::value, int > = 0 > + static void construct(BasicJsonType& j, const CompatibleObjectType& obj) + { + using std::begin; + using std::end; + + j.m_value.destroy(j.m_type); + j.m_type = value_t::object; + j.m_value.object = j.template create(begin(obj), end(obj)); + j.set_parents(); + j.assert_invariant(); + } +}; + +///////////// +// to_json // +///////////// + +template::value, int> = 0> +void to_json(BasicJsonType& j, T b) noexcept +{ + external_constructor::construct(j, b); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, const CompatibleString& s) +{ + external_constructor::construct(j, s); +} + +template +void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) +{ + external_constructor::construct(j, std::move(s)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, FloatType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, EnumType e) noexcept +{ + using underlying_type = typename std::underlying_type::type; + external_constructor::construct(j, static_cast(e)); +} + +template +void to_json(BasicJsonType& j, const std::vector& e) +{ + external_constructor::construct(j, e); +} + +template < typename BasicJsonType, typename CompatibleArrayType, + enable_if_t < is_compatible_array_type::value&& + !is_compatible_object_type::value&& + !is_compatible_string_type::value&& + !std::is_same::value&& + !is_basic_json::value, + int > = 0 > +void to_json(BasicJsonType& j, const CompatibleArrayType& arr) +{ + external_constructor::construct(j, arr); +} + +template +void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) +{ + external_constructor::construct(j, bin); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, const std::valarray& arr) +{ + external_constructor::construct(j, std::move(arr)); +} + +template +void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) +{ + external_constructor::construct(j, std::move(arr)); +} + +template < typename BasicJsonType, typename CompatibleObjectType, + enable_if_t < is_compatible_object_type::value&& !is_basic_json::value, int > = 0 > +void to_json(BasicJsonType& j, const CompatibleObjectType& obj) +{ + external_constructor::construct(j, obj); +} + +template +void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) +{ + external_constructor::construct(j, std::move(obj)); +} + +template < + typename BasicJsonType, typename T, std::size_t N, + enable_if_t < !std::is_constructible::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + int > = 0 > +void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +{ + external_constructor::construct(j, arr); +} + +template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible::value&& std::is_constructible::value, int > = 0 > +void to_json(BasicJsonType& j, const std::pair& p) +{ + j = { p.first, p.second }; +} + +// for https://github.com/nlohmann/json/pull/1134 +template>::value, int> = 0> +void to_json(BasicJsonType& j, const T& b) +{ + j = { {b.key(), b.value()} }; +} + +template +void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence /*unused*/) +{ + j = { std::get(t)... }; +} + +template::value, int > = 0> +void to_json(BasicJsonType& j, const T& t) +{ + to_json_tuple_impl(j, t, make_index_sequence::value> {}); +} + +#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM +template +void to_json(BasicJsonType& j, const std_fs::path& p) +{ + j = p.string(); +} +#endif + +struct to_json_fn +{ + template + auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward(val)))) + -> decltype(to_json(j, std::forward(val)), void()) + { + return to_json(j, std::forward(val)); + } +}; +} // namespace detail + +/// namespace to hold default `to_json` function +/// to see why this is required: +/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html +namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) +{ +constexpr const auto& to_json = detail::static_const::value; // NOLINT(misc-definitions-in-headers) +} // namespace +} // namespace nlohmann + +// #include + +// #include + + +namespace nlohmann +{ + +/// @sa https://json.nlohmann.me/api/adl_serializer/ +template +struct adl_serializer +{ + /// @brief convert a JSON value to any value type + /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/ + template + static auto from_json(BasicJsonType && j, TargetType& val) noexcept( + noexcept(::nlohmann::from_json(std::forward(j), val))) + -> decltype(::nlohmann::from_json(std::forward(j), val), void()) + { + ::nlohmann::from_json(std::forward(j), val); + } + + /// @brief convert a JSON value to any value type + /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/ + template + static auto from_json(BasicJsonType && j) noexcept( + noexcept(::nlohmann::from_json(std::forward(j), detail::identity_tag {}))) + -> decltype(::nlohmann::from_json(std::forward(j), detail::identity_tag {})) + { + return ::nlohmann::from_json(std::forward(j), detail::identity_tag {}); + } + + /// @brief convert any value type to a JSON value + /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/ + template + static auto to_json(BasicJsonType& j, TargetType && val) noexcept( + noexcept(::nlohmann::to_json(j, std::forward(val)))) + -> decltype(::nlohmann::to_json(j, std::forward(val)), void()) + { + ::nlohmann::to_json(j, std::forward(val)); + } +}; +} // namespace nlohmann + +// #include + + +#include // uint8_t, uint64_t +#include // tie +#include // move + +namespace nlohmann +{ + +/// @brief an internal type for a backed binary type +/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/ +template +class byte_container_with_subtype : public BinaryType +{ + public: + using container_type = BinaryType; + using subtype_type = std::uint64_t; + + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ + byte_container_with_subtype() noexcept(noexcept(container_type())) + : container_type() + {} + + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ + byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b))) + : container_type(b) + {} + + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ + byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b)))) + : container_type(std::move(b)) + {} + + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ + byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b))) + : container_type(b) + , m_subtype(subtype_) + , m_has_subtype(true) + {} + + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ + byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b)))) + : container_type(std::move(b)) + , m_subtype(subtype_) + , m_has_subtype(true) + {} + + bool operator==(const byte_container_with_subtype& rhs) const + { + return std::tie(static_cast(*this), m_subtype, m_has_subtype) == + std::tie(static_cast(rhs), rhs.m_subtype, rhs.m_has_subtype); + } + + bool operator!=(const byte_container_with_subtype& rhs) const + { + return !(rhs == *this); + } + + /// @brief sets the binary subtype + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/ + void set_subtype(subtype_type subtype_) noexcept + { + m_subtype = subtype_; + m_has_subtype = true; + } + + /// @brief return the binary subtype + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/ + constexpr subtype_type subtype() const noexcept + { + return m_has_subtype ? m_subtype : static_cast(-1); + } + + /// @brief return whether the value has a subtype + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/ + constexpr bool has_subtype() const noexcept + { + return m_has_subtype; + } + + /// @brief clears the binary subtype + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/ + void clear_subtype() noexcept + { + m_subtype = 0; + m_has_subtype = false; + } + + private: + subtype_type m_subtype = 0; + bool m_has_subtype = false; +}; + +} // namespace nlohmann + +// #include + +// #include + +// #include + +// #include + + +#include // uint8_t +#include // size_t +#include // hash + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ + +// boost::hash_combine +inline std::size_t combine(std::size_t seed, std::size_t h) noexcept +{ + seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U); + return seed; +} + +/*! +@brief hash a JSON value + +The hash function tries to rely on std::hash where possible. Furthermore, the +type of the JSON value is taken into account to have different hash values for +null, 0, 0U, and false, etc. + +@tparam BasicJsonType basic_json specialization +@param j JSON value to hash +@return hash value of j +*/ +template +std::size_t hash(const BasicJsonType& j) +{ + using string_t = typename BasicJsonType::string_t; + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + + const auto type = static_cast(j.type()); + switch (j.type()) + { + case BasicJsonType::value_t::null: + case BasicJsonType::value_t::discarded: + { + return combine(type, 0); + } + + case BasicJsonType::value_t::object: + { + auto seed = combine(type, j.size()); + for (const auto& element : j.items()) + { + const auto h = std::hash {}(element.key()); + seed = combine(seed, h); + seed = combine(seed, hash(element.value())); + } + return seed; + } + + case BasicJsonType::value_t::array: + { + auto seed = combine(type, j.size()); + for (const auto& element : j) + { + seed = combine(seed, hash(element)); + } + return seed; + } + + case BasicJsonType::value_t::string: + { + const auto h = std::hash {}(j.template get_ref()); + return combine(type, h); + } + + case BasicJsonType::value_t::boolean: + { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } + + case BasicJsonType::value_t::number_integer: + { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } + + case BasicJsonType::value_t::number_unsigned: + { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } + + case BasicJsonType::value_t::number_float: + { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } + + case BasicJsonType::value_t::binary: + { + auto seed = combine(type, j.get_binary().size()); + const auto h = std::hash {}(j.get_binary().has_subtype()); + seed = combine(seed, h); + seed = combine(seed, static_cast(j.get_binary().subtype())); + for (const auto byte : j.get_binary()) + { + seed = combine(seed, std::hash {}(byte)); + } + return seed; + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + return 0; // LCOV_EXCL_LINE + } +} + +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // generate_n +#include // array +#include // ldexp +#include // size_t +#include // uint8_t, uint16_t, uint32_t, uint64_t +#include // snprintf +#include // memcpy +#include // back_inserter +#include // numeric_limits +#include // char_traits, string +#include // make_pair, move +#include // vector + +// #include + +// #include + + +#include // array +#include // size_t +#include // strlen +#include // begin, end, iterator_traits, random_access_iterator_tag, distance, next +#include // shared_ptr, make_shared, addressof +#include // accumulate +#include // string, char_traits +#include // enable_if, is_base_of, is_pointer, is_integral, remove_pointer +#include // pair, declval + +#ifndef JSON_NO_IO + #include // FILE * + #include // istream +#endif // JSON_NO_IO + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +/// the supported input formats +enum class input_format_t { json, cbor, msgpack, ubjson, bson }; + +//////////////////// +// input adapters // +//////////////////// + +#ifndef JSON_NO_IO +/*! +Input adapter for stdio file access. This adapter read only 1 byte and do not use any + buffer. This adapter is a very low level adapter. +*/ +class file_input_adapter +{ + public: + using char_type = char; + + JSON_HEDLEY_NON_NULL(2) + explicit file_input_adapter(std::FILE* f) noexcept + : m_file(f) + {} + + // make class move-only + file_input_adapter(const file_input_adapter&) = delete; + file_input_adapter(file_input_adapter&&) noexcept = default; + file_input_adapter& operator=(const file_input_adapter&) = delete; + file_input_adapter& operator=(file_input_adapter&&) = delete; + ~file_input_adapter() = default; + + std::char_traits::int_type get_character() noexcept + { + return std::fgetc(m_file); + } + + private: + /// the file pointer to read from + std::FILE* m_file; +}; + + +/*! +Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at +beginning of input. Does not support changing the underlying std::streambuf +in mid-input. Maintains underlying std::istream and std::streambuf to support +subsequent use of standard std::istream operations to process any input +characters following those used in parsing the JSON input. Clears the +std::istream flags; any input errors (e.g., EOF) will be detected by the first +subsequent call for input from the std::istream. +*/ +class input_stream_adapter +{ + public: + using char_type = char; + + ~input_stream_adapter() + { + // clear stream flags; we use underlying streambuf I/O, do not + // maintain ifstream flags, except eof + if (is != nullptr) + { + is->clear(is->rdstate() & std::ios::eofbit); + } + } + + explicit input_stream_adapter(std::istream& i) + : is(&i), sb(i.rdbuf()) + {} + + // delete because of pointer members + input_stream_adapter(const input_stream_adapter&) = delete; + input_stream_adapter& operator=(input_stream_adapter&) = delete; + input_stream_adapter& operator=(input_stream_adapter&&) = delete; + + input_stream_adapter(input_stream_adapter&& rhs) noexcept + : is(rhs.is), sb(rhs.sb) + { + rhs.is = nullptr; + rhs.sb = nullptr; + } + + // std::istream/std::streambuf use std::char_traits::to_int_type, to + // ensure that std::char_traits::eof() and the character 0xFF do not + // end up as the same value, e.g. 0xFFFFFFFF. + std::char_traits::int_type get_character() + { + auto res = sb->sbumpc(); + // set eof manually, as we don't use the istream interface. + if (JSON_HEDLEY_UNLIKELY(res == std::char_traits::eof())) + { + is->clear(is->rdstate() | std::ios::eofbit); + } + return res; + } + + private: + /// the associated input stream + std::istream* is = nullptr; + std::streambuf* sb = nullptr; +}; +#endif // JSON_NO_IO + +// General-purpose iterator-based adapter. It might not be as fast as +// theoretically possible for some containers, but it is extremely versatile. +template +class iterator_input_adapter +{ + public: + using char_type = typename std::iterator_traits::value_type; + + iterator_input_adapter(IteratorType first, IteratorType last) + : current(std::move(first)), end(std::move(last)) + {} + + typename std::char_traits::int_type get_character() + { + if (JSON_HEDLEY_LIKELY(current != end)) + { + auto result = std::char_traits::to_int_type(*current); + std::advance(current, 1); + return result; + } + + return std::char_traits::eof(); + } + + private: + IteratorType current; + IteratorType end; + + template + friend struct wide_string_input_helper; + + bool empty() const + { + return current == end; + } +}; + + +template +struct wide_string_input_helper; + +template +struct wide_string_input_helper +{ + // UTF-32 + static void fill_buffer(BaseInputAdapter& input, + std::array::int_type, 4>& utf8_bytes, + size_t& utf8_bytes_index, + size_t& utf8_bytes_filled) + { + utf8_bytes_index = 0; + + if (JSON_HEDLEY_UNLIKELY(input.empty())) + { + utf8_bytes[0] = std::char_traits::eof(); + utf8_bytes_filled = 1; + } + else + { + // get the current character + const auto wc = input.get_character(); + + // UTF-32 to UTF-8 encoding + if (wc < 0x80) + { + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + else if (wc <= 0x7FF) + { + utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u) & 0x1Fu)); + utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 2; + } + else if (wc <= 0xFFFF) + { + utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u) & 0x0Fu)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 3; + } + else if (wc <= 0x10FFFF) + { + utf8_bytes[0] = static_cast::int_type>(0xF0u | ((static_cast(wc) >> 18u) & 0x07u)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 12u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); + utf8_bytes[3] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 4; + } + else + { + // unknown character + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + } + } +}; + +template +struct wide_string_input_helper +{ + // UTF-16 + static void fill_buffer(BaseInputAdapter& input, + std::array::int_type, 4>& utf8_bytes, + size_t& utf8_bytes_index, + size_t& utf8_bytes_filled) + { + utf8_bytes_index = 0; + + if (JSON_HEDLEY_UNLIKELY(input.empty())) + { + utf8_bytes[0] = std::char_traits::eof(); + utf8_bytes_filled = 1; + } + else + { + // get the current character + const auto wc = input.get_character(); + + // UTF-16 to UTF-8 encoding + if (wc < 0x80) + { + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + else if (wc <= 0x7FF) + { + utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u))); + utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 2; + } + else if (0xD800 > wc || wc >= 0xE000) + { + utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u))); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 3; + } + else + { + if (JSON_HEDLEY_UNLIKELY(!input.empty())) + { + const auto wc2 = static_cast(input.get_character()); + const auto charcode = 0x10000u + (((static_cast(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); + utf8_bytes[0] = static_cast::int_type>(0xF0u | (charcode >> 18u)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu)); + utf8_bytes[3] = static_cast::int_type>(0x80u | (charcode & 0x3Fu)); + utf8_bytes_filled = 4; + } + else + { + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + } + } + } +}; + +// Wraps another input apdater to convert wide character types into individual bytes. +template +class wide_string_input_adapter +{ + public: + using char_type = char; + + wide_string_input_adapter(BaseInputAdapter base) + : base_adapter(base) {} + + typename std::char_traits::int_type get_character() noexcept + { + // check if buffer needs to be filled + if (utf8_bytes_index == utf8_bytes_filled) + { + fill_buffer(); + + JSON_ASSERT(utf8_bytes_filled > 0); + JSON_ASSERT(utf8_bytes_index == 0); + } + + // use buffer + JSON_ASSERT(utf8_bytes_filled > 0); + JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled); + return utf8_bytes[utf8_bytes_index++]; + } + + private: + BaseInputAdapter base_adapter; + + template + void fill_buffer() + { + wide_string_input_helper::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); + } + + /// a buffer for UTF-8 bytes + std::array::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; + + /// index to the utf8_codes array for the next valid byte + std::size_t utf8_bytes_index = 0; + /// number of valid bytes in the utf8_codes array + std::size_t utf8_bytes_filled = 0; +}; + + +template +struct iterator_input_adapter_factory +{ + using iterator_type = IteratorType; + using char_type = typename std::iterator_traits::value_type; + using adapter_type = iterator_input_adapter; + + static adapter_type create(IteratorType first, IteratorType last) + { + return adapter_type(std::move(first), std::move(last)); + } +}; + +template +struct is_iterator_of_multibyte +{ + using value_type = typename std::iterator_traits::value_type; + enum + { + value = sizeof(value_type) > 1 + }; +}; + +template +struct iterator_input_adapter_factory::value>> +{ + using iterator_type = IteratorType; + using char_type = typename std::iterator_traits::value_type; + using base_adapter_type = iterator_input_adapter; + using adapter_type = wide_string_input_adapter; + + static adapter_type create(IteratorType first, IteratorType last) + { + return adapter_type(base_adapter_type(std::move(first), std::move(last))); + } +}; + +// General purpose iterator-based input +template +typename iterator_input_adapter_factory::adapter_type input_adapter(IteratorType first, IteratorType last) +{ + using factory_type = iterator_input_adapter_factory; + return factory_type::create(first, last); +} + +// Convenience shorthand from container to iterator +// Enables ADL on begin(container) and end(container) +// Encloses the using declarations in namespace for not to leak them to outside scope + +namespace container_input_adapter_factory_impl +{ + +using std::begin; +using std::end; + +template +struct container_input_adapter_factory {}; + +template +struct container_input_adapter_factory< ContainerType, + void_t()), end(std::declval()))>> + { + using adapter_type = decltype(input_adapter(begin(std::declval()), end(std::declval()))); + + static adapter_type create(const ContainerType& container) +{ + return input_adapter(begin(container), end(container)); +} + }; + +} // namespace container_input_adapter_factory_impl + +template +typename container_input_adapter_factory_impl::container_input_adapter_factory::adapter_type input_adapter(const ContainerType& container) +{ + return container_input_adapter_factory_impl::container_input_adapter_factory::create(container); +} + +#ifndef JSON_NO_IO +// Special cases with fast paths +inline file_input_adapter input_adapter(std::FILE* file) +{ + return file_input_adapter(file); +} + +inline input_stream_adapter input_adapter(std::istream& stream) +{ + return input_stream_adapter(stream); +} + +inline input_stream_adapter input_adapter(std::istream&& stream) +{ + return input_stream_adapter(stream); +} +#endif // JSON_NO_IO + +using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval(), std::declval())); + +// Null-delimited strings, and the like. +template < typename CharT, + typename std::enable_if < + std::is_pointer::value&& + !std::is_array::value&& + std::is_integral::type>::value&& + sizeof(typename std::remove_pointer::type) == 1, + int >::type = 0 > +contiguous_bytes_input_adapter input_adapter(CharT b) +{ + auto length = std::strlen(reinterpret_cast(b)); + const auto* ptr = reinterpret_cast(b); + return input_adapter(ptr, ptr + length); +} + +template +auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +{ + return input_adapter(array, array + N); +} + +// This class only handles inputs of input_buffer_adapter type. +// It's required so that expressions like {ptr, len} can be implicitly cast +// to the correct adapter. +class span_input_adapter +{ + public: + template < typename CharT, + typename std::enable_if < + std::is_pointer::value&& + std::is_integral::type>::value&& + sizeof(typename std::remove_pointer::type) == 1, + int >::type = 0 > + span_input_adapter(CharT b, std::size_t l) + : ia(reinterpret_cast(b), reinterpret_cast(b) + l) {} + + template::iterator_category, std::random_access_iterator_tag>::value, + int>::type = 0> + span_input_adapter(IteratorType first, IteratorType last) + : ia(input_adapter(first, last)) {} + + contiguous_bytes_input_adapter&& get() + { + return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg) + } + + private: + contiguous_bytes_input_adapter ia; +}; +} // namespace detail +} // namespace nlohmann + +// #include + + +#include +#include // string +#include // move +#include // vector + +// #include + +// #include + + +namespace nlohmann +{ + +/*! +@brief SAX interface + +This class describes the SAX interface used by @ref nlohmann::json::sax_parse. +Each function is called in different situations while the input is parsed. The +boolean return value informs the parser whether to continue processing the +input. +*/ +template +struct json_sax +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + + /*! + @brief a null value was read + @return whether parsing should proceed + */ + virtual bool null() = 0; + + /*! + @brief a boolean value was read + @param[in] val boolean value + @return whether parsing should proceed + */ + virtual bool boolean(bool val) = 0; + + /*! + @brief an integer number was read + @param[in] val integer value + @return whether parsing should proceed + */ + virtual bool number_integer(number_integer_t val) = 0; + + /*! + @brief an unsigned integer number was read + @param[in] val unsigned integer value + @return whether parsing should proceed + */ + virtual bool number_unsigned(number_unsigned_t val) = 0; + + /*! + @brief a floating-point number was read + @param[in] val floating-point value + @param[in] s raw token value + @return whether parsing should proceed + */ + virtual bool number_float(number_float_t val, const string_t& s) = 0; + + /*! + @brief a string value was read + @param[in] val string value + @return whether parsing should proceed + @note It is safe to move the passed string value. + */ + virtual bool string(string_t& val) = 0; + + /*! + @brief a binary value was read + @param[in] val binary value + @return whether parsing should proceed + @note It is safe to move the passed binary value. + */ + virtual bool binary(binary_t& val) = 0; + + /*! + @brief the beginning of an object was read + @param[in] elements number of object elements or -1 if unknown + @return whether parsing should proceed + @note binary formats may report the number of elements + */ + virtual bool start_object(std::size_t elements) = 0; + + /*! + @brief an object key was read + @param[in] val object key + @return whether parsing should proceed + @note It is safe to move the passed string. + */ + virtual bool key(string_t& val) = 0; + + /*! + @brief the end of an object was read + @return whether parsing should proceed + */ + virtual bool end_object() = 0; + + /*! + @brief the beginning of an array was read + @param[in] elements number of array elements or -1 if unknown + @return whether parsing should proceed + @note binary formats may report the number of elements + */ + virtual bool start_array(std::size_t elements) = 0; + + /*! + @brief the end of an array was read + @return whether parsing should proceed + */ + virtual bool end_array() = 0; + + /*! + @brief a parse error occurred + @param[in] position the position in the input where the error occurs + @param[in] last_token the last read token + @param[in] ex an exception object describing the error + @return whether parsing should proceed (must return false) + */ + virtual bool parse_error(std::size_t position, + const std::string& last_token, + const detail::exception& ex) = 0; + + json_sax() = default; + json_sax(const json_sax&) = default; + json_sax(json_sax&&) noexcept = default; + json_sax& operator=(const json_sax&) = default; + json_sax& operator=(json_sax&&) noexcept = default; + virtual ~json_sax() = default; +}; + + +namespace detail +{ +/*! +@brief SAX implementation to create a JSON value from SAX events + +This class implements the @ref json_sax interface and processes the SAX events +to create a JSON value which makes it basically a DOM parser. The structure or +hierarchy of the JSON value is managed by the stack `ref_stack` which contains +a pointer to the respective array or object for each recursion depth. + +After successful parsing, the value that is passed by reference to the +constructor contains the parsed value. + +@tparam BasicJsonType the JSON type +*/ +template +class json_sax_dom_parser +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + + /*! + @param[in,out] r reference to a JSON value that is manipulated while + parsing + @param[in] allow_exceptions_ whether parse errors yield exceptions + */ + explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) + : root(r), allow_exceptions(allow_exceptions_) + {} + + // make class move-only + json_sax_dom_parser(const json_sax_dom_parser&) = delete; + json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete; + json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + ~json_sax_dom_parser() = default; + + bool null() + { + handle_value(nullptr); + return true; + } + + bool boolean(bool val) + { + handle_value(val); + return true; + } + + bool number_integer(number_integer_t val) + { + handle_value(val); + return true; + } + + bool number_unsigned(number_unsigned_t val) + { + handle_value(val); + return true; + } + + bool number_float(number_float_t val, const string_t& /*unused*/) + { + handle_value(val); + return true; + } + + bool string(string_t& val) + { + handle_value(val); + return true; + } + + bool binary(binary_t& val) + { + handle_value(std::move(val)); + return true; + } + + bool start_object(std::size_t len) + { + ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); + + if (JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back())); + } + + return true; + } + + bool key(string_t& val) + { + // add null at given key and store the reference for later + object_element = &(ref_stack.back()->m_value.object->operator[](val)); + return true; + } + + bool end_object() + { + ref_stack.back()->set_parents(); + ref_stack.pop_back(); + return true; + } + + bool start_array(std::size_t len) + { + ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); + + if (JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back())); + } + + return true; + } + + bool end_array() + { + ref_stack.back()->set_parents(); + ref_stack.pop_back(); + return true; + } + + template + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, + const Exception& ex) + { + errored = true; + static_cast(ex); + if (allow_exceptions) + { + JSON_THROW(ex); + } + return false; + } + + constexpr bool is_errored() const + { + return errored; + } + + private: + /*! + @invariant If the ref stack is empty, then the passed value will be the new + root. + @invariant If the ref stack contains a value, then it is an array or an + object to which we can add elements + */ + template + JSON_HEDLEY_RETURNS_NON_NULL + BasicJsonType* handle_value(Value&& v) + { + if (ref_stack.empty()) + { + root = BasicJsonType(std::forward(v)); + return &root; + } + + JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); + + if (ref_stack.back()->is_array()) + { + ref_stack.back()->m_value.array->emplace_back(std::forward(v)); + return &(ref_stack.back()->m_value.array->back()); + } + + JSON_ASSERT(ref_stack.back()->is_object()); + JSON_ASSERT(object_element); + *object_element = BasicJsonType(std::forward(v)); + return object_element; + } + + /// the parsed JSON value + BasicJsonType& root; + /// stack to model hierarchy of values + std::vector ref_stack {}; + /// helper to hold the reference for the next object element + BasicJsonType* object_element = nullptr; + /// whether a syntax error occurred + bool errored = false; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; +}; + +template +class json_sax_dom_callback_parser +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using parser_callback_t = typename BasicJsonType::parser_callback_t; + using parse_event_t = typename BasicJsonType::parse_event_t; + + json_sax_dom_callback_parser(BasicJsonType& r, + const parser_callback_t cb, + const bool allow_exceptions_ = true) + : root(r), callback(cb), allow_exceptions(allow_exceptions_) + { + keep_stack.push_back(true); + } + + // make class move-only + json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete; + json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete; + json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + ~json_sax_dom_callback_parser() = default; + + bool null() + { + handle_value(nullptr); + return true; + } + + bool boolean(bool val) + { + handle_value(val); + return true; + } + + bool number_integer(number_integer_t val) + { + handle_value(val); + return true; + } + + bool number_unsigned(number_unsigned_t val) + { + handle_value(val); + return true; + } + + bool number_float(number_float_t val, const string_t& /*unused*/) + { + handle_value(val); + return true; + } + + bool string(string_t& val) + { + handle_value(val); + return true; + } + + bool binary(binary_t& val) + { + handle_value(std::move(val)); + return true; + } + + bool start_object(std::size_t len) + { + // check callback for object start + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::object_start, discarded); + keep_stack.push_back(keep); + + auto val = handle_value(BasicJsonType::value_t::object, true); + ref_stack.push_back(val.second); + + // check object limit + if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back())); + } + + return true; + } + + bool key(string_t& val) + { + BasicJsonType k = BasicJsonType(val); + + // check callback for key + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::key, k); + key_keep_stack.push_back(keep); + + // add discarded value at given key and store the reference for later + if (keep && ref_stack.back()) + { + object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded); + } + + return true; + } + + bool end_object() + { + if (ref_stack.back()) + { + if (!callback(static_cast(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) + { + // discard object + *ref_stack.back() = discarded; + } + else + { + ref_stack.back()->set_parents(); + } + } + + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(!keep_stack.empty()); + ref_stack.pop_back(); + keep_stack.pop_back(); + + if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) + { + // remove discarded value + for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) + { + if (it->is_discarded()) + { + ref_stack.back()->erase(it); + break; + } + } + } + + return true; + } + + bool start_array(std::size_t len) + { + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::array_start, discarded); + keep_stack.push_back(keep); + + auto val = handle_value(BasicJsonType::value_t::array, true); + ref_stack.push_back(val.second); + + // check array limit + if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back())); + } + + return true; + } + + bool end_array() + { + bool keep = true; + + if (ref_stack.back()) + { + keep = callback(static_cast(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); + if (keep) + { + ref_stack.back()->set_parents(); + } + else + { + // discard array + *ref_stack.back() = discarded; + } + } + + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(!keep_stack.empty()); + ref_stack.pop_back(); + keep_stack.pop_back(); + + // remove discarded value + if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) + { + ref_stack.back()->m_value.array->pop_back(); + } + + return true; + } + + template + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, + const Exception& ex) + { + errored = true; + static_cast(ex); + if (allow_exceptions) + { + JSON_THROW(ex); + } + return false; + } + + constexpr bool is_errored() const + { + return errored; + } + + private: + /*! + @param[in] v value to add to the JSON value we build during parsing + @param[in] skip_callback whether we should skip calling the callback + function; this is required after start_array() and + start_object() SAX events, because otherwise we would call the + callback function with an empty array or object, respectively. + + @invariant If the ref stack is empty, then the passed value will be the new + root. + @invariant If the ref stack contains a value, then it is an array or an + object to which we can add elements + + @return pair of boolean (whether value should be kept) and pointer (to the + passed value in the ref_stack hierarchy; nullptr if not kept) + */ + template + std::pair handle_value(Value&& v, const bool skip_callback = false) + { + JSON_ASSERT(!keep_stack.empty()); + + // do not handle this value if we know it would be added to a discarded + // container + if (!keep_stack.back()) + { + return {false, nullptr}; + } + + // create value + auto value = BasicJsonType(std::forward(v)); + + // check callback + const bool keep = skip_callback || callback(static_cast(ref_stack.size()), parse_event_t::value, value); + + // do not handle this value if we just learnt it shall be discarded + if (!keep) + { + return {false, nullptr}; + } + + if (ref_stack.empty()) + { + root = std::move(value); + return {true, &root}; + } + + // skip this value if we already decided to skip the parent + // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) + if (!ref_stack.back()) + { + return {false, nullptr}; + } + + // we now only expect arrays and objects + JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); + + // array + if (ref_stack.back()->is_array()) + { + ref_stack.back()->m_value.array->emplace_back(std::move(value)); + return {true, &(ref_stack.back()->m_value.array->back())}; + } + + // object + JSON_ASSERT(ref_stack.back()->is_object()); + // check if we should store an element for the current key + JSON_ASSERT(!key_keep_stack.empty()); + const bool store_element = key_keep_stack.back(); + key_keep_stack.pop_back(); + + if (!store_element) + { + return {false, nullptr}; + } + + JSON_ASSERT(object_element); + *object_element = std::move(value); + return {true, object_element}; + } + + /// the parsed JSON value + BasicJsonType& root; + /// stack to model hierarchy of values + std::vector ref_stack {}; + /// stack to manage which values to keep + std::vector keep_stack {}; + /// stack to manage which object keys to keep + std::vector key_keep_stack {}; + /// helper to hold the reference for the next object element + BasicJsonType* object_element = nullptr; + /// whether a syntax error occurred + bool errored = false; + /// callback function + const parser_callback_t callback = nullptr; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; + /// a discarded value for the callback + BasicJsonType discarded = BasicJsonType::value_t::discarded; +}; + +template +class json_sax_acceptor +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + + bool null() + { + return true; + } + + bool boolean(bool /*unused*/) + { + return true; + } + + bool number_integer(number_integer_t /*unused*/) + { + return true; + } + + bool number_unsigned(number_unsigned_t /*unused*/) + { + return true; + } + + bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) + { + return true; + } + + bool string(string_t& /*unused*/) + { + return true; + } + + bool binary(binary_t& /*unused*/) + { + return true; + } + + bool start_object(std::size_t /*unused*/ = static_cast(-1)) + { + return true; + } + + bool key(string_t& /*unused*/) + { + return true; + } + + bool end_object() + { + return true; + } + + bool start_array(std::size_t /*unused*/ = static_cast(-1)) + { + return true; + } + + bool end_array() + { + return true; + } + + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) + { + return false; + } +}; +} // namespace detail + +} // namespace nlohmann + +// #include + + +#include // array +#include // localeconv +#include // size_t +#include // snprintf +#include // strtof, strtod, strtold, strtoll, strtoull +#include // initializer_list +#include // char_traits, string +#include // move +#include // vector + +// #include + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +/////////// +// lexer // +/////////// + +template +class lexer_base +{ + public: + /// token types for the parser + enum class token_type + { + uninitialized, ///< indicating the scanner is uninitialized + literal_true, ///< the `true` literal + literal_false, ///< the `false` literal + literal_null, ///< the `null` literal + value_string, ///< a string -- use get_string() for actual value + value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value + value_integer, ///< a signed integer -- use get_number_integer() for actual value + value_float, ///< an floating point number -- use get_number_float() for actual value + begin_array, ///< the character for array begin `[` + begin_object, ///< the character for object begin `{` + end_array, ///< the character for array end `]` + end_object, ///< the character for object end `}` + name_separator, ///< the name separator `:` + value_separator, ///< the value separator `,` + parse_error, ///< indicating a parse error + end_of_input, ///< indicating the end of the input buffer + literal_or_value ///< a literal or the begin of a value (only for diagnostics) + }; + + /// return name of values of type token_type (only used for errors) + JSON_HEDLEY_RETURNS_NON_NULL + JSON_HEDLEY_CONST + static const char* token_type_name(const token_type t) noexcept + { + switch (t) + { + case token_type::uninitialized: + return ""; + case token_type::literal_true: + return "true literal"; + case token_type::literal_false: + return "false literal"; + case token_type::literal_null: + return "null literal"; + case token_type::value_string: + return "string literal"; + case token_type::value_unsigned: + case token_type::value_integer: + case token_type::value_float: + return "number literal"; + case token_type::begin_array: + return "'['"; + case token_type::begin_object: + return "'{'"; + case token_type::end_array: + return "']'"; + case token_type::end_object: + return "'}'"; + case token_type::name_separator: + return "':'"; + case token_type::value_separator: + return "','"; + case token_type::parse_error: + return ""; + case token_type::end_of_input: + return "end of input"; + case token_type::literal_or_value: + return "'[', '{', or a literal"; + // LCOV_EXCL_START + default: // catch non-enum values + return "unknown token"; + // LCOV_EXCL_STOP + } + } +}; +/*! +@brief lexical analysis + +This class organizes the lexical analysis during JSON deserialization. +*/ +template +class lexer : public lexer_base +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using char_type = typename InputAdapterType::char_type; + using char_int_type = typename std::char_traits::int_type; + + public: + using token_type = typename lexer_base::token_type; + + explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept + : ia(std::move(adapter)) + , ignore_comments(ignore_comments_) + , decimal_point_char(static_cast(get_decimal_point())) + {} + + // delete because of pointer members + lexer(const lexer&) = delete; + lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + lexer& operator=(lexer&) = delete; + lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + ~lexer() = default; + + private: + ///////////////////// + // locales + ///////////////////// + + /// return the locale-dependent decimal point + JSON_HEDLEY_PURE + static char get_decimal_point() noexcept + { + const auto* loc = localeconv(); + JSON_ASSERT(loc != nullptr); + return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point); + } + + ///////////////////// + // scan functions + ///////////////////// + + /*! + @brief get codepoint from 4 hex characters following `\u` + + For input "\u c1 c2 c3 c4" the codepoint is: + (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4 + = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0) + + Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f' + must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The + conversion is done by subtracting the offset (0x30, 0x37, and 0x57) + between the ASCII value of the character and the desired integer value. + + @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or + non-hex character) + */ + int get_codepoint() + { + // this function only makes sense after reading `\u` + JSON_ASSERT(current == 'u'); + int codepoint = 0; + + const auto factors = { 12u, 8u, 4u, 0u }; + for (const auto factor : factors) + { + get(); + + if (current >= '0' && current <= '9') + { + codepoint += static_cast((static_cast(current) - 0x30u) << factor); + } + else if (current >= 'A' && current <= 'F') + { + codepoint += static_cast((static_cast(current) - 0x37u) << factor); + } + else if (current >= 'a' && current <= 'f') + { + codepoint += static_cast((static_cast(current) - 0x57u) << factor); + } + else + { + return -1; + } + } + + JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF); + return codepoint; + } + + /*! + @brief check if the next byte(s) are inside a given range + + Adds the current byte and, for each passed range, reads a new byte and + checks if it is inside the range. If a violation was detected, set up an + error message and return false. Otherwise, return true. + + @param[in] ranges list of integers; interpreted as list of pairs of + inclusive lower and upper bound, respectively + + @pre The passed list @a ranges must have 2, 4, or 6 elements; that is, + 1, 2, or 3 pairs. This precondition is enforced by an assertion. + + @return true if and only if no range violation was detected + */ + bool next_byte_in_range(std::initializer_list ranges) + { + JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6); + add(current); + + for (auto range = ranges.begin(); range != ranges.end(); ++range) + { + get(); + if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) + { + add(current); + } + else + { + error_message = "invalid string: ill-formed UTF-8 byte"; + return false; + } + } + + return true; + } + + /*! + @brief scan a string literal + + This function scans a string according to Sect. 7 of RFC 8259. While + scanning, bytes are escaped and copied into buffer token_buffer. Then the + function returns successfully, token_buffer is *not* null-terminated (as it + may contain \0 bytes), and token_buffer.size() is the number of bytes in the + string. + + @return token_type::value_string if string could be successfully scanned, + token_type::parse_error otherwise + + @note In case of errors, variable error_message contains a textual + description. + */ + token_type scan_string() + { + // reset token_buffer (ignore opening quote) + reset(); + + // we entered the function by reading an open quote + JSON_ASSERT(current == '\"'); + + while (true) + { + // get next character + switch (get()) + { + // end of file while parsing string + case std::char_traits::eof(): + { + error_message = "invalid string: missing closing quote"; + return token_type::parse_error; + } + + // closing quote + case '\"': + { + return token_type::value_string; + } + + // escapes + case '\\': + { + switch (get()) + { + // quotation mark + case '\"': + add('\"'); + break; + // reverse solidus + case '\\': + add('\\'); + break; + // solidus + case '/': + add('/'); + break; + // backspace + case 'b': + add('\b'); + break; + // form feed + case 'f': + add('\f'); + break; + // line feed + case 'n': + add('\n'); + break; + // carriage return + case 'r': + add('\r'); + break; + // tab + case 't': + add('\t'); + break; + + // unicode escapes + case 'u': + { + const int codepoint1 = get_codepoint(); + int codepoint = codepoint1; // start with codepoint1 + + if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1)) + { + error_message = "invalid string: '\\u' must be followed by 4 hex digits"; + return token_type::parse_error; + } + + // check if code point is a high surrogate + if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF) + { + // expect next \uxxxx entry + if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u')) + { + const int codepoint2 = get_codepoint(); + + if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1)) + { + error_message = "invalid string: '\\u' must be followed by 4 hex digits"; + return token_type::parse_error; + } + + // check if codepoint2 is a low surrogate + if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF)) + { + // overwrite codepoint + codepoint = static_cast( + // high surrogate occupies the most significant 22 bits + (static_cast(codepoint1) << 10u) + // low surrogate occupies the least significant 15 bits + + static_cast(codepoint2) + // there is still the 0xD800, 0xDC00 and 0x10000 noise + // in the result, so we have to subtract with: + // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 + - 0x35FDC00u); + } + else + { + error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; + return token_type::parse_error; + } + } + else + { + error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; + return token_type::parse_error; + } + } + else + { + if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF)) + { + error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF"; + return token_type::parse_error; + } + } + + // result of the above calculation yields a proper codepoint + JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF); + + // translate codepoint into bytes + if (codepoint < 0x80) + { + // 1-byte characters: 0xxxxxxx (ASCII) + add(static_cast(codepoint)); + } + else if (codepoint <= 0x7FF) + { + // 2-byte characters: 110xxxxx 10xxxxxx + add(static_cast(0xC0u | (static_cast(codepoint) >> 6u))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } + else if (codepoint <= 0xFFFF) + { + // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx + add(static_cast(0xE0u | (static_cast(codepoint) >> 12u))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } + else + { + // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + add(static_cast(0xF0u | (static_cast(codepoint) >> 18u))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 12u) & 0x3Fu))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } + + break; + } + + // other characters after escape + default: + error_message = "invalid string: forbidden character after backslash"; + return token_type::parse_error; + } + + break; + } + + // invalid control characters + case 0x00: + { + error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000"; + return token_type::parse_error; + } + + case 0x01: + { + error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001"; + return token_type::parse_error; + } + + case 0x02: + { + error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002"; + return token_type::parse_error; + } + + case 0x03: + { + error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003"; + return token_type::parse_error; + } + + case 0x04: + { + error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004"; + return token_type::parse_error; + } + + case 0x05: + { + error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005"; + return token_type::parse_error; + } + + case 0x06: + { + error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006"; + return token_type::parse_error; + } + + case 0x07: + { + error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007"; + return token_type::parse_error; + } + + case 0x08: + { + error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b"; + return token_type::parse_error; + } + + case 0x09: + { + error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t"; + return token_type::parse_error; + } + + case 0x0A: + { + error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n"; + return token_type::parse_error; + } + + case 0x0B: + { + error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B"; + return token_type::parse_error; + } + + case 0x0C: + { + error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f"; + return token_type::parse_error; + } + + case 0x0D: + { + error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r"; + return token_type::parse_error; + } + + case 0x0E: + { + error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E"; + return token_type::parse_error; + } + + case 0x0F: + { + error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F"; + return token_type::parse_error; + } + + case 0x10: + { + error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010"; + return token_type::parse_error; + } + + case 0x11: + { + error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011"; + return token_type::parse_error; + } + + case 0x12: + { + error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012"; + return token_type::parse_error; + } + + case 0x13: + { + error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013"; + return token_type::parse_error; + } + + case 0x14: + { + error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014"; + return token_type::parse_error; + } + + case 0x15: + { + error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015"; + return token_type::parse_error; + } + + case 0x16: + { + error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016"; + return token_type::parse_error; + } + + case 0x17: + { + error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017"; + return token_type::parse_error; + } + + case 0x18: + { + error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018"; + return token_type::parse_error; + } + + case 0x19: + { + error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019"; + return token_type::parse_error; + } + + case 0x1A: + { + error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A"; + return token_type::parse_error; + } + + case 0x1B: + { + error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B"; + return token_type::parse_error; + } + + case 0x1C: + { + error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C"; + return token_type::parse_error; + } + + case 0x1D: + { + error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D"; + return token_type::parse_error; + } + + case 0x1E: + { + error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E"; + return token_type::parse_error; + } + + case 0x1F: + { + error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F"; + return token_type::parse_error; + } + + // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace)) + case 0x20: + case 0x21: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: + { + add(current); + break; + } + + // U+0080..U+07FF: bytes C2..DF 80..BF + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: + case 0xC7: + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD5: + case 0xD6: + case 0xD7: + case 0xD8: + case 0xD9: + case 0xDA: + case 0xDB: + case 0xDC: + case 0xDD: + case 0xDE: + case 0xDF: + { + if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF}))) + { + return token_type::parse_error; + } + break; + } + + // U+0800..U+0FFF: bytes E0 A0..BF 80..BF + case 0xE0: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF + // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xEE: + case 0xEF: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+D000..U+D7FF: bytes ED 80..9F 80..BF + case 0xED: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF + case 0xF0: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF + case 0xF1: + case 0xF2: + case 0xF3: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF + case 0xF4: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // remaining bytes (80..C1 and F5..FF) are ill-formed + default: + { + error_message = "invalid string: ill-formed UTF-8 byte"; + return token_type::parse_error; + } + } + } + } + + /*! + * @brief scan a comment + * @return whether comment could be scanned successfully + */ + bool scan_comment() + { + switch (get()) + { + // single-line comments skip input until a newline or EOF is read + case '/': + { + while (true) + { + switch (get()) + { + case '\n': + case '\r': + case std::char_traits::eof(): + case '\0': + return true; + + default: + break; + } + } + } + + // multi-line comments skip input until */ is read + case '*': + { + while (true) + { + switch (get()) + { + case std::char_traits::eof(): + case '\0': + { + error_message = "invalid comment; missing closing '*/'"; + return false; + } + + case '*': + { + switch (get()) + { + case '/': + return true; + + default: + { + unget(); + continue; + } + } + } + + default: + continue; + } + } + } + + // unexpected character after reading '/' + default: + { + error_message = "invalid comment; expecting '/' or '*' after '/'"; + return false; + } + } + } + + JSON_HEDLEY_NON_NULL(2) + static void strtof(float& f, const char* str, char** endptr) noexcept + { + f = std::strtof(str, endptr); + } + + JSON_HEDLEY_NON_NULL(2) + static void strtof(double& f, const char* str, char** endptr) noexcept + { + f = std::strtod(str, endptr); + } + + JSON_HEDLEY_NON_NULL(2) + static void strtof(long double& f, const char* str, char** endptr) noexcept + { + f = std::strtold(str, endptr); + } + + /*! + @brief scan a number literal + + This function scans a string according to Sect. 6 of RFC 8259. + + The function is realized with a deterministic finite state machine derived + from the grammar described in RFC 8259. Starting in state "init", the + input is read and used to determined the next state. Only state "done" + accepts the number. State "error" is a trap state to model errors. In the + table below, "anything" means any character but the ones listed before. + + state | 0 | 1-9 | e E | + | - | . | anything + ---------|----------|----------|----------|---------|---------|----------|----------- + init | zero | any1 | [error] | [error] | minus | [error] | [error] + minus | zero | any1 | [error] | [error] | [error] | [error] | [error] + zero | done | done | exponent | done | done | decimal1 | done + any1 | any1 | any1 | exponent | done | done | decimal1 | done + decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error] + decimal2 | decimal2 | decimal2 | exponent | done | done | done | done + exponent | any2 | any2 | [error] | sign | sign | [error] | [error] + sign | any2 | any2 | [error] | [error] | [error] | [error] | [error] + any2 | any2 | any2 | done | done | done | done | done + + The state machine is realized with one label per state (prefixed with + "scan_number_") and `goto` statements between them. The state machine + contains cycles, but any cycle can be left when EOF is read. Therefore, + the function is guaranteed to terminate. + + During scanning, the read bytes are stored in token_buffer. This string is + then converted to a signed integer, an unsigned integer, or a + floating-point number. + + @return token_type::value_unsigned, token_type::value_integer, or + token_type::value_float if number could be successfully scanned, + token_type::parse_error otherwise + + @note The scanner is independent of the current locale. Internally, the + locale's decimal point is used instead of `.` to work with the + locale-dependent converters. + */ + token_type scan_number() // lgtm [cpp/use-of-goto] + { + // reset token_buffer to store the number's bytes + reset(); + + // the type of the parsed number; initially set to unsigned; will be + // changed if minus sign, decimal point or exponent is read + token_type number_type = token_type::value_unsigned; + + // state (init): we just found out we need to scan a number + switch (current) + { + case '-': + { + add(current); + goto scan_number_minus; + } + + case '0': + { + add(current); + goto scan_number_zero; + } + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + // all other characters are rejected outside scan_number() + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + +scan_number_minus: + // state: we just parsed a leading minus sign + number_type = token_type::value_integer; + switch (get()) + { + case '0': + { + add(current); + goto scan_number_zero; + } + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + default: + { + error_message = "invalid number; expected digit after '-'"; + return token_type::parse_error; + } + } + +scan_number_zero: + // state: we just parse a zero (maybe with a leading minus sign) + switch (get()) + { + case '.': + { + add(decimal_point_char); + goto scan_number_decimal1; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_any1: + // state: we just parsed a number 0-9 (maybe with a leading minus sign) + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + case '.': + { + add(decimal_point_char); + goto scan_number_decimal1; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_decimal1: + // state: we just parsed a decimal point + number_type = token_type::value_float; + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_decimal2; + } + + default: + { + error_message = "invalid number; expected digit after '.'"; + return token_type::parse_error; + } + } + +scan_number_decimal2: + // we just parsed at least one number after a decimal point + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_decimal2; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_exponent: + // we just parsed an exponent + number_type = token_type::value_float; + switch (get()) + { + case '+': + case '-': + { + add(current); + goto scan_number_sign; + } + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + { + error_message = + "invalid number; expected '+', '-', or digit after exponent"; + return token_type::parse_error; + } + } + +scan_number_sign: + // we just parsed an exponent sign + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + { + error_message = "invalid number; expected digit after exponent sign"; + return token_type::parse_error; + } + } + +scan_number_any2: + // we just parsed a number after the exponent or exponent sign + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + goto scan_number_done; + } + +scan_number_done: + // unget the character after the number (we only read it to know that + // we are done scanning a number) + unget(); + + char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + errno = 0; + + // try to parse integers first and fall back to floats + if (number_type == token_type::value_unsigned) + { + const auto x = std::strtoull(token_buffer.data(), &endptr, 10); + + // we checked the number format before + JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); + + if (errno == 0) + { + value_unsigned = static_cast(x); + if (value_unsigned == x) + { + return token_type::value_unsigned; + } + } + } + else if (number_type == token_type::value_integer) + { + const auto x = std::strtoll(token_buffer.data(), &endptr, 10); + + // we checked the number format before + JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); + + if (errno == 0) + { + value_integer = static_cast(x); + if (value_integer == x) + { + return token_type::value_integer; + } + } + } + + // this code is reached if we parse a floating-point number or if an + // integer conversion above failed + strtof(value_float, token_buffer.data(), &endptr); + + // we checked the number format before + JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); + + return token_type::value_float; + } + + /*! + @param[in] literal_text the literal text to expect + @param[in] length the length of the passed literal text + @param[in] return_type the token type to return on success + */ + JSON_HEDLEY_NON_NULL(2) + token_type scan_literal(const char_type* literal_text, const std::size_t length, + token_type return_type) + { + JSON_ASSERT(std::char_traits::to_char_type(current) == literal_text[0]); + for (std::size_t i = 1; i < length; ++i) + { + if (JSON_HEDLEY_UNLIKELY(std::char_traits::to_char_type(get()) != literal_text[i])) + { + error_message = "invalid literal"; + return token_type::parse_error; + } + } + return return_type; + } + + ///////////////////// + // input management + ///////////////////// + + /// reset token_buffer; current character is beginning of token + void reset() noexcept + { + token_buffer.clear(); + token_string.clear(); + token_string.push_back(std::char_traits::to_char_type(current)); + } + + /* + @brief get next character from the input + + This function provides the interface to the used input adapter. It does + not throw in case the input reached EOF, but returns a + `std::char_traits::eof()` in that case. Stores the scanned characters + for use in error messages. + + @return character read from the input + */ + char_int_type get() + { + ++position.chars_read_total; + ++position.chars_read_current_line; + + if (next_unget) + { + // just reset the next_unget variable and work with current + next_unget = false; + } + else + { + current = ia.get_character(); + } + + if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) + { + token_string.push_back(std::char_traits::to_char_type(current)); + } + + if (current == '\n') + { + ++position.lines_read; + position.chars_read_current_line = 0; + } + + return current; + } + + /*! + @brief unget current character (read it again on next get) + + We implement unget by setting variable next_unget to true. The input is not + changed - we just simulate ungetting by modifying chars_read_total, + chars_read_current_line, and token_string. The next call to get() will + behave as if the unget character is read again. + */ + void unget() + { + next_unget = true; + + --position.chars_read_total; + + // in case we "unget" a newline, we have to also decrement the lines_read + if (position.chars_read_current_line == 0) + { + if (position.lines_read > 0) + { + --position.lines_read; + } + } + else + { + --position.chars_read_current_line; + } + + if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) + { + JSON_ASSERT(!token_string.empty()); + token_string.pop_back(); + } + } + + /// add a character to token_buffer + void add(char_int_type c) + { + token_buffer.push_back(static_cast(c)); + } + + public: + ///////////////////// + // value getters + ///////////////////// + + /// return integer value + constexpr number_integer_t get_number_integer() const noexcept + { + return value_integer; + } + + /// return unsigned integer value + constexpr number_unsigned_t get_number_unsigned() const noexcept + { + return value_unsigned; + } + + /// return floating-point value + constexpr number_float_t get_number_float() const noexcept + { + return value_float; + } + + /// return current string value (implicitly resets the token; useful only once) + string_t& get_string() + { + return token_buffer; + } + + ///////////////////// + // diagnostics + ///////////////////// + + /// return position of last read token + constexpr position_t get_position() const noexcept + { + return position; + } + + /// return the last read token (for errors only). Will never contain EOF + /// (an arbitrary value that is not a valid char value, often -1), because + /// 255 may legitimately occur. May contain NUL, which should be escaped. + std::string get_token_string() const + { + // escape control characters + std::string result; + for (const auto c : token_string) + { + if (static_cast(c) <= '\x1F') + { + // escape control characters + std::array cs{{}}; + static_cast((std::snprintf)(cs.data(), cs.size(), "", static_cast(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + result += cs.data(); + } + else + { + // add character as is + result.push_back(static_cast(c)); + } + } + + return result; + } + + /// return syntax error message + JSON_HEDLEY_RETURNS_NON_NULL + constexpr const char* get_error_message() const noexcept + { + return error_message; + } + + ///////////////////// + // actual scanner + ///////////////////// + + /*! + @brief skip the UTF-8 byte order mark + @return true iff there is no BOM or the correct BOM has been skipped + */ + bool skip_bom() + { + if (get() == 0xEF) + { + // check if we completely parse the BOM + return get() == 0xBB && get() == 0xBF; + } + + // the first character is not the beginning of the BOM; unget it to + // process is later + unget(); + return true; + } + + void skip_whitespace() + { + do + { + get(); + } + while (current == ' ' || current == '\t' || current == '\n' || current == '\r'); + } + + token_type scan() + { + // initially, skip the BOM + if (position.chars_read_total == 0 && !skip_bom()) + { + error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; + return token_type::parse_error; + } + + // read next character and ignore whitespace + skip_whitespace(); + + // ignore comments + while (ignore_comments && current == '/') + { + if (!scan_comment()) + { + return token_type::parse_error; + } + + // skip following whitespace + skip_whitespace(); + } + + switch (current) + { + // structural characters + case '[': + return token_type::begin_array; + case ']': + return token_type::end_array; + case '{': + return token_type::begin_object; + case '}': + return token_type::end_object; + case ':': + return token_type::name_separator; + case ',': + return token_type::value_separator; + + // literals + case 't': + { + std::array true_literal = {{static_cast('t'), static_cast('r'), static_cast('u'), static_cast('e')}}; + return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true); + } + case 'f': + { + std::array false_literal = {{static_cast('f'), static_cast('a'), static_cast('l'), static_cast('s'), static_cast('e')}}; + return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false); + } + case 'n': + { + std::array null_literal = {{static_cast('n'), static_cast('u'), static_cast('l'), static_cast('l')}}; + return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null); + } + + // string + case '\"': + return scan_string(); + + // number + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return scan_number(); + + // end of input (the null byte is needed when parsing from + // string literals) + case '\0': + case std::char_traits::eof(): + return token_type::end_of_input; + + // error + default: + error_message = "invalid literal"; + return token_type::parse_error; + } + } + + private: + /// input adapter + InputAdapterType ia; + + /// whether comments should be ignored (true) or signaled as errors (false) + const bool ignore_comments = false; + + /// the current character + char_int_type current = std::char_traits::eof(); + + /// whether the next get() call should just return current + bool next_unget = false; + + /// the start position of the current token + position_t position {}; + + /// raw input token string (for error messages) + std::vector token_string {}; + + /// buffer for variable-length tokens (numbers, strings) + string_t token_buffer {}; + + /// a description of occurred lexer errors + const char* error_message = ""; + + // number values + number_integer_t value_integer = 0; + number_unsigned_t value_unsigned = 0; + number_float_t value_float = 0; + + /// the decimal point + const char_int_type decimal_point_char = '.'; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +#include // size_t +#include // declval +#include // string + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template +using null_function_t = decltype(std::declval().null()); + +template +using boolean_function_t = + decltype(std::declval().boolean(std::declval())); + +template +using number_integer_function_t = + decltype(std::declval().number_integer(std::declval())); + +template +using number_unsigned_function_t = + decltype(std::declval().number_unsigned(std::declval())); + +template +using number_float_function_t = decltype(std::declval().number_float( + std::declval(), std::declval())); + +template +using string_function_t = + decltype(std::declval().string(std::declval())); + +template +using binary_function_t = + decltype(std::declval().binary(std::declval())); + +template +using start_object_function_t = + decltype(std::declval().start_object(std::declval())); + +template +using key_function_t = + decltype(std::declval().key(std::declval())); + +template +using end_object_function_t = decltype(std::declval().end_object()); + +template +using start_array_function_t = + decltype(std::declval().start_array(std::declval())); + +template +using end_array_function_t = decltype(std::declval().end_array()); + +template +using parse_error_function_t = decltype(std::declval().parse_error( + std::declval(), std::declval(), + std::declval())); + +template +struct is_sax +{ + private: + static_assert(is_basic_json::value, + "BasicJsonType must be of type basic_json<...>"); + + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using exception_t = typename BasicJsonType::exception; + + public: + static constexpr bool value = + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value; +}; + +template +struct is_sax_static_asserts +{ + private: + static_assert(is_basic_json::value, + "BasicJsonType must be of type basic_json<...>"); + + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using exception_t = typename BasicJsonType::exception; + + public: + static_assert(is_detected_exact::value, + "Missing/invalid function: bool null()"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool boolean(bool)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool boolean(bool)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool number_integer(number_integer_t)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool number_unsigned(number_unsigned_t)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool number_float(number_float_t, const string_t&)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool string(string_t&)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool binary(binary_t&)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool start_object(std::size_t)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool key(string_t&)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool end_object()"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool start_array(std::size_t)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool end_array()"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool parse_error(std::size_t, const " + "std::string&, const exception&)"); +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ + +/// how to treat CBOR tags +enum class cbor_tag_handler_t +{ + error, ///< throw a parse_error exception in case of a tag + ignore, ///< ignore tags + store ///< store tags as binary type +}; + +/*! +@brief determine system byte order + +@return true if and only if system's byte order is little endian + +@note from https://stackoverflow.com/a/1001328/266378 +*/ +static inline bool little_endianness(int num = 1) noexcept +{ + return *reinterpret_cast(&num) == 1; +} + + +/////////////////// +// binary reader // +/////////////////// + +/*! +@brief deserialization of CBOR, MessagePack, and UBJSON values +*/ +template> +class binary_reader +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using json_sax_t = SAX; + using char_type = typename InputAdapterType::char_type; + using char_int_type = typename std::char_traits::int_type; + + public: + /*! + @brief create a binary reader + + @param[in] adapter input adapter to read from + */ + explicit binary_reader(InputAdapterType&& adapter) noexcept : ia(std::move(adapter)) + { + (void)detail::is_sax_static_asserts {}; + } + + // make class move-only + binary_reader(const binary_reader&) = delete; + binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + binary_reader& operator=(const binary_reader&) = delete; + binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + ~binary_reader() = default; + + /*! + @param[in] format the binary format to parse + @param[in] sax_ a SAX event processor + @param[in] strict whether to expect the input to be consumed completed + @param[in] tag_handler how to treat CBOR tags + + @return whether parsing was successful + */ + JSON_HEDLEY_NON_NULL(3) + bool sax_parse(const input_format_t format, + json_sax_t* sax_, + const bool strict = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) + { + sax = sax_; + bool result = false; + + switch (format) + { + case input_format_t::bson: + result = parse_bson_internal(); + break; + + case input_format_t::cbor: + result = parse_cbor_internal(true, tag_handler); + break; + + case input_format_t::msgpack: + result = parse_msgpack_internal(); + break; + + case input_format_t::ubjson: + result = parse_ubjson_internal(); + break; + + case input_format_t::json: // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + + // strict mode: next byte must be EOF + if (result && strict) + { + if (format == input_format_t::ubjson) + { + get_ignore_noop(); + } + else + { + get(); + } + + if (JSON_HEDLEY_UNLIKELY(current != std::char_traits::eof())) + { + return sax->parse_error(chars_read, get_token_string(), + parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"), BasicJsonType())); + } + } + + return result; + } + + private: + ////////// + // BSON // + ////////// + + /*! + @brief Reads in a BSON-object and passes it to the SAX-parser. + @return whether a valid BSON-value was passed to the SAX parser + */ + bool parse_bson_internal() + { + std::int32_t document_size{}; + get_number(input_format_t::bson, document_size); + + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false))) + { + return false; + } + + return sax->end_object(); + } + + /*! + @brief Parses a C-style string from the BSON input. + @param[in,out] result A reference to the string variable where the read + string is to be stored. + @return `true` if the \x00-byte indicating the end of the string was + encountered before the EOF; false` indicates an unexpected EOF. + */ + bool get_bson_cstr(string_t& result) + { + auto out = std::back_inserter(result); + while (true) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring"))) + { + return false; + } + if (current == 0x00) + { + return true; + } + *out++ = static_cast(current); + } + } + + /*! + @brief Parses a zero-terminated string of length @a len from the BSON + input. + @param[in] len The length (including the zero-byte at the end) of the + string to be read. + @param[in,out] result A reference to the string variable where the read + string is to be stored. + @tparam NumberType The type of the length @a len + @pre len >= 1 + @return `true` if the string was successfully parsed + */ + template + bool get_bson_string(const NumberType len, string_t& result) + { + if (JSON_HEDLEY_UNLIKELY(len < 1)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"), BasicJsonType())); + } + + return get_string(input_format_t::bson, len - static_cast(1), result) && get() != std::char_traits::eof(); + } + + /*! + @brief Parses a byte array input of length @a len from the BSON input. + @param[in] len The length of the byte array to be read. + @param[in,out] result A reference to the binary variable where the read + array is to be stored. + @tparam NumberType The type of the length @a len + @pre len >= 0 + @return `true` if the byte array was successfully parsed + */ + template + bool get_bson_binary(const NumberType len, binary_t& result) + { + if (JSON_HEDLEY_UNLIKELY(len < 0)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"), BasicJsonType())); + } + + // All BSON binary values have a subtype + std::uint8_t subtype{}; + get_number(input_format_t::bson, subtype); + result.set_subtype(subtype); + + return get_binary(input_format_t::bson, len, result); + } + + /*! + @brief Read a BSON document element of the given @a element_type. + @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html + @param[in] element_type_parse_position The position in the input stream, + where the `element_type` was read. + @warning Not all BSON element types are supported yet. An unsupported + @a element_type will give rise to a parse_error.114: + Unsupported BSON record type 0x... + @return whether a valid BSON-object/array was passed to the SAX parser + */ + bool parse_bson_element_internal(const char_int_type element_type, + const std::size_t element_type_parse_position) + { + switch (element_type) + { + case 0x01: // double + { + double number{}; + return get_number(input_format_t::bson, number) && sax->number_float(static_cast(number), ""); + } + + case 0x02: // string + { + std::int32_t len{}; + string_t value; + return get_number(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value); + } + + case 0x03: // object + { + return parse_bson_internal(); + } + + case 0x04: // array + { + return parse_bson_array(); + } + + case 0x05: // binary + { + std::int32_t len{}; + binary_t value; + return get_number(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value); + } + + case 0x08: // boolean + { + return sax->boolean(get() != 0); + } + + case 0x0A: // null + { + return sax->null(); + } + + case 0x10: // int32 + { + std::int32_t value{}; + return get_number(input_format_t::bson, value) && sax->number_integer(value); + } + + case 0x12: // int64 + { + std::int64_t value{}; + return get_number(input_format_t::bson, value) && sax->number_integer(value); + } + + default: // anything else not supported (yet) + { + std::array cr{{}}; + static_cast((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()), BasicJsonType())); + } + } + } + + /*! + @brief Read a BSON element list (as specified in the BSON-spec) + + The same binary layout is used for objects and arrays, hence it must be + indicated with the argument @a is_array which one is expected + (true --> array, false --> object). + + @param[in] is_array Determines if the element list being read is to be + treated as an object (@a is_array == false), or as an + array (@a is_array == true). + @return whether a valid BSON-object/array was passed to the SAX parser + */ + bool parse_bson_element_list(const bool is_array) + { + string_t key; + + while (auto element_type = get()) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list"))) + { + return false; + } + + const std::size_t element_type_parse_position = chars_read; + if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key))) + { + return false; + } + + if (!is_array && !sax->key(key)) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position))) + { + return false; + } + + // get_bson_cstr only appends + key.clear(); + } + + return true; + } + + /*! + @brief Reads an array from the BSON input and passes it to the SAX-parser. + @return whether a valid BSON-array was passed to the SAX parser + */ + bool parse_bson_array() + { + std::int32_t document_size{}; + get_number(input_format_t::bson, document_size); + + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true))) + { + return false; + } + + return sax->end_array(); + } + + ////////// + // CBOR // + ////////// + + /*! + @param[in] get_char whether a new character should be retrieved from the + input (true) or whether the last read character should + be considered instead (false) + @param[in] tag_handler how CBOR tags should be treated + + @return whether a valid CBOR value was passed to the SAX parser + */ + bool parse_cbor_internal(const bool get_char, + const cbor_tag_handler_t tag_handler) + { + switch (get_char ? get() : current) + { + // EOF + case std::char_traits::eof(): + return unexpect_eof(input_format_t::cbor, "value"); + + // Integer 0x00..0x17 (0..23) + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + return sax->number_unsigned(static_cast(current)); + + case 0x18: // Unsigned integer (one-byte uint8_t follows) + { + std::uint8_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } + + case 0x19: // Unsigned integer (two-byte uint16_t follows) + { + std::uint16_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } + + case 0x1A: // Unsigned integer (four-byte uint32_t follows) + { + std::uint32_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } + + case 0x1B: // Unsigned integer (eight-byte uint64_t follows) + { + std::uint64_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } + + // Negative integer -1-0x00..-1-0x17 (-1..-24) + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + return sax->number_integer(static_cast(0x20 - 1 - current)); + + case 0x38: // Negative integer (one-byte uint8_t follows) + { + std::uint8_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); + } + + case 0x39: // Negative integer -1-n (two-byte uint16_t follows) + { + std::uint16_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); + } + + case 0x3A: // Negative integer -1-n (four-byte uint32_t follows) + { + std::uint32_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); + } + + case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows) + { + std::uint64_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) + - static_cast(number)); + } + + // Binary data (0x00..0x17 bytes follow) + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: // Binary data (one-byte uint8_t for n follows) + case 0x59: // Binary data (two-byte uint16_t for n follow) + case 0x5A: // Binary data (four-byte uint32_t for n follow) + case 0x5B: // Binary data (eight-byte uint64_t for n follow) + case 0x5F: // Binary data (indefinite length) + { + binary_t b; + return get_cbor_binary(b) && sax->binary(b); + } + + // UTF-8 string (0x00..0x17 bytes follow) + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: // UTF-8 string (one-byte uint8_t for n follows) + case 0x79: // UTF-8 string (two-byte uint16_t for n follow) + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) + case 0x7F: // UTF-8 string (indefinite length) + { + string_t s; + return get_cbor_string(s) && sax->string(s); + } + + // array (0x00..0x17 data items follow) + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + return get_cbor_array(static_cast(static_cast(current) & 0x1Fu), tag_handler); + + case 0x98: // array (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); + } + + case 0x99: // array (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); + } + + case 0x9A: // array (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); + } + + case 0x9B: // array (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(detail::conditional_static_cast(len), tag_handler); + } + + case 0x9F: // array (indefinite length) + return get_cbor_array(static_cast(-1), tag_handler); + + // map (0x00..0x17 pairs of data items follow) + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + return get_cbor_object(static_cast(static_cast(current) & 0x1Fu), tag_handler); + + case 0xB8: // map (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); + } + + case 0xB9: // map (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); + } + + case 0xBA: // map (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); + } + + case 0xBB: // map (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(detail::conditional_static_cast(len), tag_handler); + } + + case 0xBF: // map (indefinite length) + return get_cbor_object(static_cast(-1), tag_handler); + + case 0xC6: // tagged item + case 0xC7: + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD8: // tagged item (1 bytes follow) + case 0xD9: // tagged item (2 bytes follow) + case 0xDA: // tagged item (4 bytes follow) + case 0xDB: // tagged item (8 bytes follow) + { + switch (tag_handler) + { + case cbor_tag_handler_t::error: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); + } + + case cbor_tag_handler_t::ignore: + { + // ignore binary subtype + switch (current) + { + case 0xD8: + { + std::uint8_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; + } + case 0xD9: + { + std::uint16_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; + } + case 0xDA: + { + std::uint32_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; + } + case 0xDB: + { + std::uint64_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; + } + default: + break; + } + return parse_cbor_internal(true, tag_handler); + } + + case cbor_tag_handler_t::store: + { + binary_t b; + // use binary subtype and store in binary container + switch (current) + { + case 0xD8: + { + std::uint8_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + case 0xD9: + { + std::uint16_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + case 0xDA: + { + std::uint32_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + case 0xDB: + { + std::uint64_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + default: + return parse_cbor_internal(true, tag_handler); + } + get(); + return get_cbor_binary(b) && sax->binary(b); + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + return false; // LCOV_EXCL_LINE + } + } + + case 0xF4: // false + return sax->boolean(false); + + case 0xF5: // true + return sax->boolean(true); + + case 0xF6: // null + return sax->null(); + + case 0xF9: // Half-Precision Float (two-byte IEEE 754) + { + const auto byte1_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) + { + return false; + } + const auto byte2_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) + { + return false; + } + + const auto byte1 = static_cast(byte1_raw); + const auto byte2 = static_cast(byte2_raw); + + // code from RFC 7049, Appendix D, Figure 3: + // As half-precision floating-point numbers were only added + // to IEEE 754 in 2008, today's programming platforms often + // still only have limited support for them. It is very + // easy to include at least decoding support for them even + // without such support. An example of a small decoder for + // half-precision floating-point numbers in the C language + // is shown in Fig. 3. + const auto half = static_cast((byte1 << 8u) + byte2); + const double val = [&half] + { + const int exp = (half >> 10u) & 0x1Fu; + const unsigned int mant = half & 0x3FFu; + JSON_ASSERT(0 <= exp&& exp <= 32); + JSON_ASSERT(mant <= 1024); + switch (exp) + { + case 0: + return std::ldexp(mant, -24); + case 31: + return (mant == 0) + ? std::numeric_limits::infinity() + : std::numeric_limits::quiet_NaN(); + default: + return std::ldexp(mant + 1024, exp - 25); + } + }(); + return sax->number_float((half & 0x8000u) != 0 + ? static_cast(-val) + : static_cast(val), ""); + } + + case 0xFA: // Single-Precision Float (four-byte IEEE 754) + { + float number{}; + return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); + } + + case 0xFB: // Double-Precision Float (eight-byte IEEE 754) + { + double number{}; + return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); + } + + default: // anything else (0xFF is handled inside the other types) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); + } + } + } + + /*! + @brief reads a CBOR string + + This function first reads starting bytes to determine the expected + string length and then copies this number of bytes into a string. + Additionally, CBOR's strings with indefinite lengths are supported. + + @param[out] result created string + + @return whether string creation completed + */ + bool get_cbor_string(string_t& result) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string"))) + { + return false; + } + + switch (current) + { + // UTF-8 string (0x00..0x17 bytes follow) + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + { + return get_string(input_format_t::cbor, static_cast(current) & 0x1Fu, result); + } + + case 0x78: // UTF-8 string (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x79: // UTF-8 string (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x7F: // UTF-8 string (indefinite length) + { + while (get() != 0xFF) + { + string_t chunk; + if (!get_cbor_string(chunk)) + { + return false; + } + result.append(chunk); + } + return true; + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"), BasicJsonType())); + } + } + } + + /*! + @brief reads a CBOR byte array + + This function first reads starting bytes to determine the expected + byte array length and then copies this number of bytes into the byte array. + Additionally, CBOR's byte arrays with indefinite lengths are supported. + + @param[out] result created byte array + + @return whether byte array creation completed + */ + bool get_cbor_binary(binary_t& result) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary"))) + { + return false; + } + + switch (current) + { + // Binary data (0x00..0x17 bytes follow) + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + { + return get_binary(input_format_t::cbor, static_cast(current) & 0x1Fu, result); + } + + case 0x58: // Binary data (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x59: // Binary data (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x5A: // Binary data (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x5B: // Binary data (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x5F: // Binary data (indefinite length) + { + while (get() != 0xFF) + { + binary_t chunk; + if (!get_cbor_binary(chunk)) + { + return false; + } + result.insert(result.end(), chunk.begin(), chunk.end()); + } + return true; + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"), BasicJsonType())); + } + } + } + + /*! + @param[in] len the length of the array or static_cast(-1) for an + array of indefinite size + @param[in] tag_handler how CBOR tags should be treated + @return whether array creation completed + */ + bool get_cbor_array(const std::size_t len, + const cbor_tag_handler_t tag_handler) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) + { + return false; + } + + if (len != static_cast(-1)) + { + for (std::size_t i = 0; i < len; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) + { + return false; + } + } + } + else + { + while (get() != 0xFF) + { + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) + { + return false; + } + } + } + + return sax->end_array(); + } + + /*! + @param[in] len the length of the object or static_cast(-1) for an + object of indefinite size + @param[in] tag_handler how CBOR tags should be treated + @return whether object creation completed + */ + bool get_cbor_object(const std::size_t len, + const cbor_tag_handler_t tag_handler) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) + { + return false; + } + + if (len != 0) + { + string_t key; + if (len != static_cast(-1)) + { + for (std::size_t i = 0; i < len; ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) + { + return false; + } + key.clear(); + } + } + else + { + while (get() != 0xFF) + { + if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) + { + return false; + } + key.clear(); + } + } + } + + return sax->end_object(); + } + + ///////////// + // MsgPack // + ///////////// + + /*! + @return whether a valid MessagePack value was passed to the SAX parser + */ + bool parse_msgpack_internal() + { + switch (get()) + { + // EOF + case std::char_traits::eof(): + return unexpect_eof(input_format_t::msgpack, "value"); + + // positive fixint + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5C: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: + return sax->number_unsigned(static_cast(current)); + + // fixmap + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: + return get_msgpack_object(static_cast(static_cast(current) & 0x0Fu)); + + // fixarray + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + case 0x98: + case 0x99: + case 0x9A: + case 0x9B: + case 0x9C: + case 0x9D: + case 0x9E: + case 0x9F: + return get_msgpack_array(static_cast(static_cast(current) & 0x0Fu)); + + // fixstr + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + case 0xD9: // str 8 + case 0xDA: // str 16 + case 0xDB: // str 32 + { + string_t s; + return get_msgpack_string(s) && sax->string(s); + } + + case 0xC0: // nil + return sax->null(); + + case 0xC2: // false + return sax->boolean(false); + + case 0xC3: // true + return sax->boolean(true); + + case 0xC4: // bin 8 + case 0xC5: // bin 16 + case 0xC6: // bin 32 + case 0xC7: // ext 8 + case 0xC8: // ext 16 + case 0xC9: // ext 32 + case 0xD4: // fixext 1 + case 0xD5: // fixext 2 + case 0xD6: // fixext 4 + case 0xD7: // fixext 8 + case 0xD8: // fixext 16 + { + binary_t b; + return get_msgpack_binary(b) && sax->binary(b); + } + + case 0xCA: // float 32 + { + float number{}; + return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); + } + + case 0xCB: // float 64 + { + double number{}; + return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); + } + + case 0xCC: // uint 8 + { + std::uint8_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xCD: // uint 16 + { + std::uint16_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xCE: // uint 32 + { + std::uint32_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xCF: // uint 64 + { + std::uint64_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xD0: // int 8 + { + std::int8_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xD1: // int 16 + { + std::int16_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xD2: // int 32 + { + std::int32_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xD3: // int 64 + { + std::int64_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xDC: // array 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); + } + + case 0xDD: // array 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); + } + + case 0xDE: // map 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); + } + + case 0xDF: // map 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); + } + + // negative fixint + case 0xE0: + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xED: + case 0xEE: + case 0xEF: + case 0xF0: + case 0xF1: + case 0xF2: + case 0xF3: + case 0xF4: + case 0xF5: + case 0xF6: + case 0xF7: + case 0xF8: + case 0xF9: + case 0xFA: + case 0xFB: + case 0xFC: + case 0xFD: + case 0xFE: + case 0xFF: + return sax->number_integer(static_cast(current)); + + default: // anything else + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); + } + } + } + + /*! + @brief reads a MessagePack string + + This function first reads starting bytes to determine the expected + string length and then copies this number of bytes into a string. + + @param[out] result created string + + @return whether string creation completed + */ + bool get_msgpack_string(string_t& result) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string"))) + { + return false; + } + + switch (current) + { + // fixstr + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + { + return get_string(input_format_t::msgpack, static_cast(current) & 0x1Fu, result); + } + + case 0xD9: // str 8 + { + std::uint8_t len{}; + return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); + } + + case 0xDA: // str 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); + } + + case 0xDB: // str 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"), BasicJsonType())); + } + } + } + + /*! + @brief reads a MessagePack byte array + + This function first reads starting bytes to determine the expected + byte array length and then copies this number of bytes into a byte array. + + @param[out] result created byte array + + @return whether byte array creation completed + */ + bool get_msgpack_binary(binary_t& result) + { + // helper function to set the subtype + auto assign_and_return_true = [&result](std::int8_t subtype) + { + result.set_subtype(static_cast(subtype)); + return true; + }; + + switch (current) + { + case 0xC4: // bin 8 + { + std::uint8_t len{}; + return get_number(input_format_t::msgpack, len) && + get_binary(input_format_t::msgpack, len, result); + } + + case 0xC5: // bin 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && + get_binary(input_format_t::msgpack, len, result); + } + + case 0xC6: // bin 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && + get_binary(input_format_t::msgpack, len, result); + } + + case 0xC7: // ext 8 + { + std::uint8_t len{}; + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, len) && + get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, len, result) && + assign_and_return_true(subtype); + } + + case 0xC8: // ext 16 + { + std::uint16_t len{}; + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, len) && + get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, len, result) && + assign_and_return_true(subtype); + } + + case 0xC9: // ext 32 + { + std::uint32_t len{}; + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, len) && + get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, len, result) && + assign_and_return_true(subtype); + } + + case 0xD4: // fixext 1 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 1, result) && + assign_and_return_true(subtype); + } + + case 0xD5: // fixext 2 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 2, result) && + assign_and_return_true(subtype); + } + + case 0xD6: // fixext 4 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 4, result) && + assign_and_return_true(subtype); + } + + case 0xD7: // fixext 8 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 8, result) && + assign_and_return_true(subtype); + } + + case 0xD8: // fixext 16 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 16, result) && + assign_and_return_true(subtype); + } + + default: // LCOV_EXCL_LINE + return false; // LCOV_EXCL_LINE + } + } + + /*! + @param[in] len the length of the array + @return whether array creation completed + */ + bool get_msgpack_array(const std::size_t len) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) + { + return false; + } + + for (std::size_t i = 0; i < len; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) + { + return false; + } + } + + return sax->end_array(); + } + + /*! + @param[in] len the length of the object + @return whether object creation completed + */ + bool get_msgpack_object(const std::size_t len) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) + { + return false; + } + + string_t key; + for (std::size_t i = 0; i < len; ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) + { + return false; + } + key.clear(); + } + + return sax->end_object(); + } + + //////////// + // UBJSON // + //////////// + + /*! + @param[in] get_char whether a new character should be retrieved from the + input (true, default) or whether the last read + character should be considered instead + + @return whether a valid UBJSON value was passed to the SAX parser + */ + bool parse_ubjson_internal(const bool get_char = true) + { + return get_ubjson_value(get_char ? get_ignore_noop() : current); + } + + /*! + @brief reads a UBJSON string + + This function is either called after reading the 'S' byte explicitly + indicating a string, or in case of an object key where the 'S' byte can be + left out. + + @param[out] result created string + @param[in] get_char whether a new character should be retrieved from the + input (true, default) or whether the last read + character should be considered instead + + @return whether string creation completed + */ + bool get_ubjson_string(string_t& result, const bool get_char = true) + { + if (get_char) + { + get(); // TODO(niels): may we ignore N here? + } + + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) + { + return false; + } + + switch (current) + { + case 'U': + { + std::uint8_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + case 'i': + { + std::int8_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + case 'I': + { + std::int16_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + case 'l': + { + std::int32_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + case 'L': + { + std::int64_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + default: + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"), BasicJsonType())); + } + } + + /*! + @param[out] result determined size + @return whether size determination completed + */ + bool get_ubjson_size_value(std::size_t& result) + { + switch (get_ignore_noop()) + { + case 'U': + { + std::uint8_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + case 'i': + { + std::int8_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char + return true; + } + + case 'I': + { + std::int16_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + case 'l': + { + std::int32_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + case 'L': + { + std::int64_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"), BasicJsonType())); + } + } + } + + /*! + @brief determine the type and size for a container + + In the optimized UBJSON format, a type and a size can be provided to allow + for a more compact representation. + + @param[out] result pair of the size and the type + + @return whether pair creation completed + */ + bool get_ubjson_size_type(std::pair& result) + { + result.first = string_t::npos; // size + result.second = 0; // type + + get_ignore_noop(); + + if (current == '$') + { + result.second = get(); // must not ignore 'N', because 'N' maybe the type + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type"))) + { + return false; + } + + get_ignore_noop(); + if (JSON_HEDLEY_UNLIKELY(current != '#')) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) + { + return false; + } + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"), BasicJsonType())); + } + + return get_ubjson_size_value(result.first); + } + + if (current == '#') + { + return get_ubjson_size_value(result.first); + } + + return true; + } + + /*! + @param prefix the previously read or set type prefix + @return whether value creation completed + */ + bool get_ubjson_value(const char_int_type prefix) + { + switch (prefix) + { + case std::char_traits::eof(): // EOF + return unexpect_eof(input_format_t::ubjson, "value"); + + case 'T': // true + return sax->boolean(true); + case 'F': // false + return sax->boolean(false); + + case 'Z': // null + return sax->null(); + + case 'U': + { + std::uint8_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number); + } + + case 'i': + { + std::int8_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + } + + case 'I': + { + std::int16_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + } + + case 'l': + { + std::int32_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + } + + case 'L': + { + std::int64_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + } + + case 'd': + { + float number{}; + return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); + } + + case 'D': + { + double number{}; + return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); + } + + case 'H': + { + return get_ubjson_high_precision_number(); + } + + case 'C': // char + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char"))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(current > 127)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"), BasicJsonType())); + } + string_t s(1, static_cast(current)); + return sax->string(s); + } + + case 'S': // string + { + string_t s; + return get_ubjson_string(s) && sax->string(s); + } + + case '[': // array + return get_ubjson_array(); + + case '{': // object + return get_ubjson_object(); + + default: // anything else + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); + } + } + } + + /*! + @return whether array creation completed + */ + bool get_ubjson_array() + { + std::pair size_and_type; + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) + { + return false; + } + + if (size_and_type.first != string_t::npos) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) + { + return false; + } + + if (size_and_type.second != 0) + { + if (size_and_type.second != 'N') + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) + { + return false; + } + } + } + } + else + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) + { + return false; + } + } + } + } + else + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) + { + return false; + } + + while (current != ']') + { + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false))) + { + return false; + } + get_ignore_noop(); + } + } + + return sax->end_array(); + } + + /*! + @return whether object creation completed + */ + bool get_ubjson_object() + { + std::pair size_and_type; + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) + { + return false; + } + + string_t key; + if (size_and_type.first != string_t::npos) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) + { + return false; + } + + if (size_and_type.second != 0) + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) + { + return false; + } + key.clear(); + } + } + else + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) + { + return false; + } + key.clear(); + } + } + } + else + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) + { + return false; + } + + while (current != '}') + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) + { + return false; + } + get_ignore_noop(); + key.clear(); + } + } + + return sax->end_object(); + } + + // Note, no reader for UBJSON binary types is implemented because they do + // not exist + + bool get_ubjson_high_precision_number() + { + // get size of following number string + std::size_t size{}; + auto res = get_ubjson_size_value(size); + if (JSON_HEDLEY_UNLIKELY(!res)) + { + return res; + } + + // get number string + std::vector number_vector; + for (std::size_t i = 0; i < size; ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number"))) + { + return false; + } + number_vector.push_back(static_cast(current)); + } + + // parse number string + using ia_type = decltype(detail::input_adapter(number_vector)); + auto number_lexer = detail::lexer(detail::input_adapter(number_vector), false); + const auto result_number = number_lexer.scan(); + const auto number_string = number_lexer.get_token_string(); + const auto result_remainder = number_lexer.scan(); + + using token_type = typename detail::lexer_base::token_type; + + if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) + { + return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType())); + } + + switch (result_number) + { + case token_type::value_integer: + return sax->number_integer(number_lexer.get_number_integer()); + case token_type::value_unsigned: + return sax->number_unsigned(number_lexer.get_number_unsigned()); + case token_type::value_float: + return sax->number_float(number_lexer.get_number_float(), std::move(number_string)); + case token_type::uninitialized: + case token_type::literal_true: + case token_type::literal_false: + case token_type::literal_null: + case token_type::value_string: + case token_type::begin_array: + case token_type::begin_object: + case token_type::end_array: + case token_type::end_object: + case token_type::name_separator: + case token_type::value_separator: + case token_type::parse_error: + case token_type::end_of_input: + case token_type::literal_or_value: + default: + return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType())); + } + } + + /////////////////////// + // Utility functions // + /////////////////////// + + /*! + @brief get next character from the input + + This function provides the interface to the used input adapter. It does + not throw in case the input reached EOF, but returns a -'ve valued + `std::char_traits::eof()` in that case. + + @return character read from the input + */ + char_int_type get() + { + ++chars_read; + return current = ia.get_character(); + } + + /*! + @return character read from the input after ignoring all 'N' entries + */ + char_int_type get_ignore_noop() + { + do + { + get(); + } + while (current == 'N'); + + return current; + } + + /* + @brief read a number from the input + + @tparam NumberType the type of the number + @param[in] format the current format (for diagnostics) + @param[out] result number of type @a NumberType + + @return whether conversion completed + + @note This function needs to respect the system's endianness, because + bytes in CBOR, MessagePack, and UBJSON are stored in network order + (big endian) and therefore need reordering on little endian systems. + */ + template + bool get_number(const input_format_t format, NumberType& result) + { + // step 1: read input into array with system's byte order + std::array vec{}; + for (std::size_t i = 0; i < sizeof(NumberType); ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) + { + return false; + } + + // reverse byte order prior to conversion if necessary + if (is_little_endian != InputIsLittleEndian) + { + vec[sizeof(NumberType) - i - 1] = static_cast(current); + } + else + { + vec[i] = static_cast(current); // LCOV_EXCL_LINE + } + } + + // step 2: convert array into number of type T and return + std::memcpy(&result, vec.data(), sizeof(NumberType)); + return true; + } + + /*! + @brief create a string by reading characters from the input + + @tparam NumberType the type of the number + @param[in] format the current format (for diagnostics) + @param[in] len number of characters to read + @param[out] result string created by reading @a len bytes + + @return whether string creation completed + + @note We can not reserve @a len bytes for the result, because @a len + may be too large. Usually, @ref unexpect_eof() detects the end of + the input before we run out of string memory. + */ + template + bool get_string(const input_format_t format, + const NumberType len, + string_t& result) + { + bool success = true; + for (NumberType i = 0; i < len; i++) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string"))) + { + success = false; + break; + } + result.push_back(static_cast(current)); + } + return success; + } + + /*! + @brief create a byte array by reading bytes from the input + + @tparam NumberType the type of the number + @param[in] format the current format (for diagnostics) + @param[in] len number of bytes to read + @param[out] result byte array created by reading @a len bytes + + @return whether byte array creation completed + + @note We can not reserve @a len bytes for the result, because @a len + may be too large. Usually, @ref unexpect_eof() detects the end of + the input before we run out of memory. + */ + template + bool get_binary(const input_format_t format, + const NumberType len, + binary_t& result) + { + bool success = true; + for (NumberType i = 0; i < len; i++) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary"))) + { + success = false; + break; + } + result.push_back(static_cast(current)); + } + return success; + } + + /*! + @param[in] format the current format (for diagnostics) + @param[in] context further context information (for diagnostics) + @return whether the last read character is not EOF + */ + JSON_HEDLEY_NON_NULL(3) + bool unexpect_eof(const input_format_t format, const char* context) const + { + if (JSON_HEDLEY_UNLIKELY(current == std::char_traits::eof())) + { + return sax->parse_error(chars_read, "", + parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), BasicJsonType())); + } + return true; + } + + /*! + @return a string representation of the last read byte + */ + std::string get_token_string() const + { + std::array cr{{}}; + static_cast((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + return std::string{cr.data()}; + } + + /*! + @param[in] format the current format + @param[in] detail a detailed error message + @param[in] context further context information + @return a message string to use in the parse_error exceptions + */ + std::string exception_message(const input_format_t format, + const std::string& detail, + const std::string& context) const + { + std::string error_msg = "syntax error while parsing "; + + switch (format) + { + case input_format_t::cbor: + error_msg += "CBOR"; + break; + + case input_format_t::msgpack: + error_msg += "MessagePack"; + break; + + case input_format_t::ubjson: + error_msg += "UBJSON"; + break; + + case input_format_t::bson: + error_msg += "BSON"; + break; + + case input_format_t::json: // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + + return error_msg + " " + context + ": " + detail; + } + + private: + /// input adapter + InputAdapterType ia; + + /// the current character + char_int_type current = std::char_traits::eof(); + + /// the number of characters read + std::size_t chars_read = 0; + + /// whether we can assume little endianness + const bool is_little_endian = little_endianness(); + + /// the SAX parser + json_sax_t* sax = nullptr; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + +// #include + + +#include // isfinite +#include // uint8_t +#include // function +#include // string +#include // move +#include // vector + +// #include + +// #include + +// #include + +// #include + +// #include + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +//////////// +// parser // +//////////// + +enum class parse_event_t : std::uint8_t +{ + /// the parser read `{` and started to process a JSON object + object_start, + /// the parser read `}` and finished processing a JSON object + object_end, + /// the parser read `[` and started to process a JSON array + array_start, + /// the parser read `]` and finished processing a JSON array + array_end, + /// the parser read a key of a value in an object + key, + /// the parser finished reading a JSON value + value +}; + +template +using parser_callback_t = + std::function; + +/*! +@brief syntax analysis + +This class implements a recursive descent parser. +*/ +template +class parser +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using lexer_t = lexer; + using token_type = typename lexer_t::token_type; + + public: + /// a parser reading from an input adapter + explicit parser(InputAdapterType&& adapter, + const parser_callback_t cb = nullptr, + const bool allow_exceptions_ = true, + const bool skip_comments = false) + : callback(cb) + , m_lexer(std::move(adapter), skip_comments) + , allow_exceptions(allow_exceptions_) + { + // read first token + get_token(); + } + + /*! + @brief public parser interface + + @param[in] strict whether to expect the last token to be EOF + @param[in,out] result parsed JSON value + + @throw parse_error.101 in case of an unexpected token + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + */ + void parse(const bool strict, BasicJsonType& result) + { + if (callback) + { + json_sax_dom_callback_parser sdp(result, callback, allow_exceptions); + sax_parse_internal(&sdp); + + // in strict mode, input must be completely read + if (strict && (get_token() != token_type::end_of_input)) + { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"), BasicJsonType())); + } + + // in case of an error, return discarded value + if (sdp.is_errored()) + { + result = value_t::discarded; + return; + } + + // set top-level value to null if it was discarded by the callback + // function + if (result.is_discarded()) + { + result = nullptr; + } + } + else + { + json_sax_dom_parser sdp(result, allow_exceptions); + sax_parse_internal(&sdp); + + // in strict mode, input must be completely read + if (strict && (get_token() != token_type::end_of_input)) + { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType())); + } + + // in case of an error, return discarded value + if (sdp.is_errored()) + { + result = value_t::discarded; + return; + } + } + + result.assert_invariant(); + } + + /*! + @brief public accept interface + + @param[in] strict whether to expect the last token to be EOF + @return whether the input is a proper JSON text + */ + bool accept(const bool strict = true) + { + json_sax_acceptor sax_acceptor; + return sax_parse(&sax_acceptor, strict); + } + + template + JSON_HEDLEY_NON_NULL(2) + bool sax_parse(SAX* sax, const bool strict = true) + { + (void)detail::is_sax_static_asserts {}; + const bool result = sax_parse_internal(sax); + + // strict mode: next byte must be EOF + if (result && strict && (get_token() != token_type::end_of_input)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType())); + } + + return result; + } + + private: + template + JSON_HEDLEY_NON_NULL(2) + bool sax_parse_internal(SAX* sax) + { + // stack to remember the hierarchy of structured values we are parsing + // true = array; false = object + std::vector states; + // value to avoid a goto (see comment where set to true) + bool skip_to_state_evaluation = false; + + while (true) + { + if (!skip_to_state_evaluation) + { + // invariant: get_token() was called before each iteration + switch (last_token) + { + case token_type::begin_object: + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) + { + return false; + } + + // closing } -> we are done + if (get_token() == token_type::end_object) + { + if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) + { + return false; + } + break; + } + + // parse key + if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType())); + } + if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) + { + return false; + } + + // parse separator (:) + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType())); + } + + // remember we are now inside an object + states.push_back(false); + + // parse values + get_token(); + continue; + } + + case token_type::begin_array: + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) + { + return false; + } + + // closing ] -> we are done + if (get_token() == token_type::end_array) + { + if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) + { + return false; + } + break; + } + + // remember we are now inside an array + states.push_back(true); + + // parse values (no need to call get_token) + continue; + } + + case token_type::value_float: + { + const auto res = m_lexer.get_number_float(); + + if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'", BasicJsonType())); + } + + if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) + { + return false; + } + + break; + } + + case token_type::literal_false: + { + if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) + { + return false; + } + break; + } + + case token_type::literal_null: + { + if (JSON_HEDLEY_UNLIKELY(!sax->null())) + { + return false; + } + break; + } + + case token_type::literal_true: + { + if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) + { + return false; + } + break; + } + + case token_type::value_integer: + { + if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) + { + return false; + } + break; + } + + case token_type::value_string: + { + if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) + { + return false; + } + break; + } + + case token_type::value_unsigned: + { + if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) + { + return false; + } + break; + } + + case token_type::parse_error: + { + // using "uninitialized" to avoid "expected" message + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), BasicJsonType())); + } + + case token_type::uninitialized: + case token_type::end_array: + case token_type::end_object: + case token_type::name_separator: + case token_type::value_separator: + case token_type::end_of_input: + case token_type::literal_or_value: + default: // the last token was unexpected + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), BasicJsonType())); + } + } + } + else + { + skip_to_state_evaluation = false; + } + + // we reached this line after we successfully parsed a value + if (states.empty()) + { + // empty stack: we reached the end of the hierarchy: done + return true; + } + + if (states.back()) // array + { + // comma -> next value + if (get_token() == token_type::value_separator) + { + // parse a new value + get_token(); + continue; + } + + // closing ] + if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) + { + if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) + { + return false; + } + + // We are done with this array. Before we can parse a + // new value, we need to evaluate the new state first. + // By setting skip_to_state_evaluation to false, we + // are effectively jumping to the beginning of this if. + JSON_ASSERT(!states.empty()); + states.pop_back(); + skip_to_state_evaluation = true; + continue; + } + + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), BasicJsonType())); + } + + // states.back() is false -> object + + // comma -> next value + if (get_token() == token_type::value_separator) + { + // parse key + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType())); + } + + if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) + { + return false; + } + + // parse separator (:) + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType())); + } + + // parse values + get_token(); + continue; + } + + // closing } + if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) + { + if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) + { + return false; + } + + // We are done with this object. Before we can parse a + // new value, we need to evaluate the new state first. + // By setting skip_to_state_evaluation to false, we + // are effectively jumping to the beginning of this if. + JSON_ASSERT(!states.empty()); + states.pop_back(); + skip_to_state_evaluation = true; + continue; + } + + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), BasicJsonType())); + } + } + + /// get next token from lexer + token_type get_token() + { + return last_token = m_lexer.scan(); + } + + std::string exception_message(const token_type expected, const std::string& context) + { + std::string error_msg = "syntax error "; + + if (!context.empty()) + { + error_msg += "while parsing " + context + " "; + } + + error_msg += "- "; + + if (last_token == token_type::parse_error) + { + error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" + + m_lexer.get_token_string() + "'"; + } + else + { + error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token)); + } + + if (expected != token_type::uninitialized) + { + error_msg += "; expected " + std::string(lexer_t::token_type_name(expected)); + } + + return error_msg; + } + + private: + /// callback function + const parser_callback_t callback = nullptr; + /// the type of the last read token + token_type last_token = token_type::uninitialized; + /// the lexer + lexer_t m_lexer; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; +}; + +} // namespace detail +} // namespace nlohmann + +// #include + + +// #include + + +#include // ptrdiff_t +#include // numeric_limits + +// #include + + +namespace nlohmann +{ +namespace detail +{ +/* +@brief an iterator for primitive JSON types + +This class models an iterator for primitive JSON types (boolean, number, +string). It's only purpose is to allow the iterator/const_iterator classes +to "iterate" over primitive values. Internally, the iterator is modeled by +a `difference_type` variable. Value begin_value (`0`) models the begin, +end_value (`1`) models past the end. +*/ +class primitive_iterator_t +{ + private: + using difference_type = std::ptrdiff_t; + static constexpr difference_type begin_value = 0; + static constexpr difference_type end_value = begin_value + 1; + + JSON_PRIVATE_UNLESS_TESTED: + /// iterator as signed integer type + difference_type m_it = (std::numeric_limits::min)(); + + public: + constexpr difference_type get_value() const noexcept + { + return m_it; + } + + /// set iterator to a defined beginning + void set_begin() noexcept + { + m_it = begin_value; + } + + /// set iterator to a defined past the end + void set_end() noexcept + { + m_it = end_value; + } + + /// return whether the iterator can be dereferenced + constexpr bool is_begin() const noexcept + { + return m_it == begin_value; + } + + /// return whether the iterator is at end + constexpr bool is_end() const noexcept + { + return m_it == end_value; + } + + friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it == rhs.m_it; + } + + friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it < rhs.m_it; + } + + primitive_iterator_t operator+(difference_type n) noexcept + { + auto result = *this; + result += n; + return result; + } + + friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it - rhs.m_it; + } + + primitive_iterator_t& operator++() noexcept + { + ++m_it; + return *this; + } + + primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp) + { + auto result = *this; + ++m_it; + return result; + } + + primitive_iterator_t& operator--() noexcept + { + --m_it; + return *this; + } + + primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp) + { + auto result = *this; + --m_it; + return result; + } + + primitive_iterator_t& operator+=(difference_type n) noexcept + { + m_it += n; + return *this; + } + + primitive_iterator_t& operator-=(difference_type n) noexcept + { + m_it -= n; + return *this; + } +}; +} // namespace detail +} // namespace nlohmann + + +namespace nlohmann +{ +namespace detail +{ +/*! +@brief an iterator value + +@note This structure could easily be a union, but MSVC currently does not allow +unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. +*/ +template struct internal_iterator +{ + /// iterator for JSON objects + typename BasicJsonType::object_t::iterator object_iterator {}; + /// iterator for JSON arrays + typename BasicJsonType::array_t::iterator array_iterator {}; + /// generic iterator for all other types + primitive_iterator_t primitive_iterator {}; +}; +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next +#include // conditional, is_const, remove_const + +// #include + +// #include + +// #include + +// #include + +// #include + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +// forward declare, to be able to friend it later on +template class iteration_proxy; +template class iteration_proxy_value; + +/*! +@brief a template for a bidirectional iterator for the @ref basic_json class +This class implements a both iterators (iterator and const_iterator) for the +@ref basic_json class. +@note An iterator is called *initialized* when a pointer to a JSON value has + been set (e.g., by a constructor or a copy assignment). If the iterator is + default-constructed, it is *uninitialized* and most methods are undefined. + **The library uses assertions to detect calls on uninitialized iterators.** +@requirement The class satisfies the following concept requirements: +- +[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): + The iterator that can be moved can be moved in both directions (i.e. + incremented and decremented). +@since version 1.0.0, simplified in version 2.0.9, change to bidirectional + iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593) +*/ +template +class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) +{ + /// the iterator with BasicJsonType of different const-ness + using other_iter_impl = iter_impl::value, typename std::remove_const::type, const BasicJsonType>::type>; + /// allow basic_json to access private members + friend other_iter_impl; + friend BasicJsonType; + friend iteration_proxy; + friend iteration_proxy_value; + + using object_t = typename BasicJsonType::object_t; + using array_t = typename BasicJsonType::array_t; + // make sure BasicJsonType is basic_json or const basic_json + static_assert(is_basic_json::type>::value, + "iter_impl only accepts (const) basic_json"); + + public: + + /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. + /// The C++ Standard has never required user-defined iterators to derive from std::iterator. + /// A user-defined iterator should provide publicly accessible typedefs named + /// iterator_category, value_type, difference_type, pointer, and reference. + /// Note that value_type is required to be non-const, even for constant iterators. + using iterator_category = std::bidirectional_iterator_tag; + + /// the type of the values when the iterator is dereferenced + using value_type = typename BasicJsonType::value_type; + /// a type to represent differences between iterators + using difference_type = typename BasicJsonType::difference_type; + /// defines a pointer to the type iterated over (value_type) + using pointer = typename std::conditional::value, + typename BasicJsonType::const_pointer, + typename BasicJsonType::pointer>::type; + /// defines a reference to the type iterated over (value_type) + using reference = + typename std::conditional::value, + typename BasicJsonType::const_reference, + typename BasicJsonType::reference>::type; + + iter_impl() = default; + ~iter_impl() = default; + iter_impl(iter_impl&&) noexcept = default; + iter_impl& operator=(iter_impl&&) noexcept = default; + + /*! + @brief constructor for a given JSON instance + @param[in] object pointer to a JSON object for this iterator + @pre object != nullptr + @post The iterator is initialized; i.e. `m_object != nullptr`. + */ + explicit iter_impl(pointer object) noexcept : m_object(object) + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + m_it.object_iterator = typename object_t::iterator(); + break; + } + + case value_t::array: + { + m_it.array_iterator = typename array_t::iterator(); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + m_it.primitive_iterator = primitive_iterator_t(); + break; + } + } + } + + /*! + @note The conventional copy constructor and copy assignment are implicitly + defined. Combined with the following converting constructor and + assignment, they support: (1) copy from iterator to iterator, (2) + copy from const iterator to const iterator, and (3) conversion from + iterator to const iterator. However conversion from const iterator + to iterator is not defined. + */ + + /*! + @brief const copy constructor + @param[in] other const iterator to copy from + @note This copy constructor had to be defined explicitly to circumvent a bug + occurring on msvc v19.0 compiler (VS 2015) debug build. For more + information refer to: https://github.com/nlohmann/json/issues/1608 + */ + iter_impl(const iter_impl& other) noexcept + : m_object(other.m_object), m_it(other.m_it) + {} + + /*! + @brief converting assignment + @param[in] other const iterator to copy from + @return const/non-const iterator + @note It is not checked whether @a other is initialized. + */ + iter_impl& operator=(const iter_impl& other) noexcept + { + if (&other != this) + { + m_object = other.m_object; + m_it = other.m_it; + } + return *this; + } + + /*! + @brief converting constructor + @param[in] other non-const iterator to copy from + @note It is not checked whether @a other is initialized. + */ + iter_impl(const iter_impl::type>& other) noexcept + : m_object(other.m_object), m_it(other.m_it) + {} + + /*! + @brief converting assignment + @param[in] other non-const iterator to copy from + @return const/non-const iterator + @note It is not checked whether @a other is initialized. + */ + iter_impl& operator=(const iter_impl::type>& other) noexcept // NOLINT(cert-oop54-cpp) + { + m_object = other.m_object; + m_it = other.m_it; + return *this; + } + + JSON_PRIVATE_UNLESS_TESTED: + /*! + @brief set the iterator to the first value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + void set_begin() noexcept + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + m_it.object_iterator = m_object->m_value.object->begin(); + break; + } + + case value_t::array: + { + m_it.array_iterator = m_object->m_value.array->begin(); + break; + } + + case value_t::null: + { + // set to end so begin()==end() is true: null is empty + m_it.primitive_iterator.set_end(); + break; + } + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + m_it.primitive_iterator.set_begin(); + break; + } + } + } + + /*! + @brief set the iterator past the last value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + void set_end() noexcept + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + m_it.object_iterator = m_object->m_value.object->end(); + break; + } + + case value_t::array: + { + m_it.array_iterator = m_object->m_value.array->end(); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + m_it.primitive_iterator.set_end(); + break; + } + } + } + + public: + /*! + @brief return a reference to the value pointed to by the iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference operator*() const + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); + return m_it.object_iterator->second; + } + + case value_t::array: + { + JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); + return *m_it.array_iterator; + } + + case value_t::null: + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) + { + return *m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + } + } + } + + /*! + @brief dereference the iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + pointer operator->() const + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); + return &(m_it.object_iterator->second); + } + + case value_t::array: + { + JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); + return &*m_it.array_iterator; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) + { + return m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + } + } + } + + /*! + @brief post-increment (it++) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp) + { + auto result = *this; + ++(*this); + return result; + } + + /*! + @brief pre-increment (++it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator++() + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + std::advance(m_it.object_iterator, 1); + break; + } + + case value_t::array: + { + std::advance(m_it.array_iterator, 1); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + ++m_it.primitive_iterator; + break; + } + } + + return *this; + } + + /*! + @brief post-decrement (it--) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp) + { + auto result = *this; + --(*this); + return result; + } + + /*! + @brief pre-decrement (--it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator--() + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + std::advance(m_it.object_iterator, -1); + break; + } + + case value_t::array: + { + std::advance(m_it.array_iterator, -1); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + --m_it.primitive_iterator; + break; + } + } + + return *this; + } + + /*! + @brief comparison: equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > + bool operator==(const IterImpl& other) const + { + // if objects are not the same, the comparison is undefined + if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) + { + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object)); + } + + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + return (m_it.object_iterator == other.m_it.object_iterator); + + case value_t::array: + return (m_it.array_iterator == other.m_it.array_iterator); + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return (m_it.primitive_iterator == other.m_it.primitive_iterator); + } + } + + /*! + @brief comparison: not equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > + bool operator!=(const IterImpl& other) const + { + return !operator==(other); + } + + /*! + @brief comparison: smaller + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator<(const iter_impl& other) const + { + // if objects are not the same, the comparison is undefined + if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) + { + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object)); + } + + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", *m_object)); + + case value_t::array: + return (m_it.array_iterator < other.m_it.array_iterator); + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return (m_it.primitive_iterator < other.m_it.primitive_iterator); + } + } + + /*! + @brief comparison: less than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator<=(const iter_impl& other) const + { + return !other.operator < (*this); + } + + /*! + @brief comparison: greater than + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator>(const iter_impl& other) const + { + return !operator<=(other); + } + + /*! + @brief comparison: greater than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator>=(const iter_impl& other) const + { + return !operator<(other); + } + + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator+=(difference_type i) + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object)); + + case value_t::array: + { + std::advance(m_it.array_iterator, i); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + m_it.primitive_iterator += i; + break; + } + } + + return *this; + } + + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator-=(difference_type i) + { + return operator+=(-i); + } + + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator+(difference_type i) const + { + auto result = *this; + result += i; + return result; + } + + /*! + @brief addition of distance and iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + friend iter_impl operator+(difference_type i, const iter_impl& it) + { + auto result = it; + result += i; + return result; + } + + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator-(difference_type i) const + { + auto result = *this; + result -= i; + return result; + } + + /*! + @brief return difference + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + difference_type operator-(const iter_impl& other) const + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object)); + + case value_t::array: + return m_it.array_iterator - other.m_it.array_iterator; + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return m_it.primitive_iterator - other.m_it.primitive_iterator; + } + } + + /*! + @brief access to successor + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference operator[](difference_type n) const + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", *m_object)); + + case value_t::array: + return *std::next(m_it.array_iterator, n); + + case value_t::null: + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) + { + return *m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + } + } + } + + /*! + @brief return the key of an object iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + const typename object_t::key_type& key() const + { + JSON_ASSERT(m_object != nullptr); + + if (JSON_HEDLEY_LIKELY(m_object->is_object())) + { + return m_it.object_iterator->first; + } + + JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", *m_object)); + } + + /*! + @brief return the value of an iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference value() const + { + return operator*(); + } + + JSON_PRIVATE_UNLESS_TESTED: + /// associated JSON instance + pointer m_object = nullptr; + /// the actual iterator of the associated instance + internal_iterator::type> m_it {}; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +#include // ptrdiff_t +#include // reverse_iterator +#include // declval + +namespace nlohmann +{ +namespace detail +{ +////////////////////// +// reverse_iterator // +////////////////////// + +/*! +@brief a template for a reverse iterator class + +@tparam Base the base iterator type to reverse. Valid types are @ref +iterator (to create @ref reverse_iterator) and @ref const_iterator (to +create @ref const_reverse_iterator). + +@requirement The class satisfies the following concept requirements: +- +[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): + The iterator that can be moved can be moved in both directions (i.e. + incremented and decremented). +- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator): + It is possible to write to the pointed-to element (only if @a Base is + @ref iterator). + +@since version 1.0.0 +*/ +template +class json_reverse_iterator : public std::reverse_iterator +{ + public: + using difference_type = std::ptrdiff_t; + /// shortcut to the reverse iterator adapter + using base_iterator = std::reverse_iterator; + /// the reference type for the pointed-to element + using reference = typename Base::reference; + + /// create reverse iterator from iterator + explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept + : base_iterator(it) {} + + /// create reverse iterator from base class + explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} + + /// post-increment (it++) + json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp) + { + return static_cast(base_iterator::operator++(1)); + } + + /// pre-increment (++it) + json_reverse_iterator& operator++() + { + return static_cast(base_iterator::operator++()); + } + + /// post-decrement (it--) + json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp) + { + return static_cast(base_iterator::operator--(1)); + } + + /// pre-decrement (--it) + json_reverse_iterator& operator--() + { + return static_cast(base_iterator::operator--()); + } + + /// add to iterator + json_reverse_iterator& operator+=(difference_type i) + { + return static_cast(base_iterator::operator+=(i)); + } + + /// add to iterator + json_reverse_iterator operator+(difference_type i) const + { + return static_cast(base_iterator::operator+(i)); + } + + /// subtract from iterator + json_reverse_iterator operator-(difference_type i) const + { + return static_cast(base_iterator::operator-(i)); + } + + /// return difference + difference_type operator-(const json_reverse_iterator& other) const + { + return base_iterator(*this) - base_iterator(other); + } + + /// access to successor + reference operator[](difference_type n) const + { + return *(this->operator+(n)); + } + + /// return the key of an object iterator + auto key() const -> decltype(std::declval().key()) + { + auto it = --this->base(); + return it.key(); + } + + /// return the value of an iterator + reference value() const + { + auto it = --this->base(); + return it.operator * (); + } +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +#include // all_of +#include // isdigit +#include // max +#include // accumulate +#include // string +#include // move +#include // vector + +// #include + +// #include + +// #include + +// #include + + +namespace nlohmann +{ + +/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document +/// @sa https://json.nlohmann.me/api/json_pointer/ +template +class json_pointer +{ + // allow basic_json to access private members + NLOHMANN_BASIC_JSON_TPL_DECLARATION + friend class basic_json; + + public: + /// @brief create JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/ + explicit json_pointer(const std::string& s = "") + : reference_tokens(split(s)) + {} + + /// @brief return a string representation of the JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/to_string/ + std::string to_string() const + { + return std::accumulate(reference_tokens.begin(), reference_tokens.end(), + std::string{}, + [](const std::string & a, const std::string & b) + { + return a + "/" + detail::escape(b); + }); + } + + /// @brief return a string representation of the JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/ + operator std::string() const + { + return to_string(); + } + + /// @brief append another JSON pointer at the end of this JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ + json_pointer& operator/=(const json_pointer& ptr) + { + reference_tokens.insert(reference_tokens.end(), + ptr.reference_tokens.begin(), + ptr.reference_tokens.end()); + return *this; + } + + /// @brief append an unescaped reference token at the end of this JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ + json_pointer& operator/=(std::string token) + { + push_back(std::move(token)); + return *this; + } + + /// @brief append an array index at the end of this JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ + json_pointer& operator/=(std::size_t array_idx) + { + return *this /= std::to_string(array_idx); + } + + /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ + friend json_pointer operator/(const json_pointer& lhs, + const json_pointer& rhs) + { + return json_pointer(lhs) /= rhs; + } + + /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ + friend json_pointer operator/(const json_pointer& lhs, std::string token) // NOLINT(performance-unnecessary-value-param) + { + return json_pointer(lhs) /= std::move(token); + } + + /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ + friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx) + { + return json_pointer(lhs) /= array_idx; + } + + /// @brief returns the parent of this JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/ + json_pointer parent_pointer() const + { + if (empty()) + { + return *this; + } + + json_pointer res = *this; + res.pop_back(); + return res; + } + + /// @brief remove last reference token + /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/ + void pop_back() + { + if (JSON_HEDLEY_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); + } + + reference_tokens.pop_back(); + } + + /// @brief return last reference token + /// @sa https://json.nlohmann.me/api/json_pointer/back/ + const std::string& back() const + { + if (JSON_HEDLEY_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); + } + + return reference_tokens.back(); + } + + /// @brief append an unescaped token at the end of the reference pointer + /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ + void push_back(const std::string& token) + { + reference_tokens.push_back(token); + } + + /// @brief append an unescaped token at the end of the reference pointer + /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ + void push_back(std::string&& token) + { + reference_tokens.push_back(std::move(token)); + } + + /// @brief return whether pointer points to the root document + /// @sa https://json.nlohmann.me/api/json_pointer/empty/ + bool empty() const noexcept + { + return reference_tokens.empty(); + } + + private: + /*! + @param[in] s reference token to be converted into an array index + + @return integer representation of @a s + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index begins not with a digit + @throw out_of_range.404 if string @a s could not be converted to an integer + @throw out_of_range.410 if an array index exceeds size_type + */ + static typename BasicJsonType::size_type array_index(const std::string& s) + { + using size_type = typename BasicJsonType::size_type; + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) + { + JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'", BasicJsonType())); + } + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number", BasicJsonType())); + } + + std::size_t processed_chars = 0; + unsigned long long res = 0; // NOLINT(runtime/int) + JSON_TRY + { + res = std::stoull(s, &processed_chars); + } + JSON_CATCH(std::out_of_range&) + { + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType())); + } + + // check if the string was completely read + if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size())) + { + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType())); + } + + // only triggered on special platforms (like 32bit), see also + // https://github.com/nlohmann/json/pull/2203 + if (res >= static_cast((std::numeric_limits::max)())) // NOLINT(runtime/int) + { + JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type", BasicJsonType())); // LCOV_EXCL_LINE + } + + return static_cast(res); + } + + JSON_PRIVATE_UNLESS_TESTED: + json_pointer top() const + { + if (JSON_HEDLEY_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); + } + + json_pointer result = *this; + result.reference_tokens = {reference_tokens[0]}; + return result; + } + + private: + /*! + @brief create and return a reference to the pointed to value + + @complexity Linear in the number of reference tokens. + + @throw parse_error.109 if array index is not a number + @throw type_error.313 if value cannot be unflattened + */ + BasicJsonType& get_and_create(BasicJsonType& j) const + { + auto* result = &j; + + // in case no reference tokens exist, return a reference to the JSON value + // j which will be overwritten by a primitive value + for (const auto& reference_token : reference_tokens) + { + switch (result->type()) + { + case detail::value_t::null: + { + if (reference_token == "0") + { + // start a new array if reference token is 0 + result = &result->operator[](0); + } + else + { + // start a new object otherwise + result = &result->operator[](reference_token); + } + break; + } + + case detail::value_t::object: + { + // create an entry in the object + result = &result->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + // create an entry in the array + result = &result->operator[](array_index(reference_token)); + break; + } + + /* + The following code is only reached if there exists a reference + token _and_ the current value is primitive. In this case, we have + an error situation, because primitive values may only occur as + single value; that is, with an empty list of reference tokens. + */ + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", j)); + } + } + + return *result; + } + + /*! + @brief return a reference to the pointed to value + + @note This version does not throw if a value is not present, but tries to + create nested values instead. For instance, calling this function + with pointer `"/this/that"` on a null value is equivalent to calling + `operator[]("this").operator[]("that")` on that value, effectively + changing the null value to an object. + + @param[in] ptr a JSON value + + @return reference to the JSON value pointed to by the JSON pointer + + @complexity Linear in the length of the JSON pointer. + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + BasicJsonType& get_unchecked(BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + // convert null values to arrays or objects before continuing + if (ptr->is_null()) + { + // check if reference token is a number + const bool nums = + std::all_of(reference_token.begin(), reference_token.end(), + [](const unsigned char x) + { + return std::isdigit(x); + }); + + // change value to array for numbers or "-" or to object otherwise + *ptr = (nums || reference_token == "-") + ? detail::value_t::array + : detail::value_t::object; + } + + switch (ptr->type()) + { + case detail::value_t::object: + { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + if (reference_token == "-") + { + // explicitly treat "-" as index beyond the end + ptr = &ptr->operator[](ptr->m_value.array->size()); + } + else + { + // convert array index to number; unchecked access + ptr = &ptr->operator[](array_index(reference_token)); + } + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); + } + } + + return *ptr; + } + + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + BasicJsonType& get_checked(BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + JSON_THROW(detail::out_of_range::create(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range", *ptr)); + } + + // note: at performs range check + ptr = &ptr->at(array_index(reference_token)); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); + } + } + + return *ptr; + } + + /*! + @brief return a const reference to the pointed to value + + @param[in] ptr a JSON value + + @return const reference to the JSON value pointed to by the JSON + pointer + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" cannot be used for const access + JSON_THROW(detail::out_of_range::create(402, "array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range", *ptr)); + } + + // use unchecked array access + ptr = &ptr->operator[](array_index(reference_token)); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); + } + } + + return *ptr; + } + + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + const BasicJsonType& get_checked(const BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + JSON_THROW(detail::out_of_range::create(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range", *ptr)); + } + + // note: at performs range check + ptr = &ptr->at(array_index(reference_token)); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); + } + } + + return *ptr; + } + + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + */ + bool contains(const BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + if (!ptr->contains(reference_token)) + { + // we did not find the key in the object + return false; + } + + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + return false; + } + if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9"))) + { + // invalid char + return false; + } + if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) + { + if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9'))) + { + // first char should be between '1' and '9' + return false; + } + for (std::size_t i = 1; i < reference_token.size(); i++) + { + if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9'))) + { + // other char should be between '0' and '9' + return false; + } + } + } + + const auto idx = array_index(reference_token); + if (idx >= ptr->size()) + { + // index out of range + return false; + } + + ptr = &ptr->operator[](idx); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + { + // we do not expect primitive values if there is still a + // reference token to process + return false; + } + } + } + + // no reference token left means we found a primitive value + return true; + } + + /*! + @brief split the string input to reference tokens + + @note This function is only called by the json_pointer constructor. + All exceptions below are documented there. + + @throw parse_error.107 if the pointer is not empty or begins with '/' + @throw parse_error.108 if character '~' is not followed by '0' or '1' + */ + static std::vector split(const std::string& reference_string) + { + std::vector result; + + // special case: empty reference string -> no reference tokens + if (reference_string.empty()) + { + return result; + } + + // check if nonempty reference string begins with slash + if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) + { + JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'", BasicJsonType())); + } + + // extract the reference tokens: + // - slash: position of the last read slash (or end of string) + // - start: position after the previous slash + for ( + // search for the first slash after the first character + std::size_t slash = reference_string.find_first_of('/', 1), + // set the beginning of the first reference token + start = 1; + // we can stop if start == 0 (if slash == std::string::npos) + start != 0; + // set the beginning of the next reference token + // (will eventually be 0 if slash == std::string::npos) + start = (slash == std::string::npos) ? 0 : slash + 1, + // find next slash + slash = reference_string.find_first_of('/', start)) + { + // use the text between the beginning of the reference token + // (start) and the last slash (slash). + auto reference_token = reference_string.substr(start, slash - start); + + // check reference tokens are properly escaped + for (std::size_t pos = reference_token.find_first_of('~'); + pos != std::string::npos; + pos = reference_token.find_first_of('~', pos + 1)) + { + JSON_ASSERT(reference_token[pos] == '~'); + + // ~ must be followed by 0 or 1 + if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 || + (reference_token[pos + 1] != '0' && + reference_token[pos + 1] != '1'))) + { + JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", BasicJsonType())); + } + } + + // finally, store the reference token + detail::unescape(reference_token); + result.push_back(reference_token); + } + + return result; + } + + private: + /*! + @param[in] reference_string the reference string to the current value + @param[in] value the value to consider + @param[in,out] result the result object to insert values to + + @note Empty objects or arrays are flattened to `null`. + */ + static void flatten(const std::string& reference_string, + const BasicJsonType& value, + BasicJsonType& result) + { + switch (value.type()) + { + case detail::value_t::array: + { + if (value.m_value.array->empty()) + { + // flatten empty array as null + result[reference_string] = nullptr; + } + else + { + // iterate array and use index as reference string + for (std::size_t i = 0; i < value.m_value.array->size(); ++i) + { + flatten(reference_string + "/" + std::to_string(i), + value.m_value.array->operator[](i), result); + } + } + break; + } + + case detail::value_t::object: + { + if (value.m_value.object->empty()) + { + // flatten empty object as null + result[reference_string] = nullptr; + } + else + { + // iterate object and use keys as reference string + for (const auto& element : *value.m_value.object) + { + flatten(reference_string + "/" + detail::escape(element.first), element.second, result); + } + } + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + { + // add primitive value with its reference string + result[reference_string] = value; + break; + } + } + } + + /*! + @param[in] value flattened JSON + + @return unflattened JSON + + @throw parse_error.109 if array index is not a number + @throw type_error.314 if value is not an object + @throw type_error.315 if object values are not primitive + @throw type_error.313 if value cannot be unflattened + */ + static BasicJsonType + unflatten(const BasicJsonType& value) + { + if (JSON_HEDLEY_UNLIKELY(!value.is_object())) + { + JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", value)); + } + + BasicJsonType result; + + // iterate the JSON object values + for (const auto& element : *value.m_value.object) + { + if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) + { + JSON_THROW(detail::type_error::create(315, "values in object must be primitive", element.second)); + } + + // assign value to reference pointed to by JSON pointer; Note that if + // the JSON pointer is "" (i.e., points to the whole value), function + // get_and_create returns a reference to result itself. An assignment + // will then create a primitive value. + json_pointer(element.first).get_and_create(result) = element.second; + } + + return result; + } + + /*! + @brief compares two JSON pointers for equality + + @param[in] lhs JSON pointer to compare + @param[in] rhs JSON pointer to compare + @return whether @a lhs is equal to @a rhs + + @complexity Linear in the length of the JSON pointer + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + */ + friend bool operator==(json_pointer const& lhs, + json_pointer const& rhs) noexcept + { + return lhs.reference_tokens == rhs.reference_tokens; + } + + /*! + @brief compares two JSON pointers for inequality + + @param[in] lhs JSON pointer to compare + @param[in] rhs JSON pointer to compare + @return whether @a lhs is not equal @a rhs + + @complexity Linear in the length of the JSON pointer + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + */ + friend bool operator!=(json_pointer const& lhs, + json_pointer const& rhs) noexcept + { + return !(lhs == rhs); + } + + /// the reference tokens + std::vector reference_tokens; +}; +} // namespace nlohmann + +// #include + + +#include +#include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template +class json_ref +{ + public: + using value_type = BasicJsonType; + + json_ref(value_type&& value) + : owned_value(std::move(value)) + {} + + json_ref(const value_type& value) + : value_ref(&value) + {} + + json_ref(std::initializer_list init) + : owned_value(init) + {} + + template < + class... Args, + enable_if_t::value, int> = 0 > + json_ref(Args && ... args) + : owned_value(std::forward(args)...) + {} + + // class should be movable only + json_ref(json_ref&&) noexcept = default; + json_ref(const json_ref&) = delete; + json_ref& operator=(const json_ref&) = delete; + json_ref& operator=(json_ref&&) = delete; + ~json_ref() = default; + + value_type moved_or_copied() const + { + if (value_ref == nullptr) + { + return std::move(owned_value); + } + return *value_ref; + } + + value_type const& operator*() const + { + return value_ref ? *value_ref : owned_value; + } + + value_type const* operator->() const + { + return &** this; + } + + private: + mutable value_type owned_value = nullptr; + value_type const* value_ref = nullptr; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + +// #include + +// #include + +// #include + + +#include // reverse +#include // array +#include // isnan, isinf +#include // uint8_t, uint16_t, uint32_t, uint64_t +#include // memcpy +#include // numeric_limits +#include // string +#include // move + +// #include + +// #include + +// #include + + +#include // copy +#include // size_t +#include // back_inserter +#include // shared_ptr, make_shared +#include // basic_string +#include // vector + +#ifndef JSON_NO_IO + #include // streamsize + #include // basic_ostream +#endif // JSON_NO_IO + +// #include + + +namespace nlohmann +{ +namespace detail +{ +/// abstract output adapter interface +template struct output_adapter_protocol +{ + virtual void write_character(CharType c) = 0; + virtual void write_characters(const CharType* s, std::size_t length) = 0; + virtual ~output_adapter_protocol() = default; + + output_adapter_protocol() = default; + output_adapter_protocol(const output_adapter_protocol&) = default; + output_adapter_protocol(output_adapter_protocol&&) noexcept = default; + output_adapter_protocol& operator=(const output_adapter_protocol&) = default; + output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default; +}; + +/// a type to simplify interfaces +template +using output_adapter_t = std::shared_ptr>; + +/// output adapter for byte vectors +template> +class output_vector_adapter : public output_adapter_protocol +{ + public: + explicit output_vector_adapter(std::vector& vec) noexcept + : v(vec) + {} + + void write_character(CharType c) override + { + v.push_back(c); + } + + JSON_HEDLEY_NON_NULL(2) + void write_characters(const CharType* s, std::size_t length) override + { + std::copy(s, s + length, std::back_inserter(v)); + } + + private: + std::vector& v; +}; + +#ifndef JSON_NO_IO +/// output adapter for output streams +template +class output_stream_adapter : public output_adapter_protocol +{ + public: + explicit output_stream_adapter(std::basic_ostream& s) noexcept + : stream(s) + {} + + void write_character(CharType c) override + { + stream.put(c); + } + + JSON_HEDLEY_NON_NULL(2) + void write_characters(const CharType* s, std::size_t length) override + { + stream.write(s, static_cast(length)); + } + + private: + std::basic_ostream& stream; +}; +#endif // JSON_NO_IO + +/// output adapter for basic_string +template> +class output_string_adapter : public output_adapter_protocol +{ + public: + explicit output_string_adapter(StringType& s) noexcept + : str(s) + {} + + void write_character(CharType c) override + { + str.push_back(c); + } + + JSON_HEDLEY_NON_NULL(2) + void write_characters(const CharType* s, std::size_t length) override + { + str.append(s, length); + } + + private: + StringType& str; +}; + +template> +class output_adapter +{ + public: + template> + output_adapter(std::vector& vec) + : oa(std::make_shared>(vec)) {} + +#ifndef JSON_NO_IO + output_adapter(std::basic_ostream& s) + : oa(std::make_shared>(s)) {} +#endif // JSON_NO_IO + + output_adapter(StringType& s) + : oa(std::make_shared>(s)) {} + + operator output_adapter_t() + { + return oa; + } + + private: + output_adapter_t oa = nullptr; +}; +} // namespace detail +} // namespace nlohmann + + +namespace nlohmann +{ +namespace detail +{ +/////////////////// +// binary writer // +/////////////////// + +/*! +@brief serialization to CBOR and MessagePack values +*/ +template +class binary_writer +{ + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using number_float_t = typename BasicJsonType::number_float_t; + + public: + /*! + @brief create a binary writer + + @param[in] adapter output adapter to write to + */ + explicit binary_writer(output_adapter_t adapter) : oa(std::move(adapter)) + { + JSON_ASSERT(oa); + } + + /*! + @param[in] j JSON value to serialize + @pre j.type() == value_t::object + */ + void write_bson(const BasicJsonType& j) + { + switch (j.type()) + { + case value_t::object: + { + write_bson_object(*j.m_value.object); + break; + } + + case value_t::null: + case value_t::array: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()), j)); + } + } + } + + /*! + @param[in] j JSON value to serialize + */ + void write_cbor(const BasicJsonType& j) + { + switch (j.type()) + { + case value_t::null: + { + oa->write_character(to_char_type(0xF6)); + break; + } + + case value_t::boolean: + { + oa->write_character(j.m_value.boolean + ? to_char_type(0xF5) + : to_char_type(0xF4)); + break; + } + + case value_t::number_integer: + { + if (j.m_value.number_integer >= 0) + { + // CBOR does not differentiate between positive signed + // integers and unsigned integers. Therefore, we used the + // code from the value_t::number_unsigned case here. + if (j.m_value.number_integer <= 0x17) + { + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x18)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x19)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x1A)); + write_number(static_cast(j.m_value.number_integer)); + } + else + { + oa->write_character(to_char_type(0x1B)); + write_number(static_cast(j.m_value.number_integer)); + } + } + else + { + // The conversions below encode the sign in the first + // byte, and the value is converted to a positive number. + const auto positive_number = -1 - j.m_value.number_integer; + if (j.m_value.number_integer >= -24) + { + write_number(static_cast(0x20 + positive_number)); + } + else if (positive_number <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x38)); + write_number(static_cast(positive_number)); + } + else if (positive_number <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x39)); + write_number(static_cast(positive_number)); + } + else if (positive_number <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x3A)); + write_number(static_cast(positive_number)); + } + else + { + oa->write_character(to_char_type(0x3B)); + write_number(static_cast(positive_number)); + } + } + break; + } + + case value_t::number_unsigned: + { + if (j.m_value.number_unsigned <= 0x17) + { + write_number(static_cast(j.m_value.number_unsigned)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x18)); + write_number(static_cast(j.m_value.number_unsigned)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x19)); + write_number(static_cast(j.m_value.number_unsigned)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x1A)); + write_number(static_cast(j.m_value.number_unsigned)); + } + else + { + oa->write_character(to_char_type(0x1B)); + write_number(static_cast(j.m_value.number_unsigned)); + } + break; + } + + case value_t::number_float: + { + if (std::isnan(j.m_value.number_float)) + { + // NaN is 0xf97e00 in CBOR + oa->write_character(to_char_type(0xF9)); + oa->write_character(to_char_type(0x7E)); + oa->write_character(to_char_type(0x00)); + } + else if (std::isinf(j.m_value.number_float)) + { + // Infinity is 0xf97c00, -Infinity is 0xf9fc00 + oa->write_character(to_char_type(0xf9)); + oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); + oa->write_character(to_char_type(0x00)); + } + else + { + write_compact_float(j.m_value.number_float, detail::input_format_t::cbor); + } + break; + } + + case value_t::string: + { + // step 1: write control byte and the string length + const auto N = j.m_value.string->size(); + if (N <= 0x17) + { + write_number(static_cast(0x60 + N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x78)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x79)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x7A)); + write_number(static_cast(N)); + } + // LCOV_EXCL_START + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x7B)); + write_number(static_cast(N)); + } + // LCOV_EXCL_STOP + + // step 2: write the string + oa->write_characters( + reinterpret_cast(j.m_value.string->c_str()), + j.m_value.string->size()); + break; + } + + case value_t::array: + { + // step 1: write control byte and the array size + const auto N = j.m_value.array->size(); + if (N <= 0x17) + { + write_number(static_cast(0x80 + N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x98)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x99)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x9A)); + write_number(static_cast(N)); + } + // LCOV_EXCL_START + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x9B)); + write_number(static_cast(N)); + } + // LCOV_EXCL_STOP + + // step 2: write each element + for (const auto& el : *j.m_value.array) + { + write_cbor(el); + } + break; + } + + case value_t::binary: + { + if (j.m_value.binary->has_subtype()) + { + if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + { + write_number(static_cast(0xd8)); + write_number(static_cast(j.m_value.binary->subtype())); + } + else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + { + write_number(static_cast(0xd9)); + write_number(static_cast(j.m_value.binary->subtype())); + } + else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + { + write_number(static_cast(0xda)); + write_number(static_cast(j.m_value.binary->subtype())); + } + else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + { + write_number(static_cast(0xdb)); + write_number(static_cast(j.m_value.binary->subtype())); + } + } + + // step 1: write control byte and the binary array size + const auto N = j.m_value.binary->size(); + if (N <= 0x17) + { + write_number(static_cast(0x40 + N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x58)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x59)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x5A)); + write_number(static_cast(N)); + } + // LCOV_EXCL_START + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x5B)); + write_number(static_cast(N)); + } + // LCOV_EXCL_STOP + + // step 2: write each element + oa->write_characters( + reinterpret_cast(j.m_value.binary->data()), + N); + + break; + } + + case value_t::object: + { + // step 1: write control byte and the object size + const auto N = j.m_value.object->size(); + if (N <= 0x17) + { + write_number(static_cast(0xA0 + N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0xB8)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0xB9)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0xBA)); + write_number(static_cast(N)); + } + // LCOV_EXCL_START + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0xBB)); + write_number(static_cast(N)); + } + // LCOV_EXCL_STOP + + // step 2: write each element + for (const auto& el : *j.m_value.object) + { + write_cbor(el.first); + write_cbor(el.second); + } + break; + } + + case value_t::discarded: + default: + break; + } + } + + /*! + @param[in] j JSON value to serialize + */ + void write_msgpack(const BasicJsonType& j) + { + switch (j.type()) + { + case value_t::null: // nil + { + oa->write_character(to_char_type(0xC0)); + break; + } + + case value_t::boolean: // true and false + { + oa->write_character(j.m_value.boolean + ? to_char_type(0xC3) + : to_char_type(0xC2)); + break; + } + + case value_t::number_integer: + { + if (j.m_value.number_integer >= 0) + { + // MessagePack does not differentiate between positive + // signed integers and unsigned integers. Therefore, we used + // the code from the value_t::number_unsigned case here. + if (j.m_value.number_unsigned < 128) + { + // positive fixnum + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 8 + oa->write_character(to_char_type(0xCC)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 16 + oa->write_character(to_char_type(0xCD)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 32 + oa->write_character(to_char_type(0xCE)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 64 + oa->write_character(to_char_type(0xCF)); + write_number(static_cast(j.m_value.number_integer)); + } + } + else + { + if (j.m_value.number_integer >= -32) + { + // negative fixnum + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) + { + // int 8 + oa->write_character(to_char_type(0xD0)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) + { + // int 16 + oa->write_character(to_char_type(0xD1)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) + { + // int 32 + oa->write_character(to_char_type(0xD2)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) + { + // int 64 + oa->write_character(to_char_type(0xD3)); + write_number(static_cast(j.m_value.number_integer)); + } + } + break; + } + + case value_t::number_unsigned: + { + if (j.m_value.number_unsigned < 128) + { + // positive fixnum + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 8 + oa->write_character(to_char_type(0xCC)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 16 + oa->write_character(to_char_type(0xCD)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 32 + oa->write_character(to_char_type(0xCE)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 64 + oa->write_character(to_char_type(0xCF)); + write_number(static_cast(j.m_value.number_integer)); + } + break; + } + + case value_t::number_float: + { + write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack); + break; + } + + case value_t::string: + { + // step 1: write control byte and the string length + const auto N = j.m_value.string->size(); + if (N <= 31) + { + // fixstr + write_number(static_cast(0xA0 | N)); + } + else if (N <= (std::numeric_limits::max)()) + { + // str 8 + oa->write_character(to_char_type(0xD9)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + // str 16 + oa->write_character(to_char_type(0xDA)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + // str 32 + oa->write_character(to_char_type(0xDB)); + write_number(static_cast(N)); + } + + // step 2: write the string + oa->write_characters( + reinterpret_cast(j.m_value.string->c_str()), + j.m_value.string->size()); + break; + } + + case value_t::array: + { + // step 1: write control byte and the array size + const auto N = j.m_value.array->size(); + if (N <= 15) + { + // fixarray + write_number(static_cast(0x90 | N)); + } + else if (N <= (std::numeric_limits::max)()) + { + // array 16 + oa->write_character(to_char_type(0xDC)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + // array 32 + oa->write_character(to_char_type(0xDD)); + write_number(static_cast(N)); + } + + // step 2: write each element + for (const auto& el : *j.m_value.array) + { + write_msgpack(el); + } + break; + } + + case value_t::binary: + { + // step 0: determine if the binary type has a set subtype to + // determine whether or not to use the ext or fixext types + const bool use_ext = j.m_value.binary->has_subtype(); + + // step 1: write control byte and the byte string length + const auto N = j.m_value.binary->size(); + if (N <= (std::numeric_limits::max)()) + { + std::uint8_t output_type{}; + bool fixed = true; + if (use_ext) + { + switch (N) + { + case 1: + output_type = 0xD4; // fixext 1 + break; + case 2: + output_type = 0xD5; // fixext 2 + break; + case 4: + output_type = 0xD6; // fixext 4 + break; + case 8: + output_type = 0xD7; // fixext 8 + break; + case 16: + output_type = 0xD8; // fixext 16 + break; + default: + output_type = 0xC7; // ext 8 + fixed = false; + break; + } + + } + else + { + output_type = 0xC4; // bin 8 + fixed = false; + } + + oa->write_character(to_char_type(output_type)); + if (!fixed) + { + write_number(static_cast(N)); + } + } + else if (N <= (std::numeric_limits::max)()) + { + std::uint8_t output_type = use_ext + ? 0xC8 // ext 16 + : 0xC5; // bin 16 + + oa->write_character(to_char_type(output_type)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + std::uint8_t output_type = use_ext + ? 0xC9 // ext 32 + : 0xC6; // bin 32 + + oa->write_character(to_char_type(output_type)); + write_number(static_cast(N)); + } + + // step 1.5: if this is an ext type, write the subtype + if (use_ext) + { + write_number(static_cast(j.m_value.binary->subtype())); + } + + // step 2: write the byte string + oa->write_characters( + reinterpret_cast(j.m_value.binary->data()), + N); + + break; + } + + case value_t::object: + { + // step 1: write control byte and the object size + const auto N = j.m_value.object->size(); + if (N <= 15) + { + // fixmap + write_number(static_cast(0x80 | (N & 0xF))); + } + else if (N <= (std::numeric_limits::max)()) + { + // map 16 + oa->write_character(to_char_type(0xDE)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + // map 32 + oa->write_character(to_char_type(0xDF)); + write_number(static_cast(N)); + } + + // step 2: write each element + for (const auto& el : *j.m_value.object) + { + write_msgpack(el.first); + write_msgpack(el.second); + } + break; + } + + case value_t::discarded: + default: + break; + } + } + + /*! + @param[in] j JSON value to serialize + @param[in] use_count whether to use '#' prefixes (optimized format) + @param[in] use_type whether to use '$' prefixes (optimized format) + @param[in] add_prefix whether prefixes need to be used for this value + */ + void write_ubjson(const BasicJsonType& j, const bool use_count, + const bool use_type, const bool add_prefix = true) + { + switch (j.type()) + { + case value_t::null: + { + if (add_prefix) + { + oa->write_character(to_char_type('Z')); + } + break; + } + + case value_t::boolean: + { + if (add_prefix) + { + oa->write_character(j.m_value.boolean + ? to_char_type('T') + : to_char_type('F')); + } + break; + } + + case value_t::number_integer: + { + write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix); + break; + } + + case value_t::number_unsigned: + { + write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix); + break; + } + + case value_t::number_float: + { + write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix); + break; + } + + case value_t::string: + { + if (add_prefix) + { + oa->write_character(to_char_type('S')); + } + write_number_with_ubjson_prefix(j.m_value.string->size(), true); + oa->write_characters( + reinterpret_cast(j.m_value.string->c_str()), + j.m_value.string->size()); + break; + } + + case value_t::array: + { + if (add_prefix) + { + oa->write_character(to_char_type('[')); + } + + bool prefix_required = true; + if (use_type && !j.m_value.array->empty()) + { + JSON_ASSERT(use_count); + const CharType first_prefix = ubjson_prefix(j.front()); + const bool same_prefix = std::all_of(j.begin() + 1, j.end(), + [this, first_prefix](const BasicJsonType & v) + { + return ubjson_prefix(v) == first_prefix; + }); + + if (same_prefix) + { + prefix_required = false; + oa->write_character(to_char_type('$')); + oa->write_character(first_prefix); + } + } + + if (use_count) + { + oa->write_character(to_char_type('#')); + write_number_with_ubjson_prefix(j.m_value.array->size(), true); + } + + for (const auto& el : *j.m_value.array) + { + write_ubjson(el, use_count, use_type, prefix_required); + } + + if (!use_count) + { + oa->write_character(to_char_type(']')); + } + + break; + } + + case value_t::binary: + { + if (add_prefix) + { + oa->write_character(to_char_type('[')); + } + + if (use_type && !j.m_value.binary->empty()) + { + JSON_ASSERT(use_count); + oa->write_character(to_char_type('$')); + oa->write_character('U'); + } + + if (use_count) + { + oa->write_character(to_char_type('#')); + write_number_with_ubjson_prefix(j.m_value.binary->size(), true); + } + + if (use_type) + { + oa->write_characters( + reinterpret_cast(j.m_value.binary->data()), + j.m_value.binary->size()); + } + else + { + for (size_t i = 0; i < j.m_value.binary->size(); ++i) + { + oa->write_character(to_char_type('U')); + oa->write_character(j.m_value.binary->data()[i]); + } + } + + if (!use_count) + { + oa->write_character(to_char_type(']')); + } + + break; + } + + case value_t::object: + { + if (add_prefix) + { + oa->write_character(to_char_type('{')); + } + + bool prefix_required = true; + if (use_type && !j.m_value.object->empty()) + { + JSON_ASSERT(use_count); + const CharType first_prefix = ubjson_prefix(j.front()); + const bool same_prefix = std::all_of(j.begin(), j.end(), + [this, first_prefix](const BasicJsonType & v) + { + return ubjson_prefix(v) == first_prefix; + }); + + if (same_prefix) + { + prefix_required = false; + oa->write_character(to_char_type('$')); + oa->write_character(first_prefix); + } + } + + if (use_count) + { + oa->write_character(to_char_type('#')); + write_number_with_ubjson_prefix(j.m_value.object->size(), true); + } + + for (const auto& el : *j.m_value.object) + { + write_number_with_ubjson_prefix(el.first.size(), true); + oa->write_characters( + reinterpret_cast(el.first.c_str()), + el.first.size()); + write_ubjson(el.second, use_count, use_type, prefix_required); + } + + if (!use_count) + { + oa->write_character(to_char_type('}')); + } + + break; + } + + case value_t::discarded: + default: + break; + } + } + + private: + ////////// + // BSON // + ////////// + + /*! + @return The size of a BSON document entry header, including the id marker + and the entry name size (and its null-terminator). + */ + static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j) + { + const auto it = name.find(static_cast(0)); + if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos)) + { + JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", j)); + static_cast(j); + } + + return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; + } + + /*! + @brief Writes the given @a element_type and @a name to the output adapter + */ + void write_bson_entry_header(const string_t& name, + const std::uint8_t element_type) + { + oa->write_character(to_char_type(element_type)); // boolean + oa->write_characters( + reinterpret_cast(name.c_str()), + name.size() + 1u); + } + + /*! + @brief Writes a BSON element with key @a name and boolean value @a value + */ + void write_bson_boolean(const string_t& name, + const bool value) + { + write_bson_entry_header(name, 0x08); + oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00)); + } + + /*! + @brief Writes a BSON element with key @a name and double value @a value + */ + void write_bson_double(const string_t& name, + const double value) + { + write_bson_entry_header(name, 0x01); + write_number(value); + } + + /*! + @return The size of the BSON-encoded string in @a value + */ + static std::size_t calc_bson_string_size(const string_t& value) + { + return sizeof(std::int32_t) + value.size() + 1ul; + } + + /*! + @brief Writes a BSON element with key @a name and string value @a value + */ + void write_bson_string(const string_t& name, + const string_t& value) + { + write_bson_entry_header(name, 0x02); + + write_number(static_cast(value.size() + 1ul)); + oa->write_characters( + reinterpret_cast(value.c_str()), + value.size() + 1); + } + + /*! + @brief Writes a BSON element with key @a name and null value + */ + void write_bson_null(const string_t& name) + { + write_bson_entry_header(name, 0x0A); + } + + /*! + @return The size of the BSON-encoded integer @a value + */ + static std::size_t calc_bson_integer_size(const std::int64_t value) + { + return (std::numeric_limits::min)() <= value && value <= (std::numeric_limits::max)() + ? sizeof(std::int32_t) + : sizeof(std::int64_t); + } + + /*! + @brief Writes a BSON element with key @a name and integer @a value + */ + void write_bson_integer(const string_t& name, + const std::int64_t value) + { + if ((std::numeric_limits::min)() <= value && value <= (std::numeric_limits::max)()) + { + write_bson_entry_header(name, 0x10); // int32 + write_number(static_cast(value)); + } + else + { + write_bson_entry_header(name, 0x12); // int64 + write_number(static_cast(value)); + } + } + + /*! + @return The size of the BSON-encoded unsigned integer in @a j + */ + static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept + { + return (value <= static_cast((std::numeric_limits::max)())) + ? sizeof(std::int32_t) + : sizeof(std::int64_t); + } + + /*! + @brief Writes a BSON element with key @a name and unsigned @a value + */ + void write_bson_unsigned(const string_t& name, + const BasicJsonType& j) + { + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + write_bson_entry_header(name, 0x10 /* int32 */); + write_number(static_cast(j.m_value.number_unsigned)); + } + else if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + write_bson_entry_header(name, 0x12 /* int64 */); + write_number(static_cast(j.m_value.number_unsigned)); + } + else + { + JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(j.m_value.number_unsigned) + " cannot be represented by BSON as it does not fit int64", j)); + } + } + + /*! + @brief Writes a BSON element with key @a name and object @a value + */ + void write_bson_object_entry(const string_t& name, + const typename BasicJsonType::object_t& value) + { + write_bson_entry_header(name, 0x03); // object + write_bson_object(value); + } + + /*! + @return The size of the BSON-encoded array @a value + */ + static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value) + { + std::size_t array_index = 0ul; + + const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el) + { + return result + calc_bson_element_size(std::to_string(array_index++), el); + }); + + return sizeof(std::int32_t) + embedded_document_size + 1ul; + } + + /*! + @return The size of the BSON-encoded binary array @a value + */ + static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value) + { + return sizeof(std::int32_t) + value.size() + 1ul; + } + + /*! + @brief Writes a BSON element with key @a name and array @a value + */ + void write_bson_array(const string_t& name, + const typename BasicJsonType::array_t& value) + { + write_bson_entry_header(name, 0x04); // array + write_number(static_cast(calc_bson_array_size(value))); + + std::size_t array_index = 0ul; + + for (const auto& el : value) + { + write_bson_element(std::to_string(array_index++), el); + } + + oa->write_character(to_char_type(0x00)); + } + + /*! + @brief Writes a BSON element with key @a name and binary value @a value + */ + void write_bson_binary(const string_t& name, + const binary_t& value) + { + write_bson_entry_header(name, 0x05); + + write_number(static_cast(value.size())); + write_number(value.has_subtype() ? static_cast(value.subtype()) : static_cast(0x00)); + + oa->write_characters(reinterpret_cast(value.data()), value.size()); + } + + /*! + @brief Calculates the size necessary to serialize the JSON value @a j with its @a name + @return The calculated size for the BSON document entry for @a j with the given @a name. + */ + static std::size_t calc_bson_element_size(const string_t& name, + const BasicJsonType& j) + { + const auto header_size = calc_bson_entry_header_size(name, j); + switch (j.type()) + { + case value_t::object: + return header_size + calc_bson_object_size(*j.m_value.object); + + case value_t::array: + return header_size + calc_bson_array_size(*j.m_value.array); + + case value_t::binary: + return header_size + calc_bson_binary_size(*j.m_value.binary); + + case value_t::boolean: + return header_size + 1ul; + + case value_t::number_float: + return header_size + 8ul; + + case value_t::number_integer: + return header_size + calc_bson_integer_size(j.m_value.number_integer); + + case value_t::number_unsigned: + return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned); + + case value_t::string: + return header_size + calc_bson_string_size(*j.m_value.string); + + case value_t::null: + return header_size + 0ul; + + // LCOV_EXCL_START + case value_t::discarded: + default: + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + return 0ul; + // LCOV_EXCL_STOP + } + } + + /*! + @brief Serializes the JSON value @a j to BSON and associates it with the + key @a name. + @param name The name to associate with the JSON entity @a j within the + current BSON document + */ + void write_bson_element(const string_t& name, + const BasicJsonType& j) + { + switch (j.type()) + { + case value_t::object: + return write_bson_object_entry(name, *j.m_value.object); + + case value_t::array: + return write_bson_array(name, *j.m_value.array); + + case value_t::binary: + return write_bson_binary(name, *j.m_value.binary); + + case value_t::boolean: + return write_bson_boolean(name, j.m_value.boolean); + + case value_t::number_float: + return write_bson_double(name, j.m_value.number_float); + + case value_t::number_integer: + return write_bson_integer(name, j.m_value.number_integer); + + case value_t::number_unsigned: + return write_bson_unsigned(name, j); + + case value_t::string: + return write_bson_string(name, *j.m_value.string); + + case value_t::null: + return write_bson_null(name); + + // LCOV_EXCL_START + case value_t::discarded: + default: + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + return; + // LCOV_EXCL_STOP + } + } + + /*! + @brief Calculates the size of the BSON serialization of the given + JSON-object @a j. + @param[in] value JSON value to serialize + @pre value.type() == value_t::object + */ + static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value) + { + std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast(0), + [](size_t result, const typename BasicJsonType::object_t::value_type & el) + { + return result += calc_bson_element_size(el.first, el.second); + }); + + return sizeof(std::int32_t) + document_size + 1ul; + } + + /*! + @param[in] value JSON value to serialize + @pre value.type() == value_t::object + */ + void write_bson_object(const typename BasicJsonType::object_t& value) + { + write_number(static_cast(calc_bson_object_size(value))); + + for (const auto& el : value) + { + write_bson_element(el.first, el.second); + } + + oa->write_character(to_char_type(0x00)); + } + + ////////// + // CBOR // + ////////// + + static constexpr CharType get_cbor_float_prefix(float /*unused*/) + { + return to_char_type(0xFA); // Single-Precision Float + } + + static constexpr CharType get_cbor_float_prefix(double /*unused*/) + { + return to_char_type(0xFB); // Double-Precision Float + } + + ///////////// + // MsgPack // + ///////////// + + static constexpr CharType get_msgpack_float_prefix(float /*unused*/) + { + return to_char_type(0xCA); // float 32 + } + + static constexpr CharType get_msgpack_float_prefix(double /*unused*/) + { + return to_char_type(0xCB); // float 64 + } + + //////////// + // UBJSON // + //////////// + + // UBJSON: write number (floating point) + template::value, int>::type = 0> + void write_number_with_ubjson_prefix(const NumberType n, + const bool add_prefix) + { + if (add_prefix) + { + oa->write_character(get_ubjson_float_prefix(n)); + } + write_number(n); + } + + // UBJSON: write number (unsigned integer) + template::value, int>::type = 0> + void write_number_with_ubjson_prefix(const NumberType n, + const bool add_prefix) + { + if (n <= static_cast((std::numeric_limits::max)())) + { + if (add_prefix) + { + oa->write_character(to_char_type('i')); // int8 + } + write_number(static_cast(n)); + } + else if (n <= (std::numeric_limits::max)()) + { + if (add_prefix) + { + oa->write_character(to_char_type('U')); // uint8 + } + write_number(static_cast(n)); + } + else if (n <= static_cast((std::numeric_limits::max)())) + { + if (add_prefix) + { + oa->write_character(to_char_type('I')); // int16 + } + write_number(static_cast(n)); + } + else if (n <= static_cast((std::numeric_limits::max)())) + { + if (add_prefix) + { + oa->write_character(to_char_type('l')); // int32 + } + write_number(static_cast(n)); + } + else if (n <= static_cast((std::numeric_limits::max)())) + { + if (add_prefix) + { + oa->write_character(to_char_type('L')); // int64 + } + write_number(static_cast(n)); + } + else + { + if (add_prefix) + { + oa->write_character(to_char_type('H')); // high-precision number + } + + const auto number = BasicJsonType(n).dump(); + write_number_with_ubjson_prefix(number.size(), true); + for (std::size_t i = 0; i < number.size(); ++i) + { + oa->write_character(to_char_type(static_cast(number[i]))); + } + } + } + + // UBJSON: write number (signed integer) + template < typename NumberType, typename std::enable_if < + std::is_signed::value&& + !std::is_floating_point::value, int >::type = 0 > + void write_number_with_ubjson_prefix(const NumberType n, + const bool add_prefix) + { + if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) + { + if (add_prefix) + { + oa->write_character(to_char_type('i')); // int8 + } + write_number(static_cast(n)); + } + else if (static_cast((std::numeric_limits::min)()) <= n && n <= static_cast((std::numeric_limits::max)())) + { + if (add_prefix) + { + oa->write_character(to_char_type('U')); // uint8 + } + write_number(static_cast(n)); + } + else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) + { + if (add_prefix) + { + oa->write_character(to_char_type('I')); // int16 + } + write_number(static_cast(n)); + } + else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) + { + if (add_prefix) + { + oa->write_character(to_char_type('l')); // int32 + } + write_number(static_cast(n)); + } + else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) + { + if (add_prefix) + { + oa->write_character(to_char_type('L')); // int64 + } + write_number(static_cast(n)); + } + // LCOV_EXCL_START + else + { + if (add_prefix) + { + oa->write_character(to_char_type('H')); // high-precision number + } + + const auto number = BasicJsonType(n).dump(); + write_number_with_ubjson_prefix(number.size(), true); + for (std::size_t i = 0; i < number.size(); ++i) + { + oa->write_character(to_char_type(static_cast(number[i]))); + } + } + // LCOV_EXCL_STOP + } + + /*! + @brief determine the type prefix of container values + */ + CharType ubjson_prefix(const BasicJsonType& j) const noexcept + { + switch (j.type()) + { + case value_t::null: + return 'Z'; + + case value_t::boolean: + return j.m_value.boolean ? 'T' : 'F'; + + case value_t::number_integer: + { + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + { + return 'i'; + } + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + { + return 'U'; + } + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + { + return 'I'; + } + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + { + return 'l'; + } + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + { + return 'L'; + } + // anything else is treated as high-precision number + return 'H'; // LCOV_EXCL_LINE + } + + case value_t::number_unsigned: + { + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + return 'i'; + } + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + return 'U'; + } + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + return 'I'; + } + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + return 'l'; + } + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + return 'L'; + } + // anything else is treated as high-precision number + return 'H'; // LCOV_EXCL_LINE + } + + case value_t::number_float: + return get_ubjson_float_prefix(j.m_value.number_float); + + case value_t::string: + return 'S'; + + case value_t::array: // fallthrough + case value_t::binary: + return '['; + + case value_t::object: + return '{'; + + case value_t::discarded: + default: // discarded values + return 'N'; + } + } + + static constexpr CharType get_ubjson_float_prefix(float /*unused*/) + { + return 'd'; // float 32 + } + + static constexpr CharType get_ubjson_float_prefix(double /*unused*/) + { + return 'D'; // float 64 + } + + /////////////////////// + // Utility functions // + /////////////////////// + + /* + @brief write a number to output input + @param[in] n number of type @a NumberType + @tparam NumberType the type of the number + @tparam OutputIsLittleEndian Set to true if output data is + required to be little endian + + @note This function needs to respect the system's endianness, because bytes + in CBOR, MessagePack, and UBJSON are stored in network order (big + endian) and therefore need reordering on little endian systems. + */ + template + void write_number(const NumberType n) + { + // step 1: write number to array of length NumberType + std::array vec{}; + std::memcpy(vec.data(), &n, sizeof(NumberType)); + + // step 2: write array to output (with possible reordering) + if (is_little_endian != OutputIsLittleEndian) + { + // reverse byte order prior to conversion if necessary + std::reverse(vec.begin(), vec.end()); + } + + oa->write_characters(vec.data(), sizeof(NumberType)); + } + + void write_compact_float(const number_float_t n, detail::input_format_t format) + { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + if (static_cast(n) >= static_cast(std::numeric_limits::lowest()) && + static_cast(n) <= static_cast((std::numeric_limits::max)()) && + static_cast(static_cast(n)) == static_cast(n)) + { + oa->write_character(format == detail::input_format_t::cbor + ? get_cbor_float_prefix(static_cast(n)) + : get_msgpack_float_prefix(static_cast(n))); + write_number(static_cast(n)); + } + else + { + oa->write_character(format == detail::input_format_t::cbor + ? get_cbor_float_prefix(n) + : get_msgpack_float_prefix(n)); + write_number(n); + } +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + } + + public: + // The following to_char_type functions are implement the conversion + // between uint8_t and CharType. In case CharType is not unsigned, + // such a conversion is required to allow values greater than 128. + // See for a discussion. + template < typename C = CharType, + enable_if_t < std::is_signed::value && std::is_signed::value > * = nullptr > + static constexpr CharType to_char_type(std::uint8_t x) noexcept + { + return *reinterpret_cast(&x); + } + + template < typename C = CharType, + enable_if_t < std::is_signed::value && std::is_unsigned::value > * = nullptr > + static CharType to_char_type(std::uint8_t x) noexcept + { + static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t"); + static_assert(std::is_trivial::value, "CharType must be trivial"); + CharType result; + std::memcpy(&result, &x, sizeof(x)); + return result; + } + + template::value>* = nullptr> + static constexpr CharType to_char_type(std::uint8_t x) noexcept + { + return x; + } + + template < typename InputCharType, typename C = CharType, + enable_if_t < + std::is_signed::value && + std::is_signed::value && + std::is_same::type>::value + > * = nullptr > + static constexpr CharType to_char_type(InputCharType x) noexcept + { + return x; + } + + private: + /// whether we can assume little endianness + const bool is_little_endian = little_endianness(); + + /// the output + output_adapter_t oa = nullptr; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +#include // reverse, remove, fill, find, none_of +#include // array +#include // localeconv, lconv +#include // labs, isfinite, isnan, signbit +#include // size_t, ptrdiff_t +#include // uint8_t +#include // snprintf +#include // numeric_limits +#include // string, char_traits +#include // setfill, setw +#include // is_same +#include // move + +// #include + + +#include // array +#include // signbit, isfinite +#include // intN_t, uintN_t +#include // memcpy, memmove +#include // numeric_limits +#include // conditional + +// #include + + +namespace nlohmann +{ +namespace detail +{ + +/*! +@brief implements the Grisu2 algorithm for binary to decimal floating-point +conversion. + +This implementation is a slightly modified version of the reference +implementation which may be obtained from +http://florian.loitsch.com/publications (bench.tar.gz). + +The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch. + +For a detailed description of the algorithm see: + +[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with + Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming + Language Design and Implementation, PLDI 2010 +[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately", + Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language + Design and Implementation, PLDI 1996 +*/ +namespace dtoa_impl +{ + +template +Target reinterpret_bits(const Source source) +{ + static_assert(sizeof(Target) == sizeof(Source), "size mismatch"); + + Target target; + std::memcpy(&target, &source, sizeof(Source)); + return target; +} + +struct diyfp // f * 2^e +{ + static constexpr int kPrecision = 64; // = q + + std::uint64_t f = 0; + int e = 0; + + constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {} + + /*! + @brief returns x - y + @pre x.e == y.e and x.f >= y.f + */ + static diyfp sub(const diyfp& x, const diyfp& y) noexcept + { + JSON_ASSERT(x.e == y.e); + JSON_ASSERT(x.f >= y.f); + + return {x.f - y.f, x.e}; + } + + /*! + @brief returns x * y + @note The result is rounded. (Only the upper q bits are returned.) + */ + static diyfp mul(const diyfp& x, const diyfp& y) noexcept + { + static_assert(kPrecision == 64, "internal error"); + + // Computes: + // f = round((x.f * y.f) / 2^q) + // e = x.e + y.e + q + + // Emulate the 64-bit * 64-bit multiplication: + // + // p = u * v + // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) + // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) + // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) + // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) + // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) + // = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) + // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) + // + // (Since Q might be larger than 2^32 - 1) + // + // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) + // + // (Q_hi + H does not overflow a 64-bit int) + // + // = p_lo + 2^64 p_hi + + const std::uint64_t u_lo = x.f & 0xFFFFFFFFu; + const std::uint64_t u_hi = x.f >> 32u; + const std::uint64_t v_lo = y.f & 0xFFFFFFFFu; + const std::uint64_t v_hi = y.f >> 32u; + + const std::uint64_t p0 = u_lo * v_lo; + const std::uint64_t p1 = u_lo * v_hi; + const std::uint64_t p2 = u_hi * v_lo; + const std::uint64_t p3 = u_hi * v_hi; + + const std::uint64_t p0_hi = p0 >> 32u; + const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu; + const std::uint64_t p1_hi = p1 >> 32u; + const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu; + const std::uint64_t p2_hi = p2 >> 32u; + + std::uint64_t Q = p0_hi + p1_lo + p2_lo; + + // The full product might now be computed as + // + // p_hi = p3 + p2_hi + p1_hi + (Q >> 32) + // p_lo = p0_lo + (Q << 32) + // + // But in this particular case here, the full p_lo is not required. + // Effectively we only need to add the highest bit in p_lo to p_hi (and + // Q_hi + 1 does not overflow). + + Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up + + const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u); + + return {h, x.e + y.e + 64}; + } + + /*! + @brief normalize x such that the significand is >= 2^(q-1) + @pre x.f != 0 + */ + static diyfp normalize(diyfp x) noexcept + { + JSON_ASSERT(x.f != 0); + + while ((x.f >> 63u) == 0) + { + x.f <<= 1u; + x.e--; + } + + return x; + } + + /*! + @brief normalize x such that the result has the exponent E + @pre e >= x.e and the upper e - x.e bits of x.f must be zero. + */ + static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept + { + const int delta = x.e - target_exponent; + + JSON_ASSERT(delta >= 0); + JSON_ASSERT(((x.f << delta) >> delta) == x.f); + + return {x.f << delta, target_exponent}; + } +}; + +struct boundaries +{ + diyfp w; + diyfp minus; + diyfp plus; +}; + +/*! +Compute the (normalized) diyfp representing the input number 'value' and its +boundaries. + +@pre value must be finite and positive +*/ +template +boundaries compute_boundaries(FloatType value) +{ + JSON_ASSERT(std::isfinite(value)); + JSON_ASSERT(value > 0); + + // Convert the IEEE representation into a diyfp. + // + // If v is denormal: + // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) + // If v is normalized: + // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) + + static_assert(std::numeric_limits::is_iec559, + "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); + + constexpr int kPrecision = std::numeric_limits::digits; // = p (includes the hidden bit) + constexpr int kBias = std::numeric_limits::max_exponent - 1 + (kPrecision - 1); + constexpr int kMinExp = 1 - kBias; + constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1) + + using bits_type = typename std::conditional::type; + + const auto bits = static_cast(reinterpret_bits(value)); + const std::uint64_t E = bits >> (kPrecision - 1); + const std::uint64_t F = bits & (kHiddenBit - 1); + + const bool is_denormal = E == 0; + const diyfp v = is_denormal + ? diyfp(F, kMinExp) + : diyfp(F + kHiddenBit, static_cast(E) - kBias); + + // Compute the boundaries m- and m+ of the floating-point value + // v = f * 2^e. + // + // Determine v- and v+, the floating-point predecessor and successor if v, + // respectively. + // + // v- = v - 2^e if f != 2^(p-1) or e == e_min (A) + // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) + // + // v+ = v + 2^e + // + // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ + // between m- and m+ round to v, regardless of how the input rounding + // algorithm breaks ties. + // + // ---+-------------+-------------+-------------+-------------+--- (A) + // v- m- v m+ v+ + // + // -----------------+------+------+-------------+-------------+--- (B) + // v- m- v m+ v+ + + const bool lower_boundary_is_closer = F == 0 && E > 1; + const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); + const diyfp m_minus = lower_boundary_is_closer + ? diyfp(4 * v.f - 1, v.e - 2) // (B) + : diyfp(2 * v.f - 1, v.e - 1); // (A) + + // Determine the normalized w+ = m+. + const diyfp w_plus = diyfp::normalize(m_plus); + + // Determine w- = m- such that e_(w-) = e_(w+). + const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e); + + return {diyfp::normalize(v), w_minus, w_plus}; +} + +// Given normalized diyfp w, Grisu needs to find a (normalized) cached +// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies +// within a certain range [alpha, gamma] (Definition 3.2 from [1]) +// +// alpha <= e = e_c + e_w + q <= gamma +// +// or +// +// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q +// <= f_c * f_w * 2^gamma +// +// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies +// +// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma +// +// or +// +// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma) +// +// The choice of (alpha,gamma) determines the size of the table and the form of +// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well +// in practice: +// +// The idea is to cut the number c * w = f * 2^e into two parts, which can be +// processed independently: An integral part p1, and a fractional part p2: +// +// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e +// = (f div 2^-e) + (f mod 2^-e) * 2^e +// = p1 + p2 * 2^e +// +// The conversion of p1 into decimal form requires a series of divisions and +// modulos by (a power of) 10. These operations are faster for 32-bit than for +// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be +// achieved by choosing +// +// -e >= 32 or e <= -32 := gamma +// +// In order to convert the fractional part +// +// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ... +// +// into decimal form, the fraction is repeatedly multiplied by 10 and the digits +// d[-i] are extracted in order: +// +// (10 * p2) div 2^-e = d[-1] +// (10 * p2) mod 2^-e = d[-2] / 10^1 + ... +// +// The multiplication by 10 must not overflow. It is sufficient to choose +// +// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64. +// +// Since p2 = f mod 2^-e < 2^-e, +// +// -e <= 60 or e >= -60 := alpha + +constexpr int kAlpha = -60; +constexpr int kGamma = -32; + +struct cached_power // c = f * 2^e ~= 10^k +{ + std::uint64_t f; + int e; + int k; +}; + +/*! +For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached +power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c +satisfies (Definition 3.2 from [1]) + + alpha <= e_c + e + q <= gamma. +*/ +inline cached_power get_cached_power_for_binary_exponent(int e) +{ + // Now + // + // alpha <= e_c + e + q <= gamma (1) + // ==> f_c * 2^alpha <= c * 2^e * 2^q + // + // and since the c's are normalized, 2^(q-1) <= f_c, + // + // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) + // ==> 2^(alpha - e - 1) <= c + // + // If c were an exact power of ten, i.e. c = 10^k, one may determine k as + // + // k = ceil( log_10( 2^(alpha - e - 1) ) ) + // = ceil( (alpha - e - 1) * log_10(2) ) + // + // From the paper: + // "In theory the result of the procedure could be wrong since c is rounded, + // and the computation itself is approximated [...]. In practice, however, + // this simple function is sufficient." + // + // For IEEE double precision floating-point numbers converted into + // normalized diyfp's w = f * 2^e, with q = 64, + // + // e >= -1022 (min IEEE exponent) + // -52 (p - 1) + // -52 (p - 1, possibly normalize denormal IEEE numbers) + // -11 (normalize the diyfp) + // = -1137 + // + // and + // + // e <= +1023 (max IEEE exponent) + // -52 (p - 1) + // -11 (normalize the diyfp) + // = 960 + // + // This binary exponent range [-1137,960] results in a decimal exponent + // range [-307,324]. One does not need to store a cached power for each + // k in this range. For each such k it suffices to find a cached power + // such that the exponent of the product lies in [alpha,gamma]. + // This implies that the difference of the decimal exponents of adjacent + // table entries must be less than or equal to + // + // floor( (gamma - alpha) * log_10(2) ) = 8. + // + // (A smaller distance gamma-alpha would require a larger table.) + + // NB: + // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. + + constexpr int kCachedPowersMinDecExp = -300; + constexpr int kCachedPowersDecStep = 8; + + static constexpr std::array kCachedPowers = + { + { + { 0xAB70FE17C79AC6CA, -1060, -300 }, + { 0xFF77B1FCBEBCDC4F, -1034, -292 }, + { 0xBE5691EF416BD60C, -1007, -284 }, + { 0x8DD01FAD907FFC3C, -980, -276 }, + { 0xD3515C2831559A83, -954, -268 }, + { 0x9D71AC8FADA6C9B5, -927, -260 }, + { 0xEA9C227723EE8BCB, -901, -252 }, + { 0xAECC49914078536D, -874, -244 }, + { 0x823C12795DB6CE57, -847, -236 }, + { 0xC21094364DFB5637, -821, -228 }, + { 0x9096EA6F3848984F, -794, -220 }, + { 0xD77485CB25823AC7, -768, -212 }, + { 0xA086CFCD97BF97F4, -741, -204 }, + { 0xEF340A98172AACE5, -715, -196 }, + { 0xB23867FB2A35B28E, -688, -188 }, + { 0x84C8D4DFD2C63F3B, -661, -180 }, + { 0xC5DD44271AD3CDBA, -635, -172 }, + { 0x936B9FCEBB25C996, -608, -164 }, + { 0xDBAC6C247D62A584, -582, -156 }, + { 0xA3AB66580D5FDAF6, -555, -148 }, + { 0xF3E2F893DEC3F126, -529, -140 }, + { 0xB5B5ADA8AAFF80B8, -502, -132 }, + { 0x87625F056C7C4A8B, -475, -124 }, + { 0xC9BCFF6034C13053, -449, -116 }, + { 0x964E858C91BA2655, -422, -108 }, + { 0xDFF9772470297EBD, -396, -100 }, + { 0xA6DFBD9FB8E5B88F, -369, -92 }, + { 0xF8A95FCF88747D94, -343, -84 }, + { 0xB94470938FA89BCF, -316, -76 }, + { 0x8A08F0F8BF0F156B, -289, -68 }, + { 0xCDB02555653131B6, -263, -60 }, + { 0x993FE2C6D07B7FAC, -236, -52 }, + { 0xE45C10C42A2B3B06, -210, -44 }, + { 0xAA242499697392D3, -183, -36 }, + { 0xFD87B5F28300CA0E, -157, -28 }, + { 0xBCE5086492111AEB, -130, -20 }, + { 0x8CBCCC096F5088CC, -103, -12 }, + { 0xD1B71758E219652C, -77, -4 }, + { 0x9C40000000000000, -50, 4 }, + { 0xE8D4A51000000000, -24, 12 }, + { 0xAD78EBC5AC620000, 3, 20 }, + { 0x813F3978F8940984, 30, 28 }, + { 0xC097CE7BC90715B3, 56, 36 }, + { 0x8F7E32CE7BEA5C70, 83, 44 }, + { 0xD5D238A4ABE98068, 109, 52 }, + { 0x9F4F2726179A2245, 136, 60 }, + { 0xED63A231D4C4FB27, 162, 68 }, + { 0xB0DE65388CC8ADA8, 189, 76 }, + { 0x83C7088E1AAB65DB, 216, 84 }, + { 0xC45D1DF942711D9A, 242, 92 }, + { 0x924D692CA61BE758, 269, 100 }, + { 0xDA01EE641A708DEA, 295, 108 }, + { 0xA26DA3999AEF774A, 322, 116 }, + { 0xF209787BB47D6B85, 348, 124 }, + { 0xB454E4A179DD1877, 375, 132 }, + { 0x865B86925B9BC5C2, 402, 140 }, + { 0xC83553C5C8965D3D, 428, 148 }, + { 0x952AB45CFA97A0B3, 455, 156 }, + { 0xDE469FBD99A05FE3, 481, 164 }, + { 0xA59BC234DB398C25, 508, 172 }, + { 0xF6C69A72A3989F5C, 534, 180 }, + { 0xB7DCBF5354E9BECE, 561, 188 }, + { 0x88FCF317F22241E2, 588, 196 }, + { 0xCC20CE9BD35C78A5, 614, 204 }, + { 0x98165AF37B2153DF, 641, 212 }, + { 0xE2A0B5DC971F303A, 667, 220 }, + { 0xA8D9D1535CE3B396, 694, 228 }, + { 0xFB9B7CD9A4A7443C, 720, 236 }, + { 0xBB764C4CA7A44410, 747, 244 }, + { 0x8BAB8EEFB6409C1A, 774, 252 }, + { 0xD01FEF10A657842C, 800, 260 }, + { 0x9B10A4E5E9913129, 827, 268 }, + { 0xE7109BFBA19C0C9D, 853, 276 }, + { 0xAC2820D9623BF429, 880, 284 }, + { 0x80444B5E7AA7CF85, 907, 292 }, + { 0xBF21E44003ACDD2D, 933, 300 }, + { 0x8E679C2F5E44FF8F, 960, 308 }, + { 0xD433179D9C8CB841, 986, 316 }, + { 0x9E19DB92B4E31BA9, 1013, 324 }, + } + }; + + // This computation gives exactly the same results for k as + // k = ceil((kAlpha - e - 1) * 0.30102999566398114) + // for |e| <= 1500, but doesn't require floating-point operations. + // NB: log_10(2) ~= 78913 / 2^18 + JSON_ASSERT(e >= -1500); + JSON_ASSERT(e <= 1500); + const int f = kAlpha - e - 1; + const int k = (f * 78913) / (1 << 18) + static_cast(f > 0); + + const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; + JSON_ASSERT(index >= 0); + JSON_ASSERT(static_cast(index) < kCachedPowers.size()); + + const cached_power cached = kCachedPowers[static_cast(index)]; + JSON_ASSERT(kAlpha <= cached.e + e + 64); + JSON_ASSERT(kGamma >= cached.e + e + 64); + + return cached; +} + +/*! +For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. +For n == 0, returns 1 and sets pow10 := 1. +*/ +inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10) +{ + // LCOV_EXCL_START + if (n >= 1000000000) + { + pow10 = 1000000000; + return 10; + } + // LCOV_EXCL_STOP + if (n >= 100000000) + { + pow10 = 100000000; + return 9; + } + if (n >= 10000000) + { + pow10 = 10000000; + return 8; + } + if (n >= 1000000) + { + pow10 = 1000000; + return 7; + } + if (n >= 100000) + { + pow10 = 100000; + return 6; + } + if (n >= 10000) + { + pow10 = 10000; + return 5; + } + if (n >= 1000) + { + pow10 = 1000; + return 4; + } + if (n >= 100) + { + pow10 = 100; + return 3; + } + if (n >= 10) + { + pow10 = 10; + return 2; + } + + pow10 = 1; + return 1; +} + +inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta, + std::uint64_t rest, std::uint64_t ten_k) +{ + JSON_ASSERT(len >= 1); + JSON_ASSERT(dist <= delta); + JSON_ASSERT(rest <= delta); + JSON_ASSERT(ten_k > 0); + + // <--------------------------- delta ----> + // <---- dist ---------> + // --------------[------------------+-------------------]-------------- + // M- w M+ + // + // ten_k + // <------> + // <---- rest ----> + // --------------[------------------+----+--------------]-------------- + // w V + // = buf * 10^k + // + // ten_k represents a unit-in-the-last-place in the decimal representation + // stored in buf. + // Decrement buf by ten_k while this takes buf closer to w. + + // The tests are written in this order to avoid overflow in unsigned + // integer arithmetic. + + while (rest < dist + && delta - rest >= ten_k + && (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) + { + JSON_ASSERT(buf[len - 1] != '0'); + buf[len - 1]--; + rest += ten_k; + } +} + +/*! +Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. +M- and M+ must be normalized and share the same exponent -60 <= e <= -32. +*/ +inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, + diyfp M_minus, diyfp w, diyfp M_plus) +{ + static_assert(kAlpha >= -60, "internal error"); + static_assert(kGamma <= -32, "internal error"); + + // Generates the digits (and the exponent) of a decimal floating-point + // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's + // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. + // + // <--------------------------- delta ----> + // <---- dist ---------> + // --------------[------------------+-------------------]-------------- + // M- w M+ + // + // Grisu2 generates the digits of M+ from left to right and stops as soon as + // V is in [M-,M+]. + + JSON_ASSERT(M_plus.e >= kAlpha); + JSON_ASSERT(M_plus.e <= kGamma); + + std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e) + std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e) + + // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): + // + // M+ = f * 2^e + // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e + // = ((p1 ) * 2^-e + (p2 )) * 2^e + // = p1 + p2 * 2^e + + const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e); + + auto p1 = static_cast(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.) + std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e + + // 1) + // + // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] + + JSON_ASSERT(p1 > 0); + + std::uint32_t pow10{}; + const int k = find_largest_pow10(p1, pow10); + + // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) + // + // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) + // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) + // + // M+ = p1 + p2 * 2^e + // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e + // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e + // = d[k-1] * 10^(k-1) + ( rest) * 2^e + // + // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) + // + // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] + // + // but stop as soon as + // + // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e + + int n = k; + while (n > 0) + { + // Invariants: + // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) + // pow10 = 10^(n-1) <= p1 < 10^n + // + const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) + const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) + // + // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e + // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) + // + JSON_ASSERT(d <= 9); + buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d + // + // M+ = buffer * 10^(n-1) + (r + p2 * 2^e) + // + p1 = r; + n--; + // + // M+ = buffer * 10^n + (p1 + p2 * 2^e) + // pow10 = 10^n + // + + // Now check if enough digits have been generated. + // Compute + // + // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e + // + // Note: + // Since rest and delta share the same exponent e, it suffices to + // compare the significands. + const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2; + if (rest <= delta) + { + // V = buffer * 10^n, with M- <= V <= M+. + + decimal_exponent += n; + + // We may now just stop. But instead look if the buffer could be + // decremented to bring V closer to w. + // + // pow10 = 10^n is now 1 ulp in the decimal representation V. + // The rounding procedure works with diyfp's with an implicit + // exponent of e. + // + // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e + // + const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e; + grisu2_round(buffer, length, dist, delta, rest, ten_n); + + return; + } + + pow10 /= 10; + // + // pow10 = 10^(n-1) <= p1 < 10^n + // Invariants restored. + } + + // 2) + // + // The digits of the integral part have been generated: + // + // M+ = d[k-1]...d[1]d[0] + p2 * 2^e + // = buffer + p2 * 2^e + // + // Now generate the digits of the fractional part p2 * 2^e. + // + // Note: + // No decimal point is generated: the exponent is adjusted instead. + // + // p2 actually represents the fraction + // + // p2 * 2^e + // = p2 / 2^-e + // = d[-1] / 10^1 + d[-2] / 10^2 + ... + // + // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) + // + // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m + // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) + // + // using + // + // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) + // = ( d) * 2^-e + ( r) + // + // or + // 10^m * p2 * 2^e = d + r * 2^e + // + // i.e. + // + // M+ = buffer + p2 * 2^e + // = buffer + 10^-m * (d + r * 2^e) + // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e + // + // and stop as soon as 10^-m * r * 2^e <= delta * 2^e + + JSON_ASSERT(p2 > delta); + + int m = 0; + for (;;) + { + // Invariant: + // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e + // = buffer * 10^-m + 10^-m * (p2 ) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e + // + JSON_ASSERT(p2 <= (std::numeric_limits::max)() / 10); + p2 *= 10; + const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e + const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e + // + // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) + // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e + // + JSON_ASSERT(d <= 9); + buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d + // + // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e + // + p2 = r; + m++; + // + // M+ = buffer * 10^-m + 10^-m * p2 * 2^e + // Invariant restored. + + // Check if enough digits have been generated. + // + // 10^-m * p2 * 2^e <= delta * 2^e + // p2 * 2^e <= 10^m * delta * 2^e + // p2 <= 10^m * delta + delta *= 10; + dist *= 10; + if (p2 <= delta) + { + break; + } + } + + // V = buffer * 10^-m, with M- <= V <= M+. + + decimal_exponent -= m; + + // 1 ulp in the decimal representation is now 10^-m. + // Since delta and dist are now scaled by 10^m, we need to do the + // same with ulp in order to keep the units in sync. + // + // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e + // + const std::uint64_t ten_m = one.f; + grisu2_round(buffer, length, dist, delta, p2, ten_m); + + // By construction this algorithm generates the shortest possible decimal + // number (Loitsch, Theorem 6.2) which rounds back to w. + // For an input number of precision p, at least + // + // N = 1 + ceil(p * log_10(2)) + // + // decimal digits are sufficient to identify all binary floating-point + // numbers (Matula, "In-and-Out conversions"). + // This implies that the algorithm does not produce more than N decimal + // digits. + // + // N = 17 for p = 53 (IEEE double precision) + // N = 9 for p = 24 (IEEE single precision) +} + +/*! +v = buf * 10^decimal_exponent +len is the length of the buffer (number of decimal digits) +The buffer must be large enough, i.e. >= max_digits10. +*/ +JSON_HEDLEY_NON_NULL(1) +inline void grisu2(char* buf, int& len, int& decimal_exponent, + diyfp m_minus, diyfp v, diyfp m_plus) +{ + JSON_ASSERT(m_plus.e == m_minus.e); + JSON_ASSERT(m_plus.e == v.e); + + // --------(-----------------------+-----------------------)-------- (A) + // m- v m+ + // + // --------------------(-----------+-----------------------)-------- (B) + // m- v m+ + // + // First scale v (and m- and m+) such that the exponent is in the range + // [alpha, gamma]. + + const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e); + + const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k + + // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] + const diyfp w = diyfp::mul(v, c_minus_k); + const diyfp w_minus = diyfp::mul(m_minus, c_minus_k); + const diyfp w_plus = diyfp::mul(m_plus, c_minus_k); + + // ----(---+---)---------------(---+---)---------------(---+---)---- + // w- w w+ + // = c*m- = c*v = c*m+ + // + // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and + // w+ are now off by a small amount. + // In fact: + // + // w - v * 10^k < 1 ulp + // + // To account for this inaccuracy, add resp. subtract 1 ulp. + // + // --------+---[---------------(---+---)---------------]---+-------- + // w- M- w M+ w+ + // + // Now any number in [M-, M+] (bounds included) will round to w when input, + // regardless of how the input rounding algorithm breaks ties. + // + // And digit_gen generates the shortest possible such number in [M-, M+]. + // Note that this does not mean that Grisu2 always generates the shortest + // possible number in the interval (m-, m+). + const diyfp M_minus(w_minus.f + 1, w_minus.e); + const diyfp M_plus (w_plus.f - 1, w_plus.e ); + + decimal_exponent = -cached.k; // = -(-k) = k + + grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus); +} + +/*! +v = buf * 10^decimal_exponent +len is the length of the buffer (number of decimal digits) +The buffer must be large enough, i.e. >= max_digits10. +*/ +template +JSON_HEDLEY_NON_NULL(1) +void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) +{ + static_assert(diyfp::kPrecision >= std::numeric_limits::digits + 3, + "internal error: not enough precision"); + + JSON_ASSERT(std::isfinite(value)); + JSON_ASSERT(value > 0); + + // If the neighbors (and boundaries) of 'value' are always computed for double-precision + // numbers, all float's can be recovered using strtod (and strtof). However, the resulting + // decimal representations are not exactly "short". + // + // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars) + // says "value is converted to a string as if by std::sprintf in the default ("C") locale" + // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars' + // does. + // On the other hand, the documentation for 'std::to_chars' requires that "parsing the + // representation using the corresponding std::from_chars function recovers value exactly". That + // indicates that single precision floating-point numbers should be recovered using + // 'std::strtof'. + // + // NB: If the neighbors are computed for single-precision numbers, there is a single float + // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision + // value is off by 1 ulp. +#if 0 + const boundaries w = compute_boundaries(static_cast(value)); +#else + const boundaries w = compute_boundaries(value); +#endif + + grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus); +} + +/*! +@brief appends a decimal representation of e to buf +@return a pointer to the element following the exponent. +@pre -1000 < e < 1000 +*/ +JSON_HEDLEY_NON_NULL(1) +JSON_HEDLEY_RETURNS_NON_NULL +inline char* append_exponent(char* buf, int e) +{ + JSON_ASSERT(e > -1000); + JSON_ASSERT(e < 1000); + + if (e < 0) + { + e = -e; + *buf++ = '-'; + } + else + { + *buf++ = '+'; + } + + auto k = static_cast(e); + if (k < 10) + { + // Always print at least two digits in the exponent. + // This is for compatibility with printf("%g"). + *buf++ = '0'; + *buf++ = static_cast('0' + k); + } + else if (k < 100) + { + *buf++ = static_cast('0' + k / 10); + k %= 10; + *buf++ = static_cast('0' + k); + } + else + { + *buf++ = static_cast('0' + k / 100); + k %= 100; + *buf++ = static_cast('0' + k / 10); + k %= 10; + *buf++ = static_cast('0' + k); + } + + return buf; +} + +/*! +@brief prettify v = buf * 10^decimal_exponent + +If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point +notation. Otherwise it will be printed in exponential notation. + +@pre min_exp < 0 +@pre max_exp > 0 +*/ +JSON_HEDLEY_NON_NULL(1) +JSON_HEDLEY_RETURNS_NON_NULL +inline char* format_buffer(char* buf, int len, int decimal_exponent, + int min_exp, int max_exp) +{ + JSON_ASSERT(min_exp < 0); + JSON_ASSERT(max_exp > 0); + + const int k = len; + const int n = len + decimal_exponent; + + // v = buf * 10^(n-k) + // k is the length of the buffer (number of decimal digits) + // n is the position of the decimal point relative to the start of the buffer. + + if (k <= n && n <= max_exp) + { + // digits[000] + // len <= max_exp + 2 + + std::memset(buf + k, '0', static_cast(n) - static_cast(k)); + // Make it look like a floating-point number (#362, #378) + buf[n + 0] = '.'; + buf[n + 1] = '0'; + return buf + (static_cast(n) + 2); + } + + if (0 < n && n <= max_exp) + { + // dig.its + // len <= max_digits10 + 1 + + JSON_ASSERT(k > n); + + std::memmove(buf + (static_cast(n) + 1), buf + n, static_cast(k) - static_cast(n)); + buf[n] = '.'; + return buf + (static_cast(k) + 1U); + } + + if (min_exp < n && n <= 0) + { + // 0.[000]digits + // len <= 2 + (-min_exp - 1) + max_digits10 + + std::memmove(buf + (2 + static_cast(-n)), buf, static_cast(k)); + buf[0] = '0'; + buf[1] = '.'; + std::memset(buf + 2, '0', static_cast(-n)); + return buf + (2U + static_cast(-n) + static_cast(k)); + } + + if (k == 1) + { + // dE+123 + // len <= 1 + 5 + + buf += 1; + } + else + { + // d.igitsE+123 + // len <= max_digits10 + 1 + 5 + + std::memmove(buf + 2, buf + 1, static_cast(k) - 1); + buf[1] = '.'; + buf += 1 + static_cast(k); + } + + *buf++ = 'e'; + return append_exponent(buf, n - 1); +} + +} // namespace dtoa_impl + +/*! +@brief generates a decimal representation of the floating-point number value in [first, last). + +The format of the resulting decimal representation is similar to printf's %g +format. Returns an iterator pointing past-the-end of the decimal representation. + +@note The input number must be finite, i.e. NaN's and Inf's are not supported. +@note The buffer must be large enough. +@note The result is NOT null-terminated. +*/ +template +JSON_HEDLEY_NON_NULL(1, 2) +JSON_HEDLEY_RETURNS_NON_NULL +char* to_chars(char* first, const char* last, FloatType value) +{ + static_cast(last); // maybe unused - fix warning + JSON_ASSERT(std::isfinite(value)); + + // Use signbit(value) instead of (value < 0) since signbit works for -0. + if (std::signbit(value)) + { + value = -value; + *first++ = '-'; + } + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + if (value == 0) // +-0 + { + *first++ = '0'; + // Make it look like a floating-point number (#362, #378) + *first++ = '.'; + *first++ = '0'; + return first; + } +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + + JSON_ASSERT(last - first >= std::numeric_limits::max_digits10); + + // Compute v = buffer * 10^decimal_exponent. + // The decimal digits are stored in the buffer, which needs to be interpreted + // as an unsigned decimal integer. + // len is the length of the buffer, i.e. the number of decimal digits. + int len = 0; + int decimal_exponent = 0; + dtoa_impl::grisu2(first, len, decimal_exponent, value); + + JSON_ASSERT(len <= std::numeric_limits::max_digits10); + + // Format the buffer like printf("%.*g", prec, value) + constexpr int kMinExp = -4; + // Use digits10 here to increase compatibility with version 2. + constexpr int kMaxExp = std::numeric_limits::digits10; + + JSON_ASSERT(last - first >= kMaxExp + 2); + JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits::max_digits10); + JSON_ASSERT(last - first >= std::numeric_limits::max_digits10 + 6); + + return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); +} + +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + +// #include + +// #include + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +/////////////////// +// serialization // +/////////////////// + +/// how to treat decoding errors +enum class error_handler_t +{ + strict, ///< throw a type_error exception in case of invalid UTF-8 + replace, ///< replace invalid UTF-8 sequences with U+FFFD + ignore ///< ignore invalid UTF-8 sequences +}; + +template +class serializer +{ + using string_t = typename BasicJsonType::string_t; + using number_float_t = typename BasicJsonType::number_float_t; + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using binary_char_t = typename BasicJsonType::binary_t::value_type; + static constexpr std::uint8_t UTF8_ACCEPT = 0; + static constexpr std::uint8_t UTF8_REJECT = 1; + + public: + /*! + @param[in] s output stream to serialize to + @param[in] ichar indentation character to use + @param[in] error_handler_ how to react on decoding errors + */ + serializer(output_adapter_t s, const char ichar, + error_handler_t error_handler_ = error_handler_t::strict) + : o(std::move(s)) + , loc(std::localeconv()) + , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits::to_char_type(* (loc->thousands_sep))) + , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits::to_char_type(* (loc->decimal_point))) + , indent_char(ichar) + , indent_string(512, indent_char) + , error_handler(error_handler_) + {} + + // delete because of pointer members + serializer(const serializer&) = delete; + serializer& operator=(const serializer&) = delete; + serializer(serializer&&) = delete; + serializer& operator=(serializer&&) = delete; + ~serializer() = default; + + /*! + @brief internal implementation of the serialization function + + This function is called by the public member function dump and organizes + the serialization internally. The indentation level is propagated as + additional parameter. In case of arrays and objects, the function is + called recursively. + + - strings and object keys are escaped using `escape_string()` + - integer numbers are converted implicitly via `operator<<` + - floating-point numbers are converted to a string using `"%g"` format + - binary values are serialized as objects containing the subtype and the + byte array + + @param[in] val value to serialize + @param[in] pretty_print whether the output shall be pretty-printed + @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters + in the output are escaped with `\uXXXX` sequences, and the result consists + of ASCII characters only. + @param[in] indent_step the indent level + @param[in] current_indent the current indent level (only used internally) + */ + void dump(const BasicJsonType& val, + const bool pretty_print, + const bool ensure_ascii, + const unsigned int indent_step, + const unsigned int current_indent = 0) + { + switch (val.m_type) + { + case value_t::object: + { + if (val.m_value.object->empty()) + { + o->write_characters("{}", 2); + return; + } + + if (pretty_print) + { + o->write_characters("{\n", 2); + + // variable to hold indentation for recursive calls + const auto new_indent = current_indent + indent_step; + if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) + { + indent_string.resize(indent_string.size() * 2, ' '); + } + + // first n-1 elements + auto i = val.m_value.object->cbegin(); + for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) + { + o->write_characters(indent_string.c_str(), new_indent); + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\": ", 3); + dump(i->second, true, ensure_ascii, indent_step, new_indent); + o->write_characters(",\n", 2); + } + + // last element + JSON_ASSERT(i != val.m_value.object->cend()); + JSON_ASSERT(std::next(i) == val.m_value.object->cend()); + o->write_characters(indent_string.c_str(), new_indent); + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\": ", 3); + dump(i->second, true, ensure_ascii, indent_step, new_indent); + + o->write_character('\n'); + o->write_characters(indent_string.c_str(), current_indent); + o->write_character('}'); + } + else + { + o->write_character('{'); + + // first n-1 elements + auto i = val.m_value.object->cbegin(); + for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) + { + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\":", 2); + dump(i->second, false, ensure_ascii, indent_step, current_indent); + o->write_character(','); + } + + // last element + JSON_ASSERT(i != val.m_value.object->cend()); + JSON_ASSERT(std::next(i) == val.m_value.object->cend()); + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\":", 2); + dump(i->second, false, ensure_ascii, indent_step, current_indent); + + o->write_character('}'); + } + + return; + } + + case value_t::array: + { + if (val.m_value.array->empty()) + { + o->write_characters("[]", 2); + return; + } + + if (pretty_print) + { + o->write_characters("[\n", 2); + + // variable to hold indentation for recursive calls + const auto new_indent = current_indent + indent_step; + if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) + { + indent_string.resize(indent_string.size() * 2, ' '); + } + + // first n-1 elements + for (auto i = val.m_value.array->cbegin(); + i != val.m_value.array->cend() - 1; ++i) + { + o->write_characters(indent_string.c_str(), new_indent); + dump(*i, true, ensure_ascii, indent_step, new_indent); + o->write_characters(",\n", 2); + } + + // last element + JSON_ASSERT(!val.m_value.array->empty()); + o->write_characters(indent_string.c_str(), new_indent); + dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); + + o->write_character('\n'); + o->write_characters(indent_string.c_str(), current_indent); + o->write_character(']'); + } + else + { + o->write_character('['); + + // first n-1 elements + for (auto i = val.m_value.array->cbegin(); + i != val.m_value.array->cend() - 1; ++i) + { + dump(*i, false, ensure_ascii, indent_step, current_indent); + o->write_character(','); + } + + // last element + JSON_ASSERT(!val.m_value.array->empty()); + dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); + + o->write_character(']'); + } + + return; + } + + case value_t::string: + { + o->write_character('\"'); + dump_escaped(*val.m_value.string, ensure_ascii); + o->write_character('\"'); + return; + } + + case value_t::binary: + { + if (pretty_print) + { + o->write_characters("{\n", 2); + + // variable to hold indentation for recursive calls + const auto new_indent = current_indent + indent_step; + if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) + { + indent_string.resize(indent_string.size() * 2, ' '); + } + + o->write_characters(indent_string.c_str(), new_indent); + + o->write_characters("\"bytes\": [", 10); + + if (!val.m_value.binary->empty()) + { + for (auto i = val.m_value.binary->cbegin(); + i != val.m_value.binary->cend() - 1; ++i) + { + dump_integer(*i); + o->write_characters(", ", 2); + } + dump_integer(val.m_value.binary->back()); + } + + o->write_characters("],\n", 3); + o->write_characters(indent_string.c_str(), new_indent); + + o->write_characters("\"subtype\": ", 11); + if (val.m_value.binary->has_subtype()) + { + dump_integer(val.m_value.binary->subtype()); + } + else + { + o->write_characters("null", 4); + } + o->write_character('\n'); + o->write_characters(indent_string.c_str(), current_indent); + o->write_character('}'); + } + else + { + o->write_characters("{\"bytes\":[", 10); + + if (!val.m_value.binary->empty()) + { + for (auto i = val.m_value.binary->cbegin(); + i != val.m_value.binary->cend() - 1; ++i) + { + dump_integer(*i); + o->write_character(','); + } + dump_integer(val.m_value.binary->back()); + } + + o->write_characters("],\"subtype\":", 12); + if (val.m_value.binary->has_subtype()) + { + dump_integer(val.m_value.binary->subtype()); + o->write_character('}'); + } + else + { + o->write_characters("null}", 5); + } + } + return; + } + + case value_t::boolean: + { + if (val.m_value.boolean) + { + o->write_characters("true", 4); + } + else + { + o->write_characters("false", 5); + } + return; + } + + case value_t::number_integer: + { + dump_integer(val.m_value.number_integer); + return; + } + + case value_t::number_unsigned: + { + dump_integer(val.m_value.number_unsigned); + return; + } + + case value_t::number_float: + { + dump_float(val.m_value.number_float); + return; + } + + case value_t::discarded: + { + o->write_characters("", 11); + return; + } + + case value_t::null: + { + o->write_characters("null", 4); + return; + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + } + + JSON_PRIVATE_UNLESS_TESTED: + /*! + @brief dump escaped string + + Escape a string by replacing certain special characters by a sequence of an + escape character (backslash) and another character and other control + characters by a sequence of "\u" followed by a four-digit hex + representation. The escaped string is written to output stream @a o. + + @param[in] s the string to escape + @param[in] ensure_ascii whether to escape non-ASCII characters with + \uXXXX sequences + + @complexity Linear in the length of string @a s. + */ + void dump_escaped(const string_t& s, const bool ensure_ascii) + { + std::uint32_t codepoint{}; + std::uint8_t state = UTF8_ACCEPT; + std::size_t bytes = 0; // number of bytes written to string_buffer + + // number of bytes written at the point of the last valid byte + std::size_t bytes_after_last_accept = 0; + std::size_t undumped_chars = 0; + + for (std::size_t i = 0; i < s.size(); ++i) + { + const auto byte = static_cast(s[i]); + + switch (decode(state, codepoint, byte)) + { + case UTF8_ACCEPT: // decode found a new code point + { + switch (codepoint) + { + case 0x08: // backspace + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'b'; + break; + } + + case 0x09: // horizontal tab + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 't'; + break; + } + + case 0x0A: // newline + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'n'; + break; + } + + case 0x0C: // formfeed + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'f'; + break; + } + + case 0x0D: // carriage return + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'r'; + break; + } + + case 0x22: // quotation mark + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = '\"'; + break; + } + + case 0x5C: // reverse solidus + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = '\\'; + break; + } + + default: + { + // escape control characters (0x00..0x1F) or, if + // ensure_ascii parameter is used, non-ASCII characters + if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F))) + { + if (codepoint <= 0xFFFF) + { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + static_cast((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x", + static_cast(codepoint))); + bytes += 6; + } + else + { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + static_cast((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x", + static_cast(0xD7C0u + (codepoint >> 10u)), + static_cast(0xDC00u + (codepoint & 0x3FFu)))); + bytes += 12; + } + } + else + { + // copy byte to buffer (all previous bytes + // been copied have in default case above) + string_buffer[bytes++] = s[i]; + } + break; + } + } + + // write buffer and reset index; there must be 13 bytes + // left, as this is the maximal number of bytes to be + // written ("\uxxxx\uxxxx\0") for one code point + if (string_buffer.size() - bytes < 13) + { + o->write_characters(string_buffer.data(), bytes); + bytes = 0; + } + + // remember the byte position of this accept + bytes_after_last_accept = bytes; + undumped_chars = 0; + break; + } + + case UTF8_REJECT: // decode found invalid UTF-8 byte + { + switch (error_handler) + { + case error_handler_t::strict: + { + JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + hex_bytes(byte | 0), BasicJsonType())); + } + + case error_handler_t::ignore: + case error_handler_t::replace: + { + // in case we saw this character the first time, we + // would like to read it again, because the byte + // may be OK for itself, but just not OK for the + // previous sequence + if (undumped_chars > 0) + { + --i; + } + + // reset length buffer to the last accepted index; + // thus removing/ignoring the invalid characters + bytes = bytes_after_last_accept; + + if (error_handler == error_handler_t::replace) + { + // add a replacement character + if (ensure_ascii) + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'u'; + string_buffer[bytes++] = 'f'; + string_buffer[bytes++] = 'f'; + string_buffer[bytes++] = 'f'; + string_buffer[bytes++] = 'd'; + } + else + { + string_buffer[bytes++] = detail::binary_writer::to_char_type('\xEF'); + string_buffer[bytes++] = detail::binary_writer::to_char_type('\xBF'); + string_buffer[bytes++] = detail::binary_writer::to_char_type('\xBD'); + } + + // write buffer and reset index; there must be 13 bytes + // left, as this is the maximal number of bytes to be + // written ("\uxxxx\uxxxx\0") for one code point + if (string_buffer.size() - bytes < 13) + { + o->write_characters(string_buffer.data(), bytes); + bytes = 0; + } + + bytes_after_last_accept = bytes; + } + + undumped_chars = 0; + + // continue processing the string + state = UTF8_ACCEPT; + break; + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + break; + } + + default: // decode found yet incomplete multi-byte code point + { + if (!ensure_ascii) + { + // code point will not be escaped - copy byte to buffer + string_buffer[bytes++] = s[i]; + } + ++undumped_chars; + break; + } + } + } + + // we finished processing the string + if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT)) + { + // write buffer + if (bytes > 0) + { + o->write_characters(string_buffer.data(), bytes); + } + } + else + { + // we finish reading, but do not accept: string was incomplete + switch (error_handler) + { + case error_handler_t::strict: + { + JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + hex_bytes(static_cast(s.back() | 0)), BasicJsonType())); + } + + case error_handler_t::ignore: + { + // write all accepted bytes + o->write_characters(string_buffer.data(), bytes_after_last_accept); + break; + } + + case error_handler_t::replace: + { + // write all accepted bytes + o->write_characters(string_buffer.data(), bytes_after_last_accept); + // add a replacement character + if (ensure_ascii) + { + o->write_characters("\\ufffd", 6); + } + else + { + o->write_characters("\xEF\xBF\xBD", 3); + } + break; + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + } + } + + private: + /*! + @brief count digits + + Count the number of decimal (base 10) digits for an input unsigned integer. + + @param[in] x unsigned integer number to count its digits + @return number of decimal digits + */ + inline unsigned int count_digits(number_unsigned_t x) noexcept + { + unsigned int n_digits = 1; + for (;;) + { + if (x < 10) + { + return n_digits; + } + if (x < 100) + { + return n_digits + 1; + } + if (x < 1000) + { + return n_digits + 2; + } + if (x < 10000) + { + return n_digits + 3; + } + x = x / 10000u; + n_digits += 4; + } + } + + /*! + * @brief convert a byte to a uppercase hex representation + * @param[in] byte byte to represent + * @return representation ("00".."FF") + */ + static std::string hex_bytes(std::uint8_t byte) + { + std::string result = "FF"; + constexpr const char* nibble_to_hex = "0123456789ABCDEF"; + result[0] = nibble_to_hex[byte / 16]; + result[1] = nibble_to_hex[byte % 16]; + return result; + } + + // templates to avoid warnings about useless casts + template ::value, int> = 0> + bool is_negative_number(NumberType x) + { + return x < 0; + } + + template < typename NumberType, enable_if_t ::value, int > = 0 > + bool is_negative_number(NumberType /*unused*/) + { + return false; + } + + /*! + @brief dump an integer + + Dump a given integer to output stream @a o. Works internally with + @a number_buffer. + + @param[in] x integer number (signed or unsigned) to dump + @tparam NumberType either @a number_integer_t or @a number_unsigned_t + */ + template < typename NumberType, detail::enable_if_t < + std::is_integral::value || + std::is_same::value || + std::is_same::value || + std::is_same::value, + int > = 0 > + void dump_integer(NumberType x) + { + static constexpr std::array, 100> digits_to_99 + { + { + {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}}, + {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}}, + {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}}, + {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}}, + {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}}, + {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}}, + {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}}, + {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}}, + {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}}, + {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}}, + } + }; + + // special case for "0" + if (x == 0) + { + o->write_character('0'); + return; + } + + // use a pointer to fill the buffer + auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg) + + number_unsigned_t abs_value; + + unsigned int n_chars{}; + + if (is_negative_number(x)) + { + *buffer_ptr = '-'; + abs_value = remove_sign(static_cast(x)); + + // account one more byte for the minus sign + n_chars = 1 + count_digits(abs_value); + } + else + { + abs_value = static_cast(x); + n_chars = count_digits(abs_value); + } + + // spare 1 byte for '\0' + JSON_ASSERT(n_chars < number_buffer.size() - 1); + + // jump to the end to generate the string from backward, + // so we later avoid reversing the result + buffer_ptr += n_chars; + + // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu + // See: https://www.youtube.com/watch?v=o4-CwDo2zpg + while (abs_value >= 100) + { + const auto digits_index = static_cast((abs_value % 100)); + abs_value /= 100; + *(--buffer_ptr) = digits_to_99[digits_index][1]; + *(--buffer_ptr) = digits_to_99[digits_index][0]; + } + + if (abs_value >= 10) + { + const auto digits_index = static_cast(abs_value); + *(--buffer_ptr) = digits_to_99[digits_index][1]; + *(--buffer_ptr) = digits_to_99[digits_index][0]; + } + else + { + *(--buffer_ptr) = static_cast('0' + abs_value); + } + + o->write_characters(number_buffer.data(), n_chars); + } + + /*! + @brief dump a floating-point number + + Dump a given floating-point number to output stream @a o. Works internally + with @a number_buffer. + + @param[in] x floating-point number to dump + */ + void dump_float(number_float_t x) + { + // NaN / inf + if (!std::isfinite(x)) + { + o->write_characters("null", 4); + return; + } + + // If number_float_t is an IEEE-754 single or double precision number, + // use the Grisu2 algorithm to produce short numbers which are + // guaranteed to round-trip, using strtof and strtod, resp. + // + // NB: The test below works if == . + static constexpr bool is_ieee_single_or_double + = (std::numeric_limits::is_iec559 && std::numeric_limits::digits == 24 && std::numeric_limits::max_exponent == 128) || + (std::numeric_limits::is_iec559 && std::numeric_limits::digits == 53 && std::numeric_limits::max_exponent == 1024); + + dump_float(x, std::integral_constant()); + } + + void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/) + { + auto* begin = number_buffer.data(); + auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x); + + o->write_characters(begin, static_cast(end - begin)); + } + + void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) + { + // get number of digits for a float -> text -> float round-trip + static constexpr auto d = std::numeric_limits::max_digits10; + + // the actual conversion + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x); + + // negative value indicates an error + JSON_ASSERT(len > 0); + // check if buffer was large enough + JSON_ASSERT(static_cast(len) < number_buffer.size()); + + // erase thousands separator + if (thousands_sep != '\0') + { + // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081 + const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep); + std::fill(end, number_buffer.end(), '\0'); + JSON_ASSERT((end - number_buffer.begin()) <= len); + len = (end - number_buffer.begin()); + } + + // convert decimal point to '.' + if (decimal_point != '\0' && decimal_point != '.') + { + // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081 + const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point); + if (dec_pos != number_buffer.end()) + { + *dec_pos = '.'; + } + } + + o->write_characters(number_buffer.data(), static_cast(len)); + + // determine if we need to append ".0" + const bool value_is_int_like = + std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1, + [](char c) + { + return c == '.' || c == 'e'; + }); + + if (value_is_int_like) + { + o->write_characters(".0", 2); + } + } + + /*! + @brief check whether a string is UTF-8 encoded + + The function checks each byte of a string whether it is UTF-8 encoded. The + result of the check is stored in the @a state parameter. The function must + be called initially with state 0 (accept). State 1 means the string must + be rejected, because the current byte is not allowed. If the string is + completely processed, but the state is non-zero, the string ended + prematurely; that is, the last byte indicated more bytes should have + followed. + + @param[in,out] state the state of the decoding + @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT) + @param[in] byte next byte to decode + @return new state + + @note The function has been edited: a std::array is used. + + @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann + @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ + */ + static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept + { + static const std::array utf8d = + { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF + 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF + 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF + 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF + 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2 + 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4 + 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6 + 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8 + } + }; + + JSON_ASSERT(byte < utf8d.size()); + const std::uint8_t type = utf8d[byte]; + + codep = (state != UTF8_ACCEPT) + ? (byte & 0x3fu) | (codep << 6u) + : (0xFFu >> type) & (byte); + + std::size_t index = 256u + static_cast(state) * 16u + static_cast(type); + JSON_ASSERT(index < 400); + state = utf8d[index]; + return state; + } + + /* + * Overload to make the compiler happy while it is instantiating + * dump_integer for number_unsigned_t. + * Must never be called. + */ + number_unsigned_t remove_sign(number_unsigned_t x) + { + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + return x; // LCOV_EXCL_LINE + } + + /* + * Helper function for dump_integer + * + * This function takes a negative signed integer and returns its absolute + * value as unsigned integer. The plus/minus shuffling is necessary as we can + * not directly remove the sign of an arbitrary signed integer as the + * absolute values of INT_MIN and INT_MAX are usually not the same. See + * #1708 for details. + */ + inline number_unsigned_t remove_sign(number_integer_t x) noexcept + { + JSON_ASSERT(x < 0 && x < (std::numeric_limits::max)()); // NOLINT(misc-redundant-expression) + return static_cast(-(x + 1)) + 1; + } + + private: + /// the output of the serializer + output_adapter_t o = nullptr; + + /// a (hopefully) large enough character buffer + std::array number_buffer{{}}; + + /// the locale + const std::lconv* loc = nullptr; + /// the locale's thousand separator character + const char thousands_sep = '\0'; + /// the locale's decimal point character + const char decimal_point = '\0'; + + /// string buffer + std::array string_buffer{{}}; + + /// the indentation character + const char indent_char; + /// the indentation string + string_t indent_string; + + /// error_handler how to react on decoding errors + const error_handler_t error_handler; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + +// #include + + +#include // less +#include // initializer_list +#include // input_iterator_tag, iterator_traits +#include // allocator +#include // for out_of_range +#include // enable_if, is_convertible +#include // pair +#include // vector + +// #include + + +namespace nlohmann +{ + +/// ordered_map: a minimal map-like container that preserves insertion order +/// for use within nlohmann::basic_json +template , + class Allocator = std::allocator>> + struct ordered_map : std::vector, Allocator> +{ + using key_type = Key; + using mapped_type = T; + using Container = std::vector, Allocator>; + using iterator = typename Container::iterator; + using const_iterator = typename Container::const_iterator; + using size_type = typename Container::size_type; + using value_type = typename Container::value_type; + + // Explicit constructors instead of `using Container::Container` + // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4) + ordered_map() noexcept(noexcept(Container())) : Container{} {} + explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {} + template + ordered_map(It first, It last, const Allocator& alloc = Allocator()) + : Container{first, last, alloc} {} + ordered_map(std::initializer_list init, const Allocator& alloc = Allocator() ) + : Container{init, alloc} {} + + std::pair emplace(const key_type& key, T&& t) + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + return {it, false}; + } + } + Container::emplace_back(key, t); + return {--this->end(), true}; + } + + T& operator[](const Key& key) + { + return emplace(key, T{}).first->second; + } + + const T& operator[](const Key& key) const + { + return at(key); + } + + T& at(const Key& key) + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + return it->second; + } + } + + JSON_THROW(std::out_of_range("key not found")); + } + + const T& at(const Key& key) const + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + return it->second; + } + } + + JSON_THROW(std::out_of_range("key not found")); + } + + size_type erase(const Key& key) + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + // Since we cannot move const Keys, re-construct them in place + for (auto next = it; ++next != this->end(); ++it) + { + it->~value_type(); // Destroy but keep allocation + new (&*it) value_type{std::move(*next)}; + } + Container::pop_back(); + return 1; + } + } + return 0; + } + + iterator erase(iterator pos) + { + return erase(pos, std::next(pos)); + } + + iterator erase(iterator first, iterator last) + { + const auto elements_affected = std::distance(first, last); + const auto offset = std::distance(Container::begin(), first); + + // This is the start situation. We need to delete elements_affected + // elements (3 in this example: e, f, g), and need to return an + // iterator past the last deleted element (h in this example). + // Note that offset is the distance from the start of the vector + // to first. We will need this later. + + // [ a, b, c, d, e, f, g, h, i, j ] + // ^ ^ + // first last + + // Since we cannot move const Keys, we re-construct them in place. + // We start at first and re-construct (viz. copy) the elements from + // the back of the vector. Example for first iteration: + + // ,--------. + // v | destroy e and re-construct with h + // [ a, b, c, d, e, f, g, h, i, j ] + // ^ ^ + // it it + elements_affected + + for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it) + { + it->~value_type(); // destroy but keep allocation + new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it + } + + // [ a, b, c, d, h, i, j, h, i, j ] + // ^ ^ + // first last + + // remove the unneeded elements at the end of the vector + Container::resize(this->size() - static_cast(elements_affected)); + + // [ a, b, c, d, h, i, j ] + // ^ ^ + // first last + + // first is now pointing past the last deleted element, but we cannot + // use this iterator, because it may have been invalidated by the + // resize call. Instead, we can return begin() + offset. + return Container::begin() + offset; + } + + size_type count(const Key& key) const + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + return 1; + } + } + return 0; + } + + iterator find(const Key& key) + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + return it; + } + } + return Container::end(); + } + + const_iterator find(const Key& key) const + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + return it; + } + } + return Container::end(); + } + + std::pair insert( value_type&& value ) + { + return emplace(value.first, std::move(value.second)); + } + + std::pair insert( const value_type& value ) + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == value.first) + { + return {it, false}; + } + } + Container::push_back(value); + return {--this->end(), true}; + } + + template + using require_input_iter = typename std::enable_if::iterator_category, + std::input_iterator_tag>::value>::type; + + template> + void insert(InputIt first, InputIt last) + { + for (auto it = first; it != last; ++it) + { + insert(*it); + } + } +}; + +} // namespace nlohmann + + +#if defined(JSON_HAS_CPP_17) + #include +#endif + +/*! +@brief namespace for Niels Lohmann +@see https://github.com/nlohmann +@since version 1.0.0 +*/ +namespace nlohmann +{ + +/*! +@brief a class to store JSON values + +@internal +@invariant The member variables @a m_value and @a m_type have the following +relationship: +- If `m_type == value_t::object`, then `m_value.object != nullptr`. +- If `m_type == value_t::array`, then `m_value.array != nullptr`. +- If `m_type == value_t::string`, then `m_value.string != nullptr`. +The invariants are checked by member function assert_invariant(). + +@note ObjectType trick from https://stackoverflow.com/a/9860911 +@endinternal + +@since version 1.0.0 + +@nosubgrouping +*/ +NLOHMANN_BASIC_JSON_TPL_DECLARATION +class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) +{ + private: + template friend struct detail::external_constructor; + friend ::nlohmann::json_pointer; + + template + friend class ::nlohmann::detail::parser; + friend ::nlohmann::detail::serializer; + template + friend class ::nlohmann::detail::iter_impl; + template + friend class ::nlohmann::detail::binary_writer; + template + friend class ::nlohmann::detail::binary_reader; + template + friend class ::nlohmann::detail::json_sax_dom_parser; + template + friend class ::nlohmann::detail::json_sax_dom_callback_parser; + friend class ::nlohmann::detail::exception; + + /// workaround type for MSVC + using basic_json_t = NLOHMANN_BASIC_JSON_TPL; + + JSON_PRIVATE_UNLESS_TESTED: + // convenience aliases for types residing in namespace detail; + using lexer = ::nlohmann::detail::lexer_base; + + template + static ::nlohmann::detail::parser parser( + InputAdapterType adapter, + detail::parser_callback_tcb = nullptr, + const bool allow_exceptions = true, + const bool ignore_comments = false + ) + { + return ::nlohmann::detail::parser(std::move(adapter), + std::move(cb), allow_exceptions, ignore_comments); + } + + private: + using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t; + template + using internal_iterator = ::nlohmann::detail::internal_iterator; + template + using iter_impl = ::nlohmann::detail::iter_impl; + template + using iteration_proxy = ::nlohmann::detail::iteration_proxy; + template using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator; + + template + using output_adapter_t = ::nlohmann::detail::output_adapter_t; + + template + using binary_reader = ::nlohmann::detail::binary_reader; + template using binary_writer = ::nlohmann::detail::binary_writer; + + JSON_PRIVATE_UNLESS_TESTED: + using serializer = ::nlohmann::detail::serializer; + + public: + using value_t = detail::value_t; + /// JSON Pointer, see @ref nlohmann::json_pointer + using json_pointer = ::nlohmann::json_pointer; + template + using json_serializer = JSONSerializer; + /// how to treat decoding errors + using error_handler_t = detail::error_handler_t; + /// how to treat CBOR tags + using cbor_tag_handler_t = detail::cbor_tag_handler_t; + /// helper type for initializer lists of basic_json values + using initializer_list_t = std::initializer_list>; + + using input_format_t = detail::input_format_t; + /// SAX interface type, see @ref nlohmann::json_sax + using json_sax_t = json_sax; + + //////////////// + // exceptions // + //////////////// + + /// @name exceptions + /// Classes to implement user-defined exceptions. + /// @{ + + using exception = detail::exception; + using parse_error = detail::parse_error; + using invalid_iterator = detail::invalid_iterator; + using type_error = detail::type_error; + using out_of_range = detail::out_of_range; + using other_error = detail::other_error; + + /// @} + + + ///////////////////// + // container types // + ///////////////////// + + /// @name container types + /// The canonic container types to use @ref basic_json like any other STL + /// container. + /// @{ + + /// the type of elements in a basic_json container + using value_type = basic_json; + + /// the type of an element reference + using reference = value_type&; + /// the type of an element const reference + using const_reference = const value_type&; + + /// a type to represent differences between iterators + using difference_type = std::ptrdiff_t; + /// a type to represent container sizes + using size_type = std::size_t; + + /// the allocator type + using allocator_type = AllocatorType; + + /// the type of an element pointer + using pointer = typename std::allocator_traits::pointer; + /// the type of an element const pointer + using const_pointer = typename std::allocator_traits::const_pointer; + + /// an iterator for a basic_json container + using iterator = iter_impl; + /// a const iterator for a basic_json container + using const_iterator = iter_impl; + /// a reverse iterator for a basic_json container + using reverse_iterator = json_reverse_iterator; + /// a const reverse iterator for a basic_json container + using const_reverse_iterator = json_reverse_iterator; + + /// @} + + + /// @brief returns the allocator associated with the container + /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/ + static allocator_type get_allocator() + { + return allocator_type(); + } + + /// @brief returns version information on the library + /// @sa https://json.nlohmann.me/api/basic_json/meta/ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json meta() + { + basic_json result; + + result["copyright"] = "(C) 2013-2022 Niels Lohmann"; + result["name"] = "JSON for Modern C++"; + result["url"] = "https://github.com/nlohmann/json"; + result["version"]["string"] = + std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." + + std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." + + std::to_string(NLOHMANN_JSON_VERSION_PATCH); + result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR; + result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR; + result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH; + +#ifdef _WIN32 + result["platform"] = "win32"; +#elif defined __linux__ + result["platform"] = "linux"; +#elif defined __APPLE__ + result["platform"] = "apple"; +#elif defined __unix__ + result["platform"] = "unix"; +#else + result["platform"] = "unknown"; +#endif + +#if defined(__ICC) || defined(__INTEL_COMPILER) + result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; +#elif defined(__clang__) + result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; +#elif defined(__GNUC__) || defined(__GNUG__) + result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}}; +#elif defined(__HP_cc) || defined(__HP_aCC) + result["compiler"] = "hp" +#elif defined(__IBMCPP__) + result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}}; +#elif defined(_MSC_VER) + result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}}; +#elif defined(__PGI) + result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}}; +#elif defined(__SUNPRO_CC) + result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}}; +#else + result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; +#endif + +#ifdef __cplusplus + result["compiler"]["c++"] = std::to_string(__cplusplus); +#else + result["compiler"]["c++"] = "unknown"; +#endif + return result; + } + + + /////////////////////////// + // JSON value data types // + /////////////////////////// + + /// @name JSON value data types + /// The data types to store a JSON value. These types are derived from + /// the template arguments passed to class @ref basic_json. + /// @{ + + /// @brief object key comparator type + /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/ +#if defined(JSON_HAS_CPP_14) + // Use transparent comparator if possible, combined with perfect forwarding + // on find() and count() calls prevents unnecessary string construction. + using object_comparator_t = std::less<>; +#else + using object_comparator_t = std::less; +#endif + + /// @brief a type for an object + /// @sa https://json.nlohmann.me/api/basic_json/object_t/ + using object_t = ObjectType>>; + + /// @brief a type for an array + /// @sa https://json.nlohmann.me/api/basic_json/array_t/ + using array_t = ArrayType>; + + /// @brief a type for a string + /// @sa https://json.nlohmann.me/api/basic_json/string_t/ + using string_t = StringType; + + /// @brief a type for a boolean + /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/ + using boolean_t = BooleanType; + + /// @brief a type for a number (integer) + /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/ + using number_integer_t = NumberIntegerType; + + /// @brief a type for a number (unsigned) + /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/ + using number_unsigned_t = NumberUnsignedType; + + /// @brief a type for a number (floating-point) + /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/ + using number_float_t = NumberFloatType; + + /// @brief a type for a packed binary type + /// @sa https://json.nlohmann.me/api/basic_json/binary_t/ + using binary_t = nlohmann::byte_container_with_subtype; + + /// @} + + private: + + /// helper for exception-safe object creation + template + JSON_HEDLEY_RETURNS_NON_NULL + static T* create(Args&& ... args) + { + AllocatorType alloc; + using AllocatorTraits = std::allocator_traits>; + + auto deleter = [&](T * obj) + { + AllocatorTraits::deallocate(alloc, obj, 1); + }; + std::unique_ptr obj(AllocatorTraits::allocate(alloc, 1), deleter); + AllocatorTraits::construct(alloc, obj.get(), std::forward(args)...); + JSON_ASSERT(obj != nullptr); + return obj.release(); + } + + //////////////////////// + // JSON value storage // + //////////////////////// + + JSON_PRIVATE_UNLESS_TESTED: + /*! + @brief a JSON value + + The actual storage for a JSON value of the @ref basic_json class. This + union combines the different storage types for the JSON value types + defined in @ref value_t. + + JSON type | value_t type | used type + --------- | --------------- | ------------------------ + object | object | pointer to @ref object_t + array | array | pointer to @ref array_t + string | string | pointer to @ref string_t + boolean | boolean | @ref boolean_t + number | number_integer | @ref number_integer_t + number | number_unsigned | @ref number_unsigned_t + number | number_float | @ref number_float_t + binary | binary | pointer to @ref binary_t + null | null | *no value is stored* + + @note Variable-length types (objects, arrays, and strings) are stored as + pointers. The size of the union should not exceed 64 bits if the default + value types are used. + + @since version 1.0.0 + */ + union json_value + { + /// object (stored with pointer to save storage) + object_t* object; + /// array (stored with pointer to save storage) + array_t* array; + /// string (stored with pointer to save storage) + string_t* string; + /// binary (stored with pointer to save storage) + binary_t* binary; + /// boolean + boolean_t boolean; + /// number (integer) + number_integer_t number_integer; + /// number (unsigned integer) + number_unsigned_t number_unsigned; + /// number (floating-point) + number_float_t number_float; + + /// default constructor (for null values) + json_value() = default; + /// constructor for booleans + json_value(boolean_t v) noexcept : boolean(v) {} + /// constructor for numbers (integer) + json_value(number_integer_t v) noexcept : number_integer(v) {} + /// constructor for numbers (unsigned) + json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} + /// constructor for numbers (floating-point) + json_value(number_float_t v) noexcept : number_float(v) {} + /// constructor for empty values of a given type + json_value(value_t t) + { + switch (t) + { + case value_t::object: + { + object = create(); + break; + } + + case value_t::array: + { + array = create(); + break; + } + + case value_t::string: + { + string = create(""); + break; + } + + case value_t::binary: + { + binary = create(); + break; + } + + case value_t::boolean: + { + boolean = static_cast(false); + break; + } + + case value_t::number_integer: + { + number_integer = static_cast(0); + break; + } + + case value_t::number_unsigned: + { + number_unsigned = static_cast(0); + break; + } + + case value_t::number_float: + { + number_float = static_cast(0.0); + break; + } + + case value_t::null: + { + object = nullptr; // silence warning, see #821 + break; + } + + case value_t::discarded: + default: + { + object = nullptr; // silence warning, see #821 + if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) + { + JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.5", basic_json())); // LCOV_EXCL_LINE + } + break; + } + } + } + + /// constructor for strings + json_value(const string_t& value) : string(create(value)) {} + + /// constructor for rvalue strings + json_value(string_t&& value) : string(create(std::move(value))) {} + + /// constructor for objects + json_value(const object_t& value) : object(create(value)) {} + + /// constructor for rvalue objects + json_value(object_t&& value) : object(create(std::move(value))) {} + + /// constructor for arrays + json_value(const array_t& value) : array(create(value)) {} + + /// constructor for rvalue arrays + json_value(array_t&& value) : array(create(std::move(value))) {} + + /// constructor for binary arrays + json_value(const typename binary_t::container_type& value) : binary(create(value)) {} + + /// constructor for rvalue binary arrays + json_value(typename binary_t::container_type&& value) : binary(create(std::move(value))) {} + + /// constructor for binary arrays (internal type) + json_value(const binary_t& value) : binary(create(value)) {} + + /// constructor for rvalue binary arrays (internal type) + json_value(binary_t&& value) : binary(create(std::move(value))) {} + + void destroy(value_t t) + { + if (t == value_t::array || t == value_t::object) + { + // flatten the current json_value to a heap-allocated stack + std::vector stack; + + // move the top-level items to stack + if (t == value_t::array) + { + stack.reserve(array->size()); + std::move(array->begin(), array->end(), std::back_inserter(stack)); + } + else + { + stack.reserve(object->size()); + for (auto&& it : *object) + { + stack.push_back(std::move(it.second)); + } + } + + while (!stack.empty()) + { + // move the last item to local variable to be processed + basic_json current_item(std::move(stack.back())); + stack.pop_back(); + + // if current_item is array/object, move + // its children to the stack to be processed later + if (current_item.is_array()) + { + std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack)); + + current_item.m_value.array->clear(); + } + else if (current_item.is_object()) + { + for (auto&& it : *current_item.m_value.object) + { + stack.push_back(std::move(it.second)); + } + + current_item.m_value.object->clear(); + } + + // it's now safe that current_item get destructed + // since it doesn't have any children + } + } + + switch (t) + { + case value_t::object: + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, object); + std::allocator_traits::deallocate(alloc, object, 1); + break; + } + + case value_t::array: + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, array); + std::allocator_traits::deallocate(alloc, array, 1); + break; + } + + case value_t::string: + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, string); + std::allocator_traits::deallocate(alloc, string, 1); + break; + } + + case value_t::binary: + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, binary); + std::allocator_traits::deallocate(alloc, binary, 1); + break; + } + + case value_t::null: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::discarded: + default: + { + break; + } + } + } + }; + + private: + /*! + @brief checks the class invariants + + This function asserts the class invariants. It needs to be called at the + end of every constructor to make sure that created objects respect the + invariant. Furthermore, it has to be called each time the type of a JSON + value is changed, because the invariant expresses a relationship between + @a m_type and @a m_value. + + Furthermore, the parent relation is checked for arrays and objects: If + @a check_parents true and the value is an array or object, then the + container's elements must have the current value as parent. + + @param[in] check_parents whether the parent relation should be checked. + The value is true by default and should only be set to false + during destruction of objects when the invariant does not + need to hold. + */ + void assert_invariant(bool check_parents = true) const noexcept + { + JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr); + JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr); + JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr); + JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr); + +#if JSON_DIAGNOSTICS + JSON_TRY + { + // cppcheck-suppress assertWithSideEffect + JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j) + { + return j.m_parent == this; + })); + } + JSON_CATCH(...) {} // LCOV_EXCL_LINE +#endif + static_cast(check_parents); + } + + void set_parents() + { +#if JSON_DIAGNOSTICS + switch (m_type) + { + case value_t::array: + { + for (auto& element : *m_value.array) + { + element.m_parent = this; + } + break; + } + + case value_t::object: + { + for (auto& element : *m_value.object) + { + element.second.m_parent = this; + } + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + break; + } +#endif + } + + iterator set_parents(iterator it, typename iterator::difference_type count_set_parents) + { +#if JSON_DIAGNOSTICS + for (typename iterator::difference_type i = 0; i < count_set_parents; ++i) + { + (it + i)->m_parent = this; + } +#else + static_cast(count_set_parents); +#endif + return it; + } + + reference set_parent(reference j, std::size_t old_capacity = static_cast(-1)) + { +#if JSON_DIAGNOSTICS + if (old_capacity != static_cast(-1)) + { + // see https://github.com/nlohmann/json/issues/2838 + JSON_ASSERT(type() == value_t::array); + if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) + { + // capacity has changed: update all parents + set_parents(); + return j; + } + } + + // ordered_json uses a vector internally, so pointers could have + // been invalidated; see https://github.com/nlohmann/json/issues/2962 +#ifdef JSON_HEDLEY_MSVC_VERSION +#pragma warning(push ) +#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr +#endif + if (detail::is_ordered_map::value) + { + set_parents(); + return j; + } +#ifdef JSON_HEDLEY_MSVC_VERSION +#pragma warning( pop ) +#endif + + j.m_parent = this; +#else + static_cast(j); + static_cast(old_capacity); +#endif + return j; + } + + public: + ////////////////////////// + // JSON parser callback // + ////////////////////////// + + /// @brief parser event types + /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/ + using parse_event_t = detail::parse_event_t; + + /// @brief per-element parser callback type + /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/ + using parser_callback_t = detail::parser_callback_t; + + ////////////////// + // constructors // + ////////////////// + + /// @name constructors and destructors + /// Constructors of class @ref basic_json, copy/move constructor, copy + /// assignment, static functions creating objects, and the destructor. + /// @{ + + /// @brief create an empty value with a given type + /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ + basic_json(const value_t v) + : m_type(v), m_value(v) + { + assert_invariant(); + } + + /// @brief create a null object + /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ + basic_json(std::nullptr_t = nullptr) noexcept + : basic_json(value_t::null) + { + assert_invariant(); + } + + /// @brief create a JSON value from compatible types + /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ + template < typename CompatibleType, + typename U = detail::uncvref_t, + detail::enable_if_t < + !detail::is_basic_json::value && detail::is_compatible_type::value, int > = 0 > + basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape) + JSONSerializer::to_json(std::declval(), + std::forward(val)))) + { + JSONSerializer::to_json(*this, std::forward(val)); + set_parents(); + assert_invariant(); + } + + /// @brief create a JSON value from an existing one + /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ + template < typename BasicJsonType, + detail::enable_if_t < + detail::is_basic_json::value&& !std::is_same::value, int > = 0 > + basic_json(const BasicJsonType& val) + { + using other_boolean_t = typename BasicJsonType::boolean_t; + using other_number_float_t = typename BasicJsonType::number_float_t; + using other_number_integer_t = typename BasicJsonType::number_integer_t; + using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using other_string_t = typename BasicJsonType::string_t; + using other_object_t = typename BasicJsonType::object_t; + using other_array_t = typename BasicJsonType::array_t; + using other_binary_t = typename BasicJsonType::binary_t; + + switch (val.type()) + { + case value_t::boolean: + JSONSerializer::to_json(*this, val.template get()); + break; + case value_t::number_float: + JSONSerializer::to_json(*this, val.template get()); + break; + case value_t::number_integer: + JSONSerializer::to_json(*this, val.template get()); + break; + case value_t::number_unsigned: + JSONSerializer::to_json(*this, val.template get()); + break; + case value_t::string: + JSONSerializer::to_json(*this, val.template get_ref()); + break; + case value_t::object: + JSONSerializer::to_json(*this, val.template get_ref()); + break; + case value_t::array: + JSONSerializer::to_json(*this, val.template get_ref()); + break; + case value_t::binary: + JSONSerializer::to_json(*this, val.template get_ref()); + break; + case value_t::null: + *this = nullptr; + break; + case value_t::discarded: + m_type = value_t::discarded; + break; + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + set_parents(); + assert_invariant(); + } + + /// @brief create a container (array or object) from an initializer list + /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ + basic_json(initializer_list_t init, + bool type_deduction = true, + value_t manual_type = value_t::array) + { + // check if each element is an array with two elements whose first + // element is a string + bool is_an_object = std::all_of(init.begin(), init.end(), + [](const detail::json_ref& element_ref) + { + return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string(); + }); + + // adjust type if type deduction is not wanted + if (!type_deduction) + { + // if array is wanted, do not create an object though possible + if (manual_type == value_t::array) + { + is_an_object = false; + } + + // if object is wanted but impossible, throw an exception + if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) + { + JSON_THROW(type_error::create(301, "cannot create object from initializer list", basic_json())); + } + } + + if (is_an_object) + { + // the initializer list is a list of pairs -> create object + m_type = value_t::object; + m_value = value_t::object; + + for (auto& element_ref : init) + { + auto element = element_ref.moved_or_copied(); + m_value.object->emplace( + std::move(*((*element.m_value.array)[0].m_value.string)), + std::move((*element.m_value.array)[1])); + } + } + else + { + // the initializer list describes an array -> create array + m_type = value_t::array; + m_value.array = create(init.begin(), init.end()); + } + + set_parents(); + assert_invariant(); + } + + /// @brief explicitly create a binary array (without subtype) + /// @sa https://json.nlohmann.me/api/basic_json/binary/ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json binary(const typename binary_t::container_type& init) + { + auto res = basic_json(); + res.m_type = value_t::binary; + res.m_value = init; + return res; + } + + /// @brief explicitly create a binary array (with subtype) + /// @sa https://json.nlohmann.me/api/basic_json/binary/ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype) + { + auto res = basic_json(); + res.m_type = value_t::binary; + res.m_value = binary_t(init, subtype); + return res; + } + + /// @brief explicitly create a binary array + /// @sa https://json.nlohmann.me/api/basic_json/binary/ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json binary(typename binary_t::container_type&& init) + { + auto res = basic_json(); + res.m_type = value_t::binary; + res.m_value = std::move(init); + return res; + } + + /// @brief explicitly create a binary array (with subtype) + /// @sa https://json.nlohmann.me/api/basic_json/binary/ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype) + { + auto res = basic_json(); + res.m_type = value_t::binary; + res.m_value = binary_t(std::move(init), subtype); + return res; + } + + /// @brief explicitly create an array from an initializer list + /// @sa https://json.nlohmann.me/api/basic_json/array/ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json array(initializer_list_t init = {}) + { + return basic_json(init, false, value_t::array); + } + + /// @brief explicitly create an object from an initializer list + /// @sa https://json.nlohmann.me/api/basic_json/object/ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json object(initializer_list_t init = {}) + { + return basic_json(init, false, value_t::object); + } + + /// @brief construct an array with count copies of given value + /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ + basic_json(size_type cnt, const basic_json& val) + : m_type(value_t::array) + { + m_value.array = create(cnt, val); + set_parents(); + assert_invariant(); + } + + /// @brief construct a JSON container given an iterator range + /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ + template < class InputIT, typename std::enable_if < + std::is_same::value || + std::is_same::value, int >::type = 0 > + basic_json(InputIT first, InputIT last) + { + JSON_ASSERT(first.m_object != nullptr); + JSON_ASSERT(last.m_object != nullptr); + + // make sure iterator fits the current value + if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) + { + JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", basic_json())); + } + + // copy type from first iterator + m_type = first.m_object->m_type; + + // check if iterator range is complete for primitive values + switch (m_type) + { + case value_t::boolean: + case value_t::number_float: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::string: + { + if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin() + || !last.m_it.primitive_iterator.is_end())) + { + JSON_THROW(invalid_iterator::create(204, "iterators out of range", *first.m_object)); + } + break; + } + + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::binary: + case value_t::discarded: + default: + break; + } + + switch (m_type) + { + case value_t::number_integer: + { + m_value.number_integer = first.m_object->m_value.number_integer; + break; + } + + case value_t::number_unsigned: + { + m_value.number_unsigned = first.m_object->m_value.number_unsigned; + break; + } + + case value_t::number_float: + { + m_value.number_float = first.m_object->m_value.number_float; + break; + } + + case value_t::boolean: + { + m_value.boolean = first.m_object->m_value.boolean; + break; + } + + case value_t::string: + { + m_value = *first.m_object->m_value.string; + break; + } + + case value_t::object: + { + m_value.object = create(first.m_it.object_iterator, + last.m_it.object_iterator); + break; + } + + case value_t::array: + { + m_value.array = create(first.m_it.array_iterator, + last.m_it.array_iterator); + break; + } + + case value_t::binary: + { + m_value = *first.m_object->m_value.binary; + break; + } + + case value_t::null: + case value_t::discarded: + default: + JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()), *first.m_object)); + } + + set_parents(); + assert_invariant(); + } + + + /////////////////////////////////////// + // other constructors and destructor // + /////////////////////////////////////// + + template, + std::is_same>::value, int> = 0 > + basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {} + + /// @brief copy constructor + /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ + basic_json(const basic_json& other) + : m_type(other.m_type) + { + // check of passed value is valid + other.assert_invariant(); + + switch (m_type) + { + case value_t::object: + { + m_value = *other.m_value.object; + break; + } + + case value_t::array: + { + m_value = *other.m_value.array; + break; + } + + case value_t::string: + { + m_value = *other.m_value.string; + break; + } + + case value_t::boolean: + { + m_value = other.m_value.boolean; + break; + } + + case value_t::number_integer: + { + m_value = other.m_value.number_integer; + break; + } + + case value_t::number_unsigned: + { + m_value = other.m_value.number_unsigned; + break; + } + + case value_t::number_float: + { + m_value = other.m_value.number_float; + break; + } + + case value_t::binary: + { + m_value = *other.m_value.binary; + break; + } + + case value_t::null: + case value_t::discarded: + default: + break; + } + + set_parents(); + assert_invariant(); + } + + /// @brief move constructor + /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ + basic_json(basic_json&& other) noexcept + : m_type(std::move(other.m_type)), + m_value(std::move(other.m_value)) + { + // check that passed value is valid + other.assert_invariant(false); + + // invalidate payload + other.m_type = value_t::null; + other.m_value = {}; + + set_parents(); + assert_invariant(); + } + + /// @brief copy assignment + /// @sa https://json.nlohmann.me/api/basic_json/operator=/ + basic_json& operator=(basic_json other) noexcept ( + std::is_nothrow_move_constructible::value&& + std::is_nothrow_move_assignable::value&& + std::is_nothrow_move_constructible::value&& + std::is_nothrow_move_assignable::value + ) + { + // check that passed value is valid + other.assert_invariant(); + + using std::swap; + swap(m_type, other.m_type); + swap(m_value, other.m_value); + + set_parents(); + assert_invariant(); + return *this; + } + + /// @brief destructor + /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/ + ~basic_json() noexcept + { + assert_invariant(false); + m_value.destroy(m_type); + } + + /// @} + + public: + /////////////////////// + // object inspection // + /////////////////////// + + /// @name object inspection + /// Functions to inspect the type of a JSON value. + /// @{ + + /// @brief serialization + /// @sa https://json.nlohmann.me/api/basic_json/dump/ + string_t dump(const int indent = -1, + const char indent_char = ' ', + const bool ensure_ascii = false, + const error_handler_t error_handler = error_handler_t::strict) const + { + string_t result; + serializer s(detail::output_adapter(result), indent_char, error_handler); + + if (indent >= 0) + { + s.dump(*this, true, ensure_ascii, static_cast(indent)); + } + else + { + s.dump(*this, false, ensure_ascii, 0); + } + + return result; + } + + /// @brief return the type of the JSON value (explicit) + /// @sa https://json.nlohmann.me/api/basic_json/type/ + constexpr value_t type() const noexcept + { + return m_type; + } + + /// @brief return whether type is primitive + /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/ + constexpr bool is_primitive() const noexcept + { + return is_null() || is_string() || is_boolean() || is_number() || is_binary(); + } + + /// @brief return whether type is structured + /// @sa https://json.nlohmann.me/api/basic_json/is_structured/ + constexpr bool is_structured() const noexcept + { + return is_array() || is_object(); + } + + /// @brief return whether value is null + /// @sa https://json.nlohmann.me/api/basic_json/is_null/ + constexpr bool is_null() const noexcept + { + return m_type == value_t::null; + } + + /// @brief return whether value is a boolean + /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/ + constexpr bool is_boolean() const noexcept + { + return m_type == value_t::boolean; + } + + /// @brief return whether value is a number + /// @sa https://json.nlohmann.me/api/basic_json/is_number/ + constexpr bool is_number() const noexcept + { + return is_number_integer() || is_number_float(); + } + + /// @brief return whether value is an integer number + /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/ + constexpr bool is_number_integer() const noexcept + { + return m_type == value_t::number_integer || m_type == value_t::number_unsigned; + } + + /// @brief return whether value is an unsigned integer number + /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/ + constexpr bool is_number_unsigned() const noexcept + { + return m_type == value_t::number_unsigned; + } + + /// @brief return whether value is a floating-point number + /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/ + constexpr bool is_number_float() const noexcept + { + return m_type == value_t::number_float; + } + + /// @brief return whether value is an object + /// @sa https://json.nlohmann.me/api/basic_json/is_object/ + constexpr bool is_object() const noexcept + { + return m_type == value_t::object; + } + + /// @brief return whether value is an array + /// @sa https://json.nlohmann.me/api/basic_json/is_array/ + constexpr bool is_array() const noexcept + { + return m_type == value_t::array; + } + + /// @brief return whether value is a string + /// @sa https://json.nlohmann.me/api/basic_json/is_string/ + constexpr bool is_string() const noexcept + { + return m_type == value_t::string; + } + + /// @brief return whether value is a binary array + /// @sa https://json.nlohmann.me/api/basic_json/is_binary/ + constexpr bool is_binary() const noexcept + { + return m_type == value_t::binary; + } + + /// @brief return whether value is discarded + /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/ + constexpr bool is_discarded() const noexcept + { + return m_type == value_t::discarded; + } + + /// @brief return the type of the JSON value (implicit) + /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/ + constexpr operator value_t() const noexcept + { + return m_type; + } + + /// @} + + private: + ////////////////// + // value access // + ////////////////// + + /// get a boolean (explicit) + boolean_t get_impl(boolean_t* /*unused*/) const + { + if (JSON_HEDLEY_LIKELY(is_boolean())) + { + return m_value.boolean; + } + + JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()), *this)); + } + + /// get a pointer to the value (object) + object_t* get_impl_ptr(object_t* /*unused*/) noexcept + { + return is_object() ? m_value.object : nullptr; + } + + /// get a pointer to the value (object) + constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept + { + return is_object() ? m_value.object : nullptr; + } + + /// get a pointer to the value (array) + array_t* get_impl_ptr(array_t* /*unused*/) noexcept + { + return is_array() ? m_value.array : nullptr; + } + + /// get a pointer to the value (array) + constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept + { + return is_array() ? m_value.array : nullptr; + } + + /// get a pointer to the value (string) + string_t* get_impl_ptr(string_t* /*unused*/) noexcept + { + return is_string() ? m_value.string : nullptr; + } + + /// get a pointer to the value (string) + constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept + { + return is_string() ? m_value.string : nullptr; + } + + /// get a pointer to the value (boolean) + boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept + { + return is_boolean() ? &m_value.boolean : nullptr; + } + + /// get a pointer to the value (boolean) + constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept + { + return is_boolean() ? &m_value.boolean : nullptr; + } + + /// get a pointer to the value (integer number) + number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept + { + return is_number_integer() ? &m_value.number_integer : nullptr; + } + + /// get a pointer to the value (integer number) + constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept + { + return is_number_integer() ? &m_value.number_integer : nullptr; + } + + /// get a pointer to the value (unsigned number) + number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept + { + return is_number_unsigned() ? &m_value.number_unsigned : nullptr; + } + + /// get a pointer to the value (unsigned number) + constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept + { + return is_number_unsigned() ? &m_value.number_unsigned : nullptr; + } + + /// get a pointer to the value (floating-point number) + number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept + { + return is_number_float() ? &m_value.number_float : nullptr; + } + + /// get a pointer to the value (floating-point number) + constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept + { + return is_number_float() ? &m_value.number_float : nullptr; + } + + /// get a pointer to the value (binary) + binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept + { + return is_binary() ? m_value.binary : nullptr; + } + + /// get a pointer to the value (binary) + constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept + { + return is_binary() ? m_value.binary : nullptr; + } + + /*! + @brief helper function to implement get_ref() + + This function helps to implement get_ref() without code duplication for + const and non-const overloads + + @tparam ThisType will be deduced as `basic_json` or `const basic_json` + + @throw type_error.303 if ReferenceType does not match underlying value + type of the current JSON + */ + template + static ReferenceType get_ref_impl(ThisType& obj) + { + // delegate the call to get_ptr<>() + auto* ptr = obj.template get_ptr::type>(); + + if (JSON_HEDLEY_LIKELY(ptr != nullptr)) + { + return *ptr; + } + + JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()), obj)); + } + + public: + /// @name value access + /// Direct access to the stored value of a JSON value. + /// @{ + + /// @brief get a pointer value (implicit) + /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/ + template::value, int>::type = 0> + auto get_ptr() noexcept -> decltype(std::declval().get_impl_ptr(std::declval())) + { + // delegate the call to get_impl_ptr<>() + return get_impl_ptr(static_cast(nullptr)); + } + + /// @brief get a pointer value (implicit) + /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/ + template < typename PointerType, typename std::enable_if < + std::is_pointer::value&& + std::is_const::type>::value, int >::type = 0 > + constexpr auto get_ptr() const noexcept -> decltype(std::declval().get_impl_ptr(std::declval())) + { + // delegate the call to get_impl_ptr<>() const + return get_impl_ptr(static_cast(nullptr)); + } + + private: + /*! + @brief get a value (explicit) + + Explicit type conversion between the JSON value and a compatible value + which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) + and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). + The value is converted by calling the @ref json_serializer + `from_json()` method. + + The function is equivalent to executing + @code {.cpp} + ValueType ret; + JSONSerializer::from_json(*this, ret); + return ret; + @endcode + + This overloads is chosen if: + - @a ValueType is not @ref basic_json, + - @ref json_serializer has a `from_json()` method of the form + `void from_json(const basic_json&, ValueType&)`, and + - @ref json_serializer does not have a `from_json()` method of + the form `ValueType from_json(const basic_json&)` + + @tparam ValueType the returned value type + + @return copy of the JSON value, converted to @a ValueType + + @throw what @ref json_serializer `from_json()` method throws + + @liveexample{The example below shows several conversions from JSON values + to other types. There a few things to note: (1) Floating-point numbers can + be converted to integers\, (2) A JSON array can be converted to a standard + `std::vector`\, (3) A JSON object can be converted to C++ + associative containers such as `std::unordered_map`.,get__ValueType_const} + + @since version 2.1.0 + */ + template < typename ValueType, + detail::enable_if_t < + detail::is_default_constructible::value&& + detail::has_from_json::value, + int > = 0 > + ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept( + JSONSerializer::from_json(std::declval(), std::declval()))) + { + auto ret = ValueType(); + JSONSerializer::from_json(*this, ret); + return ret; + } + + /*! + @brief get a value (explicit); special case + + Explicit type conversion between the JSON value and a compatible value + which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) + and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). + The value is converted by calling the @ref json_serializer + `from_json()` method. + + The function is equivalent to executing + @code {.cpp} + return JSONSerializer::from_json(*this); + @endcode + + This overloads is chosen if: + - @a ValueType is not @ref basic_json and + - @ref json_serializer has a `from_json()` method of the form + `ValueType from_json(const basic_json&)` + + @note If @ref json_serializer has both overloads of + `from_json()`, this one is chosen. + + @tparam ValueType the returned value type + + @return copy of the JSON value, converted to @a ValueType + + @throw what @ref json_serializer `from_json()` method throws + + @since version 2.1.0 + */ + template < typename ValueType, + detail::enable_if_t < + detail::has_non_default_from_json::value, + int > = 0 > + ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept( + JSONSerializer::from_json(std::declval()))) + { + return JSONSerializer::from_json(*this); + } + + /*! + @brief get special-case overload + + This overloads converts the current @ref basic_json in a different + @ref basic_json type + + @tparam BasicJsonType == @ref basic_json + + @return a copy of *this, converted into @a BasicJsonType + + @complexity Depending on the implementation of the called `from_json()` + method. + + @since version 3.2.0 + */ + template < typename BasicJsonType, + detail::enable_if_t < + detail::is_basic_json::value, + int > = 0 > + BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const + { + return *this; + } + + /*! + @brief get special-case overload + + This overloads avoids a lot of template boilerplate, it can be seen as the + identity method + + @tparam BasicJsonType == @ref basic_json + + @return a copy of *this + + @complexity Constant. + + @since version 2.1.0 + */ + template::value, + int> = 0> + basic_json get_impl(detail::priority_tag<3> /*unused*/) const + { + return *this; + } + + /*! + @brief get a pointer value (explicit) + @copydoc get() + */ + template::value, + int> = 0> + constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept + -> decltype(std::declval().template get_ptr()) + { + // delegate the call to get_ptr + return get_ptr(); + } + + public: + /*! + @brief get a (pointer) value (explicit) + + Performs explicit type conversion between the JSON value and a compatible value if required. + + - If the requested type is a pointer to the internally stored JSON value that pointer is returned. + No copies are made. + + - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible + from the current @ref basic_json. + + - Otherwise the value is converted by calling the @ref json_serializer `from_json()` + method. + + @tparam ValueTypeCV the provided value type + @tparam ValueType the returned value type + + @return copy of the JSON value, converted to @tparam ValueType if necessary + + @throw what @ref json_serializer `from_json()` method throws if conversion is required + + @since version 2.1.0 + */ + template < typename ValueTypeCV, typename ValueType = detail::uncvref_t> +#if defined(JSON_HAS_CPP_14) + constexpr +#endif + auto get() const noexcept( + noexcept(std::declval().template get_impl(detail::priority_tag<4> {}))) + -> decltype(std::declval().template get_impl(detail::priority_tag<4> {})) + { + // we cannot static_assert on ValueTypeCV being non-const, because + // there is support for get(), which is why we + // still need the uncvref + static_assert(!std::is_reference::value, + "get() cannot be used with reference types, you might want to use get_ref()"); + return get_impl(detail::priority_tag<4> {}); + } + + /*! + @brief get a pointer value (explicit) + + Explicit pointer access to the internally stored JSON value. No copies are + made. + + @warning The pointer becomes invalid if the underlying JSON object + changes. + + @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref + object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, + @ref number_unsigned_t, or @ref number_float_t. + + @return pointer to the internally stored JSON value if the requested + pointer type @a PointerType fits to the JSON value; `nullptr` otherwise + + @complexity Constant. + + @liveexample{The example below shows how pointers to internal values of a + JSON value can be requested. Note that no type conversions are made and a + `nullptr` is returned if the value and the requested pointer type does not + match.,get__PointerType} + + @sa see @ref get_ptr() for explicit pointer-member access + + @since version 1.0.0 + */ + template::value, int>::type = 0> + auto get() noexcept -> decltype(std::declval().template get_ptr()) + { + // delegate the call to get_ptr + return get_ptr(); + } + + /// @brief get a value (explicit) + /// @sa https://json.nlohmann.me/api/basic_json/get_to/ + template < typename ValueType, + detail::enable_if_t < + !detail::is_basic_json::value&& + detail::has_from_json::value, + int > = 0 > + ValueType & get_to(ValueType& v) const noexcept(noexcept( + JSONSerializer::from_json(std::declval(), v))) + { + JSONSerializer::from_json(*this, v); + return v; + } + + // specialization to allow calling get_to with a basic_json value + // see https://github.com/nlohmann/json/issues/2175 + template::value, + int> = 0> + ValueType & get_to(ValueType& v) const + { + v = *this; + return v; + } + + template < + typename T, std::size_t N, + typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + detail::enable_if_t < + detail::has_from_json::value, int > = 0 > + Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + noexcept(noexcept(JSONSerializer::from_json( + std::declval(), v))) + { + JSONSerializer::from_json(*this, v); + return v; + } + + /// @brief get a reference value (implicit) + /// @sa https://json.nlohmann.me/api/basic_json/get_ref/ + template::value, int>::type = 0> + ReferenceType get_ref() + { + // delegate call to get_ref_impl + return get_ref_impl(*this); + } + + /// @brief get a reference value (implicit) + /// @sa https://json.nlohmann.me/api/basic_json/get_ref/ + template < typename ReferenceType, typename std::enable_if < + std::is_reference::value&& + std::is_const::type>::value, int >::type = 0 > + ReferenceType get_ref() const + { + // delegate call to get_ref_impl + return get_ref_impl(*this); + } + + /*! + @brief get a value (implicit) + + Implicit type conversion between the JSON value and a compatible value. + The call is realized by calling @ref get() const. + + @tparam ValueType non-pointer type compatible to the JSON value, for + instance `int` for JSON integer numbers, `bool` for JSON booleans, or + `std::vector` types for JSON arrays. The character type of @ref string_t + as well as an initializer list of this type is excluded to avoid + ambiguities as these types implicitly convert to `std::string`. + + @return copy of the JSON value, converted to type @a ValueType + + @throw type_error.302 in case passed type @a ValueType is incompatible + to the JSON value type (e.g., the JSON value is of type boolean, but a + string is requested); see example below + + @complexity Linear in the size of the JSON value. + + @liveexample{The example below shows several conversions from JSON values + to other types. There a few things to note: (1) Floating-point numbers can + be converted to integers\, (2) A JSON array can be converted to a standard + `std::vector`\, (3) A JSON object can be converted to C++ + associative containers such as `std::unordered_map`.,operator__ValueType} + + @since version 1.0.0 + */ + template < typename ValueType, typename std::enable_if < + detail::conjunction < + detail::negation>, + detail::negation>, + detail::negation>>, + detail::negation>, + detail::negation>, + detail::negation>>, + +#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914)) + detail::negation>, +#endif + detail::is_detected_lazy + >::value, int >::type = 0 > + JSON_EXPLICIT operator ValueType() const + { + // delegate the call to get<>() const + return get(); + } + + /// @brief get a binary value + /// @sa https://json.nlohmann.me/api/basic_json/get_binary/ + binary_t& get_binary() + { + if (!is_binary()) + { + JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this)); + } + + return *get_ptr(); + } + + /// @brief get a binary value + /// @sa https://json.nlohmann.me/api/basic_json/get_binary/ + const binary_t& get_binary() const + { + if (!is_binary()) + { + JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this)); + } + + return *get_ptr(); + } + + /// @} + + + //////////////////// + // element access // + //////////////////// + + /// @name element access + /// Access to the JSON value. + /// @{ + + /// @brief access specified array element with bounds checking + /// @sa https://json.nlohmann.me/api/basic_json/at/ + reference at(size_type idx) + { + // at only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + JSON_TRY + { + return set_parent(m_value.array->at(idx)); + } + JSON_CATCH (std::out_of_range&) + { + // create better exception explanation + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this)); + } + } + else + { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); + } + } + + /// @brief access specified array element with bounds checking + /// @sa https://json.nlohmann.me/api/basic_json/at/ + const_reference at(size_type idx) const + { + // at only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + JSON_TRY + { + return m_value.array->at(idx); + } + JSON_CATCH (std::out_of_range&) + { + // create better exception explanation + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this)); + } + } + else + { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); + } + } + + /// @brief access specified object element with bounds checking + /// @sa https://json.nlohmann.me/api/basic_json/at/ + reference at(const typename object_t::key_type& key) + { + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + JSON_TRY + { + return set_parent(m_value.object->at(key)); + } + JSON_CATCH (std::out_of_range&) + { + // create better exception explanation + JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this)); + } + } + else + { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); + } + } + + /// @brief access specified object element with bounds checking + /// @sa https://json.nlohmann.me/api/basic_json/at/ + const_reference at(const typename object_t::key_type& key) const + { + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + JSON_TRY + { + return m_value.object->at(key); + } + JSON_CATCH (std::out_of_range&) + { + // create better exception explanation + JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this)); + } + } + else + { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); + } + } + + /// @brief access specified array element + /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ + reference operator[](size_type idx) + { + // implicitly convert null value to an empty array + if (is_null()) + { + m_type = value_t::array; + m_value.array = create(); + assert_invariant(); + } + + // operator[] only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + // fill up array with null values if given idx is outside range + if (idx >= m_value.array->size()) + { +#if JSON_DIAGNOSTICS + // remember array size & capacity before resizing + const auto old_size = m_value.array->size(); + const auto old_capacity = m_value.array->capacity(); +#endif + m_value.array->resize(idx + 1); + +#if JSON_DIAGNOSTICS + if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) + { + // capacity has changed: update all parents + set_parents(); + } + else + { + // set parent for values added above + set_parents(begin() + static_cast(old_size), static_cast(idx + 1 - old_size)); + } +#endif + assert_invariant(); + } + + return m_value.array->operator[](idx); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this)); + } + + /// @brief access specified array element + /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ + const_reference operator[](size_type idx) const + { + // const operator[] only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + return m_value.array->operator[](idx); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this)); + } + + /// @brief access specified object element + /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ + reference operator[](const typename object_t::key_type& key) + { + // implicitly convert null value to an empty object + if (is_null()) + { + m_type = value_t::object; + m_value.object = create(); + assert_invariant(); + } + + // operator[] only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + return set_parent(m_value.object->operator[](key)); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); + } + + /// @brief access specified object element + /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ + const_reference operator[](const typename object_t::key_type& key) const + { + // const operator[] only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + JSON_ASSERT(m_value.object->find(key) != m_value.object->end()); + return m_value.object->find(key)->second; + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); + } + + /// @brief access specified object element + /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ + template + JSON_HEDLEY_NON_NULL(2) + reference operator[](T* key) + { + // implicitly convert null to object + if (is_null()) + { + m_type = value_t::object; + m_value = value_t::object; + assert_invariant(); + } + + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + return set_parent(m_value.object->operator[](key)); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); + } + + /// @brief access specified object element + /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ + template + JSON_HEDLEY_NON_NULL(2) + const_reference operator[](T* key) const + { + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + JSON_ASSERT(m_value.object->find(key) != m_value.object->end()); + return m_value.object->find(key)->second; + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); + } + + /// @brief access specified object element with default value + /// @sa https://json.nlohmann.me/api/basic_json/value/ + /// using std::is_convertible in a std::enable_if will fail when using explicit conversions + template < class ValueType, typename std::enable_if < + detail::is_getable::value + && !std::is_same::value, int >::type = 0 > + ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const + { + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + // if key is found, return value and given default value otherwise + const auto it = find(key); + if (it != end()) + { + return it->template get(); + } + + return default_value; + } + + JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this)); + } + + /// @brief access specified object element with default value + /// @sa https://json.nlohmann.me/api/basic_json/value/ + /// overload for a default value of type const char* + string_t value(const typename object_t::key_type& key, const char* default_value) const + { + return value(key, string_t(default_value)); + } + + /// @brief access specified object element via JSON Pointer with default value + /// @sa https://json.nlohmann.me/api/basic_json/value/ + template::value, int>::type = 0> + ValueType value(const json_pointer& ptr, const ValueType& default_value) const + { + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + // if pointer resolves a value, return it or use default value + JSON_TRY + { + return ptr.get_checked(this).template get(); + } + JSON_INTERNAL_CATCH (out_of_range&) + { + return default_value; + } + } + + JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this)); + } + + /// @brief access specified object element via JSON Pointer with default value + /// @sa https://json.nlohmann.me/api/basic_json/value/ + /// overload for a default value of type const char* + JSON_HEDLEY_NON_NULL(3) + string_t value(const json_pointer& ptr, const char* default_value) const + { + return value(ptr, string_t(default_value)); + } + + /// @brief access the first element + /// @sa https://json.nlohmann.me/api/basic_json/front/ + reference front() + { + return *begin(); + } + + /// @brief access the first element + /// @sa https://json.nlohmann.me/api/basic_json/front/ + const_reference front() const + { + return *cbegin(); + } + + /// @brief access the last element + /// @sa https://json.nlohmann.me/api/basic_json/back/ + reference back() + { + auto tmp = end(); + --tmp; + return *tmp; + } + + /// @brief access the last element + /// @sa https://json.nlohmann.me/api/basic_json/back/ + const_reference back() const + { + auto tmp = cend(); + --tmp; + return *tmp; + } + + /// @brief remove element given an iterator + /// @sa https://json.nlohmann.me/api/basic_json/erase/ + template < class IteratorType, typename std::enable_if < + std::is_same::value || + std::is_same::value, int >::type + = 0 > + IteratorType erase(IteratorType pos) + { + // make sure iterator fits the current value + if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); + } + + IteratorType result = end(); + + switch (m_type) + { + case value_t::boolean: + case value_t::number_float: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::string: + case value_t::binary: + { + if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin())) + { + JSON_THROW(invalid_iterator::create(205, "iterator out of range", *this)); + } + + if (is_string()) + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, m_value.string); + std::allocator_traits::deallocate(alloc, m_value.string, 1); + m_value.string = nullptr; + } + else if (is_binary()) + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, m_value.binary); + std::allocator_traits::deallocate(alloc, m_value.binary, 1); + m_value.binary = nullptr; + } + + m_type = value_t::null; + assert_invariant(); + break; + } + + case value_t::object: + { + result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); + break; + } + + case value_t::array: + { + result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); + break; + } + + case value_t::null: + case value_t::discarded: + default: + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); + } + + return result; + } + + /// @brief remove elements given an iterator range + /// @sa https://json.nlohmann.me/api/basic_json/erase/ + template < class IteratorType, typename std::enable_if < + std::is_same::value || + std::is_same::value, int >::type + = 0 > + IteratorType erase(IteratorType first, IteratorType last) + { + // make sure iterator fits the current value + if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) + { + JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", *this)); + } + + IteratorType result = end(); + + switch (m_type) + { + case value_t::boolean: + case value_t::number_float: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::string: + case value_t::binary: + { + if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin() + || !last.m_it.primitive_iterator.is_end())) + { + JSON_THROW(invalid_iterator::create(204, "iterators out of range", *this)); + } + + if (is_string()) + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, m_value.string); + std::allocator_traits::deallocate(alloc, m_value.string, 1); + m_value.string = nullptr; + } + else if (is_binary()) + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, m_value.binary); + std::allocator_traits::deallocate(alloc, m_value.binary, 1); + m_value.binary = nullptr; + } + + m_type = value_t::null; + assert_invariant(); + break; + } + + case value_t::object: + { + result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, + last.m_it.object_iterator); + break; + } + + case value_t::array: + { + result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, + last.m_it.array_iterator); + break; + } + + case value_t::null: + case value_t::discarded: + default: + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); + } + + return result; + } + + /// @brief remove element from a JSON object given a key + /// @sa https://json.nlohmann.me/api/basic_json/erase/ + size_type erase(const typename object_t::key_type& key) + { + // this erase only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + return m_value.object->erase(key); + } + + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); + } + + /// @brief remove element from a JSON array given an index + /// @sa https://json.nlohmann.me/api/basic_json/erase/ + void erase(const size_type idx) + { + // this erase only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + if (JSON_HEDLEY_UNLIKELY(idx >= size())) + { + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this)); + } + + m_value.array->erase(m_value.array->begin() + static_cast(idx)); + } + else + { + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); + } + } + + /// @} + + + //////////// + // lookup // + //////////// + + /// @name lookup + /// @{ + + /// @brief find an element in a JSON object + /// @sa https://json.nlohmann.me/api/basic_json/find/ + template + iterator find(KeyT&& key) + { + auto result = end(); + + if (is_object()) + { + result.m_it.object_iterator = m_value.object->find(std::forward(key)); + } + + return result; + } + + /// @brief find an element in a JSON object + /// @sa https://json.nlohmann.me/api/basic_json/find/ + template + const_iterator find(KeyT&& key) const + { + auto result = cend(); + + if (is_object()) + { + result.m_it.object_iterator = m_value.object->find(std::forward(key)); + } + + return result; + } + + /// @brief returns the number of occurrences of a key in a JSON object + /// @sa https://json.nlohmann.me/api/basic_json/count/ + template + size_type count(KeyT&& key) const + { + // return 0 for all nonobject types + return is_object() ? m_value.object->count(std::forward(key)) : 0; + } + + /// @brief check the existence of an element in a JSON object + /// @sa https://json.nlohmann.me/api/basic_json/contains/ + template < typename KeyT, typename std::enable_if < + !std::is_same::type, json_pointer>::value, int >::type = 0 > + bool contains(KeyT && key) const + { + return is_object() && m_value.object->find(std::forward(key)) != m_value.object->end(); + } + + /// @brief check the existence of an element in a JSON object given a JSON pointer + /// @sa https://json.nlohmann.me/api/basic_json/contains/ + bool contains(const json_pointer& ptr) const + { + return ptr.contains(this); + } + + /// @} + + + /////////////// + // iterators // + /////////////// + + /// @name iterators + /// @{ + + /// @brief returns an iterator to the first element + /// @sa https://json.nlohmann.me/api/basic_json/begin/ + iterator begin() noexcept + { + iterator result(this); + result.set_begin(); + return result; + } + + /// @brief returns an iterator to the first element + /// @sa https://json.nlohmann.me/api/basic_json/begin/ + const_iterator begin() const noexcept + { + return cbegin(); + } + + /// @brief returns a const iterator to the first element + /// @sa https://json.nlohmann.me/api/basic_json/cbegin/ + const_iterator cbegin() const noexcept + { + const_iterator result(this); + result.set_begin(); + return result; + } + + /// @brief returns an iterator to one past the last element + /// @sa https://json.nlohmann.me/api/basic_json/end/ + iterator end() noexcept + { + iterator result(this); + result.set_end(); + return result; + } + + /// @brief returns an iterator to one past the last element + /// @sa https://json.nlohmann.me/api/basic_json/end/ + const_iterator end() const noexcept + { + return cend(); + } + + /// @brief returns an iterator to one past the last element + /// @sa https://json.nlohmann.me/api/basic_json/cend/ + const_iterator cend() const noexcept + { + const_iterator result(this); + result.set_end(); + return result; + } + + /// @brief returns an iterator to the reverse-beginning + /// @sa https://json.nlohmann.me/api/basic_json/rbegin/ + reverse_iterator rbegin() noexcept + { + return reverse_iterator(end()); + } + + /// @brief returns an iterator to the reverse-beginning + /// @sa https://json.nlohmann.me/api/basic_json/rbegin/ + const_reverse_iterator rbegin() const noexcept + { + return crbegin(); + } + + /// @brief returns an iterator to the reverse-end + /// @sa https://json.nlohmann.me/api/basic_json/rend/ + reverse_iterator rend() noexcept + { + return reverse_iterator(begin()); + } + + /// @brief returns an iterator to the reverse-end + /// @sa https://json.nlohmann.me/api/basic_json/rend/ + const_reverse_iterator rend() const noexcept + { + return crend(); + } + + /// @brief returns a const reverse iterator to the last element + /// @sa https://json.nlohmann.me/api/basic_json/crbegin/ + const_reverse_iterator crbegin() const noexcept + { + return const_reverse_iterator(cend()); + } + + /// @brief returns a const reverse iterator to one before the first + /// @sa https://json.nlohmann.me/api/basic_json/crend/ + const_reverse_iterator crend() const noexcept + { + return const_reverse_iterator(cbegin()); + } + + public: + /// @brief wrapper to access iterator member functions in range-based for + /// @sa https://json.nlohmann.me/api/basic_json/items/ + /// @deprecated This function is deprecated since 3.1.0 and will be removed in + /// version 4.0.0 of the library. Please use @ref items() instead; + /// that is, replace `json::iterator_wrapper(j)` with `j.items()`. + JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) + static iteration_proxy iterator_wrapper(reference ref) noexcept + { + return ref.items(); + } + + /// @brief wrapper to access iterator member functions in range-based for + /// @sa https://json.nlohmann.me/api/basic_json/items/ + /// @deprecated This function is deprecated since 3.1.0 and will be removed in + /// version 4.0.0 of the library. Please use @ref items() instead; + /// that is, replace `json::iterator_wrapper(j)` with `j.items()`. + JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) + static iteration_proxy iterator_wrapper(const_reference ref) noexcept + { + return ref.items(); + } + + /// @brief helper to access iterator member functions in range-based for + /// @sa https://json.nlohmann.me/api/basic_json/items/ + iteration_proxy items() noexcept + { + return iteration_proxy(*this); + } + + /// @brief helper to access iterator member functions in range-based for + /// @sa https://json.nlohmann.me/api/basic_json/items/ + iteration_proxy items() const noexcept + { + return iteration_proxy(*this); + } + + /// @} + + + ////////////// + // capacity // + ////////////// + + /// @name capacity + /// @{ + + /// @brief checks whether the container is empty. + /// @sa https://json.nlohmann.me/api/basic_json/empty/ + bool empty() const noexcept + { + switch (m_type) + { + case value_t::null: + { + // null values are empty + return true; + } + + case value_t::array: + { + // delegate call to array_t::empty() + return m_value.array->empty(); + } + + case value_t::object: + { + // delegate call to object_t::empty() + return m_value.object->empty(); + } + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + // all other types are nonempty + return false; + } + } + } + + /// @brief returns the number of elements + /// @sa https://json.nlohmann.me/api/basic_json/size/ + size_type size() const noexcept + { + switch (m_type) + { + case value_t::null: + { + // null values are empty + return 0; + } + + case value_t::array: + { + // delegate call to array_t::size() + return m_value.array->size(); + } + + case value_t::object: + { + // delegate call to object_t::size() + return m_value.object->size(); + } + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + // all other types have size 1 + return 1; + } + } + } + + /// @brief returns the maximum possible number of elements + /// @sa https://json.nlohmann.me/api/basic_json/max_size/ + size_type max_size() const noexcept + { + switch (m_type) + { + case value_t::array: + { + // delegate call to array_t::max_size() + return m_value.array->max_size(); + } + + case value_t::object: + { + // delegate call to object_t::max_size() + return m_value.object->max_size(); + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + // all other types have max_size() == size() + return size(); + } + } + } + + /// @} + + + /////////////// + // modifiers // + /////////////// + + /// @name modifiers + /// @{ + + /// @brief clears the contents + /// @sa https://json.nlohmann.me/api/basic_json/clear/ + void clear() noexcept + { + switch (m_type) + { + case value_t::number_integer: + { + m_value.number_integer = 0; + break; + } + + case value_t::number_unsigned: + { + m_value.number_unsigned = 0; + break; + } + + case value_t::number_float: + { + m_value.number_float = 0.0; + break; + } + + case value_t::boolean: + { + m_value.boolean = false; + break; + } + + case value_t::string: + { + m_value.string->clear(); + break; + } + + case value_t::binary: + { + m_value.binary->clear(); + break; + } + + case value_t::array: + { + m_value.array->clear(); + break; + } + + case value_t::object: + { + m_value.object->clear(); + break; + } + + case value_t::null: + case value_t::discarded: + default: + break; + } + } + + /// @brief add an object to an array + /// @sa https://json.nlohmann.me/api/basic_json/push_back/ + void push_back(basic_json&& val) + { + // push_back only works for null objects or arrays + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) + { + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this)); + } + + // transform null object into an array + if (is_null()) + { + m_type = value_t::array; + m_value = value_t::array; + assert_invariant(); + } + + // add element to array (move semantics) + const auto old_capacity = m_value.array->capacity(); + m_value.array->push_back(std::move(val)); + set_parent(m_value.array->back(), old_capacity); + // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor + } + + /// @brief add an object to an array + /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ + reference operator+=(basic_json&& val) + { + push_back(std::move(val)); + return *this; + } + + /// @brief add an object to an array + /// @sa https://json.nlohmann.me/api/basic_json/push_back/ + void push_back(const basic_json& val) + { + // push_back only works for null objects or arrays + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) + { + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this)); + } + + // transform null object into an array + if (is_null()) + { + m_type = value_t::array; + m_value = value_t::array; + assert_invariant(); + } + + // add element to array + const auto old_capacity = m_value.array->capacity(); + m_value.array->push_back(val); + set_parent(m_value.array->back(), old_capacity); + } + + /// @brief add an object to an array + /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ + reference operator+=(const basic_json& val) + { + push_back(val); + return *this; + } + + /// @brief add an object to an object + /// @sa https://json.nlohmann.me/api/basic_json/push_back/ + void push_back(const typename object_t::value_type& val) + { + // push_back only works for null objects or objects + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) + { + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this)); + } + + // transform null object into an object + if (is_null()) + { + m_type = value_t::object; + m_value = value_t::object; + assert_invariant(); + } + + // add element to object + auto res = m_value.object->insert(val); + set_parent(res.first->second); + } + + /// @brief add an object to an object + /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ + reference operator+=(const typename object_t::value_type& val) + { + push_back(val); + return *this; + } + + /// @brief add an object to an object + /// @sa https://json.nlohmann.me/api/basic_json/push_back/ + void push_back(initializer_list_t init) + { + if (is_object() && init.size() == 2 && (*init.begin())->is_string()) + { + basic_json&& key = init.begin()->moved_or_copied(); + push_back(typename object_t::value_type( + std::move(key.get_ref()), (init.begin() + 1)->moved_or_copied())); + } + else + { + push_back(basic_json(init)); + } + } + + /// @brief add an object to an object + /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ + reference operator+=(initializer_list_t init) + { + push_back(init); + return *this; + } + + /// @brief add an object to an array + /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/ + template + reference emplace_back(Args&& ... args) + { + // emplace_back only works for null objects or arrays + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) + { + JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()), *this)); + } + + // transform null object into an array + if (is_null()) + { + m_type = value_t::array; + m_value = value_t::array; + assert_invariant(); + } + + // add element to array (perfect forwarding) + const auto old_capacity = m_value.array->capacity(); + m_value.array->emplace_back(std::forward(args)...); + return set_parent(m_value.array->back(), old_capacity); + } + + /// @brief add an object to an object if key does not exist + /// @sa https://json.nlohmann.me/api/basic_json/emplace/ + template + std::pair emplace(Args&& ... args) + { + // emplace only works for null objects or arrays + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) + { + JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()), *this)); + } + + // transform null object into an object + if (is_null()) + { + m_type = value_t::object; + m_value = value_t::object; + assert_invariant(); + } + + // add element to array (perfect forwarding) + auto res = m_value.object->emplace(std::forward(args)...); + set_parent(res.first->second); + + // create result iterator and set iterator to the result of emplace + auto it = begin(); + it.m_it.object_iterator = res.first; + + // return pair of iterator and boolean + return {it, res.second}; + } + + /// Helper for insertion of an iterator + /// @note: This uses std::distance to support GCC 4.8, + /// see https://github.com/nlohmann/json/pull/1257 + template + iterator insert_iterator(const_iterator pos, Args&& ... args) + { + iterator result(this); + JSON_ASSERT(m_value.array != nullptr); + + auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator); + m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); + result.m_it.array_iterator = m_value.array->begin() + insert_pos; + + // This could have been written as: + // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); + // but the return value of insert is missing in GCC 4.8, so it is written this way instead. + + set_parents(); + return result; + } + + /// @brief inserts element into array + /// @sa https://json.nlohmann.me/api/basic_json/insert/ + iterator insert(const_iterator pos, const basic_json& val) + { + // insert only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + // check if iterator pos fits to this JSON value + if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); + } + + // insert to array and return iterator + return insert_iterator(pos, val); + } + + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); + } + + /// @brief inserts element into array + /// @sa https://json.nlohmann.me/api/basic_json/insert/ + iterator insert(const_iterator pos, basic_json&& val) + { + return insert(pos, val); + } + + /// @brief inserts copies of element into array + /// @sa https://json.nlohmann.me/api/basic_json/insert/ + iterator insert(const_iterator pos, size_type cnt, const basic_json& val) + { + // insert only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + // check if iterator pos fits to this JSON value + if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); + } + + // insert to array and return iterator + return insert_iterator(pos, cnt, val); + } + + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); + } + + /// @brief inserts range of elements into array + /// @sa https://json.nlohmann.me/api/basic_json/insert/ + iterator insert(const_iterator pos, const_iterator first, const_iterator last) + { + // insert only works for arrays + if (JSON_HEDLEY_UNLIKELY(!is_array())) + { + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); + } + + // check if iterator pos fits to this JSON value + if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); + } + + // check if range iterators belong to the same JSON object + if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) + { + JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this)); + } + + if (JSON_HEDLEY_UNLIKELY(first.m_object == this)) + { + JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", *this)); + } + + // insert to array and return iterator + return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); + } + + /// @brief inserts elements from initializer list into array + /// @sa https://json.nlohmann.me/api/basic_json/insert/ + iterator insert(const_iterator pos, initializer_list_t ilist) + { + // insert only works for arrays + if (JSON_HEDLEY_UNLIKELY(!is_array())) + { + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); + } + + // check if iterator pos fits to this JSON value + if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); + } + + // insert to array and return iterator + return insert_iterator(pos, ilist.begin(), ilist.end()); + } + + /// @brief inserts range of elements into object + /// @sa https://json.nlohmann.me/api/basic_json/insert/ + void insert(const_iterator first, const_iterator last) + { + // insert only works for objects + if (JSON_HEDLEY_UNLIKELY(!is_object())) + { + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); + } + + // check if range iterators belong to the same JSON object + if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) + { + JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this)); + } + + // passed iterators must belong to objects + if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) + { + JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this)); + } + + m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); + } + + /// @brief updates a JSON object from another object, overwriting existing keys + /// @sa https://json.nlohmann.me/api/basic_json/update/ + void update(const_reference j, bool merge_objects = false) + { + update(j.begin(), j.end(), merge_objects); + } + + /// @brief updates a JSON object from another object, overwriting existing keys + /// @sa https://json.nlohmann.me/api/basic_json/update/ + void update(const_iterator first, const_iterator last, bool merge_objects = false) + { + // implicitly convert null value to an empty object + if (is_null()) + { + m_type = value_t::object; + m_value.object = create(); + assert_invariant(); + } + + if (JSON_HEDLEY_UNLIKELY(!is_object())) + { + JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this)); + } + + // check if range iterators belong to the same JSON object + if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) + { + JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this)); + } + + // passed iterators must belong to objects + if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) + { + JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(first.m_object->type_name()), *first.m_object)); + } + + for (auto it = first; it != last; ++it) + { + if (merge_objects && it.value().is_object()) + { + auto it2 = m_value.object->find(it.key()); + if (it2 != m_value.object->end()) + { + it2->second.update(it.value(), true); + continue; + } + } + m_value.object->operator[](it.key()) = it.value(); +#if JSON_DIAGNOSTICS + m_value.object->operator[](it.key()).m_parent = this; +#endif + } + } + + /// @brief exchanges the values + /// @sa https://json.nlohmann.me/api/basic_json/swap/ + void swap(reference other) noexcept ( + std::is_nothrow_move_constructible::value&& + std::is_nothrow_move_assignable::value&& + std::is_nothrow_move_constructible::value&& + std::is_nothrow_move_assignable::value + ) + { + std::swap(m_type, other.m_type); + std::swap(m_value, other.m_value); + + set_parents(); + other.set_parents(); + assert_invariant(); + } + + /// @brief exchanges the values + /// @sa https://json.nlohmann.me/api/basic_json/swap/ + friend void swap(reference left, reference right) noexcept ( + std::is_nothrow_move_constructible::value&& + std::is_nothrow_move_assignable::value&& + std::is_nothrow_move_constructible::value&& + std::is_nothrow_move_assignable::value + ) + { + left.swap(right); + } + + /// @brief exchanges the values + /// @sa https://json.nlohmann.me/api/basic_json/swap/ + void swap(array_t& other) // NOLINT(bugprone-exception-escape) + { + // swap only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + std::swap(*(m_value.array), other); + } + else + { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); + } + } + + /// @brief exchanges the values + /// @sa https://json.nlohmann.me/api/basic_json/swap/ + void swap(object_t& other) // NOLINT(bugprone-exception-escape) + { + // swap only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + std::swap(*(m_value.object), other); + } + else + { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); + } + } + + /// @brief exchanges the values + /// @sa https://json.nlohmann.me/api/basic_json/swap/ + void swap(string_t& other) // NOLINT(bugprone-exception-escape) + { + // swap only works for strings + if (JSON_HEDLEY_LIKELY(is_string())) + { + std::swap(*(m_value.string), other); + } + else + { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); + } + } + + /// @brief exchanges the values + /// @sa https://json.nlohmann.me/api/basic_json/swap/ + void swap(binary_t& other) // NOLINT(bugprone-exception-escape) + { + // swap only works for strings + if (JSON_HEDLEY_LIKELY(is_binary())) + { + std::swap(*(m_value.binary), other); + } + else + { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); + } + } + + /// @brief exchanges the values + /// @sa https://json.nlohmann.me/api/basic_json/swap/ + void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape) + { + // swap only works for strings + if (JSON_HEDLEY_LIKELY(is_binary())) + { + std::swap(*(m_value.binary), other); + } + else + { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); + } + } + + /// @} + + public: + ////////////////////////////////////////// + // lexicographical comparison operators // + ////////////////////////////////////////// + + /// @name lexicographical comparison operators + /// @{ + + /// @brief comparison: equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ + friend bool operator==(const_reference lhs, const_reference rhs) noexcept + { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + const auto lhs_type = lhs.type(); + const auto rhs_type = rhs.type(); + + if (lhs_type == rhs_type) + { + switch (lhs_type) + { + case value_t::array: + return *lhs.m_value.array == *rhs.m_value.array; + + case value_t::object: + return *lhs.m_value.object == *rhs.m_value.object; + + case value_t::null: + return true; + + case value_t::string: + return *lhs.m_value.string == *rhs.m_value.string; + + case value_t::boolean: + return lhs.m_value.boolean == rhs.m_value.boolean; + + case value_t::number_integer: + return lhs.m_value.number_integer == rhs.m_value.number_integer; + + case value_t::number_unsigned: + return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned; + + case value_t::number_float: + return lhs.m_value.number_float == rhs.m_value.number_float; + + case value_t::binary: + return *lhs.m_value.binary == *rhs.m_value.binary; + + case value_t::discarded: + default: + return false; + } + } + else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) + { + return static_cast(lhs.m_value.number_integer) == rhs.m_value.number_float; + } + else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) + { + return lhs.m_value.number_float == static_cast(rhs.m_value.number_integer); + } + else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) + { + return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_float; + } + else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) + { + return lhs.m_value.number_float == static_cast(rhs.m_value.number_unsigned); + } + else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) + { + return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_integer; + } + else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) + { + return lhs.m_value.number_integer == static_cast(rhs.m_value.number_unsigned); + } + + return false; +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + } + + /// @brief comparison: equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ + template::value, int>::type = 0> + friend bool operator==(const_reference lhs, ScalarType rhs) noexcept + { + return lhs == basic_json(rhs); + } + + /// @brief comparison: equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ + template::value, int>::type = 0> + friend bool operator==(ScalarType lhs, const_reference rhs) noexcept + { + return basic_json(lhs) == rhs; + } + + /// @brief comparison: not equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ + friend bool operator!=(const_reference lhs, const_reference rhs) noexcept + { + return !(lhs == rhs); + } + + /// @brief comparison: not equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ + template::value, int>::type = 0> + friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept + { + return lhs != basic_json(rhs); + } + + /// @brief comparison: not equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ + template::value, int>::type = 0> + friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept + { + return basic_json(lhs) != rhs; + } + + /// @brief comparison: less than + /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ + friend bool operator<(const_reference lhs, const_reference rhs) noexcept + { + const auto lhs_type = lhs.type(); + const auto rhs_type = rhs.type(); + + if (lhs_type == rhs_type) + { + switch (lhs_type) + { + case value_t::array: + // note parentheses are necessary, see + // https://github.com/nlohmann/json/issues/1530 + return (*lhs.m_value.array) < (*rhs.m_value.array); + + case value_t::object: + return (*lhs.m_value.object) < (*rhs.m_value.object); + + case value_t::null: + return false; + + case value_t::string: + return (*lhs.m_value.string) < (*rhs.m_value.string); + + case value_t::boolean: + return (lhs.m_value.boolean) < (rhs.m_value.boolean); + + case value_t::number_integer: + return (lhs.m_value.number_integer) < (rhs.m_value.number_integer); + + case value_t::number_unsigned: + return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned); + + case value_t::number_float: + return (lhs.m_value.number_float) < (rhs.m_value.number_float); + + case value_t::binary: + return (*lhs.m_value.binary) < (*rhs.m_value.binary); + + case value_t::discarded: + default: + return false; + } + } + else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) + { + return static_cast(lhs.m_value.number_integer) < rhs.m_value.number_float; + } + else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) + { + return lhs.m_value.number_float < static_cast(rhs.m_value.number_integer); + } + else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) + { + return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_float; + } + else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) + { + return lhs.m_value.number_float < static_cast(rhs.m_value.number_unsigned); + } + else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) + { + return lhs.m_value.number_integer < static_cast(rhs.m_value.number_unsigned); + } + else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) + { + return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_integer; + } + + // We only reach this line if we cannot compare values. In that case, + // we compare types. Note we have to call the operator explicitly, + // because MSVC has problems otherwise. + return operator<(lhs_type, rhs_type); + } + + /// @brief comparison: less than + /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ + template::value, int>::type = 0> + friend bool operator<(const_reference lhs, ScalarType rhs) noexcept + { + return lhs < basic_json(rhs); + } + + /// @brief comparison: less than + /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ + template::value, int>::type = 0> + friend bool operator<(ScalarType lhs, const_reference rhs) noexcept + { + return basic_json(lhs) < rhs; + } + + /// @brief comparison: less than or equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ + friend bool operator<=(const_reference lhs, const_reference rhs) noexcept + { + return !(rhs < lhs); + } + + /// @brief comparison: less than or equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ + template::value, int>::type = 0> + friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept + { + return lhs <= basic_json(rhs); + } + + /// @brief comparison: less than or equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ + template::value, int>::type = 0> + friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept + { + return basic_json(lhs) <= rhs; + } + + /// @brief comparison: greater than + /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ + friend bool operator>(const_reference lhs, const_reference rhs) noexcept + { + return !(lhs <= rhs); + } + + /// @brief comparison: greater than + /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ + template::value, int>::type = 0> + friend bool operator>(const_reference lhs, ScalarType rhs) noexcept + { + return lhs > basic_json(rhs); + } + + /// @brief comparison: greater than + /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ + template::value, int>::type = 0> + friend bool operator>(ScalarType lhs, const_reference rhs) noexcept + { + return basic_json(lhs) > rhs; + } + + /// @brief comparison: greater than or equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ + friend bool operator>=(const_reference lhs, const_reference rhs) noexcept + { + return !(lhs < rhs); + } + + /// @brief comparison: greater than or equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ + template::value, int>::type = 0> + friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept + { + return lhs >= basic_json(rhs); + } + + /// @brief comparison: greater than or equal + /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ + template::value, int>::type = 0> + friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept + { + return basic_json(lhs) >= rhs; + } + + /// @} + + /////////////////// + // serialization // + /////////////////// + + /// @name serialization + /// @{ +#ifndef JSON_NO_IO + /// @brief serialize to stream + /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ + friend std::ostream& operator<<(std::ostream& o, const basic_json& j) + { + // read width member and use it as indentation parameter if nonzero + const bool pretty_print = o.width() > 0; + const auto indentation = pretty_print ? o.width() : 0; + + // reset width to 0 for subsequent calls to this stream + o.width(0); + + // do the actual serialization + serializer s(detail::output_adapter(o), o.fill()); + s.dump(j, pretty_print, false, static_cast(indentation)); + return o; + } + + /// @brief serialize to stream + /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ + /// @deprecated This function is deprecated since 3.0.0 and will be removed in + /// version 4.0.0 of the library. Please use + /// operator<<(std::ostream&, const basic_json&) instead; that is, + /// replace calls like `j >> o;` with `o << j;`. + JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&)) + friend std::ostream& operator>>(const basic_json& j, std::ostream& o) + { + return o << j; + } +#endif // JSON_NO_IO + /// @} + + + ///////////////////// + // deserialization // + ///////////////////// + + /// @name deserialization + /// @{ + + /// @brief deserialize from a compatible input + /// @sa https://json.nlohmann.me/api/basic_json/parse/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json parse(InputType&& i, + const parser_callback_t cb = nullptr, + const bool allow_exceptions = true, + const bool ignore_comments = false) + { + basic_json result; + parser(detail::input_adapter(std::forward(i)), cb, allow_exceptions, ignore_comments).parse(true, result); + return result; + } + + /// @brief deserialize from a pair of character iterators + /// @sa https://json.nlohmann.me/api/basic_json/parse/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json parse(IteratorType first, + IteratorType last, + const parser_callback_t cb = nullptr, + const bool allow_exceptions = true, + const bool ignore_comments = false) + { + basic_json result; + parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result); + return result; + } + + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len)) + static basic_json parse(detail::span_input_adapter&& i, + const parser_callback_t cb = nullptr, + const bool allow_exceptions = true, + const bool ignore_comments = false) + { + basic_json result; + parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result); + return result; + } + + /// @brief check if the input is valid JSON + /// @sa https://json.nlohmann.me/api/basic_json/accept/ + template + static bool accept(InputType&& i, + const bool ignore_comments = false) + { + return parser(detail::input_adapter(std::forward(i)), nullptr, false, ignore_comments).accept(true); + } + + /// @brief check if the input is valid JSON + /// @sa https://json.nlohmann.me/api/basic_json/accept/ + template + static bool accept(IteratorType first, IteratorType last, + const bool ignore_comments = false) + { + return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true); + } + + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len)) + static bool accept(detail::span_input_adapter&& i, + const bool ignore_comments = false) + { + return parser(i.get(), nullptr, false, ignore_comments).accept(true); + } + + /// @brief generate SAX events + /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ + template + JSON_HEDLEY_NON_NULL(2) + static bool sax_parse(InputType&& i, SAX* sax, + input_format_t format = input_format_t::json, + const bool strict = true, + const bool ignore_comments = false) + { + auto ia = detail::input_adapter(std::forward(i)); + return format == input_format_t::json + ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) + : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); + } + + /// @brief generate SAX events + /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ + template + JSON_HEDLEY_NON_NULL(3) + static bool sax_parse(IteratorType first, IteratorType last, SAX* sax, + input_format_t format = input_format_t::json, + const bool strict = true, + const bool ignore_comments = false) + { + auto ia = detail::input_adapter(std::move(first), std::move(last)); + return format == input_format_t::json + ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) + : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); + } + + /// @brief generate SAX events + /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ + /// @deprecated This function is deprecated since 3.8.0 and will be removed in + /// version 4.0.0 of the library. Please use + /// sax_parse(ptr, ptr + len) instead. + template + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...)) + JSON_HEDLEY_NON_NULL(2) + static bool sax_parse(detail::span_input_adapter&& i, SAX* sax, + input_format_t format = input_format_t::json, + const bool strict = true, + const bool ignore_comments = false) + { + auto ia = i.get(); + return format == input_format_t::json + // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) + ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) + // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) + : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); + } +#ifndef JSON_NO_IO + /// @brief deserialize from stream + /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/ + /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in + /// version 4.0.0 of the library. Please use + /// operator>>(std::istream&, basic_json&) instead; that is, + /// replace calls like `j << i;` with `i >> j;`. + JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&)) + friend std::istream& operator<<(basic_json& j, std::istream& i) + { + return operator>>(i, j); + } + + /// @brief deserialize from stream + /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/ + friend std::istream& operator>>(std::istream& i, basic_json& j) + { + parser(detail::input_adapter(i)).parse(false, j); + return i; + } +#endif // JSON_NO_IO + /// @} + + /////////////////////////// + // convenience functions // + /////////////////////////// + + /// @brief return the type as string + /// @sa https://json.nlohmann.me/api/basic_json/type_name/ + JSON_HEDLEY_RETURNS_NON_NULL + const char* type_name() const noexcept + { + switch (m_type) + { + case value_t::null: + return "null"; + case value_t::object: + return "object"; + case value_t::array: + return "array"; + case value_t::string: + return "string"; + case value_t::boolean: + return "boolean"; + case value_t::binary: + return "binary"; + case value_t::discarded: + return "discarded"; + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + default: + return "number"; + } + } + + + JSON_PRIVATE_UNLESS_TESTED: + ////////////////////// + // member variables // + ////////////////////// + + /// the type of the current element + value_t m_type = value_t::null; + + /// the value of the current element + json_value m_value = {}; + +#if JSON_DIAGNOSTICS + /// a pointer to a parent value (for debugging purposes) + basic_json* m_parent = nullptr; +#endif + + ////////////////////////////////////////// + // binary serialization/deserialization // + ////////////////////////////////////////// + + /// @name binary serialization/deserialization support + /// @{ + + public: + /// @brief create a CBOR serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ + static std::vector to_cbor(const basic_json& j) + { + std::vector result; + to_cbor(j, result); + return result; + } + + /// @brief create a CBOR serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ + static void to_cbor(const basic_json& j, detail::output_adapter o) + { + binary_writer(o).write_cbor(j); + } + + /// @brief create a CBOR serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ + static void to_cbor(const basic_json& j, detail::output_adapter o) + { + binary_writer(o).write_cbor(j); + } + + /// @brief create a MessagePack serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ + static std::vector to_msgpack(const basic_json& j) + { + std::vector result; + to_msgpack(j, result); + return result; + } + + /// @brief create a MessagePack serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ + static void to_msgpack(const basic_json& j, detail::output_adapter o) + { + binary_writer(o).write_msgpack(j); + } + + /// @brief create a MessagePack serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ + static void to_msgpack(const basic_json& j, detail::output_adapter o) + { + binary_writer(o).write_msgpack(j); + } + + /// @brief create a UBJSON serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ + static std::vector to_ubjson(const basic_json& j, + const bool use_size = false, + const bool use_type = false) + { + std::vector result; + to_ubjson(j, result, use_size, use_type); + return result; + } + + /// @brief create a UBJSON serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ + static void to_ubjson(const basic_json& j, detail::output_adapter o, + const bool use_size = false, const bool use_type = false) + { + binary_writer(o).write_ubjson(j, use_size, use_type); + } + + /// @brief create a UBJSON serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ + static void to_ubjson(const basic_json& j, detail::output_adapter o, + const bool use_size = false, const bool use_type = false) + { + binary_writer(o).write_ubjson(j, use_size, use_type); + } + + /// @brief create a BSON serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ + static std::vector to_bson(const basic_json& j) + { + std::vector result; + to_bson(j, result); + return result; + } + + /// @brief create a BSON serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ + static void to_bson(const basic_json& j, detail::output_adapter o) + { + binary_writer(o).write_bson(j); + } + + /// @brief create a BSON serialization of a given JSON value + /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ + static void to_bson(const basic_json& j, detail::output_adapter o) + { + binary_writer(o).write_bson(j); + } + + /// @brief create a JSON value from an input in CBOR format + /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_cbor(InputType&& i, + const bool strict = true, + const bool allow_exceptions = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::forward(i)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); + return res ? result : basic_json(value_t::discarded); + } + + /// @brief create a JSON value from an input in CBOR format + /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_cbor(IteratorType first, IteratorType last, + const bool strict = true, + const bool allow_exceptions = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::move(first), std::move(last)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); + return res ? result : basic_json(value_t::discarded); + } + + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) + static basic_json from_cbor(const T* ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) + { + return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler); + } + + + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) + static basic_json from_cbor(detail::span_input_adapter&& i, + const bool strict = true, + const bool allow_exceptions = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = i.get(); + // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); + return res ? result : basic_json(value_t::discarded); + } + + /// @brief create a JSON value from an input in MessagePack format + /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_msgpack(InputType&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::forward(i)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + /// @brief create a JSON value from an input in MessagePack format + /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_msgpack(IteratorType first, IteratorType last, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::move(first), std::move(last)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) + static basic_json from_msgpack(const T* ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true) + { + return from_msgpack(ptr, ptr + len, strict, allow_exceptions); + } + + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) + static basic_json from_msgpack(detail::span_input_adapter&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = i.get(); + // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + /// @brief create a JSON value from an input in UBJSON format + /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_ubjson(InputType&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::forward(i)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + /// @brief create a JSON value from an input in UBJSON format + /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_ubjson(IteratorType first, IteratorType last, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::move(first), std::move(last)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) + static basic_json from_ubjson(const T* ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true) + { + return from_ubjson(ptr, ptr + len, strict, allow_exceptions); + } + + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) + static basic_json from_ubjson(detail::span_input_adapter&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = i.get(); + // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + /// @brief create a JSON value from an input in BSON format + /// @sa https://json.nlohmann.me/api/basic_json/from_bson/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_bson(InputType&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::forward(i)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + /// @brief create a JSON value from an input in BSON format + /// @sa https://json.nlohmann.me/api/basic_json/from_bson/ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_bson(IteratorType first, IteratorType last, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::move(first), std::move(last)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) + static basic_json from_bson(const T* ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true) + { + return from_bson(ptr, ptr + len, strict, allow_exceptions); + } + + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) + static basic_json from_bson(detail::span_input_adapter&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = i.get(); + // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + /// @} + + ////////////////////////// + // JSON Pointer support // + ////////////////////////// + + /// @name JSON Pointer functions + /// @{ + + /// @brief access specified element via JSON Pointer + /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ + reference operator[](const json_pointer& ptr) + { + return ptr.get_unchecked(this); + } + + /// @brief access specified element via JSON Pointer + /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ + const_reference operator[](const json_pointer& ptr) const + { + return ptr.get_unchecked(this); + } + + /// @brief access specified element via JSON Pointer + /// @sa https://json.nlohmann.me/api/basic_json/at/ + reference at(const json_pointer& ptr) + { + return ptr.get_checked(this); + } + + /// @brief access specified element via JSON Pointer + /// @sa https://json.nlohmann.me/api/basic_json/at/ + const_reference at(const json_pointer& ptr) const + { + return ptr.get_checked(this); + } + + /// @brief return flattened JSON value + /// @sa https://json.nlohmann.me/api/basic_json/flatten/ + basic_json flatten() const + { + basic_json result(value_t::object); + json_pointer::flatten("", *this, result); + return result; + } + + /// @brief unflatten a previously flattened JSON value + /// @sa https://json.nlohmann.me/api/basic_json/unflatten/ + basic_json unflatten() const + { + return json_pointer::unflatten(*this); + } + + /// @} + + ////////////////////////// + // JSON Patch functions // + ////////////////////////// + + /// @name JSON Patch functions + /// @{ + + /// @brief applies a JSON patch + /// @sa https://json.nlohmann.me/api/basic_json/patch/ + basic_json patch(const basic_json& json_patch) const + { + // make a working copy to apply the patch to + basic_json result = *this; + + // the valid JSON Patch operations + enum class patch_operations {add, remove, replace, move, copy, test, invalid}; + + const auto get_op = [](const std::string & op) + { + if (op == "add") + { + return patch_operations::add; + } + if (op == "remove") + { + return patch_operations::remove; + } + if (op == "replace") + { + return patch_operations::replace; + } + if (op == "move") + { + return patch_operations::move; + } + if (op == "copy") + { + return patch_operations::copy; + } + if (op == "test") + { + return patch_operations::test; + } + + return patch_operations::invalid; + }; + + // wrapper for "add" operation; add value at ptr + const auto operation_add = [&result](json_pointer & ptr, basic_json val) + { + // adding to the root of the target document means replacing it + if (ptr.empty()) + { + result = val; + return; + } + + // make sure the top element of the pointer exists + json_pointer top_pointer = ptr.top(); + if (top_pointer != ptr) + { + result.at(top_pointer); + } + + // get reference to parent of JSON pointer ptr + const auto last_path = ptr.back(); + ptr.pop_back(); + basic_json& parent = result[ptr]; + + switch (parent.m_type) + { + case value_t::null: + case value_t::object: + { + // use operator[] to add value + parent[last_path] = val; + break; + } + + case value_t::array: + { + if (last_path == "-") + { + // special case: append to back + parent.push_back(val); + } + else + { + const auto idx = json_pointer::array_index(last_path); + if (JSON_HEDLEY_UNLIKELY(idx > parent.size())) + { + // avoid undefined behavior + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", parent)); + } + + // default case: insert add offset + parent.insert(parent.begin() + static_cast(idx), val); + } + break; + } + + // if there exists a parent it cannot be primitive + case value_t::string: // LCOV_EXCL_LINE + case value_t::boolean: // LCOV_EXCL_LINE + case value_t::number_integer: // LCOV_EXCL_LINE + case value_t::number_unsigned: // LCOV_EXCL_LINE + case value_t::number_float: // LCOV_EXCL_LINE + case value_t::binary: // LCOV_EXCL_LINE + case value_t::discarded: // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + }; + + // wrapper for "remove" operation; remove value at ptr + const auto operation_remove = [this, &result](json_pointer & ptr) + { + // get reference to parent of JSON pointer ptr + const auto last_path = ptr.back(); + ptr.pop_back(); + basic_json& parent = result.at(ptr); + + // remove child + if (parent.is_object()) + { + // perform range check + auto it = parent.find(last_path); + if (JSON_HEDLEY_LIKELY(it != parent.end())) + { + parent.erase(it); + } + else + { + JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found", *this)); + } + } + else if (parent.is_array()) + { + // note erase performs range check + parent.erase(json_pointer::array_index(last_path)); + } + }; + + // type check: top level value must be an array + if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array())) + { + JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", json_patch)); + } + + // iterate and apply the operations + for (const auto& val : json_patch) + { + // wrapper to get a value for an operation + const auto get_value = [&val](const std::string & op, + const std::string & member, + bool string_type) -> basic_json & + { + // find value + auto it = val.m_value.object->find(member); + + // context-sensitive error message + const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'"; + + // check if desired value is present + if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end())) + { + // NOLINTNEXTLINE(performance-inefficient-string-concatenation) + JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'", val)); + } + + // check if result is of type string + if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string())) + { + // NOLINTNEXTLINE(performance-inefficient-string-concatenation) + JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'", val)); + } + + // no error: return value + return it->second; + }; + + // type check: every element of the array must be an object + if (JSON_HEDLEY_UNLIKELY(!val.is_object())) + { + JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", val)); + } + + // collect mandatory members + const auto op = get_value("op", "op", true).template get(); + const auto path = get_value(op, "path", true).template get(); + json_pointer ptr(path); + + switch (get_op(op)) + { + case patch_operations::add: + { + operation_add(ptr, get_value("add", "value", false)); + break; + } + + case patch_operations::remove: + { + operation_remove(ptr); + break; + } + + case patch_operations::replace: + { + // the "path" location must exist - use at() + result.at(ptr) = get_value("replace", "value", false); + break; + } + + case patch_operations::move: + { + const auto from_path = get_value("move", "from", true).template get(); + json_pointer from_ptr(from_path); + + // the "from" location must exist - use at() + basic_json v = result.at(from_ptr); + + // The move operation is functionally identical to a + // "remove" operation on the "from" location, followed + // immediately by an "add" operation at the target + // location with the value that was just removed. + operation_remove(from_ptr); + operation_add(ptr, v); + break; + } + + case patch_operations::copy: + { + const auto from_path = get_value("copy", "from", true).template get(); + const json_pointer from_ptr(from_path); + + // the "from" location must exist - use at() + basic_json v = result.at(from_ptr); + + // The copy is functionally identical to an "add" + // operation at the target location using the value + // specified in the "from" member. + operation_add(ptr, v); + break; + } + + case patch_operations::test: + { + bool success = false; + JSON_TRY + { + // check if "value" matches the one at "path" + // the "path" location must exist - use at() + success = (result.at(ptr) == get_value("test", "value", false)); + } + JSON_INTERNAL_CATCH (out_of_range&) + { + // ignore out of range errors: success remains false + } + + // throw an exception if test fails + if (JSON_HEDLEY_UNLIKELY(!success)) + { + JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump(), val)); + } + + break; + } + + case patch_operations::invalid: + default: + { + // op must be "add", "remove", "replace", "move", "copy", or + // "test" + JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid", val)); + } + } + } + + return result; + } + + /// @brief creates a diff as a JSON patch + /// @sa https://json.nlohmann.me/api/basic_json/diff/ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json diff(const basic_json& source, const basic_json& target, + const std::string& path = "") + { + // the patch + basic_json result(value_t::array); + + // if the values are the same, return empty patch + if (source == target) + { + return result; + } + + if (source.type() != target.type()) + { + // different types: replace value + result.push_back( + { + {"op", "replace"}, {"path", path}, {"value", target} + }); + return result; + } + + switch (source.type()) + { + case value_t::array: + { + // first pass: traverse common elements + std::size_t i = 0; + while (i < source.size() && i < target.size()) + { + // recursive call to compare array values at index i + auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i)); + result.insert(result.end(), temp_diff.begin(), temp_diff.end()); + ++i; + } + + // We now reached the end of at least one array + // in a second pass, traverse the remaining elements + + // remove my remaining elements + const auto end_index = static_cast(result.size()); + while (i < source.size()) + { + // add operations in reverse order to avoid invalid + // indices + result.insert(result.begin() + end_index, object( + { + {"op", "remove"}, + {"path", path + "/" + std::to_string(i)} + })); + ++i; + } + + // add other remaining elements + while (i < target.size()) + { + result.push_back( + { + {"op", "add"}, + {"path", path + "/-"}, + {"value", target[i]} + }); + ++i; + } + + break; + } + + case value_t::object: + { + // first pass: traverse this object's elements + for (auto it = source.cbegin(); it != source.cend(); ++it) + { + // escape the key name to be used in a JSON patch + const auto path_key = path + "/" + detail::escape(it.key()); + + if (target.find(it.key()) != target.end()) + { + // recursive call to compare object values at key it + auto temp_diff = diff(it.value(), target[it.key()], path_key); + result.insert(result.end(), temp_diff.begin(), temp_diff.end()); + } + else + { + // found a key that is not in o -> remove it + result.push_back(object( + { + {"op", "remove"}, {"path", path_key} + })); + } + } + + // second pass: traverse other object's elements + for (auto it = target.cbegin(); it != target.cend(); ++it) + { + if (source.find(it.key()) == source.end()) + { + // found a key that is not in this -> add it + const auto path_key = path + "/" + detail::escape(it.key()); + result.push_back( + { + {"op", "add"}, {"path", path_key}, + {"value", it.value()} + }); + } + } + + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + // both primitive type: replace value + result.push_back( + { + {"op", "replace"}, {"path", path}, {"value", target} + }); + break; + } + } + + return result; + } + + /// @} + + //////////////////////////////// + // JSON Merge Patch functions // + //////////////////////////////// + + /// @name JSON Merge Patch functions + /// @{ + + /// @brief applies a JSON Merge Patch + /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/ + void merge_patch(const basic_json& apply_patch) + { + if (apply_patch.is_object()) + { + if (!is_object()) + { + *this = object(); + } + for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it) + { + if (it.value().is_null()) + { + erase(it.key()); + } + else + { + operator[](it.key()).merge_patch(it.value()); + } + } + } + else + { + *this = apply_patch; + } + } + + /// @} +}; + +/// @brief user-defined to_string function for JSON values +/// @sa https://json.nlohmann.me/api/basic_json/to_string/ +NLOHMANN_BASIC_JSON_TPL_DECLARATION +std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) +{ + return j.dump(); +} + +} // namespace nlohmann + +/////////////////////// +// nonmember support // +/////////////////////// + +namespace std // NOLINT(cert-dcl58-cpp) +{ + +/// @brief hash value for JSON objects +/// @sa https://json.nlohmann.me/api/basic_json/std_hash/ +NLOHMANN_BASIC_JSON_TPL_DECLARATION +struct hash +{ + std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const + { + return nlohmann::detail::hash(j); + } +}; + +// specialization for std::less +template<> +struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679 +{ + /*! + @brief compare two value_t enum values + @since version 3.0.0 + */ + bool operator()(nlohmann::detail::value_t lhs, + nlohmann::detail::value_t rhs) const noexcept + { + return nlohmann::detail::operator<(lhs, rhs); + } +}; + +// C++20 prohibit function specialization in the std namespace. +#ifndef JSON_HAS_CPP_20 + +/// @brief exchanges the values of two JSON objects +/// @sa https://json.nlohmann.me/api/basic_json/std_swap/ +NLOHMANN_BASIC_JSON_TPL_DECLARATION +inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name) + is_nothrow_move_constructible::value&& // NOLINT(misc-redundant-expression) + is_nothrow_move_assignable::value) +{ + j1.swap(j2); +} + +#endif + +} // namespace std + +/// @brief user-defined string literal for JSON values +/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/ +JSON_HEDLEY_NON_NULL(1) +inline nlohmann::json operator "" _json(const char* s, std::size_t n) +{ + return nlohmann::json::parse(s, s + n); +} + +/// @brief user-defined string literal for JSON pointer +/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/ +JSON_HEDLEY_NON_NULL(1) +inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) +{ + return nlohmann::json::json_pointer(std::string(s, n)); +} + +// #include + + +// restore clang diagnostic settings +#if defined(__clang__) + #pragma clang diagnostic pop +#endif + +// clean up +#undef JSON_ASSERT +#undef JSON_INTERNAL_CATCH +#undef JSON_CATCH +#undef JSON_THROW +#undef JSON_TRY +#undef JSON_PRIVATE_UNLESS_TESTED +#undef JSON_HAS_CPP_11 +#undef JSON_HAS_CPP_14 +#undef JSON_HAS_CPP_17 +#undef JSON_HAS_CPP_20 +#undef JSON_HAS_FILESYSTEM +#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM +#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION +#undef NLOHMANN_BASIC_JSON_TPL +#undef JSON_EXPLICIT +#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL + +// #include + + +#undef JSON_HEDLEY_ALWAYS_INLINE +#undef JSON_HEDLEY_ARM_VERSION +#undef JSON_HEDLEY_ARM_VERSION_CHECK +#undef JSON_HEDLEY_ARRAY_PARAM +#undef JSON_HEDLEY_ASSUME +#undef JSON_HEDLEY_BEGIN_C_DECLS +#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#undef JSON_HEDLEY_CLANG_HAS_FEATURE +#undef JSON_HEDLEY_CLANG_HAS_WARNING +#undef JSON_HEDLEY_COMPCERT_VERSION +#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#undef JSON_HEDLEY_CONCAT +#undef JSON_HEDLEY_CONCAT3 +#undef JSON_HEDLEY_CONCAT3_EX +#undef JSON_HEDLEY_CONCAT_EX +#undef JSON_HEDLEY_CONST +#undef JSON_HEDLEY_CONSTEXPR +#undef JSON_HEDLEY_CONST_CAST +#undef JSON_HEDLEY_CPP_CAST +#undef JSON_HEDLEY_CRAY_VERSION +#undef JSON_HEDLEY_CRAY_VERSION_CHECK +#undef JSON_HEDLEY_C_DECL +#undef JSON_HEDLEY_DEPRECATED +#undef JSON_HEDLEY_DEPRECATED_FOR +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#undef JSON_HEDLEY_DIAGNOSTIC_POP +#undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#undef JSON_HEDLEY_DMC_VERSION +#undef JSON_HEDLEY_DMC_VERSION_CHECK +#undef JSON_HEDLEY_EMPTY_BASES +#undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#undef JSON_HEDLEY_END_C_DECLS +#undef JSON_HEDLEY_FLAGS +#undef JSON_HEDLEY_FLAGS_CAST +#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#undef JSON_HEDLEY_GCC_HAS_BUILTIN +#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#undef JSON_HEDLEY_GCC_HAS_EXTENSION +#undef JSON_HEDLEY_GCC_HAS_FEATURE +#undef JSON_HEDLEY_GCC_HAS_WARNING +#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#undef JSON_HEDLEY_GCC_VERSION +#undef JSON_HEDLEY_GCC_VERSION_CHECK +#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#undef JSON_HEDLEY_GNUC_HAS_FEATURE +#undef JSON_HEDLEY_GNUC_HAS_WARNING +#undef JSON_HEDLEY_GNUC_VERSION +#undef JSON_HEDLEY_GNUC_VERSION_CHECK +#undef JSON_HEDLEY_HAS_ATTRIBUTE +#undef JSON_HEDLEY_HAS_BUILTIN +#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#undef JSON_HEDLEY_HAS_EXTENSION +#undef JSON_HEDLEY_HAS_FEATURE +#undef JSON_HEDLEY_HAS_WARNING +#undef JSON_HEDLEY_IAR_VERSION +#undef JSON_HEDLEY_IAR_VERSION_CHECK +#undef JSON_HEDLEY_IBM_VERSION +#undef JSON_HEDLEY_IBM_VERSION_CHECK +#undef JSON_HEDLEY_IMPORT +#undef JSON_HEDLEY_INLINE +#undef JSON_HEDLEY_INTEL_CL_VERSION +#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK +#undef JSON_HEDLEY_INTEL_VERSION +#undef JSON_HEDLEY_INTEL_VERSION_CHECK +#undef JSON_HEDLEY_IS_CONSTANT +#undef JSON_HEDLEY_IS_CONSTEXPR_ +#undef JSON_HEDLEY_LIKELY +#undef JSON_HEDLEY_MALLOC +#undef JSON_HEDLEY_MCST_LCC_VERSION +#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK +#undef JSON_HEDLEY_MESSAGE +#undef JSON_HEDLEY_MSVC_VERSION +#undef JSON_HEDLEY_MSVC_VERSION_CHECK +#undef JSON_HEDLEY_NEVER_INLINE +#undef JSON_HEDLEY_NON_NULL +#undef JSON_HEDLEY_NO_ESCAPE +#undef JSON_HEDLEY_NO_RETURN +#undef JSON_HEDLEY_NO_THROW +#undef JSON_HEDLEY_NULL +#undef JSON_HEDLEY_PELLES_VERSION +#undef JSON_HEDLEY_PELLES_VERSION_CHECK +#undef JSON_HEDLEY_PGI_VERSION +#undef JSON_HEDLEY_PGI_VERSION_CHECK +#undef JSON_HEDLEY_PREDICT +#undef JSON_HEDLEY_PRINTF_FORMAT +#undef JSON_HEDLEY_PRIVATE +#undef JSON_HEDLEY_PUBLIC +#undef JSON_HEDLEY_PURE +#undef JSON_HEDLEY_REINTERPRET_CAST +#undef JSON_HEDLEY_REQUIRE +#undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#undef JSON_HEDLEY_REQUIRE_MSG +#undef JSON_HEDLEY_RESTRICT +#undef JSON_HEDLEY_RETURNS_NON_NULL +#undef JSON_HEDLEY_SENTINEL +#undef JSON_HEDLEY_STATIC_ASSERT +#undef JSON_HEDLEY_STATIC_CAST +#undef JSON_HEDLEY_STRINGIFY +#undef JSON_HEDLEY_STRINGIFY_EX +#undef JSON_HEDLEY_SUNPRO_VERSION +#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#undef JSON_HEDLEY_TINYC_VERSION +#undef JSON_HEDLEY_TINYC_VERSION_CHECK +#undef JSON_HEDLEY_TI_ARMCL_VERSION +#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK +#undef JSON_HEDLEY_TI_CL2000_VERSION +#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK +#undef JSON_HEDLEY_TI_CL430_VERSION +#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK +#undef JSON_HEDLEY_TI_CL6X_VERSION +#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK +#undef JSON_HEDLEY_TI_CL7X_VERSION +#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK +#undef JSON_HEDLEY_TI_CLPRU_VERSION +#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK +#undef JSON_HEDLEY_TI_VERSION +#undef JSON_HEDLEY_TI_VERSION_CHECK +#undef JSON_HEDLEY_UNAVAILABLE +#undef JSON_HEDLEY_UNLIKELY +#undef JSON_HEDLEY_UNPREDICTABLE +#undef JSON_HEDLEY_UNREACHABLE +#undef JSON_HEDLEY_UNREACHABLE_RETURN +#undef JSON_HEDLEY_VERSION +#undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#undef JSON_HEDLEY_VERSION_DECODE_MINOR +#undef JSON_HEDLEY_VERSION_DECODE_REVISION +#undef JSON_HEDLEY_VERSION_ENCODE +#undef JSON_HEDLEY_WARNING +#undef JSON_HEDLEY_WARN_UNUSED_RESULT +#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG +#undef JSON_HEDLEY_FALL_THROUGH + + + +#endif // INCLUDE_NLOHMANN_JSON_HPP_ diff --git a/tools/mapping-tester/config-template.xml b/tools/mapping-tester/config-template.xml new file mode 100644 index 00000000..a01da687 --- /dev/null +++ b/tools/mapping-tester/config-template.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {% if mapping.constraint == "conservative" %} + + + + {% endif %} + + + + + + + {% if mapping.constraint == "consistent" %} + + + + {% endif %} + + + + + + + + {% if mapping.constraint == "consistent" %} + + {% else %} + + {% endif %} + + + + + diff --git a/tools/mapping-tester/gatherstats.py b/tools/mapping-tester/gatherstats.py new file mode 100755 index 00000000..24397c13 --- /dev/null +++ b/tools/mapping-tester/gatherstats.py @@ -0,0 +1,118 @@ +#! /usr/bin/env python3 + +import argparse +import csv +import glob +import json +import os + + +def parseArguments(args): + parser = argparse.ArgumentParser(description="Gathers stats after a run") + parser.add_argument( + "-o", + "--outdir", + default="cases", + help="Directory to generate the test suite in.", + ) + parser.add_argument( + "-f", + "--file", + type=argparse.FileType("w"), + default="stats.csv", + help="The resulting CSV file containing all stats.", + ) + return parser.parse_args(args) + + +def statsFromTimings(dir): + stats = {} + assert os.path.isdir(dir) + file = os.path.join(dir, "precice-B-events.json") + if os.path.isfile(file): + try: + timings = {} + with open(file, "r") as jsonfile: + timings = json.load(jsonfile)["Ranks"][0]["Timings"] + stats["globalTime"] = timings["_GLOBAL"]["Max"] + stats["initializeTime"] = timings["initialize"]["Max"] + computeMappingName = [ + x + for x in timings.keys() + if x.startswith("advance/map") + and x.endswith("computeMapping.FromA-MeshToB-Mesh") + ][0] + mapDataName = [ + x + for x in timings.keys() + if x.startswith("advance/map") + and x.endswith("mapData.FromA-MeshToB-Mesh") + ][0] + stats["computeMappingTime"] = timings[computeMappingName]["Max"] + stats["mapDataTime"] = timings[mapDataName]["Max"] + except BaseException: + pass + return stats + + +def memoryStats(dir): + stats = {} + assert os.path.isdir(dir) + for P in "A", "B": + memfile = os.path.join(dir, f"memory-{P}.log") + total = 0 + if os.path.isfile(memfile): + try: + with open(memfile, "r") as file: + total = sum([float(e) / 1024.0 for e in file.readlines()]) + except BaseException: + pass + stats[f"peakMem{P}"] = total + + return stats + + +def main(argv): + args = parseArguments(argv[1:]) + + globber = os.path.join(args.outdir, "**", "*.stats.json") + statFiles = [ + os.path.relpath(path, args.outdir) + for path in glob.iglob(globber, recursive=True) + ] + allstats = [] + fields = [] + for file in statFiles: + print("Found: " + file) + casedir = os.path.join(args.outdir, os.path.dirname(file)) + parts = os.path.normpath(file).split(os.sep) + assert len(parts) >= 5 + mapping, constraint, meshes, ranks, _ = parts[-5:] + meshA, meshB = meshes.split("-") + ranksA, ranksB = meshes.split("-") + + with open(os.path.join(args.outdir, file), "r") as jsonfile: + stats = json.load(jsonfile) + stats["mapping"] = mapping + stats["constraint"] = constraint + stats["mesh A"] = meshA + stats["mesh B"] = meshB + stats["ranks A"] = ranksA + stats["ranks B"] = ranksB + stats.update(statsFromTimings(casedir)) + stats.update(memoryStats(casedir)) + allstats.append(stats) + if not fields: + fields += stats.keys() + + assert fields + writer = csv.DictWriter(args.file, fieldnames=fields) + writer.writeheader() + writer.writerows(allstats) + return 0 + + +if __name__ == "__main__": + import sys + + sys.exit(main(sys.argv)) diff --git a/tools/mapping-tester/generate.py b/tools/mapping-tester/generate.py new file mode 100755 index 00000000..d66d9fb1 --- /dev/null +++ b/tools/mapping-tester/generate.py @@ -0,0 +1,303 @@ +#! /usr/bin/env python3 + +import argparse +import json +import os + +from jinja2 import Template + + +def generateConfig(template, setup): + template = Template(template) + return template.render(setup) + + +def as_iter(something): + try: + iter(something) + return something + except TypeError: + return [something] + + +def generateCases(setup): + meshes = setup["general"]["meshes"] + network = setup["general"].get("network", "lo") + syncmode = setup["general"].get("syncmode", "false") + + cases = [] + for group in setup["groups"]: + for name, mapping in group["mapping"]["cases"].items(): + for constraint in group["mapping"]["constraints"]: + for inname in group["meshes"]["A"]: + infile = meshes["A"][inname] + for outname in group["meshes"]["B"]: + outfile = meshes["B"][outname] + for ranksA, ranksB in zip( + as_iter(setup["general"]["ranks"].get("A", 1)), + as_iter(setup["general"]["ranks"].get("B", 1)), + ): + cases.append( + { + "function": setup["general"]["function"], + "mapping": { + "name": name, + "kind": mapping["kind"], + "constraint": constraint, + "options": mapping.get("options", ""), + }, + "A": { + "ranks": ranksA, + "mesh": { + "name": inname, + "file": infile, + }, + }, + "B": { + "ranks": ranksB, + "mesh": { + "name": outname, + "file": outfile, + }, + }, + "network": network, + "syncmode": syncmode, + } + ) + + return cases + + +def getCaseFolders(case): + return [ + case["mapping"]["name"], + case["mapping"]["constraint"], + "{}-{}".format(case["A"]["mesh"]["name"], case["B"]["mesh"]["name"]), + "{}-{}".format(case["A"]["ranks"], case["B"]["ranks"]), + ] + + +def caseToSortable(case): + parts = case.split(os.path.sep) + kind = parts[0] + mesha, meshb = map(float, parts[-2].split("-")) + + kindCost = 0 + if kind.startswith("gaussian"): + kindCost = 1 + elif kind.startswith("tps"): + kindCost = 2 + + return (kindCost, -mesha, -meshb) + + +def createMasterRunScripts(casemap, dir): + common = [ + "#!/bin/bash", + "", + 'cd "$( dirname "${BASH_SOURCE[0]}" )"', + "RUNNER=/bin/bash", + "", + ] + + # Generate master runner script + content = common + [ + "${RUNNER} " + os.path.join(case, "runall.sh") for case in casemap.keys() + ] + open(os.path.join(dir, "runall.sh"), "w").writelines( + [line + "\n" for line in content] + ) + + # Generate master postprocessing script + post = common + [ + "${RUNNER} " + os.path.join(case, "postprocessall.sh") + for case in casemap.keys() + ] + open(os.path.join(dir, "postprocessall.sh"), "w").writelines( + [line + "\n" for line in post] + ) + + for case, instances in casemap.items(): + # Generate master runner script + content = common + [ + "${RUNNER} " + os.path.join(*instance, "run-wrapper.sh") + for instance in instances + ] + open(os.path.join(dir, case, "runall.sh"), "w").writelines( + [line + "\n" for line in content] + ) + + # Generate master postprocessing script + post = common + [ + "${RUNNER} " + os.path.join(*instance, "post.sh") for instance in instances + ] + open(os.path.join(dir, case, "postprocessall.sh"), "w").writelines( + [line + "\n" for line in post] + ) + + +def createRunScript(outdir, path, case): + amesh = case["A"]["mesh"]["name"] + aranks = case["A"]["ranks"] + ameshLocation = os.path.relpath( + os.path.join(outdir, "meshes", amesh, str(aranks), amesh), path + ) + + # Generate runner script + acmd = '/usr/bin/time -f %M -a -o memory-A.log precice-aste-run -v -p A --data "{}" --mesh {} || kill 0 &'.format( + case["function"], ameshLocation + ) + if aranks > 1: + acmd = "mpirun -n {} $ASTE_A_MPIARGS {}".format(aranks, acmd) + + bmesh = case["B"]["mesh"]["name"] + branks = case["B"]["ranks"] + bmeshLocation = os.path.relpath( + os.path.join(outdir, "meshes", bmesh, str(branks), bmesh), path + ) + mapped_data_name = case["function"] + "(mapped)" + bcmd = '/usr/bin/time -f %M -a -o memory-B.log precice-aste-run -v -p B --data "{}" --mesh {} --output mapped || kill 0 &'.format( + mapped_data_name, bmeshLocation + ) + if branks > 1: + bcmd = "mpirun -n {} $ASTE_B_MPIARGS {}".format(branks, bcmd) + + content = [ + "#!/bin/bash", + "set -e -u", + 'cd "$( dirname "${BASH_SOURCE[0]}" )"', + "echo '=========='", + "rm -f memory-A.log memory-B.log done running failed", + "rm -fr mapped && mkdir mapped", + "touch running", + "echo '= {} ({}) {} - {}'".format( + case["mapping"]["name"], case["mapping"]["constraint"], amesh, bmesh + ), + "echo '=========='", + "", + "set -m", + "(", + acmd, + bcmd, + "wait", + ")", + 'if [[ "$?" -eq 0 ]]; then', + "touch done", + "else", + "touch failed", + "fi", + "rm -f running", + ] + open(os.path.join(path, "run.sh"), "w").writelines( + [line + "\n" for line in content] + ) + + # Generate wrapper script for runner + wrapper = [ + "#!/bin/bash", + 'cd "$( dirname "${BASH_SOURCE[0]}" )"', + "/bin/bash run.sh 2>&1 | tee run.log", + ] + open(os.path.join(path, "run-wrapper.sh"), "w").writelines( + [line + "\n" for line in wrapper] + ) + + # Generate post processing script + post_content = [ + "#!/bin/bash", + "set -e -u", + 'cd "$( dirname "${BASH_SOURCE[0]}" )"', + "echo '= {} ({}) {} - {}'".format( + case["mapping"]["name"], case["mapping"]["constraint"], amesh, bmesh + ), + ] + if branks == 1: + joincmd = "[ ! -f mapped.vtu ] || mv --update mapped.vtu mapped.vtk" + diffcmd = 'precice-aste-evaluate --data error --diffdata "{1}" --diff --stats --mesh mapped.vtk --function "{0}" | tee diff.log'.format( + case["function"], mapped_data_name + ) + post_content += [joincmd, diffcmd] + else: + [recoveryFileLocation, tmpPrefix] = os.path.split( + os.path.normpath(bmeshLocation) + ) + tmprecoveryFile = recoveryFileLocation + "/{}_recovery.json".format(bmesh) + joincmd = "precice-aste-join --mesh mapped -r {} -o result.vtk".format( + tmprecoveryFile + ) + diffcmd = 'precice-aste-evaluate --data error --diffdata "{1}" --diff --stats --mesh result.vtk --function "{0}" | tee diff.log'.format( + case["function"], mapped_data_name + ) + post_content += [joincmd, diffcmd] + open(os.path.join(path, "post.sh"), "w").writelines( + [line + "\n" for line in post_content] + ) + + +def setupCases(outdir, template, cases): + casemap = {} + for case in cases: + folders = getCaseFolders(case) + casemap.setdefault(folders[0], []).append(folders[1:]) + name = [outdir] + folders + path = os.path.join(*name) + config = os.path.join(path, "precice-config.xml") + + print(f"Generating {path}") + os.makedirs(path, exist_ok=True) + with open(config, "w") as config: + config.write(generateConfig(template, case)) + createRunScript(outdir, path, case) + print(f"Generated {len(cases)} cases") + + print(f"Generating master scripts") + createMasterRunScripts(casemap, outdir) + + +def parseArguments(args): + parser = argparse.ArgumentParser(description="Generator for a mapping test suite") + parser.add_argument( + "-o", + "--outdir", + default="cases", + help="Directory to generate the test suite in.", + ) + parser.add_argument( + "-s", + "--setup", + type=argparse.FileType("r"), + default="setup.json", + help="The test setup file to use.", + ) + parser.add_argument( + "-t", + "--template", + type=argparse.FileType("r"), + default="config-template.xml", + help="The precice config template to use.", + ) + return parser.parse_args(args) + + +def main(argv): + # Parse the input arguments + args = parseArguments(argv[1:]) + # Parse the json file using the json module + setup = json.load(args.setup) + # Read the xml-template file + template = args.template.read() + # Generate the actual cases + cases = generateCases(setup) + outdir = os.path.normpath(args.outdir) + if os.path.isdir(outdir): + print('Warning: outdir "{}" already exisits.'.format(outdir)) + + setupCases(outdir, template, cases) + + return 0 + + +if __name__ == "__main__": + import sys + + sys.exit(main(sys.argv)) diff --git a/tools/mapping-tester/local_rbf.py b/tools/mapping-tester/local_rbf.py new file mode 100755 index 00000000..7c1b745f --- /dev/null +++ b/tools/mapping-tester/local_rbf.py @@ -0,0 +1,135 @@ +#! python3 + +import argparse +import itertools +import json +import math +import sys + + +class ArgumentSanitizationError(BaseException): + def __init__(self, message): + super().__init__(message) + + +def sanitize(element, options): + if element not in options: + raise ArgumentSanitizationError( + f"Argument {element} is not one of the following valid options: {', '.join(options)}" + ) + return element + + +def parseArguments(argv): + # Setup options + valid_polynomials = set(["on", "separate", "off"]) + valid_types = set( + [ + "multiquadrics", + "inverse-multiquadrics", + "volume-splines", + "gaussian", + "compact-tps-c2", + "compact-polynomial-c0", + "compact-polynomial-c6", + ] + ) + + # Setup defaults + default_polynomials = "on,separate" + default_types = "gaussian" + + # Parse arguments + parser = argparse.ArgumentParser() + parser.add_argument("-A", "--a-meshes", dest="a", type=str, required=True) + parser.add_argument("-B", "--b-meshes", dest="b", type=str, required=True) + parser.add_argument("-p", "--polynomials", default=default_polynomials, type=str) + parser.add_argument("-t", "--types", default=default_types, type=str) + parser.add_argument("-n", "--coverage", default="3,5,10,15", type=str) + parser.add_argument( + "-o", "--output", default=sys.stdout, type=argparse.FileType("w") + ) + parser.add_argument("-r", "--solver-rtol", default=1e-9, type=float) + + args = parser.parse_args(argv[1:]) + + # Sanitize arguments + args.a = [float(e.strip()) for e in args.a.split(",")] + args.b = [float(e.strip()) for e in args.b.split(",")] + args.polynomials = [ + sanitize(e, valid_polynomials) for e in args.polynomials.split(",") + ] + args.types = [sanitize(e, valid_types) for e in args.types.split(",")] + args.coverage = [int(e.strip()) for e in args.coverage.split(",")] + + return args + + +class NotImplementedError(BaseException): + def __init__(self, type): + super().__init__(f"The rbf mapping type {type} is not implemented.") + + +def getConfigurator(type): + """ + Provides a configuration function for given types of mappings. + The returned resulting function takes the edge lenght h and the coverage n + as arguments and returns an option string for the rbf mapping. + """ + + # The various configuration functions + def gauss(h, n): + GAUSSIAN_DECAY = 1e-9 + shape = math.sqrt(-math.log(GAUSSIAN_DECAY)) / (float(h) * int(n)) + return f'shape-parameter="{shape}"' + + def compact_tps_c2(h, n): + return f'support-radius="{h*n}"' + + # This dictionary maps a type to a configuration function defined above + res = { + "gaussian": gauss, + "compact-tps-c2": compact_tps_c2, + }.get(type) + if res is None: + raise NotImplementedError(type) + return res + + +def main(argv): + args = parseArguments(argv) + sections = [] + # We group by a meshes as we only produce conservative mappings. + # For conservative mappings, the shape function depends on the edge lenght + # of mesh a. + for a in args.a: + cases = {} + for polynomial, coverage, type in itertools.product( + args.polynomials, args.coverage, args.types + ): + name = f"{type}-n{coverage}-{polynomial}" + assert name not in cases + config = getConfigurator(type)(a, coverage) + cases[name] = { + "kind": f"rbf-{type}", + "options": f'{config} polynomial="{polynomial}" solver-rtol="{args.solver_rtol}"', + } + section = { + "mapping": {"constraints": ["consistent"], "cases": cases}, + "meshes": { + "A": ["{:g}".format(a)], + "B": ["{:g}".format(b) for b in args.b], + }, + } + sections.append(section) + + json.dump(sections, args.output, indent=2) + + +if __name__ == "__main__": + try: + main(sys.argv) + except Exception as e: + print(e) + sys.exit(1) + sys.exit(0) diff --git a/tools/mapping-tester/plotconv.py b/tools/mapping-tester/plotconv.py new file mode 100755 index 00000000..8e20201e --- /dev/null +++ b/tools/mapping-tester/plotconv.py @@ -0,0 +1,224 @@ +#! /usr/bin/env python3 + +import argparse +import math + +import matplotlib.pyplot as plt +import numpy as np +import pandas + + +def parseArguments(args): + parser = argparse.ArgumentParser( + description="Creates convergence plots from gathered stats" + ) + parser.add_argument( + "-f", + "--file", + type=argparse.FileType("r"), + default="stats.csv", + help="The CSV file containing the gathered stats.", + ) + parser.add_argument( + "-p", + "--prefix", + default="result", + help="The prefix for all generated PDF plots.", + ) + return parser.parse_args(args) + + +def lavg(l): + return math.exp(sum(map(math.log, l)) / len(l)) + + +# seaborn.color_palette("colorblind", 10).as_hex() +style_colours = [ + "#0173b2", + "#de8f05", + "#029e73", + "#d55e00", + "#cc78bc", + "#ca9161", + "#fbafe4", + "#949494", + "#ece133", + "#56b4e9", +] +style_markers = ["o", "D", "s"] +styles = [(c, m) for m in style_markers for c in style_colours] + + +def plotConv(ax, df, yname): + xmin = df["mesh A"].min() + xmax = df["mesh A"].max() + ymin = df[yname].min() + ymax = df[yname].max() + + print(xmin, xmax) + print(ymin, ymax) + + # 1st order line + fox = [xmax, xmin] + foy1 = ymax + foy2 = foy1 * (fox[1] / fox[0]) + foy = [foy1, foy2] + ax.axline( + (fox[0], foy[0]), (fox[1], foy[1]), color="lightgray", linewidth=1.0, zorder=-1 + ) + ax.annotate("1st order", xy=(lavg(fox), lavg(foy)), color="gray", zorder=-1) + + # # 2nd order line + sox = [xmin, xmax] + soy1 = ymin + soy2 = soy1 * ((sox[1] / sox[0]) ** 2) + soy = [soy1, soy2] + print(sox, soy) + ax.axline( + (sox[0], soy[0]), (sox[1], soy[1]), color="lightgray", linewidth=1.0, zorder=-1 + ) + ax.annotate("2nd order", xy=(lavg(sox), lavg(soy)), color="gray", zorder=-1) + + +def plotError(df, prefix): + yname = "relative-l2" + fig, ax = plt.subplots(sharex=True, sharey=True) + series = df.groupby("mapping") + for grouped, style in zip(series, styles): + name, group = grouped + if group[yname].max() == 0: + print(f"Dropping {yname}-series {name} as all 0") + continue + color, marker = style + group.plot( + ax=ax, + loglog=True, + x="mesh A", + y=yname, + label=name, + marker=marker, + color=color, + ) + ax.set_xlabel("edge length(h) of mesh A") + ax.set_ylabel("relative-l2 error mapping to mesh B") + + plotConv(ax, df, yname) + + plt.gca().invert_xaxis() + plt.grid() + plt.savefig(prefix + "-error.pdf") + + +def plotMemory(df, prefix): + yname = "peakMemB" + fig, ax = plt.subplots(sharex=True, sharey=True) + series = df.groupby("mapping") + for grouped, style in zip(series, styles): + name, group = grouped + if group[yname].max() == 0: + print(f"Dropping {yname}-series {name} as all 0") + continue + color, marker = style + group.plot( + ax=ax, + loglog=True, + x="mesh A", + y=yname, + label=name, + marker=marker, + color=color, + ) + ax.set_xlabel("edge length(h) of mesh A") + ax.set_ylabel("peak memory of participant B [bytes]") + + # plotConv(ax, df, yname) + + plt.gca().invert_xaxis() + plt.grid() + plt.savefig(prefix + "-peakMemB.pdf") + + +def plotComputeMappingTime(df, prefix): + yname = "computeMappingTime" + fig, ax = plt.subplots(sharex=True, sharey=True) + series = df.groupby("mapping") + for grouped, style in zip(series, styles): + name, group = grouped + if group[yname].max() == 0: + print(f"Dropping {yname}-series {name} as all 0") + continue + color, marker = style + group.plot( + ax=ax, + loglog=True, + x="mesh A", + y=yname, + label=name, + marker=marker, + color=color, + ) + + ax.set_xlabel("edge length(h) of mesh A") + ax.set_ylabel("time to compute mapping [ms]") + + # plotConv(ax, df, yname) + + plt.gca().invert_xaxis() + plt.grid() + plt.savefig(prefix + "-computet.pdf") + + +def plotMapDataTime(df, prefix): + yname = "mapDataTime" + fig, ax = plt.subplots(sharex=True, sharey=True) + series = df.groupby("mapping") + for grouped, style in zip(series, styles): + name, group = grouped + if group[yname].max() == 0: + print(f"Dropping {yname}-series {name} as all 0") + continue + color, marker = style + group.plot( + ax=ax, + loglog=True, + x="mesh A", + y=yname, + label=name, + marker=marker, + color=color, + ) + + ax.set_xlabel("edge length(h) of mesh A") + ax.set_ylabel("time to map Data [ms]") + + # plotConv(ax, df, yname) + + plt.gca().invert_xaxis() + plt.grid() + plt.savefig(prefix + "-mapt.pdf") + + +def main(argv): + args = parseArguments(argv[1:]) + + plt.rcParams["legend.fontsize"] = "small" + plt.rcParams["figure.figsize"] = "8, 8" + plt.rcParams["figure.autolayout"] = "true" + + df = pandas.read_csv(args.file) + toMeshes = df["mesh B"].unique() + assert ( + len(toMeshes) == 1 + ), f"There are {len(toMeshes)} to-meshes but only 1 is allowed. Fix your dataset!" + df.sort_values("mesh A", inplace=True) + plotError(df, args.prefix) + plotMemory(df, args.prefix) + plotMapDataTime(df, args.prefix) + plotComputeMappingTime(df, args.prefix) + return 0 + + +if __name__ == "__main__": + import sys + + sys.exit(main(sys.argv)) diff --git a/tools/mapping-tester/plots/paperplot.py b/tools/mapping-tester/plots/paperplot.py new file mode 100755 index 00000000..45e4b7c7 --- /dev/null +++ b/tools/mapping-tester/plots/paperplot.py @@ -0,0 +1,226 @@ +#! python3 + + +import argparse +import itertools +import math + +import matplotlib.pyplot as plt +import numpy as np +import pandas + + +def parseArguments(args): + parser = argparse.ArgumentParser( + description="Creates convergence plots from gathered stats" + ) + parser.add_argument( + "-f", + "--file", + type=argparse.FileType("r"), + default="stats.csv", + help="The CSV file containing the gathered stats.", + ) + parser.add_argument( + "--show", action="store_true", help="Shows the plots insead of saving them." + ) + return parser.parse_args(args) + + +def lavg(l): + return math.exp(sum(map(math.log, l)) / len(l)) + + +def getStyler(): + styles = ["solid", "dashed", "dashdot"] + colors = [ + "#0173b2", + "#de8f05", + "#029e73", + "#d55e00", + "#cc78bc", + "#ca9161", + "#fbafe4", + "#949494", + "#ece133", + "#56b4e9", + ] + markers = ["o", "v", "^", "D", "*"] + for style in itertools.product(styles, markers, colors): + yield style + + +def plot_order(ax, nth, xmin, xmax, ymin, ymax): + x1, y1 = xmax, ymax + + def f(x): + return y1 * ((x / x1) ** nth) + + xl, xu = xmin, xmax + for step in range(4): + xt = lavg([xu, xl]) + yt = f(xt) + + if yt > ymin: + xu = xt + if yt < ymin: + xl = xt + x2, y2 = xu, f(xu) + + xs, ys = [x1, x2], [y1, y2] + ax.plot(xs, ys, color="lightgray", linewidth=1.0, zorder=-1) + ax.annotate( + "{} order".format(nth), xy=(lavg(xs), lavg(ys)), color="gray", zorder=-1 + ) + + +def main(argv): + args = parseArguments(argv[1:]) + + df = pandas.read_csv(args.file) + numeric_cols = [ + "mesh A", + "mesh B", + "count", + "min", + "max", + "median", + "relative-l2", + "weighted-l2", + "99th percentile", + "95th percentile", + "90th percentile", + "peakMemA", + "peakMemB", + "computeMappingTime", + ] + df[numeric_cols] = df[numeric_cols].apply(pandas.to_numeric) + + # remove all matching meshes + df = df[df["mesh A"] != df["mesh B"]] + + singleB = df[df["mesh B"] == 0.025] + + # \item about the best way to go: for one target mesh compare best local-rbf (gaussian), global-rbf (tps), nn, np (For each geometry: 12 series) + # Goal: show errors of best mappings (user perspective) + best = singleB[ + singleB["mapping"].apply( + lambda n: (n in ["nn", "np", "tps"]) | n.endswith("-separate") + ) + ] + plot(best, "best-mappings", xname="mesh A", yname="relative-l2", show=args.show) + + # \item pick one geometry, one target mesh: nn, np, tps, gaussian-nX separate + # Goal: show memory usage of best mappings (user perspective) + plot( + singleB, + "memory-usage", + xname="mesh A", + yname="peakMemB", + show=args.show, + conv=False, + ) + + # \item pick one geometry, one target mesh: nn, np, tps, gaussian-nX separate + # Goal: show compute time of best mappings (user perspective) + plot( + singleB[singleB["computeMappingTime"] > 0], + "compute-time", + xname="mesh A", + yname="computeMappingTime", + show=args.show, + conv=False, + ) + + # \item pick one geometry, one target mesh, varying rank counts: nn, np, tps, gaussian-nX separate + # Goal: show weak scalability of best mappings (user perspective) + # TODO plot(singleB, show=args.show) + + # \item pick one geometry, fixed rank count, varying target meshes: nn, np, tps, gaussian-nX separate + # Goal: show strong scalability of best mappings (user perspective) + plot( + singleB, + "strong-scaling", + xname="mesh A", + yname="computeMappingTime", + show=args.show, + conv=False, + ) + + # \item pick one geometry and target mesh: compare gaussian rbf on vs separate and different support radii (8 series) + # Goal: Options for local-rbf you should not choose and why + gaussians = singleB[df["mapping"].str.startswith("gaussian")] + plot(gaussians, "rbf-comp", xname="mesh A", yname="relative-l2", show=args.show) + + # \item pick one geometry: 3 different target meshes: np vs gaussian-n5-separate (6 series) + # Goal: Above holds for different target meshes + reverse = df.query('mapping == "np" | mapping == "gaussian-n5-separate"') + plot(reverse, "changing-b", xname="mesh A", yname="relative-l2", show=args.show) + + return 0 + + +def plot( + df, + output, + xname="mesh A", + yname="relative-l2", + groupname="mesh B", + show=False, + conv=True, +): + fmt = "{} onto {}" + styler = getStyler() + + print("Plot x:{} y:{} grouped by {}".format(xname, yname, groupname)) + + df = df.sort_values(xname) + grouped = df.groupby(["mapping", groupname]) + + fig, ax = plt.subplots(sharex=True, sharey=True, figsize=(10, 5)) + + for name, group in grouped: + print("\tGroup {} with {} points".format(fmt.format(*name), group.shape[0])) + l, m, c = next(styler) + group.plot( + ax=ax, + loglog=True, + x=xname, + y=yname, + label=fmt.format(*name), + marker=m, + linestyle=l, + color=c, + ) + ax.set_xlabel("edge length(h) of {}".format(xname)) + ax.set_ylabel("{} error mapping to mesh B".format(yname)) + + if conv: + filtered = df[yname] + plot_order( + ax, 1, df[xname].min(), df[xname].max(), filtered.min(), filtered.max() + ) + plot_order( + ax, 2, df[xname].min(), df[xname].max(), filtered.min(), filtered.max() + ) + plot_order( + ax, 3, df[xname].min(), df[xname].max(), filtered.min(), filtered.max() + ) + + plt.gca().invert_xaxis() + plt.grid() + ax.legend(loc="upper left", bbox_to_anchor=(1, 1)) + plt.subplots_adjust(right=0.7) + + if show: + plt.show() + else: + parts = [output] + parts.extend(".pdf") + fig.savefig("".join(parts), pad_inches=1) + + +if __name__ == "__main__": + import sys + + sys.exit(main(sys.argv)) diff --git a/tools/mapping-tester/plots/plot.py b/tools/mapping-tester/plots/plot.py new file mode 100755 index 00000000..de862d63 --- /dev/null +++ b/tools/mapping-tester/plots/plot.py @@ -0,0 +1,181 @@ +#! python3 + +import argparse +import itertools +import math + +import matplotlib.pyplot as plt +import numpy as np +import pandas + + +def parseArguments(args): + parser = argparse.ArgumentParser( + description="Creates convergence plots from gathered stats" + ) + parser.add_argument( + "-f", + "--file", + type=argparse.FileType("r"), + default="stats.csv", + help="The CSV file containing the gathered stats.", + ) + parser.add_argument( + "-ni", + "--no-inverse", + dest="inverse", + action="store_false", + help="Do not create inverse plots.", + ) + parser.add_argument( + "--show", action="store_true", help="Shows the plots insead of saving them." + ) + return parser.parse_args(args) + + +def lavg(l): + return math.exp(sum(map(math.log, l)) / len(l)) + + +def getStyler(): + styles = ["solid", "dashed", "dashdot"] + colors = [ + "#0173b2", + "#de8f05", + "#029e73", + "#d55e00", + "#cc78bc", + "#ca9161", + "#fbafe4", + "#949494", + "#ece133", + "#56b4e9", + ] + markers = ["o", "v", "^", "D", "*"] + for style in itertools.product(styles, markers, colors): + yield style + + +def plot_order(ax, nth, xmin, xmax, ymin, ymax): + x1, y1 = xmax, ymax + + def f(x): + return y1 * ((x / x1) ** nth) + + xl, xu = xmin, xmax + for step in range(4): + xt = lavg([xu, xl]) + yt = f(xt) + + if yt > ymin: + xu = xt + if yt < ymin: + xl = xt + x2, y2 = xu, f(xu) + + xs, ys = [x1, x2], [y1, y2] + ax.plot(xs, ys, color="lightgray", linewidth=1.0, zorder=-1) + ax.annotate( + "{} order".format(nth), xy=(lavg(xs), lavg(ys)), color="gray", zorder=-1 + ) + + +def main(argv): + args = parseArguments(argv[1:]) + + df = pandas.read_csv(args.file) + numeric_cols = [ + "mesh A", + "mesh B", + "count", + "min", + "max", + "median", + "relative-l2", + "weighted-l2", + "99th percentile", + "95th percentile", + "90th percentile", + ] + df[numeric_cols] = df[numeric_cols].apply(pandas.to_numeric) + + # A on x axes + plot(df, False, True, args.show) + plot(df, False, False, args.show) + + if args.inverse: + # B on x axes + plot(df, True, True, args.show) + plot(df, True, False, args.show) + return 0 + + +def plot(df, inverse, idfilter, show=False): + if inverse: + xname = "mesh B" + groupname = "mesh A" + fmt = "{} from {}" + else: + xname = "mesh A" + groupname = "mesh B" + fmt = "{} onto {}" + yname = "relative-l2" + styler = getStyler() + + print("Plot x:{} y:{} grouped by {}".format(xname, yname, groupname)) + + df.sort_values(xname, inplace=True) + grouped = df.groupby(["mapping", groupname]) + + fig, ax = plt.subplots(sharex=True, sharey=True, figsize=(10, 5)) + + for name, group in grouped: + filtered = group[group["mesh A"] != group["mesh B"]] if idfilter else group + print("\tGroup {} with {} points".format(fmt.format(*name), filtered.shape[0])) + l, m, c = next(styler) + filtered.plot( + ax=ax, + loglog=True, + x=xname, + y=yname, + label=fmt.format(*name), + marker=m, + linestyle=l, + color=c, + ) + ax.set_xlabel("edge length(h) of {}".format(xname)) + ax.set_ylabel("{} error mapping to mesh B".format(yname)) + + if not inverse: + filtered = df[df["mesh A"] != df["mesh B"]][yname] + plot_order( + ax, 1, df[xname].min(), df[xname].max(), filtered.min(), filtered.max() + ) + plot_order( + ax, 2, df[xname].min(), df[xname].max(), filtered.min(), filtered.max() + ) + plot_order( + ax, 3, df[xname].min(), df[xname].max(), filtered.min(), filtered.max() + ) + + plt.gca().invert_xaxis() + plt.grid() + ax.legend(loc="upper left", bbox_to_anchor=(1, 1)) + plt.subplots_adjust(right=0.7) + + if show: + plt.show() + else: + parts = ["plot"] + if inverse: + parts.extend("-inverse") + if idfilter: + parts.extend("-noid") + parts.extend(".pdf") + fig.savefig("".join(parts), pad_inches=1) + + +if __name__ == "__main__": + import sys + + sys.exit(main(sys.argv)) diff --git a/tools/mapping-tester/preparemeshes.py b/tools/mapping-tester/preparemeshes.py new file mode 100755 index 00000000..78e77d99 --- /dev/null +++ b/tools/mapping-tester/preparemeshes.py @@ -0,0 +1,139 @@ +#! /usr/bin/env python3 + +import argparse +import itertools +import json +import os +import shutil +import subprocess + + +def parseArguments(args): + parser = argparse.ArgumentParser(description="Prepares meshes for a test suite") + parser.add_argument( + "-o", + "--outdir", + default="cases", + help="Directory to generate the test suite in.", + ) + parser.add_argument( + "-s", + "--setup", + type=argparse.FileType("r"), + default="setup.json", + help="The test setup file to use.", + ) + parser.add_argument( + "-f", "--force", action="store_true", help="Remove existing meshes." + ) + + return parser.parse_args(args) + + +def prepareMainMesh(meshdir, name, file, function, force=False): + mainDir = os.path.join(meshdir, name, "1") + mainMesh = os.path.join(mainDir, name + ".vtu") + print("Preparing Mesh {} in {}".format(name, mainDir)) + + if os.path.isdir(mainDir): + if force: + print(" Regenerating the mesh.") + shutil.rmtree(mainDir) + else: + print(" Mesh already exists.") + + return + + os.makedirs(mainDir, exist_ok=True) + data_name = "{}".format(function) + [pathName, tmpfilename] = os.path.split(os.path.normpath(mainMesh)) + subprocess.run( + [ + "precice-aste-evaluate", + "--mesh", + os.path.expandvars(file), + "--function", + function, + "--data", + data_name, + "--directory", + pathName, + "-o", + tmpfilename, + ] + ) + + +def preparePartMesh(meshdir, name, p, force=False): + + if p == 1: + return + + mainMesh = os.path.join(meshdir, name, "1", name + ".vtu") + partDir = os.path.join(meshdir, name, str(p)) + partMesh = os.path.join(partDir, name) + print("Preparing Mesh {} with {} paritions in {}".format(name, p, partDir)) + + if os.path.isdir(partDir): + if force: + print(" Regenerating the partitioned mesh.") + shutil.rmtree(partDir) + else: + print(" Partitioned mesh already exists.") + + return + + os.makedirs(partDir, exist_ok=True) + [pathName, tmpfilename] = os.path.split(os.path.normpath(partMesh)) + subprocess.run( + [ + "precice-aste-partition", + "--mesh", + mainMesh, + "--algorithm", + "meshfree", + "-o", + partMesh, + "--directory", + pathName, + "-n", + str(p), + ] + ) + + +def main(argv): + args = parseArguments(argv[1:]) + setup = json.load(args.setup) + outdir = os.path.normpath(args.outdir) + + if os.path.isdir(outdir): + print('Warning: outdir "{}" already exisits.'.format(outdir)) + meshdir = os.path.join(outdir, "meshes") + function = setup["general"]["function"] + + partitions = set( + [int(rank) for pranks in setup["general"]["ranks"].values() for rank in pranks] + ) + + for name, file in set( + itertools.chain( + setup["general"]["meshes"]["A"].items(), + setup["general"]["meshes"]["B"].items(), + ) + ): + + if not os.path.isfile(os.path.expandvars(file)): + raise Exception(f'\033[91m Unable to open file called "{file}".\033[0m') + prepareMainMesh(meshdir, name, file, function, args.force) + + for p in partitions: + preparePartMesh(meshdir, name, p, args.force) + + return 0 + + +if __name__ == "__main__": + import sys + + sys.exit(main(sys.argv)) diff --git a/tools/mapping-tester/setup-turbine-big.json b/tools/mapping-tester/setup-turbine-big.json new file mode 100644 index 00000000..5ba655f4 --- /dev/null +++ b/tools/mapping-tester/setup-turbine-big.json @@ -0,0 +1,352 @@ +{ + "general": { + "function": "0.78 + cos(10*(x+y+z))", + "ranks": { + "A": [ + 48 + ], + "B": [ + 96 + ] + }, + "network": "ib0", + "syncmode": true, + "meshes": { + "A": { + "0.004": "$ASTE_MESHES/0.004.vtk", + "0.003": "$ASTE_MESHES/0.003.vtk", + "0.002": "$ASTE_MESHES/0.002.vtk", + "0.001": "$ASTE_MESHES/0.001.vtk", + "0.0007": "$ASTE_MESHES/0.0007.vtk", + "0.0005": "$ASTE_MESHES/0.0005.vtk" + }, + "B": { + "0.0014": "$ASTE_MESHES/0.0014.vtk" + } + } + }, + "groups": [ + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "np": { + "kind": "nearest-projection" + }, + "nn": { + "kind": "nearest-neighbor" + } + } + }, + "meshes": { + "A": [ + "0.004", + "0.003", + "0.002", + "0.001", + "0.0007", + "0.0005" + ], + "B": [ + "0.0014" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "compact-tps-c2-n3-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.012\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.02\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.028\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.04\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n3-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.012\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.02\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.028\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.04\" polynomial=\"on\" solver-rtol=\"1e-06\"" + } + } + }, + "meshes": { + "A": [ + "0.004" + ], + "B": [ + "0.0014" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "compact-tps-c2-n3-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.009000000000000001\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.015\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.021\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.03\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n3-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.009000000000000001\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.015\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.021\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.03\" polynomial=\"on\" solver-rtol=\"1e-06\"" + } + } + }, + "meshes": { + "A": [ + "0.003" + ], + "B": [ + "0.0014" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "compact-tps-c2-n3-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.006\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.01\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.014\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.02\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n3-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.006\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.01\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.014\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.02\" polynomial=\"on\" solver-rtol=\"1e-06\"" + } + } + }, + "meshes": { + "A": [ + "0.002" + ], + "B": [ + "0.0014" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "compact-tps-c2-n3-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.003\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.005\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.007\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.01\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n3-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.003\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.005\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.007\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.01\" polynomial=\"on\" solver-rtol=\"1e-06\"" + } + } + }, + "meshes": { + "A": [ + "0.001" + ], + "B": [ + "0.0014" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "compact-tps-c2-n3-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.0021\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.0035\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.0049\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.007\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n3-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.0021\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.0035\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.0049\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.007\" polynomial=\"on\" solver-rtol=\"1e-06\"" + } + } + }, + "meshes": { + "A": [ + "0.0007" + ], + "B": [ + "0.0014" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "compact-tps-c2-n3-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.0015\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.0025\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.0035\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.005\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n3-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.0015\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.0025\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.0035\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.005\" polynomial=\"on\" solver-rtol=\"1e-06\"" + } + } + }, + "meshes": { + "A": [ + "0.0005" + ], + "B": [ + "0.0014" + ] + } + } + ] +} diff --git a/tools/mapping-tester/setup-turbine-small-tps.json b/tools/mapping-tester/setup-turbine-small-tps.json new file mode 100644 index 00000000..b2747a97 --- /dev/null +++ b/tools/mapping-tester/setup-turbine-small-tps.json @@ -0,0 +1,55 @@ +{ + "general": { + "function": "0.78 + cos(10*(x+y+z))", + "ranks": { + "A": [ + 2 + ], + "B": [ + 4 + ] + }, + "syncmode": true, + "meshes": { + "A": { + "0.03": "$ASTE_MESHES/0.03.vtk", + "0.02": "$ASTE_MESHES/0.02.vtk", + "0.01": "$ASTE_MESHES/0.01.vtk", + "0.008": "$ASTE_MESHES/0.008.vtk", + "0.006": "$ASTE_MESHES/0.006.vtk", + "0.004": "$ASTE_MESHES/0.004.vtk" + }, + "B": { + "0.009": "$ASTE_MESHES/0.009.vtk" + } + } + }, + "groups": [ + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "tps": { + "kind": "rbf-thin-plate-splines", + "options": "use-qr-decomposition=\"1\"" + } + } + }, + "meshes": { + "A": [ + "0.03", + "0.02", + "0.01", + "0.008", + "0.006", + "0.004" + ], + "B": [ + "0.009" + ] + } + } + ] +} diff --git a/tools/mapping-tester/setup-turbine-small.json b/tools/mapping-tester/setup-turbine-small.json new file mode 100644 index 00000000..d8d887c1 --- /dev/null +++ b/tools/mapping-tester/setup-turbine-small.json @@ -0,0 +1,698 @@ +{ + "general": { + "function": "0.78 + cos(10*(x+y+z))", + "ranks": { + "A": [ + 48 + ], + "B": [ + 96 + ] + }, + "network": "ib0", + "syncmode": true, + "meshes": { + "A": { + "0.03": "$ASTE_MESHES/0.03.vtk", + "0.02": "$ASTE_MESHES/0.02.vtk", + "0.01": "$ASTE_MESHES/0.01.vtk", + "0.008": "$ASTE_MESHES/0.008.vtk", + "0.006": "$ASTE_MESHES/0.006.vtk", + "0.004": "$ASTE_MESHES/0.004.vtk" + }, + "B": { + "0.009": "$ASTE_MESHES/0.009.vtk" + } + } + }, + "groups": [ + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "np": { + "kind": "nearest-projection" + }, + "nn": { + "kind": "nearest-neighbor" + }, + "tps": { + "kind": "rbf-thin-plate-splines", + "options": "use-qr-decomposition=\"1\"" + } + } + }, + "meshes": { + "A": [ + "0.03", + "0.02", + "0.01", + "0.008", + "0.006", + "0.004" + ], + "B": [ + "0.009" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"50.580904312838214\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n3-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.09\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"30.34854258770293\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.15\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n7-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"21.677530419787807\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.21\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"15.174271293851465\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.3\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"50.580904312838214\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n3-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.09\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"30.34854258770293\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.15\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "gaussian-n7-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"21.677530419787807\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.21\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"15.174271293851465\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.3\" polynomial=\"on\" solver-rtol=\"1e-06\"" + } + } + }, + "meshes": { + "A": [ + "0.03" + ], + "B": [ + "0.009" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"75.87135646925732\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n3-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.06\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"45.52281388155439\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.1\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n7-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"32.51629562968171\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.14\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"22.761406940777196\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.2\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"75.87135646925732\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n3-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.06\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"45.52281388155439\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.1\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "gaussian-n7-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"32.51629562968171\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.14\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"22.761406940777196\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.2\" polynomial=\"on\" solver-rtol=\"1e-06\"" + } + } + }, + "meshes": { + "A": [ + "0.02" + ], + "B": [ + "0.009" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"151.74271293851464\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n3-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.03\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"91.04562776310878\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.05\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n7-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"65.03259125936341\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.07\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"45.52281388155439\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.1\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"151.74271293851464\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n3-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.03\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"91.04562776310878\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.05\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "gaussian-n7-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"65.03259125936341\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.07\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"45.52281388155439\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.1\" polynomial=\"on\" solver-rtol=\"1e-06\"" + } + } + }, + "meshes": { + "A": [ + "0.01" + ], + "B": [ + "0.009" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"189.6783911731433\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n3-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.024\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"113.80703470388598\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.04\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n7-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"81.29073907420427\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.056\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"56.90351735194299\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.08\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"189.6783911731433\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n3-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.024\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"113.80703470388598\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.04\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "gaussian-n7-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"81.29073907420427\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.056\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"56.90351735194299\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.08\" polynomial=\"on\" solver-rtol=\"1e-06\"" + } + } + }, + "meshes": { + "A": [ + "0.008" + ], + "B": [ + "0.009" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"252.90452156419104\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n3-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.018000000000000002\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"151.74271293851464\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.03\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n7-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"108.38765209893901\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.042\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"75.87135646925732\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.06\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"252.90452156419104\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n3-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.018000000000000002\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"151.74271293851464\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.03\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "gaussian-n7-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"108.38765209893901\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.042\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"75.87135646925732\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.06\" polynomial=\"on\" solver-rtol=\"1e-06\"" + } + } + }, + "meshes": { + "A": [ + "0.006" + ], + "B": [ + "0.009" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"379.3567823462866\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n3-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.012\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"227.61406940777195\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.02\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n7-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"162.58147814840854\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.028\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"113.80703470388598\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.04\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"379.3567823462866\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n3-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.012\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"227.61406940777195\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n5-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.02\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "gaussian-n7-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"162.58147814840854\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n7-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.028\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"113.80703470388598\" polynomial=\"on\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n10-on": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.04\" polynomial=\"on\" solver-rtol=\"1e-06\"" + } + } + }, + "meshes": { + "A": [ + "0.004" + ], + "B": [ + "0.009" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "compact-tps-c2-n15-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.44999999999999996\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n20-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.6\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + } + } + }, + "meshes": { + "A": [ + "0.03" + ], + "B": [ + "0.009" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "compact-tps-c2-n15-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.3\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n20-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.4\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + } + } + }, + "meshes": { + "A": [ + "0.02" + ], + "B": [ + "0.009" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "compact-tps-c2-n15-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.15\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n20-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.2\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + } + } + }, + "meshes": { + "A": [ + "0.01" + ], + "B": [ + "0.009" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "compact-tps-c2-n15-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.12\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n20-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.16\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + } + } + }, + "meshes": { + "A": [ + "0.008" + ], + "B": [ + "0.009" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "compact-tps-c2-n15-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.09\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n20-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.12\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + } + } + }, + "meshes": { + "A": [ + "0.006" + ], + "B": [ + "0.009" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "compact-tps-c2-n15-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.06\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + }, + "compact-tps-c2-n20-separate": { + "kind": "rbf-compact-tps-c2", + "options": "support-radius=\"0.08\" polynomial=\"separate\" solver-rtol=\"1e-06\"" + } + } + }, + "meshes": { + "A": [ + "0.004" + ], + "B": [ + "0.009" + ] + } + } + ] +} diff --git a/tools/mapping-tester/setup.json b/tools/mapping-tester/setup.json new file mode 100644 index 00000000..22527335 --- /dev/null +++ b/tools/mapping-tester/setup.json @@ -0,0 +1,880 @@ +{ + "general": { + "function": "cos(0.1*(x+y+z))", + "ranks": { + "A": [1, 2], + "B": [1, 2] + }, + "meshes": { + "A": { + "1": "/work_fast/ga36qid/precice/meshes/turbine/UnitSize/1.vtk", + "0.75": "/work_fast/ga36qid/precice/meshes/turbine/UnitSize/0.75.vtk", + "0.5": "/work_fast/ga36qid/precice/meshes/turbine/UnitSize/0.5.vtk", + "0.25": "/work_fast/ga36qid/precice/meshes/turbine/UnitSize/0.25.vtk", + "0.1": "/work_fast/ga36qid/precice/meshes/turbine/UnitSize/0.1.vtk", + "0.075": "/work_fast/ga36qid/precice/meshes/turbine/UnitSize/0.075.vtk", + "0.05": "/work_fast/ga36qid/precice/meshes/turbine/UnitSize/0.05.vtk", + "0.025": "/work_fast/ga36qid/precice/meshes/turbine/UnitSize/0.025.vtk", + "0.01": "/work_fast/ga36qid/precice/meshes/turbine/UnitSize/0.01.vtk", + "0.0075": "/work_fast/ga36qid/precice/meshes/turbine/UnitSize/0.0075.vtk", + "0.005": "/work_fast/ga36qid/precice/meshes/turbine/UnitSize/0.005.vtk", + "0.0025": "/work_fast/ga36qid/precice/meshes/turbine/UnitSize/0.0025.vtk", + "0.001": "/work_fast/ga36qid/precice/meshes/turbine/UnitSize/0.001.vtk", + "0.00075": "/work_fast/ga36qid/precice/meshes/turbine/UnitSize/0.00075.vtk", + "0.0005": "/work_fast/ga36qid/precice/meshes/turbine/UnitSize/0.0005.vtk" + }, + "B": { + "0.5": "/work_fast/ga36qid/precice/meshes/turbine/UnitSize/0.5.vtk", + "0.025": "/work_fast/ga36qid/precice/meshes/turbine/UnitSize/0.025.vtk", + "0.001": "/work_fast/ga36qid/precice/meshes/turbine/UnitSize/0.001.vtk" + } + } + }, + "groups": [ + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "np": { + "kind": "nearest-projection" + }, + "nn": { + "kind": "nearest-neighbor" + } + } + }, + "meshes": { + "A": [ + "1", + "0.75", + "0.5", + "0.25", + "0.1", + "0.075", + "0.05", + "0.025", + "0.01", + "0.0075", + "0.005", + "0.0025", + "0.001", + "0.00075", + "0.0005" + ], + "B": [ + "0.5", + "0.025", + "0.001" + ] + } + }, + + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"1.5174271293851465\" polynomial=\"on\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"0.9104562776310878\" polynomial=\"on\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"0.4552281388155439\" polynomial=\"on\"" + }, + "gaussian-n15-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"0.30348542587702926\" polynomial=\"on\"" + }, + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"1.5174271293851465\" polynomial=\"separate\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"0.9104562776310878\" polynomial=\"separate\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"0.4552281388155439\" polynomial=\"separate\"" + }, + "gaussian-n15-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"0.30348542587702926\" polynomial=\"separate\"" + } + } + }, + "meshes": { + "A": [ + "1" + ], + "B": [ + "0.5", + "0.025", + "0.001" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"2.0232361725135286\" polynomial=\"on\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"1.213941703508117\" polynomial=\"on\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"0.6069708517540585\" polynomial=\"on\"" + }, + "gaussian-n15-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"0.4046472345027057\" polynomial=\"on\"" + }, + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"2.0232361725135286\" polynomial=\"separate\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"1.213941703508117\" polynomial=\"separate\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"0.6069708517540585\" polynomial=\"separate\"" + }, + "gaussian-n15-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"0.4046472345027057\" polynomial=\"separate\"" + } + } + }, + "meshes": { + "A": [ + "0.75" + ], + "B": [ + "0.5", + "0.025", + "0.001" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"3.034854258770293\" polynomial=\"on\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"1.8209125552621757\" polynomial=\"on\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"0.9104562776310878\" polynomial=\"on\"" + }, + "gaussian-n15-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"0.6069708517540585\" polynomial=\"on\"" + }, + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"3.034854258770293\" polynomial=\"separate\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"1.8209125552621757\" polynomial=\"separate\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"0.9104562776310878\" polynomial=\"separate\"" + }, + "gaussian-n15-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"0.6069708517540585\" polynomial=\"separate\"" + } + } + }, + "meshes": { + "A": [ + "0.5" + ], + "B": [ + "0.5", + "0.025", + "0.001" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"6.069708517540586\" polynomial=\"on\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"3.6418251105243513\" polynomial=\"on\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"1.8209125552621757\" polynomial=\"on\"" + }, + "gaussian-n15-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"1.213941703508117\" polynomial=\"on\"" + }, + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"6.069708517540586\" polynomial=\"separate\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"3.6418251105243513\" polynomial=\"separate\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"1.8209125552621757\" polynomial=\"separate\"" + }, + "gaussian-n15-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"1.213941703508117\" polynomial=\"separate\"" + } + } + }, + "meshes": { + "A": [ + "0.25" + ], + "B": [ + "0.5", + "0.025", + "0.001" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"15.174271293851461\" polynomial=\"on\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"9.104562776310878\" polynomial=\"on\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"4.552281388155439\" polynomial=\"on\"" + }, + "gaussian-n15-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"3.034854258770293\" polynomial=\"on\"" + }, + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"15.174271293851461\" polynomial=\"separate\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"9.104562776310878\" polynomial=\"separate\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"4.552281388155439\" polynomial=\"separate\"" + }, + "gaussian-n15-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"3.034854258770293\" polynomial=\"separate\"" + } + } + }, + "meshes": { + "A": [ + "0.1" + ], + "B": [ + "0.5", + "0.025", + "0.001" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"20.232361725135288\" polynomial=\"on\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"12.139417035081172\" polynomial=\"on\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"6.069708517540586\" polynomial=\"on\"" + }, + "gaussian-n15-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"4.046472345027057\" polynomial=\"on\"" + }, + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"20.232361725135288\" polynomial=\"separate\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"12.139417035081172\" polynomial=\"separate\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"6.069708517540586\" polynomial=\"separate\"" + }, + "gaussian-n15-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"4.046472345027057\" polynomial=\"separate\"" + } + } + }, + "meshes": { + "A": [ + "0.075" + ], + "B": [ + "0.5", + "0.025", + "0.001" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"30.348542587702923\" polynomial=\"on\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"18.209125552621757\" polynomial=\"on\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"9.104562776310878\" polynomial=\"on\"" + }, + "gaussian-n15-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"6.069708517540586\" polynomial=\"on\"" + }, + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"30.348542587702923\" polynomial=\"separate\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"18.209125552621757\" polynomial=\"separate\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"9.104562776310878\" polynomial=\"separate\"" + }, + "gaussian-n15-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"6.069708517540586\" polynomial=\"separate\"" + } + } + }, + "meshes": { + "A": [ + "0.05" + ], + "B": [ + "0.5", + "0.025", + "0.001" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"60.697085175405846\" polynomial=\"on\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"36.41825110524351\" polynomial=\"on\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"18.209125552621757\" polynomial=\"on\"" + }, + "gaussian-n15-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"12.139417035081172\" polynomial=\"on\"" + }, + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"60.697085175405846\" polynomial=\"separate\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"36.41825110524351\" polynomial=\"separate\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"18.209125552621757\" polynomial=\"separate\"" + }, + "gaussian-n15-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"12.139417035081172\" polynomial=\"separate\"" + } + } + }, + "meshes": { + "A": [ + "0.025" + ], + "B": [ + "0.5", + "0.025", + "0.001" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"151.74271293851464\" polynomial=\"on\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"91.04562776310878\" polynomial=\"on\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"45.52281388155439\" polynomial=\"on\"" + }, + "gaussian-n15-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"30.34854258770293\" polynomial=\"on\"" + }, + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"151.74271293851464\" polynomial=\"separate\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"91.04562776310878\" polynomial=\"separate\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"45.52281388155439\" polynomial=\"separate\"" + }, + "gaussian-n15-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"30.34854258770293\" polynomial=\"separate\"" + } + } + }, + "meshes": { + "A": [ + "0.01" + ], + "B": [ + "0.5", + "0.025", + "0.001" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"202.32361725135286\" polynomial=\"on\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"121.39417035081172\" polynomial=\"on\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"60.69708517540586\" polynomial=\"on\"" + }, + "gaussian-n15-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"40.464723450270576\" polynomial=\"on\"" + }, + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"202.32361725135286\" polynomial=\"separate\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"121.39417035081172\" polynomial=\"separate\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"60.69708517540586\" polynomial=\"separate\"" + }, + "gaussian-n15-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"40.464723450270576\" polynomial=\"separate\"" + } + } + }, + "meshes": { + "A": [ + "0.0075" + ], + "B": [ + "0.5", + "0.025", + "0.001" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"303.4854258770293\" polynomial=\"on\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"182.09125552621757\" polynomial=\"on\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"91.04562776310878\" polynomial=\"on\"" + }, + "gaussian-n15-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"60.69708517540586\" polynomial=\"on\"" + }, + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"303.4854258770293\" polynomial=\"separate\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"182.09125552621757\" polynomial=\"separate\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"91.04562776310878\" polynomial=\"separate\"" + }, + "gaussian-n15-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"60.69708517540586\" polynomial=\"separate\"" + } + } + }, + "meshes": { + "A": [ + "0.005" + ], + "B": [ + "0.5", + "0.025", + "0.001" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"606.9708517540586\" polynomial=\"on\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"364.18251105243513\" polynomial=\"on\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"182.09125552621757\" polynomial=\"on\"" + }, + "gaussian-n15-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"121.39417035081172\" polynomial=\"on\"" + }, + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"606.9708517540586\" polynomial=\"separate\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"364.18251105243513\" polynomial=\"separate\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"182.09125552621757\" polynomial=\"separate\"" + }, + "gaussian-n15-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"121.39417035081172\" polynomial=\"separate\"" + } + } + }, + "meshes": { + "A": [ + "0.0025" + ], + "B": [ + "0.5", + "0.025", + "0.001" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"1517.4271293851464\" polynomial=\"on\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"910.4562776310878\" polynomial=\"on\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"455.2281388155439\" polynomial=\"on\"" + }, + "gaussian-n15-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"303.4854258770293\" polynomial=\"on\"" + }, + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"1517.4271293851464\" polynomial=\"separate\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"910.4562776310878\" polynomial=\"separate\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"455.2281388155439\" polynomial=\"separate\"" + }, + "gaussian-n15-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"303.4854258770293\" polynomial=\"separate\"" + } + } + }, + "meshes": { + "A": [ + "0.001" + ], + "B": [ + "0.5", + "0.025", + "0.001" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"2023.2361725135283\" polynomial=\"on\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"1213.9417035081171\" polynomial=\"on\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"606.9708517540586\" polynomial=\"on\"" + }, + "gaussian-n15-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"404.6472345027057\" polynomial=\"on\"" + }, + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"2023.2361725135283\" polynomial=\"separate\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"1213.9417035081171\" polynomial=\"separate\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"606.9708517540586\" polynomial=\"separate\"" + }, + "gaussian-n15-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"404.6472345027057\" polynomial=\"separate\"" + } + } + }, + "meshes": { + "A": [ + "0.00075" + ], + "B": [ + "0.5", + "0.025", + "0.001" + ] + } + }, + { + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "gaussian-n3-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"3034.8542587702927\" polynomial=\"on\"" + }, + "gaussian-n5-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"1820.9125552621756\" polynomial=\"on\"" + }, + "gaussian-n10-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"910.4562776310878\" polynomial=\"on\"" + }, + "gaussian-n15-on": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"606.9708517540586\" polynomial=\"on\"" + }, + "gaussian-n3-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"3034.8542587702927\" polynomial=\"separate\"" + }, + "gaussian-n5-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"1820.9125552621756\" polynomial=\"separate\"" + }, + "gaussian-n10-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"910.4562776310878\" polynomial=\"separate\"" + }, + "gaussian-n15-separate": { + "kind": "rbf-gaussian", + "options": "shape-parameter=\"606.9708517540586\" polynomial=\"separate\"" + } + } + }, + "meshes": { + "A": [ + "0.0005" + ], + "B": [ + "0.5", + "0.025", + "0.001" + ] + } + }, +{ + "mapping": { + "constraints": [ + "consistent" + ], + "cases": { + "tps-poly-separate": { + "kind": "rbf-thin-plate-splines", + "options": "polynomial=\"separate\"" + }, + "tps-poly-on": { + "kind": "rbf-thin-plate-splines", + "options": "polynomial=\"on\"" + } + } + }, + "meshes": { + "A": [ + "1", + "0.75", + "0.5", + "0.25", + "0.1", + "0.075", + "0.05", + "0.025", + "0.01", + "0.0075", + "0.005", + "0.0025", + "0.001", + "0.00075", + "0.0005" + ], + "B": [ + "0.5", + "0.025" + ] + } + } + ] +} diff --git a/tools/mesh-generators/README.md b/tools/mesh-generators/README.md new file mode 100644 index 00000000..c983f95b --- /dev/null +++ b/tools/mesh-generators/README.md @@ -0,0 +1,10 @@ +# Unit square & unit cube mesh generator + +These scripts can generate mesh of a unit square/cube (with triangles or tetrahedral elements) with specified resolution. +Run with output file name and target mesh size as arguments. For instance : + +```bash +python generate_unit_cube.py --mesh coarse.vtk --resolution 0.2 +``` + +This requires the `gmsh` and `meshio` Python packages. diff --git a/tools/mesh-generators/generate_unit_cube.py b/tools/mesh-generators/generate_unit_cube.py new file mode 100644 index 00000000..bbd1882c --- /dev/null +++ b/tools/mesh-generators/generate_unit_cube.py @@ -0,0 +1,102 @@ +import argparse + +import gmsh +import meshio + + +def generate_unit_cube_vtk(out, resolution): + + gmsh.initialize() + + gmsh.model.add("t1") + + lc = resolution + gmsh.model.geo.addPoint(0, 0, 0, lc, 1) + gmsh.model.geo.addPoint(1, 0, 0, lc, 2) + gmsh.model.geo.addPoint(1, 1, 0, lc, 3) + gmsh.model.geo.addPoint(0, 1, 0, lc, 4) + gmsh.model.geo.addPoint(0, 0, 1, lc, 5) + gmsh.model.geo.addPoint(1, 0, 1, lc, 6) + gmsh.model.geo.addPoint(1, 1, 1, lc, 7) + gmsh.model.geo.addPoint(0, 1, 1, lc, 8) + + # Lower face + ab = gmsh.model.geo.addLine(1, 2) + bc = gmsh.model.geo.addLine(2, 3) + cd = gmsh.model.geo.addLine(3, 4) + da = gmsh.model.geo.addLine(4, 1) + + # Upper face + ef = gmsh.model.geo.addLine(5, 6) + fg = gmsh.model.geo.addLine(6, 7) + gh = gmsh.model.geo.addLine(7, 8) + he = gmsh.model.geo.addLine(8, 5) + + # Verticla edges, from bottom to top + ae = gmsh.model.geo.addLine(1, 5) + bf = gmsh.model.geo.addLine(2, 6) + cg = gmsh.model.geo.addLine(3, 7) + dh = gmsh.model.geo.addLine(4, 8) + + gmsh.model.geo.addCurveLoop([ab, bc, cd, da], 1) + gmsh.model.geo.addCurveLoop([ef, fg, gh, he], 2) + gmsh.model.geo.addCurveLoop([ab, bf, -ef, -ae], 3) + gmsh.model.geo.addCurveLoop([bc, cg, -fg, -bf], 4) + gmsh.model.geo.addCurveLoop([cd, dh, -gh, -cg], 5) + gmsh.model.geo.addCurveLoop([da, ae, -he, -dh], 6) + + gmsh.model.geo.addPlaneSurface([1], 1) + gmsh.model.geo.addPlaneSurface([2], 2) + gmsh.model.geo.addPlaneSurface([3], 3) + gmsh.model.geo.addPlaneSurface([4], 4) + gmsh.model.geo.addPlaneSurface([5], 5) + gmsh.model.geo.addPlaneSurface([6], 6) + surfaceLoop = gmsh.model.geo.addSurfaceLoop([1, 2, 3, 4, 5, 6]) + gmsh.model.geo.addVolume([surfaceLoop], 1) + + gmsh.model.geo.synchronize() + + # Add groups + gmsh.model.addPhysicalGroup(3, [1], name="Volume") + + gmsh.model.mesh.generate(3) + gmsh.write("tmp.msh") + + gmsh.finalize() + + # Convert + + mesh = meshio.read("tmp.msh") + mesh.write(out, binary=True) + + +def print_usage(): + print( + "Usage: generate_unit_cube.py filename.vtk/vtu mesh_resolution. Example: generate_unit_cube.py coarse.vtk 0.25" + ) + + +def parse_args(): + parser = argparse.ArgumentParser(description="__doc__") + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument( + "--mesh", + "-m", + dest="output", + help="The name of the file to create. Must be a .vtk or .vtu file.", + ) + parser.add_argument( + "--resolution", + "-r", + dest="resolution", + default="0.1", + help="Target mesh size (each element should be smaller than this)", + ) + + args, _ = parser.parse_known_args() + return args + + +if __name__ == "__main__": + args = parse_args() + generate_unit_cube_vtk(args.output, float(args.resolution)) diff --git a/tools/mesh-generators/generate_unit_square.py b/tools/mesh-generators/generate_unit_square.py new file mode 100644 index 00000000..3636aed5 --- /dev/null +++ b/tools/mesh-generators/generate_unit_square.py @@ -0,0 +1,73 @@ +import argparse + +import gmsh +import meshio + + +def generate_unit_square_vtk(out, resolution): + + gmsh.initialize() + + gmsh.model.add("t1") + + lc = resolution + gmsh.model.geo.addPoint(0, 0, 0, lc, 1) + gmsh.model.geo.addPoint(1, 0, 0, lc, 2) + gmsh.model.geo.addPoint(1, 1, 0, lc, 3) + gmsh.model.geo.addPoint(0, 1, 0, lc, 4) + + gmsh.model.geo.addLine(1, 2) + gmsh.model.geo.addLine(2, 3) + gmsh.model.geo.addLine(3, 4) + gmsh.model.geo.addLine(4, 1) + + gmsh.model.geo.addCurveLoop([1, 2, 3, 4], 1) + + surface = gmsh.model.geo.addPlaneSurface([1], 1) + + gmsh.model.geo.synchronize() + + # Add groups + gmsh.model.addPhysicalGroup(2, [surface], name="Surface") + + gmsh.model.mesh.generate(3) + gmsh.write("tmp.msh") + + gmsh.finalize() + + # Convert + + mesh = meshio.read("tmp.msh") + mesh.write(out) + + +def print_usage(): + print( + "Usage: generate_unit_cube.py filename.vtk/vtu mesh_resolution. Example: generate_unit_cube.py coarse.vtk 0.25" + ) + + +def parse_args(): + parser = argparse.ArgumentParser(description="__doc__") + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument( + "--mesh", + "-m", + dest="output", + help="The name of the file to create. Must be a .vtk or .vtu file.", + ) + parser.add_argument( + "--resolution", + "-r", + dest="resolution", + default="0.1", + help="Target mesh size (each element should be smaller than this)", + ) + + args, _ = parser.parse_known_args() + return args + + +if __name__ == "__main__": + args = parse_args() + generate_unit_square_vtk(args.output, float(args.resolution)) diff --git a/tools/mesh-generators/requirements.txt b/tools/mesh-generators/requirements.txt new file mode 100644 index 00000000..1a142c0f --- /dev/null +++ b/tools/mesh-generators/requirements.txt @@ -0,0 +1,2 @@ +gmsh>=4.10.0 +meshio>=5.3.4 diff --git a/tools/mesh-tools/makefile b/tools/mesh-tools/makefile new file mode 100644 index 00000000..e1ce9522 --- /dev/null +++ b/tools/mesh-tools/makefile @@ -0,0 +1,9 @@ +.PHONY: all + +all: mesh scale + +mesh: mesh.cpp + g++ -lgmsh mesh.cpp -o mesh + +scale: scale.cpp + g++ -lgmsh scale.cpp -o scale diff --git a/tools/mesh-tools/mesh.cpp b/tools/mesh-tools/mesh.cpp new file mode 100644 index 00000000..1650f874 --- /dev/null +++ b/tools/mesh-tools/mesh.cpp @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include +#include + +std::string formatSize(double size) +{ + std::string str = std::to_string(size); + str.erase(str.find_last_not_of('0') + 1, std::string::npos); + return str; +} + +int main(int argc, char **argv) +{ + if (argc < 3) { + std::cerr << "Usage: exe INPUT SIZE, [SIZE, ...]\n"; + return 1; + } + + const std::string input(argv[1]); + + std::vector sizes; + for (int i = 2; i < argc; ++i) { + sizes.push_back(std::atof(argv[i])); + } + + gmsh::initialize(0, nullptr); + + gmsh::vectorpair v; + try { + gmsh::model::occ::importShapes(input, v); + } catch (...) { + gmsh::logger::write("Could not load STEP file: bye!"); + gmsh::finalize(); + return 0; + } + gmsh::model::occ::synchronize(); + + gmsh::option::setNumber("Mesh.Algorithm", 5); + gmsh::option::setNumber("Mesh.SaveAll", 1); + gmsh::option::setNumber("Mesh.Binary", 1); + + for (double size : sizes) { + const auto name = formatSize(size); + std::cout << "= Generating " << name << '\n'; + gmsh::option::setNumber("Mesh.MeshSizeMin", size); + gmsh::option::setNumber("Mesh.MeshSizeMax", size); + gmsh::model::mesh::generate(2); + gmsh::model::mesh::removeDuplicateNodes(); + gmsh::write(name + ".vtk"); + gmsh::model::mesh::clear(); + } + + gmsh::finalize(); + return 0; +} diff --git a/tools/mesh-tools/scale.cpp b/tools/mesh-tools/scale.cpp new file mode 100644 index 00000000..85e53258 --- /dev/null +++ b/tools/mesh-tools/scale.cpp @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include + +struct AABB { + double xmin, ymin, zmin; + double xmax, ymax, zmax; + + static AABB fromGMSH(const std::pair &p) + { + AABB box; + gmsh::model::occ::getBoundingBox(p.first, p.second, box.xmin, box.ymin, box.zmin, box.xmax, box.ymax, box.zmax); + return box; + } + + void print() const + { + std::cout << "x " << xmin << " " << xmax << '\n'; + std::cout << "y " << ymin << " " << ymax << '\n'; + std::cout << "z " << zmin << " " << zmax << '\n'; + } +}; + +AABB operator+(const AABB &lhs, const AABB &rhs) +{ + return { + std::min(lhs.xmin, rhs.xmin), + std::min(lhs.ymin, rhs.ymin), + std::min(lhs.zmin, rhs.zmin), + std::max(lhs.xmax, rhs.xmax), + std::max(lhs.ymax, rhs.ymax), + std::max(lhs.zmax, rhs.zmax)}; +} + +AABB getBoundingBox(const gmsh::vectorpair &v) +{ + return std::accumulate(std::next(v.begin()), v.end(), AABB::fromGMSH(v.front()), [](auto last, auto next) { return last + AABB::fromGMSH(next); }); +} + +int main(int argc, char **argv) +{ + if (argc != 3) { + std::cerr << "Usage exe INPUT OUTPUT\n"; + return 1; + } + const std::string input(argv[1]); + const std::string output(argv[2]); + + gmsh::initialize(0, nullptr); + + // Load a STEP file (using `importShapes' instead of `merge' allows to + // directly retrieve the tags of the highest dimensional imported entities): + gmsh::vectorpair v; + try { + gmsh::model::occ::importShapes(input, v); + } catch (...) { + gmsh::logger::write("Could not load STEP file: bye!"); + gmsh::finalize(); + return 0; + } + + // Get the bounding box of the volume: + const auto box = getBoundingBox(v); + + std::cout << "Initial size\n"; + box.print(); + + const auto xd = box.xmax - box.xmin; + const auto yd = box.ymax - box.ymin; + const auto zd = box.zmax - box.zmin; + const auto width = std::max(std::max(xd, yd), zd); + const auto scale = 1.0 / width; + // Center around origin + gmsh::model::occ::translate(v, -box.xmin - xd / 2, -box.ymin - yd / 2, -box.zmin - zd / 2); + // Scale down to unit size + gmsh::model::occ::dilate(v, 0, 0, 0, scale, scale, scale); + const auto b2 = getBoundingBox(v); + gmsh::model::occ::translate(v, -b2.xmin, -b2.ymin, -b2.zmin); + try { + gmsh::model::occ::removeAllDuplicates(); + } catch (...) { + std::cerr << "Deduplication failed\n"; + } + gmsh::model::occ::synchronize(); + gmsh::vectorpair v2; + gmsh::model::getEntities(v2); + gmsh::write(output); + gmsh::finalize(); + return 0; +} diff --git a/tools/split-mesh-error/elasticTube/fluid_solver.cpp b/tools/split-mesh-error/elasticTube/fluid_solver.cpp new file mode 100644 index 00000000..6969f708 --- /dev/null +++ b/tools/split-mesh-error/elasticTube/fluid_solver.cpp @@ -0,0 +1,214 @@ +#include +#include +#include "precice/SolverInterface.hpp" + +using std::cout; +using std::endl; + +using namespace precice; +using namespace precice::constants; + +int main(int argc, char **argv) +{ + cout << "Starting Fluid Solver..." << endl; + + if (argc != 5) { + cout << endl; + cout << "Usage: " << argv[0] << " configurationFileName N tau kappa" << endl; + cout << endl; + cout << "N: Number of mesh elements." << endl; + cout << "tau: Dimensionless time step size." << endl; + cout << "kappa: Dimensionless structural stiffness." << endl; + return -1; + } + + std::string configFileName(argv[1]); + int nx = atoi(argv[2]); + int ny = atoi(argv[3]); + int nz = atoi(argv[4]); + double tau = 0.01; + double kappa = 100; + int N = nx * ny * nz; + + double lenX = 20 / nx; + double lenY = 20 / ny; + double lenZ = 6 / nz; + + std::cout << "N: " << N << " tau: " << tau << " kappa: " << kappa << std::endl; + + std::string solverName = "FLUID"; + + std::string outputFilePrefix = "Postproc/out_fluid"; + + cout << "Configure preCICE..." << endl; + // Create preCICE with the solver's name, the rank, and the total number of processes. + SolverInterface interface(solverName, configFileName, 0, 1); + + int i; + int w = 0; + int patchID = 0; + double *velocity, *velocity_n, *pressure, *pressure_n, *crossSectionLength, *crossSectionLength_n, *grid; + + int dimensions = interface.getDimensions(); + + velocity = new double[N]; + velocity_n = new double[N]; + pressure = new double[N]; + pressure_n = new double[N]; + crossSectionLength = new double[N]; + crossSectionLength_n = new double[N]; + grid = new double[dimensions * N]; + + // get IDs from preCICE + int meshID = interface.getMeshID("Fluid_Nodes"); + int crossSectionLengthID = interface.getDataID("CrossSectionLength", meshID); + int pressureID = interface.getDataID("Pressure", meshID); + + for (double k = 0; k < nz; k++) { + for (double j = 0; j < ny; j++) { + for (double i = 0; i < nx; i++) { + grid[w * 3] = i * lenX; + grid[w * 3 + 1] = j * lenY; + grid[w * 3 + 2] = k * lenZ; + pressure[w] = (0.1 - (k * lenZ) / 2) * ((i * lenX) + (j * lenY)); + // pressure[w] = 1; + pressure_n[w] = pressure[w]; + crossSectionLength[w] = (0.1 - (k * lenZ) / 2) * ((i * lenX) + (j * lenY)); + // crossSectionLength[w] = 1; + crossSectionLength_n[w] = crossSectionLength[w]; + std::cout << "Grid points are: X = " << grid[w * 3] << ", Y = " << grid[w * 3 + 1] << ", Z = " << grid[w * 3 + 2] << std::endl; + std::cout << "Pressure = " << pressure[w] << std::endl; + // patchIDs[w] = 1; + // dataIndices[w] = interface.setMeshVertex(meshID, vertices[w].data()); + w++; + } + } + } + + int *vertexIDs; + vertexIDs = new int[N]; + + // init data values and mesh + for (i = 0; i < N; i++) { + velocity[i] = 1.0 / (kappa * 1.0); + velocity_n[i] = 1.0 / (kappa * 1.0); + // crossSectionLength[i] = 1.0; + // crossSectionLength_n[i] = 0.0; + // pressure[i] = 0.0; + // pressure_n[i] = 0.0; + + // for (int dim = 0; dim < dimensions; dim++) + // grid[i * dimensions + dim] = i * (1 - dim); + } + + double t = 0.0; // time + double dt = 1; // solver timestep size + + // tell preCICE about your coupling interface mesh + interface.setMeshVertices(meshID, N, grid, vertexIDs); + + w = 0; + for (double k = 0; k < nz; k++) { + for (double j = 0; j < ny; j++) { + for (double i = 0; i < nx; i++) { + patchID = 0; + if (k > 0) { + patchID = 1; + cout << "PatchID = 1" << endl; + } else { + cout << "PatchID = 0" << endl; + } + interface.setMeshVertexPatch(meshID, w, patchID); + w++; + } + } + } + + cout << "Initialize preCICE..." << endl; + interface.initialize(); + + // write initial data if required + if (interface.isActionRequired(actionWriteInitialData())) { + interface.writeBlockScalarData(pressureID, N, vertexIDs, pressure); + interface.markActionFulfilled(actionWriteInitialData()); + } + + // initial data is sent or received if necessary + interface.initializeData(); + + // read data if available + if (interface.isReadDataAvailable()) { + interface.readBlockScalarData(crossSectionLengthID, N, vertexIDs, crossSectionLength); + } + + int out_counter = 0; + + while (interface.isCouplingOngoing()) { + // for an implicit coupling, you can store an iteration checkpoint here (from the first iteration of a timestep) + // this is, however, not necessary for this scenario + if (interface.isActionRequired(actionWriteIterationCheckpoint())) { + interface.markActionFulfilled(actionWriteIterationCheckpoint()); + } + + for (int i = 0; i < N; i++) { + std::cout << "patch ID = : " << interface.getMeshVertexPatch(meshID, i) << std::endl; + } + + // Modify values of pressure + if (out_counter > 1) { + for (int i = 0; i < N; i++) { + if (N > nx * ny) { + pressure[i] = -1; + } + std::cout << "pressure: " << pressure[i] << std::endl; + } + } else { + for (int i = 0; i < N; i++) { + std::cout << "pressure: " << pressure[i] << std::endl; + } + } + + // write pressure data to precice + interface.writeBlockScalarData(pressureID, N, vertexIDs, pressure); + + interface.advance(dt); + + // read crossSectionLength data from precice + interface.readBlockScalarData(crossSectionLengthID, N, vertexIDs, crossSectionLength); + for (int i = 0; i < N; i++) { + std::cout << "crossSectionLength: " << crossSectionLength[i] << std::endl; + } + for (int i = 0; i < N; i++) { + std::cout << "error: " << crossSectionLength[i] - crossSectionLength_n[i] << std::endl; + } + + // set variables back to checkpoint + // if (interface.isActionRequired(actionReadIterationCheckpoint())) { + // i.e. not yet converged, you could restore a checkpoint here (not necessary for this scenario) + // interface.markActionFulfilled(actionReadIterationCheckpoint()); + // } + // else{ + // t += dt; + // for (i = 0; i < N; i++) { + // velocity_n[i] = velocity[i]; + // pressure_n[i] = pressure[i]; + // crossSectionLength_n[i] = crossSectionLength[i]; + //} + // write_vtk(t, out_counter, outputFilePrefix.c_str(), N, grid, velocity_n, pressure, crossSectionLength, crossSectionLength_n); + out_counter++; + //} + } + + interface.finalize(); + + delete[] velocity; + delete[] velocity_n; + delete[] pressure; + delete[] pressure_n; + delete[] crossSectionLength; + delete[] crossSectionLength_n; + delete[] vertexIDs; + delete[] grid; + + return 0; +} diff --git a/tools/split-mesh-error/elasticTube/precice-config.xml b/tools/split-mesh-error/elasticTube/precice-config.xml new file mode 100644 index 00000000..9e64eafb --- /dev/null +++ b/tools/split-mesh-error/elasticTube/precice-config.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/split-mesh-error/elasticTube/structure_solver.cpp b/tools/split-mesh-error/elasticTube/structure_solver.cpp new file mode 100644 index 00000000..525f94ec --- /dev/null +++ b/tools/split-mesh-error/elasticTube/structure_solver.cpp @@ -0,0 +1,200 @@ +#include +#include +#include "precice/SolverInterface.hpp" +//#include "mpi.h" + +using std::cout; +using std::endl; + +void printData(const std::vector &data) +{ + cout << "Received data = " << data[0]; + for (size_t i = 1; i < data.size(); i++) { + cout << ", " << data[i]; + } + cout << endl; +} + +int main(int argc, char **argv) +{ + cout << "Starting Structure Solver..." << endl; + using namespace precice; + using namespace precice::constants; + + if (argc != 5) { + cout << endl; + cout << "Usage: " << argv[0] << " configurationFileName N" << endl; + cout << endl; + cout << "N: Number of mesh elements, needs to be equal for fluid and structure solver." << endl; + return -1; + } + + std::string configFileName(argv[1]); + int nx = atoi(argv[2]); + int ny = atoi(argv[3]); + int nz = atoi(argv[4]); + int N = nx * ny * nz; + int w = 0; + int patchID = 0; + + double lenX = 20 / nx; + double lenY = 20 / ny; + double lenZ = 2 / nz; + + std::cout << "N: " << N << std::endl; + + std::string solverName = "STRUCTURE"; + + SolverInterface interface(solverName, configFileName, 0, 1); + cout << "preCICE configured..." << endl; + + // init data + double *crossSectionLength, *crossSectionLength_n, *pressure, *pressure_n; + int dimensions = interface.getDimensions(); + crossSectionLength = new double[N]; // Second dimension (only one cell deep) stored right after the first dimension: see SolverInterfaceImpl::setMeshVertices + crossSectionLength_n = new double[N]; + pressure = new double[N]; + pressure_n = new double[N]; + double *grid; + grid = new double[dimensions * N]; + + for (double k = 0; k < nz; k++) { + for (double j = 0; j < ny; j++) { + for (double i = 0; i < nx; i++) { + grid[w * 3] = i * lenX; + grid[w * 3 + 1] = j * lenY; + grid[w * 3 + 2] = k * lenZ; + std::cout << "Grid points are: X = " << grid[w * 3] << ", Y = " << grid[w * 3 + 1] << ", Z = " << grid[w * 3 + 2] << std::endl; + // pressure[w] = (0.1 - (k*lenZ)/2)*((i*lenX)+(j*lenY)); + pressure[w] = 1; + pressure_n[w] = pressure[w]; + crossSectionLength[w] = (0.1 - (k * lenZ) / 2) * ((i * lenX) + (j * lenY)); + // crossSectionLength[w] = 1; + crossSectionLength_n[w] = crossSectionLength[w]; + // dataIndices[w] = interface.setMeshVertex(meshID, vertices[w].data()); + w++; + } + } + } + + double dt = 1; // solver timestep size + double precice_dt; // maximum precice timestep size + + // precice stuff + int meshID = interface.getMeshID("Structure_Nodes"); + int crossSectionLengthID = interface.getDataID("CrossSectionLength", meshID); + int pressureID = interface.getDataID("Pressure", meshID); + int *vertexIDs; + vertexIDs = new int[N]; + + int tstep_counter = 0; // number of time steps (only coupling iteration time steps) + int t = 0; // number of time steps (including subcycling time steps) + int tsub = 0; // number of current subcycling time steps + int n_subcycles = 0; // number of subcycles + // int t_steps_total = 0; // number of total timesteps, i.e., t_steps*n_subcycles + + interface.setMeshVertices(meshID, N, grid, vertexIDs); + + w = 0; + for (double k = 0; k < nz; k++) { + for (double j = 0; j < ny; j++) { + for (double i = 0; i < nx; i++) { + patchID = 0; + if (k > 0) { + patchID = 1; + cout << "PatchID = 1" << endl; + } else { + cout << "PatchID = 0" << endl; + } + interface.setMeshVertexPatch(meshID, w, patchID); + w++; + } + } + } + + cout << "Structure: init precice..." << endl; + precice_dt = interface.initialize(); + + n_subcycles = (int) (precice_dt / dt); + // t_steps_total = 100*n_subcycles; + + if (interface.isActionRequired(actionWriteInitialData())) { + interface.writeBlockScalarData(crossSectionLengthID, N, vertexIDs, crossSectionLength); + // interface.initializeData(); + interface.markActionFulfilled(actionWriteInitialData()); + } + + interface.initializeData(); + + if (interface.isReadDataAvailable()) { + interface.readBlockScalarData(pressureID, N, vertexIDs, pressure); + } + + while (interface.isCouplingOngoing()) { + // When an implicit coupling scheme is used, checkpointing is required + if (interface.isActionRequired(actionWriteIterationCheckpoint())) { + + if (tstep_counter > 0) { + cout << "Advancing in time, finished timestep: " << tstep_counter << endl; + t += n_subcycles; + tsub = 0; + } + tstep_counter++; + + // write checkpoint, save state variables (not needed here, stationary solver) + interface.markActionFulfilled(actionWriteIterationCheckpoint()); + } + + // choose smalles time step (sub-cycling if dt is smaller than precice_dt) + dt = std::min(precice_dt, dt); + + // advance in time for subcycling + tsub++; + + /*for (double k = 0; k < nz; k++){ + for (double j = 0; j < ny; j++){ + for (double i = 0; i < nx; i++){ + crossSectionLength[i] = (0.1 - (lenZ)/2)*((lenX)+(lenY)); + std::cout << "crossSectionLength: " << crossSectionLength[i] << std::endl; + } + } + } +*/ + + // send crossSectionLength data to precice + for (int i = 0; i < N; i++) { + std::cout << "crossSectionLength: " << crossSectionLength[i] << std::endl; + } + interface.writeBlockScalarData(crossSectionLengthID, N, vertexIDs, crossSectionLength); + + // advance + precice_dt = interface.advance(dt); + + // receive pressure data from precice + interface.readBlockScalarData(pressureID, N, vertexIDs, pressure); + for (int i = 0; i < N; i++) { + std::cout << "pressure: " << pressure[i] << std::endl; + } + for (int i = 0; i < N; i++) { + std::cout << "error: " << pressure[i] - pressure_n[i] << std::endl; + } + + if (interface.isActionRequired(actionReadIterationCheckpoint())) { + cout << "Iterate" << endl; + tsub = 0; + + interface.markActionFulfilled(actionReadIterationCheckpoint()); + } + } + + interface.finalize(); + + delete[] crossSectionLength; + delete[] pressure; + delete[] grid; + delete[] vertexIDs; + + cout << "Exiting StructureSolver" << endl; + + return 0; +}