[
  {
    "path": ".github/workflows/continuous_integration.yml",
    "content": "name: CI\non: [push, pull_request]\n\njobs:\n  build-linux:\n    runs-on: ubuntu-18.04\n    steps:\n    - uses: actions/checkout@v1\n    - name: install dependencies\n      run: |\n        sudo echo \"deb https://apt.llvm.org/bionic/ llvm-toolchain-bionic-11 main\" | sudo tee -a /etc/apt/sources.list\n        sudo wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -\n        sudo apt -y update\n        sudo apt-get -o Dpkg::Options::=\"--force-overwrite\" --allow-unauthenticated -y install -y g++-9 llvm-11 llvm-11-dev libllvm11 libmpfr-dev libmpfr6\n    - name: build\n      env:\n        LLVM_CONFIG: llvm-config-11\n        CC: gcc-9\n        CXX: g++-9\n      run: make -j2 build\n    - name: jit/llvm\n      run: build/sysroot/usr/local/bin/flaxc -sysroot build/sysroot -profile --ffi-escape -run -backend llvm build/tester.flx\n    - name: jit/interp\n      run: build/sysroot/usr/local/bin/flaxc -sysroot build/sysroot -profile --ffi-escape -run -backend interp build/tester.flx\n    - name: compile/llvm\n      run: build/sysroot/usr/local/bin/flaxc -sysroot build/sysroot -profile --ffi-escape build/tester.flx && ./tester\n\n  build-macos:\n    runs-on: macOS-10.15\n    steps:\n    - uses: actions/checkout@v1\n    - name: install dependencies\n      run: |\n        brew install mpfr llvm pkg-config\n    - name: build\n      env:\n        LLVM_CONFIG: /usr/local/opt/llvm/bin/llvm-config\n      run: PATH=\"$PATH:$(pwd)/llvm/11.0.0/bin\" make -j2 build\n    - name: jit/llvm\n      run: build/sysroot/usr/local/bin/flaxc -sysroot build/sysroot -profile --ffi-escape -run -backend llvm build/tester.flx\n    - name: jit/interp\n      run: build/sysroot/usr/local/bin/flaxc -sysroot build/sysroot -profile --ffi-escape -run -backend interp build/tester.flx\n    - name: compile/llvm\n      run: build/sysroot/usr/local/bin/flaxc -sysroot build/sysroot -profile --ffi-escape build/tester.flx && ./tester\n\n  build-windows:\n    runs-on: windows-2019\n    env:\n      MPIR_ROOT_DIR:   C:/tmp/lib/mpir\n      MPFR_ROOT_DIR:   C:/tmp/lib/mpfr\n      LLVM_ROOT_DIR:   C:/tmp/lib/llvm\n      LIBFFI_ROOT_DIR: C:/tmp/lib/libffi\n      ACTIONS_ALLOW_UNSECURE_COMMANDS: true\n    steps:\n      - uses: seanmiddleditch/gha-setup-ninja@v1\n      - uses: seanmiddleditch/gha-setup-vsdevenv@master\n      - uses: actions/checkout@v1\n      - name: cache libraries\n        uses: actions/cache@v1.0.0\n        id: cache-libs\n        with:\n          path: C:/tmp/lib\n          key: cached-libs\n      - name: download libraries\n        if: steps.cache-libs.outputs.cache-hit != 'true'\n        run: |\n          echo \"root dirs:\" $LLVM_ROOT_DIR\n          echo \"extraction: C:\\tmp\\lib\"\n          Invoke-WebRequest 'https://github.com/flax-lang/flax/releases/download/win-build-deps/libraries.zip' -OutFile 'libs.zip'\n          7z x -y -o\"C:\\tmp\\lib\" libs.zip\n      - name: install meson\n        run: pip install meson\n      - name: build\n        run: |\n          meson --buildtype=release build/meson-rel\n          ninja -C build/meson-rel\n      - name: copy stdlib\n        run: |\n          New-Item -Force -Path build\\sysroot\\usr\\local\\lib\\flaxlibs -ItemType Directory\n          Copy-Item -Recurse -Force libs\\* build\\sysroot\\usr\\local\\lib\\flaxlibs\\\n      - name: jit/llvm\n        run: build\\meson-rel\\flaxc.exe -sysroot build\\sysroot -run -backend llvm --ffi-escape build\\tester.flx\n      - name: jit/interp\n        run: build\\meson-rel\\flaxc.exe -sysroot build\\sysroot -run -backend interp --ffi-escape build\\tester.flx\n      - name: compile/llvm\n        run: |\n          build\\meson-rel\\flaxc.exe -sysroot build\\sysroot --ffi-escape build\\tester.flx\n          .\\tester.exe\n\n\n\n\n\n\n"
  },
  {
    "path": ".gitignore",
    "content": "# Compiled Object files\n*.slo\n*.lo\n*.o\n*.obj\n\n# Precompiled Headers\n*.gch*\n*.pch*\n\n# Makefile dependencies\n*.cpp.d\n*.c.d\n*.h.d\n\n# Compiled Dynamic libraries\n*.so\n*.dylib\n*.dll\n\n# Fortran module files\n*.mod\n\n# Compiled Static libraries\n*.lai\n*.la\n*.a\n*.lib\n\n# Executables\n*.exe\n*.out\n*.app\n*.pdb\n\n# profile data\n*.profdata\n*.profraw\n\n\n# overrides:\ncommit\nrun\n*.sublime-*\nbuild/sysroot\nbuild/meson-*\n.modifydates\n\nbuild/test\nbuild/gltest\nbuild/standalone\n*.ll\n*.bc\n\nbuild/plots.txt\nbuild/massive.flx\n\n*.ir\nshakefile.hi\nshakefile\n.shake.database\nchecker-276\ncountloc\n\n.shake.lock\nbug-repro\n.clang_complete\n*.code-workspace\n\n.vscode\n*.vcxproj.filters\n*.vcxproj.user\n\ncountloc.bat\nbuilddir\n\nprof.svg\nprof_with_square.svg\nbuild/cmake-output\n.idea\n# CMakeLists.txt\n\n.flax-repl-history\n\ndocs/.antlr\n\ncodealike.json\n\nbuild/test\nbuild/tester\nbuild/supertiny\nbuild/gltest\n\nrelease.fish\nmacosx.zip\nflax.config\nflax.creator\nflax.creator.user\nflax.files\nflax.includes\n.vs/\nbuild/__pycache__\n*.vspx\n\n.cache\ncompile_flags.txt\n"
  },
  {
    "path": ".semaphore/semaphore.yml",
    "content": "version: v1.0\r\nname: flax\r\nagent:\r\n  machine:\r\n    type: e1-standard-2\r\n    os_image: ubuntu1804\r\nblocks:\r\n  - name: \"linux-build\"\r\n    task:\r\n      agent:\r\n        machine:\r\n          type: e1-standard-2\r\n          os_image: ubuntu1804\r\n      jobs:\r\n      - name: build\r\n        commands:\r\n          - checkout\r\n          - sudo echo \"deb https://apt.llvm.org/bionic/ llvm-toolchain-bionic-11 main\" | sudo tee -a /etc/apt/sources.list\r\n          - sudo wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -\r\n          - sudo apt -y update\r\n          - sudo apt-get -o Dpkg::Options::=\"--force-overwrite\" --allow-unauthenticated -y install -y llvm-11 llvm-11-dev libllvm11 libmpfr-dev libmpfr6\r\n          - CXX=g++-8 CC=gcc-8 LLVM_CONFIG=llvm-config-11 make -j2 build\r\n          - build/sysroot/usr/local/bin/flaxc -sysroot build/sysroot -profile --ffi-escape -run -backend llvm build/tester.flx\r\n          - build/sysroot/usr/local/bin/flaxc -sysroot build/sysroot -profile --ffi-escape -run -backend interp build/tester.flx\r\n          - build/sysroot/usr/local/bin/flaxc -sysroot build/sysroot -profile --ffi-escape build/tester.flx && ./tester\r\n"
  },
  {
    "path": "LICENSE",
    "content": "Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2015 zhiayang\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n\n"
  },
  {
    "path": "Makefile",
    "content": "# Makefile for Orion-X3/Orion-X4/mx and derivatives\n# Written in 2011\n# This makefile is licensed under the WTFPL\n\n\n\nWARNINGS\t\t:= -Wno-unused-parameter -Wno-sign-conversion -Wno-padded -Wno-conversion -Wno-shadow -Wno-missing-noreturn -Wno-unused-macros -Wno-switch-enum -Wno-deprecated -Wno-format-nonliteral -Wno-trigraphs -Wno-unused-const-variable -Wdeprecated-declarations -Werror=return-type\n\nGCCWARNINGS     := -Wno-init-list-lifetime\n\n\nCLANGWARNINGS\t:= -Wno-undefined-func-template -Wno-comma -Wno-nullability-completeness -Wno-redundant-move -Wno-nested-anon-types -Wno-gnu-anonymous-struct -Wno-reserved-id-macro -Wno-extra-semi -Wno-gnu-zero-variadic-macro-arguments -Wno-shift-sign-overflow -Wno-exit-time-destructors -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-documentation-unknown-command -Wno-weak-vtables -Wno-c++98-compat -Wold-style-cast\n\n\nSYSROOT\t\t\t:= build/sysroot\nPREFIX\t\t\t:= usr/local\nOUTPUTBIN\t\t:= flaxc\n\nOUTPUT\t\t\t:= $(SYSROOT)/$(PREFIX)/bin/$(OUTPUTBIN)\n\nCC\t\t\t\t?= \"clang\"\nCXX\t\t\t\t?= \"clang++\"\nLLVM_CONFIG\t\t?= \"llvm-config\"\n\n\nCXXSRC\t\t\t:= $(shell find source external/tinyprocesslib -iname \"*.cpp\")\nCXXOBJ\t\t\t:= $(CXXSRC:.cpp=.cpp.o)\nCXXDEPS\t\t\t:= $(CXXSRC:.cpp=.cpp.d)\n\nPRECOMP_HDRS\t:= source/include/precompile.h\nPRECOMP_GCH\t\t:= $(PRECOMP_HDRS:.h=.h.gch)\n\nFLXLIBLOCATION\t:= $(SYSROOT)/$(PREFIX)/lib\nFLXSRC\t\t\t:= $(shell find libs -iname \"*.flx\")\n\n\nNUMFILES\t\t:= $$(($(words $(CXXSRC))))\n\nDEFINES         := -D__USE_MINGW_ANSI_STDIO=1\nSANITISE\t\t:=\n\nCXXFLAGS\t\t+= -std=c++17 -fvisibility=hidden -O0 -g -c -Wall -frtti -fno-omit-frame-pointer $(SANITISE) $(DEFINES)\n\nLDFLAGS\t\t\t+= $(SANITISE) -fvisibility=hidden\n\n\n\nUNAME_IDENT\t\t:= $(shell uname)\nCOMPILER_IDENT\t:= $(shell $(CC) --version | head -n 1)\n\n\nifeq (\"$(UNAME_IDENT)\",\"Darwin\")\n\tLIBFFI_CFLAGS  := $(shell env PKG_CONFIG_PATH=/usr/local/opt/libffi/lib/pkgconfig pkg-config --cflags libffi)\n\tLIBFFI_LDFLAGS := $(shell env PKG_CONFIG_PATH=/usr/local/opt/libffi/lib/pkgconfig pkg-config --libs libffi)\nelse\n\tLIBFFI_CFLAGS  := $(shell pkg-config --cflags libffi)\n\tLIBFFI_LDFLAGS := $(shell pkg-config --libs libffi)\n\n\t# on linux, we need to explicitly export our functions\n\t# like __declspec(dllexport) except __attribute__((visibility(\"default\")))\n\tLDFLAGS += -Wl,--export-dynamic\nendif\n\nMPFR_CFLAGS     := $(shell pkg-config --cflags mpfr)\nMPFR_LDFLAGS    := $(shell pkg-config --libs mpfr)\n\nCXXFLAGS += $(MPFR_CFLAGS) $(LIBFFI_CFLAGS)\nLDFLAGS  += $(MPFR_LDFLAGS) $(LIBFFI_LDFLAGS)\n\nENABLE_CODE_COVERAGE ?= \"yes\"\n\nifneq (,$(findstring clang,$(COMPILER_IDENT)))\n\tCXXFLAGS += -Xclang -fcolor-diagnostics $(SANITISE) $(CLANGWARNINGS)\n\tifeq (\"$(ENABLE_CODE_COVERAGE)\",\"yes\")\n\t\tCXXFLAGS += -fprofile-instr-generate -fcoverage-mapping\n\t\tLDFLAGS  += -fprofile-instr-generate -fcoverage-mapping\n\tendif\nelse\n\tCXXFLAGS += $(GCCWARNINGS)\n\tifeq (\"$(ENABLE_CODE_COVERAGE)\",\"yes\")\n\t\tCXXFLAGS += -fprofile-arcs -ftest-coverage\n\t\tLDFLAGS  += -lgcov\n\tendif\nendif\n\n\nUTF8REWIND_AR   := external/libutf8rewind.a\n\n\nFLXFLAGS\t\t+= -sysroot $(SYSROOT) --ffi-escape\n\nSUPERTINYBIN\t:= build/supertiny\nGLTESTBIN\t\t:= build/gltest\nTESTBIN\t\t\t:= build/tester\n\nSUPERTINYSRC\t:= build/supertiny.flx\nGLTESTSRC\t\t:= build/gltest.flx\nTESTSRC\t\t\t:= build/tester.flx\n\n\n.DEFAULT_GOAL = jit\n-include $(CXXDEPS)\n-include source/include/precompile.h.d\n\n.PHONY: copylibs jit compile clean build linux ci satest tiny\n\nsatest: build\n\t@$(OUTPUT) $(FLXFLAGS) -run build/standalone.flx\n\ntester: build\n\t@$(OUTPUT) $(FLXFLAGS) -run build/tester.flx\n\nci: test\n\njit: build\n\t@$(OUTPUT) $(FLXFLAGS) -run -o $(SUPERTINYBIN) $(SUPERTINYSRC)\n\ncompile: build\n\t@$(OUTPUT) $(FLXFLAGS) -o $(SUPERTINYBIN) $(SUPERTINYSRC) -lm\n\ntest: build\n\t@$(OUTPUT) $(FLXFLAGS) -run -o $(TESTBIN) $(TESTSRC)\n\nrepl: build\n\t@$(OUTPUT) $(FLXFLAGS) -repl\n\ngltest: build\n\t@$(OUTPUT) $(FLXFLAGS) -run -framework GLUT -framework OpenGL -lsdl2 -o $(GLTESTBIN) $(GLTESTSRC)\n\nbuild1:\n\nbuild: build1 $(OUTPUT) copylibs\n\t# built\n\nbuild/%.flx: build\n\t@$(OUTPUT) $(FLXFLAGS) -run -profile $@\n\n\n\ncopylibs: $(FLXSRC)\n\t@mkdir -p $(FLXLIBLOCATION)/flaxlibs\n\t@cp -R libs $(FLXLIBLOCATION)/\n\t@rm -r $(FLXLIBLOCATION)/flaxlibs\n\t@mv $(FLXLIBLOCATION)/libs $(FLXLIBLOCATION)/flaxlibs\n\n\n$(OUTPUT): $(PRECOMP_GCH) $(CXXOBJ) $(COBJ) $(UTF8REWIND_AR)\n\t@printf \"# linking\\n\"\n\t@mkdir -p $(dir $(OUTPUT))\n\t@$(CXX) -o $@ $(CXXOBJ) $(COBJ) $(LDFLAGS) -Lexternal -L$(shell $(LLVM_CONFIG) --prefix)/lib $(shell $(LLVM_CONFIG) --system-libs --libs core engine native linker bitwriter lto vectorize all-targets object orcjit) -lmpfr -lgmp -lpthread -ldl -lffi -lutf8rewind\n\n\n%.cpp.o: %.cpp\n\t@$(eval DONEFILES += \"CPP\")\n\t@printf \"# compiling [$(words $(DONEFILES))/$(NUMFILES)] $<\\n\"\n\t@$(CXX) $(CXXFLAGS) $(WARNINGS) -include source/include/precompile.h -Isource/include -Iexternal -I$(shell $(LLVM_CONFIG) --includedir) -MMD -MP -o $@ $<\n\n%.h.gch: %.h\n\t@printf \"# precompiling header $<\\n\"\n\t@$(CXX) $(CXXFLAGS) $(WARNINGS) -o $@ $< -MMD -MP\n\n\n$(UTF8REWIND_AR):\n\t@$(MAKE) -C external/utf8rewind all\n\n# haha\nclena: clean\nclean:\n\t@rm -f $(OUTPUT)\n\t@find source -name \"*.o\" | xargs rm -f\n\t@find source -name \"*.gch*\" | xargs rm -f\n\t@find source -name \"*.pch*\" | xargs rm -f\n\n\t@find source -name \"*.c.m\" | xargs rm -f\n\t@find source -name \"*.c.d\" | xargs rm -f\n\t@find source -name \"*.cpp.m\" | xargs rm -f\n\t@find source -name \"*.cpp.d\" | xargs rm -f\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "README.md",
    "content": "# [Flax](https://flax-lang.github.io)\n\nA low level, general-purpose language with high level syntax and expressibility.\n\n\n[![forthebadge](https://forthebadge.com/images/badges/made-with-crayons.svg)](http://forthebadge.com)\n[![forthebadge](https://forthebadge.com/images/badges/built-with-resentment.svg)](http://forthebadge.com)\n\n[![build status](https://ci.appveyor.com/api/projects/status/c9cmm08t27ef1hji/branch/master?svg=true)](https://ci.appveyor.com/project/zhiayang/flax/branch/master)\n&nbsp;&nbsp;&nbsp;&nbsp;\n[![build status](https://github.com/flax-lang/flax/workflows/CI/badge.svg)](https://github.com/flax-lang/flax/actions)\n&nbsp;&nbsp;&nbsp;&nbsp;\n[![Build Status](https://semaphoreci.com/api/v1/zhiayang/flax/branches/master/badge.svg)](https://semaphoreci.com/zhiayang/flax)\n\n\n-----------------------------------------------\n\n#### Disclaimer ####\n\nI work on Flax in my spare time, and as the lone developer I cannot guarantee continuous development.\nI'm no famous artist but this is my magnum opus, so it'll not be abandoned anytime soon.\n\n### Language Goals\n\n- No header files.\n- Minimal runtime\n- Minimal stupidity\n- Clean, expressive syntax\n\n\n-----------------------------------------------\n\n\n### Current Features\n\n- Structs, unions, enums\n- Arrays (fixed and dynamic), slices\n- Pointer manipulation/arithmetic\n- Operator overloading\n- Generic functions and types\n- Type inference (including for generics)\n- Full compile-time execution (of arbitrary code)\n- Classes, including virtual dispatch and (single) inheritance\n\n-----------------------------------------------\n\n\n### Language Syntax\n\n- We don't have a proper place that documents everything yet, but most of the basic stuff is probably not gonna change much.\n  The testing code in `build/tests/` (most of them, anyway — check `tester.flx` to see which ones we call) tests basically 90% of the\n  language, so that's the syntax reference for now.\n- Yes, the syntax is not \"officially\" defined by a grammar. The reference parser implementation is the One True Definition, for now.\n\n-----------------------------------------------\n\n\n\n### Code Sample\n\n```rust\nimport std::io as _\n\n@entry fn main()\n{\n\tprintln(\"hello, world!\")\n}\n\n```\n\n```rust\ndo {\n\tfn prints<T, U>(m: T, a: [U: ...])\n\t{\n\t\tfor x in a => printf(\" %.2d\", m * x)\n\t}\n\n\tprintf(\"set 6:\")\n\tlet xs = [ 1, 2, 3, 4, 5 ]\n\tprints(3, ...xs)\n\n\tprintf(\"\\n\")\n}\n\ndo {\n\tunion option<T>\n\t{\n\t\tsome: T\n\t\tnone\n\t}\n\n\tlet x = option::some(\"foobar\")\n\tlet y = option::some(456)\n\n\tprintln(\"x = %, y = %\", x as some, y as some)\n}\n```\n\n-----------------------------------------------\n\n\n### Building the Flax compiler\n\n#### Dependencies ####\n- LLVM 11, mostly due to their obsession with changing the IR interface every damn version\n- GMP/MPIR\n- MPFR\n- libffi\n\n\n#### macOS / Linux\n\n- The `makefile` is the preferred way to build on UNIX systems.\n- LLVM needs to be installed. On macOS, `brew install llvm` should work, and you might need to do some PPA fiddling for Debian-based distros.\n- A C++17-compatible compiler should be used.\n- Find the `flaxc` executable in `build/sysroot/usr/local/bin`.\n- Additionally, the (admittedly limited) standard library will be copied from `./libs` to `./build/sysroot/usr/local/lib/flaxlibs/`.\n\n\n#### Windows\n\n- Install [meson](https://mesonbuild.com/).\n- Run `env MPIR_ROOT_DIR=... LLVM_ROOT_DIR=... meson meson-build-dir` to set the locations for the dependencies (see `meson.build` for the names, there are 4) and configure the build.\n- Optionally, pass `--buildtype=release` to build a release-mode compiler (highly recommended).\n- Run `ninja -C meson-build-dir`.\n- `flaxc.exe` will be found in the build directory.\n\n##### Libraries\n- Download the [prebuilt binaries](https://github.com/flax-lang/flax/releases/tag/win-build-deps) for the 4 dependencies, and place them somewhere.\n- Note: the folder structure of the libraries should be `(llvm|mpir|mpfr|libffi)/(Release|Debug)/(include|lib)/...`.\n\n\n-----------------------------------------------\n\n\n### Building Flax Programs\n\nSince nobody in their right mind is *actually* using this, please pass `-sysroot build/sysroot` to invocations of the compiler -- else the compiler will default to looking somewhere in `/usr/local/lib` for libraries. Speaking of which, standard libraries are looked for in `<sysroot>/<prefix>/lib/flaxlibs/`. Prefix is set to `/usr/local/` by default.\n\nSince version 0.41.2, executables can be generated on all 3 of our supported platforms! For Linux and macOS, all that is required is a working C compiler in the `$PATH`; we call `cc` to link object files.\n\nFor Windows, even if you are not building the compiler from source (eg. you are using a released binary), Visual Studio 2017 or newer must still be installed, with the \"Desktop development with C++\", \"MSVC v142 (or whatever)\", and \"Windows 10 SDK\" components. However, we currently find the toolchain through [established means](https://gist.github.com/machinamentum/a2b587a68a49094257da0c39a6c4405f), so that `link.exe` does not have to be in the `%PATH%`, ie. you do not have to call `vcvarsall.bat` before running the compiler.\n\n-----------------------------------------------\n\n### Contributors\n\nSpecial thanks to the Unofficial Official Language Consultants:\n[darkf](https://github.com/darkf), [adrian17](https://github.com/adrian17),\n[sim642](https://github.com/sim642), and [ryu0](https://github.com/ryu0).\n\n\n\n\n### Contributing\n\nFeel free to open an issue if you feel that there's any missing feature, or if you found a bug in the compiler. Pull requests are also\nwelcome.\n\n\n\n### Licensing\n\nThe Flax compiler itself (this repository) is licensed under the Apache 2.0 license (see `LICENSE` file). For ease of building, some dependencies\nare included in the repository itself (under the `external` folder) and compiled together, instead of as a separate library (shared or otherwise).\nThese are:\n\n1. [mpreal](https://bitbucket.org/advanpix/mpreal), GPL\n2. [utf8rewind](https://bitbucket.org/knight666/utf8rewind), MIT\n3. [tinyprocesslib](https://gitlab.com/eidheim/tiny-process-library), MIT\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "appveyor.yml",
    "content": "image: Visual Studio 2019\nclone_depth: 50\nclone_folder: c:\\projects\\flax\n\nenvironment:\n  global:\n    MPIR_ROOT_DIR:    c:\\projects\\lib\\mpir\n    MPFR_ROOT_DIR:    c:\\projects\\lib\\mpfr\n    LLVM_ROOT_DIR:    c:\\projects\\lib\\llvm\n    LIBFFI_ROOT_DIR:  c:\\projects\\lib\\libffi\n\n\ncache:\n  - c:\\projects\\lib -> appveyor.yml\n\n\ninstall:\n  # Set up the build environment\n  - cmd: call \"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvarsall.bat\" x64\n  # download our deps.\n  - ps: \"[Net.ServicePointManager]::SecurityProtocol = 'Ssl3, Tls, Tls11, Tls12'\"\n  - ps: >-\n      If (!(Test-Path c:\\projects\\lib -PathType Container)) {\n        Invoke-WebRequest 'https://github.com/flax-lang/flax/releases/download/win-build-deps/libraries.zip' -OutFile 'c:\\projects\\libs.zip'\n        7z x -y -oc:\\projects\\lib c:\\projects\\libs.zip\n      }\n  # Download ninja\n  - cmd: mkdir C:\\ninja-build\n  - ps: (new-object net.webclient).DownloadFile('https://github.com/mesonbuild/cidata/raw/master/ninja.exe', 'C:\\ninja-build\\ninja.exe')\n  - cmd: set PYTHON_ROOT=C:\\python37-x64\n  # Add neccessary paths to PATH variable\n  - cmd: set PATH=%cd%;C:\\ninja-build;%PYTHON_ROOT%;%PYTHON_ROOT%\\Scripts;%PATH%\n  # Install meson\n  - cmd: pip install meson\n\n\nbuild_script:\n  - ps: meson --buildtype=release build/meson-rel\n  - ps: ninja -C build/meson-rel\n\ntest_script:\n  - ps: cd c:\\projects\\flax\n  - ps: New-Item -Force -Path build\\sysroot\\usr\\local\\lib\\flaxlibs -ItemType Directory\n  - ps: Copy-Item -Recurse -Force libs\\* build\\sysroot\\usr\\local\\lib\\flaxlibs\\\n  - ps: build\\meson-rel\\flaxc.exe -sysroot build\\sysroot --ffi-escape -run -backend llvm build\\tester.flx\n  - ps: build\\meson-rel\\flaxc.exe -sysroot build\\sysroot --ffi-escape -run -backend interp build\\tester.flx\n  - ps: build\\meson-rel\\flaxc.exe -sysroot build\\sysroot --ffi-escape build\\tester.flx\n  - ps: .\\tester.exe\n\nafter_test:\n  - cmd: 7z a windows-x64.zip %APPVEYOR_BUILD_FOLDER%\\build\\meson-rel\\flaxc.exe\n  - cmd: 7z a windows-x64.zip %APPVEYOR_BUILD_FOLDER%\\build\\sysroot\\usr\\local\\lib\n  - cmd: 7z rn windows-x64.zip flaxc.exe sysroot\\usr\\local\\bin\\flaxc.exe\n  - cmd: 7z rn windows-x64.zip lib sysroot\\usr\\local\\lib\n\nartifacts:\n  - path: windows-x64.zip\n\ndeploy:\n  - provider: GitHub\n    description: ''\n    artifact: windows-x64.zip\n    auth_token:\n      secure: Sk3O32lE4SgtirIRqI2PWP2tkfCg2Iurz+eFrLN7C9s/nIUCDbxV0T5hjjZqMIw5\n    on:\n      APPVEYOR_REPO_TAG: true\n\n\n\n\n"
  },
  {
    "path": "build/a.flx",
    "content": "// a.flx\n// Copyright (c) 2020, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n// import libc as _\nexport a\nimport libc\n\nimport std::io as _\n\n// import b\n// import d\n\n@entry fn main()\n{\n\tprint(\"uwu\\n\")\n}\n"
  },
  {
    "path": "build/b.flx",
    "content": "// b.flx\n// Copyright (c) 2020, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport a\nimport libc\n\n"
  },
  {
    "path": "build/c.flx",
    "content": "// ultratiny.flx\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport ultratiny\n\n// import libc as _\nimport a\n\n@entry fn main()\n{\n\t// printf(\"q = %d\\n\", 37)\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "build/d.flx",
    "content": "// d.flx\n// Copyright (c) 2020, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport a\nimport libc\n"
  },
  {
    "path": "build/generate_test.py",
    "content": "#!/usr/bin/env python3\n\n# taken from github.com/pervognesn/bitwise/ion/generate_test.py\n\nimport sys\n\ndef gen_test(reps):\n\ttemplate = \"\"\"\n\tlet names(?) = [ \"max\", \"ollie\", \"coco\", \"piper\", \"tim\", \"bill\", \"alex\", \"ron\", \"isaac\", \"jim\" ]\n\n\tclass Animal(?)\n\t{\n\t\tinit(w: f64)\n\t\t{\n\t\t\t// printf(\"make animal w = %f\\\\n\", w)\n\t\t\tweight = w\n\t\t\tname = names(?)[rand() % names(?).length]\n\t\t}\n\n\t\tvirtual fn makeNoise()\n\t\t{\n\t\t\tprintf(\"some generic sound\\\\n\")\n\t\t}\n\n\t\tvar name: str\n\t\tvar weight: f64\n\t\tvar cute: bool = true\n\t}\n\n\tclass Dog(?) : Animal(?)\n\t{\n\t\tinit() : super(w: 300)\n\t\t{\n\t\t\t// printf(\"make dog (w = %f)\\\\n\", weight)\n\t\t}\n\n\t\toverride fn makeNoise()\n\t\t{\n\t\t\tprintf(\"bark bark (%f)\\\\n\", weight)\n\t\t}\n\n\t\tvirtual fn wag()\n\t\t{\n\t\t\tprintf(\"wagging tail of length %d\\\\n\", tail)\n\t\t}\n\n\t\tvar tail: int = 37\n\t}\n\n\tclass Dalmation(?) : Dog(?)\n\t{\n\t\tinit() : super()\n\t\t{\n\t\t\tprintf(\"make dalmation\\\\n\")\n\t\t}\n\n\t\toverride fn wag()\n\t\t{\n\t\t\tprintf(\"dalmation wags %d\\\\n\", tail)\n\t\t}\n\n\t\tvar numSpots: int\n\t}\n\n\n\tclass LinkedList(?)<T>\n\t{\n\t\tstruct Node\n\t\t{\n\t\t\tvar data: T\n\n\t\t\tvar prev: &Node\n\t\t\tvar next: &Node\n\t\t}\n\n\t\tvar head: &Node\n\t\tvar tail: &Node\n\n\t\tvar count: int\n\n\t\tinit()\n\t\t{\n\t\t}\n\n\t\tmut fn insert(thing: T)\n\t\t{\n\t\t\tvar nn = alloc mut Node (data: thing, prev: null, next: null)\n\n\t\t\tif head == null { head = nn; tail = nn }\n\t\t\telse\n\t\t\t{\n\t\t\t\tvar ot = tail as mut\n\t\t\t\ttail = nn\n\n\t\t\t\tnn.prev = ot\n\t\t\t\tot.next = nn\n\t\t\t}\n\n\t\t\tcount += 1\n\t\t}\n\n\t\tstatic fn hello() -> T { printf(\"hi\\\\n\"); return 10 }\n\t}\n\n\n\n\n\tfn stuff(?)()\n\t{\n\t\tdo {\n\t\t\t// don't question.\n\t\t\tsrand(284811)\n\n\t\t\t// fn test() -> f64 { printf(\"hi\\\\n\"); return 31.51 }\n\n\t\t\tlet dogs = alloc &Dog(?) [5] {\n\t\t\t\tif i % 2 == 1   { it = alloc Dalmation(?) }\n\t\t\t\telse            { it = alloc Dog(?) }\n\t\t\t}\n\n\t\t\tfor dog, i in dogs {\n\t\t\t\tprintf(\"%d: %s - \", i, dog.name)\n\t\t\t\tdog.wag()\n\t\t\t}\n\t\t}\n\n\n\t\tdo {\n\t\t\tvar list: LinkedList(?)!<T: int>\n\n\t\t\tlist.insert(10)\n\t\t\tlist.insert(20)\n\t\t\tlist.insert(30)\n\t\t\tlist.insert(40)\n\n\t\t\tvar head = list.head\n\t\t\twhile(head)\n\t\t\t{\n\t\t\t\tprintf(\"%d\\\\n\", head.data)\n\t\t\t\thead = head.next\n\t\t\t}\n\t\t}\n\t}\n\n\tfn genericstuff(?)()\n\t{\n\t\tdo {\n\t\t\tfn gincr<A>(x: A) -> A => x + 1\n\t\t\tfn apply<B, C>(x: B, f: fn(B) -> C) -> C => f(x)\n\n\t\t\tfn mapstupid<D, E, F>(arr: [D:], f: fn(D) -> E, fa: fn(D, fn(D) -> E) -> F) -> [F]\n\t\t\t{\n\t\t\t\tvar i = 0\n\t\t\t\tvar ret: [F]\n\t\t\t\twhile i < arr.length\n\t\t\t\t{\n\t\t\t\t\tret.append(fa(arr[i], f))\n\t\t\t\t\ti += 1\n\t\t\t\t}\n\n\t\t\t\treturn ret\n\t\t\t}\n\n\t\t\tprintf(\"set 4:\")\n\t\t\tlet new = mapstupid([ 5, 6, 7, 8, 9 ], gincr, apply)\n\t\t\tfor it in new { printf(\" %d\", it) }\n\n\t\t\tprintf(\"\\\\n\")\n\t\t}\n\n\n\t\tdo {\n\n\t\t\tfn map2<T, K, R>(arr: [(T, K):], f: fn(T, K) -> R) -> [R]\n\t\t\t{\n\t\t\t\tvar i = 0\n\t\t\t\tvar ret: [R]\n\t\t\t\twhile i < arr.length\n\t\t\t\t{\n\t\t\t\t\tret.append(f(arr[i].0, arr[i].1))\n\t\t\t\t\ti += 1\n\t\t\t\t}\n\n\t\t\t\treturn ret\n\t\t\t}\n\n\n\t\t\tfn add2<A, B>(x: A, y: B) -> A => x + y\n\n\n\t\t\tprintf(\"set 5:\")\n\t\t\tlet new = map2([ (2, 2), (4, 4), (6, 6), (8, 8), (10, 10) ], add2)\n\t\t\tfor it in new { printf(\" %d\", it) }\n\n\t\t\tprintf(\"\\\\nset (?) done\\\\n\\\\n\")\n\t\t}\n\t}\n\t\"\"\"\n\n\toutfile = open(\"build/massive.flx\", \"wt\")\n\n\toutfile.write(\"export massive\\n\")\n\toutfile.write(\"import libc as _\\n\")\n\toutfile.write(\"ffi fn srand(s: i32)\\n\")\n\toutfile.write(\"ffi fn rand() -> i32\\n\")\n\n\t# dupes = range(128 * 48)\n\tdupes = range(reps)\n\n\tfor i in dupes:\n\t\toutfile.write(template.replace(\"(?)\", str(i)) + \"\\n\")\n\n\n\toutfile.write(\"@entry fn main() -> i32 {\\n\")\n\tfor i in dupes:\n\t\toutfile.write(\"\\tstuff(?)()\\n\".replace(\"(?)\", str(i)))\n\t\toutfile.write(\"\\tgenericstuff(?)()\\n\".replace(\"(?)\", str(i)))\n\n\toutfile.write(\"\\treturn 0\\n}\\n\")\n\n\toutfile.close()\n\n\n\n\nif __name__ == '__main__':\n    globals()[sys.argv[1]](int(sys.argv[2]))\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "build/gltest.flx",
    "content": "// gltest.flx\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n// import Foundation\nimport \"OpenGL/GL.flx\"\nimport \"SDL2/SDL.flx\" as _\n\nimport libc as _\n\nffi fn rand() -> i32\n\nfn frand(a: f64, b: f64) -> f64\n{\n    let r = (rand() as f64) / 2147483647.0\n    let diff = b - a\n\n    let x = r * diff\n    return a + x\n}\n\nffi fn log(a: f64) -> f64\nffi fn sin(a: f64) -> f64\nffi fn fabs(a: f64) -> f64\nffi fn fmin(a: f64, b: f64) -> f64\nffi fn fmax(a: f64, b: f64) -> f64\nffi fn sqrt(a: f64) -> f64\n\nfn clamp(x: f64, lower: f64, upper: f64) -> f64\n{\n    return fmin(upper, fmax(x, lower))\n}\n\n\n\n\n\npublic fn main(argc: i32, argv: &&i8) -> int\n{\n\tSDL_Init(INIT_EVERYTHING)\n\tlet mw = SDL_CreateWindow(\"test\", 805240832, 805240832, 640, 480, 2)\n\n\tif mw == null\n\t{\n\t\tprintf(\"omg no\\n\")\n\t}\n\telse\n\t{\n\t\tprintf(\"window init: %p\\n\", mw)\n\t}\n\n\tlet glc = SDL_GL_CreateContext(mw)\n\n\tSDL_GL_SetAttribute(GL_MULTISAMPLEBUFFERS, 1)\n\tSDL_GL_SetAttribute(GL_MULTISAMPLESAMPLES, 2)\n\n\tGL::glClearColor(0, 0, 0, 0)\n\n\tGL::glMatrixMode(GL::GL::PROJECTION)\n\tGL::glLoadIdentity()\n\tGL::gluPerspective(45.0, (640.0 / 480.0), 0.1, 100.0)\n\n\tGL::glMatrixMode(GL::GL::MODELVIEW)\n\tGL::glLoadIdentity()\n\n\n\tGL::glEnableClientState(GL::GL::VERTEX_ARRAY)\n\tGL::glEnableClientState(GL::GL::TEXTURE_COORD_ARRAY)\n\tGL::glEnableClientState(GL::GL::COLOR_ARRAY)\n\tGL::glEnableClientState(GL::GL::NORMAL_ARRAY)\n\n\tGL::glEnable(GL::GL::MULTISAMPLE)\n\tGL::glEnable(GL::GL::DEPTH_TEST)\n\tGL::glDepthFunc(GL::GL::LESS)\n\n\tGL::glBlendColor(1.0, 1.0, 1.0, 1.0)\n\n\tvar rx: f64 = 0\n\tvar ry: f64 = 0\n\tvar rz: f64 = 0\n\n\tlet vertices = [\t0.0, -0.525731, 0.850651,\n\t\t\t\t\t\t0.850651, 0.0, 0.525731,\n\t\t\t\t\t\t0.850651, 0.0, -0.525731,\n\t\t\t\t\t\t-0.850651, 0.0, -0.525731,\n\t\t\t\t\t\t-0.850651, 0.0, 0.525731,\n\t\t\t\t\t\t-0.525731, 0.850651, 0.0,\n\t\t\t\t\t\t0.525731, 0.850651, 0.0,\n\t\t\t\t\t\t0.525731, -0.850651, 0.0,\n\t\t\t\t\t\t-0.525731, -0.850651, 0.0,\n\t\t\t\t\t\t0.0, -0.525731, -0.850651,\n\t\t\t\t\t\t0.0, 0.525731, -0.850651,\n\t\t\t\t\t\t0.0, 0.525731, 0.850651\n\t\t\t\t\t]\n\n\t// var colours: f64[36]\n\tvar colours = alloc f64[48]\n\tdefer free colours\n\n\tvar i = 0\n\twhile i < 48\n\t{\n\t\tcolours[i + 0] = frand(0.3, 0.9)\n\t\tcolours[i + 1] = frand(0.3, 0.9)\n\t\tcolours[i + 2] = frand(0.3, 0.9)\n\t\tcolours[i + 3] = 1.0\n\t\ti += 4\n\t}\n\n\tlet indices: [u8: 60] = [\n\t\t\t\t\t\t\t1,  2,  6,\n\t\t\t\t\t\t\t1,  7,  2,\n\t\t\t\t\t\t\t3,  4,  5,\n\t\t\t\t\t\t\t4,  3,  8,\n\t\t\t\t\t\t\t6,  5,  11,\n\t\t\t\t\t\t\t5,  6,  10,\n\t\t\t\t\t\t\t9,  10, 2,\n\t\t\t\t\t\t\t10, 9,  3,\n\t\t\t\t\t\t\t7,  8,  9,\n\t\t\t\t\t\t\t8,  7,  0,\n\t\t\t\t\t\t\t11, 0,  1,\n\t\t\t\t\t\t\t0,  11, 4,\n\t\t\t\t\t\t\t6,  2,  10,\n\t\t\t\t\t\t\t1,  6,  11,\n\t\t\t\t\t\t\t3,  5,  10,\n\t\t\t\t\t\t\t5,  4,  11,\n\t\t\t\t\t\t\t2,  7,  9,\n\t\t\t\t\t\t\t7,  1,  0,\n\t\t\t\t\t\t\t3,  9,  8,\n\t\t\t\t\t\t\t4,  8,  0\n\t\t\t\t\t\t]\n\n\n\tlet normals = [\n\t\t\t\t\t\t0.000000, -0.417775, 0.675974,\n\t\t\t\t\t\t0.675973, 0.000000, 0.417775,\n\t\t\t\t\t\t0.675973, -0.000000, -0.417775,\n\t\t\t\t\t\t-0.675973, 0.000000, -0.417775,\n\t\t\t\t\t\t-0.675973, -0.000000, 0.417775,\n\t\t\t\t\t\t-0.417775, 0.675974, 0.000000,\n\t\t\t\t\t\t0.417775, 0.675973, -0.000000,\n\t\t\t\t\t\t0.417775, -0.675974, 0.000000,\n\t\t\t\t\t\t-0.417775, -0.675974, 0.000000,\n\t\t\t\t\t\t0.000000, -0.417775, -0.675973,\n\t\t\t\t\t\t0.000000, 0.417775, -0.675974,\n\t\t\t\t\t\t0.000000, 0.417775, 0.675973\n\t\t\t\t\t]\n\n\n\n\n\tvar speed = 1.0\n\tvar scale = 1.0\n\n\tvar run = true\n\n\tvar srx = 0.0\n\tvar sry = 0.0\n\tvar srz = 0.0\n\n\tlet stderr = fdopen(2, \"a\")\n\twhile run\n\t{\n\t\tGL::glClear(GL::GL::COLOR_BUFFER_BIT | GL::GL::DEPTH_BUFFER_BIT)\n\t\tGL::glClearColor(0.109, 0.109, 0.109, 1.0)\n\t\tGL::glTranslated(0.0, 0.0, -5.0)\n\n\t\tGL::glRotated(rx, frand(0, 1), 0, 0)\n\t\tGL::glRotated(ry, 0, frand(0, 1), 0)\n\t\tGL::glRotated(rz, 0, 0, frand(0, 1))\n\n\n\t\tGL::glVertexPointer(3, GL::GL::DOUBLE, 0, vertices.ptr as &void)\n\t\tGL::glColorPointer(4, GL::GL::DOUBLE, 0, colours.ptr as &void)\n\t\tGL::glNormalPointer(GL::GL::DOUBLE, 0, normals.ptr as &void)\n\n\t\tGL::glDrawElements(GL::GL::TRIANGLES, 60, GL::GL::UNSIGNED_BYTE, indices as &void)\n\n\t\tGL::glLoadIdentity()\n\n\t\tSDL_GL_SwapWindow(mw)\n\n\t\tusleep((1 * 1000) as u32)\n\n\t\trx += srx * speed\n\t\try += sry * speed\n\t\trz += srz * speed\n\n\t\tvar e: Event\n\t\twhile SDL_PollEvent(&e) == 1\n\t\t{\n\t\t\tif e.type == EventType::Quit\n\t\t\t{\n\t\t\t\tprintf(\"\\nexiting\\n\")\n\t\t\t\trun = false\n\t\t\t}\n\t\t\telse if e.type == EventType::KeyUp\n\t\t\t{\n\t\t\t\tif (&e as &SDL.KeyboardEvent).keysym.sym == SDL.Key.R\n\t\t\t\t{\n\t\t\t\t\tsrx = frand(-2.5, 2.5)\n\t\t\t\t\tsry = frand(-2.5, 2.5)\n\t\t\t\t\tsrz = frand(-2.5, 2.5)\n\t\t\t\t}\n\t\t\t\telse if (&e as &SDL.KeyboardEvent).keysym.sym == SDL.Key.F\n\t\t\t\t{\n\t\t\t\t\trx = 0\n\t\t\t\t\try = 0\n\t\t\t\t\trz = 0\n\t\t\t\t\tsrx = 0\n\t\t\t\t\tsry = 0\n\t\t\t\t\tsrz = 0\n\t\t\t\t\tspeed = 1.0\n\n\t\t\t\t\tglLoadIdentity()\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if e.type == SDL.EventType.KeyDown\n\t\t\t{\n\t\t\t\tlet ke = *(&e as &SDL.KeyboardEvent)\n\n\t\t\t\tif ke.keysym.sym == SDL.Key.Space\n\t\t\t\t{\n\t\t\t\t\tsrx *= 0.9\n\t\t\t\t\tsry *= 0.9\n\t\t\t\t\tsrz *= 0.9\n\n\t\t\t\t}\n\n\t\t\t\telse if ke.keysym.sym == SDL.Key.C { scale -= 0.5 }\n\t\t\t\telse if ke.keysym.sym == SDL.Key.V { scale += 0.5 }\n\t\t\t\telse if ke.keysym.sym == SDL.Key.X { speed += scale }\n\t\t\t\telse if ke.keysym.sym == SDL.Key.Z { speed -= scale }\n\t\t\t\telse if ke.keysym.sym == SDL.Key.D { sry -= scale }\n\t\t\t\telse if ke.keysym.sym == SDL.Key.A { sry += scale }\n\t\t\t\telse if ke.keysym.sym == SDL.Key.Q { srz -= scale }\n\t\t\t\telse if ke.keysym.sym == SDL.Key.E { srz += scale }\n\t\t\t\telse if ke.keysym.sym == SDL.Key.W { srx -= scale }\n\t\t\t\telse if ke.keysym.sym == SDL.Key.S { srx += scale }\n\n\n\t\t\t\tfprintf(stderr, \"                                               \\r> %.2lf / %.2lf : %.2lf, %.2lf, %.2lf\\r\", speed,\n\t\t\t\t\tscale, srx, sry, srz)\n\t\t\t\tfflush(stderr)\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\ttodo: enums suck\n\t\t*/\n\t}\n\n\n\n\n\n\n\n\n\treturn 0\n}\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "build/old/raii_poc.flx",
    "content": "// raii_poc.flx\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport ultratiny\nimport libc as _\nimport \"tests/scopes.flx\"\n\nclass Foo\n{\n\tinit(x: int)\n\t{\n\t\tprintf(\"* create foo %d\\n\", x)\n\t\tthis.rc = alloc mut int\n\t\t*this.rc = 1\n\n\t\tthis.v = x\n\t}\n\n\tcopy(from: &self) { this.v = from.v; this.rc = from.rc; *this.rc += 1; printf(\"* copy foo %d/rc: %d\\n\", this.v, *this.rc) }\n\tmove(from: &mut self) { this.v = from.v; this.rc = from.rc; from.rc = null; printf(\"* move foo %d/rc: %d\\n\", this.v, *this.rc) }\n\n\tdeinit { if(this.rc) => *this.rc -= 1; printf(\"* delete foo %d/rc: %d\\n\", this.v, *this.rc) }\n\n\tvar rc: &mut int\n\tvar v: int\n}\n\nfn bar() -> Foo\n{\n\treturn Foo(x: 7)\n}\n\nfn con(x: Foo)\n{\n\tprintf(\"\\nconsumed %d, rc: %d\\n\\n\", x.v, *x.rc)\n}\n\n\n@entry fn main()\n{\n\tlet y = bar()\n\tprintf(\"\\ny.value = %d, rc: %d\\n\\n\", y.v, *y.rc)\n\n\tlet x = Foo(x: 13)\n\tprintf(\"\\nx.value = %d, rc: %d\\n\\n\", x.v, *x.rc)\n\n\tcon(x)\n\n\t// test_scopes::doScopeTest(\"__llvm_jit__build/test\")\n}\n\n\n\n/*\n\t! let x = alloc int { it = ... } fails!!\n\n\ttodo to cleanup semantics:\n\t1. copy and move constructors must call a base class constructor if there is not default one\n\t2. allow omitting the explicit call if the base class has a no-arg constructor (to prevent init() : super() { ... })\n\t3. check if constructing stuff in conditionals will wrongly destruct them!\n\n\ttodo for implementing destructors properly:\n\t2. only classes can contain other classes! (ANY notwithstanding)\n\t3. similar to how class constructors call the superclass constructors, we need to call base destructors also!\n\t4. virtual destructors! need to add it to the vtable!!!!!\n*/\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "build/run-test.ps1",
    "content": "# hmm\n\nParam\n(\n\t[string] $buildType,\n\t[string] $theProgram,\n\n\t[Parameter(ValueFromRemainingArguments=$true)]\n\t[string[]]$extraArgs\n)\n\nrobocopy \"libs\" \"build\\sysroot\\usr\\local\\lib\\flaxlibs\" /mir /nfl /ndl /njh /njs /nc /ns /np\n\nif($buildType -eq \"release\") {\n\t$buildDir = \"build\\meson-rel\"\n}\n\nif($buildType -eq \"debug\") {\n\t$buildDir = \"build\\meson-dbg\"\n}\n\nif($buildType -eq \"debugopt\") {\n\t$buildDir = \"build\\meson-reldbg\"\n}\n\nninja -C $buildDir\n\nif($?) {\n\t# cls\n\t& $buildDir\\flaxc.exe -Ox -sysroot build\\sysroot -run \"build\\$theProgram.flx\" --ffi-escape $extraArgs\n}\n\nif($buildType -eq \"release\") {\n\tcopy \"$buildDir\\flaxc.exe\" build\\sysroot\\usr\\local\\bin\\\n}\n"
  },
  {
    "path": "build/speed-test.py",
    "content": "#!/usr/bin/env python3\n\nimport re\nimport os\nimport subprocess\nimport generate_test\n\nimport prettytable\nfrom prettytable import PrettyTable\n\ntab = PrettyTable([ \"reps\", \"firs\", \"total\", \"lexer\", \"parser\", \"typecheck\", \"codegen\" ])\ntab.set_style(prettytable.PLAIN_COLUMNS)\ntab.align = \"l\"\n\n\ncounts = range(32, 1025, 32)\n# counts = range(32, 64, 32)\n\nplots = open(\"build/plots.txt\", \"wt\")\n\nfor i in counts:\n\tgenerate_test.gen_test(i)\n\tif os.name == \"nt\":\n\t\tflaxc_path = \"build/meson-rel/flaxc.exe\"\n\telse:\n\t\tflaxc_path = \"build/sysroot/usr/local/bin/flaxc\"\n\n\toutput = subprocess.run([ flaxc_path, \"-sysroot\", \"build/sysroot\", \"-run\", \"-backend\", \"none\", \"build/massive.flx\" ],\n\t\tcapture_output = True, text = True).stdout\n\n\t# rex = re.findall(r\"compile took (\\d+\\.\\d+) \\(lexer: (\\d+\\.\\d+), parser: (\\d+\\.\\d+), typecheck: (\\d+\\.\\d+), codegen (\\d+\\.\\d+)\\) ms(.+)\",\n\t\t# output)\n\n\trex = re.compile(r\"compile took (\\d+\\.\\d+) \\(lexer: (\\d+\\.\\d+), parser: (\\d+\\.\\d+), typecheck: (\\d+\\.\\d+), codegen: (\\d+\\.\\d+)\\) ms.*\\n(\\d+) FIR values generated\")\n\n\tm = rex.search(output)\n\n\tt_compile       = m.group(1)\n\tt_lexer         = m.group(2)\n\tt_parser        = m.group(3)\n\tt_typecheck     = m.group(4)\n\tt_codegen       = m.group(5)\n\tn_fvals         = m.group(6)\n\n\tn_lines = 0\n\twith open(\"build/massive.flx\", \"r\") as f:\n\t\tfor k, l in enumerate(f):\n\t\t\tpass\n\t\tn_lines = k + 1\n\t\tf.close()\n\n\ttab.add_row([ n_lines, n_fvals, t_compile, t_lexer, t_parser, t_typecheck, t_codegen ])\n\tprint(n_lines, n_fvals, t_compile, t_lexer, t_parser, t_typecheck, t_codegen)\n\n\nplots.write(str(tab))\nplots.close()\n\n\n\n\n"
  },
  {
    "path": "build/supertiny.flx",
    "content": "// supertiny.flx\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n\nexport supertiny\n\nimport std::io\nimport libc as _\n\n// import std::io\n// import std::map\nimport std::opt\n\n@raw union ipv4\n{\n\t_: struct {\n\t\t_: @raw union {\n\t\t\tbytes2: [u8: 4]\n\t\t\traw3: u32\n\t\t}\n\t}\n\n\t_: struct {\n\t\tbytes: [u8: 4]\n\t}\n\n\t_: struct {\n\t\traw2: u32\n\t}\n\n\traw: u32\n}\n\n\nstruct foo\n{\n\tx: int\n}\n\nlet glob = \"foozle\"[2:]\nlet glob2 = string(\"lmao\")\n\n@entry fn main()\n{\n\t// do {\n\t// \tvar addr: ipv4\n\t// \taddr.raw3 = 0xff01a8c0;\n\n\t// \tprintf(\"%d.%d.%d.%d\\n\", addr.bytes[0], addr.bytes[1], addr.bytes[2], addr.bytes[3]);\n\t// }\n\n\tdo {\n\t\tvar x: int\n\t\tvar y: int\n\n\t\t(x, y) = (30, 40)\n\t\t(x, y) = (y, x)\n\n\t\tprintf(\"%d, %d\\n\", x, y)\n\t}\n\n\tdo {\n\t\tprintf(\"%s\\n\", glob)\n\t}\n\n\t// fn foo<T>(a: T) -> T\n\t// {\n\t// \treturn a\n\t// }\n\n\t// do {\n\t// \t// let q = foo(x: 10)\n\t// \tprintf(\"hello, world!\\n\")\n\n\t// \tlet q = foo!<G: int>(10)\n\t// }\n\n\t// fn qux() -> int => 30\n\n\t// let x = std::opt::some!<int>(10)\n\t// let f = foo!<int>(3)\n\t// let q = qux!<int>()\n\n\n\n\t/* do {\n\t\tvar x: @raw union {\n\t\t\tbar: f64\n\t\t\tfoo: i64\n\t\t}\n\n\t\tx.bar = 3.14159\n\n\t\tprintf(\"x = %.2lf\\n\", x.bar)\n\t\tprintf(\"x = %d\\n\", x.foo)\n\t} */\n}\n\n\n/*\n\nimport std::opt\nimport std::map\n\n\tvar map: std::map!<int, str>\n\tmap.insert(3, \"foo\")\n\n\tlet r = map.search(3)\n\n\tlibc::printf(\"map[3] = %s\\n\", map.search(3) as std::opt::some)\n\n\tlet res = map.remove(3)\n\tlibc::printf(\"map[3]: res = %d, is_none = %d\\n\", res, map.search(3) is std::opt::none)\n\n*/\n\n/*\nclass X\n{\n\tinit(c: int)\n\t{\n\t\tthis.data = c\n\t}\n\n\tvar data: int\n}\n\nclass Y : X\n{\n\tinit(c: int) : super(c: c + 30) { }\n}\n\nclass Z : Y\n{\n\tinit(c: int) : super(c: c - 90) { }\n}\n\nclass A\n{\n\tinit() { }\n\tvirtual fn foo(a: &Y) -> &Y\n\t{\n\t\tstd::io::println(\"A::foo()\")\n\t\treturn alloc Y(c: 471)\n\t}\n}\n\nclass B : A\n{\n\tinit() : super() { }\n\n\toverride fn foo(a: &X) -> &Z\n\t{\n\t\tstd::io::println(\"B::foo()\")\n\t\treturn alloc Z(c: 748)\n\t}\n}\n*/\n\n/*\n\t! important stuff to fix !\n\t{\n\t\t2. splatting tuples into a generic function *will not work*\n\t\t3. pass the overall location to the polymorph solver.\n\n\t\t5. for optional arguments on virtual functions, we need to reach a decision --- do we ban it entirely,\n\t\t\tor follow what c++ does, which is to use the default values specified on the static type of the pointer?\n\t\t\tnote: we are definitely *not* going to handle it at runtime.\n\n\t\t6. see the error message when we pass a [T1:] to a [T2:...] without splatting; we should probably give a better\n\t\t\tdiagnostic, and eg. recommend splatting it, if the internal types match (ie. T1 == T2).\n\n\t\t\tat the very least, the current message complains about casting [T1:] to T2, which isn't really correct.\n\t}\n\n\n\tTODO for the immediate time frame (that keeps getting longer and where the real work always gets postponed)\n\n\t7. move long error messages on spans nearer to the left margin when there's only one span in the error.\n\t9. fix errors (in general?) {\n\t\ta. the generic solver should basically return only a Span, ie. a location with text.\n\t\tb. maybe find some way to 'link' two spans together with one message.\n\t\tc. figure out if/how we should split up errors when there are too many spans in one context.\n\t\t\t- do we duplicate the context?\n\t\t\t- if not then???\n\t}\n\n\t16. operator overload errors {\n\t\tsomething like this:\n\n\t\tfailed to resolve candidate for 'operator == (type_1, type_2)'\n\t\tcallsite was here: 'foo == bar'\n\t\tpotential candidates: 'operator == (type_1, type_3)'\n\n\t\tofc potential candidates should be limited to ones where at least one of the types\n\t\tare similar.\n\t}\n\n\t17. better errors for ref-counting legality {\n\t\twhen throwing an error due to having a ref-counted type in unsupported places (like in a raw-union), we\n\t\tshould let the compiler show which member made the struct refcounted (because having a RC field in a struct\n\t\tmakes that struct RC), since the 'root cause' could be nested very deep in the type hierarchy somewhere.\n\n\t\teg.\n\t\terror: reference-counted type 'foo' cannot be a member of a raw-union:\n\t\t 39 |    bar: foo\n\n\t\tnote:  'foo' inherits reference-counting from indirectly containing a field with a reference-counted type:\n\t\t 303 |   blabla: string\n\n\t\tnote:  this is the type hierarchy leading from 'foo' leading to the type in question:\n\t\t       (foo <- qux <- some_type_t <- ... <- some_struct <- string)\n\n\n\t\tof course it would be nice if we can selectively print more context and omit stuff in the middle, like this:\n\n\t\t10  |    struct some_struct {\n\t\t... |       ...\n\t\t391 |       blabla: string\n\t\t    |\n\n\t\tsomething like that. detecting indentation would be a little tricky if we want to correctly indent the\n\t\t'...' that would appear in the struct body.\n\n\t\tactually having a proper API to set up this kind of error message would be a tough one as well...\n\t}\n\n\t18. figure out how constructors should work with transparent fields {\n\n\t\tI think it's currently not worth the effort to support initialising transparent fields in constructors; there's\n\t\tway too much stuff that needs to change. some findings:\n\n\t\tto actually allow it to pass typechecking, we just need to pass the \"extended set\" of field names to\n\t\t`verifyStructConstructorArguments`, which ought to suffice. problem is, we call that from the polymorph\n\t\tengine as well, and that's something i don't really feel like touching at the moment.\n\n\t\t^ as a corollary to that, we also need a way to discover all the transparent fields that are accessible at any\n\t\tpoint. currently in typecheck/dotop, we currently do an ad-hoc kind of thing, where we search for a particular\n\t\tname that's needed. should be not-that-difficult to get a list of all accessible things, i hope.\n\n\t\t^ we might need to duplicate this to work with ast::StructDefn as well, since the polymorph engine also uses\n\t\tthe same verifyStructConstructorArguments to instantiate types a-la function calls.\n\n\t\twe also need some way to actually insert the value into the struct when it's being constructed, which might also\n\t\tget complicated.\n\n\t\tTL;DR: too complicated, not worth the time currently.\n\n\t}\n*/\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "build/tester.flx",
    "content": "// tester.flx\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport tester\n\nimport libc\nimport std::io\nimport std::limits\n\nimport \"tests/fizzbuzz.flx\"\nimport \"tests/recursiveFib.flx\"\nimport \"tests/slices.flx\"\nimport \"tests/classes.flx\"\nimport \"tests/scopes.flx\"\nimport \"tests/defertest.flx\"\nimport \"tests/anytest.flx\"\nimport \"tests/decomposition.flx\"\nimport \"tests/intlimits.flx\"\nimport \"tests/generics.flx\"\nimport \"tests/linkedlist.flx\"\nimport \"tests/forloops.flx\"\nimport \"tests/arraytest.flx\"\nimport \"tests/functions.flx\"\nimport \"tests/unions.flx\"\nimport \"tests/using.flx\"\nimport \"tests/basic.flx\"\n\nfn runTests()\n{\n\t// fib\n\tlet fibTitle        = \"       *** FIBONACII SEQUENCE ***       \\n\"\n\tlet fizzbuzzTitle   = \"            *** FIZZBUZZ ***            \\n\"\n\tlet intLimitsTitle  = \"       *** PRINTING INT LIMITS ***      \\n\"\n\tlet scopeTitle      = \"*** SCOPE RESOLUTION REGRESSION TEST ***\\n\"\n\tlet operatorTitle   = \" *** OPERATOR/TUPLE REGRESSION TEST *** \\n\"\n\tlet arrayTitle      = \"      *** ARRAY REGRESSION TEST ***     \\n\"\n\tlet genericsTitle   = \"    *** GENERICS REGRESSION TEST ***    \\n\"\n\tlet functionsTitle  = \"    *** FUNCTION REGRESSION TEST ***    \\n\"\n\tlet classTitle      = \"      *** CLASS REGRESSION TEST ***     \\n\"\n\tlet deferTitle      = \"       *** DEFER SEMANTICS TEST ***     \\n\"\n\tlet anyTitle        = \"        *** ANY SEMANTICS TEST ***      \\n\"\n\tlet slicesTitle     = \"     *** SLICES REGRESSION TEST ***     \\n\"\n\tlet decomposeTitle  = \" *** DECOMPOSITION REGRESSION TEST ***  \\n\"\n\tlet forLoopTitle    = \"    *** FOR LOOP REGRESSION TEST ***    \\n\"\n\tlet linkedListTitle = \"        *** LINKED LIST TEST ***        \\n\"\n\tlet unionsTitle     = \"           *** UNIONS TEST ***          \\n\"\n\tlet usingTitle      = \"           *** USING TEST ***           \\n\"\n\tlet miscTitle       = \"       *** MISCELLANEOUS TESTS ***      \\n\"\n\tlet basicTitle      = \"           *** BASIC TESTS ***          \\n\"\n\tlet thinLine        = \"----------------------------------------\\n\"\n\tlet endTitle        = \"============ TESTS COMPLETE ============\\n\"\n\n\n\tstd::io::print(\"%%\", fibTitle, thinLine)\n\tdo {\n\t\tvar n = 1\n\t\twhile n < 20\n\t\t{\n\t\t\tstd::io::print(\"%\", test_fib::doRecursiveFib(n))\n\t\t\tn += 1\n\n\t\t\tif n != 20\n\t\t\t{\n\t\t\t\tstd::io::print(\", \")\n\t\t\t}\n\t\t}\n\t\tstd::io::print(\"\\n\\n\\n\")\n\t}\n\n\t// fizzbuzz\n\tstd::io::print(\"%%\", fizzbuzzTitle, thinLine)\n\ttest_fizz::doFizzBuzz(15)\n\tstd::io::print(\"\\n\\n\\n\")\n\n\n\t// int limits\n\tstd::io::print(\"%%\", intLimitsTitle, thinLine)\n\ttest_limits::printIntegerLimits()\n\tstd::io::print(\"\\n\\n\\n\")\n\n\n\t// scopes\n\tstd::io::print(\"%%\", scopeTitle, thinLine)\n\ttest_scopes::doScopeTest(\"__llvm_jit__build/test\")\n\tstd::io::print(\"\\n\\n\\n\")\n\n\n\t// operators and tuples (vectors type, mainly)\n\tstd::io::print(\"%%\", operatorTitle, thinLine)\n\t// doOperatorTupleTest()\n\tstd::io::print(\"\\n\\n\\n\")\n\n\n\t// arrays\n\tstd::io::print(\"%%\", arrayTitle, thinLine)\n\ttest_arrays::doArrayTest()\n\tstd::io::print(\"\\n\\n\\n\")\n\n\n\t// generics\n\tstd::io::print(\"%%\", genericsTitle, thinLine)\n\ttest_generics::doGenericsTest()\n\tstd::io::print(\"\\n\\n\\n\")\n\n\n\t// classes\n\tstd::io::print(\"%%\", classTitle, thinLine)\n\ttest_classes::doClassTest()\n\tstd::io::print(\"\\n\\n\\n\")\n\n\n\t// first-class-functions\n\tstd::io::print(\"%%\", functionsTitle, thinLine)\n\ttest_functions::doFunctionTest()\n\tstd::io::print(\"\\n\\n\\n\")\n\n\n\t// defer semantics\n\tstd::io::print(\"%%\", deferTitle, thinLine)\n\ttest_defer::doDeferTest()\n\tstd::io::print(\"\\n\\n\\n\")\n\n\n\t// any\n\tstd::io::print(\"%%\", anyTitle, thinLine)\n\ttest_any::doAnyTest()\n\tstd::io::print(\"\\n\\n\\n\")\n\n\n\t// slices\n\tstd::io::print(\"%%\", slicesTitle, thinLine)\n\ttest_slices::doSlicesTest()\n\tstd::io::print(\"\\n\\n\\n\")\n\n\n\t// decomposition\n\tstd::io::print(\"%%\", decomposeTitle, thinLine)\n\ttest_decomposition::doDecompositionTest()\n\tstd::io::print(\"\\n\\n\\n\")\n\n\n\t// for-loops\n\tstd::io::print(\"%%\", forLoopTitle, thinLine)\n\ttest_forloops::doForLoopTest()\n\tstd::io::print(\"\\n\\n\\n\")\n\n\n\t// linked-list (generics)\n\tstd::io::print(\"%%\", linkedListTitle, thinLine)\n\ttest_linkedlist::doLinkedListTest()\n\tstd::io::print(\"\\n\\n\\n\")\n\n\n\t// unions (generics)\n\tstd::io::print(\"%%\", unionsTitle, thinLine)\n\ttest_unions::doUnionsTest()\n\tstd::io::print(\"\\n\\n\\n\")\n\n\n\t// using\n\tstd::io::print(\"%%\", usingTitle, thinLine)\n\ttest_using::doUsingTest()\n\tstd::io::print(\"\\n\\n\\n\")\n\n\n\t// misc tests\n\tstd::io::print(\"%%\", miscTitle, thinLine)\n\t// miscellaneousTests()\n\tstd::io::print(\"\\n\\n\\n\")\n\n\tstd::io::print(\"%%\", basicTitle, thinLine)\n\ttest_basic::doBasicTest()\n\tstd::io::print(\"\\n\\n\\n\")\n\n\t// fin.\n\tstd::io::print(\"%\\n\\n\\n\\n\\n\", endTitle)\n}\n\n\n\n@entry fn main() -> int\n{\n\trunTests()\n\n\n\tstd::io::print(\"\\n<< done >>\\n\")\n\treturn 0\n}\n\n\n\n\n\n\n\n"
  },
  {
    "path": "build/tests/anytest.flx",
    "content": "// anytest.flx\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport test_any\n// import \"stdio\" as _\n\nimport libc as _\n\nvar glob: any\n\nstruct Large\n{\n\ta: i64\n\tb: i64\n\tc: i64\n\td: i64\n\te: i64\n}\n\npublic fn doAnyTest()\n{\n\tfn foo(a: any)\n\t{\n\t\tif(a is Large)\n\t\t{\n\t\t\tprintf(\"a = %d\\n\", (a as Large).a)\n\t\t\tglob = a\n\t\t}\n\t\telse\n\t\t{\n\t\t\tprintf(\"not large\\n\")\n\t\t}\n\t}\n\n\tdo {\n\t\tvar k: any = any(40)\n\t\tk = \"foo\"\n\n\t\tprintf(\"k as int = %s\\n\", k as str)\n\n\t\tk = 301\n\n\t\tprintf(\"k as int = %d\\n\", k as int)\n\n\t\tprintf(\"typeid(k): %d\\n\", typeid(k))\n\t}\n\n\tdo {\n\t\tvar x: any = Large(10, 20, 30, 40, 50)\n\n\t\tvar k = x as Large\n\t\tk.c = 173\n\t\tk.a = 631\n\n\t\tfoo(x)\n\t\tfoo(k)\n\t\tfoo(401.3)\n\n\t\tfn bar() -> any => any(10)\n\n\t\tprintf(\"bar = %d, qux = %d\\n\", bar() as int, 30)\n\t\tprintf(\"a = %d, b = %d, c = %d/%x, d = %d, e = %d\\n\", k.a, k.b, k.c, (x as Large).c, k.d, k.e)\n\t}\n}\n\n\n\n\n\n\n"
  },
  {
    "path": "build/tests/arraytest.flx",
    "content": "// arraytest.flx\n// Copyright (c) 2014 - 2015, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport test_arrays\nimport libc\n\npublic fn doArrayTest()\n{\n\tdo {\n\t\tvar arr: [[int: 2]: 2] = [ [ 1, 2 ], [ 5, 6 ] ]\n\t\tarr[1][1] = 400\n\n\t\tlibc::printf(\"a[0][0]: %d, a[0][1]: %d, a[1][0]: %d, a[1][1]: %d\\n\", arr[0][0], arr[0][1], arr[1][0], arr[1][1])\n\n\t\tvar d: [f64: 4] = [ 1.0, 2.0, 4.0, 8.0 ]\n\t\tlibc::printf(\"d[0]: %f, d[1]: %f, d[2]: %f, d[3]: %f\\n\", d[0], d[1], d[2], d[3]);\n\n\n\t\tvar arr1: &mut int = @raw alloc mut int [4]\n\t\tarr1[1] = 97\n\t\tarr1[2] = 43\n\n\t\tlibc::printf(\"arr[1] = %d\\n\", (arr1 + 1)[0])\n\t\tlibc::printf(\"arr[2] = %d\\n\", (3 + arr1)[-1])\n\n\t\tfree arr1\n\n\t\tlibc::printf(\"\\n\\n\")\n\t\t// var s = alloc[4][4] string(\"array of array of strings test\")\n\t\t// s[1][2] = \"BOO YOU STRING\"\n\n\t\t// libc::printf(\"s[1][2] = %s, s[1][2].length = %ld\\n\", s[1][2], s[1][2].length)\n\n\t\t// free s\n\t}\n\n\tlibc::printf(\"\\n\")\n\tdynamicArrays()\n}\n\nfn foldl<T>(arr: [T:], x: T, f: fn(T, T) -> T) -> T\n{\n\tif arr.length == 0 => return x\n\treturn foldl(arr[1:], f(x, arr[0]), f)\n}\n\nfn foldr<T>(arr: [T:], x: T, f: fn(T, T) -> T) -> T\n{\n\tif arr.length == 0 => return x\n\treturn f(foldr(arr[:$-1], arr[0], f), x)\n}\n\nfn f(a: int, b: int) -> int\n{\n\treturn a * b\n}\n\nfn setup(max: int) -> [int]\n{\n\tvar arr: [int]\n\n\tvar i = 1\n\twhile i <= max\n\t{\n\t\tarr.append(i)\n\t\ti += 1\n\t}\n\n\treturn arr\n}\n\nfn dynamicArrays()\n{\n\tdo {\n\t\tlibc::printf(\"PRE X\\n\")\n\t\tvar x: [string]\n\t\tlibc::printf(\"POST X\\n\")\n\t\tvar y = alloc string [5]\n\n\t\tvar i = 0\n\n\t\tx.append(string(\"aaa\") + string(\"AAA\"))\n\t\tx.append(string(\"BBB\") + string(\"bbb\"))\n\t\tx.append(string(\"ccc\") + string(\"CCC\"))\n\t\tx.append(string(\"DDD\") + string(\"ddd\"))\n\t\tx.append(string(\"eee\") + string(\"EEE\"))\n\n\t\tx += y\n\n\t\tlet k = x\n\t\tvar z = k.clone()\n\n\t\tlibc::printf(\"z.length = %d\\n\", z.length)\n\n\t\tz[9] = string(\"LAST ELEMENT\")\n\n\t\tlibc::printf(\"z <= x: %d\\n\", z <= x)\n\n\t\twhile i < z.length\n\t\t{\n\t\t\tlibc::printf(\"z[%ld] = %s // %ld\\n\", i, z[i], z[i].refcount)\n\t\t\ti += 1\n\t\t}\n\n\t\tlibc::printf(\"z.back() = %s, length = %ld, cap = %ld\\n\", z[z.length - 1], z.length, z.capacity)\n\n\t\tlibc::printf(\"x == k ? %d\\n\", x == k)\n\n\t\tlet fib = setup(5)\n\n\t\tlet sum = foldl(fib, 1, f)\n\t\tlibc::printf(\"sum = %d\\n\", sum)\n\t}\n}\n\n/*\n\tMAKE:\n\t110 / 195\n\n\n\tSHAKE:\n\t107 / 191\n\n\tFMODULES:\n\t95 / 166\n\t96 / 167\n*/\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "build/tests/basic.flx",
    "content": "// basic.flx\n// Copyright (c) 2019, zhiayang, Apache License 2.0.\n\nexport test_basic\nimport libc as _\nimport std::io as _\n\n// TODO: reorganise these tests if possible\n//       eg. move them to a more appropriate file? I think some of these might fit.\npublic fn doBasicTest()\n{\n\t// put a default argument here so we can test that.\n\tfn print_array<T>(xs: [T:])\n\t{\n\t\tfor x in xs => print(\"% \", x)\n\t\tprintln()\n\t}\n\n\n\t// test logical operators\n\tdo {\n\t\tfn t() -> bool { print(\"T \"); return true }\n\t\tfn f() -> bool { print(\"F \"); return false }\n\n\t\tif t() || f() => println(\"yes\")\n\t\tif t() && f() => println(\"no\")\n\n\t\tprintf(\"\\n\\n\")\n\t}\n\n\t// test tuple assignment\n\tdo {\n\t\tvar (a, b) = (10, 20)\n\t\tprintln(\"a = %, b = %\", a, b)\n\n\t\t(b, a) = (a, b)\n\t\tprintln(\"swapped: a = %, b = %\\n\", a, b)\n\t}\n\n\t// test assignment & appending\n\tdo {\n\t\tdo {\n\t\t\tvar xs: [str] = [ \"foo\", \"bar\" ]\n\t\t\txs += \"qux\"\n\n\t\t\tvar ys: [i64] = [ 1, 2, 3, 4 ]\n\t\t\tys += 5 as i64\n\n\t\t\tprint_array(xs)\n\t\t\tprint_array(ys)\n\t\t}\n\n\t\tprintln()\n\n\t\tdo {\n\t\t\tvar xs: [str] = [ \"foo\", \"bar\" ]\n\t\t\txs += [ \"pepega\", \"kekw\" ]\n\n\t\t\tvar ys: [i64] = [ 1, 2, 3, 4 ]\n\t\t\tys += [ 5, 6, 7, 8 ]\n\n\t\t\tprint_array(xs)\n\t\t\tprint_array(ys)\n\t\t}\n\n\t\tprintln()\n\n\t\tdo {\n\t\t\tvar s = string(\"some string\")\n\t\t\ts += \"_appendage\"\n\n\t\t\tvar t = string(\"an underscore: \")\n\t\t\tt += '_'\n\n\t\t\tprintln(\"s = %\", s)\n\t\t\tprintln(\"t = %\", t)\n\t\t}\n\t}\n\n\tprintln()\n\n\t// test + on non-arithmetics\n\tdo {\n\t\tlet a = string(\"hello \") + \"world\"\n\t\tprintln(\"a = %\", a)\n\n\t\tlet b = string(\"an asterisk: \") + '*'\n\t\tprintln(\"b = %\\n\", b)\n\n\t\tlet c: [int] = [ 2, 3, 5, 7 ]\n\t\tlet d: [int] = [ 11, 13, 17, 19 ]\n\n\t\tprint_array(c + d)\n\t}\n\n\tprintln()\n\n\t// test builtin functions on aggregate data types\n\tdo {\n\t\tvar a: [int] = [ 2, 3, 5, 7 ]\n\t\tprint(\"% : \", a.pop())\n\t\tprint_array(a)\n\n\t\tvar b: [int: 3] = [ 1, 4, 9 ]\n\t\t// drop to printf for %p support\n\t\tprintf(\"b.ptr = %p, b.length = %d\\n\\n\", b.ptr, b.length)\n\n\t\tvar s = string(\"thank you ございました\")\n\t\tprintln(\"\\\"%\\\".count = % (expect 16)\\n\", s, s.count)\n\n\t\tvar r = 0...10 step 2\n\t\tfor i in r => print(\"% \", i)\n\t\tprintln(\"\\nstart: %, end: %, step: %\", r.begin, r.end, r.step)\n\n\t\tvar c: any = 30\n\t\tprintln(\"c.typeid = %, c.refcount = %\", c.id, c.refcount)\n\n\t\tenum E: u32\n\t\t{\n\t\t\tcase ONE = 100\n\t\t\tcase TWO = 200\n\t\t}\n\n\t\tvar e = E::TWO\n\t\tprintln(\"e.index = %, e.value = %, e.name = %\", e.index, e.value, e.name)\n\t}\n\n\n\tprintln()\n\n\t// other strange things\n\tdo {\n\t\tstruct Foozle\n\t\t{\n\t\t\tx: fn(int) -> int\n\n\t\t\tfn foo() -> int\n\t\t\t{\n\t\t\t\treturn x(30)\n\t\t\t}\n\t\t}\n\n\t\tfn triple(x: int) -> int => x * 3\n\n\t\tlet f = Foozle(x: triple)\n\t\tprintln(\"f = %\", f.foo())\n\n\t\tlet g = triple\n\t\tprintln(\"g(76) = %\", g(76))\n\t}\n\n\n\tprintln()\n}\n\n// well just a test.\n#run println(\"** hello, world!\")\n"
  },
  {
    "path": "build/tests/classes.flx",
    "content": "// classes.flx\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport test_classes\n\nimport libc as _\n\nffi fn srand(s: i32)\nffi fn rand() -> i32\n\nlet names = [ \"max\", \"ollie\", \"coco\", \"piper\", \"tim\", \"bill\", \"alex\", \"ron\", \"isaac\", \"jim\" ]\n\nclass Animal\n{\n\tinit(w: f64)\n\t{\n\t\t// printf(\"make animal w = %f\\n\", w)\n\t\tweight = w\n\t\tname = names[rand() % names.length]\n\t}\n\n\tvirtual fn makeNoise()\n\t{\n\t\tprintf(\"some generic sound\\n\")\n\t}\n\n\tvar name: str\n\tvar weight: f64\n\tvar cute: bool = true\n}\n\nclass Dog : Animal\n{\n\tinit() : super(w: 300)\n\t{\n\t\t// printf(\"make dog (w = %f)\\n\", weight)\n\t}\n\n\toverride fn makeNoise()\n\t{\n\t\tprintf(\"bark bark (%f)\\n\", weight)\n\t}\n\n\tvirtual fn wag()\n\t{\n\t\tprintf(\"wagging tail of length %d\\n\", tail)\n\t}\n\n\tvar tail: int = 37\n}\n\nclass Dalmation : Dog\n{\n\tinit() : super()\n\t{\n\t\tprintf(\"make dalmation\\n\")\n\t}\n\n\toverride fn wag()\n\t{\n\t\tprintf(\"dalmation wags %d\\n\", tail)\n\t}\n\n\tvar numSpots: int\n}\n\n\npublic fn doClassTest()\n{\n\tdo {\n\n\t\t// don't question.\n\t\tsrand(2848131)\n\n\t\tlet dogs = alloc &Dog [10] {\n\t\t\tif i % 3 == 1   => it = alloc Dalmation\n\t\t\telse            => it = alloc Dog\n\n\t\t\tif i % 2 == 1   => (it as mut).tail = i + 1 * 3\n\t\t}\n\n\t\tfor dog, i in dogs {\n\t\t\tprintf(\"%d: %s:   \\t\", i, dog.name)\n\t\t\tdog.wag()\n\t\t}\n\t}\n}\n\n\n"
  },
  {
    "path": "build/tests/decomposition.flx",
    "content": "// decomposition.flx\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport test_decomposition\n\nimport libc as _\n\npublic fn doDecompositionTest()\n{\n\tdo {\n\t\tprintf(\"\\n\\n>> tuple decomposition\\n\")\n\n\t\tlet tup = (10, 20, 30)\n\t\tlet (x, &y, _) = tup\n\n\t\tprintf(\"x = %d, y = %d\\n\", x, y == null)\n\n\t\tlet (a, (b, c, _, _)) = (\"a\", (30, 40, 50, 60))\n\t\tprintf(\"a = '%s', b = %d, c = %d\\n\", a, b, c)\n\t}\n\n\n\tdo {\n\t\tprintf(\"\\n>> array decomposition\\n\")\n\t\tvar arr = [ 2, 3, 5, 7, 11, 13, 17 ]\n\n\t\tvar [ a, &b, &c, ... &x ] = arr\n\t\t*(b as mut) = 30\n\n\t\tprintf(\"a = %d, b = %d, c = %d, d = %d, e = %d (x.length = %d)\\n\", a, *b, c == null, x[0], x[1], x.length)\n\n\n\t\tdo {\n\n\t\t\tvar arr2: [str]\n\t\t\tarr2.append(\"hello\")\n\t\t\tarr2.append(\"world\")\n\t\t\tarr2.append(\"bouys\")\n\n\t\t\tlet [ a, ... &b ] = arr2\n\n\t\t\t// can bind directly, if you're that kind of person...\n\t\t\tlet [ ... &c ] = arr2\n\t\t\tprintf(\"a = %s, b = %d, c = %d\\n\", a, b.length, c.length)\n\t\t}\n\n\t\tdo {\n\t\t\tprintf(\"\\n>> string decomposition\\n\")\n\t\t\tlet longstring = \"In the event of unexpected shutdown, all personnel are to evacuate the area immediately.\\n\\n\"\n\n\t\t\tlet [ a, b, c, ... &chars ] = longstring\n\n\t\t\tprintf(\"a = '%c', b = '%c', c = '%c'\\n\", a, b, c)\n\n\t\t\t// this should not, and thankfully, does not, work.\n\t\t\t// chars[3] = char(\"$\")\n\n\t\t\tvar k = 0\n\t\t\twhile k < chars.length\n\t\t\t{\n\t\t\t\tprintf(\"%c\", chars[k])\n\t\t\t\tk += 1\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "build/tests/defertest.flx",
    "content": "// defer.flx\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport test_defer\nimport libc as _\n\n\npublic fn doDeferTest()\n{\n\tbar()\n}\n\n\nfn foo(x: int) -> int\n{\n\tprintf(\"calling foo %d\\n\", x)\n\treturn 2 * x\n}\n\n\nfn bar() -> int\n{\n\t// numbered by *correct* order of appearance.\n\t// defer should execute after the return.\n\n\tfoo(1)\n\tdefer foo(3)\n\treturn foo(2)\n}\n\n\n"
  },
  {
    "path": "build/tests/fizzbuzz.flx",
    "content": "// fizzbuzz.flx\n// Copyright (c) 2014 - 2015, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport test_fizz\nimport libc\n\npublic fn doFizzBuzz(num: int)\n{\n\tvar i = 0\n\twhile i <= num\n\t{\n\t\tlibc::printf(\"%02d:      \", i)\n\n\t\tif i % 3 == 0\n\t\t{\n\t\t\tlibc::printf(\"Fizz\")\n\t\t}\n\t\tif i % 5 == 0\n\t\t{\n\t\t\tlibc::printf(\"Buzz\")\n\t\t}\n\n\t\tif i % 5 != 0 && i % 3 != 0\n\t\t{\n\t\t\tlibc::printf(\"%d\", i)\n\t\t}\n\n\t\tlibc::printf(\"\\n\")\n\t\ti += 1\n\t}\n}\n"
  },
  {
    "path": "build/tests/forloops.flx",
    "content": "// forloops.flx\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport test_forloops\nimport libc as _\n\npublic fn doForLoopTest()\n{\n\tdo {\n\t\tprintf(\"\\n>> ranges\\n\")\n\n\t\tlet r1 = 0 ... 3\n\t\tlet r2 = 0 ..< 1\n\n\t\tprintf(\"r1.l = %d, r1.u = %d\\n\", r1.begin, r1.end)\n\t\tprintf(\"r2.l = %d, r2.u = %d\\n\\n\", r2.begin, r2.end)\n\n\t\tfor i, j in r1\n\t\t{\n\t\t\tprintf(\"%d: i = %d\\n\", j, i)\n\t\t}\n\t}\n\n\tdo {\n\t\tprintf(\"\\n>> for-in array\\n\")\n\n\t\tlet x = [ (1, \"a\"), (2, \"b\"), (3, \"c\"), (4, \"d\") ]\n\t\tlet fixed: [(int, int): 3] = [ (10, 2), (7, 3), (3, 2) ]\n\n\t\tfor (a, b), i in x\n\t\t{\n\t\t\tprintf(\"%d: %d / %s\\n\", i, a, b)\n\t\t}\n\t}\n\n\tdo {\n\t\tprintf(\"\\n>> for-in string\\n\")\n\n\t\tfor c, i in \"woohoo\"\n\t\t{\n\t\t\tprintf(\"%d: '%c', \", i, c)\n\t\t}\n\n\t\tprintf(\"\\n\")\n\t}\n}\n\n\n\n"
  },
  {
    "path": "build/tests/functions.flx",
    "content": "// functions.flx\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport test_functions\nimport libc as _\n\nfn foo(a: int) { printf(\"foo: %d\\n\", a) }\nfn bar(a: int) { printf(\"bar: %d\\n\", a) }\nfn qux() { (\"qux\\n\") }\n\nclass SomeClass\n{\n\tinit() { }\n\tfn foo(a: int) { printf(\"foo in class: %d\\n\", a) }\n\tstatic fn bar(a: int) { printf(\"static bar in class: %d\\n\", a) }\n}\n\nnamespace SomeNS\n{\n\tfn foo(a: int) { printf(\"foo in namespace: %d\\n\", a) }\n\n\tclass NestedClass\n\t{\n\t\tinit() { }\n\n\t\tfn foo(a: int) { printf(\"foo in nested class: %d\\n\", a) }\n\t\tstatic fn bar(a: int) { printf(\"static bar in nested class: %d\\n\", a) }\n\n\t\t// fn mgen<T>(a: T) -> T { printf(\"method generic: %p // %d\\n\", self, a) }\n\t\t// static fn smgen<T>(a: T) -> T { printf(\"static generic: %d\\n\", a) }\n\t}\n\n\t// fn ngen<T>(a: T) -> T { printf(\"namespace generic: %p // %d\\n\", a) }\n}\n\n\n\nfn gen<T>(a: T) -> T\n{\n\tif(typeid(a) == typeid(int))        => printf(\"int: %d\\n\", a)\n\telse if(typeid(a) == typeid(f64))   => printf(\"float: %lf\\n\", a)\n\n\treturn a + 1\n}\n\nfn et(a: int)\n{\n\tprintf(\" %d\", a)\n}\n\nfn et1(a: int) -> int\n{\n\tprintf(\" %d\", a)\n\treturn a\n}\n\n\nclass SomeStruct\n{\n\tinit() { }\n\n\n\tvar f: fn(&SomeStruct, int) -> int\n\tfn fun(a: string) -> int\n\t{\n\t\tprintf(\"method: %s\\n\", a)\n\t\treturn 40\n\t}\n\n\tstatic fn sfn(self: &SomeStruct, a: int) -> int\n\t{\n\t\tprintf(\"static: %d\\n\", a);\n\t\treturn a;\n\t}\n}\n\n\npublic fn doFunctionTest()\n{\n\tvar f = qux\n\tf()\n\n\tvar g = foo\n\tg(10)\n\n\tg = bar\n\tg(20)\n\n\tprintf(\"each test:\")\n\tlet arr = (alloc int[4])[:].ptr\n\tarr[0] = 11\n\tarr[1] = 22\n\tarr[2] = 33\n\tarr[3] = 44\n\n\teach(arr, 4, et)\n\n\n\n\tprintf(\"\\n\\nscope test\\n\")\n\tdo {\n\n\t\tg = SomeClass::bar\n\t\tg(10)\n\n\t\tg = SomeNS::NestedClass::bar\n\t\tg(20)\n\n\t\tg = SomeNS::foo\n\t\tg(30)\n\t}\n\n\n\tprintf(\"\\nmethod test\\n\")\n\tdo {\n\t\tvar method = SomeClass::foo\n\t\tlet sc = SomeClass()\n\t\tmethod(&sc, 40)\n\n\t\tvar method2 = SomeNS::NestedClass::foo\n\t\tlet nc = SomeNS::NestedClass()\n\t\tmethod2(&nc, 50)\n\t}\n\n\n\t// printf(\"\\ngeneric test\\n\")\n\t// do {\n\t// \tvar gf: [(int) -> int] = gen\n\t// \tvar gff: [(f64) -> f64] = gen\n\n\t// \tgf(100)\n\t// \tgff(3.1415926536)\n\n\t// \t// gf = SomeNS.ngen\n\t// \tgf(200)\n\n\n\t// \t// reassignment\n\t// \tprintf(\"\\nclass test\\n\")\n\t// \tdo {\n\t// \t\tvar gf2: [(int) -> int] = et1\n\t// \t\tprintf(\"et:\"); gf2(300); printf(\"\\n\")\n\t// \t\tgf2 = gen\n\t// \t\tgf2(400)\n\n\t// \t\tvar s = SomeStruct()\n\n\t// \t\tlet gf3 = SomeStruct.sfn\n\t// \t\tgf3(&s, 500)\n\n\t// \t\ts.f = gf3\n\t// \t\tlet gf4 = s.f\n\t// \t\tgf4(&s, 600)\n\n\t// \t\tprintf(\"\\ngeneric member test\\n\")\n\n\t// \t\tlet gf5: [(int) -> int] = SomeNS.NestedClass.smgen\n\t// \t\tgf5(10)\n\n\t// \t\tvar gf6: [(SomeNS.NestedClass*, int) -> int]\n\t// \t\tgf6 = SomeNS.NestedClass.mgen\n\n\t// \t\tlet nc = SomeNS.NestedClass()\n\t// \t\tgf6(&nc, 10)\n\n\n\t// \t\tprintf(\"\\ndirect field calling\\n\")\n\t// \t\tlet res1 = s.f(&s, 10)\n\t// \t}\n\t// }\n}\n\n\n\nfn each(arr: &int, length: int, f: fn(int) -> void)\n{\n\tvar i = 0\n\n\twhile i < length\n\t{\n\t\tf(arr[i])\n\t\ti += 1\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "build/tests/generics.flx",
    "content": "// generics.flx\n// Copyright (c) 2014 - 2015, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport test_generics\nimport libc as _\n\npublic fn doGenericsTest()\n{\n\t// some normal FP stuff\n\tfn map<T, U>(arr: [T:], fun: fn(T) -> U) -> [U]\n\t{\n\t\tvar ret: [U]\n\t\tfor it in arr => ret.append(fun(it))\n\n\t\treturn ret\n\t}\n\n\tdo {\n\t\tprintf(\"set 1:\")\n\n\t\tfn twice<K>(a: K) -> K => a * 2\n\n\t\tlet new = map(fun: twice, arr: [ 1, 2, 3, 4, 5 ])\n\t\tfor it in new { printf(\" %d\", it) }\n\n\t\tprintf(\"\\n\")\n\t}\n\n\tdo {\n\t\tprintf(\"set 2:\")\n\n\t\tfn twice(a: str) -> string => string(a) + string(a)\n\n\t\tlet new = map([ \"a\", \"b\", \"c\", \"d\", \"e\" ], twice)\n\t\tfor it in new => printf(\" %s\", it)\n\n\t\tprintf(\"\\n\")\n\t}\n\n\tdo {\n\t\tprintf(\"set 3:\")\n\n\t\tfn square<T, U>(a: T) -> U => (a * a)\n\n\t\tlet new: [f64] = map([ 7.3, 8.7, 9.1, 10.4, 11.6 ], square)\n\t\tfor it in new { printf(\" %.2f\", it) }\n\n\t\tprintf(\"\\n\")\n\t}\n\n\tdo {\n\t\tfn gincr<A>(x: A) -> A => x + 1\n\t\tfn apply<B, C>(x: B, f: fn(B) -> C) -> C => f(x)\n\n\t\tfn mapstupid<D, E, F>(arr: [D:], f: fn(D) -> E, fa: fn(D, fn(D) -> E) -> F) -> [F]\n\t\t{\n\t\t\tvar i = 0\n\t\t\tvar ret: [F]\n\t\t\twhile i < arr.length\n\t\t\t{\n\t\t\t\tret.append(fa(arr[i], f))\n\t\t\t\ti += 1\n\t\t\t}\n\n\t\t\treturn ret\n\t\t}\n\n\t\tprintf(\"set 4:\")\n\t\tlet new = mapstupid([ 5, 6, 7, 8, 9 ], gincr, apply)\n\t\tfor it in new { printf(\" %d\", it) }\n\n\t\tprintf(\"\\n\")\n\t}\n\n\tdo {\n\t\tfn map2<T, K, R>(arr: [(T, K):], f: fn(T, K) -> R) -> [R]\n\t\t{\n\t\t\tvar i = 0\n\t\t\tvar ret: [R]\n\t\t\twhile i < arr.length\n\t\t\t{\n\t\t\t\tret.append(f(arr[i].0, arr[i].1))\n\t\t\t\ti += 1\n\t\t\t}\n\n\t\t\treturn ret\n\t\t}\n\n\t\tfn add2<A, B>(x: A, y: B) -> A => x + y\n\n\t\tprintf(\"set 5:\")\n\t\tlet new = map2([ (2, 2), (4, 4), (6, 6), (8, 8), (10, 10) ], add2)\n\t\tfor it in new { printf(\" %d\", it) }\n\n\t\tprintf(\"\\n\")\n\t}\n\n\tdo {\n\t\tfn prints<T, U>(m: T, a: [U: ...])\n\t\t{\n\t\t\tfor x in a => printf(\" %.2d\", m * x)\n\t\t}\n\n\t\tprintf(\"set 6:\")\n\t\tlet xs = [ 1, 2, 3, 4, 5 ]\n\t\tprints(3, ...xs)\n\n\t\tprintf(\"\\n\")\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "build/tests/intlimits.flx",
    "content": "// intlimits.flx\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport test_limits\n\nimport libc\nimport std::limits\n\npublic fn printIntegerLimits()\n{\n\tlibc::printf(\" i8::min  = %hhd\\t\\t\\t i8::max  = %hhd\\n\", std::limits::int8::min, std::limits::int8::max);\n\tlibc::printf(\"i16::min  = %hd\\t\\t\\ti16::max  = %hd\\n\", std::limits::int16::min, std::limits::int16::max);\n\tlibc::printf(\"i32::min  = %d\\t\\t\\ti32::max  = %d\\n\", std::limits::int32::min, std::limits::int32::max);\n\tlibc::printf(\"i64::min  = %lld\\ti64::max  = %lld\\n\", std::limits::int64::min, std::limits::int64::max);\n\n\tlibc::printf(\"\\n\")\n\n\tlibc::printf(\" u8::min  = %hhu\\t\\t\\t\\t u8::max  = %hhu\\n\", std::limits::uint8::min, std::limits::uint8::max);\n\tlibc::printf(\"u16::min  = %hu\\t\\t\\t\\tu16::max  = %hu\\n\", std::limits::uint16::min, std::limits::uint16::max);\n\tlibc::printf(\"u32::min  = %u\\t\\t\\t\\tu32::max  = %u\\n\", std::limits::uint32::min, std::limits::uint32::max);\n\tlibc::printf(\"u64::min  = %llu\\t\\t\\t\\tu64::max  = %llu\\n\", std::limits::uint64::min, std::limits::uint64::max);\n}\n"
  },
  {
    "path": "build/tests/linkedlist.flx",
    "content": "// linkedlist.flx\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport test_linkedlist\nimport libc as _\n\nclass LinkedList<T>\n{\n\tstruct Node\n\t{\n\t\tprev: &Node\n\t\tnext: &Node\n\n\t\tdata: T\n\t}\n\n\tvar head: &Node\n\tvar tail: &Node\n\n\tvar count: int\n\n\tinit(data: T)\n\t{\n\t\tprintf(\"called init\\n\")\n\t}\n\n\tmut fn insert(thing: T)\n\t{\n\t\tvar nn = alloc mut Node (data: thing, prev: null, next: null)\n\n\t\tif head == null { head = nn; tail = nn }\n\t\telse\n\t\t{\n\t\t\tvar ot = tail as mut\n\t\t\ttail = nn\n\n\t\t\tnn.prev = ot\n\t\t\tot.next = nn\n\t\t}\n\n\t\tcount += 1\n\t}\n\n\tstatic fn hello() { printf(\"hi\\n\"); }\n}\n\n\npublic fn doLinkedListTest()\n{\n\tdo {\n\t\tvar list = LinkedList(data: 41)\n\t\tLinkedList!<int>::hello()\n\n\t\tvar list2 = LinkedList(data: \"foo\")\n\t\tlist2.insert(\"hello\")\n\t\tlist2.insert(\"world\")\n\n\t\tlist.insert(10)\n\t\tlist.insert(20)\n\t\tlist.insert(30)\n\t\tlist.insert(40)\n\n\t\tdo {\n\t\t\tvar head = list.head\n\t\t\twhile(head)\n\t\t\t{\n\t\t\t\tprintf(\"%d\\n\", head.data)\n\t\t\t\thead = head.next\n\t\t\t}\n\t\t}\n\n\t\tdo {\n\t\t\tvar head = list2.head\n\t\t\twhile(head)\n\t\t\t{\n\t\t\t\tprintf(\"%s\\n\", head.data)\n\t\t\t\thead = head.next\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n"
  },
  {
    "path": "build/tests/misc.flx",
    "content": "// misc.flx\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n\nclass TestingClass\n{\n\tinit(x: int)\n\t{\n\t\tself.thing = x\n\t}\n\n\tvar thing: int\n}\n\n\nextension TestingClass : StringConvertible, Equatable\n{\n\tfn toString() -> string { \"hello\" }\n\n\toperator == (a: TestingClass) -> bool\n\t{\n\t\treturn self.thing == a.thing\n\t}\n}\n\n\nfn cts<T : StringConvertible>(thing: T) -> string\n{\n\treturn thing.toString()\n}\n\nfn pt<T>(a: T, b: &T) -> T\n{\n\treturn a\n}\n\nfn vt<T>(b: T[...])\n{\n\tvar i = 0\n\n\twhile i < b.length\n\t{\n\t\tprintf(\"%d\\n\", b[i])\n\t\ti += 1\n\t}\n}\n\nfn vt2<T>(a: T, b: int[...])\n{\n\t// do something.\n\tvariadicTest(a, b)\n}\n\n\n@nomangle fn mtest(k: int, g: int)\n{\n\tprintf(\"(%d, %d)\\n\", k, g)\n\n\tlet x = TestingClass(10)\n\tlet y = TestingClass(20)\n\n\tlet g = 10\n\tpt(10, &g)\n\n\tvt(10, 30, 40, 50, 60)\n\tvt2(\"hi\", 1, 2, 3, 4)\n\n\tprintf(\"%d, (%s, %s, %s, %s)\\n\", x == y, cts(k), cts(x), cts(g), cts(y))\n}\n\n\n\n\n// although it would be possible to move the slipshod array system into a generic Array<> thing, once it's implemented\n// sidenote: oh look, it works for arbitrary types.\n// sometimes, i'm impressed by the things i've implemented.\n\n// i think this form of varargs should *stay*, since it's basically a compiler primitive.\n// once we have an Array<> type, then it'd be as simple as having the Array<T> class define an initialiser with T[...],\n// since we can forward LLVarArrays effortlessly. then it's as easy as let arr = Array(b), and you can have all the Array<> class\n// niceties with varargs, without compromising freestanding functionality.\n\n// imho it's not worth it to have the compiler do the same thing as with String, because 1. String is not generic, and 2. varargs isn't\n// a \"core\" language feature, so to speak.\n\npublic fn variadicTest(a: string, b: int[...])\n{\n\tprintf(\"%s: [\", a)\n\tvar i = 0\n\twhile i < b.length\n\t{\n\t\tprintf(\"%d\", b[i])\n\t\ti += 1\n\n\t\tif i != b.length { printf(\", \") }\n\t}\n\n\tprintf(\"]\\n\")\n}\n\nextension string\n{\n\t// static fn withRaw(r: int8*) -> string\n\t// {\n\t// \tvar s: string\n\n\t// \tlet len = strlen(r)\n\t// \ts.raw = malloc(len + 8 + 1)\n\t// }\n}\n\n\n\npublic fn miscellaneousTests()\n{\n\tmtest(10, 41)\n\n\tdo {\n\t\tvar bar = (10, 20)\n\t\tvar foo: &&(&&(&&(float, float)[10])[3])\n\t}\n\n\tdo {\n\t\tvar g = \"439\"\n\t\tlet k = g.toInteger()\n\t\tprintf(\"%s, %d\\n\", g, k)\n\t}\n\n\tdo {\n\t\tprintf(\"'4' is digit: %d\\n\", char(\"5\").isDigit())\n\t}\n\n\tdo {\n\n\t\tstruct winsize\n\t\t{\n\t\t\tvar row: u16\n\t\t\tvar col: u16\n\t\t\tvar xpixel: u16\n\t\t\tvar ypixel: u16\n\t\t}\n\n\t\tvar ws: winsize\n\t\tioctl(1, 1074295912 as u64, &ws)\n\n\t\tprintf(\"terminal size: %hdx%hd (chars), %hdx%hd (pixels)\\n\", ws.col, ws.row, ws.xpixel, ws.ypixel)\n\t}\n\n\tdo {\n\t\tfn test() -> string\n\t\t{\n\t\t\treturn \"hello!\"\n\t\t}\n\n\t\tlet s = string(\"hello\")\n\t\tstring(\"hello\").raw\n\t\tprintf(\"test = %p %d\\n\", test().raw, i64(10))\n\t}\n\n\tdo {\n\n\t\tif let k = 30; k > 27\n\t\t{\n\t\t\tprintf(\"(if-let) k > 27\\n\")\n\t\t}\n\t}\n\n\n\tdo {\n\n\t\tenum SomeEnum\n\t\t{\n\t\t\tcase Up\n\t\t\tcase Down\n\t\t\tcase Left\n\t\t\tcase Right\n\t\t}\n\n\t\tstruct Foop\n\t\t{\n\t\t\tvar x: int\n\t\t}\n\n\t\tclass Barf\n\t\t{\n\t\t\tstatic var y: int = 40\n\t\t\tstatic var fkr: int\n\t\t\t{\n\t\t\t\tget { 30 }\n\t\t\t}\n\n\t\t\tfn foo() -> f64\n\t\t\t{\n\t\t\t\t43.1\n\t\t\t}\n\t\t}\n\n\t\tlet e = SomeEnum.Down\n\t\tlet f = Foop(10)\n\t\tlet barf = Barf()\n\n\t\tlet fo = barf.foo\n\n\t\tprintf(\"f.x = %d, b.c = %d, fo = %d\\n\", f.x, 3, Barf.y)\n\n\t\tlet tup = (\"a\", (30, 40, 50, 60))\n\t\tlet k = tup.1.1\n\n\t\tprintf(\"k = %d\\n\", k)\n\n\t\tlet s = \"some string \\\n\t\tbroken over \\\n\t\tmultiple lines\"\n\n\t\tprintf(\"s = %s\\n\", s)\n\n\t\tprintf(\"%d, %.7lf\\n\", k, +3.000141);\n\t}\n\n\n\tdo {\n\n\t\tfn foo<T>(a: T[], b: T) { }\n\t\tfn bar<T>(a: T, b: T[]) { }\n\n\t\tbar(10, [ ])\n\t\tfoo([ ], 20)\n\n\t\tvar z: int[:]\n\n\t\tstruct Test\n\t\t{\n\t\t\tvar a: int\n\t\t\tvar b: int\n\t\t}\n\n\t\tlet ta = Test(10, 10)\n\t\tlet tb = Test(10, 10)\n\n\t\tprintf(\"> %d / %d / %d <\\n\", sizeof(Test), sizeof(ta), sizeof(&ta))\n\n\t\tprintf(\"ta == tb: %d\\n\", ta == tb)\n\t}\n\n\n\n\tvariadicTest(\"ints\", 10, 20, 30, 40, 50, 60)\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "build/tests/operators.flx",
    "content": "// operators.flx\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nimport Math\nimport Foundation\n\nclass CPTest\n{\n\tvar readwrite: int\n\t{\n\t\tget { printf(\"READ\\n\"); return 31 }\n\t\tset { printf(\"WRITE: %d\\n\", value) }\n\t}\n}\n\n\n\n\n\n\npublic fn doOperatorTupleTest()\n{\n\tdo {\n\t\tlet g: i8 = 100\n\t\tprintf(\"g is: %d\\n\", g)\n\t}\n\n\tdo {\n\t\tlet m = (fa(), fb())\n\t\tprintf(\"m is [(%f, %f, %f), (%f, %f, %f)]\\n\", m.0.x, m.0.y, m.0.z, m.1.x, m.1.y, m.1.z)\n\n\t\tlet dot = m.0 • m.1\n\t\tprintf(\"dot = %f\\n\", dot);\n\n\t\tlet v1 = Math.Vector3(1.0, 2.0, 4.0)\n\t\tlet v2 = Math.Vector3(3.0, 6.0, 9.0)\n\n\t\tvar v = v1 + v2\n\t\tprintf(\"v: (%f, %f, %f)\\n\", v.x, v.y, v.z)\n\t\tv += v1\n\n\t\tv = v1 + v2 + v1\n\n\t\tlet vv = 3 * v\n\t\tprintf(\"v: (%f, %f, %f)\\n\", v.x, v.y, v.z)\n\t\tprintf(\"vv: (%f, %f, %f)\\n\", vv.x, vv.y, vv.z)\n\n\t\tlet cross = m.0 ⨯ m.1\n\t\tprintf(\"cross = (%f, %f, %f)\\n\", cross.x, cross.y, cross.z)\n\n\n\t\tlet crossn = m.1 ⨯ m.0\n\t\tprintf(\"crossn = (%f, %f, %f)\\n\", crossn.x, crossn.y, crossn.z)\n\t}\n\n\n\tdo {\n\t\t// var args = alloc[10] Any\n\t\t// args[0] = \"HELLO\"\n\t\t// #(args + 1) = 40\n\t\t// args[2] = \"GOODBYE\"\n\t}\n\n\n\tdo {\n\t\tlet v1 = Math.Vector2(1.0, 4.0)\n\t\tlet v2 = Math.Vector2(3.0, 7.0)\n\n\t\tlet vr = v1 ⨯ v2\n\t\tprintf(\"(%.2f), vr = %.2f\\n\", v1 • v2, vr)\n\n\t\tvar lol: string = \"HELLO\"\n\t\tprintf(\"%c\\n\", lol[1])\n\t\tprintf(\"lol[2]: %c // %s\\n\", lol[1], lol)\n\t}\n}\n\n\n\nfn fa() -> Math.Vector3\n{\n\tvar ret: Math.Vector3\n\tret.x = 1\n\tret.y = 2\n\tret.z = 3\n\n\treturn ret\n}\n\nfn fb() -> Math.Vector3\n{\n\tvar ret: Math.Vector3\n\tret.x = 4\n\tret.y = 5\n\tret.z = 6\n\n\treturn ret\n}\n\n\n\n\n\n"
  },
  {
    "path": "build/tests/recursiveFib.flx",
    "content": "// recursiveFib.flx\n// Copyright (c) 2014 - 2015, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport test_fib\n\nfn doRecursiveFib(n: int, v: int, prev: int) -> int\n{\n\tif n == 0 { return prev }\n\tif n == 1 { return v }\n\n\treturn doRecursiveFib(n - 1, v + prev, v)\n}\n\npublic fn doRecursiveFib(n: int) -> int\n{\n\treturn doRecursiveFib(n, 1, 0)\n}\n"
  },
  {
    "path": "build/tests/scopes.flx",
    "content": "// scopes.flx\n// Copyright (c) 2014 - 2015, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport test_scopes\n\nimport libc as _\nimport std::math\n\n\n@operator[prefix, 900, √]\n\noperator prefix √ (x: f64) -> f64 { return math::sqrt(x) }\n\nclass Orr\n{\n\tinit() { }\n\n\tstatic var Another = 76\n\tvar bar: int = 371\n}\n\nclass Something\n{\n\tinit() { }\n\n\tfn somefoo() -> Orr => Orr()\n\n\tstatic var Or: Orr\n\tvar oor: int = 400\n\n\n\n\tclass Inside\n\t{\n\t\tinit() { }\n\n\t\tfn insideFoo() -> int => 10\n\t\tstatic fn staticInside() -> int => 23\n\n\t\tstatic var Another = 511\n\t}\n\n\tenum InsideEnum : i64\n\t{\n\t\tcase None\n\t\tcase Single\n\t\tcase Double\n\t\tcase Triple\n\t\tcase Quadruple\n\t\tcase Quintuple\n\t\tcase Hextuple\n\t}\n}\n\nenum OutsideEnum : i64\n{\n\tcase Zero\n\tcase One\n\tcase Two\n\tcase Three\n\tcase Four\n}\n\nenum StrongEnum : i64\n{\n\tcase Red\n\tcase Green\n\tcase Blue\n}\n\n\nclass Sheep\n{\n\tinit() { }\n\n\tvar thing: int = 43\n\tvar foo: Something\n\n\tstatic var afoo: Something\n}\n\nnamespace n1\n{\n\tnamespace n2\n\t{\n\t\tvar m: Sheep\n\n\t\tvar tup: (str, int)\n\t\tfn nest() -> (str, int)\n\t\t{\n\t\t\tprintf(\"nested\\n\");\n\t\t\treturn (\"TUPLE ONE\", 591)\n\t\t}\n\n\t\tclass DeepClass\n\t\t{\n\t\t\tinit() { }\n\n\t\t\tclass DeeperClass\n\t\t\t{\n\t\t\t\tinit() { }\n\n\t\t\t\tstatic fn deepStatic() -> int => 23\n\t\t\t}\n\t\t}\n\t}\n}\n\n\npublic fn doScopeTest(argv: str)\n{\n\tlet p = 64.4 ÷ 4.1\n\n\tlet m = √(41.5)\n\n\tlet mmx = Something::Inside::Another\n\tlet another = 4\n\tlet foo = Something()\n\n\tlet mm = foo.somefoo().bar\n\n\n\tlet gg = (4, 100.39)\n\tprintf(\"gg.0: %d, gg.1: %.2f\\n\", (4, 50).0, gg.1)\n\n\tprintf(\"[%d]\\n\", foo.oor)\n\tprintf(\"p: %f, g: %d, m: %d, %.14f\\n\\n\", p, another, mmx, math::π)\n\n\n\tlet x1: int = OutsideEnum::Three as int\n\tlet x2: int = Something::InsideEnum::Quadruple as int\n\tlet x3 = n1::n2::DeepClass::DeeperClass()\n\tprintf(\"x1: %d, x2: %d, x3: %d\\n\", x1, x2, n1::n2::DeepClass::DeeperClass::deepStatic())\n\n\n\tn1::n2::m.foo.oor = 968\n\tprintf(\"oor = %d\\n\", n1::n2::m.foo.oor)\n\n\tlet t1 = n1::n2::m.foo.somefoo().bar\n\tlet t2 = n1::n2::nest().0.length\n\n\tn1::n2::tup.0 = \"HELLO, WORLD!\" //string(\"HELLO, WORLD\") + \"!\"\n\tprintf(\"tup: %s\\n\", n1::n2::tup.0)\n\n\tprintf(\"t1 = %d, t2 = %d\\n\", t1, t2)\n\tprintf(\"afoo: %d\\n\", Sheep::afoo.somefoo().bar)\n\n}\n\n\n\n\n\n\n"
  },
  {
    "path": "build/tests/slices.flx",
    "content": "// slices.flx\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport test_slices\nimport libc\n\npublic fn doSlicesTest()\n{\n\tdo {\n\t\tvar arr = [ 2, 3, 5, 7, 11, 13, 17 ]\n\t\tlet slice = arr[:]\n\t\tlibc::printf(\"-- %d, %d, %d, %d, %d, %d, %d --\\n\", slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6])\n\n\t\tlet s = \"Hello, world!\"\n\t\tlibc::printf(\"original: %s\\nslice: %.*s\\n\", s, s[3:10].length, s[3:10])\n\t}\n}\n\n@entry fn main()\n{\n\tdoSlicesTest()\n}\n"
  },
  {
    "path": "build/tests/unions.flx",
    "content": "// unions.flx\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport test_unions\nimport libc as _\n\nunion option<T>\n{\n\tsome: T\n\tnone\n}\n\n@raw union ipv4\n{\n\t_: struct {\n\t\t_: @raw union {\n\t\t\tbytes2: [u8: 4]\n\t\t\traw3: u32\n\t\t}\n\t}\n\n\t_: struct {\n\t\tbytes: [u8: 4]\n\t}\n\n\t_: struct {\n\t\traw2: u32\n\t}\n\n\traw: u32\n}\n\npublic fn doUnionsTest()\n{\n\tdo {\n\n\t\tlet x = option::some(\"foobar\")\n\t\tlet y = option::some(456)\n\n\t\tprintf(\"x = %s, y = %d\\n\", x as option!<str>::some, y as option!<int>::some)\n\t}\n\n\tdo {\n\t\tunion Bar\n\t\t{\n\t\t\tsome: str\n\t\t\tother: int\n\t\t\tnone\n\t\t}\n\n\t\tlet q = Bar::some(\"hello\")\n\t\tlet v = Bar::other(30)\n\t\tlet m = Bar::none\n\n\t\tprintf(\"q = %s, v = %d\\n\", q as Bar::some, v as Bar::other)\n\t}\n\n\tdo {\n\t\tvar addr: ipv4\n\t\taddr.raw3 = 0xff01a8c0;\n\t\tprintf(\"%d.%d.%d.%d\\n\", addr.bytes[0], addr.bytes[1], addr.bytes[2], addr.bytes[3]);\n\t}\n}\n\n\n\n\n\n\n\n"
  },
  {
    "path": "build/tests/using.flx",
    "content": "// using.flx\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport test_using\nimport libc as _\n\npublic fn doUsingTest()\n{\n\tdo {\n\t\tenum Foo: int\n\t\t{\n\t\t\tcase Alpha      = 10\n\t\t\tcase Bravo      = 20\n\t\t\tcase Charlie    = 30\n\t\t}\n\n\t\tusing Foo as _\n\t\tprintf(\"a = %d, b = %d, c = %d\\n\", Alpha.value, Bravo.value, Charlie.value)\n\n\t\tusing Foo as f\n\t\tprintf(\"a = %d, b = %d, c = %d\\n\", 3 * f::Alpha.value, 3 * f::Bravo.value, 3 * f::Charlie.value)\n\t}\n\n\tdo {\n\t\tclass xxx<T>\n\t\t{\n\t\t\tinit() { }\n\n\t\t\tvar k: T\n\t\t\tenum Foo: int\n\t\t\t{\n\t\t\t\tcase Alpha      = 71\n\t\t\t\tcase Bravo      = 72\n\t\t\t\tcase Charlie    = 73\n\t\t\t}\n\t\t}\n\n\t\tusing xxx!<int>::Foo as _\n\n\t\tprintf(\"a = %d, b = %d, c = %d\\n\", Alpha.value, Bravo.value, Charlie.value)\n\t}\n\n\tdo {\n\t\tunion Option<T>\n\t\t{\n\t\t\tsome: T\n\t\t\tnone\n\t\t}\n\n\t\tusing Option as _\n\n\t\tlet x = some(381)\n\t\tlet y = some(\"hi\")\n\t\tprintf(\"x = %d, y = %s\\n\", x as some, y as some)\n\t}\n\n\tdo {\n\t\tunion Option<T>\n\t\t{\n\t\t\tsome: T\n\t\t\tnone\n\t\t}\n\n\t\tusing Option!<T: int> as _\n\t\tusing Option!<str> as _\n\n\t\tlet x = some(30)\n\t\tlet y = some(\"bye\")\n\t\tprintf(\"x = %d, y = %s\\n\", x as some, y as some)\n\t}\n}\n\n\n"
  },
  {
    "path": "build/tiniest.flx",
    "content": "// tiniest.flx\n// Copyright (c) 2020, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nimport libc\n\nclass wrapper<T>\n{\n\tinit()\n\t{\n\t}\n\n\tstatic fn method<U>(a: T, b: U)\n\t{\n\t\tlibc::printf(\"t = %d, u = %d\\n\", typeid(a), typeid(b));\n\t}\n}\n\n\n@entry fn main()\n{\n\twrapper::method(1, \"asdf\")\n\tlibc::printf(\"hello, world\\n\")\n}\n"
  },
  {
    "path": "build/tmp/repro_1.flx",
    "content": "// repro_1.flx\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n/*\nimport libc as _\n// import repro_2 as _\nimport repro_2\nimport std::limits as lim\n\nusing repro_2 as _\n\n@entry fn main()\n{\n\tclass Foozle\n\t{\n\t\tinit() { }\n\n\t\tstatic fn alpha() { }\n\n\t\tclass Flub\n\t\t{\n\t\t\tinit() { }\n\n\t\t\tstatic fn beta() { }\n\n\t\t\tstatic fn omega() { printf(\"owo\\n\") }\n\t\t};\n\t}\n\n\tprintf(\"four = %d\\n\", Foo::FOUR.value);\n\n\tprintf(\"hello\\n\");\n\n\tusing Foozle::Flub as Flubzle\n\tFlubzle::omega();\n\n\tprintf(\"%d\\n\", Bar::bla(3));\n\tprintf(\"lmao\\n\");\n\n\tlet x = lim::int16::max;\n\tprintf(\"x = %x\\n\", x);\n\n\t// let c = \"a\" + \"b\"\n}\n*/\n\n\nimport libc\nimport repro_3\n\n// using libc as _\n\n@entry fn main2()\n{\n\t// std::io::println(\"owo\")\n\t// owo::println(\"owo\")\n\t// uwu::owo::foozle()\n\t// printf(\"owo\\n\")\n\trepro_3::foozle(10)\n}\n\n"
  },
  {
    "path": "build/tmp/repro_2.flx",
    "content": "// repro_2.flx\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\npublic enum Foo: i32\n{\n\tcase ONE    = 1\n\tcase TWO    = 2\n\tcase FOUR   = 4\n}\n\npublic class Bar\n{\n\tinit() { }\n\n\tstatic fn bla(x: int) -> int => x * x\n}\n"
  },
  {
    "path": "build/tmp/repro_3.flx",
    "content": "// repro_3.flx\n// Copyright (c) 2020, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n// public import libc as _\nimport libc\n\nfn foozle(x: int, y: int) -> int\n{\n\treturn x * y\n}\n\npublic fn foozle(x: int)\n{\n\tfoozle(x, x + 2)\n\t// libc::printf(\"asdf %d\\n\", foozle(x, x + 2));\n}\n"
  },
  {
    "path": "build/tmp2/a.flx",
    "content": "// a.flx\n// Copyright (c) 2020, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nimport libc as _\n\n@entry fn main()\n{\n\t// let x = bazzle() * 2\n\t// foozle(3)\n\tvar i = 0\n\twhile true\n\t{\n\t\tdefer { i += 1 }\n\t\tif i < -30 => break\n\t\telse if i > 10 => break\n\n\t\tprintf(\"i = %d\\n\", i)\n\t}\n}\n"
  },
  {
    "path": "build/tmp2/b.flx",
    "content": "// b.flx\n// Copyright (c) 2020, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n<<<<<<< Updated upstream\npublic import c as _\n\npublic fn bazzle() -> int => 30\n=======\npublic let INIT_TIMER: u32                      = 0x00000001\npublic let INIT_AUDIO: u32                      = 0x00000010\n>>>>>>> Stashed changes\n"
  },
  {
    "path": "build/tmp2/c.flx",
    "content": "// c.flx\n// Copyright (c) 2020, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n<<<<<<< Updated upstream\nexport c\n\nffi fn printf(fmt: &i8, ...) -> int\n\npublic fn foozle(x: int)\n{\n\tprintf(\"hello, world! (%d)\\n\", x)\n}\n=======\n>>>>>>> Stashed changes\n"
  },
  {
    "path": "build/ultratiny.flx",
    "content": "// ultratiny.flx\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport ultratiny\n\nimport libc as _\nimport std::io as _\n\n// import std::math\n\n@compiler_support[\"raii_trait::drop\"] trait Drop { fn deinit() }\n@compiler_support[\"raii_trait::copy\"] trait Copy { fn copy(other: &self) }\n@compiler_support[\"raii_trait::move\"] trait Move { fn move(other: &mut self) }\n\nclass Foo1\n{\n\tinit() { }\n\tdeinit { printf(\"killed base\\n\"); }\n}\n\nclass Foo : Foo1, Drop, Copy, Move\n{\n\tvar data: int\n\n\tinit(x: int) : super()\n\t{\n\t\tprintf(\"of make (%d)\\n\", x)\n\t\tthis.data = x\n\t}\n\n\t// fn deinit()\n\t// {\n\t// \tprintf(\"is kill (%d)\\n\", data)\n\t// }\n\n\tfn copy(other: &self)\n\t{\n\t\tthis.data = other.data\n\t\tprintf(\"am copy (%d)\\n\", data)\n\t}\n\n\tfn move(other: &mut self)\n\t{\n\t\tthis.data = other.data\n\t\tother.data = 0\n\n\t\tprintf(\"be move (%d)\\n\", data)\n\t}\n}\n\nclass Bar\n{\n\tvar data: int\n\tinit(x: int)\n\t{\n\t\tthis.data = x\n\t}\n}\n\nfn one() -> Foo\n{\n\treturn Foo(x: 33)\n}\n\nfn two(x: Foo)\n{\n\tprintf(\"x.data = %d\\n\", x.data)\n}\n\n\n\n@entry fn main()\n{\n\tlet q = one()\n\tq.data = 17\n\n\ttwo(q)\n\n\tprintf(\"q = %d\\n\", q)\n}\n\n\n/*\n\traii traits checklist:\n\n\tproblem with deinit: in any given class implementation, the user-defined deinit *needs* to call both:\n\t(a) the inline destructor for the class\n\t(b) the user-defined destructor for the base class\n\t(c) the inline destructor for the base class\n\n\tso this is a bunch of work that isn't done? also, in the base class case, the derived class cannot properly\n\tdefine a deinit() function, because of redefinitions. what's the solution?\n\n\t(1) everything becomes virtual (ew)\n\t(2) method hiding (also ew)\n\t(3) ???\n\n\n\t3. remove the copy/move/destruct stuff from FIR?\n*/\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "changelog.md",
    "content": "# Partial Changelog\n\n\n### 2018-12-09 `(1350296)`\n- fix a refcounting bug where things were getting freed too early. the cause of this bug is when we transitioned to the lvalue system, around\n\t`24addf2`, when we added arguments to the refcounting stack; we forgot to include a corresponding increment in the call argument codegen, which\n\thas since been rectified.\n\n\n---\n### 2018-12-08 `(201a2ce)`\n- allow `::` to refer to the topmost scope, like in C++\n- allow `^` at any location in the scope path to refer to the parent scope -- eg. `::qux::^::foo::^::bar` (naturally will fail at the root scope!)\n- for some reason, added a more verbose error message when you try to use a value as a type -- it searches up the tree for an actual type with the name,\n\tand tells you how to refer to it -- using the parent-scope specifier mentioned above.\n\n\n---\n### 2018-12-07 `(621aea2)`\n- add location info to `pts` types -- which will soon need to be carried over to `fir` -- probably some kind of `TypeLocator` struct that I have in mind.\n- abstract away which `hash_map` we use -- preliminary tests show `ska::flat_hash_map` gives us a ~9% perf improvement across-the-board -- using the\n\t`massive.flx` and associated test framework.\n\n\n---\n### 2018-12-06 `(aa33f64)`\n- add a flag to call `abort()` on error -- now the default behaviour is to `exit(-1)`.\n\n\n---\n### 2018-12-06 `(f04726c)`\n- fixed our `std::map` implementation a bit\n- calls to `malloc` should go through our new malloc wrapper which checks for `null` returns\n- hoist `make_lval` similar to `alloca` -- was causing stack overflow issues!\n- apply type transforms (`poly/transforms.cpp`) in reverse, duh! surprised we didn't run into this sooner.\n- fix an oversight where we allowed variables to be 'used' in nested functions (due to the scoping rules implicitly), and let it slip to llvm-land (!)\n\n\n---\n### 2018-12-05 `(3119634)`\n- fixed a bug where we failed to infer union types -- was just checking the wrong thing.\n- add a check for unwrapping (with `as`) union values to variants with no values (eg. `opt::none`)\n- fixed a bug where we were not checking for duplicates when adding unresolved generic defns and operator overloads.\n\n\n---\n### 2018-12-04 `(2dbb858)`\n- fix omission of floating-point comparison ops (oops)\n- further patches to merge-block-elision\n- fix ir-block error when doing multiple logical operators (`&&` and `||`)\n- `is` check parses its rhs-operand the same way as `as` now (aka properly!)\n- add the concept of `realScope`, which is the original scope of a definition -- aka where it got defined. we need this idea because we can call `ast::typecheck()` from *any* scope, usually when instantiating generics\n- clean up string output to use `::` for scopes instead of `.`\n- change the criteria of finding an existing definition (for generic things) to only match the last N items of the current\n\tstate with the stored state -- instead of the previous vice-versa situation. (ie. the current state can be smaller than the stored state)\n- add a distance penalty for resolving a generic function, also add a check where we don't re-add a function twice (eg. when recursively calling a\n\tgeneric function)\n- `ast::Block`s now push an anonymous scope -- no idea why they didn't. fixes a pretty massive bug where bodies of an if statement shared the same scope\n- probably some other misc fixes i forgot\n\n\n---\n### 2018-12-02 `(05b3953)`\n- fix a using bug (`d1a0efe`)\n- clean up the generated IR blocks, and implement 'merge-block-elision' properly (`76481a2`)\n- fix implicit method calls (that i forgot to fix after refactoring the self-handling previously)\n\n\n---\n### 2018-12-01 `(076e176)`\n- allow `export`-ing a path, eg. `std::limits`. this is different from namespacing the entire file (unlike C++), because we would then\n\tget `limits::std::...` instead\n- allow `import`-ing a path as well, so we can do `import std::limits as foo::bar::qux`.\n- `import`s of string paths (eg. `import \"foo/bar\"`) no longer append an `.flx` extension automatically!\n\n\n---\n### 2018-11-06 `(59f8469)`\n- flip the declaration of `ffi-as` so the external name is after `as` -- and now as a string literal (because your external names might have\n\tflax-illegal characters inside)\n\n\n---\n### 2018-11-06 `(a2721fc)`\n- declare foreign functions `as` something -- useful for OpenGL especially, (1) to deduplicate the `gl` prefix, and (2) to allow overloading of all\n\tthe different `glVertex<N><T>` where `N = 2, 3, 4`, `T = i, f, d` or something.\n\n\n---\n### 2018-11-06 `(e2f235b)`\n- `public` and `private` imports, where the former re-exports things and the latter is the default behaviour.\n\n\n---\n### 2018-11-05 `(494a01e)`\n- static access now uses `::` instead of `.`, along the veins of C++ and Rust.\n- polymorph instantiations now take the form of `Foo!<...>` (the exclamation mark) -- making it less likely to be ambiguous.\n- polymorph arguments can now be positional, meaning `Foo!<int>` instead of `Foo!<T: int>`. The rules are similar to that of funtion calls\n\t-- no positional arguments after named arguments.\n\n\n---\n### 2018-10-28 `(0b937a5)`\n- add chained comparison operators, eg. `10 < x < 30` would *succinctly* check for `x` between 10 and 30.\n- consequently, changed the precedence for all six comparison operators (`==`, `!=`, `<`, `<=`, `>`, and `>=`) to be the same (500)\n\n\n---\n### 2018-10-28 `(f7fd4e6)`\n- using unions -- including both generic and instantiated unions\n- vastly improved (i'd say) inference for variants of unions (when accessing them implicitly)\n\n\n---\n### 2018-10-27 `(e365997)`\n- infer polymorphs with union variants (except singleton variants)\n- clean up some of the `TypecheckState` god object\n- fixed a number of related bugs regarding namespaced generics\n- give polymorphic types a `TypeParamMap_t` if there was a `type_infer`\n\n\n---\n### 2018-10-05 `(9de42cb)`\n- major revamp of the generic solver -- the algorithm is mostly unchanged, but the interface and stuff is reworked.\n- finally implemented the iterative solver\n- variadic generics work\n- took out tuple splatting for now.\n\n\n---\n### 2018-07-31 `(efc961e)`\n- generic unions, but they're quite verbose.\n\n\n---\n### 2018-07-29 `(e475e99)`\n- add tagged union types, including support for `is` and `as` to check and unwrap respectively\n- infer type parameters for a type from a constructor call\n\n\n---\n### 2018-07-23 `(c89c809)`\n- fix the recursive instantiation of generic functions.\n\n\n---\n### 2018-07-23 `(ff2a45a)`\n- no longer stack allocate for arguments\n- new lvalue/rvalue system in the IRBuilder, to make our lives slightly easier; we no longer need to pass a value/pointer pair,\n\tand we handle the thing in the translator -- not very complicated.\n- add `$` as an alias for `.length` when in a subscript or slicing context, similar to how D does it.\n- we currently have a bug where we cannot recursively instantiate a generic function.\n\n\n---\n### 2018-07-16 `(fdc65d7)`\n- factor the any-making/getting stuff into functions for less IR mess.\n- fix a massive bug in `alloc` where we never called the user-code, or set the length.\n- add stack-allocs for arguments so we can take their address. might be in poor taste, we'll see.\n- enable more tests in `tester.flx`.\n\n\n---\n### 2018-07-15 `(70d78b4)`\n- fix string-literal-backslash bug.\n- clean up some of the old cruft lying around.\n- we can just make our own function called `char` that takes a slice and returns the first character. no compile-time guarantees,\n\tbut until we figure out something better it's better than nothing.\n\n\n---\n### 2018-07-15 `(0e53fce)`\n- fix the bug where we were dealing incorrectly with non-generic types nested inside generic types.\n- fix calling variadic functions with no variadic args (by inserting an empty thing varslice in the generated arg list)\n- fix 0-cost casting between signed/unsigned ints causing overload failure.\n\n\n---\n### 2018-07-15 `(7e8322d)`\n- add `is` to streamline checking the `typeid` of `any` types.\n\n\n---\n### 2018-06-10 `(d1284a9)`\n- fix a bug wrt. scopes; refcount decrementing now happens at every block scope (not just loops) -- added a new `BlockPoint` thing to convey this.\n- fix a massive bug where `else-if` cases were never even being evaluated.\n- `stdio.flx`!\n\n\n---\n### 2018-06-10 `(1aade5f)`\n- replace the individual IR stuff for strings and dynamic arrays with their SAA equivalents.\n- add an `any` type -- kinda works like pre-rewrite. contains 32-byte internal buffer to store SAA types without additional heap allocations,\n\ttypes larger than 32-bytes get heap-allocated.\n- add `typeid()` to deal with the `any` types.\n\n\n---\n### 2018-06-10 `(8ab9dad)`\n- finally add the check for accessing `refcount` when the pointer is `null`; now we return `0` instead of crashing.\n\n\n---\n### 2018-06-10 `(8d9c0d2)`\n- fix a bug where we added generic versions for operators twice. (this caused an assertion to fire)\n\n\n---\n### 2018-06-10 `(aa8f9a9)`\n- fixed a bug wrt. passing generic stuff to generic functions -- now we check only for a subset of the generic stack instead of the whole thing\n\twhen checking for existing stuff.\n\n\n---\n### 2018-06-08 `(e530c81)`\n- remove mpfr from our code\n\n\n---\n### 2018-06-03 `(ef6326c)`\n- actually fix the bug. we were previously *moving out* of arrays in a destructuring binding, which is definitely not what we want.\n\tnow we increment the refcount before passing it off to the binding, so we don't prematurely free.\n\n\n---\n### 2018-06-03 `(4d0aa96)`\n- fix a massive design flaw wrt. arrays -- they now no longer modify the refcount of their elements. only when they are completely freed,\n\tthen we run a decrement loop (once!) over the elements.\n- this should fix the linux crash as well. note: classes test fails, so we've turned that off for now.\n\n\n---\n### 2018-06-03 `(c060a50)`\n- fix a recursion bug with checking for placeholders\n- fix a bug where we would try to do implicit field access on non-field stuff -- set a flag during typechecking so we know.\n- add more tests.\n\n\n---\n### 2018-06-02 `(a86608b)`\n- fix a parsing bug involving closing braces and namespaces.\n\n\n---\n### 2018-06-02 `(e35c883)`\n- still no iterative solver, but made the error output slightly better.\n- also, if we're assigning the result to something with a concrete type, allow the inference thing to work with that\n\tinformation as well.\n\n\n---\n### 2018-05-31 `(dbc7cd2)`\n- pretty much complete implementation of the generic type solver for arbitrary levels of nesting.\n- one final detail is the lack of the iterative solver; that's trivial though and i'll do that on the weekend.\n\n\n---\n### 2018-05-28 `(1e41f88)`\n- fix a couple of bugs relating to SAA types and their refouncting pointers\n- fix a thing where single-expr functions weren't handling `doBlockEndThings` properly.\n- start drilling holes for the generic inference stuff\n\n\n---\n### 2018-05-27 `(337a6a5)`\n- eliminate `exitless_error`, and made everything that used to use it use our new error system.\n\n\n---\n### 2018-05-27 `(e479ba2)`\n- overhaul the error output system for non-trivial cases (it's awesome), remove `HighlightOptions` because we now have `SpanError`.\n- make osx travis use `tester.flx` so we stop having the CI say failed.\n\n\n---\n### 2018-05-27 `(6385652)`\n- sort the candidates by line number, and don't print too many of the fake margin/gutter things.\n- change typecache (thanks adrian) to be better.\n\n\n---\n### 2018-05-27 `(ce9f113)`\n- magnificently beautiful and informative errors for function call overload failure.\n\n\n---\n### 2018-05-18 `(80d5297)`\n- fix a couple of unrelated bugs\n- varidic arrays are now slice-based instead of dynarray-based\n- variadic functions work, mostly. not thoroughly tested (nothing ever is)\n\n\n---\n### 2018-05-03 `(65b25b3)`\n- parse the variadic type as `[T: ...]`\n- allow `[as T: x, y, ... z]` syntax for specifying explicitly that the element type should be `T`.\n\n\n---\n### 2018-05-03 `(25dadf0)`\n- remove `char` type; everything is now `i8`, and `isCharType()` just checks if its an `i8`\n- constructor syntax for builtin types, and strings from slices and/or ptr+data\n- fix a couple of mutability bugs here and there with the new gluecode.\n\n\n---\n### 2018-05-01 `(f3a06c3)`\n- actually add the instructions and stuff, fix a couple of bugs\n- `fir::ConstantString` is now actually a slice.\n- move as many of the dynamic array stuff to the new `SAA` functions as possible.\n- increase length when appending\n\n\n---\n### 2018-05-01 `(0ceb391)`\n- strings now behave like dynamic arrays\n- new concept of `SAA`, string-array-analogues (for now just strings and arrays lol) that have the `{ ptr, len, cap, refptr }` pattern.\n\n\n---\n### 2018-04-30 `(312b94a)`\n- check generic things when looking for duplicate definitions (to the best of our abilities)\n- actually make generic constructors work properly instead of by random chance\n\n\n---\n### 2018-04-30 `(1734444)`\n- generic functions work\n- made error reporting slightly better, though now it becames a little messy.\n\n\n---\n### 2018-04-20 `(c911408)`\n- actually make generic types work, because we never tested them properly last time.\n- fixed a bug in `pts::NamedType` that didn't take the generic mapping into account -- also fixed related issue in the parser\n\n\n---\n### 2018-04-20 `(860b61e)`\n- move to a `TCResult` thing for typechecking returns, cleans up generic types a bunch\n- fix a bug where we couldn't define generic types inside of a scope (eg. in a function)\n\n\n---\n### 2018-04-14 `(1b85906)`\n- make init methods always mutable, for obvious reasons. Also, virtual stuff still works and didn't break, which is a plus.\n\n\n---\n### 2018-04-14 `(7107d5e)`\n- remove all code with side effects (mostly `eat()` stuff in the parser) from within asserts.\n\n\n---\n### 2018-04-14 `(e9ebbb0)`\n- fix type-printing for the new array syntax (finally)\n- string literals now have a type of `[char:]`, with the appropriate implicit casts in place from `string` and to `&i8`\n- add implicit casting for tuple types if their elements can also be implicitly casted (trivial)\n- fix an issue re: constant slices in the llvm translator backend (everything was null)\n- distinguish appending and construct-from-two-ing for strings in the runtime-glue-code; will probably use `realloc` to implement mutating via append for\n\tstrings once we get the shitty refcount madness sorted out.\n\n\n---\n### 2018-04-09 `(81a0eb7)`\n- add `[mut T:]` syntax for specifying mutable slices; otherwise they will be immutable. If using type inference, then they'll be inferred depending on\n\twhat is sliced.\n\n\n---\n### 2018-04-08 `(f824a97)`\n- overhaul the mutability system to be similar to Rust; now, pointers can indicate whether the memory they point to is mutable, and `let` vs `var` only\n\tdetermines whether the variable itself can be modified. Use `&mut T` for the new thing.\n- allow `mut` to be used with methods; if it is present, then a mutable `self` is passed in, otherwise an immutable `self` is passed.\n- add casting to `mut`: `foo as mut` or `foo as !mut` to cast an immutable pointer/slice to a mutable one, and vice versa.\n- distinguish mutable and non-mutable slices, some rules about which things become mutable when sliced and which don't.\n\n\n---\n### 2018-04-07 `(ec9adb2)`\n- add generic types for structs -- presumably works for classes and stuff as well.\n- fix bug where we couldn't do methods in structs.\n- fix bug where we treated variable declarations inside method bodies as field declarations\n- fix bug where we were infinite-looping on method/field stuff on structs\n\n\n---\n### 2018-03-05 `(d9133a8)`\n- change type syntax to be `[T]` for dynamic arrays, `[T:]` for slices, and `[T: N]` for fixed arrays\n- change strings to return `[char:]` instead of making a copy of the string. This allows mutation... at your own risk (for literal strings??)\n- add `str` as an alias for the aforementioned `[char:]`\n\n\n---\n### 2018-03-04 `(b48e10f)`\n- change `alloc` syntax to be like this: `alloc TYPE (ARGS...) [N, M, ...] { BODY }`, where, importantly, `BODY` is code that will be run on each element in\n\tthe allocated array, with bindings `it` (mutable, for obvious reasons), and `i` (immutable, again obviously) representing the current element and the index\n\trespectively.\n- unfortunately what we said about how `&T[]` parses was completely wrong; it parses as `&(T[])` instead.\n\n\n---\n### 2018-02-27 `(b89aa2c)`\n- fix how we did refcounts for arrays; instead of being 8 bytes behind the data pointer like we were doing for strings, they're now just stored in a separate\n\tpointer in the dynamic array struct itself. added code in appropriate places to detect null-ness of this pointer, as well as allocating + freeing it\n\tappropriately.\n- add for loops with tuple destructuring (in theory arbitrary destructuring, since we use the existing framework for such things).\n- add iteration count binding for for-loops; `for (a, b), it in foo { it == 1, 2, ... }`\n\n\n---\n### 2018-02-19 `(3eb36eb)`\n- fix the completely uncaught disaster of mismatched comparison ops in binary arithmetic\n- fix bug where we were double-offsetting the indices in insertvalue and extractvalue (for classes)\n- fix certain cases in codegen where our `TypeDefn` wasn't code-generated yet, leading to a whole host of failures. // ! STILL NOT ROBUST\n- fix typo in operator for division, causing it not to work properly (typoed `-` instead of `/`)\n- change pointer syntax to use `&T` vs `T*`. fyi, `&T[]` parses intuitively as `(&T)[]`; use `&(T[])` to get `T[]*` of old\n- change syntax of `alloc` (some time ago actually) to allow passing arguments to constructors; new syntax is `alloc(T, arg1, arg2, ...) [N1, N2, ...]`\n\n\n---\n### 2018-02-19 `(6dc5ed5)`\n- fix the behaviour of foreach loops such that they don't unnecessarily make values (and in the case of classes, call the constructor) for the loop variable\n\n\n---\n### 2018-02-19 `(f7568e9)`\n- add dynamic dispatch for virtual methods (WOO)\n- probably fix some low-key bugs somewhere\n\n\n---\n### 2018-02-19 `(7268a2c)`\n- enforce calling superclass constructor (via `init(...) : super(...)`) in class constructor definitions\n- fix semantics, by calling superclass inline-init function in derived-class inline-init function\n- refactor code internally to pull stuff out more.\n\n\n---\n### 2018-02-17 `(ba4de52)`\n- re-worked method detection (whether we're in a method or a normal function) to handle the edge case of nested function defs (specifically in a method)\n- make base-class declarations visible in derived classes, including via implicit-self\n- method hiding detection -- it is illegal to have a method in a derived class with the same signature as a method in the base class (without virtual)\n\n\n---\n### 2018-02-15 `(e885c8f)`\n- fix regression wrt. scoping and telporting in dot-ops (ref `rants.md` dated 30/11/17)\n\n\n---\n### 2018-02-11 `(c94a6c1)`\n- add `using ENUM as X`, where `X` can also be `_`.\n\n\n---\n### 2018-02-11 `(8123b13)`\n- add `using X as _` that works like import -- it copies the entities in `X` to the current scope.\n\n\n---\n### 2018-02-11 `(1830146)`\n- add `using X as Y` (but where `Y` currently cannot be `_`, and `X` must be a namespace of some kind)\n\n\n---\n### 2018-02-10 `(23b51a5)`\n- fix edge cases in dot operator, where `Some_Namespace.1234` would just typecheck 'correctly' and return `1234` as the value; we now report an error.\n\n\n---\n### 2018-01-28 `(00586be)`\n- add barebones inheritance on classes. Barebones-ness is explained in `rants.md`\n\n\n---\n### 2018-01-21 `(f7a72b6)`\n- fix variable decompositions\n- enable the decomposition test we had.\n- disable searching beyond the current scope when resolving definitions, if we already found at least one thing here. Previous behaviour was wrong, and\n\tscrewed up shadowing things (would complain about ambiguous references, since we searched further up than we should've)\n\n\n---\n### 2018-01-21 `(1be1271)`\n- fix emitting `bool` in IR that was never caught because we never had a function taking `bool` args, thus we never mangled it.\n- add class constructors; all arguments must be named, and can only call declared init functions.\n\n\n---\n### 2018-01-20 `(c6a204a)`\n- add order-independent type usage, a-la functions. This allows `A` to refer to `B` and `A` to simultaneously refer to `B`.\n- fix detection (rather add it) of recursive definitions, eg. `struct A { var x: A }`, or `struct A { var x: B }; struct B { var x: A }`\n- add `sizeof` operator\n\n\n---\n### 2018-01-19 `(b7fb307)`\n- add static fields in classes, with working initialisers\n\n\n---\n### 2018-01-14 `(81faedb)`\n- add error backtrace, but at a great cost...\n\n\n---\n### 2018-01-14 `(b4dabf6)`\n- add splatting for single values, to fill up single-level tuple destructures, eg. `let (a, b) = ...10; a == b == 10`\n\n\n---\n### 2018-01-14 `(597b1f2)`\n- add array and tuple decomposition, and allow them to nest to arbitrarily ridiculous levels.\n\n\n---\n### 2018-01-14 `(f8d983c)`\n- allow assignment to tuples containing lvalues, to enable the tuple-swap idiom eg. `(a, b) = (b, a)`\n\n\n---\n### 2018-01-13 `(e91b4a2)`\n- add splatting of tuples in function calls; can have multiple tuples\n\n\n---\n### 2018-01-12 `(9e3356d)`\n- improve robustness by making range literals `(X...Y)` parse as binary operators instead of hacky postfix unary ops.\n\n\n---\n### 2018-01-07`(7cb117f)`\n- fix a bug that prevented parsing of function types taking 0 parameters, ie. `() -> T`\n\n\n---\n### 2018-01-07`(4eaae34)`\n- fix custom unary operators for certain cases (`@` was not being done properly, amongst other things)\n\n\n---\n### 2018-01-07 `(d06e235)`\n- add named arguments for all function calls, including methods, but excluding fn-pointer calls\n\n\n---\n### 2018-01-07 `(d0f8c93)`\n- fix some bugs re: the previous commit.\n\n\n---\n### 2018-01-06 `(ec728cd)`\n- add constructor syntax for types (as previously discussed), where you can do some fields with names, or all fields positionally.\n\n\n---\n### 2018-01-06 `(ec7b2f3)`\n- fix false assertion (assert index > 0) for InsertValue by index in FIR. Index can obviously be 0 for the first element.\n\n\n---\n### 2017-12-31 `(3add15b)`\n- fix implicit casting arguments to overloaded operators\n- add ability to overload unicode symbols as operators\n\n\n---\n### 2017-12-31 `(d2f8dbd)`\n- add ability to overload prefix operators\n- internally, move Operator to be a string type to make our lives easier with overloading.\n\n\n---\n### 2017-12-31 `(dcc28ba)`\n- fix member access on structs that were passed as arguments (ie. 'did not have pointer' -- solved by using ExtractValue in such cases)\n- fix method calling (same thing as above) -- but this time we need to use ImmutAlloc, because we need a `this` pointer\n- add basic operator overloading for binary, non-assigment operators.\n\n\n---\n### 2017-12-29 `(45e818e)`\n- check for, and error on, duplicate module imports.\n\n\n---\n### 2017-12-17 `(5a9aa9e)`\n- add deferred statements and blocks\n\n\n---\n### 2017-12-16 `(80a6619)`\n- add single-expression functions with `fn foo(a: T) -> T => a * 2`\n\n\n---\n### 2017-12-10 `(3b438c2)`\n- add support for reverse ranges (negative steps, start > end)\n\n\n---\n### 2017-12-10 `(f3f8dbb)`\n- add ranges\n- add foreach loops on ranges, arrays, and strings\n- add '=>' syntax for single-statement blocks, eg. `if x == 0 => x += 4`\n\n\n---\n### 2017-12-08 `(dacc809)`\n- fix lexing/parsing of negative numerical literals\n\n\n---\n### 2017-12-07 `(ca3ae4b)`\n- better type inference/support for empty array literals\n- implicit conversion from pointers to booleans for null checking\n\n\n---\n### 2017-12-03 `(5be4db1)`\n- fix runtime glue code for arrays wrt. reference counting\n\n\n---\n### 2017-12-02 `(e3a2b55)`\n- add alloc and dealloc\n- add dynamic array operators (`pop()`, `back()`)\n\n\n---\n### 2017-11-19 `(b7c6f74)`\n- add enums\n\n\n---\n### 2017-10-22 `(408260c)`\n- add classes\n\n\n"
  },
  {
    "path": "external/mpreal/mpreal.h",
    "content": "/*\n\tMPFR C++: Multi-precision floating point number class for C++.\n\tBased on MPFR library:    http://mpfr.org\n\n\tProject homepage:    http://www.holoborodko.com/pavel/mpfr\n\tContact e-mail:      pavel@holoborodko.com\n\n\tCopyright (c) 2008-2015 Pavel Holoborodko\n\n\tContributors:\n\tDmitriy Gubanov, Konstantin Holoborodko, Brian Gladman,\n\tHelmut Jarausch, Fokko Beekhof, Ulrich Mutze, Heinz van Saanen,\n\tPere Constans, Peter van Hoof, Gael Guennebaud, Tsai Chia Cheng,\n\tAlexei Zubanov, Jauhien Piatlicki, Victor Berger, John Westwood,\n\tPetr Aleksandrov, Orion Poplawski, Charles Karney, Arash Partow,\n\tRodney James, Jorge Leitao.\n\n\tLicensing:\n\t(A) MPFR C++ is under GNU General Public License (\"GPL\").\n\n\t(B) Non-free licenses may also be purchased from the author, for users who\n\t\tdo not want their programs protected by the GPL.\n\n\t\tThe non-free licenses are for users that wish to use MPFR C++ in\n\t\ttheir products but are unwilling to release their software\n\t\tunder the GPL (which would require them to release source code\n\t\tand allow free redistribution).\n\n\t\tSuch users can purchase an unlimited-use license from the author.\n\t\tContact us for more details.\n\n\tGNU General Public License (\"GPL\") copyright permissions statement:\n\t**************************************************************************\n\tThis program is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tThis program is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\tGNU General Public License for more details.\n\n\tYou should have received a copy of the GNU General Public License\n\talong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef __MPREAL_H__\n#define __MPREAL_H__\n\n#include <string>\n#include <iostream>\n#include <sstream>\n#include <stdexcept>\n#include <cfloat>\n#include <cmath>\n#include <cstring>\n#include <limits>\n#include <cstdint>\n#include <complex>\n#include <algorithm>\n\n// Options\n#define MPREAL_HAVE_MSVC_DEBUGVIEW              // Enable Debugger Visualizer for \"Debug\" builds in MSVC.\n#define MPREAL_HAVE_DYNAMIC_STD_NUMERIC_LIMITS  // Enable extended std::numeric_limits<mpfr::mpreal> specialization.\n\t\t\t\t\t\t\t\t\t\t\t\t// Meaning that \"digits\", \"round_style\" and similar members are defined as functions, not constants.\n\t\t\t\t\t\t\t\t\t\t\t\t// See std::numeric_limits<mpfr::mpreal> at the end of the file for more information.\n\n// Library version\n#define MPREAL_VERSION_MAJOR 3\n#define MPREAL_VERSION_MINOR 6\n#define MPREAL_VERSION_PATCHLEVEL 2\n#define MPREAL_VERSION_STRING \"3.6.2\"\n\n\n// disable deprecated warnings for mpfr.\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n\t#pragma warning(disable: 4996)\n#else\n\t#pragma GCC diagnostic push\n\t#pragma GCC diagnostic ignored \"-Wdeprecated-declarations\"\n\t#pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#endif\n\n\n\n// Detect compiler using signatures from http://predef.sourceforge.net/\n#if defined(__GNUC__) && defined(__INTEL_COMPILER)\n\t#define IsInf(x) isinf(x)                   // Intel ICC compiler on Linux\n\n#elif defined(_MSC_VER)                         // Microsoft Visual C++\n\t#define IsInf(x) (!_finite(x))\n\n#else\n\t#define IsInf(x) std::isinf(x)              // GNU C/C++ (and/or other compilers), just hope for C99 conformance\n#endif\n\n// A Clang feature extension to determine compiler features.\n#ifndef __has_feature\n\t#define __has_feature(x) 0\n#endif\n\n// Detect support for r-value references (move semantic). Borrowed from Eigen.\n#if (__has_feature(cxx_rvalue_references) || \\\n\t   defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L || \\\n\t  (defined(_MSC_VER) && _MSC_VER >= 1600))\n\n\t#define MPREAL_HAVE_MOVE_SUPPORT\n\n\t// Use fields in mpfr_t structure to check if it was initialized / set dummy initialization\n\t#define mpfr_is_initialized(x)      (0 != (x)->_mpfr_d)\n\t#define mpfr_set_uninitialized(x)   ((x)->_mpfr_d = 0 )\n#endif\n\n// Detect support for explicit converters.\n#if (__has_feature(cxx_explicit_conversions) || \\\n\t   (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC_MINOR >= 5) || __cplusplus >= 201103L || \\\n\t   (defined(_MSC_VER) && _MSC_VER >= 1800))\n\n\t#define MPREAL_HAVE_EXPLICIT_CONVERTERS\n#endif\n\n#define MPFR_USE_INTMAX_T   // Enable 64-bit integer types - should be defined before mpfr.h\n\n#if defined(MPREAL_HAVE_MSVC_DEBUGVIEW) && defined(_MSC_VER) && defined(_DEBUG)\n\t#define MPREAL_MSVC_DEBUGVIEW_CODE     DebugView = toString();\n\t#define MPREAL_MSVC_DEBUGVIEW_DATA     std::string DebugView;\n#else\n\t#define MPREAL_MSVC_DEBUGVIEW_CODE\n\t#define MPREAL_MSVC_DEBUGVIEW_DATA\n#endif\n\n\n#include <mpfr.h>\n\n\n\n\n#if (MPFR_VERSION < MPFR_VERSION_NUM(3,0,0))\n\t#include <cstdlib>                          // Needed for random()\n#endif\n\n// Less important options\n#define MPREAL_DOUBLE_BITS_OVERFLOW (-1)        // Triggers overflow exception during conversion to double if mpreal\n\t\t\t\t\t\t\t\t\t\t\t\t// cannot fit in MPREAL_DOUBLE_BITS_OVERFLOW bits\n\t\t\t\t\t\t\t\t\t\t\t\t// = -1 disables overflow checks (default)\n\n// Fast replacement for mpfr_set_zero(x, +1):\n// (a) uses low-level data members, might not be compatible with new versions of MPFR\n// (b) sign is not set, add (x)->_mpfr_sign = 1;\n#define mpfr_set_zero_fast(x)  ((x)->_mpfr_exp = __MPFR_EXP_ZERO)\n\n#if defined(__GNUC__)\n  #define MPREAL_PERMISSIVE_EXPR __extension__\n#else\n  #define MPREAL_PERMISSIVE_EXPR\n#endif\n\nnamespace mpfr {\n\nclass mpreal {\nprivate:\n\tmpfr_t mp;\n\npublic:\n\n\t// Get default rounding mode & precision\n\tinline static mp_rnd_t   get_default_rnd()    {    return (mp_rnd_t)(mpfr_get_default_rounding_mode());       }\n\tinline static mp_prec_t  get_default_prec()   {    return mpfr_get_default_prec();                            }\n\n\t// Constructors && type conversions\n\tmpreal();\n\tmpreal(const mpreal& u);\n\tmpreal(const mpf_t u);\n\tmpreal(const mpz_t u,                  mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());\n\tmpreal(const mpq_t u,                  mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());\n\tmpreal(const double u,                 mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());\n\tmpreal(const long double u,            mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());\n\tmpreal(const unsigned long long int u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());\n\tmpreal(const long long int u,          mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());\n\tmpreal(const unsigned long int u,      mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());\n\tmpreal(const unsigned int u,           mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());\n\tmpreal(const long int u,               mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());\n\tmpreal(const int u,                    mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd());\n\n\t// Construct mpreal from mpfr_t structure.\n\t// shared = true allows to avoid deep copy, so that mpreal and 'u' share the same data & pointers.\n\tmpreal(const mpfr_t  u, bool shared = false);\n\n\tmpreal(const char* s,             mp_prec_t prec = mpreal::get_default_prec(), int base = 10, mp_rnd_t mode = mpreal::get_default_rnd());\n\tmpreal(const std::string& s,      mp_prec_t prec = mpreal::get_default_prec(), int base = 10, mp_rnd_t mode = mpreal::get_default_rnd());\n\n\t~mpreal();\n\n#ifdef MPREAL_HAVE_MOVE_SUPPORT\n\tmpreal& operator=(mpreal&& v) noexcept;\n\tmpreal(mpreal&& u) noexcept;\n#endif\n\n\t// Operations\n\t// =\n\t// +, -, *, /, ++, --, <<, >>\n\t// *=, +=, -=, /=,\n\t// <, >, ==, <=, >=\n\n\t// =\n\tmpreal& operator=(const mpreal& v);\n\tmpreal& operator=(const mpf_t v);\n\tmpreal& operator=(const mpz_t v);\n\tmpreal& operator=(const mpq_t v);\n\tmpreal& operator=(const long double v);\n\tmpreal& operator=(const double v);\n\tmpreal& operator=(const unsigned long int v);\n\tmpreal& operator=(const unsigned long long int v);\n\tmpreal& operator=(const long long int v);\n\tmpreal& operator=(const unsigned int v);\n\tmpreal& operator=(const long int v);\n\tmpreal& operator=(const int v);\n\tmpreal& operator=(const char* s);\n\tmpreal& operator=(const std::string& s);\n\ttemplate <typename real_t> mpreal& operator= (const std::complex<real_t>& z);\n\n\t// +\n\tmpreal& operator+=(const mpreal& v);\n\tmpreal& operator+=(const mpf_t v);\n\tmpreal& operator+=(const mpz_t v);\n\tmpreal& operator+=(const mpq_t v);\n\tmpreal& operator+=(const long double u);\n\tmpreal& operator+=(const double u);\n\tmpreal& operator+=(const unsigned long int u);\n\tmpreal& operator+=(const unsigned int u);\n\tmpreal& operator+=(const long int u);\n\tmpreal& operator+=(const int u);\n\n\tmpreal& operator+=(const long long int  u);\n\tmpreal& operator+=(const unsigned long long int u);\n\tmpreal& operator-=(const long long int  u);\n\tmpreal& operator-=(const unsigned long long int u);\n\tmpreal& operator*=(const long long int  u);\n\tmpreal& operator*=(const unsigned long long int u);\n\tmpreal& operator/=(const long long int  u);\n\tmpreal& operator/=(const unsigned long long int u);\n\n\tconst mpreal operator+() const;\n\tmpreal& operator++ ();\n\tconst mpreal  operator++ (int);\n\n\t// -\n\tmpreal& operator-=(const mpreal& v);\n\tmpreal& operator-=(const mpz_t v);\n\tmpreal& operator-=(const mpq_t v);\n\tmpreal& operator-=(const long double u);\n\tmpreal& operator-=(const double u);\n\tmpreal& operator-=(const unsigned long int u);\n\tmpreal& operator-=(const unsigned int u);\n\tmpreal& operator-=(const long int u);\n\tmpreal& operator-=(const int u);\n\tconst mpreal operator-() const;\n\tfriend const mpreal operator-(const unsigned long int b, const mpreal& a);\n\tfriend const mpreal operator-(const unsigned int b,      const mpreal& a);\n\tfriend const mpreal operator-(const long int b,          const mpreal& a);\n\tfriend const mpreal operator-(const int b,               const mpreal& a);\n\tfriend const mpreal operator-(const double b,            const mpreal& a);\n\tmpreal& operator-- ();\n\tconst mpreal  operator-- (int);\n\n\t// *\n\tmpreal& operator*=(const mpreal& v);\n\tmpreal& operator*=(const mpz_t v);\n\tmpreal& operator*=(const mpq_t v);\n\tmpreal& operator*=(const long double v);\n\tmpreal& operator*=(const double v);\n\tmpreal& operator*=(const unsigned long int v);\n\tmpreal& operator*=(const unsigned int v);\n\tmpreal& operator*=(const long int v);\n\tmpreal& operator*=(const int v);\n\n\t// /\n\tmpreal& operator/=(const mpreal& v);\n\tmpreal& operator/=(const mpz_t v);\n\tmpreal& operator/=(const mpq_t v);\n\tmpreal& operator/=(const long double v);\n\tmpreal& operator/=(const double v);\n\tmpreal& operator/=(const unsigned long int v);\n\tmpreal& operator/=(const unsigned int v);\n\tmpreal& operator/=(const long int v);\n\tmpreal& operator/=(const int v);\n\tfriend const mpreal operator/(const unsigned long int b, const mpreal& a);\n\tfriend const mpreal operator/(const unsigned int b,      const mpreal& a);\n\tfriend const mpreal operator/(const long int b,          const mpreal& a);\n\tfriend const mpreal operator/(const int b,               const mpreal& a);\n\tfriend const mpreal operator/(const double b,            const mpreal& a);\n\n\t//<<= Fast Multiplication by 2^u\n\tmpreal& operator<<=(const unsigned long int u);\n\tmpreal& operator<<=(const unsigned int u);\n\tmpreal& operator<<=(const long int u);\n\tmpreal& operator<<=(const int u);\n\n\t//>>= Fast Division by 2^u\n\tmpreal& operator>>=(const unsigned long int u);\n\tmpreal& operator>>=(const unsigned int u);\n\tmpreal& operator>>=(const long int u);\n\tmpreal& operator>>=(const int u);\n\n\t// Type Conversion operators\n\tbool               toBool      (                        )    const;\n\tlong               toLong      (mp_rnd_t mode = GMP_RNDZ)    const;\n\tunsigned long      toULong     (mp_rnd_t mode = GMP_RNDZ)    const;\n\tlong long          toLLong     (mp_rnd_t mode = GMP_RNDZ)    const;\n\tunsigned long long toULLong    (mp_rnd_t mode = GMP_RNDZ)    const;\n\tfloat              toFloat     (mp_rnd_t mode = GMP_RNDN)    const;\n\tdouble             toDouble    (mp_rnd_t mode = GMP_RNDN)    const;\n\tlong double        toLDouble   (mp_rnd_t mode = GMP_RNDN)    const;\n\n#if defined (MPREAL_HAVE_EXPLICIT_CONVERTERS)\n\texplicit operator bool               () const { return toBool();                 }\n\texplicit operator int                () const { return int(toLong());            }\n\texplicit operator long               () const { return toLong();                 }\n\texplicit operator long long          () const { return toLLong();                }\n\texplicit operator unsigned           () const { return unsigned(toULong());      }\n\texplicit operator unsigned long      () const { return toULong();                }\n\texplicit operator unsigned long long () const { return toULLong();               }\n\texplicit operator float              () const { return toFloat();                }\n\texplicit operator double             () const { return toDouble();               }\n\texplicit operator long double        () const { return toLDouble();              }\n#endif\n\n\t// Get raw pointers so that mpreal can be directly used in raw mpfr_* functions\n\t::mpfr_ptr    mpfr_ptr();\n\t::mpfr_srcptr mpfr_ptr()    const;\n\t::mpfr_srcptr mpfr_srcptr() const;\n\n\t// Convert mpreal to string with n significant digits in base b\n\t// n = -1 -> convert with the maximum available digits\n\tstd::string toString(int n = -1, int b = 10, mp_rnd_t mode = mpreal::get_default_rnd()) const;\n\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))\n\tstd::string toString(const std::string& format) const;\n#endif\n\n\tstd::ostream& output(std::ostream& os) const;\n\n\t// Math Functions\n\tfriend const mpreal sqr (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal sqrt(const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal sqrt(const unsigned long int v, mp_rnd_t rnd_mode);\n\tfriend const mpreal cbrt(const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal root(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode);\n\tfriend const mpreal pow (const mpreal& a, const mpreal& b, mp_rnd_t rnd_mode);\n\tfriend const mpreal pow (const mpreal& a, const mpz_t b, mp_rnd_t rnd_mode);\n\tfriend const mpreal pow (const mpreal& a, const unsigned long int b, mp_rnd_t rnd_mode);\n\tfriend const mpreal pow (const mpreal& a, const long int b, mp_rnd_t rnd_mode);\n\tfriend const mpreal pow (const unsigned long int a, const mpreal& b, mp_rnd_t rnd_mode);\n\tfriend const mpreal pow (const unsigned long int a, const unsigned long int b, mp_rnd_t rnd_mode);\n\tfriend const mpreal fabs(const mpreal& v, mp_rnd_t rnd_mode);\n\n\tfriend const mpreal abs(const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal dim(const mpreal& a, const mpreal& b, mp_rnd_t rnd_mode);\n\tfriend inline const mpreal mul_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode);\n\tfriend inline const mpreal mul_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode);\n\tfriend inline const mpreal div_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode);\n\tfriend inline const mpreal div_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode);\n\tfriend int cmpabs(const mpreal& a,const mpreal& b);\n\n\tfriend const mpreal log  (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal log2 (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal logb (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal log10(const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal exp  (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal exp2 (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal exp10(const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal log1p(const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal expm1(const mpreal& v, mp_rnd_t rnd_mode);\n\n\tfriend const mpreal cos(const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal sin(const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal tan(const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal sec(const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal csc(const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal cot(const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend int sin_cos(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode);\n\n\tfriend const mpreal acos  (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal asin  (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal atan  (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal atan2 (const mpreal& y, const mpreal& x, mp_rnd_t rnd_mode);\n\tfriend const mpreal acot  (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal asec  (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal acsc  (const mpreal& v, mp_rnd_t rnd_mode);\n\n\tfriend const mpreal cosh  (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal sinh  (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal tanh  (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal sech  (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal csch  (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal coth  (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal acosh (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal asinh (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal atanh (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal acoth (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal asech (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal acsch (const mpreal& v, mp_rnd_t rnd_mode);\n\n\tfriend const mpreal hypot (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode);\n\n\tfriend const mpreal fac_ui (unsigned long int v,  mp_prec_t prec, mp_rnd_t rnd_mode);\n\tfriend const mpreal eint   (const mpreal& v, mp_rnd_t rnd_mode);\n\n\tfriend const mpreal gamma    (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal tgamma   (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal lngamma  (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal lgamma   (const mpreal& v, int *signp, mp_rnd_t rnd_mode);\n\tfriend const mpreal zeta     (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal erf      (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal erfc     (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal besselj0 (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal besselj1 (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal besseljn (long n, const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal bessely0 (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal bessely1 (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal besselyn (long n, const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal fma      (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode);\n\tfriend const mpreal fms      (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode);\n\tfriend const mpreal agm      (const mpreal& v1, const mpreal& v2, mp_rnd_t rnd_mode);\n\tfriend const mpreal sum      (const mpreal tab[], const unsigned long int n, int& status, mp_rnd_t rnd_mode);\n\tfriend int sgn(const mpreal& v); // returns -1 or +1\n\n// MPFR 2.4.0 Specifics\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))\n\tfriend int          sinh_cosh   (mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal li2         (const mpreal& v,                       mp_rnd_t rnd_mode);\n\tfriend const mpreal fmod        (const mpreal& x, const mpreal& y,      mp_rnd_t rnd_mode);\n\tfriend const mpreal rec_sqrt    (const mpreal& v,                       mp_rnd_t rnd_mode);\n\n\t// MATLAB's semantic equivalents\n\tfriend const mpreal rem (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode); // Remainder after division\n\tfriend const mpreal mod (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode); // Modulus after division\n#endif\n\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))\n\tfriend const mpreal digamma (const mpreal& v,        mp_rnd_t rnd_mode);\n\tfriend const mpreal ai      (const mpreal& v,        mp_rnd_t rnd_mode);\n\tfriend const mpreal urandom (gmp_randstate_t& state, mp_rnd_t rnd_mode);     // use gmp_randinit_default() to init state, gmp_randclear() to clear\n#endif\n\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,1,0))\n\tfriend const mpreal grandom (gmp_randstate_t& state, mp_rnd_t rnd_mode);     // use gmp_randinit_default() to init state, gmp_randclear() to clear\n\tfriend const mpreal grandom (unsigned int seed);\n#endif\n\n\t// Uniformly distributed random number generation in [0,1] using\n\t// Mersenne-Twister algorithm by default.\n\t// Use parameter to setup seed, e.g.: random((unsigned)time(NULL))\n\t// Check urandom() for more precise control.\n\tfriend const mpreal random(unsigned int seed);\n\n\t// Exponent and mantissa manipulation\n\tfriend const mpreal frexp (const mpreal& v, mp_exp_t* exp);\n\tfriend const mpreal ldexp (const mpreal& v, mp_exp_t exp);\n\tfriend const mpreal scalbn(const mpreal& v, mp_exp_t exp);\n\n\t// Splits mpreal value into fractional and integer parts.\n\t// Returns fractional part and stores integer part in n.\n\tfriend const mpreal modf(const mpreal& v, mpreal& n);\n\n\t// Constants\n\t// don't forget to call mpfr_free_cache() for every thread where you are using const-functions\n\tfriend const mpreal const_log2      (mp_prec_t prec, mp_rnd_t rnd_mode);\n\tfriend const mpreal const_pi        (mp_prec_t prec, mp_rnd_t rnd_mode);\n\tfriend const mpreal const_euler     (mp_prec_t prec, mp_rnd_t rnd_mode);\n\tfriend const mpreal const_catalan   (mp_prec_t prec, mp_rnd_t rnd_mode);\n\n\t// returns +inf iff sign>=0 otherwise -inf\n\tfriend const mpreal const_infinity(int sign, mp_prec_t prec);\n\n\t// Output/ Input\n\tfriend std::ostream& operator<<(std::ostream& os, const mpreal& v);\n\tfriend std::istream& operator>>(std::istream& is, mpreal& v);\n\n\t// Integer Related Functions\n\tfriend const mpreal rint (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal ceil (const mpreal& v);\n\tfriend const mpreal floor(const mpreal& v);\n\tfriend const mpreal round(const mpreal& v);\n\tfriend const mpreal trunc(const mpreal& v);\n\tfriend const mpreal rint_ceil   (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal rint_floor  (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal rint_round  (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal rint_trunc  (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal frac        (const mpreal& v, mp_rnd_t rnd_mode);\n\tfriend const mpreal remainder   (         const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode);\n\tfriend const mpreal remquo      (long* q, const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode);\n\n\t// Miscellaneous Functions\n\tfriend const mpreal nexttoward (const mpreal& x, const mpreal& y);\n\tfriend const mpreal nextabove  (const mpreal& x);\n\tfriend const mpreal nextbelow  (const mpreal& x);\n\n\t// use gmp_randinit_default() to init state, gmp_randclear() to clear\n\tfriend const mpreal urandomb (gmp_randstate_t& state);\n\n// MPFR < 2.4.2 Specifics\n#if (MPFR_VERSION <= MPFR_VERSION_NUM(2,4,2))\n\tfriend const mpreal random2 (mp_size_t size, mp_exp_t exp);\n#endif\n\n\t// Instance Checkers\n\tfriend bool isnan    (const mpreal& v);\n\tfriend bool isinf    (const mpreal& v);\n\tfriend bool isfinite (const mpreal& v);\n\n\tfriend bool isnum    (const mpreal& v);\n\tfriend bool iszero   (const mpreal& v);\n\tfriend bool isint    (const mpreal& v);\n\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))\n\tfriend bool isregular(const mpreal& v);\n#endif\n\n\t// Set/Get instance properties\n\tinline mp_prec_t    get_prec() const;\n\tinline void         set_prec(mp_prec_t prec, mp_rnd_t rnd_mode = get_default_rnd());    // Change precision with rounding mode\n\n\t// Aliases for get_prec(), set_prec() - needed for compatibility with std::complex<mpreal> interface\n\tinline mpreal&      setPrecision(int Precision, mp_rnd_t RoundingMode = get_default_rnd());\n\tinline int          getPrecision() const;\n\n\t// Set mpreal to +/- inf, NaN, +/-0\n\tmpreal&        setInf  (int Sign = +1);\n\tmpreal&        setNan  ();\n\tmpreal&        setZero (int Sign = +1);\n\tmpreal&        setSign (int Sign, mp_rnd_t RoundingMode = get_default_rnd());\n\n\t//Exponent\n\tmp_exp_t get_exp();\n\tint set_exp(mp_exp_t e);\n\tint check_range  (int t, mp_rnd_t rnd_mode = get_default_rnd());\n\tint subnormalize (int t, mp_rnd_t rnd_mode = get_default_rnd());\n\n\t// Inexact conversion from float\n\tinline bool fits_in_bits(double x, int n);\n\n\t// Set/Get global properties\n\tstatic void            set_default_prec(mp_prec_t prec);\n\tstatic void            set_default_rnd(mp_rnd_t rnd_mode);\n\n\tstatic mp_exp_t  get_emin (void);\n\tstatic mp_exp_t  get_emax (void);\n\tstatic mp_exp_t  get_emin_min (void);\n\tstatic mp_exp_t  get_emin_max (void);\n\tstatic mp_exp_t  get_emax_min (void);\n\tstatic mp_exp_t  get_emax_max (void);\n\tstatic int       set_emin (mp_exp_t exp);\n\tstatic int       set_emax (mp_exp_t exp);\n\n\t// Efficient swapping of two mpreal values - needed for std algorithms\n\tfriend void swap(mpreal& x, mpreal& y);\n\n\tfriend const mpreal fmax(const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode);\n\tfriend const mpreal fmin(const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode);\n\nprivate:\n\t// Human friendly Debug Preview in Visual Studio.\n\t// Put one of these lines:\n\t//\n\t// mpfr::mpreal=<DebugView>                              ; Show value only\n\t// mpfr::mpreal=<DebugView>, <mp[0]._mpfr_prec,u>bits    ; Show value & precision\n\t//\n\t// at the beginning of\n\t// [Visual Studio Installation Folder]\\Common7\\Packages\\Debugger\\autoexp.dat\n\tMPREAL_MSVC_DEBUGVIEW_DATA\n\n\t// \"Smart\" resources deallocation. Checks if instance initialized before deletion.\n\tvoid clear(::mpfr_ptr);\n};\n\n//////////////////////////////////////////////////////////////////////////\n// Exceptions\nclass conversion_overflow : public std::exception {\npublic:\n\tstd::string why() { return \"inexact conversion from floating point\"; }\n};\n\n//////////////////////////////////////////////////////////////////////////\n// Constructors & converters\n// Default constructor: creates mp number and initializes it to 0.\ninline mpreal::mpreal()\n{\n\tmpfr_init2(mpfr_ptr(), mpreal::get_default_prec());\n\tmpfr_set_zero_fast(mpfr_ptr());\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n}\n\ninline mpreal::mpreal(const mpreal& u)\n{\n\tmpfr_init2(mpfr_ptr(),mpfr_get_prec(u.mpfr_srcptr()));\n\tmpfr_set  (mpfr_ptr(),u.mpfr_srcptr(),mpreal::get_default_rnd());\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n}\n\n#ifdef MPREAL_HAVE_MOVE_SUPPORT\ninline mpreal::mpreal(mpreal&& other) noexcept\n{\n\tmpfr_set_uninitialized(mpfr_ptr());     // make sure \"other\" holds no pointer to actual data\n\tmpfr_swap(mpfr_ptr(), other.mpfr_ptr());\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n}\n\ninline mpreal& mpreal::operator=(mpreal&& other) noexcept\n{\n\tmpfr_swap(mpfr_ptr(), other.mpfr_ptr());\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n#endif\n\ninline mpreal::mpreal(const mpfr_t  u, bool shared)\n{\n\tif(shared)\n\t{\n\t\tstd::memcpy(mpfr_ptr(), u, sizeof(mpfr_t));\n\t}\n\telse\n\t{\n\t\tmpfr_init2(mpfr_ptr(), mpfr_get_prec(u));\n\t\tmpfr_set  (mpfr_ptr(), u, mpreal::get_default_rnd());\n\t}\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n}\n\ninline mpreal::mpreal(const mpf_t u)\n{\n\tmpfr_init2(mpfr_ptr(),(mp_prec_t) mpf_get_prec(u)); // (gmp: mp_bitcnt_t) unsigned long -> long (mpfr: mp_prec_t)\n\tmpfr_set_f(mpfr_ptr(),u,mpreal::get_default_rnd());\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n}\n\ninline mpreal::mpreal(const mpz_t u, mp_prec_t prec, mp_rnd_t mode)\n{\n\tmpfr_init2(mpfr_ptr(), prec);\n\tmpfr_set_z(mpfr_ptr(), u, mode);\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n}\n\ninline mpreal::mpreal(const mpq_t u, mp_prec_t prec, mp_rnd_t mode)\n{\n\tmpfr_init2(mpfr_ptr(), prec);\n\tmpfr_set_q(mpfr_ptr(), u, mode);\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n}\n\ninline mpreal::mpreal(const double u, mp_prec_t prec, mp_rnd_t mode)\n{\n\t mpfr_init2(mpfr_ptr(), prec);\n\n#if (MPREAL_DOUBLE_BITS_OVERFLOW > -1)\n\tif(fits_in_bits(u, MPREAL_DOUBLE_BITS_OVERFLOW))\n\t{\n\t\tmpfr_set_d(mpfr_ptr(), u, mode);\n\t}else\n\t\tthrow conversion_overflow();\n#else\n\tmpfr_set_d(mpfr_ptr(), u, mode);\n#endif\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n}\n\ninline mpreal::mpreal(const long double u, mp_prec_t prec, mp_rnd_t mode)\n{\n\tmpfr_init2 (mpfr_ptr(), prec);\n\tmpfr_set_ld(mpfr_ptr(), u, mode);\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n}\n\ninline mpreal::mpreal(const unsigned long long int u, mp_prec_t prec, mp_rnd_t mode)\n{\n\tmpfr_init2 (mpfr_ptr(), prec);\n\tmpfr_set_uj(mpfr_ptr(), u, mode);\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n}\n\ninline mpreal::mpreal(const long long int u, mp_prec_t prec, mp_rnd_t mode)\n{\n\tmpfr_init2 (mpfr_ptr(), prec);\n\tmpfr_set_sj(mpfr_ptr(), u, mode);\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n}\n\ninline mpreal::mpreal(const unsigned long int u, mp_prec_t prec, mp_rnd_t mode)\n{\n\tmpfr_init2 (mpfr_ptr(), prec);\n\tmpfr_set_ui(mpfr_ptr(), u, mode);\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n}\n\ninline mpreal::mpreal(const unsigned int u, mp_prec_t prec, mp_rnd_t mode)\n{\n\tmpfr_init2 (mpfr_ptr(), prec);\n\tmpfr_set_ui(mpfr_ptr(), u, mode);\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n}\n\ninline mpreal::mpreal(const long int u, mp_prec_t prec, mp_rnd_t mode)\n{\n\tmpfr_init2 (mpfr_ptr(), prec);\n\tmpfr_set_si(mpfr_ptr(), u, mode);\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n}\n\ninline mpreal::mpreal(const int u, mp_prec_t prec, mp_rnd_t mode)\n{\n\tmpfr_init2 (mpfr_ptr(), prec);\n\tmpfr_set_si(mpfr_ptr(), u, mode);\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n}\n\ninline mpreal::mpreal(const char* s, mp_prec_t prec, int base, mp_rnd_t mode)\n{\n\tmpfr_init2  (mpfr_ptr(), prec);\n\tmpfr_set_str(mpfr_ptr(), s, base, mode);\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n}\n\ninline mpreal::mpreal(const std::string& s, mp_prec_t prec, int base, mp_rnd_t mode)\n{\n\tmpfr_init2  (mpfr_ptr(), prec);\n\tmpfr_set_str(mpfr_ptr(), s.c_str(), base, mode);\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n}\n\ninline void mpreal::clear(::mpfr_ptr x)\n{\n#ifdef MPREAL_HAVE_MOVE_SUPPORT\n\tif(mpfr_is_initialized(x))\n#endif\n\tmpfr_clear(x);\n}\n\ninline mpreal::~mpreal()\n{\n\tclear(mpfr_ptr());\n}\n\n// internal namespace needed for template magic\nnamespace internal{\n\n\t// Use SFINAE to restrict arithmetic operations instantiation only for numeric types\n\t// This is needed for smooth integration with libraries based on expression templates, like Eigen.\n\t// TODO: Do the same for boolean operators.\n\ttemplate <typename ArgumentType> struct result_type {};\n\n\ttemplate <> struct result_type<mpreal>              {typedef mpreal type;};\n\ttemplate <> struct result_type<mpz_t>               {typedef mpreal type;};\n\ttemplate <> struct result_type<mpq_t>               {typedef mpreal type;};\n\ttemplate <> struct result_type<long double>         {typedef mpreal type;};\n\ttemplate <> struct result_type<double>              {typedef mpreal type;};\n\ttemplate <> struct result_type<unsigned long int>   {typedef mpreal type;};\n\ttemplate <> struct result_type<unsigned int>        {typedef mpreal type;};\n\ttemplate <> struct result_type<long int>            {typedef mpreal type;};\n\ttemplate <> struct result_type<int>                 {typedef mpreal type;};\n\ttemplate <> struct result_type<long long>           {typedef mpreal type;};\n\ttemplate <> struct result_type<unsigned long long>  {typedef mpreal type;};\n}\n\n// + Addition\ntemplate <typename Rhs>\ninline const typename internal::result_type<Rhs>::type\n\toperator+(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) += rhs;    }\n\ntemplate <typename Lhs>\ninline const typename internal::result_type<Lhs>::type\n\toperator+(const Lhs& lhs, const mpreal& rhs){ return mpreal(rhs) += lhs;    }\n\n// - Subtraction\ntemplate <typename Rhs>\ninline const typename internal::result_type<Rhs>::type\n\toperator-(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) -= rhs;    }\n\ntemplate <typename Lhs>\ninline const typename internal::result_type<Lhs>::type\n\toperator-(const Lhs& lhs, const mpreal& rhs){ return mpreal(lhs) -= rhs;    }\n\n// * Multiplication\ntemplate <typename Rhs>\ninline const typename internal::result_type<Rhs>::type\n\toperator*(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) *= rhs;    }\n\ntemplate <typename Lhs>\ninline const typename internal::result_type<Lhs>::type\n\toperator*(const Lhs& lhs, const mpreal& rhs){ return mpreal(rhs) *= lhs;    }\n\n// / Division\ntemplate <typename Rhs>\ninline const typename internal::result_type<Rhs>::type\n\toperator/(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) /= rhs;    }\n\ntemplate <typename Lhs>\ninline const typename internal::result_type<Lhs>::type\n\toperator/(const Lhs& lhs, const mpreal& rhs){ return mpreal(lhs) /= rhs;    }\n\n//////////////////////////////////////////////////////////////////////////\n// sqrt\nconst mpreal sqrt(const unsigned int v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal sqrt(const long int v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal sqrt(const int v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal sqrt(const long double v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal sqrt(const double v, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\n\n// abs\ninline const mpreal abs(const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd());\n\n//////////////////////////////////////////////////////////////////////////\n// pow\nconst mpreal pow(const mpreal& a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const mpreal& a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const mpreal& a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const mpreal& a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\n\nconst mpreal pow(const unsigned int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const long int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const long double a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const double a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\n\nconst mpreal pow(const unsigned long int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const unsigned long int a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const unsigned long int a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const unsigned long int a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const unsigned long int a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\n\nconst mpreal pow(const unsigned int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const unsigned int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const unsigned int a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const unsigned int a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const unsigned int a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const unsigned int a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\n\nconst mpreal pow(const long int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const long int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const long int a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const long int a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const long int a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const long int a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\n\nconst mpreal pow(const int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const int a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const int a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const int a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const int a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\n\nconst mpreal pow(const long double a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const long double a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const long double a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const long double a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const long double a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\n\nconst mpreal pow(const double a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const double a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const double a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const double a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\nconst mpreal pow(const double a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\n\ninline const mpreal mul_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\ninline const mpreal mul_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\ninline const mpreal div_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\ninline const mpreal div_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode = mpreal::get_default_rnd());\n\n//////////////////////////////////////////////////////////////////////////\n// Estimate machine epsilon for the given precision\n// Returns smallest eps such that 1.0 + eps != 1.0\ninline mpreal machine_epsilon(mp_prec_t prec = mpreal::get_default_prec());\n\n// Returns smallest eps such that x + eps != x (relative machine epsilon)\ninline mpreal machine_epsilon(const mpreal& x);\n\n// Gives max & min values for the required precision,\n// minval is 'safe' meaning 1 / minval does not overflow\n// maxval is 'safe' meaning 1 / maxval does not underflow\ninline mpreal minval(mp_prec_t prec = mpreal::get_default_prec());\ninline mpreal maxval(mp_prec_t prec = mpreal::get_default_prec());\n\n// 'Dirty' equality check 1: |a-b| < min{|a|,|b|} * eps\ninline bool isEqualFuzzy(const mpreal& a, const mpreal& b, const mpreal& eps);\n\n// 'Dirty' equality check 2: |a-b| < min{|a|,|b|} * eps( min{|a|,|b|} )\ninline bool isEqualFuzzy(const mpreal& a, const mpreal& b);\n\n// 'Bitwise' equality check\n//  maxUlps - a and b can be apart by maxUlps binary numbers.\ninline bool isEqualUlps(const mpreal& a, const mpreal& b, int maxUlps);\n\n//////////////////////////////////////////////////////////////////////////\n// Convert precision in 'bits' to decimal digits and vice versa.\n//    bits   = ceil(digits*log[2](10))\n//    digits = floor(bits*log[10](2))\n\ninline mp_prec_t digits2bits(int d);\ninline int       bits2digits(mp_prec_t b);\n\n//////////////////////////////////////////////////////////////////////////\n// min, max\nconst mpreal (max)(const mpreal& x, const mpreal& y);\nconst mpreal (min)(const mpreal& x, const mpreal& y);\n\n//////////////////////////////////////////////////////////////////////////\n// Implementation\n//////////////////////////////////////////////////////////////////////////\n\n//////////////////////////////////////////////////////////////////////////\n// Operators - Assignment\ninline mpreal& mpreal::operator=(const mpreal& v)\n{\n\tif (this != &v)\n\t{\n\t\tmp_prec_t tp = mpfr_get_prec(  mpfr_srcptr());\n\t\tmp_prec_t vp = mpfr_get_prec(v.mpfr_srcptr());\n\n\t\tif(tp != vp){\n\t\t\tclear(mpfr_ptr());\n\t\t\tmpfr_init2(mpfr_ptr(), vp);\n\t\t}\n\n\t\tmpfr_set(mpfr_ptr(), v.mpfr_srcptr(), mpreal::get_default_rnd());\n\n\t\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\t}\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator=(const mpf_t v)\n{\n\tmpfr_set_f(mpfr_ptr(), v, mpreal::get_default_rnd());\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator=(const mpz_t v)\n{\n\tmpfr_set_z(mpfr_ptr(), v, mpreal::get_default_rnd());\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator=(const mpq_t v)\n{\n\tmpfr_set_q(mpfr_ptr(), v, mpreal::get_default_rnd());\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator=(const long double v)\n{\n\tmpfr_set_ld(mpfr_ptr(), v, mpreal::get_default_rnd());\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator=(const double v)\n{\n#if (MPREAL_DOUBLE_BITS_OVERFLOW > -1)\n\tif(fits_in_bits(v, MPREAL_DOUBLE_BITS_OVERFLOW))\n\t{\n\t\tmpfr_set_d(mpfr_ptr(),v,mpreal::get_default_rnd());\n\t}else\n\t\tthrow conversion_overflow();\n#else\n\tmpfr_set_d(mpfr_ptr(),v,mpreal::get_default_rnd());\n#endif\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator=(const unsigned long int v)\n{\n\tmpfr_set_ui(mpfr_ptr(), v, mpreal::get_default_rnd());\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator=(const unsigned int v)\n{\n\tmpfr_set_ui(mpfr_ptr(), v, mpreal::get_default_rnd());\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator=(const unsigned long long int v)\n{\n\tmpfr_set_uj(mpfr_ptr(), v, mpreal::get_default_rnd());\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator=(const long long int v)\n{\n\tmpfr_set_sj(mpfr_ptr(), v, mpreal::get_default_rnd());\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator=(const long int v)\n{\n\tmpfr_set_si(mpfr_ptr(), v, mpreal::get_default_rnd());\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator=(const int v)\n{\n\tmpfr_set_si(mpfr_ptr(), v, mpreal::get_default_rnd());\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator=(const char* s)\n{\n\t// Use other converters for more precise control on base & precision & rounding:\n\t//\n\t//        mpreal(const char* s,        mp_prec_t prec, int base, mp_rnd_t mode)\n\t//        mpreal(const std::string& s,mp_prec_t prec, int base, mp_rnd_t mode)\n\t//\n\t// Here we assume base = 10 and we use precision of target variable.\n\n\tmpfr_t t;\n\n\tmpfr_init2(t, mpfr_get_prec(mpfr_srcptr()));\n\n\tif(0 == mpfr_set_str(t, s, 10, mpreal::get_default_rnd()))\n\t{\n\t\tmpfr_set(mpfr_ptr(), t, mpreal::get_default_rnd());\n\t\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\t}\n\n\tclear(t);\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator=(const std::string& s)\n{\n\t// Use other converters for more precise control on base & precision & rounding:\n\t//\n\t//        mpreal(const char* s,        mp_prec_t prec, int base, mp_rnd_t mode)\n\t//        mpreal(const std::string& s,mp_prec_t prec, int base, mp_rnd_t mode)\n\t//\n\t// Here we assume base = 10 and we use precision of target variable.\n\n\tmpfr_t t;\n\n\tmpfr_init2(t, mpfr_get_prec(mpfr_srcptr()));\n\n\tif(0 == mpfr_set_str(t, s.c_str(), 10, mpreal::get_default_rnd()))\n\t{\n\t\tmpfr_set(mpfr_ptr(), t, mpreal::get_default_rnd());\n\t\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\t}\n\n\tclear(t);\n\treturn *this;\n}\n\ntemplate <typename real_t>\ninline mpreal& mpreal::operator= (const std::complex<real_t>& z)\n{\n\t*this = z.real();\n\treturn *this;\n}\n\n//////////////////////////////////////////////////////////////////////////\n// + Addition\ninline mpreal& mpreal::operator+=(const mpreal& v)\n{\n\tmpfr_add(mpfr_ptr(), mpfr_srcptr(), v.mpfr_srcptr(), mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator+=(const mpf_t u)\n{\n\t*this += mpreal(u);\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator+=(const mpz_t u)\n{\n\tmpfr_add_z(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator+=(const mpq_t u)\n{\n\tmpfr_add_q(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator+= (const long double u)\n{\n\t*this += mpreal(u);\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator+= (const double u)\n{\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))\n\tmpfr_add_d(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());\n#else\n\t*this += mpreal(u);\n#endif\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator+=(const unsigned long int u)\n{\n\tmpfr_add_ui(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator+=(const unsigned int u)\n{\n\tmpfr_add_ui(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator+=(const long int u)\n{\n\tmpfr_add_si(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator+=(const int u)\n{\n\tmpfr_add_si(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator+=(const long long int u)         {    *this += mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this;    }\ninline mpreal& mpreal::operator+=(const unsigned long long int u){    *this += mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this;    }\ninline mpreal& mpreal::operator-=(const long long int  u)        {    *this -= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this;    }\ninline mpreal& mpreal::operator-=(const unsigned long long int u){    *this -= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this;    }\ninline mpreal& mpreal::operator*=(const long long int  u)        {    *this *= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this;    }\ninline mpreal& mpreal::operator*=(const unsigned long long int u){    *this *= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this;    }\ninline mpreal& mpreal::operator/=(const long long int  u)        {    *this /= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this;    }\ninline mpreal& mpreal::operator/=(const unsigned long long int u){    *this /= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this;    }\n\ninline const mpreal mpreal::operator+()const    {    return mpreal(*this); }\n\ninline const mpreal operator+(const mpreal& a, const mpreal& b)\n{\n\tmpreal c(0, (std::max)(mpfr_get_prec(a.mpfr_ptr()), mpfr_get_prec(b.mpfr_ptr())));\n\tmpfr_add(c.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), mpreal::get_default_rnd());\n\treturn c;\n}\n\ninline mpreal& mpreal::operator++()\n{\n\treturn *this += 1;\n}\n\ninline const mpreal mpreal::operator++ (int)\n{\n\tmpreal x(*this);\n\t*this += 1;\n\treturn x;\n}\n\ninline mpreal& mpreal::operator--()\n{\n\treturn *this -= 1;\n}\n\ninline const mpreal mpreal::operator-- (int)\n{\n\tmpreal x(*this);\n\t*this -= 1;\n\treturn x;\n}\n\n//////////////////////////////////////////////////////////////////////////\n// - Subtraction\ninline mpreal& mpreal::operator-=(const mpreal& v)\n{\n\tmpfr_sub(mpfr_ptr(),mpfr_srcptr(),v.mpfr_srcptr(),mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator-=(const mpz_t v)\n{\n\tmpfr_sub_z(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator-=(const mpq_t v)\n{\n\tmpfr_sub_q(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator-=(const long double v)\n{\n\t*this -= mpreal(v);\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator-=(const double v)\n{\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))\n\tmpfr_sub_d(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n#else\n\t*this -= mpreal(v);\n#endif\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator-=(const unsigned long int v)\n{\n\tmpfr_sub_ui(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator-=(const unsigned int v)\n{\n\tmpfr_sub_ui(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator-=(const long int v)\n{\n\tmpfr_sub_si(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator-=(const int v)\n{\n\tmpfr_sub_si(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline const mpreal mpreal::operator-()const\n{\n\tmpreal u(*this);\n\tmpfr_neg(u.mpfr_ptr(),u.mpfr_srcptr(),mpreal::get_default_rnd());\n\treturn u;\n}\n\ninline const mpreal operator-(const mpreal& a, const mpreal& b)\n{\n\tmpreal c(0, (std::max)(mpfr_get_prec(a.mpfr_ptr()), mpfr_get_prec(b.mpfr_ptr())));\n\tmpfr_sub(c.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), mpreal::get_default_rnd());\n\treturn c;\n}\n\ninline const mpreal operator-(const double  b, const mpreal& a)\n{\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))\n\tmpreal x(0, mpfr_get_prec(a.mpfr_ptr()));\n\tmpfr_d_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());\n\treturn x;\n#else\n\tmpreal x(b, mpfr_get_prec(a.mpfr_ptr()));\n\tx -= a;\n\treturn x;\n#endif\n}\n\ninline const mpreal operator-(const unsigned long int b, const mpreal& a)\n{\n\tmpreal x(0, mpfr_get_prec(a.mpfr_ptr()));\n\tmpfr_ui_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());\n\treturn x;\n}\n\ninline const mpreal operator-(const unsigned int b, const mpreal& a)\n{\n\tmpreal x(0, mpfr_get_prec(a.mpfr_ptr()));\n\tmpfr_ui_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());\n\treturn x;\n}\n\ninline const mpreal operator-(const long int b, const mpreal& a)\n{\n\tmpreal x(0, mpfr_get_prec(a.mpfr_ptr()));\n\tmpfr_si_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());\n\treturn x;\n}\n\ninline const mpreal operator-(const int b, const mpreal& a)\n{\n\tmpreal x(0, mpfr_get_prec(a.mpfr_ptr()));\n\tmpfr_si_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());\n\treturn x;\n}\n\n//////////////////////////////////////////////////////////////////////////\n// * Multiplication\ninline mpreal& mpreal::operator*= (const mpreal& v)\n{\n\tmpfr_mul(mpfr_ptr(),mpfr_srcptr(),v.mpfr_srcptr(),mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator*=(const mpz_t v)\n{\n\tmpfr_mul_z(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator*=(const mpq_t v)\n{\n\tmpfr_mul_q(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator*=(const long double v)\n{\n\t*this *= mpreal(v);\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator*=(const double v)\n{\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))\n\tmpfr_mul_d(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n#else\n\t*this *= mpreal(v);\n#endif\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator*=(const unsigned long int v)\n{\n\tmpfr_mul_ui(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator*=(const unsigned int v)\n{\n\tmpfr_mul_ui(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator*=(const long int v)\n{\n\tmpfr_mul_si(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator*=(const int v)\n{\n\tmpfr_mul_si(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline const mpreal operator*(const mpreal& a, const mpreal& b)\n{\n\tmpreal c(0, (std::max)(mpfr_get_prec(a.mpfr_ptr()), mpfr_get_prec(b.mpfr_ptr())));\n\tmpfr_mul(c.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), mpreal::get_default_rnd());\n\treturn c;\n}\n\n//////////////////////////////////////////////////////////////////////////\n// / Division\ninline mpreal& mpreal::operator/=(const mpreal& v)\n{\n\tmpfr_div(mpfr_ptr(),mpfr_srcptr(),v.mpfr_srcptr(),mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator/=(const mpz_t v)\n{\n\tmpfr_div_z(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator/=(const mpq_t v)\n{\n\tmpfr_div_q(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator/=(const long double v)\n{\n\t*this /= mpreal(v);\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator/=(const double v)\n{\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))\n\tmpfr_div_d(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n#else\n\t*this /= mpreal(v);\n#endif\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator/=(const unsigned long int v)\n{\n\tmpfr_div_ui(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator/=(const unsigned int v)\n{\n\tmpfr_div_ui(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator/=(const long int v)\n{\n\tmpfr_div_si(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator/=(const int v)\n{\n\tmpfr_div_si(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline const mpreal operator/(const mpreal& a, const mpreal& b)\n{\n\tmpreal c(0, (std::max)(mpfr_get_prec(a.mpfr_srcptr()), mpfr_get_prec(b.mpfr_srcptr())));\n\tmpfr_div(c.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), mpreal::get_default_rnd());\n\treturn c;\n}\n\ninline const mpreal operator/(const unsigned long int b, const mpreal& a)\n{\n\tmpreal x(0, mpfr_get_prec(a.mpfr_srcptr()));\n\tmpfr_ui_div(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());\n\treturn x;\n}\n\ninline const mpreal operator/(const unsigned int b, const mpreal& a)\n{\n\tmpreal x(0, mpfr_get_prec(a.mpfr_srcptr()));\n\tmpfr_ui_div(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());\n\treturn x;\n}\n\ninline const mpreal operator/(const long int b, const mpreal& a)\n{\n\tmpreal x(0, mpfr_get_prec(a.mpfr_srcptr()));\n\tmpfr_si_div(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());\n\treturn x;\n}\n\ninline const mpreal operator/(const int b, const mpreal& a)\n{\n\tmpreal x(0, mpfr_get_prec(a.mpfr_srcptr()));\n\tmpfr_si_div(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());\n\treturn x;\n}\n\ninline const mpreal operator/(const double  b, const mpreal& a)\n{\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))\n\tmpreal x(0, mpfr_get_prec(a.mpfr_srcptr()));\n\tmpfr_d_div(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd());\n\treturn x;\n#else\n\tmpreal x(0, mpfr_get_prec(a.mpfr_ptr()));\n\tx /= a;\n\treturn x;\n#endif\n}\n\n//////////////////////////////////////////////////////////////////////////\n// Shifts operators - Multiplication/Division by power of 2\ninline mpreal& mpreal::operator<<=(const unsigned long int u)\n{\n\tmpfr_mul_2ui(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator<<=(const unsigned int u)\n{\n\tmpfr_mul_2ui(mpfr_ptr(),mpfr_srcptr(),static_cast<unsigned long int>(u),mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator<<=(const long int u)\n{\n\tmpfr_mul_2si(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator<<=(const int u)\n{\n\tmpfr_mul_2si(mpfr_ptr(),mpfr_srcptr(),static_cast<long int>(u),mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator>>=(const unsigned long int u)\n{\n\tmpfr_div_2ui(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator>>=(const unsigned int u)\n{\n\tmpfr_div_2ui(mpfr_ptr(),mpfr_srcptr(),static_cast<unsigned long int>(u),mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator>>=(const long int u)\n{\n\tmpfr_div_2si(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::operator>>=(const int u)\n{\n\tmpfr_div_2si(mpfr_ptr(),mpfr_srcptr(),static_cast<long int>(u),mpreal::get_default_rnd());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline const mpreal operator<<(const mpreal& v, const unsigned long int k)\n{\n\treturn mul_2ui(v,k);\n}\n\ninline const mpreal operator<<(const mpreal& v, const unsigned int k)\n{\n\treturn mul_2ui(v,static_cast<unsigned long int>(k));\n}\n\ninline const mpreal operator<<(const mpreal& v, const long int k)\n{\n\treturn mul_2si(v,k);\n}\n\ninline const mpreal operator<<(const mpreal& v, const int k)\n{\n\treturn mul_2si(v,static_cast<long int>(k));\n}\n\ninline const mpreal operator>>(const mpreal& v, const unsigned long int k)\n{\n\treturn div_2ui(v,k);\n}\n\ninline const mpreal operator>>(const mpreal& v, const long int k)\n{\n\treturn div_2si(v,k);\n}\n\ninline const mpreal operator>>(const mpreal& v, const unsigned int k)\n{\n\treturn div_2ui(v,static_cast<unsigned long int>(k));\n}\n\ninline const mpreal operator>>(const mpreal& v, const int k)\n{\n\treturn div_2si(v,static_cast<long int>(k));\n}\n\n// mul_2ui\ninline const mpreal mul_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode)\n{\n\tmpreal x(v);\n\tmpfr_mul_2ui(x.mpfr_ptr(),v.mpfr_srcptr(),k,rnd_mode);\n\treturn x;\n}\n\n// mul_2si\ninline const mpreal mul_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode)\n{\n\tmpreal x(v);\n\tmpfr_mul_2si(x.mpfr_ptr(),v.mpfr_srcptr(),k,rnd_mode);\n\treturn x;\n}\n\ninline const mpreal div_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode)\n{\n\tmpreal x(v);\n\tmpfr_div_2ui(x.mpfr_ptr(),v.mpfr_srcptr(),k,rnd_mode);\n\treturn x;\n}\n\ninline const mpreal div_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode)\n{\n\tmpreal x(v);\n\tmpfr_div_2si(x.mpfr_ptr(),v.mpfr_srcptr(),k,rnd_mode);\n\treturn x;\n}\n\n//////////////////////////////////////////////////////////////////////////\n//Relational operators\n\n// WARNING:\n//\n// Please note that following checks for double-NaN are guaranteed to work only in IEEE math mode:\n//\n// isnan(b) =  (b != b)\n// isnan(b) = !(b == b)  (we use in code below)\n//\n// Be cautions if you use compiler options which break strict IEEE compliance (e.g. -ffast-math in GCC).\n// Use std::isnan instead (C++11).\n\ninline bool operator >  (const mpreal& a, const mpreal& b           ){  return (mpfr_greater_p(a.mpfr_srcptr(),b.mpfr_srcptr()) != 0 );            }\ninline bool operator >  (const mpreal& a, const unsigned long int b ){  return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) > 0 );                 }\ninline bool operator >  (const mpreal& a, const unsigned int b      ){  return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) > 0 );                 }\ninline bool operator >  (const mpreal& a, const long int b          ){  return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) > 0 );                 }\ninline bool operator >  (const mpreal& a, const int b               ){  return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) > 0 );                 }\ninline bool operator >  (const mpreal& a, const long double b       ){  return !isnan(a) && (b == b) && (mpfr_cmp_ld(a.mpfr_srcptr(),b) > 0 );    }\ninline bool operator >  (const mpreal& a, const double b            ){  return !isnan(a) && (b == b) && (mpfr_cmp_d (a.mpfr_srcptr(),b) > 0 );    }\n\ninline bool operator >= (const mpreal& a, const mpreal& b           ){  return (mpfr_greaterequal_p(a.mpfr_srcptr(),b.mpfr_srcptr()) != 0 );       }\ninline bool operator >= (const mpreal& a, const unsigned long int b ){  return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) >= 0 );                }\ninline bool operator >= (const mpreal& a, const unsigned int b      ){  return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) >= 0 );                }\ninline bool operator >= (const mpreal& a, const long int b          ){  return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) >= 0 );                }\ninline bool operator >= (const mpreal& a, const int b               ){  return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) >= 0 );                }\ninline bool operator >= (const mpreal& a, const long double b       ){  return !isnan(a) && (b == b) && (mpfr_cmp_ld(a.mpfr_srcptr(),b) >= 0 );   }\ninline bool operator >= (const mpreal& a, const double b            ){  return !isnan(a) && (b == b) && (mpfr_cmp_d (a.mpfr_srcptr(),b) >= 0 );   }\n\ninline bool operator <  (const mpreal& a, const mpreal& b           ){  return (mpfr_less_p(a.mpfr_srcptr(),b.mpfr_srcptr()) != 0 );               }\ninline bool operator <  (const mpreal& a, const unsigned long int b ){  return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) < 0 );                 }\ninline bool operator <  (const mpreal& a, const unsigned int b      ){  return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) < 0 );                 }\ninline bool operator <  (const mpreal& a, const long int b          ){  return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) < 0 );                 }\ninline bool operator <  (const mpreal& a, const int b               ){  return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) < 0 );                 }\ninline bool operator <  (const mpreal& a, const long double b       ){  return !isnan(a) && (b == b) && (mpfr_cmp_ld(a.mpfr_srcptr(),b) < 0 );    }\ninline bool operator <  (const mpreal& a, const double b            ){  return !isnan(a) && (b == b) && (mpfr_cmp_d (a.mpfr_srcptr(),b) < 0 );    }\n\ninline bool operator <= (const mpreal& a, const mpreal& b           ){  return (mpfr_lessequal_p(a.mpfr_srcptr(),b.mpfr_srcptr()) != 0 );          }\ninline bool operator <= (const mpreal& a, const unsigned long int b ){  return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) <= 0 );                }\ninline bool operator <= (const mpreal& a, const unsigned int b      ){  return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) <= 0 );                }\ninline bool operator <= (const mpreal& a, const long int b          ){  return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) <= 0 );                }\ninline bool operator <= (const mpreal& a, const int b               ){  return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) <= 0 );                }\ninline bool operator <= (const mpreal& a, const long double b       ){  return !isnan(a) && (b == b) && (mpfr_cmp_ld(a.mpfr_srcptr(),b) <= 0 );   }\ninline bool operator <= (const mpreal& a, const double b            ){  return !isnan(a) && (b == b) && (mpfr_cmp_d (a.mpfr_srcptr(),b) <= 0 );   }\n\ninline bool operator == (const mpreal& a, const mpreal& b           ){  return (mpfr_equal_p(a.mpfr_srcptr(),b.mpfr_srcptr()) != 0 );              }\ninline bool operator == (const mpreal& a, const unsigned long int b ){  return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) == 0 );                }\ninline bool operator == (const mpreal& a, const unsigned int b      ){  return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) == 0 );                }\ninline bool operator == (const mpreal& a, const long int b          ){  return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) == 0 );                }\ninline bool operator == (const mpreal& a, const int b               ){  return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) == 0 );                }\ninline bool operator == (const mpreal& a, const long double b       ){  return !isnan(a) && (b == b) && (mpfr_cmp_ld(a.mpfr_srcptr(),b) == 0 );   }\ninline bool operator == (const mpreal& a, const double b            ){  return !isnan(a) && (b == b) && (mpfr_cmp_d (a.mpfr_srcptr(),b) == 0 );   }\n\ninline bool operator != (const mpreal& a, const mpreal& b           ){  return !(a == b);  }\ninline bool operator != (const mpreal& a, const unsigned long int b ){  return !(a == b);  }\ninline bool operator != (const mpreal& a, const unsigned int b      ){  return !(a == b);  }\ninline bool operator != (const mpreal& a, const long int b          ){  return !(a == b);  }\ninline bool operator != (const mpreal& a, const int b               ){  return !(a == b);  }\ninline bool operator != (const mpreal& a, const long double b       ){  return !(a == b);  }\ninline bool operator != (const mpreal& a, const double b            ){  return !(a == b);  }\n\ninline bool isnan    (const mpreal& op){    return (mpfr_nan_p    (op.mpfr_srcptr()) != 0 );    }\ninline bool isinf    (const mpreal& op){    return (mpfr_inf_p    (op.mpfr_srcptr()) != 0 );    }\ninline bool isfinite (const mpreal& op){    return (mpfr_number_p (op.mpfr_srcptr()) != 0 );    }\ninline bool iszero   (const mpreal& op){    return (mpfr_zero_p   (op.mpfr_srcptr()) != 0 );    }\ninline bool isint    (const mpreal& op){    return (mpfr_integer_p(op.mpfr_srcptr()) != 0 );    }\n\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))\ninline bool isregular(const mpreal& op){    return (mpfr_regular_p(op.mpfr_srcptr()));}\n#endif\n\n//////////////////////////////////////////////////////////////////////////\n// Type Converters\ninline bool               mpreal::toBool   (             )  const    {    return  mpfr_zero_p (mpfr_srcptr()) == 0;     }\ninline long               mpreal::toLong   (mp_rnd_t mode)  const    {    return  mpfr_get_si (mpfr_srcptr(), mode);    }\ninline unsigned long      mpreal::toULong  (mp_rnd_t mode)  const    {    return  mpfr_get_ui (mpfr_srcptr(), mode);    }\ninline float              mpreal::toFloat  (mp_rnd_t mode)  const    {    return  mpfr_get_flt(mpfr_srcptr(), mode);    }\ninline double             mpreal::toDouble (mp_rnd_t mode)  const    {    return  mpfr_get_d  (mpfr_srcptr(), mode);    }\ninline long double        mpreal::toLDouble(mp_rnd_t mode)  const    {    return  mpfr_get_ld (mpfr_srcptr(), mode);    }\ninline long long          mpreal::toLLong  (mp_rnd_t mode)  const    {    return  mpfr_get_sj (mpfr_srcptr(), mode);    }\ninline unsigned long long mpreal::toULLong (mp_rnd_t mode)  const    {    return  mpfr_get_uj (mpfr_srcptr(), mode);    }\n\ninline ::mpfr_ptr     mpreal::mpfr_ptr()             { return mp; }\ninline ::mpfr_srcptr  mpreal::mpfr_ptr()    const    { return mp; }\ninline ::mpfr_srcptr  mpreal::mpfr_srcptr() const    { return mp; }\n\ntemplate <class T>\ninline std::string toString(T t, std::ios_base & (*f)(std::ios_base&))\n{\n\tstd::ostringstream oss;\n\toss << f << t;\n\treturn oss.str();\n}\n\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))\n\ninline std::string mpreal::toString(const std::string& format) const\n{\n\tchar *s = NULL;\n\tstd::string out;\n\n\tif( !format.empty() )\n\t{\n\t\tif(!(mpfr_asprintf(&s, format.c_str(), mpfr_srcptr()) < 0))\n\t\t{\n\t\t\tout = std::string(s);\n\n\t\t\tmpfr_free_str(s);\n\t\t}\n\t}\n\n\treturn out;\n}\n\n#endif\n\ninline std::string mpreal::toString(int n, int b, mp_rnd_t mode) const\n{\n\t// TODO: Add extended format specification (f, e, rounding mode) as it done in output operator\n\t(void)b;\n\t(void)mode;\n\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))\n\n\tstd::ostringstream format;\n\n\tint digits = (n >= 0) ? n : 1 + bits2digits(mpfr_get_prec(mpfr_srcptr()));\n\n\tformat << \"%.\" << digits << \"RNg\";\n\n\treturn toString(format.str());\n\n#else\n\n\tchar *s, *ns = NULL;\n\tsize_t slen, nslen;\n\tmp_exp_t exp;\n\tstd::string out;\n\n\tif(mpfr_inf_p(mp))\n\t{\n\t\tif(mpfr_sgn(mp)>0) return \"+Inf\";\n\t\telse               return \"-Inf\";\n\t}\n\n\tif(mpfr_zero_p(mp)) return \"0\";\n\tif(mpfr_nan_p(mp))  return \"NaN\";\n\n\ts  = mpfr_get_str(NULL, &exp, b, 0, mp, mode);\n\tns = mpfr_get_str(NULL, &exp, b, (std::max)(0,n), mp, mode);\n\n\tif(s!=NULL && ns!=NULL)\n\t{\n\t\tslen  = strlen(s);\n\t\tnslen = strlen(ns);\n\t\tif(nslen<=slen)\n\t\t{\n\t\t\tmpfr_free_str(s);\n\t\t\ts = ns;\n\t\t\tslen = nslen;\n\t\t}\n\t\telse {\n\t\t\tmpfr_free_str(ns);\n\t\t}\n\n\t\t// Make human eye-friendly formatting if possible\n\t\tif (exp>0 && static_cast<size_t>(exp)<slen)\n\t\t{\n\t\t\tif(s[0]=='-')\n\t\t\t{\n\t\t\t\t// Remove zeros starting from right end\n\t\t\t\tchar* ptr = s+slen-1;\n\t\t\t\twhile (*ptr=='0' && ptr>s+exp) ptr--;\n\n\t\t\t\tif(ptr==s+exp) out = std::string(s,exp+1);\n\t\t\t\telse           out = std::string(s,exp+1)+'.'+std::string(s+exp+1,ptr-(s+exp+1)+1);\n\n\t\t\t\t//out = string(s,exp+1)+'.'+string(s+exp+1);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Remove zeros starting from right end\n\t\t\t\tchar* ptr = s+slen-1;\n\t\t\t\twhile (*ptr=='0' && ptr>s+exp-1) ptr--;\n\n\t\t\t\tif(ptr==s+exp-1) out = std::string(s,exp);\n\t\t\t\telse             out = std::string(s,exp)+'.'+std::string(s+exp,ptr-(s+exp)+1);\n\n\t\t\t\t//out = string(s,exp)+'.'+string(s+exp);\n\t\t\t}\n\n\t\t}else{ // exp<0 || exp>slen\n\t\t\tif(s[0]=='-')\n\t\t\t{\n\t\t\t\t// Remove zeros starting from right end\n\t\t\t\tchar* ptr = s+slen-1;\n\t\t\t\twhile (*ptr=='0' && ptr>s+1) ptr--;\n\n\t\t\t\tif(ptr==s+1) out = std::string(s,2);\n\t\t\t\telse         out = std::string(s,2)+'.'+std::string(s+2,ptr-(s+2)+1);\n\n\t\t\t\t//out = string(s,2)+'.'+string(s+2);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Remove zeros starting from right end\n\t\t\t\tchar* ptr = s+slen-1;\n\t\t\t\twhile (*ptr=='0' && ptr>s) ptr--;\n\n\t\t\t\tif(ptr==s) out = std::string(s,1);\n\t\t\t\telse       out = std::string(s,1)+'.'+std::string(s+1,ptr-(s+1)+1);\n\n\t\t\t\t//out = string(s,1)+'.'+string(s+1);\n\t\t\t}\n\n\t\t\t// Make final string\n\t\t\tif(--exp)\n\t\t\t{\n\t\t\t\tif(exp>0) out += \"e+\"+mpfr::toString<mp_exp_t>(exp,std::dec);\n\t\t\t\telse       out += \"e\"+mpfr::toString<mp_exp_t>(exp,std::dec);\n\t\t\t}\n\t\t}\n\n\t\tmpfr_free_str(s);\n\t\treturn out;\n\t}else{\n\t\treturn \"conversion error!\";\n\t}\n#endif\n}\n\n\n//////////////////////////////////////////////////////////////////////////\n// I/O\ninline std::ostream& mpreal::output(std::ostream& os) const\n{\n\tstd::ostringstream format;\n\tconst std::ios::fmtflags flags = os.flags();\n\n\tformat << ((flags & std::ios::showpos) ? \"%+\" : \"%\");\n\tif (os.precision() >= 0)\n\t\tformat << '.' << os.precision() << \"R*\"\n\t\t\t   << ((flags & std::ios::floatfield) == std::ios::fixed ? 'f' :\n\t\t\t\t   (flags & std::ios::floatfield) == std::ios::scientific ? 'e' :\n\t\t\t\t   'g');\n\telse\n\t\tformat << \"R*e\";\n\n\tchar *s = NULL;\n\tif(!(mpfr_asprintf(&s, format.str().c_str(),\n\t\t\t\t\t\tmpfr::mpreal::get_default_rnd(),\n\t\t\t\t\t\tmpfr_srcptr())\n\t\t< 0))\n\t{\n\t\tos << std::string(s);\n\t\tmpfr_free_str(s);\n\t}\n\treturn os;\n}\n\ninline std::ostream& operator<<(std::ostream& os, const mpreal& v)\n{\n\treturn v.output(os);\n}\n\ninline std::istream& operator>>(std::istream &is, mpreal& v)\n{\n\t// TODO: use cout::hexfloat and other flags to setup base\n\tstd::string tmp;\n\tis >> tmp;\n\tmpfr_set_str(v.mpfr_ptr(), tmp.c_str(), 10, mpreal::get_default_rnd());\n\treturn is;\n}\n\n//////////////////////////////////////////////////////////////////////////\n//     Bits - decimal digits relation\n//        bits   = ceil(digits*log[2](10))\n//        digits = floor(bits*log[10](2))\n\ninline mp_prec_t digits2bits(int d)\n{\n\tconst double LOG2_10 = 3.3219280948873624;\n\n\treturn mp_prec_t(std::ceil( d * LOG2_10 ));\n}\n\ninline int bits2digits(mp_prec_t b)\n{\n\tconst double LOG10_2 = 0.30102999566398119;\n\n\treturn int(std::floor( b * LOG10_2 ));\n}\n\n//////////////////////////////////////////////////////////////////////////\n// Set/Get number properties\ninline int sgn(const mpreal& op)\n{\n\treturn mpfr_sgn(op.mpfr_srcptr());\n}\n\ninline mpreal& mpreal::setSign(int sign, mp_rnd_t RoundingMode)\n{\n\tmpfr_setsign(mpfr_ptr(), mpfr_srcptr(), (sign < 0 ? 1 : 0), RoundingMode);\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline int mpreal::getPrecision() const\n{\n\treturn int(mpfr_get_prec(mpfr_srcptr()));\n}\n\ninline mpreal& mpreal::setPrecision(int Precision, mp_rnd_t RoundingMode)\n{\n\tmpfr_prec_round(mpfr_ptr(), Precision, RoundingMode);\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::setInf(int sign)\n{\n\tmpfr_set_inf(mpfr_ptr(), sign);\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::setNan()\n{\n\tmpfr_set_nan(mpfr_ptr());\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mpreal& mpreal::setZero(int sign)\n{\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))\n\tmpfr_set_zero(mpfr_ptr(), sign);\n#else\n\tmpfr_set_si(mpfr_ptr(), 0, (mpfr_get_default_rounding_mode)());\n\tsetSign(sign);\n#endif\n\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn *this;\n}\n\ninline mp_prec_t mpreal::get_prec() const\n{\n\treturn mpfr_get_prec(mpfr_srcptr());\n}\n\ninline void mpreal::set_prec(mp_prec_t prec, mp_rnd_t rnd_mode)\n{\n\tmpfr_prec_round(mpfr_ptr(),prec,rnd_mode);\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n}\n\ninline mp_exp_t mpreal::get_exp ()\n{\n\treturn mpfr_get_exp(mpfr_srcptr());\n}\n\ninline int mpreal::set_exp (mp_exp_t e)\n{\n\tint x = mpfr_set_exp(mpfr_ptr(), e);\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn x;\n}\n\ninline const mpreal frexp(const mpreal& v, mp_exp_t* exp)\n{\n\tmpreal x(v);\n\t*exp = x.get_exp();\n\tx.set_exp(0);\n\treturn x;\n}\n\ninline const mpreal ldexp(const mpreal& v, mp_exp_t exp)\n{\n\tmpreal x(v);\n\n\t// rounding is not important since we are just increasing the exponent (= exact operation)\n\tmpfr_mul_2si(x.mpfr_ptr(), x.mpfr_srcptr(), exp, mpreal::get_default_rnd());\n\treturn x;\n}\n\ninline const mpreal scalbn(const mpreal& v, mp_exp_t exp)\n{\n\treturn ldexp(v, exp);\n}\n\ninline mpreal machine_epsilon(mp_prec_t prec)\n{\n\t/* the smallest eps such that 1 + eps != 1 */\n\treturn machine_epsilon(mpreal(1, prec));\n}\n\ninline mpreal machine_epsilon(const mpreal& x)\n{\n\t/* the smallest eps such that x + eps != x */\n\tif( x < 0)\n\t{\n\t\treturn nextabove(-x) + x;\n\t}else{\n\t\treturn nextabove( x) - x;\n\t}\n}\n\n// minval is 'safe' meaning 1 / minval does not overflow\ninline mpreal minval(mp_prec_t prec)\n{\n\t/* min = 1/2 * 2^emin = 2^(emin - 1) */\n\treturn mpreal(1, prec) << mpreal::get_emin()-1;\n}\n\n// maxval is 'safe' meaning 1 / maxval does not underflow\ninline mpreal maxval(mp_prec_t prec)\n{\n\t/* max = (1 - eps) * 2^emax, eps is machine epsilon */\n\treturn (mpreal(1, prec) - machine_epsilon(prec)) << mpreal::get_emax();\n}\n\ninline bool isEqualUlps(const mpreal& a, const mpreal& b, int maxUlps)\n{\n\treturn abs(a - b) <= machine_epsilon((max)(abs(a), abs(b))) * maxUlps;\n}\n\ninline bool isEqualFuzzy(const mpreal& a, const mpreal& b, const mpreal& eps)\n{\n\treturn abs(a - b) <= eps;\n}\n\ninline bool isEqualFuzzy(const mpreal& a, const mpreal& b)\n{\n\treturn isEqualFuzzy(a, b, machine_epsilon((max)(1, (min)(abs(a), abs(b)))));\n}\n\n//////////////////////////////////////////////////////////////////////////\n// C++11 sign functions.\ninline mpreal copysign(const mpreal& x, const  mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal rop(0, mpfr_get_prec(x.mpfr_ptr()));\n\tmpfr_setsign(rop.mpfr_ptr(), x.mpfr_srcptr(), mpfr_signbit(y.mpfr_srcptr()), rnd_mode);\n\treturn rop;\n}\n\ninline bool signbit(const mpreal& x)\n{\n\treturn mpfr_signbit(x.mpfr_srcptr());\n}\n\ninline const mpreal modf(const mpreal& v, mpreal& n)\n{\n\tmpreal f(v);\n\n\t// rounding is not important since we are using the same number\n\tmpfr_frac (f.mpfr_ptr(),f.mpfr_srcptr(),mpreal::get_default_rnd());\n\tmpfr_trunc(n.mpfr_ptr(),v.mpfr_srcptr());\n\treturn f;\n}\n\ninline int mpreal::check_range (int t, mp_rnd_t rnd_mode)\n{\n\treturn mpfr_check_range(mpfr_ptr(),t,rnd_mode);\n}\n\ninline int mpreal::subnormalize (int t,mp_rnd_t rnd_mode)\n{\n\tint r = mpfr_subnormalize(mpfr_ptr(),t,rnd_mode);\n\tMPREAL_MSVC_DEBUGVIEW_CODE;\n\treturn r;\n}\n\ninline mp_exp_t mpreal::get_emin (void)\n{\n\treturn mpfr_get_emin();\n}\n\ninline int mpreal::set_emin (mp_exp_t exp)\n{\n\treturn mpfr_set_emin(exp);\n}\n\ninline mp_exp_t mpreal::get_emax (void)\n{\n\treturn mpfr_get_emax();\n}\n\ninline int mpreal::set_emax (mp_exp_t exp)\n{\n\treturn mpfr_set_emax(exp);\n}\n\ninline mp_exp_t mpreal::get_emin_min (void)\n{\n\treturn mpfr_get_emin_min();\n}\n\ninline mp_exp_t mpreal::get_emin_max (void)\n{\n\treturn mpfr_get_emin_max();\n}\n\ninline mp_exp_t mpreal::get_emax_min (void)\n{\n\treturn mpfr_get_emax_min();\n}\n\ninline mp_exp_t mpreal::get_emax_max (void)\n{\n\treturn mpfr_get_emax_max();\n}\n\n//////////////////////////////////////////////////////////////////////////\n// Mathematical Functions\n//////////////////////////////////////////////////////////////////////////\n#define MPREAL_UNARY_MATH_FUNCTION_BODY(f)                    \\\n\t\tmpreal y(0, mpfr_get_prec(x.mpfr_srcptr()));          \\\n\t\tmpfr_##f(y.mpfr_ptr(), x.mpfr_srcptr(), r);           \\\n\t\treturn y;\n\ninline const mpreal sqr  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd())\n{   MPREAL_UNARY_MATH_FUNCTION_BODY(sqr );    }\n\ninline const mpreal sqrt (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd())\n{   MPREAL_UNARY_MATH_FUNCTION_BODY(sqrt);    }\n\ninline const mpreal sqrt(const unsigned long int x, mp_rnd_t r)\n{\n\tmpreal y;\n\tmpfr_sqrt_ui(y.mpfr_ptr(), x, r);\n\treturn y;\n}\n\ninline const mpreal sqrt(const unsigned int v, mp_rnd_t rnd_mode)\n{\n\treturn sqrt(static_cast<unsigned long int>(v),rnd_mode);\n}\n\ninline const mpreal sqrt(const long int v, mp_rnd_t rnd_mode)\n{\n\tif (v>=0)   return sqrt(static_cast<unsigned long int>(v),rnd_mode);\n\telse        return mpreal().setNan(); // NaN\n}\n\ninline const mpreal sqrt(const int v, mp_rnd_t rnd_mode)\n{\n\tif (v>=0)   return sqrt(static_cast<unsigned long int>(v),rnd_mode);\n\telse        return mpreal().setNan(); // NaN\n}\n\ninline const mpreal root(const mpreal& x, unsigned long int k, mp_rnd_t r = mpreal::get_default_rnd())\n{\n\tmpreal y(0, mpfr_get_prec(x.mpfr_srcptr()));\n\tmpfr_root(y.mpfr_ptr(), x.mpfr_srcptr(), k, r);\n\treturn y;\n}\n\ninline const mpreal dim(const mpreal& a, const mpreal& b, mp_rnd_t r = mpreal::get_default_rnd())\n{\n\tmpreal y(0, mpfr_get_prec(a.mpfr_srcptr()));\n\tmpfr_dim(y.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), r);\n\treturn y;\n}\n\ninline int cmpabs(const mpreal& a,const mpreal& b)\n{\n\treturn mpfr_cmpabs(a.mpfr_ptr(), b.mpfr_srcptr());\n}\n\ninline int sin_cos(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\treturn mpfr_sin_cos(s.mpfr_ptr(), c.mpfr_ptr(), v.mpfr_srcptr(), rnd_mode);\n}\n\ninline const mpreal sqrt  (const long double v, mp_rnd_t rnd_mode)    {   return sqrt(mpreal(v),rnd_mode);    }\ninline const mpreal sqrt  (const double v, mp_rnd_t rnd_mode)         {   return sqrt(mpreal(v),rnd_mode);    }\n\ninline const mpreal cbrt  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(cbrt );    }\ninline const mpreal fabs  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(abs  );    }\ninline const mpreal abs   (const mpreal& x, mp_rnd_t r)                             {   MPREAL_UNARY_MATH_FUNCTION_BODY(abs  );    }\ninline const mpreal log   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(log  );    }\ninline const mpreal log2  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(log2 );    }\ninline const mpreal log10 (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(log10);    }\ninline const mpreal exp   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(exp  );    }\ninline const mpreal exp2  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(exp2 );    }\ninline const mpreal exp10 (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(exp10);    }\ninline const mpreal cos   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(cos  );    }\ninline const mpreal sin   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(sin  );    }\ninline const mpreal tan   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(tan  );    }\ninline const mpreal sec   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(sec  );    }\ninline const mpreal csc   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(csc  );    }\ninline const mpreal cot   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(cot  );    }\ninline const mpreal acos  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(acos );    }\ninline const mpreal asin  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(asin );    }\ninline const mpreal atan  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(atan );    }\n\ninline const mpreal logb  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   return log2 (abs(x),r);                    }\n\ninline const mpreal acot  (const mpreal& v, mp_rnd_t r = mpreal::get_default_rnd()) {   return atan (1/v, r);                      }\ninline const mpreal asec  (const mpreal& v, mp_rnd_t r = mpreal::get_default_rnd()) {   return acos (1/v, r);                      }\ninline const mpreal acsc  (const mpreal& v, mp_rnd_t r = mpreal::get_default_rnd()) {   return asin (1/v, r);                      }\ninline const mpreal acoth (const mpreal& v, mp_rnd_t r = mpreal::get_default_rnd()) {   return atanh(1/v, r);                      }\ninline const mpreal asech (const mpreal& v, mp_rnd_t r = mpreal::get_default_rnd()) {   return acosh(1/v, r);                      }\ninline const mpreal acsch (const mpreal& v, mp_rnd_t r = mpreal::get_default_rnd()) {   return asinh(1/v, r);                      }\n\ninline const mpreal cosh  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(cosh );    }\ninline const mpreal sinh  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(sinh );    }\ninline const mpreal tanh  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(tanh );    }\ninline const mpreal sech  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(sech );    }\ninline const mpreal csch  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(csch );    }\ninline const mpreal coth  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(coth );    }\ninline const mpreal acosh (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(acosh);    }\ninline const mpreal asinh (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(asinh);    }\ninline const mpreal atanh (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(atanh);    }\n\ninline const mpreal log1p   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(log1p  );    }\ninline const mpreal expm1   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(expm1  );    }\ninline const mpreal eint    (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(eint   );    }\ninline const mpreal gamma   (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(gamma  );    }\ninline const mpreal tgamma  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(gamma  );    }\ninline const mpreal lngamma (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(lngamma);    }\ninline const mpreal zeta    (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(zeta   );    }\ninline const mpreal erf     (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(erf    );    }\ninline const mpreal erfc    (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(erfc   );    }\ninline const mpreal besselj0(const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(j0     );    }\ninline const mpreal besselj1(const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(j1     );    }\ninline const mpreal bessely0(const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(y0     );    }\ninline const mpreal bessely1(const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(y1     );    }\n\ninline const mpreal atan2 (const mpreal& y, const mpreal& x, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal a(0,(std::max)(y.getPrecision(), x.getPrecision()));\n\tmpfr_atan2(a.mpfr_ptr(), y.mpfr_srcptr(), x.mpfr_srcptr(), rnd_mode);\n\treturn a;\n}\n\ninline const mpreal hypot (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal a(0,(std::max)(y.getPrecision(), x.getPrecision()));\n\tmpfr_hypot(a.mpfr_ptr(), x.mpfr_srcptr(), y.mpfr_srcptr(), rnd_mode);\n\treturn a;\n}\n\ninline const mpreal remainder (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal a(0,(std::max)(y.getPrecision(), x.getPrecision()));\n\tmpfr_remainder(a.mpfr_ptr(), x.mpfr_srcptr(), y.mpfr_srcptr(), rnd_mode);\n\treturn a;\n}\n\ninline const mpreal remquo (long* q, const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal a(0,(std::max)(y.getPrecision(), x.getPrecision()));\n\tmpfr_remquo(a.mpfr_ptr(),q, x.mpfr_srcptr(), y.mpfr_srcptr(), rnd_mode);\n\treturn a;\n}\n\ninline const mpreal fac_ui (unsigned long int v, mp_prec_t prec     = mpreal::get_default_prec(),\n\t\t\t\t\t\t\t\t\t\t\t\t mp_rnd_t  rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal x(0, prec);\n\tmpfr_fac_ui(x.mpfr_ptr(),v,rnd_mode);\n\treturn x;\n}\n\n\ninline const mpreal lgamma (const mpreal& v, int *signp = 0, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal x(v);\n\tint tsignp;\n\n\tif(signp)   mpfr_lgamma(x.mpfr_ptr(),  signp,v.mpfr_srcptr(),rnd_mode);\n\telse        mpfr_lgamma(x.mpfr_ptr(),&tsignp,v.mpfr_srcptr(),rnd_mode);\n\n\treturn x;\n}\n\n\ninline const mpreal besseljn (long n, const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd())\n{\n\tmpreal  y(0, x.getPrecision());\n\tmpfr_jn(y.mpfr_ptr(), n, x.mpfr_srcptr(), r);\n\treturn y;\n}\n\ninline const mpreal besselyn (long n, const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd())\n{\n\tmpreal  y(0, x.getPrecision());\n\tmpfr_yn(y.mpfr_ptr(), n, x.mpfr_srcptr(), r);\n\treturn y;\n}\n\ninline const mpreal fma (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal a;\n\tmp_prec_t p1, p2, p3;\n\n\tp1 = v1.get_prec();\n\tp2 = v2.get_prec();\n\tp3 = v3.get_prec();\n\n\ta.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1));\n\n\tmpfr_fma(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode);\n\treturn a;\n}\n\ninline const mpreal fms (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal a;\n\tmp_prec_t p1, p2, p3;\n\n\tp1 = v1.get_prec();\n\tp2 = v2.get_prec();\n\tp3 = v3.get_prec();\n\n\ta.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1));\n\n\tmpfr_fms(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode);\n\treturn a;\n}\n\ninline const mpreal agm (const mpreal& v1, const mpreal& v2, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal a;\n\tmp_prec_t p1, p2;\n\n\tp1 = v1.get_prec();\n\tp2 = v2.get_prec();\n\n\ta.set_prec(p1>p2?p1:p2);\n\n\tmpfr_agm(a.mp, v1.mp, v2.mp, rnd_mode);\n\n\treturn a;\n}\n\ninline const mpreal sum (const mpreal tab[], const unsigned long int n, int& status, mp_rnd_t mode = mpreal::get_default_rnd())\n{\n\tmpfr_srcptr *p = new mpfr_srcptr[n];\n\n\tfor (unsigned long int  i = 0; i < n; i++)\n\t\tp[i] = tab[i].mpfr_srcptr();\n\n\tmpreal x;\n\tstatus = mpfr_sum(x.mpfr_ptr(), (mpfr_ptr*)p, n, mode);\n\n\tdelete [] p;\n\treturn x;\n}\n\n//////////////////////////////////////////////////////////////////////////\n// MPFR 2.4.0 Specifics\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))\n\ninline int sinh_cosh(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\treturn mpfr_sinh_cosh(s.mp,c.mp,v.mp,rnd_mode);\n}\n\ninline const mpreal li2 (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd())\n{\n\tMPREAL_UNARY_MATH_FUNCTION_BODY(li2);\n}\n\ninline const mpreal rem (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\t/*  R = rem(X,Y) if Y != 0, returns X - n * Y where n = trunc(X/Y). */\n\treturn fmod(x, y, rnd_mode);\n}\n\ninline const mpreal mod (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\t(void)rnd_mode;\n\n\t/*\n\n\tm = mod(x,y) if y != 0, returns x - n*y where n = floor(x/y)\n\n\tThe following are true by convention:\n\t- mod(x,0) is x\n\t- mod(x,x) is 0\n\t- mod(x,y) for x != y and y != 0 has the same sign as y.\n\n\t*/\n\n\tif(iszero(y)) return x;\n\tif(x == y) return 0;\n\n\tmpreal m = x - floor(x / y) * y;\n\n\tm.setSign(sgn(y)); // make sure result has the same sign as Y\n\n\treturn m;\n}\n\ninline const mpreal fmod (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal a;\n\tmp_prec_t yp, xp;\n\n\typ = y.get_prec();\n\txp = x.get_prec();\n\n\ta.set_prec(yp>xp?yp:xp);\n\n\tmpfr_fmod(a.mp, x.mp, y.mp, rnd_mode);\n\n\treturn a;\n}\n\ninline const mpreal rec_sqrt(const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal x(v);\n\tmpfr_rec_sqrt(x.mp,v.mp,rnd_mode);\n\treturn x;\n}\n#endif //  MPFR 2.4.0 Specifics\n\n//////////////////////////////////////////////////////////////////////////\n// MPFR 3.0.0 Specifics\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))\ninline const mpreal digamma (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(digamma);     }\ninline const mpreal ai      (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(ai);          }\n#endif // MPFR 3.0.0 Specifics\n\n//////////////////////////////////////////////////////////////////////////\n// Constants\ninline const mpreal const_log2 (mp_prec_t p = mpreal::get_default_prec(), mp_rnd_t r = mpreal::get_default_rnd())\n{\n\tmpreal x(0, p);\n\tmpfr_const_log2(x.mpfr_ptr(), r);\n\treturn x;\n}\n\ninline const mpreal const_pi (mp_prec_t p = mpreal::get_default_prec(), mp_rnd_t r = mpreal::get_default_rnd())\n{\n\tmpreal x(0, p);\n\tmpfr_const_pi(x.mpfr_ptr(), r);\n\treturn x;\n}\n\ninline const mpreal const_euler (mp_prec_t p = mpreal::get_default_prec(), mp_rnd_t r = mpreal::get_default_rnd())\n{\n\tmpreal x(0, p);\n\tmpfr_const_euler(x.mpfr_ptr(), r);\n\treturn x;\n}\n\ninline const mpreal const_catalan (mp_prec_t p = mpreal::get_default_prec(), mp_rnd_t r = mpreal::get_default_rnd())\n{\n\tmpreal x(0, p);\n\tmpfr_const_catalan(x.mpfr_ptr(), r);\n\treturn x;\n}\n\ninline const mpreal const_infinity (int sign = 1, mp_prec_t p = mpreal::get_default_prec())\n{\n\tmpreal x(0, p);\n\tmpfr_set_inf(x.mpfr_ptr(), sign);\n\treturn x;\n}\n\n//////////////////////////////////////////////////////////////////////////\n// Integer Related Functions\ninline const mpreal ceil(const mpreal& v)\n{\n\tmpreal x(v);\n\tmpfr_ceil(x.mp,v.mp);\n\treturn x;\n}\n\ninline const mpreal floor(const mpreal& v)\n{\n\tmpreal x(v);\n\tmpfr_floor(x.mp,v.mp);\n\treturn x;\n}\n\ninline const mpreal round(const mpreal& v)\n{\n\tmpreal x(v);\n\tmpfr_round(x.mp,v.mp);\n\treturn x;\n}\n\ninline const mpreal trunc(const mpreal& v)\n{\n\tmpreal x(v);\n\tmpfr_trunc(x.mp,v.mp);\n\treturn x;\n}\n\ninline const mpreal rint       (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(rint      );     }\ninline const mpreal rint_ceil  (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(rint_ceil );     }\ninline const mpreal rint_floor (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(rint_floor);     }\ninline const mpreal rint_round (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(rint_round);     }\ninline const mpreal rint_trunc (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(rint_trunc);     }\ninline const mpreal frac       (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) {   MPREAL_UNARY_MATH_FUNCTION_BODY(frac      );     }\n\n//////////////////////////////////////////////////////////////////////////\n// Miscellaneous Functions\ninline void         swap (mpreal& a, mpreal& b)            {    mpfr_swap(a.mp,b.mp);   }\ninline const mpreal (max)(const mpreal& x, const mpreal& y){    return (x>y?x:y);       }\ninline const mpreal (min)(const mpreal& x, const mpreal& y){    return (x<y?x:y);       }\n\ninline const mpreal fmax(const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal a;\n\tmpfr_max(a.mp,x.mp,y.mp,rnd_mode);\n\treturn a;\n}\n\ninline const mpreal fmin(const mpreal& x, const mpreal& y,  mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal a;\n\tmpfr_min(a.mp,x.mp,y.mp,rnd_mode);\n\treturn a;\n}\n\ninline const mpreal nexttoward (const mpreal& x, const mpreal& y)\n{\n\tmpreal a(x);\n\tmpfr_nexttoward(a.mp,y.mp);\n\treturn a;\n}\n\ninline const mpreal nextabove  (const mpreal& x)\n{\n\tmpreal a(x);\n\tmpfr_nextabove(a.mp);\n\treturn a;\n}\n\ninline const mpreal nextbelow  (const mpreal& x)\n{\n\tmpreal a(x);\n\tmpfr_nextbelow(a.mp);\n\treturn a;\n}\n\ninline const mpreal urandomb (gmp_randstate_t& state)\n{\n\tmpreal x;\n\tmpfr_urandomb(x.mpfr_ptr(),state);\n\treturn x;\n}\n\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))\ninline const mpreal urandom (gmp_randstate_t& state, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal x;\n\tmpfr_urandom(x.mpfr_ptr(), state, rnd_mode);\n\treturn x;\n}\n#endif\n\n#if (MPFR_VERSION <= MPFR_VERSION_NUM(2,4,2))\ninline const mpreal random2 (mp_size_t size, mp_exp_t exp)\n{\n\tmpreal x;\n\tmpfr_random2(x.mpfr_ptr(),size,exp);\n\treturn x;\n}\n#endif\n\n// Uniformly distributed random number generation\n// a = random(seed); <- initialization & first random number generation\n// a = random();     <- next random numbers generation\n// seed != 0\ninline const mpreal random(unsigned int seed = 0)\n{\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0))\n\tstatic gmp_randstate_t state;\n\tstatic bool initialize = true;\n\n\tif(initialize)\n\t{\n\t\tgmp_randinit_default(state);\n\t\tgmp_randseed_ui(state,0);\n\t\tinitialize = false;\n\t}\n\n\tif(seed != 0)    gmp_randseed_ui(state,seed);\n\n\treturn mpfr::urandom(state);\n#else\n\tif(seed != 0)    std::srand(seed);\n\treturn mpfr::mpreal(std::rand()/(double)RAND_MAX);\n#endif\n\n}\n\n#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,1,0))\n\ninline const mpreal grandom (gmp_randstate_t& state, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal x;\n\tmpfr_grandom(x.mpfr_ptr(), NULL, state, rnd_mode);\n\treturn x;\n}\n\ninline const mpreal grandom(unsigned int seed = 0)\n{\n\tstatic gmp_randstate_t state;\n\tstatic bool initialize = true;\n\n\tif(initialize)\n\t{\n\t\tgmp_randinit_default(state);\n\t\tgmp_randseed_ui(state,0);\n\t\tinitialize = false;\n\t}\n\n\tif(seed != 0) gmp_randseed_ui(state,seed);\n\n\treturn mpfr::grandom(state);\n}\n#endif\n\n//////////////////////////////////////////////////////////////////////////\n// Set/Get global properties\ninline void mpreal::set_default_prec(mp_prec_t prec)\n{\n\tmpfr_set_default_prec(prec);\n}\n\ninline void mpreal::set_default_rnd(mp_rnd_t rnd_mode)\n{\n\tmpfr_set_default_rounding_mode(rnd_mode);\n}\n\ninline bool mpreal::fits_in_bits(double x, int n)\n{\n\tint i;\n\tdouble t;\n\treturn IsInf(x) || (std::modf ( std::ldexp ( std::frexp ( x, &i ), n ), &t ) == 0.0);\n}\n\ninline const mpreal pow(const mpreal& a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal x(a);\n\tmpfr_pow(x.mp,x.mp,b.mp,rnd_mode);\n\treturn x;\n}\n\ninline const mpreal pow(const mpreal& a, const mpz_t b, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal x(a);\n\tmpfr_pow_z(x.mp,x.mp,b,rnd_mode);\n\treturn x;\n}\n\ninline const mpreal pow(const mpreal& a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal x(a);\n\tmpfr_pow_ui(x.mp,x.mp,b,rnd_mode);\n\treturn x;\n}\n\ninline const mpreal pow(const mpreal& a, const unsigned int b, mp_rnd_t rnd_mode)\n{\n\treturn pow(a,static_cast<unsigned long int>(b),rnd_mode);\n}\n\ninline const mpreal pow(const mpreal& a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal x(a);\n\tmpfr_pow_si(x.mp,x.mp,b,rnd_mode);\n\treturn x;\n}\n\ninline const mpreal pow(const mpreal& a, const int b, mp_rnd_t rnd_mode)\n{\n\treturn pow(a,static_cast<long int>(b),rnd_mode);\n}\n\ninline const mpreal pow(const mpreal& a, const long double b, mp_rnd_t rnd_mode)\n{\n\treturn pow(a,mpreal(b),rnd_mode);\n}\n\ninline const mpreal pow(const mpreal& a, const double b, mp_rnd_t rnd_mode)\n{\n\treturn pow(a,mpreal(b),rnd_mode);\n}\n\ninline const mpreal pow(const unsigned long int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd())\n{\n\tmpreal x(a);\n\tmpfr_ui_pow(x.mp,a,b.mp,rnd_mode);\n\treturn x;\n}\n\ninline const mpreal pow(const unsigned int a, const mpreal& b, mp_rnd_t rnd_mode)\n{\n\treturn pow(static_cast<unsigned long int>(a),b,rnd_mode);\n}\n\ninline const mpreal pow(const long int a, const mpreal& b, mp_rnd_t rnd_mode)\n{\n\tif (a>=0)     return pow(static_cast<unsigned long int>(a),b,rnd_mode);\n\telse          return pow(mpreal(a),b,rnd_mode);\n}\n\ninline const mpreal pow(const int a, const mpreal& b, mp_rnd_t rnd_mode)\n{\n\tif (a>=0)     return pow(static_cast<unsigned long int>(a),b,rnd_mode);\n\telse          return pow(mpreal(a),b,rnd_mode);\n}\n\ninline const mpreal pow(const long double a, const mpreal& b, mp_rnd_t rnd_mode)\n{\n\treturn pow(mpreal(a),b,rnd_mode);\n}\n\ninline const mpreal pow(const double a, const mpreal& b, mp_rnd_t rnd_mode)\n{\n\treturn pow(mpreal(a),b,rnd_mode);\n}\n\n// pow unsigned long int\ninline const mpreal pow(const unsigned long int a, const unsigned long int b, mp_rnd_t rnd_mode)\n{\n\tmpreal x(a);\n\tmpfr_ui_pow_ui(x.mp,a,b,rnd_mode);\n\treturn x;\n}\n\ninline const mpreal pow(const unsigned long int a, const unsigned int b, mp_rnd_t rnd_mode)\n{\n\treturn pow(a,static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui\n}\n\ninline const mpreal pow(const unsigned long int a, const long int b, mp_rnd_t rnd_mode)\n{\n\tif(b>0)    return pow(a,static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui\n\telse       return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow\n}\n\ninline const mpreal pow(const unsigned long int a, const int b, mp_rnd_t rnd_mode)\n{\n\tif(b>0)    return pow(a,static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui\n\telse       return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow\n}\n\ninline const mpreal pow(const unsigned long int a, const long double b, mp_rnd_t rnd_mode)\n{\n\treturn pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow\n}\n\ninline const mpreal pow(const unsigned long int a, const double b, mp_rnd_t rnd_mode)\n{\n\treturn pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow\n}\n\n// pow unsigned int\ninline const mpreal pow(const unsigned int a, const unsigned long int b, mp_rnd_t rnd_mode)\n{\n\treturn pow(static_cast<unsigned long int>(a),b,rnd_mode); //mpfr_ui_pow_ui\n}\n\ninline const mpreal pow(const unsigned int a, const unsigned int b, mp_rnd_t rnd_mode)\n{\n\treturn pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui\n}\n\ninline const mpreal pow(const unsigned int a, const long int b, mp_rnd_t rnd_mode)\n{\n\tif(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui\n\telse    return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow\n}\n\ninline const mpreal pow(const unsigned int a, const int b, mp_rnd_t rnd_mode)\n{\n\tif(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui\n\telse    return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow\n}\n\ninline const mpreal pow(const unsigned int a, const long double b, mp_rnd_t rnd_mode)\n{\n\treturn pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow\n}\n\ninline const mpreal pow(const unsigned int a, const double b, mp_rnd_t rnd_mode)\n{\n\treturn pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow\n}\n\n// pow long int\ninline const mpreal pow(const long int a, const unsigned long int b, mp_rnd_t rnd_mode)\n{\n\tif (a>0) return pow(static_cast<unsigned long int>(a),b,rnd_mode); //mpfr_ui_pow_ui\n\telse     return pow(mpreal(a),b,rnd_mode); //mpfr_pow_ui\n}\n\ninline const mpreal pow(const long int a, const unsigned int b, mp_rnd_t rnd_mode)\n{\n\tif (a>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode);  //mpfr_ui_pow_ui\n\telse     return pow(mpreal(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_pow_ui\n}\n\ninline const mpreal pow(const long int a, const long int b, mp_rnd_t rnd_mode)\n{\n\tif (a>0)\n\t{\n\t\tif(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui\n\t\telse    return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow\n\t}else{\n\t\treturn pow(mpreal(a),b,rnd_mode); // mpfr_pow_si\n\t}\n}\n\ninline const mpreal pow(const long int a, const int b, mp_rnd_t rnd_mode)\n{\n\tif (a>0)\n\t{\n\t\tif(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui\n\t\telse    return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow\n\t}else{\n\t\treturn pow(mpreal(a),static_cast<long int>(b),rnd_mode); // mpfr_pow_si\n\t}\n}\n\ninline const mpreal pow(const long int a, const long double b, mp_rnd_t rnd_mode)\n{\n\tif (a>=0)   return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow\n\telse        return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow\n}\n\ninline const mpreal pow(const long int a, const double b, mp_rnd_t rnd_mode)\n{\n\tif (a>=0)   return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow\n\telse        return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow\n}\n\n// pow int\ninline const mpreal pow(const int a, const unsigned long int b, mp_rnd_t rnd_mode)\n{\n\tif (a>0) return pow(static_cast<unsigned long int>(a),b,rnd_mode); //mpfr_ui_pow_ui\n\telse     return pow(mpreal(a),b,rnd_mode); //mpfr_pow_ui\n}\n\ninline const mpreal pow(const int a, const unsigned int b, mp_rnd_t rnd_mode)\n{\n\tif (a>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode);  //mpfr_ui_pow_ui\n\telse     return pow(mpreal(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_pow_ui\n}\n\ninline const mpreal pow(const int a, const long int b, mp_rnd_t rnd_mode)\n{\n\tif (a>0)\n\t{\n\t\tif(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui\n\t\telse    return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow\n\t}else{\n\t\treturn pow(mpreal(a),b,rnd_mode); // mpfr_pow_si\n\t}\n}\n\ninline const mpreal pow(const int a, const int b, mp_rnd_t rnd_mode)\n{\n\tif (a>0)\n\t{\n\t\tif(b>0) return pow(static_cast<unsigned long int>(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_ui_pow_ui\n\t\telse    return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow\n\t}else{\n\t\treturn pow(mpreal(a),static_cast<long int>(b),rnd_mode); // mpfr_pow_si\n\t}\n}\n\ninline const mpreal pow(const int a, const long double b, mp_rnd_t rnd_mode)\n{\n\tif (a>=0)   return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow\n\telse        return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow\n}\n\ninline const mpreal pow(const int a, const double b, mp_rnd_t rnd_mode)\n{\n\tif (a>=0)   return pow(static_cast<unsigned long int>(a),mpreal(b),rnd_mode); //mpfr_ui_pow\n\telse        return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow\n}\n\n// pow long double\ninline const mpreal pow(const long double a, const long double b, mp_rnd_t rnd_mode)\n{\n\treturn pow(mpreal(a),mpreal(b),rnd_mode);\n}\n\ninline const mpreal pow(const long double a, const unsigned long int b, mp_rnd_t rnd_mode)\n{\n\treturn pow(mpreal(a),b,rnd_mode); //mpfr_pow_ui\n}\n\ninline const mpreal pow(const long double a, const unsigned int b, mp_rnd_t rnd_mode)\n{\n\treturn pow(mpreal(a),static_cast<unsigned long int>(b),rnd_mode); //mpfr_pow_ui\n}\n\ninline const mpreal pow(const long double a, const long int b, mp_rnd_t rnd_mode)\n{\n\treturn pow(mpreal(a),b,rnd_mode); // mpfr_pow_si\n}\n\ninline const mpreal pow(const long double a, const int b, mp_rnd_t rnd_mode)\n{\n\treturn pow(mpreal(a),static_cast<long int>(b),rnd_mode); // mpfr_pow_si\n}\n\ninline const mpreal pow(const double a, const double b, mp_rnd_t rnd_mode)\n{\n\treturn pow(mpreal(a),mpreal(b),rnd_mode);\n}\n\ninline const mpreal pow(const double a, const unsigned long int b, mp_rnd_t rnd_mode)\n{\n\treturn pow(mpreal(a),b,rnd_mode); // mpfr_pow_ui\n}\n\ninline const mpreal pow(const double a, const unsigned int b, mp_rnd_t rnd_mode)\n{\n\treturn pow(mpreal(a),static_cast<unsigned long int>(b),rnd_mode); // mpfr_pow_ui\n}\n\ninline const mpreal pow(const double a, const long int b, mp_rnd_t rnd_mode)\n{\n\treturn pow(mpreal(a),b,rnd_mode); // mpfr_pow_si\n}\n\ninline const mpreal pow(const double a, const int b, mp_rnd_t rnd_mode)\n{\n\treturn pow(mpreal(a),static_cast<long int>(b),rnd_mode); // mpfr_pow_si\n}\n} // End of mpfr namespace\n\n// Explicit specialization of std::swap for mpreal numbers\n// Thus standard algorithms will use efficient version of swap (due to Koenig lookup)\n// Non-throwing swap C++ idiom: http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-throwing_swap\nnamespace std\n{\n\t// we are allowed to extend namespace std with specializations only\n\ttemplate <>\n\tinline void swap(mpfr::mpreal& x, mpfr::mpreal& y) noexcept\n\t{\n\t\treturn mpfr::swap(x, y);\n\t}\n\n\ttemplate<>\n\tclass numeric_limits<mpfr::mpreal>\n\t{\n\tpublic:\n\t\tstatic const bool is_specialized    = true;\n\t\tstatic const bool is_signed         = true;\n\t\tstatic const bool is_integer        = false;\n\t\tstatic const bool is_exact          = false;\n\t\tstatic const int  radix             = 2;\n\n\t\tstatic const bool has_infinity      = true;\n\t\tstatic const bool has_quiet_NaN     = true;\n\t\tstatic const bool has_signaling_NaN = true;\n\n\t\tstatic const bool is_iec559         = true;        // = IEEE 754\n\t\tstatic const bool is_bounded        = true;\n\t\tstatic const bool is_modulo         = false;\n\t\tstatic const bool traps             = true;\n\t\tstatic const bool tinyness_before   = true;\n\n\t\tstatic const float_denorm_style has_denorm  = denorm_absent;\n\n\t\tinline static mpfr::mpreal (min)    (mp_prec_t precision = mpfr::mpreal::get_default_prec()) {  return  mpfr::minval(precision);  }\n\t\tinline static mpfr::mpreal (max)    (mp_prec_t precision = mpfr::mpreal::get_default_prec()) {  return  mpfr::maxval(precision);  }\n\t\tinline static mpfr::mpreal lowest   (mp_prec_t precision = mpfr::mpreal::get_default_prec()) {  return -mpfr::maxval(precision);  }\n\n\t\t// Returns smallest eps such that 1 + eps != 1 (classic machine epsilon)\n\t\tinline static mpfr::mpreal epsilon(mp_prec_t precision = mpfr::mpreal::get_default_prec()) {  return  mpfr::machine_epsilon(precision); }\n\n\t\t// Returns smallest eps such that x + eps != x (relative machine epsilon)\n\t\tinline static mpfr::mpreal epsilon(const mpfr::mpreal& x) {  return mpfr::machine_epsilon(x);  }\n\n\t\tinline static mpfr::mpreal round_error(mp_prec_t precision = mpfr::mpreal::get_default_prec())\n\t\t{\n\t\t\tmp_rnd_t r = mpfr::mpreal::get_default_rnd();\n\n\t\t\tif(r == GMP_RNDN)  return mpfr::mpreal(0.5, precision);\n\t\t\telse               return mpfr::mpreal(1.0, precision);\n\t\t}\n\n\t\tinline static const mpfr::mpreal infinity()         { return mpfr::const_infinity();     }\n\t\tinline static const mpfr::mpreal quiet_NaN()        { return mpfr::mpreal().setNan();    }\n\t\tinline static const mpfr::mpreal signaling_NaN()    { return mpfr::mpreal().setNan();    }\n\t\tinline static const mpfr::mpreal denorm_min()       { return (min)();                    }\n\n\t\t// Please note, exponent range is not fixed in MPFR\n\t\tstatic const int min_exponent = MPFR_EMIN_DEFAULT;\n\t\tstatic const int max_exponent = MPFR_EMAX_DEFAULT;\n\t\tMPREAL_PERMISSIVE_EXPR static const int min_exponent10 = (int) (MPFR_EMIN_DEFAULT * 0.3010299956639811);\n\t\tMPREAL_PERMISSIVE_EXPR static const int max_exponent10 = (int) (MPFR_EMAX_DEFAULT * 0.3010299956639811);\n\n#ifdef MPREAL_HAVE_DYNAMIC_STD_NUMERIC_LIMITS\n\n\t\t// Following members should be constant according to standard, but they can be variable in MPFR\n\t\t// So we define them as functions here.\n\t\t//\n\t\t// This is preferable way for std::numeric_limits<mpfr::mpreal> specialization.\n\t\t// But it is incompatible with standard std::numeric_limits and might not work with other libraries, e.g. boost.\n\t\t// See below for compatible implementation.\n\t\tinline static float_round_style round_style()\n\t\t{\n\t\t\tmp_rnd_t r = mpfr::mpreal::get_default_rnd();\n\n\t\t\tswitch (r)\n\t\t\t{\n\t\t\tcase GMP_RNDN: return round_to_nearest;\n\t\t\tcase GMP_RNDZ: return round_toward_zero;\n\t\t\tcase GMP_RNDU: return round_toward_infinity;\n\t\t\tcase GMP_RNDD: return round_toward_neg_infinity;\n\t\t\tdefault: return round_indeterminate;\n\t\t\t}\n\t\t}\n\n\t\tinline static int digits()                        {    return int(mpfr::mpreal::get_default_prec());    }\n\t\tinline static int digits(const mpfr::mpreal& x)   {    return x.getPrecision();                         }\n\n\t\tinline static int digits10(mp_prec_t precision = mpfr::mpreal::get_default_prec())\n\t\t{\n\t\t\treturn mpfr::bits2digits(precision);\n\t\t}\n\n\t\tinline static int digits10(const mpfr::mpreal& x)\n\t\t{\n\t\t\treturn mpfr::bits2digits(x.getPrecision());\n\t\t}\n\n\t\tinline static int max_digits10(mp_prec_t precision = mpfr::mpreal::get_default_prec())\n\t\t{\n\t\t\treturn digits10(precision);\n\t\t}\n#else\n\t\t// Digits and round_style are NOT constants when it comes to mpreal.\n\t\t// If possible, please use functions digits() and round_style() defined above.\n\t\t//\n\t\t// These (default) values are preserved for compatibility with existing libraries, e.g. boost.\n\t\t// Change them accordingly to your application.\n\t\t//\n\t\t// For example, if you use 256 bits of precision uniformly in your program, then:\n\t\t// digits       = 256\n\t\t// digits10     = 77\n\t\t// max_digits10 = 78\n\t\t//\n\t\t// Approximate formula for decimal digits is: digits10 = floor(log10(2) * digits). See bits2digits() for more details.\n\n\t\tstatic const std::float_round_style round_style = round_to_nearest;\n\t\tstatic const int digits       = 53;\n\t\tstatic const int digits10     = 15;\n\t\tstatic const int max_digits10 = 16;\n#endif\n\t};\n\n}\n\n\n#ifdef _MSC_VER\n\t#pragma warning(pop)\n#else\n\t#pragma GCC diagnostic pop\n#endif\n\n\n\n\n#endif /* __MPREAL_H__ */\n"
  },
  {
    "path": "external/tinyprocesslib/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015-2016 Ole Christian Eidheim\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "external/tinyprocesslib/README.md",
    "content": "# tiny-process-library [![Build Status](https://travis-ci.org/eidheim/tiny-process-library.svg?branch=master)](https://travis-ci.org/eidheim/tiny-process-library)\nA small platform independent library making it simple to create and stop new processes in C++, as well as writing to stdin and reading from stdout and stderr of a new process.\n\nThis library was created for, and is used by the C++ IDE project [juCi++](https://github.com/cppit/jucipp).\n\n### Features\n* No external dependencies\n* Simple to use\n* Platform independent\n  * Creating processes using executables is supported on all platforms\n  * Creating processes using functions is only possible on Unix-like systems\n* Read separately from stout and stderr using anonymous functions\n* Write to stdin\n* Kill a running process (SIGTERM is supported on Unix-like systems)\n* Correctly closes file descriptors/handles\n\n### Usage\nSee [examples.cpp](https://github.com/eidheim/tiny-process-library/blob/master/examples.cpp).\n\n### Get, compile and run\n\n#### Unix-like systems\n```sh\ngit clone http://github.com/eidheim/tiny-process-library\ncd tiny-process-library\nmkdir build\ncd build\ncmake ..\nmake\n./examples\n```\n\n#### Windows with MSYS2 (https://msys2.github.io/)\n```sh\ngit clone http://github.com/eidheim/tiny-process-library\ncd tiny-process-library\nmkdir build\ncd build\ncmake -G\"MSYS Makefiles\" ..\nmake\n./examples\n```\n"
  },
  {
    "path": "external/tinyprocesslib/process.cpp",
    "content": "#include \"tinyprocess.h\"\n\nnamespace tinyproclib {\nProcess::Process(const string_type &command, const string_type &path,\n                 std::function<void(const char* bytes, size_t n)> read_stdout,\n                 std::function<void(const char* bytes, size_t n)> read_stderr,\n                 bool open_stdin, size_t buffer_size):\n                 closed(true), read_stdout(read_stdout), read_stderr(read_stderr), open_stdin(open_stdin), buffer_size(buffer_size) {\n  open(command, path);\n  async_read();\n}\n\nProcess::~Process() {\n  close_fds();\n}\n\nProcess::id_type Process::get_id() {\n  return data.id;\n}\n\nbool Process::write(const std::string &data) {\n  return write(data.c_str(), data.size());\n}\n}\n"
  },
  {
    "path": "external/tinyprocesslib/process_os.cpp",
    "content": "#ifdef _WIN32\n#include \"process_win.inc\"\n#else\n#include \"process_unix.inc\"\n#endif\n"
  },
  {
    "path": "external/tinyprocesslib/process_unix.inc",
    "content": "#include \"tinyprocess.h\"\n#include <cstdlib>\n#include <unistd.h>\n#include <signal.h>\n#include <stdexcept>\n\nnamespace tinyproclib\n{\n\tProcess::Data::Data() : id(-1) { }\n\n\tProcess::Process(std::function<void()> function, std::function<void (const char*, size_t)> read_stdout,\n\t\tstd::function<void (const char*, size_t)> read_stderr, bool open_stdin, size_t buffer_size)\n\t\t\t: closed(true), read_stdout(read_stdout), read_stderr(read_stderr), open_stdin(open_stdin), buffer_size(buffer_size)\n\t{\n\t\topen(function);\n\t\tasync_read();\n\t}\n\n\tProcess::id_type Process::open(std::function<void()> function)\n\t{\n\t\tif(open_stdin)\tstdin_fd = std::unique_ptr<fd_type>(new fd_type);\n\t\tif(read_stdout)\tstdout_fd = std::unique_ptr<fd_type>(new fd_type);\n\t\tif(read_stderr)\tstderr_fd = std::unique_ptr<fd_type>(new fd_type);\n\n\t\tint stdin_p[2];\n\t\tint stdout_p[2];\n\t\tint stderr_p[2];\n\n\t\tif(stdin_fd && pipe(stdin_p) != 0)\n\t\t\treturn -1;\n\n\t\tif(stdout_fd && pipe(stdout_p) != 0)\n\t\t{\n\t\t\tif(stdin_fd)\n\t\t\t{\n\t\t\t\tclose(stdin_p[0]);\n\t\t\t\tclose(stdin_p[1]);\n\t\t\t}\n\t\t\treturn -1;\n\t\t}\n\t\tif(stderr_fd && pipe(stderr_p) != 0)\n\t\t{\n\t\t\tif(stdin_fd)\n\t\t\t{\n\t\t\t\tclose(stdin_p[0]);\n\t\t\t\tclose(stdin_p[1]);\n\t\t\t}\n\t\t\tif(stdout_fd)\n\t\t\t{\n\t\t\t\tclose(stdout_p[0]);\n\t\t\t\tclose(stdout_p[1]);\n\t\t\t}\n\t\t\treturn -1;\n\t\t}\n\n\t\tid_type pid = fork();\n\n\t\tif(pid < 0)\n\t\t{\n\t\t\tif(stdin_fd)\n\t\t\t{\n\t\t\t\tclose(stdin_p[0]);\n\t\t\t\tclose(stdin_p[1]);\n\t\t\t}\n\t\t\tif(stdout_fd)\n\t\t\t{\n\t\t\t\tclose(stdout_p[0]);\n\t\t\t\tclose(stdout_p[1]);\n\t\t\t}\n\t\t\tif(stderr_fd)\n\t\t\t{\n\t\t\t\tclose(stderr_p[0]);\n\t\t\t\tclose(stderr_p[1]);\n\t\t\t}\n\t\t\treturn pid;\n\t\t}\n\t\telse if(pid == 0)\n\t\t{\n\t\t\tif(stdin_fd)\tdup2(stdin_p[0], 0);\n\t\t\tif(stdout_fd)\tdup2(stdout_p[1], 1);\n\t\t\tif(stderr_fd)\tdup2(stderr_p[1], 2);\n\n\t\t\tif(stdin_fd)\n\t\t\t{\n\t\t\t\tclose(stdin_p[0]);\n\t\t\t\tclose(stdin_p[1]);\n\t\t\t}\n\t\t\tif(stdout_fd)\n\t\t\t{\n\t\t\t\tclose(stdout_p[0]);\n\t\t\t\tclose(stdout_p[1]);\n\t\t\t}\n\t\t\tif(stderr_fd)\n\t\t\t{\n\t\t\t\tclose(stderr_p[0]);\n\t\t\t\tclose(stderr_p[1]);\n\t\t\t}\n\n\t\t\t// Based on http://stackoverflow.com/a/899533/3808293\n\t\t\tint fd_max = sysconf(_SC_OPEN_MAX);\n\t\t\tfor(int fd = 3; fd < fd_max; fd++)\n\t\t\t\tclose(fd);\n\n\t\t\tsetpgid(0, 0);\n\t\t\t// TODO: See here on how to emulate tty for colors: http://stackoverflow.com/questions/1401002/trick-an-application-into-thinking-its-stdin-is-interactive-not-a-pipe\n\t\t\t// TODO: One solution is: echo \"command;exit\"|script -q /dev/null\n\n\t\t\tif(function) function();\n\t\t\t_exit(EXIT_FAILURE);\n\t\t}\n\n\t\tif(stdin_fd)\tclose(stdin_p[0]);\n\t\tif(stdout_fd)\tclose(stdout_p[1]);\n\t\tif(stderr_fd)\tclose(stderr_p[1]);\n\n\t\tif(stdin_fd)\t*stdin_fd = stdin_p[1];\n\t\tif(stdout_fd)\t*stdout_fd = stdout_p[0];\n\t\tif(stderr_fd)\t*stderr_fd = stderr_p[0];\n\n\t\tclosed = false;\n\t\tdata.id = pid;\n\n\t\treturn pid;\n\t}\n\n\tProcess::id_type Process::open(const std::string& command, const std::string& path)\n\t{\n\t\treturn open([&command, &path] {\n\t\t\tif(!path.empty())\n\t\t\t{\n\t\t\t\tauto path_escaped = path;\n\t\t\t\tsize_t pos = 0;\n\n\t\t\t\t// Based on https://www.reddit.com/r/cpp/comments/3vpjqg/a_new_platform_independent_process_library_for_c11/cxsxyb7\n\t\t\t\twhile((pos = path_escaped.find('\\'', pos)) != std::string::npos)\n\t\t\t\t{\n\t\t\t\t\tpath_escaped.replace(pos, 1, \"'\\\\''\");\n\t\t\t\t\tpos += 4;\n\t\t\t\t}\n\n\t\t\t\texecl(\"/bin/sh\", \"sh\", \"-c\", (\"cd '\" + path_escaped + \"' && \" + command).c_str(), NULL);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\texecl(\"/bin/sh\", \"sh\", \"-c\", command.c_str(), NULL);\n\t\t\t}\n\t\t});\n\t}\n\n\tvoid Process::async_read()\n\t{\n\t\tif(data.id <= 0)\n\t\t\treturn;\n\n\t\tif(stdout_fd)\n\t\t{\n\t\t\tstdout_thread = std::thread([this]() {\n\t\t\t\tauto buffer = std::unique_ptr<char[]>(new char[buffer_size]);\n\n\t\t\t\tssize_t n = 0;\n\t\t\t\twhile((n = read(*stdout_fd, buffer.get(), buffer_size)) > 0)\n\t\t\t\t\tread_stdout(buffer.get(), static_cast<size_t>(n));\n\t\t\t});\n\t\t}\n\t\tif(stderr_fd)\n\t\t{\n\t\t\tstderr_thread = std::thread([this]() {\n\t\t\t\tauto buffer = std::unique_ptr<char[]>(new char[buffer_size]);\n\t\t\t\tssize_t n = 0;\n\t\t\t\twhile((n = read(*stderr_fd, buffer.get(), buffer_size)) > 0)\n\t\t\t\t\tread_stderr(buffer.get(), static_cast<size_t>(n));\n\t\t\t});\n\t\t}\n\t}\n\n\tint Process::get_exit_status()\n\t{\n\t\tif(data.id <= 0)\n\t\t\treturn -1;\n\n\t\tint exit_status;\n\t\twaitpid(data.id, &exit_status, 0);\n\t\t{\n\t\t\tstd::lock_guard<std::mutex> lock(close_mutex);\n\t\t\tclosed = true;\n\t\t}\n\t\tclose_fds();\n\n\t\tif(exit_status >= 256)\n\t\t\texit_status = exit_status >> 8;\n\n\t\treturn exit_status;\n\t}\n\n\tvoid Process::close_fds()\n\t{\n\t\tif(stdout_thread.joinable())\n\t\t\tstdout_thread.join();\n\n\t\tif(stderr_thread.joinable())\n\t\t\tstderr_thread.join();\n\n\t\tif(stdin_fd)\n\t\t\tclose_stdin();\n\n\t\tif(stdout_fd)\n\t\t{\n\t\t\tif(data.id > 0)\n\t\t\t\tclose(*stdout_fd);\n\n\t\t\tstdout_fd.reset();\n\t\t}\n\n\t\tif(stderr_fd)\n\t\t{\n\t\t\tif(data.id > 0)\n\t\t\t\tclose(*stderr_fd);\n\n\t\t\tstderr_fd.reset();\n\t\t}\n\t}\n\n\tbool Process::write(const char* bytes, size_t n)\n\t{\n\t\tif(!open_stdin)\n\t\t\treturn false;\n\n\t\t// throw std::invalid_argument(\"Can't write to an unopened stdin pipe. Please set open_stdin=true when constructing the process.\");\n\n\t\tstd::lock_guard<std::mutex> lock(stdin_mutex);\n\t\tif(stdin_fd)\n\t\t{\n\t\t\tif(::write(*stdin_fd, bytes, n) >= 0)\n\t\t\t\treturn true;\n\n\t\t\telse\n\t\t\t\treturn false;\n\t\t}\n\t\treturn false;\n\t}\n\n\tvoid Process::close_stdin()\n\t{\n\t\tstd::lock_guard<std::mutex> lock(stdin_mutex);\n\t\tif(stdin_fd)\n\t\t{\n\t\t\tif(data.id > 0)\n\t\t\t\tclose(*stdin_fd);\n\n\t\t\tstdin_fd.reset();\n\t\t}\n\t}\n\n\tvoid Process::kill(bool force)\n\t{\n\t\tstd::lock_guard<std::mutex> lock(close_mutex);\n\t\tif(data.id>0 && !closed)\n\t\t{\n\t\t\tif(force)\n\t\t\t\t::kill(-data.id, SIGTERM);\n\n\t\t\telse\n\t\t\t\t::kill(-data.id, SIGINT);\n\t\t}\n\t}\n\n\tvoid Process::kill(id_type id, bool force)\n\t{\n\t\tif(id <= 0)\n\t\t\treturn;\n\n\t\tif(force)\n\t\t\t::kill(-id, SIGTERM);\n\n\t\telse\n\t\t\t::kill(-id, SIGINT);\n\t}\n}\n"
  },
  {
    "path": "external/tinyprocesslib/process_win.inc",
    "content": "#include \"tinyprocess.h\"\n#include <windows.h>\n#include <cstring>\n#include <TlHelp32.h>\n#include <stdexcept>\n\nnamespace tinyproclib {\nProcess::Data::Data(): id(0), handle(NULL) {}\n\nnamespace {\n  // Simple HANDLE wrapper to close it automatically from the destructor.\n  class Handle {\n  public:\n    Handle() : handle(INVALID_HANDLE_VALUE) { }\n    ~Handle() {\n      close();\n    }\n    void close() {\n      if (handle != INVALID_HANDLE_VALUE)\n        ::CloseHandle(handle);\n    }\n    HANDLE detach() {\n      HANDLE old_handle = handle;\n      handle = INVALID_HANDLE_VALUE;\n      return old_handle;\n    }\n    operator HANDLE() const { return handle; }\n    HANDLE* operator&() { return &handle; }\n  private:\n    HANDLE handle;\n  };\n\n  //Based on the discussion thread: https://www.reddit.com/r/cpp/comments/3vpjqg/a_new_platform_independent_process_library_for_c11/cxq1wsj\n  std::mutex create_process_mutex;\n}\n\n//Based on the example at https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx.\nProcess::id_type Process::open(const string_type &command, const string_type &path) {\n  if(open_stdin)\n    stdin_fd=std::unique_ptr<fd_type>(new fd_type(NULL));\n  if(read_stdout)\n    stdout_fd=std::unique_ptr<fd_type>(new fd_type(NULL));\n  if(read_stderr)\n    stderr_fd=std::unique_ptr<fd_type>(new fd_type(NULL));\n\n  Handle stdin_rd_p;\n  Handle stdin_wr_p;\n  Handle stdout_rd_p;\n  Handle stdout_wr_p;\n  Handle stderr_rd_p;\n  Handle stderr_wr_p;\n\n  SECURITY_ATTRIBUTES security_attributes;\n\n  security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);\n  security_attributes.bInheritHandle = TRUE;\n  security_attributes.lpSecurityDescriptor = nullptr;\n\n  std::lock_guard<std::mutex> lock(create_process_mutex);\n  if(stdin_fd) {\n    if (!CreatePipe(&stdin_rd_p, &stdin_wr_p, &security_attributes, 0) ||\n        !SetHandleInformation(stdin_wr_p, HANDLE_FLAG_INHERIT, 0))\n      return 0;\n  }\n  if(stdout_fd) {\n    if (!CreatePipe(&stdout_rd_p, &stdout_wr_p, &security_attributes, 0) ||\n        !SetHandleInformation(stdout_rd_p, HANDLE_FLAG_INHERIT, 0)) {\n      return 0;\n    }\n  }\n  if(stderr_fd) {\n    if (!CreatePipe(&stderr_rd_p, &stderr_wr_p, &security_attributes, 0) ||\n        !SetHandleInformation(stderr_rd_p, HANDLE_FLAG_INHERIT, 0)) {\n      return 0;\n    }\n  }\n\n  PROCESS_INFORMATION process_info;\n  STARTUPINFO startup_info;\n\n  ZeroMemory(&process_info, sizeof(PROCESS_INFORMATION));\n\n  ZeroMemory(&startup_info, sizeof(STARTUPINFO));\n  startup_info.cb = sizeof(STARTUPINFO);\n  startup_info.hStdInput = stdin_rd_p;\n  startup_info.hStdOutput = stdout_wr_p;\n  startup_info.hStdError = stderr_wr_p;\n  if(stdin_fd || stdout_fd || stderr_fd)\n    startup_info.dwFlags |= STARTF_USESTDHANDLES;\n\n  string_type process_command=command;\n#ifdef MSYS_PROCESS_USE_SH\n  size_t pos=0;\n  while((pos=process_command.find('\\\\', pos))!=string_type::npos) {\n    process_command.replace(pos, 1, \"\\\\\\\\\\\\\\\\\");\n    pos+=4;\n  }\n  pos=0;\n  while((pos=process_command.find('\\\"', pos))!=string_type::npos) {\n    process_command.replace(pos, 1, \"\\\\\\\"\");\n    pos+=2;\n  }\n  process_command.insert(0, \"sh -c \\\"\");\n  process_command+=\"\\\"\";\n#endif\n\n  BOOL bSuccess = CreateProcess(nullptr, process_command.empty()?nullptr:&process_command[0], nullptr, nullptr, TRUE, 0,\n                                nullptr, path.empty()?nullptr:path.c_str(), &startup_info, &process_info);\n\n  if(!bSuccess) {\n    CloseHandle(process_info.hProcess);\n    CloseHandle(process_info.hThread);\n    return 0;\n  }\n  else {\n    CloseHandle(process_info.hThread);\n  }\n\n  if(stdin_fd) *stdin_fd=stdin_wr_p.detach();\n  if(stdout_fd) *stdout_fd=stdout_rd_p.detach();\n  if(stderr_fd) *stderr_fd=stderr_rd_p.detach();\n\n  closed=false;\n  data.id=process_info.dwProcessId;\n  data.handle=process_info.hProcess;\n  return process_info.dwProcessId;\n}\n\nvoid Process::async_read() {\n  if(data.id==0)\n    return;\n  if(stdout_fd) {\n    stdout_thread=std::thread([this](){\n      DWORD n;\n      std::unique_ptr<char[]> buffer(new char[buffer_size]);\n      for (;;) {\n        BOOL bSuccess = ReadFile(*stdout_fd, static_cast<CHAR*>(buffer.get()), static_cast<DWORD>(buffer_size), &n, nullptr);\n        if(!bSuccess || n == 0)\n          break;\n        read_stdout(buffer.get(), static_cast<size_t>(n));\n      }\n    });\n  }\n  if(stderr_fd) {\n    stderr_thread=std::thread([this](){\n      DWORD n;\n      std::unique_ptr<char[]> buffer(new char[buffer_size]);\n      for (;;) {\n        BOOL bSuccess = ReadFile(*stderr_fd, static_cast<CHAR*>(buffer.get()), static_cast<DWORD>(buffer_size), &n, nullptr);\n        if(!bSuccess || n == 0)\n          break;\n        read_stderr(buffer.get(), static_cast<size_t>(n));\n      }\n    });\n  }\n}\n\nint Process::get_exit_status() {\n  if(data.id==0)\n    return -1;\n  DWORD exit_status;\n  WaitForSingleObject(data.handle, INFINITE);\n  if(!GetExitCodeProcess(data.handle, &exit_status))\n    exit_status=(DWORD)-1;\n  {\n    std::lock_guard<std::mutex> lock(close_mutex);\n    CloseHandle(data.handle);\n    closed=true;\n  }\n  close_fds();\n\n  return static_cast<int>(exit_status);\n}\n\nvoid Process::close_fds() {\n  if(stdout_thread.joinable())\n    stdout_thread.join();\n  if(stderr_thread.joinable())\n    stderr_thread.join();\n\n  if(stdin_fd)\n    close_stdin();\n  if(stdout_fd) {\n    if(*stdout_fd!=NULL) CloseHandle(*stdout_fd);\n    stdout_fd.reset();\n  }\n  if(stderr_fd) {\n    if(*stderr_fd!=NULL) CloseHandle(*stderr_fd);\n    stderr_fd.reset();\n  }\n}\n\nbool Process::write(const char *bytes, size_t n) {\n  if(!open_stdin)\n    throw std::invalid_argument(\"Can't write to an unopened stdin pipe. Please set open_stdin=true when constructing the process.\");\n\n  std::lock_guard<std::mutex> lock(stdin_mutex);\n  if(stdin_fd) {\n    DWORD written;\n    BOOL bSuccess=WriteFile(*stdin_fd, bytes, static_cast<DWORD>(n), &written, nullptr);\n    if(!bSuccess || written==0) {\n      return false;\n    }\n    else {\n      return true;\n    }\n  }\n  return false;\n}\n\nvoid Process::close_stdin() {\n  std::lock_guard<std::mutex> lock(stdin_mutex);\n  if(stdin_fd) {\n    if(*stdin_fd!=NULL) CloseHandle(*stdin_fd);\n    stdin_fd.reset();\n  }\n}\n\n//Based on http://stackoverflow.com/a/1173396\nvoid Process::kill(bool force) {\n  std::lock_guard<std::mutex> lock(close_mutex);\n  if(data.id>0 && !closed) {\n    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);\n    if(snapshot) {\n      PROCESSENTRY32 process;\n      ZeroMemory(&process, sizeof(process));\n      process.dwSize = sizeof(process);\n      if(Process32First(snapshot, &process)) {\n        do {\n          if(process.th32ParentProcessID==data.id) {\n            HANDLE process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, process.th32ProcessID);\n            if(process_handle) {\n              TerminateProcess(process_handle, 2);\n              CloseHandle(process_handle);\n            }\n          }\n        } while (Process32Next(snapshot, &process));\n      }\n      CloseHandle(snapshot);\n    }\n    TerminateProcess(data.handle, 2);\n  }\n}\n\n//Based on http://stackoverflow.com/a/1173396\nvoid Process::kill(id_type id, bool force) {\n  if(id==0)\n    return;\n  HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);\n  if(snapshot) {\n    PROCESSENTRY32 process;\n    ZeroMemory(&process, sizeof(process));\n    process.dwSize = sizeof(process);\n    if(Process32First(snapshot, &process)) {\n      do {\n        if(process.th32ParentProcessID==id) {\n          HANDLE process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, process.th32ProcessID);\n          if(process_handle) {\n            TerminateProcess(process_handle, 2);\n            CloseHandle(process_handle);\n          }\n        }\n      } while (Process32Next(snapshot, &process));\n    }\n    CloseHandle(snapshot);\n  }\n  HANDLE process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, id);\n  if(process_handle) TerminateProcess(process_handle, 2);\n}\n}\n"
  },
  {
    "path": "external/tinyprocesslib/tinyprocess.h",
    "content": "#ifndef TINY_PROCESS_LIBRARY_HPP_\n#define TINY_PROCESS_LIBRARY_HPP_\n\n#include <mutex>\n#include <string>\n#include <functional>\n#include <vector>\n#include <thread>\n#include <memory>\n#ifndef _WIN32\n#include <sys/wait.h>\n#endif\n\nnamespace tinyproclib {\n///Platform independent class for creating processes\nclass Process {\npublic:\n#ifdef _WIN32\n  typedef unsigned long id_type; //Process id type\n  typedef void *fd_type; //File descriptor type\n#ifdef UNICODE\n  typedef std::wstring string_type;\n#else\n  typedef std::string string_type;\n#endif\n#else\n  typedef pid_t id_type;\n  typedef int fd_type;\n  typedef std::string string_type;\n#endif\nprivate:\n  class Data {\n  public:\n    Data();\n    id_type id;\n#ifdef _WIN32\n    void *handle;\n#endif\n  };\npublic:\n  ///Note on Windows: it seems not possible to specify which pipes to redirect.\n  ///Thus, at the moment, if read_stdout==nullptr, read_stderr==nullptr and open_stdin==false,\n  ///the stdout, stderr and stdin are sent to the parent process instead.\n  Process(const string_type &command, const string_type &path=string_type(),\n          std::function<void(const char *bytes, size_t n)> read_stdout=nullptr,\n          std::function<void(const char *bytes, size_t n)> read_stderr=nullptr,\n          bool open_stdin=false,\n          size_t buffer_size=131072);\n#ifndef _WIN32\n  /// Supported on Unix-like systems only.\n  Process(std::function<void()> function,\n          std::function<void(const char *bytes, size_t n)> read_stdout=nullptr,\n          std::function<void(const char *bytes, size_t n)> read_stderr=nullptr,\n          bool open_stdin=false,\n          size_t buffer_size=131072);\n#endif\n  ~Process();\n\n  ///Get the process id of the started process.\n  id_type get_id();\n  ///Wait until process is finished, and return exit status.\n  int get_exit_status();\n  ///Write to stdin.\n  bool write(const char *bytes, size_t n);\n  ///Write to stdin. Convenience function using write(const char *, size_t).\n  bool write(const std::string &data);\n  ///Close stdin. If the process takes parameters from stdin, use this to notify that all parameters have been sent.\n  void close_stdin();\n\n  ///Kill the process. force=true is only supported on Unix-like systems.\n  void kill(bool force=false);\n  ///Kill a given process id. Use kill(bool force) instead if possible. force=true is only supported on Unix-like systems.\n  static void kill(id_type id, bool force=false);\n\nprivate:\n  Data data;\n  bool closed;\n  std::mutex close_mutex;\n  std::function<void(const char* bytes, size_t n)> read_stdout;\n  std::function<void(const char* bytes, size_t n)> read_stderr;\n  std::thread stdout_thread, stderr_thread;\n  bool open_stdin;\n  std::mutex stdin_mutex;\n  size_t buffer_size;\n\n  std::unique_ptr<fd_type> stdout_fd, stderr_fd, stdin_fd;\n\n  id_type open(const string_type &command, const string_type &path);\n#ifndef _WIN32\n  id_type open(std::function<void()> function);\n#endif\n  void async_read();\n  void close_fds();\n};\n}\n\n#endif  // TINY_PROCESS_LIBRARY_HPP_\n"
  },
  {
    "path": "external/utf8rewind/LICENSE",
    "content": "Copyright (C) 2014-2015 Quinten Lansu\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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."
  },
  {
    "path": "external/utf8rewind/README.md",
    "content": "## Introduction ##\n\n`utf8rewind` is a cross-platform and open source C library designed to extend the default string handling functions and add support for UTF-8 encoded text.\n\n## Example ##\n\n```\n#!c\n\t#include \"../include/utf8rewind.h\"\n\n\tint main(int argc, char** argv)\n\t{\n\t\tconst char* input = \"Hello World!\";\n\n\t\tstatic const size_t output_size = 256;\n\t\tchar output[output_size];\n\t\twchar_t output_wide[output_size];\n\t\tconst char* input_seek;\n\t\tsize_t converted_size;\n\t\tint32_t errors;\n\n\t\tmemset(output, 0, output_size * sizeof(char));\n\t\tmemset(output_wide, 0, output_size * sizeof(wchar_t));\n\n\t\t/*\n\t\t\tConvert input to uppercase:\n\n\t\t\t\"Hello World!\" -> \"HELLO WORLD!\"\n\t\t*/\n\n\t\tconverted_size = utf8toupper(\n\t\t\tinput, strlen(input),\n\t\t\toutput, output_size - 1,\n\t\t\t&errors);\n\t\tif (converted_size == 0 ||\n\t\t\terrors != UTF8_ERR_NONE)\n\t\t{\n\t\t\treturn -1;\n\t\t}\n\n\t\t/*\n\t\t\tConvert UTF-8 input to wide (UTF-16 or UTF-32) encoded text:\n\n\t\t\t\"HELLO WORLD!\" -> L\"HELLO WORLD!\"\n\t\t*/\n\n\t\tconverted_size = utf8towide(\n\t\t\toutput, strlen(output),\n\t\t\toutput_wide, (output_size - 1) * sizeof(wchar_t),\n\t\t\t&errors);\n\t\tif (converted_size == 0 ||\n\t\t\terrors != UTF8_ERR_NONE)\n\t\t{\n\t\t\treturn -1;\n\t\t}\n\n\t\t/*\n\t\t\tSeek in input:\n\n\t\t\tHello World!\" -> \"World!\"\n\t\t*/\n\n\t\tinput_seek = utf8seek(input, input, 6, SEEK_SET);\n\n\t\treturn 0;\n\t}\n```\n\n## Features ##\n\n* **Conversion to and from UTF-8** - `utf8rewind` provides functions for converting from and to wide, UTF-16 and UTF-32 encoded text.\n\n* **Case mapping** - The library also provides functionality for converting text to uppercase, lowercase and titlecase.\n\n* **Normalization** - With `utf8normalize`, you can normalize UTF-8 encoded text to NFC, NFD, NFKC or NFKD without converting it to UTF-32 first.\n\n* **Seeking** - Using `utf8seek`, you can seek forwards and backwards in UTF-8 encoded text.\n\n* **Cross-platform** - `utf8rewind` is written in plain C, which means it can be used on any platform with a compliant C compiler. Currently, Windows, Linux and Mac versions are available.\n\n* **Easy to integrate** - The library consists of only 13 public functions and requires no initialization. Any C or C++ project can add `utf8rewind` without breaking existing code.\n\n* **Simple bindings** - No structs are used in the public interface, only pointers. Even if you don't use C, if the language of your choice allows bindings to C functions (e.g. Python), you can benefit from integrating `utf8rewind` into your project.\n\n* **No heap allocations** - All allocations in `utf8rewind` happen on the stack. You provide the memory, without having to override `malloc`. This makes the library perfectly tailored to game engines, integrated systems and other performance-critical or memory-constrained projects.\n\n* **Safety** - Over 2300 automated unit and integration tests guarantee the safety and security of the library.\n\n## Licensing ##\n\nThis project is licensed under the MIT license, a full copy of which should have been provided with the project.\n\n## Download ##\n\n[utf8rewind-1.2.1.zip (3.17 MB)](https://bitbucket.org/knight666/utf8rewind/downloads/utf8rewind-1.2.1.zip)\n\n### Clone in Mercurial ###\n\n\thg clone https://bitbucket.org/knight666/utf8rewind utf8rewind\n\n## Building the project ##\n\nAll supported platforms use [GYP](http://code.google.com/p/gyp/) to generate a solution. This generated solution can be used to compile the project and its dependencies.\n\n### Building on Windows with Visual Studio ###\n\n\tYou will need to have Visual Studio 2010 or above installed.\n\nOpen a command window at the project's root.\n\nIf you have multiple versions of Visual Studio installed, you must first specify the version you want to use:\n\n\tset GYP_MSVS_VERSION=2012\n\nUse GYP to generate a solution:\n\n\ttools\\gyp\\gyp --depth utf8rewind.gyp\n\nOpen the solution in Visual Studio. You can use the different build configurations to generate a static library.\n\n### Building on Linux with GCC ###\n\nOpen a command window at the project's root.\n\nEnsure you have all dependencies installed using your preferred package manager:\n\n\tsudo apt-get install gcc g++ gyp doxygen\n\nUse GYP to generate a Makefile:\n\n\tgyp --depth=. utf8rewind.gyp\n\nBuild the project using `make`:\n\n\tmake\n\nFor a release build, specify the build type:\n\n\tmake BUILDTYPE=Release\n\nNote that the generated Makefile does not contain a \"clean\" target. In order to do a full rebuild, you must delete the files in the \"output\" directory manually.\n\n### Building on Mac OS X with XCode ###\n\n\\note Building on Mac OS X is currently untested. Please let us know if\nyou can help us in this regard.\n\nOpen a command window at the project's root.\n\nUse GYP to generate a solution:\n\n\ttools\\gyp\\gyp --depth utf8rewind.gyp\n\nOpen the solution in XCode and you can build the library and tests.\n\n### Running the tests ###\n\nAfter generating a solution, build and run the \"tests-rewind\" project. Verify that all tests pass on your system configuration before continuing.\n\n## Helping out ##\n\nAs a user, you can help the project in a number of ways, in order of difficulty:\n\n* **Use it** - By using the library, you are helping the project spread. It is very important to us to have the project be used by as many different projects as possible. This will allow us to create better public interfaces.\n\n* **Spread the word** - If you find `utf8rewind` useful, recommend it to your friends or coworkers.\n\n* **Complain** - No library is perfect and `utf8rewind` is no exception. If you find a fault but lack the means (time, resources, etc.) to fix it, sending complaints to the proper channels can help the project out a lot.\n\n* **Write a failing test** - If a feature is not working as intended, you can prove it by writing a failing test. By sending the test to us, we can make the adjustments necessary for it to pass.\n\n* **Write a patch** - Patches include a code change that help tests to pass. A patch must always include a set of tests that fail to pass without the patch. All patches will be reviewed and possibly cleaned up before being accepted.\n\n## Contact ##\n\nFor inquiries, complaints and patches, please contact `{quinten}{lansu} {at} {gmail}.{com}`. Remove the brackets to get a valid e-mail address."
  },
  {
    "path": "external/utf8rewind/include/utf8rewind/utf8rewind.h",
    "content": "/*\n\tCopyright (C) 2014-2016 Quinten Lansu\n\n\tPermission is hereby granted, free of charge, to any person\n\tobtaining a copy of this software and associated documentation\n\tfiles (the \"Software\"), to deal in the Software without\n\trestriction, including without limitation the rights to use,\n\tcopy, modify, merge, publish, distribute, sublicense, and/or\n\tsell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following\n\tconditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n*/\n\n#ifndef _UTF8REWIND_H_\n#define _UTF8REWIND_H_\n\n/*!\n\t\\file\n\t\\brief Public interface for UTF-8 functions.\n\n\t`utf8rewind` is a system library written in C designed to extend the default\n\tstring handling functions with support for UTF-8 encoded text.\n*/\n\n/*!\n\t\\defgroup public Public interface\n\tThe public interface for the library.\n\n\t\\defgroup version Version information\n\tMacros used to identify the version of the library.\n\n\t\\defgroup global-config Global configuration\n\tDefines used for determining the global configuration of the system and your\n\tapplication.\n\n\t\\defgroup errors Error codes\n\tValues returned by functions on error.\n\n\t\\defgroup locales Locales\n\tValues used by functions that change behavior based on the input locale.\n\n\t\\defgroup normalization Normalization flags\n\tFlags used as input for #utf8normalize and the result of #utf8isnormalized.\n\n\t\\defgroup category Category flags\n\tFlags to be used with #utf8iscategory, to check whether code points in a\n\tstring are part of that category.\n\n\t\\defgroup types Types\n\tCustom type definitions used throughout the library.\n*/\n\n#include <locale.h>\n#include <stddef.h>\n#include <stdio.h>\n#include <stdint.h>\n#include <string.h>\n#include <wchar.h>\n#include <ctype.h>\n#include <sys/types.h>\n\n/*!\n\t\\addtogroup version\n\t\\{\n*/\n\n/*!\n\t\\def UTF8_VERSION_MAKE\n\t\\brief Macro for creating a version number from a major, minor and bugfix\n\tnumber.\n*/\n#define UTF8_VERSION_MAKE(_major, _minor, _bugfix) \\\n\t((_major) * 10000) + ((_minor) * 100) + (_bugfix)\n\n/*!\n\t\\def UTF8_VERSION_MAJOR\n\t\\brief The major version number of this release.\n*/\n#define UTF8_VERSION_MAJOR   1\n\n/*!\n\t\\def UTF8_VERSION_MINOR\n\t\\brief The minor version number of this release.\n*/\n#define UTF8_VERSION_MINOR   5\n\n/*!\n\t\\def UTF8_VERSION_BUGFIX\n\t\\brief The bugfix version number of this release.\n*/\n#define UTF8_VERSION_BUGFIX  0\n\n/*!\n\t\\def UTF8_VERSION\n\t\\brief The version number as an integer.\n*/\n#define UTF8_VERSION \\\n\tUTF8_VERSION_MAKE(UTF8_VERSION_MAJOR, UTF8_VERSION_MINOR, UTF8_VERSION_BUGFIX)\n\n/*!\n\t\\def UTF8_VERSION_STRING\n\t\\brief The verion number as a string.\n*/\n#define UTF8_VERSION_STRING  \"1.5.0\"\n\n/*!\n\t\\def UTF8_VERSION_GUARD\n\t\\brief Check if feature is supported by the current release.\n*/\n#define UTF8_VERSION_GUARD(_major, _minor, _bugfix) \\\n\t(UTF8_VERSION >= UTF8_VERSION_MAKE(_major, _minor, _bugfix))\n\n/*!\n\t\\}\n*/\n\n/*!\n\t\\addtogroup errors\n\t\\{\n*/\n\n/*!\n\t\\def UTF8_ERR_NONE\n\t\\brief No errors.\n*/\n#define UTF8_ERR_NONE                           (0)\n\n/*!\n\t\\def UTF8_ERR_INVALID_DATA\n\t\\brief Input data is invalid.\n*/\n#define UTF8_ERR_INVALID_DATA                   (-1)\n\n/*!\n\t\\def UTF8_ERR_INVALID_FLAG\n\t\\brief Input flag is invalid.\n*/\n#define UTF8_ERR_INVALID_FLAG                   (-2)\n\n/*!\n\t\\def UTF8_ERR_NOT_ENOUGH_SPACE\n\t\\brief Not enough space in buffer to store result.\n*/\n#define UTF8_ERR_NOT_ENOUGH_SPACE               (-3)\n\n/*!\n\t\\def UTF8_ERR_OVERLAPPING_PARAMETERS\n\t\\brief Input and output buffers overlap in memory.\n*/\n#define UTF8_ERR_OVERLAPPING_PARAMETERS         (-4)\n\n/*!\n\t\\def UTF8_ERR_INVALID_LOCALE\n\t\\brief Invalid locale specified.\n*/\n#define UTF8_ERR_INVALID_LOCALE                 (-5)\n\n/*!\n\t\\}\n*/\n\n/*!\n\t\\addtogroup locales\n\t\\{\n*/\n\n/*!\n\t\\def UTF8_LOCALE_DEFAULT\n\t\\brief Used for text unaffected by changes in locale.\n*/\n#define UTF8_LOCALE_DEFAULT                     0\n\n/*!\n\t\\def UTF8_LOCALE_LITHUANIAN\n\t\\brief Changes behavior of the case mapping implementation when processing\n\tspecific code points. For more information, see here:\n\tftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt\n*/\n#define UTF8_LOCALE_LITHUANIAN                  1\n\n/*!\n\t\\def UTF8_LOCALE_TURKISH_AND_AZERI_LATIN\n\t\\brief Changes behavior of the case mapping implementation when processing\n\tspecific code points. For more information, see here:\n\tftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt\n*/\n#define UTF8_LOCALE_TURKISH_AND_AZERI_LATIN     2\n\n/*!\n\t\\def UTF8_LOCALE_MAXIMUM\n\t\\brief Terminal value for locales. Valid locales do not exceed this value.\n*/\n#define UTF8_LOCALE_MAXIMUM                     3\n\n/*!\n\t\\}\n*/\n\n/*!\n\t\\addtogroup normalization\n\t\\{\n*/\n\n/*!\n\t\\def UTF8_NORMALIZE_COMPOSE\n\t\\brief Normalize input to Normalization Form C (NFC).\n*/\n#define UTF8_NORMALIZE_COMPOSE                  0x00000001\n\n/*!\n\t\\def UTF8_NORMALIZE_DECOMPOSE\n\t\\brief Normalize input to Normalization Form D (NFD).\n*/\n#define UTF8_NORMALIZE_DECOMPOSE                0x00000002\n\n/*!\n\t\\def UTF8_NORMALIZE_COMPATIBILITY\n\t\\brief Changes Normalization Form from NFC to NFKC or from NFD to NFKD.\n*/\n#define UTF8_NORMALIZE_COMPATIBILITY            0x00000004\n\n/*!\n\t\\def UTF8_NORMALIZATION_RESULT_YES\n\t\\brief Text is stable and does not need to be normalized.\n*/\n#define UTF8_NORMALIZATION_RESULT_YES           (0)\n\n/*!\n\t\\def UTF8_NORMALIZATION_RESULT_MAYBE\n\t\\brief Text is unstable, but normalization may be skipped.\n*/\n#define UTF8_NORMALIZATION_RESULT_MAYBE         (1)\n\n/*!\n\t\\def UTF8_NORMALIZATION_RESULT_NO\n\t\\brief Text is unstable and must be normalized.\n*/\n#define UTF8_NORMALIZATION_RESULT_NO            (2)\n\n/*!\n\t\\}\n*/\n\n/*!\n\t\\addtogroup category\n\t\\{\n*/\n\n/*!\n\t\\def UTF8_CATEGORY_LETTER_UPPERCASE\n\t\\brief Uppercase letter code points, Lu in the Unicode database.\n*/\n#define UTF8_CATEGORY_LETTER_UPPERCASE          0x00000001\n\n/*!\n\t\\def UTF8_CATEGORY_LETTER_LOWERCASE\n\t\\brief Lowercase letter code points, Ll in the Unicode database.\n*/\n#define UTF8_CATEGORY_LETTER_LOWERCASE          0x00000002\n\n/*!\n\t\\def UTF8_CATEGORY_LETTER_TITLECASE\n\t\\brief Titlecase letter code points, Lt in the Unicode database.\n*/\n#define UTF8_CATEGORY_LETTER_TITLECASE          0x00000004\n\n/*!\n\t\\def UTF8_CATEGORY_LETTER_MODIFIER\n\t\\brief Modifier letter code points, Lm in the Unicode database.\n*/\n#define UTF8_CATEGORY_LETTER_MODIFIER           0x00000008\n\n/*!\n\t\\def UTF8_CATEGORY_LETTER_OTHER\n\t\\brief Other letter code points, Lo in the Unicode database.\n*/\n#define UTF8_CATEGORY_LETTER_OTHER              0x00000010\n\n/*!\n\t\\def UTF8_CATEGORY_LETTER\n\t\\brief Combined flag for all letter categories.\n*/\n#define UTF8_CATEGORY_LETTER \\\n\t(UTF8_CATEGORY_LETTER_UPPERCASE | UTF8_CATEGORY_LETTER_LOWERCASE | \\\n\tUTF8_CATEGORY_LETTER_TITLECASE | UTF8_CATEGORY_LETTER_MODIFIER | \\\n\tUTF8_CATEGORY_LETTER_OTHER)\n\n/*!\n\t\\def UTF8_CATEGORY_CASE_MAPPED\n\t\\brief Combined flag for all letter categories with case mapping.\n*/\n#define UTF8_CATEGORY_CASE_MAPPED \\\n\t(UTF8_CATEGORY_LETTER_UPPERCASE | UTF8_CATEGORY_LETTER_LOWERCASE | \\\n\tUTF8_CATEGORY_LETTER_TITLECASE)\n\n/*!\n\t\\def UTF8_CATEGORY_MARK_NON_SPACING\n\t\\brief Non-spacing mark code points, Mn in the Unicode database.\n*/\n#define UTF8_CATEGORY_MARK_NON_SPACING          0x00000020\n\n/*!\n\t\\def UTF8_CATEGORY_MARK_SPACING\n\t\\brief Spacing mark code points, Mc in the Unicode database.\n*/\n#define UTF8_CATEGORY_MARK_SPACING              0x00000040\n\n/*!\n\t\\def UTF8_CATEGORY_MARK_ENCLOSING\n\t\\brief Enclosing mark code points, Me in the Unicode database.\n*/\n#define UTF8_CATEGORY_MARK_ENCLOSING            0x00000080\n\n/*!\n\t\\def UTF8_CATEGORY_MARK\n\t\\brief Combined flag for all mark categories.\n*/\n#define UTF8_CATEGORY_MARK \\\n\t(UTF8_CATEGORY_MARK_NON_SPACING | UTF8_CATEGORY_MARK_SPACING | \\\n\tUTF8_CATEGORY_MARK_ENCLOSING)\n\n/*!\n\t\\def UTF8_CATEGORY_NUMBER_DECIMAL\n\t\\brief Decimal number code points, Nd in the Unicode database.\n*/\n#define UTF8_CATEGORY_NUMBER_DECIMAL            0x00000100\n\n/*!\n\t\\def UTF8_CATEGORY_NUMBER_LETTER\n\t\\brief Letter number code points, Nl in the Unicode database.\n*/\n#define UTF8_CATEGORY_NUMBER_LETTER             0x00000200\n\n/*!\n\t\\def UTF8_CATEGORY_NUMBER_OTHER\n\t\\brief Other number code points, No in the Unicode database.\n*/\n#define UTF8_CATEGORY_NUMBER_OTHER              0x00000400\n\n/*!\n\t\\def UTF8_CATEGORY_NUMBER\n\t\\brief Combined flag for all number categories.\n*/\n#define UTF8_CATEGORY_NUMBER \\\n\t(UTF8_CATEGORY_NUMBER_DECIMAL | UTF8_CATEGORY_NUMBER_LETTER | \\\n\tUTF8_CATEGORY_NUMBER_OTHER)\n\n/*!\n\t\\def UTF8_CATEGORY_PUNCTUATION_CONNECTOR\n\t\\brief Connector punctuation category, Pc in the Unicode database.\n*/\n#define UTF8_CATEGORY_PUNCTUATION_CONNECTOR     0x00000800\n\n/*!\n\t\\def UTF8_CATEGORY_PUNCTUATION_DASH\n\t\\brief Dash punctuation category, Pd in the Unicode database.\n*/\n#define UTF8_CATEGORY_PUNCTUATION_DASH          0x00001000\n\n/*!\n\t\\def UTF8_CATEGORY_PUNCTUATION_OPEN\n\t\\brief Open punctuation category, Ps in the Unicode database.\n*/\n#define UTF8_CATEGORY_PUNCTUATION_OPEN          0x00002000\n\n/*!\n\t\\def UTF8_CATEGORY_PUNCTUATION_CLOSE\n\t\\brief Close punctuation category, Pe in the Unicode database.\n*/\n#define UTF8_CATEGORY_PUNCTUATION_CLOSE         0x00004000\n\n/*!\n\t\\def UTF8_CATEGORY_PUNCTUATION_INITIAL\n\t\\brief Initial punctuation category, Pi in the Unicode database.\n*/\n#define UTF8_CATEGORY_PUNCTUATION_INITIAL       0x00008000\n\n/*!\n\t\\def UTF8_CATEGORY_PUNCTUATION_FINAL\n\t\\brief Final punctuation category, Pf in the Unicode database.\n*/\n#define UTF8_CATEGORY_PUNCTUATION_FINAL         0x00010000\n\n/*!\n\t\\def UTF8_CATEGORY_PUNCTUATION_OTHER\n\t\\brief Other punctuation category, Po in the Unicode database.\n*/\n#define UTF8_CATEGORY_PUNCTUATION_OTHER         0x00020000\n\n/*!\n\t\\def UTF8_CATEGORY_PUNCTUATION\n\t\\brief Combined flag for all punctuation categories.\n*/\n#define UTF8_CATEGORY_PUNCTUATION \\\n\t(UTF8_CATEGORY_PUNCTUATION_CONNECTOR | UTF8_CATEGORY_PUNCTUATION_DASH | \\\n\tUTF8_CATEGORY_PUNCTUATION_OPEN | UTF8_CATEGORY_PUNCTUATION_CLOSE | \\\n\tUTF8_CATEGORY_PUNCTUATION_INITIAL | UTF8_CATEGORY_PUNCTUATION_FINAL | \\\n\tUTF8_CATEGORY_PUNCTUATION_OTHER)\n\n/*!\n\t\\def UTF8_CATEGORY_SYMBOL_MATH\n\t\\brief Math symbol category, Sm in the Unicode database.\n*/\n#define UTF8_CATEGORY_SYMBOL_MATH               0x00040000\n\n/*!\n\t\\def UTF8_CATEGORY_SYMBOL_CURRENCY\n\t\\brief Currency symbol category, Sc in the Unicode database.\n*/\n#define UTF8_CATEGORY_SYMBOL_CURRENCY           0x00080000\n\n/*!\n\t\\def UTF8_CATEGORY_SYMBOL_MODIFIER\n\t\\brief Modifier symbol category, Sk in the Unicode database.\n*/\n#define UTF8_CATEGORY_SYMBOL_MODIFIER           0x00100000\n\n/*!\n\t\\def UTF8_CATEGORY_SYMBOL_OTHER\n\t\\brief Other symbol category, So in the Unicode database.\n*/\n#define UTF8_CATEGORY_SYMBOL_OTHER              0x00200000\n\n/*!\n\t\\def UTF8_CATEGORY_SYMBOL\n\t\\brief Combined flag for all symbol categories.\n*/\n#define UTF8_CATEGORY_SYMBOL \\\n\t(UTF8_CATEGORY_SYMBOL_MATH | UTF8_CATEGORY_SYMBOL_CURRENCY | \\\n\tUTF8_CATEGORY_SYMBOL_MODIFIER | UTF8_CATEGORY_SYMBOL_OTHER)\n\n/*!\n\t\\def UTF8_CATEGORY_SEPARATOR_SPACE\n\t\\brief Space separator category, Zs in the Unicode database.\n*/\n#define UTF8_CATEGORY_SEPARATOR_SPACE           0x00400000\n\n/*!\n\t\\def UTF8_CATEGORY_SEPARATOR_LINE\n\t\\brief Line separator category, Zl in the Unicode database.\n*/\n#define UTF8_CATEGORY_SEPARATOR_LINE            0x00800000\n\n/*!\n\t\\def UTF8_CATEGORY_SEPARATOR_PARAGRAPH\n\t\\brief Paragraph separator category, Zp in the Unicode database.\n*/\n#define UTF8_CATEGORY_SEPARATOR_PARAGRAPH       0x01000000\n\n/*!\n\t\\def UTF8_CATEGORY_SEPARATOR\n\t\\brief Combined flag for all separator categories.\n*/\n#define UTF8_CATEGORY_SEPARATOR \\\n\t(UTF8_CATEGORY_SEPARATOR_SPACE | UTF8_CATEGORY_SEPARATOR_LINE | \\\n\tUTF8_CATEGORY_SEPARATOR_PARAGRAPH)\n\n/*!\n\t\\def UTF8_CATEGORY_CONTROL\n\t\\brief Control category, Cc in the Unicode database.\n*/\n#define UTF8_CATEGORY_CONTROL                   0x02000000\n\n/*!\n\t\\def UTF8_CATEGORY_FORMAT\n\t\\brief Format category, Cf in the Unicode database.\n*/\n#define UTF8_CATEGORY_FORMAT                    0x04000000\n\n/*!\n\t\\def UTF8_CATEGORY_SURROGATE\n\t\\brief Surrogate category, Cs in the Unicode database.\n*/\n#define UTF8_CATEGORY_SURROGATE                 0x08000000\n\n/*!\n\t\\def UTF8_CATEGORY_PRIVATE_USE\n\t\\brief Private use category, Co in the Unicode database.\n*/\n#define UTF8_CATEGORY_PRIVATE_USE               0x10000000\n\n/*!\n\t\\def UTF8_CATEGORY_UNASSIGNED\n\t\\brief Unassigned category, Cn in the Unicode database.\n*/\n#define UTF8_CATEGORY_UNASSIGNED                0x20000000\n\n/*!\n\t\\def UTF8_CATEGORY_COMPATIBILITY\n\t\\brief Flag used for maintaining backwards compatibility with POSIX\n\tfunctions, not found in the Unicode database.\n*/\n#define UTF8_CATEGORY_COMPATIBILITY             0x40000000\n\n/*!\n\t\\def UTF8_CATEGORY_IGNORE_GRAPHEME_CLUSTER\n\t\\brief Flag used for checking only the general category of code points at\n\tthe start of a grapheme cluster.\n*/\n#define UTF8_CATEGORY_IGNORE_GRAPHEME_CLUSTER   0x80000000\n\n/*!\n\t\\def UTF8_CATEGORY_ISCNTRL\n\t\\brief Flag used for maintaining backwards compatibility with POSIX\n\t`iscntrl` function.\n*/\n#define UTF8_CATEGORY_ISCNTRL \\\n\t(UTF8_CATEGORY_COMPATIBILITY | \\\n\tUTF8_CATEGORY_CONTROL)\n\n/*!\n\t\\def UTF8_CATEGORY_ISPRINT\n\t\\brief Flag used for maintaining backwards compatibility with POSIX\n\t`isprint` function.\n*/\n#define UTF8_CATEGORY_ISPRINT \\\n\t(UTF8_CATEGORY_COMPATIBILITY | \\\n\tUTF8_CATEGORY_LETTER | UTF8_CATEGORY_NUMBER | \\\n\tUTF8_CATEGORY_PUNCTUATION | UTF8_CATEGORY_SYMBOL | \\\n\tUTF8_CATEGORY_SEPARATOR)\n\n/*!\n\t\\def UTF8_CATEGORY_ISSPACE\n\t\\brief Flag used for maintaining backwards compatibility with POSIX\n\t`isspace` function.\n*/\n#define UTF8_CATEGORY_ISSPACE \\\n\t(UTF8_CATEGORY_COMPATIBILITY | \\\n\tUTF8_CATEGORY_SEPARATOR_SPACE)\n\n/*!\n\t\\def UTF8_CATEGORY_ISBLANK\n\t\\brief Flag used for maintaining backwards compatibility with POSIX\n\t`isblank` function.\n*/\n#define UTF8_CATEGORY_ISBLANK \\\n\t(UTF8_CATEGORY_COMPATIBILITY | \\\n\tUTF8_CATEGORY_SEPARATOR_SPACE | UTF8_CATEGORY_PRIVATE_USE)\n\n/*!\n\t\\def UTF8_CATEGORY_ISGRAPH\n\t\\brief Flag used for maintaining backwards compatibility with POSIX\n\t`isgraph` function.\n*/\n#define UTF8_CATEGORY_ISGRAPH \\\n\t(UTF8_CATEGORY_COMPATIBILITY | \\\n\tUTF8_CATEGORY_LETTER | UTF8_CATEGORY_NUMBER | \\\n\tUTF8_CATEGORY_PUNCTUATION | UTF8_CATEGORY_SYMBOL)\n\n/*!\n\t\\def UTF8_CATEGORY_ISPUNCT\n\t\\brief Flag used for maintaining backwards compatibility with POSIX\n\t`ispunct` function.\n*/\n#define UTF8_CATEGORY_ISPUNCT \\\n\t(UTF8_CATEGORY_COMPATIBILITY | \\\n\tUTF8_CATEGORY_PUNCTUATION | UTF8_CATEGORY_SYMBOL)\n\n/*!\n\t\\def UTF8_CATEGORY_ISALNUM\n\t\\brief Flag used for maintaining backwards compatibility with POSIX\n\t`isalnum` function.\n*/\n#define UTF8_CATEGORY_ISALNUM \\\n\t(UTF8_CATEGORY_COMPATIBILITY | \\\n\tUTF8_CATEGORY_LETTER | UTF8_CATEGORY_NUMBER)\n\n/*!\n\t\\def UTF8_CATEGORY_ISALPHA\n\t\\brief Flag used for maintaining backwards compatibility with POSIX\n\t`isalpha` function.\n*/\n#define UTF8_CATEGORY_ISALPHA \\\n\t(UTF8_CATEGORY_COMPATIBILITY | \\\n\tUTF8_CATEGORY_LETTER)\n\n/*!\n\t\\def UTF8_CATEGORY_ISUPPER\n\t\\brief Flag used for maintaining backwards compatibility with POSIX\n\t`isupper` function.\n*/\n#define UTF8_CATEGORY_ISUPPER \\\n\t(UTF8_CATEGORY_COMPATIBILITY | \\\n\tUTF8_CATEGORY_LETTER_UPPERCASE)\n\n/*!\n\t\\def UTF8_CATEGORY_ISLOWER\n\t\\brief Flag used for maintaining backwards compatibility with POSIX\n\t`islower` function.\n*/\n#define UTF8_CATEGORY_ISLOWER \\\n\t(UTF8_CATEGORY_COMPATIBILITY | \\\n\tUTF8_CATEGORY_LETTER_LOWERCASE)\n\n/*!\n\t\\def UTF8_CATEGORY_ISDIGIT\n\t\\brief Flag used for maintaining backwards compatibility with POSIX\n\t`isdigit` function.\n*/\n#define UTF8_CATEGORY_ISDIGIT \\\n\t(UTF8_CATEGORY_COMPATIBILITY | \\\n\tUTF8_CATEGORY_NUMBER)\n\n/*!\n\t\\def UTF8_CATEGORY_ISXDIGIT\n\t\\brief Flag used for maintaining backwards compatibility with POSIX\n\t`isxdigit` function.\n*/\n#define UTF8_CATEGORY_ISXDIGIT \\\n\t(UTF8_CATEGORY_COMPATIBILITY | \\\n\tUTF8_CATEGORY_NUMBER | UTF8_CATEGORY_PRIVATE_USE)\n\n/*!\n\t\\}\n*/\n\n/*!\n\t\\addtogroup global-config\n\t\\{\n*/\n\n/*!\n\t\\def UTF8_WCHAR_SIZE\n\t\\brief Specifies the size of the `wchar_t` type. On Windows this is two\n\tbytes, on POSIX systems it is four. If not specified on the command line,\n\tthe compiler tries to automatically determine the size of the `wchar_t` type\n\tbased on the environment.\n*/\n\n#ifndef UTF8_WCHAR_SIZE\n\t#if (__SIZEOF_WCHAR_T__ == 4) || (WCHAR_MAX > UINT16_MAX) || (__WCHAR_MAX__ > UINT16_MAX)\n\t\t#define UTF8_WCHAR_SIZE (4)\n\t#else\n\t\t#define UTF8_WCHAR_SIZE (2)\n\t#endif\n#endif\n\n#if (UTF8_WCHAR_SIZE == 4)\n\t/*!\n\t\t\\def UTF8_WCHAR_UTF32\n\t\t\\brief The `wchar_t` type is treated as UTF-32 (four byte fixed\n\t\tencoding).\n\t*/\n\t#define UTF8_WCHAR_UTF32 (1)\n#elif (UTF8_WCHAR_SIZE == 2)\n\t/*!\n\t\t\\def UTF8_WCHAR_UTF16\n\t\t\\brief The `wchar_t` type is treated as UTF-16 (two byte variable\n\t\tlength encoding).\n\t*/\n\t#define UTF8_WCHAR_UTF16 (1)\n#else\n\t#error Invalid size for wchar_t type.\n#endif\n\n/*!\n\t\\def UTF8_API\n\t\\brief Calling convention for public functions.\n*/\n\n#ifndef UTF8_API\n\t#ifdef __cplusplus\n\t\t#define UTF8_API extern \"C\"\n\t#else\n\t\t#define UTF8_API\n\t#endif\n#endif\n\n/*!\n\t\\}\n*/\n\n/*!\n\t\\addtogroup types\n\t\\{\n*/\n\n/*!\n\t\\var utf16_t\n\t\\brief UTF-16 encoded code point.\n*/\ntypedef uint16_t utf16_t;\n\n/*!\n\t\\var unicode_t\n\t\\brief UTF-32 encoded code point.\n*/\ntypedef uint32_t unicode_t;\n\n/*!\n\t\\}\n*/\n\n/*!\n\t\\addtogroup public\n\t\\{\n*/\n\n/*!\n\t\\brief Get the length in code points of a UTF-8 encoded string.\n\n\tExample:\n\n\t\\code{.c}\n\t\tuint8_t CheckPassword(const char* password)\n\t\t{\n\t\t\tsize_t length = utf8len(password);\n\t\t\treturn (length == utf8len(\"hunter2\"));\n\t\t}\n\t\\endcode\n\n\t\\param[in]  text  UTF-8 encoded string.\n\n\t\\return Length in code points.\n*/\nUTF8_API size_t utf8len(const char* text);\n\n/*!\n\t\\brief Convert a UTF-16 encoded string to a UTF-8 encoded string.\n\n\t\\note This function should only be called directly if you are positive that\n\tyou are working with UTF-16 encoded text. If you're working with wide\n\tstrings, take a look at #widetoutf8 instead.\n\n\tExample:\n\n\t\\code{.c}\n\t\tuint8_t Player_SetNameUtf16(const utf16_t* name, size_t nameSize)\n\t\t{\n\t\t\tchar buffer[256];\n\t\t\tsize_t buffer_size = 255;\n\t\t\tsize_t converted_size;\n\t\t\tint32_t errors;\n\n\t\t\tif ((converted_size = utf16toutf8(name, nameSize, buffer, buffer_size, &errors)) == 0 ||\n\t\t\t\terrors != UTF8_ERR_NONE)\n\t\t\t{\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tbuffer[converted_size] = 0;\n\n\t\t\treturn Player_SetName(converted_name);\n\t\t}\n\t\\endcode\n\n\t\\param[in]   input       UTF-16 encoded string.\n\t\\param[in]   inputSize   Size of the input in bytes.\n\t\\param[out]  target      Output buffer for the result, can be NULL.\n\t\\param[in]   targetSize  Size of the output buffer in bytes.\n\t\\param[out]  errors      Output for errors.\n\n\t\\return Amount of bytes needed for storing output.\n\n\t\\retval #UTF8_ERR_NONE                    No errors.\n\t\\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.\n\t\\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.\n\t\\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.\n\n\t\\sa utf32toutf8\n\t\\sa widetoutf8\n*/\nUTF8_API size_t utf16toutf8(const utf16_t* input, size_t inputSize, char* target, size_t targetSize, int32_t* errors);\n\n/*!\n\t\\brief Convert a UTF-32 encoded string to a UTF-8 encoded string.\n\n\t\\note This function should only be called directly if you are positive that\n\tyou are working with UTF-32 encoded text. If you're working with wide\n\tstrings, take a look at #widetoutf8 instead.\n\n\tExample:\n\n\t\\code{.c}\n\t\tuint8_t Database_ExecuteQuery_Unicode(const unicode_t* query, size_t querySize)\n\t\t{\n\t\t\tchar* converted = NULL;\n\t\t\tsize_t converted_size;\n\t\t\tuint8_t result = 0;\n\t\t\tint32_t errors;\n\n\t\t\tif ((converted_size = utf32toutf8(query, querySize, NULL, 0, &errors)) == 0 ||\n\t\t\t\terrors != UTF8_ERR_NONE)\n\t\t\t{\n\t\t\t\tgoto cleanup;\n\t\t\t}\n\n\t\t\tconverted = (char*)malloc(converted_size + 1);\n\t\t\tutf32toutf8(query, querySize, converted, converted_size, NULL);\n\t\t\tconverted[converted_size] = 0;\n\n\t\t\tresult = Database_ExecuteQuery(converted);\n\n\t\tcleanup:\n\t\t\tif (converted != NULL)\n\t\t\t{\n\t\t\t\tfree(converted);\n\t\t\t\tconverted = 0;\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\t\\endcode\n\n\t\\param[in]   input       UTF-32 encoded string.\n\t\\param[in]   inputSize   Size of the input in bytes.\n\t\\param[out]  target      Output buffer for the result, can be NULL.\n\t\\param[in]   targetSize  Size of the output buffer in bytes.\n\t\\param[out]  errors      Output for errors.\n\n\t\\return Amount of bytes needed for storing output.\n\n\t\\retval #UTF8_ERR_NONE                    No errors.\n\t\\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.\n\t\\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.\n\t\\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.\n\n\t\\sa utf16toutf8\n\t\\sa widetoutf8\n*/\nUTF8_API size_t utf32toutf8(const unicode_t* input, size_t inputSize, char* target, size_t targetSize, int32_t* errors);\n\n/*!\n\t\\brief Convert a wide string to a UTF-8 encoded string.\n\n\tDepending on the platform, wide strings are either UTF-16 or UTF-32 encoded.\n\tThis function takes a wide string as input and automatically calls the\n\tcorrect conversion function.\n\n\tThis allows for a cross-platform treatment of wide text and is preferable to\n\tusing the UTF-16 or UTF-32 versions directly.\n\n\tExample:\n\n\t\\code{.c}\n\t\ttexture_t Texture_Load_Wide(const wchar_t* input)\n\t\t{\n\t\t\tchar* converted = NULL;\n\t\t\tsize_t converted_size;\n\t\t\tsize_t input_size = wcslen(input) * sizeof(wchar_t);\n\t\t\ttexture_t result = NULL;\n\t\t\tint32_t errors;\n\n\t\t\tif ((converted_size = widetoutf8(input, input_size, NULL, 0, &errors)) == 0 ||\n\t\t\t\terrors != UTF8_ERR_NONE)\n\t\t\t{\n\t\t\t\tgoto cleanup;\n\t\t\t}\n\n\t\t\tconverted = (char*)malloc(converted_size + 1);\n\t\t\twidetoutf8(input, input_size, converted, converted_size, NULL);\n\t\t\tconverted[converted_size / sizeof(wchar_t)] = 0;\n\n\t\t\tresult = Texture_Load(converted);\n\n\t\tcleanup:\n\t\t\tif (converted != NULL)\n\t\t\t{\n\t\t\t\tfree(converted);\n\t\t\t\tconverted = NULL;\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\t\\endcode\n\n\t\\param[in]   input       Wide-encoded string.\n\t\\param[in]   inputSize   Size of the input in bytes.\n\t\\param[out]  target      Output buffer for the result, can be NULL.\n\t\\param[in]   targetSize  Size of the output buffer in bytes.\n\t\\param[out]  errors      Output for errors.\n\n\t\\return Amount of bytes needed for storing output.\n\n\t\\retval #UTF8_ERR_NONE                    No errors.\n\t\\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.\n\t\\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.\n\t\\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.\n\n\t\\sa utf8towide\n\t\\sa utf16toutf8\n\t\\sa utf32toutf8\n*/\nUTF8_API size_t widetoutf8(const wchar_t* input, size_t inputSize, char* target, size_t targetSize, int32_t* errors);\n\n/*!\n\t\\brief Convert a UTF-8 encoded string to a UTF-16 encoded string.\n\n\t\\note This function should only be called directly if you are positive that\n\tyou *must* convert to UTF-16, independent of platform. If you're working\n\twith wide strings, take a look at #utf8towide instead.\n\n\tErroneous byte sequences such as missing or illegal bytes or overlong\n\tencoding of code points (e.g. using five bytes to encode a sequence that\n\tcan be represented by two bytes) are converted to the replacement\n\tcharacter U+FFFD.\n\n\tCode points outside the Basic Multilingual Plane (BMP) will be converted to\n\tsurrogate pairs, which use four bytes instead of two.\n\n\tExample:\n\n\t\\code{.c}\n\t\tvoid Font_DrawText(int x, int y, const char* text)\n\t\t{\n\t\t\tutf16_t buffer[256];\n\t\t\tsize_t buffer_size = 255 * sizeof(utf16_t);\n\t\t\tint32_t errors;\n\n\t\t\tsize_t converted_size = utf8toutf16(text, strlen(text), buffer, buffer_size, &errors);\n\t\t\tif (converted_size > 0 &&\n\t\t\t\terrors == UTF8_ERR_NONE)\n\t\t\t{\n\t\t\t\tLegacy_DrawText(g_FontCurrent, x, y, (unsigned short*)buffer, converted_size / sizeof(utf16_t));\n\t\t\t}\n\t\t}\n\t\\endcode\n\n\t\\param[in]   input       UTF-8 encoded string.\n\t\\param[in]   inputSize   Size of the input in bytes.\n\t\\param[out]  target      Output buffer for the result, can be NULL.\n\t\\param[in]   targetSize  Size of the output buffer in bytes.\n\t\\param[out]  errors      Output for errors.\n\n\t\\return Amount of bytes needed for storing output.\n\n\t\\retval #UTF8_ERR_NONE                    No errors.\n\t\\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.\n\t\\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.\n\t\\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.\n\n\t\\sa utf8towide\n\t\\sa utf8toutf32\n*/\nUTF8_API size_t utf8toutf16(const char* input, size_t inputSize, utf16_t* target, size_t targetSize, int32_t* errors);\n\n/*!\n\t\\brief Convert a UTF-8 encoded string to a UTF-32 encoded string.\n\n\t\\note This function should only be called directly if you are positive that\n\tyou *must* convert to UTF-32, independent of platform. If you're working\n\twith wide strings, take a look at #utf8towide instead.\n\n\tErroneous byte sequences such as missing or illegal bytes or overlong\n\tencoding of code points (e.g. using five bytes to encode a sequence that\n\tcan be represented by two bytes) are converted to the replacement\n\tcharacter U+FFFD.\n\n\tExample:\n\n\t\\code{.c}\n\t\tvoid TextField_AddCharacter(const char* encoded)\n\t\t{\n\t\t\tunicode_t code_point = 0;\n\t\t\tint32_t errors;\n\n\t\t\tutf8toutf32(encoded, strlen(encoded), &code_point, sizeof(unicode_t), &errors);\n\t\t\tif (errors == UTF8_ERR_NONE)\n\t\t\t{\n\t\t\t\tTextField_AddCodePoint(code_point);\n\t\t\t}\n\t\t}\n\t\\endcode\n\n\t\\param[in]   input       UTF-8 encoded string.\n\t\\param[in]   inputSize   Size of the input in bytes.\n\t\\param[out]  target      Output buffer for the result, can be NULL.\n\t\\param[in]   targetSize  Size of the output buffer in bytes.\n\t\\param[out]  errors      Output for errors.\n\n\t\\return Amount of bytes needed for storing output.\n\n\t\\retval #UTF8_ERR_NONE                    No errors.\n\t\\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.\n\t\\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.\n\t\\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.\n\n\t\\sa utf8towide\n\t\\sa utf8toutf16\n*/\nUTF8_API size_t utf8toutf32(const char* input, size_t inputSize, unicode_t* target, size_t targetSize, int32_t* errors);\n\n/*!\n\t\\brief Convert a UTF-8 encoded string to a wide string.\n\n\tDepending on the platform, wide strings are either UTF-16 or UTF-32 encoded.\n\tThis function takes a UTF-8 encoded string as input and automatically calls\n\tthe correct conversion function.\n\n\tThis allows for a cross-platform treatment of wide text and is preferable to\n\tusing the UTF-16 or UTF-32 versions directly.\n\n\tErroneous byte sequences such as missing or illegal bytes or overlong\n\tencoding of code points (e.g. using five bytes to encode a sequence that\n\tcan be represented by two bytes) are converted to the replacement\n\tcharacter U+FFFD.\n\n\t\\note Code points outside the Basic Multilingual Plane (BMP) are converted\n\tto surrogate pairs when using UTF-16. This means that strings containing\n\tcharacters outside the BMP converted on a platform with UTF-32 wide strings\n\tare *not* compatible with platforms with UTF-16 wide strings.\n\n\t\\par Hence, it is preferable to store all data as UTF-8 and only convert to\n\twide strings when required by a third-party interface.\n\n\tExample:\n\n\t\\code{.c}\n\t\tvoid Window_SetTitle(void* windowHandle, const char* text)\n\t\t{\n\t\t\tsize_t input_size = strlen(text);\n\t\t\twchar_t* converted = NULL;\n\t\t\tsize_t converted_size;\n\t\t\tint32_t errors;\n\n\t\t\tconverted_size = utf8towide(text, input_size, NULL, 0, &errors);\n\t\t\tif (converted_size == 0 ||\n\t\t\t\terrors != UTF8_ERR_NONE)\n\t\t\t{\n\t\t\t\tgoto cleanup;\n\t\t\t}\n\n\t\t\tconverted = (wchar_t*)malloc(converted_size + sizeof(wchar_t));\n\t\t\tutf8towide(text, input_size, converted, converted_size, NULL);\n\t\t\tconverted[converted_size / sizeof(wchar_t)] = 0;\n\n\t\t\tSetWindowTextW((HWND)windowHandle, converted);\n\n\t\tcleanup:\n\t\t\tif (converted != NULL)\n\t\t\t{\n\t\t\t\tfree(converted);\n\t\t\t\tconverted = NULL;\n\t\t\t}\n\t\t}\n\t\\endcode\n\n\t\\param[in]   input       UTF-8 encoded string.\n\t\\param[in]   inputSize   Size of the input in bytes.\n\t\\param[out]  target      Output buffer for the result, can be NULL.\n\t\\param[in]   targetSize  Size of the output buffer in bytes.\n\t\\param[out]  errors      Output for errors.\n\n\t\\return Amount of bytes needed for storing output.\n\n\t\\retval #UTF8_ERR_NONE                    No errors.\n\t\\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.\n\t\\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.\n\t\\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.\n\n\t\\sa widetoutf8\n\t\\sa utf8toutf16\n\t\\sa utf8toutf32\n*/\nUTF8_API size_t utf8towide(const char* input, size_t inputSize, wchar_t* target, size_t targetSize, int32_t* errors);\n\n/*!\n\t\\brief Seek into a UTF-8 encoded string.\n\n\tWorking with UTF-8 encoded strings can be tricky due to the nature of the\n\tvariable-length encoding. Because one character no longer equals one byte,\n\tit can be difficult to skip around in a UTF-8 encoded string without\n\tdecoding the code points.\n\n\tThis function provides an interface similar to `fseek` in order to enable\n\tskipping to another part of the string.\n\n\t\\note `textStart` must come before `text` in memory when seeking from the\n\tcurrent or end position.\n\n\tExample:\n\n\t\\code{.c}\n\t\tconst char* text = \"Press \\xE0\\x80\\x13 to continue.\";\n\t\tconst char fixed[1024];\n\t\tconst char* commandStart;\n\t\tconst char* commandEnd;\n\n\t\tmemset(fixed, 0, sizeof(fixed));\n\n\t\tcommandStart = strstr(text, \"\\xE0\\x80\\x13\");\n\t\tif (commandStart == 0)\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\n\t\tstrncpy(fixed, text, commandStart - text);\n\t\tstrcat(fixed, \"ENTER\");\n\n\t\tcommandEnd = utf8seek(commandStart, strlen(commandStart), text, 1, SEEK_CUR);\n\t\tif (commandEnd != commandStart)\n\t\t{\n\t\t\tstrcat(fixed, commandEnd);\n\t\t}\n\t\\endcode\n\n\t\\param[in]  text       Input string.\n\t\\param[in]  textSize   Size of the complete input string in bytes, starting from `textStart`.\n\t\\param[in]  textStart  Start of input string.\n\t\\param[in]  offset     Requested offset in code points.\n\t\\param[in]  direction  Direction to seek in.\n\t\\arg `SEEK_SET` Offset is from the start of the string.\n\t\\arg `SEEK_CUR` Offset is from the current position of the string.\n\t\\arg `SEEK_END` Offset is from the end of the string.\n\n\t\\return Pointer to offset string or no change on error.\n\n\t\\sa utf8iscategory\n*/\nUTF8_API const char* utf8seek(const char* text, size_t textSize, const char* textStart, off_t offset, int direction);\n\n/*!\n\t\\brief Returns the environment's locale as an enum value.\n\n\tThis function retrieves the (thread-local) environment locale as an enum\n\tvalue in the \\ref locales \"list of locales\". This value can be used with\n\tfunctions in this library that change behavior on certain inputs, depending\n\ton the specified locale.\n\n\tUnfortunately, no cross-platform way of setting and retrieving the system\n\tlocale is available without adding dependencies to the library. Please refer\n\tto your operating system's manual to determine how to setup the system\n\tlocale on your target system.\n\n\t\\warning This function should not be used as a replacement for platform-\n\tspecific methods for retrieving the locale. Its intended usage is to\n\t\"guess\" the desired locale by looking at the system locale.\n\n\tExample:\n\n\t\\code{.c}\n\t\tuint8_t Employee_PrintNames(const char** names, size_t nameCount)\n\t\t{\n\t\t\tsize_t locale = utf8envlocale();\n\t\t\tchar buffer[256];\n\t\t\tsize_t buffer_size = 255;\n\t\t\tint32_t errors;\n\t\t\tsize_t i;\n\n\t\t\tfor (i = 0; i < nameCount; ++i)\n\t\t\t{\n\t\t\t\tsize_t buffer_filled;\n\n\t\t\t\tmemset(buffer, 0, buffer_size);\n\n\t\t\t\tif ((buffer_filled = utf8toupper(names[i], strlen(names[i]), buffer, buffer_size, locale, &errors)) == 0 ||\n\t\t\t\t\terrors != UTF8_ERR_NONE)\n\t\t\t\t{\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\n\t\t\t\tLog_Print(buffer, buffer_filled);\n\t\t\t}\n\n\t\t\treturn 1;\n\t\t}\n\t\\endcode\n\n\t\\return A specific \\ref locales \"locale\" or #UTF8_LOCALE_DEFAULT.\n\n\t\\sa utf8toupper\n\t\\sa utf8tolower\n\t\\sa utf8totitle\n\t\\sa utf8casefold\n*/\nUTF8_API size_t utf8envlocale();\n\n/*!\n\t\\brief Convert UTF-8 encoded text to uppercase.\n\n\tThis function allows conversion of UTF-8 encoded strings to uppercase\n\twithout first changing the encoding to UTF-32. Conversion is fully compliant\n\twith the Unicode 7.0 standard.\n\n\tAlthough most code points can be converted in-place, there are notable\n\texceptions. For example, U+00DF (LATIN SMALL LETTER SHARP S) maps to\n\t\"U+0053 U+0053\" (LATIN CAPITAL LETTER S and LATIN CAPITAL LETTER S) when\n\tconverted to uppercase. Therefor, it is advised to first determine the size\n\tin bytes of the output by calling the function with a NULL output buffer.\n\n\tOnly a handful of scripts make a distinction between upper and lowercase.\n\tIn addition to modern scripts, such as Latin, Greek, Armenian and Cyrillic,\n\ta few historic or archaic scripts have case. The vast majority of scripts\n\tdo not have case distinctions.\n\n\t\\note Case mapping is not reversible. That is, `toUpper(toLower(x))\n\t!= toLower(toUpper(x))`.\n\n\t\\warning Certain code points (or combinations of code points) apply rules\n\tbased on the locale. For more information about these exceptional\n\tcode points, please refer to the Unicode standard:\n\tftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt\n\n\n\tExample:\n\n\t\\code{.c}\n\t\tvoid Button_Draw(int32_t x, int32_t y, const char* text)\n\t\t{\n\t\t\tsize_t input_size = strlen(text);\n\t\t\tchar* converted = NULL;\n\t\t\tsize_t converted_size;\n\t\t\tint32_t text_box_width, text_box_height;\n\t\t\tint32_t errors;\n\n\t\t\tif ((utf8toupper(text, input_size, NULL, 0, UTF8_LOCALE_DEFAULT, &errors)) == 0 ||\n\t\t\t\terrors != UTF8_ERR_NONE)\n\t\t\t{\n\t\t\t\tgoto cleanup;\n\t\t\t}\n\n\t\t\tconverted = (char*)malloc(converted_size + 1);\n\n\t\t\tif (converted == NULL ||\n\t\t\t\tutf8toupper(text, input_size, converted, converted_size, UTF8_LOCALE_DEFAULT, &errors) == 0 ||\n\t\t\t\terrors != UTF8_ERR_NONE)\n\t\t\t{\n\t\t\t\tgoto cleanup;\n\t\t\t}\n\n\t\t\tconverted[converted_size] = 0;\n\n\t\t\tFont_GetTextDimensions(converted, &text_box_width, &text_box_height);\n\n\t\t\tDraw_BoxFilled(x - 4, y - 4, text_box_width + 8, text_box_height + 8, 0x088A08);\n\t\t\tDraw_BoxOutline(x - 4, y - 4, text_box_width + 8, text_box_height + 8, 0xA9F5A9);\n\t\t\tFont_DrawText(x + 2, y + 1, converted, 0x000000);\n\t\t\tFont_DrawText(x, y, converted, 0xFFFFFF);\n\n\t\tcleanup:\n\t\t\tif (converted != NULL)\n\t\t\t{\n\t\t\t\tfree(converted);\n\t\t\t\tconverted = NULL;\n\t\t\t}\n\t\t}\n\t\\endcode\n\n\t\\param[in]   input       UTF-8 encoded string.\n\t\\param[in]   inputSize   Size of the input in bytes.\n\t\\param[out]  target      Output buffer for the result, can be NULL.\n\t\\param[in]   targetSize  Size of the output buffer in bytes.\n\t\\param[in]   locale      Enables locale-specific behavior in the implementation. \\ref locales \"List of valid locales.\"\n\t\\param[out]  errors      Output for errors.\n\n\t\\return Amount of bytes needed to contain output.\n\n\t\\retval #UTF8_ERR_NONE                    No errors.\n\t\\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.\n\t\\retval #UTF8_ERR_INVALID_LOCALE          Invalid locale specified.\n\t\\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.\n\t\\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.\n\n\t\\sa utf8tolower\n\t\\sa utf8totitle\n\t\\sa utf8casefold\n*/\nUTF8_API size_t utf8toupper(const char* input, size_t inputSize, char* target, size_t targetSize, size_t locale, int32_t* errors);\n\n/*!\n\t\\brief Convert UTF-8 encoded text to lowercase.\n\n\tThis function allows conversion of UTF-8 encoded strings to lowercase\n\twithout first changing the encoding to UTF-32. Conversion is fully compliant\n\twith the Unicode 7.0 standard.\n\n\tAlthough most code points can be converted to lowercase in-place, there are\n\tnotable exceptions. For example, U+0130 (LATIN CAPITAL LETTER I WITH DOT\n\tABOVE) maps to \"U+0069 U+0307\" (LATIN SMALL LETTER I and COMBINING DOT\n\tABOVE) when converted to lowercase. Therefor, it is advised to first\n\tdetermine the size in bytes of the output by calling the function with a\n\tNULL output buffer.\n\n\tOnly a handful of scripts make a distinction between upper- and lowercase.\n\tIn addition to modern scripts, such as Latin, Greek, Armenian and Cyrillic,\n\ta few historic or archaic scripts have case. The vast majority of scripts do\n\tnot have case distinctions.\n\n\t\\note Case mapping is not reversible. That is, `toUpper(toLower(x))\n\t!= toLower(toUpper(x))`.\n\n\t\\warning Certain code points (or combinations of code points) apply rules\n\tbased on the locale. For more information about these exceptional\n\tcode points, please refer to the Unicode standard:\n\tftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt\n\n\tExample:\n\n\t\\code{.c}\n\t\tauthor_t* Author_ByName(const char* name)\n\t\t{\n\t\t\tauthor_t* result = NULL;\n\t\t\tsize_t name_size = strlen(name);\n\t\t\tchar* converted = NULL;\n\t\t\tsize_t converted_size;\n\t\t\tint32_t errors;\n\t\t\tsize_t i;\n\n\t\t\tif ((converted_size = utf8tolower(name, name_size, NULL, 0, UTF8_LOCALE_DEFAULT, &errors)) == 0 ||\n\t\t\t\terrors != UTF8_ERR_NONE)\n\t\t\t{\n\t\t\t\tgoto cleanup;\n\t\t\t}\n\n\t\t\tconverted = (char*)malloc(converted_size + 1);\n\n\t\t\tif (converted == NULL ||\n\t\t\t\tutf8tolower(name, name_size, converted, converted_size, UTF8_LOCALE_DEFAULT, &errors) == 0 ||\n\t\t\t\terrors != UTF8_ERR_NONE)\n\t\t\t{\n\t\t\t\tgoto cleanup;\n\t\t\t}\n\n\t\t\tconverted[converted_size] = 0;\n\n\t\t\tfor (i = 0; i < g_AuthorCount; ++i)\n\t\t\t{\n\t\t\t\tif (!strcmp(g_Author[i].name, converted))\n\t\t\t\t{\n\t\t\t\t\tresult = &g_Author[i];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\tcleanup:\n\t\t\tif (converted != NULL)\n\t\t\t{\n\t\t\t\tfree(converted);\n\t\t\t\tconverted = NULL;\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\t\\endcode\n\n\t\\param[in]   input       UTF-8 encoded string.\n\t\\param[in]   inputSize   Size of the input in bytes.\n\t\\param[out]  target      Output buffer for the result, can be NULL.\n\t\\param[in]   targetSize  Size of the output buffer in bytes.\n\t\\param[in]   locale      Enables locale-specific behavior in the implementation. \\ref locales \"List of valid locales.\"\n\t\\param[out]  errors      Output for errors.\n\n\t\\return Amount of bytes needed for storing output.\n\n\t\\retval #UTF8_ERR_NONE                    No errors.\n\t\\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.\n\t\\retval #UTF8_ERR_INVALID_LOCALE          Invalid locale specified.\n\t\\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.\n\t\\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.\n\n\t\\sa utf8toupper\n\t\\sa utf8totitle\n\t\\sa utf8casefold\n*/\nUTF8_API size_t utf8tolower(const char* input, size_t inputSize, char* target, size_t targetSize, size_t locale, int32_t* errors);\n\n/*!\n\t\\brief Convert UTF-8 encoded text to titlecase.\n\n\tThis function allows conversion of UTF-8 encoded strings to titlecase\n\twithout first changing the encoding to UTF-32. Conversion is fully compliant\n\twith the Unicode 7.0 standard.\n\n\tTitlecase requires a bit more explanation than uppercase and lowercase,\n\tbecause it is not a common text transformation. Titlecase uses uppercase\n\tfor the first letter of each word and lowercase for the rest. Words are\n\tdefined as \"collections of code points with general category Lu, Ll, Lt, Lm\n\tor Lo according to the Unicode database\".\n\n\tEffectively, any type of punctuation can break up a word, even if this is\n\tnot grammatically valid. This happens because the titlecasing algorithm\n\tdoes not and cannot take grammar rules into account.\n\n\tText                                 | Titlecase\n\t-------------------------------------|-------------------------------------\n\tThe running man                      | The Running Man\n\tNATO Alliance                        | Nato Alliance\n\tYou're amazing at building libraries | You'Re Amazing At Building Libraries\n\n\tAlthough most code points can be converted to titlecase in-place, there are\n\tnotable exceptions. For example, U+00DF (LATIN SMALL LETTER SHARP S) maps to\n\t\"U+0053 U+0073\" (LATIN CAPITAL LETTER S and LATIN SMALL LETTER S) when\n\tconverted to titlecase. Therefor, it is advised to first determine the size\n\tin bytes of the output by calling the function with a NULL output buffer.\n\n\tOnly a handful of scripts make a distinction between upper- and lowercase.\n\tIn addition to modern scripts, such as Latin, Greek, Armenian and Cyrillic,\n\ta few historic or archaic scripts have case. The vast majority of scripts\n\tdo not have case distinctions.\n\n\t\\note Case mapping is not reversible. That is, `toUpper(toLower(x))\n\t!= toLower(toUpper(x))`.\n\n\t\\warning Certain code points (or combinations of code points) apply rules\n\tbased on the locale. For more information about these exceptional\n\tcode points, please refer to the Unicode standard:\n\tftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt\n\n\tExample:\n\n\t\\code{.c}\n\t\tvoid Book_SetTitle(book_t* book, const char* title)\n\t\t{\n\t\t\tsize_t converted_size;\n\t\t\tint32_t errors;\n\t\t\tsize_t i;\n\n\t\t\tif ((converted_size = utf8totitle(title, strlen(title), book->title, sizeof(book->title) - 1, UTF8_LOCALE_DEFAULT, &errors)) == 0 ||\n\t\t\t\terrors != UTF8_ERR_NONE)\n\t\t\t{\n\t\t\t\tmemset(book->title, 0, sizeof(book->title));\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tbook->title[converted_size] = 0;\n\t\t}\n\t\\endcode\n\n\t\\param[in]   input       UTF-8 encoded string.\n\t\\param[in]   inputSize   Size of the input in bytes.\n\t\\param[out]  target      Output buffer for the result, can be NULL.\n\t\\param[in]   targetSize  Size of the output buffer in bytes.\n\t\\param[in]   locale      Enables locale-specific behavior in the implementation. \\ref locales \"List of valid locales.\"\n\t\\param[out]  errors      Output for errors.\n\n\t\\return Amount of bytes needed for storing output.\n\n\t\\retval #UTF8_ERR_NONE                    No errors.\n\t\\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.\n\t\\retval #UTF8_ERR_INVALID_LOCALE          Invalid locale specified.\n\t\\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.\n\t\\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.\n\n\t\\sa utf8tolower\n\t\\sa utf8toupper\n\t\\sa utf8casefold\n*/\nUTF8_API size_t utf8totitle(const char* input, size_t inputSize, char* target, size_t targetSize, size_t locale, int32_t* errors);\n\n/*!\n\t\\brief Remove case distinction from UTF-8 encoded text.\n\n\tCase folding is the process of eliminating differences between code points\n\tconcerning case mapping. It is most commonly used for comparing strings in a\n\tcase-insensitive manner. Conversion is fully compliant with the Unicode 7.0\n\tstandard.\n\n\tAlthough similar to lowercasing text, there are significant differences.\n\tFor one, case folding does _not_ take locale into account when converting.\n\tIn some cases, case folding can be up to 20% faster than lowercasing the\n\tsame text, but the result cannot be treated as correct lowercased text.\n\n\tOnly two locale-specific exception are made when case folding text.\n\tIn Turkish, U+0049 LATIN CAPITAL LETTER I maps to U+0131 LATIN SMALL LETTER\n\tDOTLESS I and U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE maps to U+0069\n\tLATIN SMALL LETTER I.\n\n\tAlthough most code points can be case folded in-place, there are notable\n\texceptions. For example, U+0130 (LATIN CAPITAL LETTER I WITH DOT ABOVE) maps\n\tto \"U+0069 U+0307\" (LATIN SMALL LETTER I and COMBINING DOT ABOVE) when\n\tconverted to lowercase. Therefor, it is advised to first determine the size\n\tin bytes of the output by calling the function with a NULL output buffer.\n\n\tOnly a handful of scripts make a distinction between upper- and lowercase.\n\tIn addition to modern scripts, such as Latin, Greek, Armenian and Cyrillic,\n\ta few historic or archaic scripts have case. The vast majority of scripts\n\tdo not have case distinctions.\n\n\tExample:\n\n\t\\code{.c}\n\t\tint32_t Command_ParseCommand(const char* argument)\n\t\t{\n\t\t\tchar* buffer = NULL;\n\t\t\tsize_t buffer_size = 0;\n\t\t\tint32_t errors;\n\t\t\tint32_t result = 0;\n\n\t\t\tif ((buffer_size = utf8casefold(argument, strlen(argument), NULL, 0, UTF8_LOCALE_DEFAULT, &errors)) == 0 ||\n\t\t\t\terrors != UTF8_ERR_NONE)\n\t\t\t{\n\t\t\t\tresult = -1;\n\n\t\t\t\tgoto cleanup;\n\t\t\t}\n\n\t\t\tbuffer = (char*)malloc(buffer_size);\n\n\t\t\tif (buffer == NULL ||\n\t\t\t\tutf8casefold(argument, strlen(argument), buffer, buffer_size, UTF8_LOCALE_DEFAULT, &errors) == 0 ||\n\t\t\t\terrors != UTF8_ERR_NONE)\n\t\t\t{\n\t\t\t\tresult = -1;\n\n\t\t\t\tgoto cleanup;\n\t\t\t}\n\n\t\t\tif (!strncmp(buffer, \"-username\", strlen(\"-username\")))\n\t\t\t{\n\t\t\t\tresult = eCommand_Username;\n\t\t\t}\n\t\t\telse if (\n\t\t\t\t!strncmp(buffer, \"-password\", strlen(\"-password\")))\n\t\t\t{\n\t\t\t\tresult = eCommand_Password;\n\t\t\t}\n\t\t\telse if (\n\t\t\t\t!strncmp(buffer, \"-message\", strlen(\"-message\")))\n\t\t\t{\n\t\t\t\tresult = eCommand_Message;\n\t\t\t}\n\n\t\tcleanup:\n\t\t\tif (buffer != NULL)\n\t\t\t{\n\t\t\t\tfree(buffer);\n\t\t\t\tbuffer = NULL;\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\t\\endcode\n\n\t\\param[in]   input       UTF-8 encoded string.\n\t\\param[in]   inputSize   Size of the input in bytes.\n\t\\param[out]  target      Output buffer for the result, can be NULL.\n\t\\param[in]   targetSize  Size of the output buffer in bytes.\n\t\\param[in]   locale      Enables locale-specific behavior in the implementation. \\ref locales \"List of valid locales.\"\n\t\\param[out]  errors      Output for errors.\n\n\t\\return Amount of bytes needed for storing output.\n\n\t\\retval #UTF8_ERR_NONE                    No errors.\n\t\\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.\n\t\\retval #UTF8_ERR_INVALID_LOCALE          Invalid locale specified.\n\t\\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.\n\t\\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.\n\n\t\\sa utf8tolower\n\t\\sa utf8toupper\n\t\\sa utf8totitle\n*/\nUTF8_API size_t utf8casefold(const char* input, size_t inputSize, char* target, size_t targetSize, size_t locale, int32_t* errors);\n\n/*!\n\t\\brief Check if a string is stable in the specified Unicode Normalization\n\tForm.\n\n\tThis function can be used as a preprocessing step, before attempting to\n\tnormalize a string. Normalization is a very expensive process, it is often\n\tcheaper to first determine if the string is unstable in the requested\n\tnormalization form.\n\n\tThe result of the check will be YES if the string is stable and MAYBE or NO\n\tif it is unstable. If the result is MAYBE, the string does not necessarily\n\thave to be normalized.\n\n\tIf the result is unstable, the offset parameter is set to the offset for the\n\tfirst unstable code point. If the string is stable, the offset is equivalent\n\tto the length of the string in bytes.\n\n\tYou must specify the desired Unicode Normalization Form by using a\n\tcombination of flags:\n\n\tUnicode                      | Flags\n\t---------------------------- | ---------------------------------------------------------\n\tNormalization Form C (NFC)   | #UTF8_NORMALIZE_COMPOSE\n\tNormalization Form KC (NFKC) | #UTF8_NORMALIZE_COMPOSE + #UTF8_NORMALIZE_COMPATIBILITY\n\tNormalization Form D (NFD)   | #UTF8_NORMALIZE_DECOMPOSE\n\tNormalization Form KD (NFKD) | #UTF8_NORMALIZE_DECOMPOSE + #UTF8_NORMALIZE_COMPATIBILITY\n\n\tFor more information, please review [Unicode Standard Annex #15 - Unicode\n\tNormalization Forms](http://www.unicode.org/reports/tr15/).\n\n\tExample:\n\n\t\\code{.c}\n\t\tuint8_t Text_InspectComposed(const char* text)\n\t\t{\n\t\t\tconst char* src = text;\n\t\t\tsize_t src_size = strlen(text);\n\t\t\tsize_t offset;\n\t\t\tsize_t total_offset;\n\n\t\t\tif (utf8isnormalized(src, src_size, UTF8_NORMALIZE_COMPOSE, &offset) == UTF8_NORMALIZATION_RESULT_YES)\n\t\t\t{\n\t\t\t\tprintf(\"Clean!\\n\");\n\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\ttotal_offset = offset;\n\n\t\t\tdo\n\t\t\t{\n\t\t\t\tconst char* next;\n\n\t\t\t\tprintf(\"Unstable at byte %d\\n\", total_offset);\n\n\t\t\t\tnext = utf8seek(src, text, 1, SEEK_CUR);\n\t\t\t\tif (next == src)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\ttotal_offset += offset;\n\n\t\t\t\tsrc = next;\n\t\t\t\tsrc_size -= next - src;\n\t\t\t}\n\t\t\twhile (utf8isnormalized(src, src_size, UTF8_NORMALIZE_COMPOSE, &offset) != UTF8_NORMALIZATION_RESULT_YES);\n\n\t\t\treturn 0;\n\t\t}\n\t\\endcode\n\n\t\\param[in]   input       UTF-8 encoded string.\n\t\\param[in]   inputSize   Size of the input in bytes.\n\t\\param[in]   flags       Desired normalization form. Must be a combination of \\ref normalization \"normalization flags\".\n\t\\param[out]  offset      Offset to first unstable code point or length of input in bytes if stable.\n\n\t\\retval #UTF8_NORMALIZATION_RESULT_YES    Input is stable and does not have to be normalized.\n\t\\retval #UTF8_NORMALIZATION_RESULT_MAYBE  Input is unstable, but normalization may be skipped.\n\t\\retval #UTF8_NORMALIZATION_RESULT_NO     Input is unstable and must be normalized.\n\n\t\\sa utf8normalize\n*/\nUTF8_API uint8_t utf8isnormalized(const char* input, size_t inputSize, size_t flags, size_t* offset);\n\n/*!\n\t\\brief Normalize a string to the specified Unicode Normalization Form.\n\n\tThe Unicode standard defines two standards for equivalence between\n\tcharacters: canonical and compatibility equivalence. Canonically equivalent\n\tcharacters and sequence represent the same abstract character and must be\n\trendered with the same appearance and behavior. Compatibility equivalent\n\tcharacters have a weaker equivalence and may be rendered differently.\n\n\tUnicode Normalization Forms are formally defined standards that can be used\n\tto test whether any two strings of characters are equivalent to each other.\n\tThis equivalence may be canonical or compatibility.\n\n\tThe algorithm puts all combining marks into a specified order and uses the\n\trules for decomposition and composition to transform the string into one of\n\tfour Unicode Normalization Forms. A binary comparison can then be used to\n\tdetermine equivalence.\n\n\tThese are the Unicode Normalization Forms:\n\n\tForm                         | Description\n\t---------------------------- | ---------------------------------------------\n\tNormalization Form D (NFD)   | Canonical decomposition\n\tNormalization Form C (NFC)   | Canonical decomposition, followed by canonical composition\n\tNormalization Form KD (NFKD) | Compatibility decomposition\n\tNormalization Form KC (NFKC) | Compatibility decomposition, followed by canonical composition\n\n\t`utf8normalize` can be used to transform text into one of these forms. You\n\tmust specify the desired Unicode Normalization Form by using a combination\n\tof flags:\n\n\tForm                          | Flags\n\t----------------------------- | ---------------------------------------------------------\n\tNormalization Form D (NFD)    | #UTF8_NORMALIZE_DECOMPOSE\n\tNormalization Form C (NFC)    | #UTF8_NORMALIZE_COMPOSE\n\tNormalization Form KD (NFKD)  | #UTF8_NORMALIZE_DECOMPOSE + #UTF8_NORMALIZE_COMPATIBILITY\n\tNormalization Form KC (NFKC)  | #UTF8_NORMALIZE_COMPOSE + #UTF8_NORMALIZE_COMPATIBILITY\n\n\tFor more information, please review [Unicode Standard Annex #15 - Unicode\n\tNormalization Forms](http://www.unicode.org/reports/tr15/).\n\n\t\\note Unnormalized text is rare in the wild. As an example, *all* text\n\tfound on the Internet as HTML source code must be encoded as NFC, as\n\tspecified by the W3C.\n\n\tExample:\n\n\t\\code{.c}\n\t\tvoid Font_RenderTextNormalized(const char* input)\n\t\t{\n\t\t\tconst char* src = NULL;\n\t\t\tconst char* src_start;\n\t\t\tsize_t src_size;\n\t\t\tchar* converted = NULL;\n\t\t\tsize_t converted_size = 0;\n\t\t\tsize_t input_size = strlen(input);\n\n\t\t\tif (utf8isnormalized(input, input_size, UTF8_NORMALIZE_COMPOSE, NULL) != UTF8_NORMALIZATION_RESULT_YES)\n\t\t\t{\n\t\t\t\tint32_t errors;\n\n\t\t\t\tconverted_size = utf8normalize(input, input_size, NULL, 0, UTF8_NORMALIZE_COMPOSE, &errors);\n\t\t\t\tif (converted_size > 0 &&\n\t\t\t\t\terrors == UTF8_ERR_NONE)\n\t\t\t\t{\n\t\t\t\t\tconverted = (char*)malloc(converted_size + 1);\n\t\t\t\t\tutf8normalize(input, input_size, converted, converted_size, UTF8_NORMALIZE_COMPOSE, NULL);\n\t\t\t\t\tconverted[converted_size] = 0;\n\n\t\t\t\t\tsrc = (const char*)converted;\n\t\t\t\t\tsrc_size = converted_size;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (src == NULL)\n\t\t\t{\n\t\t\t\tsrc = (const char*)input;\n\t\t\t\tsrc_size = input_size;\n\t\t\t}\n\n\t\t\tsrc_start = src;\n\n\t\t\twhile (src_size > 0)\n\t\t\t{\n\t\t\t\tconst char* next;\n\t\t\t\tint32_t errors;\n\n\t\t\t\tnext = utf8seek(src, src_size, src_start, 1, SEEK_CUR);\n\t\t\t\tif (next == src)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tunicode_t code_point;\n\t\t\t\tutf8toutf32(src, (size_t)(next - src), &code_point, sizeof(unicode_t), &errors);\n\t\t\t\tif (errors != UTF8_ERR_NONE)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tFont_RenderCodePoint(code_point);\n\n\t\t\t\tsrc_size -= next - src;\n\t\t\t\tsrc = next;\n\t\t\t}\n\n\t\t\tif (converted != NULL)\n\t\t\t{\n\t\t\t\tfree(converted);\n\t\t\t\tconverted = NULL;\n\t\t\t}\n\t\t}\n\t\\endcode\n\n\t\\param[in]   input       UTF-8 encoded string.\n\t\\param[in]   inputSize   Size of the input in bytes.\n\t\\param[out]  target      Output buffer for the result, can be NULL.\n\t\\param[in]   targetSize  Size of the output buffer in bytes.\n\t\\param[in]   flags       Desired normalization form. Must be a combination of #UTF8_NORMALIZE_COMPOSE, #UTF8_NORMALIZE_DECOMPOSE and #UTF8_NORMALIZE_COMPATIBILITY.\n\t\\param[out]  errors      Output for errors.\n\n\t\\return Amount of bytes needed for storing output.\n\n\t\\retval #UTF8_ERR_NONE                    No errors.\n\t\\retval #UTF8_ERR_INVALID_FLAG            Invalid combination of flags was specified.\n\t\\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.\n\t\\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.\n\t\\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.\n\n\t\\sa utf8isnormalized\n*/\nUTF8_API size_t utf8normalize(const char* input, size_t inputSize, char* target, size_t targetSize, size_t flags, int32_t* errors);\n\n/*!\n\t\\brief Check if the input string conforms to the category specified by the\n\tflags.\n\n\tThis function can be used to check if the code points in a string are part\n\tof a category. Valid flags are members of the\n\t\\ref category \"list of categories\". The category for a code point is\n\tdefined as part of the entry in UnicodeData.txt, the data file for the\n\tUnicode code point database.\n\n\t\\note The function is _greedy_. This means it will try to match as many\n\tcode points with the matching category flags as possible and return the\n\toffset in the input in bytes. If this is undesired behavior, use `utf8seek`\n\tto seek in the input first before matching it with the category flags.\n\n\tBy default, the function will treat grapheme clusters as a single code\n\tpoint. This means that the following string:\n\n\tCode point | Canonical combining class | General category      | Name\n\t---------- | ------------------------- | --------------------- | ----------------------\n\tU+0045     | 0                         | Lu (Uppercase letter) | LATIN CAPITAL LETTER E\n\tU+0300     | 230                       | Mn (Non-spacing mark) | COMBINING GRAVE ACCENT\n\n\tWill match with #UTF8_CATEGORY_LETTER_UPPERCASE in its entirety, because\n\tthe COMBINING GRAVE ACCENT is treated as part of the grapheme cluster. This\n\tis useful when e.g. creating a text parser, because you do not have to\n\tnormalize the text first.\n\n\tIf this is undesired behavior, specify the\n\t#UTF8_CATEGORY_IGNORE_GRAPHEME_CLUSTER flag.\n\n\t\\warning In order to maintain backwards compatibility with POSIX functions\n\tlike `isdigit` and `isspace`, compatibility flags have been provided. Note,\n\thowever, that the result is only guaranteed to be correct for code points\n\tin the Basic Latin range, between U+0000 and 0+007F. Combining a\n\tcompatibility flag with a regular category flag will result in undefined\n\tbehavior.\n\n\tExample:\n\n\t\\code{.c}\n\t\tconst char* Parser_NextIdentifier(char** output, size_t* outputSize, const char* input, size_t inputSize)\n\t\t{\n\t\t\tconst char* src = input;\n\t\t\tsize_t src_size = inputSize;\n\t\t\tsize_t whitespace_size;\n\t\t\tsize_t identifier_size;\n\n\t\t\twhitespace_size = utf8iscategory(src, src_size, UTF8_CATEGORY_SEPARATOR_SPACE);\n\t\t\tif (whitespace_size == 0)\n\t\t\t{\n\t\t\t\twhitespace_size = utf8iscategory(src, src_size, UTF8_CATEGORY_ISSPACE);\n\t\t\t}\n\n\t\t\tif (whitespace_size > 0)\n\t\t\t{\n\t\t\t\tif (whitespace_size >= src_size)\n\t\t\t\t{\n\t\t\t\t\treturn src + src_size;\n\t\t\t\t}\n\n\t\t\t\tsrc += whitespace_size;\n\t\t\t\tsrc_size -= whitespace_size;\n\t\t\t}\n\n\t\t\tidentifier_size = utf8iscategory(src, src_size, UTF8_CATEGORY_LETTER | UTF8_CATEGORY_PUNCTUATION_CONNECTOR | UTF8_CATEGORY_PUNCTUATION_DASH);\n\t\t\tif (identifier_size == 0)\n\t\t\t{\n\t\t\t\treturn src;\n\t\t\t}\n\n\t\t\t*output = (char*)malloc(identifier_size + 1);\n\t\t\tmemcpy(*output, src, identifier_size);\n\t\t\t(*output)[identifier_size] = 0;\n\t\t\t*outputSize = identifier_size;\n\n\t\t\tif (identifier_size >= src_size)\n\t\t\t{\n\t\t\t\treturn src + src_size;\n\t\t\t}\n\n\t\t\treturn src + identifier_size;\n\t\t}\n\t\\endcode\n\n\t\\param[in]   input       UTF-8 encoded string.\n\t\\param[in]   inputSize   Size of the input in bytes.\n\t\\param[in]   flags       Requested category. Must be a combination of \\ref category \"category flags\" or a single compatibility flag.\n\n\t\\return Number of bytes in the input that conform to the specified category flags.\n\n\t\\sa utf8seek\n*/\nUTF8_API size_t utf8iscategory(const char* input, size_t inputSize, size_t flags);\n\n/*!\n\t\\}\n*/\n\n#endif /* _UTF8REWIND_H_ */\n\n"
  },
  {
    "path": "external/utf8rewind/makefile",
    "content": "# bleugh.\n# so we can call from our main makefile.\n\nCSRC    := $(shell find source -name \"*.c\")\nCOBJ    := $(CSRC:.c=.c.o)\n\n.PHONY: all\n\nall: ../libutf8rewind.a\n\t@:\n\n../libutf8rewind.a: $(COBJ)\n\t@echo \"# libutf8rewind\"\n\t@$(AR) rcs ../libutf8rewind.a $(COBJ)\n\n%.c.o: %.c\n\t@echo \"# utf8rewind/$(notdir $<)\"\n\t@$(CC) -std=c11 -O3 -c -Iinclude -o $@ $<\n\n\n\n\n"
  },
  {
    "path": "external/utf8rewind/source/internal/base.h",
    "content": "/*\n\tCopyright (C) 2014-2016 Quinten Lansu\n\n\tPermission is hereby granted, free of charge, to any person\n\tobtaining a copy of this software and associated documentation\n\tfiles (the \"Software\"), to deal in the Software without\n\trestriction, including without limitation the rights to use,\n\tcopy, modify, merge, publish, distribute, sublicense, and/or\n\tsell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following\n\tconditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n*/\n\n#ifndef _UTF8REWIND_INTERNAL_BASE_H_\n#define _UTF8REWIND_INTERNAL_BASE_H_\n\n/*!\n\t\\file\n\t\\brief Base header for internal interface.\n\n\t\\cond INTERNAL\n*/\n\n#include \"../../include/utf8rewind/utf8rewind.h\"\n\n#if defined(__GNUC__) && !defined(COMPILER_ICC)\n\t#define UTF8_UNUSED(_parameter) _parameter __attribute__ ((unused))\n#else\n\t#define UTF8_UNUSED(_parameter) _parameter\n#endif\n\n#define UTF8_SET_ERROR(_error) \\\n\tif (errors != 0) { *errors = UTF8_ERR_ ## _error; }\n\n/* Validates input before transforming */\n/* Check for parameter overlap using the separating axis theorem */\n\n#define UTF8_VALIDATE_PARAMETERS_CHAR(_inputType, _result) \\\n\tif (input == 0) { \\\n\t\tUTF8_SET_ERROR(INVALID_DATA); \\\n\t\treturn _result; \\\n\t} \\\n\telse if (inputSize < sizeof(_inputType)) { \\\n\t\tif (target != 0) { \\\n\t\t\tif (targetSize < 3) { \\\n\t\t\t\tUTF8_SET_ERROR(NOT_ENOUGH_SPACE); \\\n\t\t\t\treturn _result; \\\n\t\t\t} \\\n\t\t\tmemcpy(target, REPLACEMENT_CHARACTER_STRING, REPLACEMENT_CHARACTER_STRING_LENGTH); \\\n\t\t} \\\n\t\tUTF8_SET_ERROR(INVALID_DATA); \\\n\t\treturn _result + REPLACEMENT_CHARACTER_STRING_LENGTH; \\\n\t} \\\n\tif (target != 0 && targetSize == 0) { \\\n\t\tUTF8_SET_ERROR(NOT_ENOUGH_SPACE); \\\n\t\treturn _result; \\\n\t} \\\n\tif ((char*)input == target) { \\\n\t\tUTF8_SET_ERROR(OVERLAPPING_PARAMETERS); \\\n\t\treturn _result; \\\n\t} \\\n\t{ \\\n\t\tchar* input_center = (char*)input + (inputSize / 2); \\\n\t\tchar* target_center = target + (targetSize / 2); \\\n\t\tsize_t delta = (size_t)((input_center > target_center) ? (input_center - target_center) : (target_center - input_center)); \\\n\t\tif (delta < (inputSize + targetSize) / 2) { \\\n\t\t\tUTF8_SET_ERROR(OVERLAPPING_PARAMETERS); \\\n\t\t\treturn _result; \\\n\t\t} \\\n\t}\n\n#define UTF8_VALIDATE_PARAMETERS(_inputType, _outputType, _result) \\\n\tif (input == 0) { \\\n\t\tUTF8_SET_ERROR(INVALID_DATA); \\\n\t\treturn _result; \\\n\t} \\\n\telse if (inputSize < sizeof(_inputType)) { \\\n\t\tif (target != 0) { \\\n\t\t\tif (targetSize < sizeof(_outputType)) { \\\n\t\t\t\tUTF8_SET_ERROR(NOT_ENOUGH_SPACE); \\\n\t\t\t\treturn _result; \\\n\t\t\t} \\\n\t\t\t*target = REPLACEMENT_CHARACTER; \\\n\t\t} \\\n\t\tUTF8_SET_ERROR(INVALID_DATA); \\\n\t\treturn _result + sizeof(_outputType); \\\n\t} \\\n\tif (target != 0 && targetSize < sizeof(_outputType)) { \\\n\t\tUTF8_SET_ERROR(NOT_ENOUGH_SPACE); \\\n\t\treturn _result; \\\n\t} \\\n\tif ((char*)input == (char*)target) { \\\n\t\tUTF8_SET_ERROR(OVERLAPPING_PARAMETERS); \\\n\t\treturn _result; \\\n\t} \\\n\t{ \\\n\t\tchar* input_center = (char*)input + (inputSize / 2); \\\n\t\tchar* target_center = (char*)target + (targetSize / 2); \\\n\t\tsize_t delta = (size_t)((input_center > target_center) ? (input_center - target_center) : (target_center - input_center)); \\\n\t\tif (delta < (inputSize + targetSize) / 2) { \\\n\t\t\tUTF8_SET_ERROR(OVERLAPPING_PARAMETERS); \\\n\t\t\treturn _result; \\\n\t\t} \\\n\t}\n\n/*! \\endcond */\n\n#endif /* _UTF8REWIND_INTERNAL_BASE_H_ */"
  },
  {
    "path": "external/utf8rewind/source/internal/casemapping.c",
    "content": "/*\n\tCopyright (C) 2014-2016 Quinten Lansu\n\n\tPermission is hereby granted, free of charge, to any person\n\tobtaining a copy of this software and associated documentation\n\tfiles (the \"Software\"), to deal in the Software without\n\trestriction, including without limitation the rights to use,\n\tcopy, modify, merge, publish, distribute, sublicense, and/or\n\tsell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following\n\tconditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n*/\n\n#include \"casemapping.h\"\n\n#include \"base.h\"\n#include \"codepoint.h\"\n#include \"database.h\"\n#include \"streaming.h\"\n\nstatic const char basic_latin_lowercase_table[58] = {\n\t/* LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z */\n\t0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C,\n\t0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,\n\t0x79, 0x7A,\n\n\t0x5B, /* LEFT SQUARE BRACKET */\n\t0x5C, /* REVERSE SOLIDUS */\n\t0x5D, /* RIGHT SQUARE BRACKET */\n\t0x5E, /* CIRCUMFLEX ACCENT */\n\t0x5F, /* LOW LINE */\n\t0x60, /* GRAVE ACCENT */\n\n\t/* LATIN SMALL LETTER A - LATIN SMALL LETTER Z */\n\t0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C,\n\t0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,\n\t0x79, 0x7A\n};\n\nstatic const char basic_latin_uppercase_table[58] = {\n\t/* LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z */\n\t0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,\n\t0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,\n\t0x59, 0x5A,\n\n\t0x5B, /* LEFT SQUARE BRACKET */\n\t0x5C, /* REVERSE SOLIDUS */\n\t0x5D, /* RIGHT SQUARE BRACKET */\n\t0x5E, /* CIRCUMFLEX ACCENT */\n\t0x5F, /* LOW LINE */\n\t0x60, /* GRAVE ACCENT */\n\n\t/* LATIN SMALL LETTER A - LATIN SMALL LETTER Z */\n\t0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,\n\t0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,\n\t0x59, 0x5A\n};\n\nuint8_t casemapping_initialize(\n\tCaseMappingState* state,\n\tconst char* input, size_t inputSize,\n\tchar* target, size_t targetSize,\n\tconst uint32_t* propertyIndex1, const uint32_t* propertyIndex2, const uint32_t* propertyData,\n\tuint8_t quickCheck, size_t locale,\n\tint32_t* errors)\n{\n\tmemset(state, 0, sizeof(CaseMappingState));\n\n\tif (locale >= UTF8_LOCALE_MAXIMUM)\n\t{\n\t\tUTF8_SET_ERROR(INVALID_LOCALE);\n\n\t\treturn 0;\n\t}\n\n\tstate->src = input;\n\tstate->src_size = inputSize;\n\tstate->dst = target;\n\tstate->dst_size = targetSize;\n\tstate->property_index1 = propertyIndex1;\n\tstate->property_index2 = propertyIndex2;\n\tstate->property_data = propertyData;\n\tstate->quickcheck_flags = quickCheck;\n\tstate->locale = locale;\n\n\treturn 1;\n}\n\nsize_t casemapping_execute(CaseMappingState* state, int32_t* errors)\n{\n\tuint8_t qc_casemapped = 0;\n\tuint8_t bytes_needed = 0;\n\tconst char* resolved = 0;\n\tStreamState stream;\n\tuint8_t i;\n\n\t/* Read next code point */\n\n\tstate->last_code_point_size = codepoint_read(state->src, state->src_size, &state->last_code_point);\n\tif (state->last_code_point_size == 0)\n\t{\n\t\tgoto invaliddata;\n\t}\n\n\t/* Check for invalid characters */\n\n\tif (state->last_code_point == REPLACEMENT_CHARACTER)\n\t{\n\t\t/* Get code point properties */\n\n\t\tstate->last_canonical_combining_class = CCC_NOT_REORDERED;\n\t\tstate->last_general_category = UTF8_CATEGORY_SYMBOL_OTHER;\n\n\t\tresolved = REPLACEMENT_CHARACTER_STRING;\n\t\tbytes_needed = REPLACEMENT_CHARACTER_STRING_LENGTH;\n\n\t\tgoto writeresolved;\n\t}\n\n\tif (state->locale == UTF8_LOCALE_TURKISH_AND_AZERI_LATIN)\n\t{\n\t\t/*\n\t\t\tCode point General Category does not need to be modified, because\n\t\t\tall mappings result in the same General Category\n\t\t*/\n\n\t\tif (state->property_data == LowercaseDataPtr)\n\t\t{\n\t\t\tif (state->last_code_point == CP_LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE)\n\t\t\t{\n\t\t\t\tstate->last_code_point = CP_LATIN_SMALL_LETTER_I;\n\n\t\t\t\tresolved = \"i\";\n\t\t\t\tbytes_needed = 1;\n\t\t\t}\n\t\t\telse if (\n\t\t\t\tstate->last_code_point == CP_LATIN_CAPITAL_LETTER_I)\n\t\t\t{\n\t\t\t\tif (state->src_size == 0)\n\t\t\t\t{\n\t\t\t\t\t/* Early-out for easy case */\n\n\t\t\t\t\tstate->last_code_point = CP_LATIN_SMALL_LETTER_DOTLESS_I;\n\n\t\t\t\t\tresolved = \"\\xC4\\xB1\";\n\t\t\t\t\tbytes_needed = 2;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tuint8_t found = 0;\n\n\t\t\t\t\t/* Initialize stream and read the next sequence */\n\n\t\t\t\t\tif (!stream_initialize(&stream, state->src, state->src_size) ||\n\t\t\t\t\t\t!stream_read(&stream, QuickCheckNFCIndexPtr, QuickCheckNFCDataPtr))\n\t\t\t\t\t{\n\t\t\t\t\t\tgoto writeregular;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Erase COMBINING DOT ABOVE from sequence */\n\n\t\t\t\t\tfor (i = stream.current - 1; i > 0; --i)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (stream.codepoint[i] == CP_COMBINING_DOT_ABOVE)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstream.canonical_combining_class[i] = CCC_INVALID;\n\n\t\t\t\t\t\t\tfound++;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Stabilize sequence and write to output */\n\n\t\t\t\t\tif (!stream.stable ||\n\t\t\t\t\t\tfound > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tstream_reorder(&stream);\n\n\t\t\t\t\t\tstream.current -= found;\n\t\t\t\t\t}\n\n\t\t\t\t\tstream.codepoint[0] = (found > 0) ? CP_LATIN_SMALL_LETTER_I : CP_LATIN_SMALL_LETTER_DOTLESS_I;\n\n\t\t\t\t\tgoto writestream;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (state->last_code_point == CP_LATIN_SMALL_LETTER_I)\n\t\t\t{\n\t\t\t\tstate->last_code_point = CP_LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE;\n\n\t\t\t\tresolved = \"\\xC4\\xB0\";\n\t\t\t\tbytes_needed = 2;\n\t\t\t}\n\t\t\telse if (\n\t\t\t\tstate->last_code_point == CP_LATIN_SMALL_LETTER_DOTLESS_I)\n\t\t\t{\n\t\t\t\tstate->last_code_point = CP_LATIN_CAPITAL_LETTER_I;\n\n\t\t\t\tresolved = \"I\";\n\t\t\t\tbytes_needed = 1;\n\t\t\t}\n\t\t}\n\n\t\t/* Check if mapping succeeded */\n\n\t\tif (resolved != 0)\n\t\t{\n\t\t\t/* Code point properties */\n\n\t\t\tstate->last_general_category = UTF8_CATEGORY_LETTER;\n\n\t\t\tgoto writeresolved;\n\t\t}\n\t}\n\telse if (\n\t\tstate->locale == UTF8_LOCALE_LITHUANIAN)\n\t{\n\t\tif (state->property_data == LowercaseDataPtr)\n\t\t{\n\t\t\tunicode_t cp_additional_accent = 0;\n\t\t\tuint8_t write_soft_dot = 1;\n\n\t\t\tswitch (state->last_code_point)\n\t\t\t{\n\n\t\t\tcase CP_LATIN_CAPITAL_LETTER_I:\n\t\t\t\tstate->last_code_point = CP_LATIN_SMALL_LETTER_I;\n\t\t\t\tbreak;\n\n\t\t\tcase CP_LATIN_CAPITAL_LETTER_J:\n\t\t\t\tstate->last_code_point = CP_LATIN_SMALL_LETTER_J;\n\t\t\t\tbreak;\n\n\t\t\tcase CP_LATIN_CAPITAL_LETTER_I_WITH_OGONEK:\n\t\t\t\tstate->last_code_point = CP_LATIN_SMALL_LETTER_I_WITH_OGONEK;\n\t\t\t\tbreak;\n\n\t\t\tcase CP_LATIN_CAPITAL_LETTER_I_WITH_GRAVE:\n\t\t\t\tstate->last_code_point = CP_LATIN_SMALL_LETTER_I;\n\t\t\t\tcp_additional_accent = CP_COMBINING_GRAVE_ACCENT;\n\t\t\t\tbreak;\n\n\t\t\tcase CP_LATIN_CAPITAL_LETTER_I_WITH_ACUTE:\n\t\t\t\tstate->last_code_point = CP_LATIN_SMALL_LETTER_I;\n\t\t\t\tcp_additional_accent = CP_COMBINING_ACUTE_ACCENT;\n\t\t\t\tbreak;\n\n\t\t\tcase CP_LATIN_CAPITAL_LETTER_I_WITH_TILDE:\n\t\t\t\tstate->last_code_point = CP_LATIN_SMALL_LETTER_I;\n\t\t\t\tcp_additional_accent = CP_COMBINING_TILDE_ACCENT;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tgoto writeregular;\n\n\t\t\t}\n\n\t\t\t/* Initialize stream and read the next sequence */\n\n\t\t\tif (!stream_initialize(&stream, state->src, state->src_size) ||\n\t\t\t\t!stream_read(&stream, QuickCheckNFCIndexPtr, QuickCheckNFCDataPtr))\n\t\t\t{\n\t\t\t\tgoto writeregular;\n\t\t\t}\n\n\t\t\t/* Assign the lowercase code point to the start of the stream */\n\n\t\t\tstream.codepoint[0] = state->last_code_point;\n\n\t\t\t/* Check if COMBINING DOT ABOVE is not yet present */ \n\n\t\t\tfor (i = stream.current - 1; i > 0; --i)\n\t\t\t{\n\t\t\t\tif (stream.codepoint[i] == CP_COMBINING_DOT_ABOVE)\n\t\t\t\t{\n\t\t\t\t\twrite_soft_dot = 0;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Stabilize the sequence */\n\n\t\t\tif (!stream.stable)\n\t\t\t{\n\t\t\t\tstream_reorder(&stream);\n\n\t\t\t\tstream.stable = 1;\n\t\t\t}\n\n\t\t\t/* Write COMBINING DOT ABOVE */\n\n\t\t\tif (write_soft_dot &&\n\t\t\t\tstream.current < STREAM_BUFFER_MAX)\n\t\t\t{\n\t\t\t\t/* Ensure the COMBINING DOT ABOVE comes before other accents with the same CCC */\n\n\t\t\t\tif (stream.canonical_combining_class[stream.current - 1] == CCC_ABOVE)\n\t\t\t\t{\n\t\t\t\t\tunicode_t cp_swap = stream.codepoint[stream.current - 1];\n\t\t\t\t\tstream.codepoint[stream.current - 1] = CP_COMBINING_DOT_ABOVE;\n\t\t\t\t\tstream.codepoint[stream.current] = cp_swap;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tstream.codepoint[stream.current] = CP_COMBINING_DOT_ABOVE;\n\t\t\t\t}\n\n\t\t\t\tstream.canonical_combining_class[stream.current] = CCC_ABOVE;\n\n\t\t\t\t/* Check if sequence has become unstable */\n\n\t\t\t\tstream.stable = stream.canonical_combining_class[stream.current - 1] <= CCC_ABOVE;\n\n\t\t\t\tstream.current++;\n\t\t\t}\n\n\t\t\t/* Write additional accent */\n\n\t\t\tif (cp_additional_accent != 0 &&\n\t\t\t\tstream.current < STREAM_BUFFER_MAX)\n\t\t\t{\n\t\t\t\t/* Additional accents are always of the upper variety */\n\n\t\t\t\tstream.codepoint[stream.current] = cp_additional_accent;\n\t\t\t\tstream.canonical_combining_class[stream.current] = CCC_ABOVE;\n\n\t\t\t\t/* Check if sequence has become unstable */\n\n\t\t\t\tif (stream.stable &&\n\t\t\t\t\tstream.canonical_combining_class[stream.current] < stream.canonical_combining_class[stream.current - 1])\n\t\t\t\t{\n\t\t\t\t\tstream.stable = 0;\n\t\t\t\t}\n\n\t\t\t\tstream.current++;\n\t\t\t}\n\n\t\t\t/* Stabilize the sequence */\n\n\t\t\tif (!stream.stable)\n\t\t\t{\n\t\t\t\tstream_reorder(&stream);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tuint8_t erase_count = 0;\n\n\t\t\tswitch (state->last_code_point)\n\t\t\t{\n\n\t\t\tcase CP_LATIN_SMALL_LETTER_I:\n\t\t\t\tstate->last_code_point = CP_LATIN_CAPITAL_LETTER_I;\n\t\t\t\tbreak;\n\n\t\t\tcase CP_LATIN_SMALL_LETTER_J:\n\t\t\t\tstate->last_code_point = CP_LATIN_CAPITAL_LETTER_J;\n\t\t\t\tbreak;\n\n\t\t\tcase CP_LATIN_SMALL_LETTER_I_WITH_OGONEK:\n\t\t\t\tstate->last_code_point = CP_LATIN_CAPITAL_LETTER_I_WITH_OGONEK;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tgoto writeregular;\n\n\t\t\t}\n\n\t\t\t/* Initialize stream and read the next sequence */\n\n\t\t\tif (!stream_initialize(&stream, state->src, state->src_size) ||\n\t\t\t\t!stream_read(&stream, QuickCheckNFCIndexPtr, QuickCheckNFCDataPtr))\n\t\t\t{\n\t\t\t\tgoto writeregular;\n\t\t\t}\n\n\t\t\t/* Assign the uppercase code point to the start of the stream */\n\n\t\t\tstream.codepoint[0] = state->last_code_point;\n\n\t\t\t/* Remove COMBINING DOT ABOVE from sequence */\n\n\t\t\tfor (i = 1; i < stream.current; ++i)\n\t\t\t{\n\t\t\t\tif (stream.codepoint[i] == CP_COMBINING_DOT_ABOVE)\n\t\t\t\t{\n\t\t\t\t\tstream.canonical_combining_class[i] = CCC_INVALID;\n\t\t\t\t\terase_count++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Stabilize the sequence */\n\n\t\t\tif (!stream.stable ||\n\t\t\t\terase_count > 0)\n\t\t\t{\n\t\t\t\tstream_reorder(&stream);\n\n\t\t\t\tstream.current -= erase_count;\n\t\t\t}\n\t\t}\n\n\t\tgoto writestream;\n\t}\n\nwriteregular:\n\t/* Get code point properties */\n\n\tstate->last_canonical_combining_class = PROPERTY_GET_CCC(state->last_code_point);\n\tstate->last_general_category = PROPERTY_GET_GC(state->last_code_point);\n\n\t/* Move source cursor */\n\n\tif (state->src_size >= state->last_code_point_size)\n\t{\n\t\tstate->src += state->last_code_point_size;\n\t\tstate->src_size -= state->last_code_point_size;\n\t}\n\telse\n\t{\n\t\tstate->src_size = 0;\n\t}\n\n\t/* Write to output */\n\n\tif (state->last_code_point_size == 1)\n\t{\n\t\t/* Write Basic Latin to output buffer*/\n\n\t\tif (state->dst != 0)\n\t\t{\n\t\t\tif (state->dst_size < 1)\n\t\t\t{\n\t\t\t\tgoto outofspace;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tUppercase letters are U+0041 ('A') to U+005A ('Z')\n\t\t\t\tLowercase letters are U+0061 ('a') to U+007A ('z')\n\t\t\t*/\n\n\t\t\tif (state->last_code_point >= 0x41 &&\n\t\t\t\tstate->last_code_point <= 0x7A)\n\t\t\t{\n\t\t\t\tif (state->property_data == LowercaseDataPtr)\n\t\t\t\t{\n\t\t\t\t\t*state->dst = basic_latin_lowercase_table[state->last_code_point - 0x41];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t*state->dst = basic_latin_uppercase_table[state->last_code_point - 0x41];\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* All other code points in Basic Latin are unaffected by case mapping */\n\n\t\t\t\t*state->dst = (char)state->last_code_point;\n\t\t\t}\n\n\t\t\tstate->dst++;\n\t\t\tstate->dst_size--;\n\t\t}\n\n\t\tbytes_needed = 1;\n\t}\n\telse\n\t{\n\t\tif (state->property_data == LowercaseDataPtr &&\n\t\t\tstate->last_code_point == CP_GREEK_CAPITAL_LETTER_SIGMA)\n\t\t{\n\t\t\t/*\n\t\t\t\tIf the final letter of a word (defined as \"a collection of code\n\t\t\t\tpoints with the General Category 'Letter'\") is a GREEK CAPITAL\n\t\t\t\tLETTER SIGMA and more than one code point was processed, the\n\t\t\t\tlowercase version is U+03C2 GREEK SMALL LETTER FINAL SIGMA\n\t\t\t\tinstead of U+03C3 GREEK SMALL LETTER SIGMA.\n\t\t\t*/\n\n\t\t\t/* At least one code point should have been read */\n\n\t\t\tuint8_t should_convert = state->total_bytes_needed > 0;\n\n\t\t\tif (state->src_size > 0)\n\t\t\t{\n\t\t\t\tunicode_t peeked = 0;\n\t\t\t\tconst char* peeked_src = state->src;\n\t\t\t\tsize_t peeked_src_size = state->src_size;\n\n\t\t\t\twhile (1)\n\t\t\t\t{\n\t\t\t\t\tuint8_t peeked_read = 0;\n\n\t\t\t\t\t/* Peek next code point */\n\n\t\t\t\t\tif ((peeked_read = codepoint_read(peeked_src, peeked_src_size, &peeked)) == 0 ||\n\t\t\t\t\t\tpeeked_src_size < peeked_read)\n\t\t\t\t\t{\n\t\t\t\t\t\tshould_convert = 1;\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Convert if the \"word\" has ended */\n\n\t\t\t\t\tif (PROPERTY_GET_CCC(peeked) == CCC_NOT_REORDERED)\n\t\t\t\t\t{\n\t\t\t\t\t\tshould_convert = (PROPERTY_GET_GC(peeked) & UTF8_CATEGORY_LETTER) == 0;\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tpeeked_src += peeked_read;\n\t\t\t\t\tpeeked_src_size -= peeked_read;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Write the converted code point to the output buffer */\n\n\t\t\tbytes_needed = 2;\n\n\t\t\tif (state->dst != 0)\n\t\t\t{\n\t\t\t\tif (state->dst_size < bytes_needed)\n\t\t\t\t{\n\t\t\t\t\tgoto outofspace;\n\t\t\t\t}\n\n\t\t\t\tmemcpy(state->dst, should_convert ? \"\\xCF\\x82\" : \"\\xCF\\x83\", bytes_needed);\n\n\t\t\t\tstate->dst += bytes_needed;\n\t\t\t\tstate->dst_size -= bytes_needed;\n\t\t\t}\n\n\t\t\treturn bytes_needed;\n\t\t}\n\n\t\t/* Check if the code point is case mapped */\n\n\t\tqc_casemapped = PROPERTY_GET_CM(state->last_code_point);\n\t\tif ((qc_casemapped & state->quickcheck_flags) != 0)\n\t\t{\n\t\t\t/* Attempt to resolve the case mapping */\n\n\t\t\tresolved = database_querydecomposition(state->last_code_point, state->property_index1, state->property_index2, state->property_data, &bytes_needed);\n\t\t\tif (resolved != 0)\n\t\t\t{\n\t\t\t\t/* Code point properties */\n\n\t\t\t\tstate->last_general_category = UTF8_CATEGORY_LETTER;\n\n\t\t\t\tgoto writeresolvedonly;\n\t\t\t}\n\t\t}\n\n\t\t/* Write code point unchanged to output */\n\n\t\tbytes_needed = codepoint_write(state->last_code_point, &state->dst, &state->dst_size);\n\t\tif (bytes_needed == 0)\n\t\t{\n\t\t\tgoto outofspace;\n\t\t}\n\t}\n\n\treturn bytes_needed;\n\nwriteresolved:\n\t/* Move source cursor */\n\n\tif (state->src_size >= state->last_code_point_size)\n\t{\n\t\tstate->src += state->last_code_point_size;\n\t\tstate->src_size -= state->last_code_point_size;\n\t}\n\telse\n\t{\n\t\tstate->src_size = 0;\n\t}\n\nwriteresolvedonly:\n\t/* Write resolved string to output */\n\n\tif (state->dst != 0)\n\t{\n\t\tif (state->dst_size < bytes_needed)\n\t\t{\n\t\t\tgoto outofspace;\n\t\t}\n\n\t\tmemcpy(state->dst, resolved, bytes_needed);\n\n\t\tstate->dst += bytes_needed;\n\t\tstate->dst_size -= bytes_needed;\n\t}\n\n\treturn bytes_needed;\n\nwritestream:\n\t/* Get code point properties */\n\n\tstate->last_code_point = stream.codepoint[stream.current - 1];\n\tstate->last_canonical_combining_class = stream.canonical_combining_class[stream.current - 1];\n\tstate->last_general_category = PROPERTY_GET_GC(stream.codepoint[0]);\n\n\t/* Move source cursor */\n\n\tstate->src = stream.src;\n\tstate->src_size = stream.src_size;\n\n\t/* Write result to the output buffer */\n\n\tif (!stream_write(&stream, &state->dst, &state->dst_size, &bytes_needed))\n\t{\n\t\tgoto outofspace;\n\t}\n\n\treturn bytes_needed;\n\ninvaliddata:\n\tUTF8_SET_ERROR(INVALID_DATA);\n\n\tstate->src_size = 0;\n\n\treturn 0;\n\noutofspace:\n\tUTF8_SET_ERROR(NOT_ENOUGH_SPACE);\n\n\tstate->src_size = 0;\n\n\treturn 0;\n}"
  },
  {
    "path": "external/utf8rewind/source/internal/casemapping.h",
    "content": "/*\n\tCopyright (C) 2014-2016 Quinten Lansu\n\n\tPermission is hereby granted, free of charge, to any person\n\tobtaining a copy of this software and associated documentation\n\tfiles (the \"Software\"), to deal in the Software without\n\trestriction, including without limitation the rights to use,\n\tcopy, modify, merge, publish, distribute, sublicense, and/or\n\tsell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following\n\tconditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n*/\n\n#ifndef _UTF8REWIND_INTERNAL_CASEMAPPING_H_\n#define _UTF8REWIND_INTERNAL_CASEMAPPING_H_\n\n/*!\n\t\\file\n\t\\brief Case mapping interface.\n\n\t\\cond INTERNAL\n*/\n\n#include \"../../include/utf8rewind/utf8rewind.h\"\n\ntypedef struct {\n\tconst char* src;\n\tchar* dst;\n\tsize_t src_size;\n\tsize_t dst_size;\n\tsize_t total_bytes_needed;\n\tunicode_t last_code_point;\n\tsize_t locale;\n\tconst uint32_t* property_index1;\n\tconst uint32_t* property_index2;\n\tconst uint32_t* property_data;\n\tuint32_t last_general_category;\n\tuint8_t last_code_point_size;\n\tuint8_t last_canonical_combining_class;\n\tuint8_t quickcheck_flags;\n} CaseMappingState;\n\nuint8_t casemapping_initialize(\n\tCaseMappingState* state,\n\tconst char* input, size_t inputSize,\n\tchar* target, size_t targetSize,\n\tconst uint32_t* propertyIndex1, const uint32_t* propertyIndex2, const uint32_t* propertyData,\n\tuint8_t quickCheck, size_t locale,\n\tint32_t* errors);\n\nsize_t casemapping_execute(CaseMappingState* state, int32_t* errors);\n\n/*! \\endcond */\n\n#endif /* _UTF8REWIND_INTERNAL_CASEMAPPING_H_ */"
  },
  {
    "path": "external/utf8rewind/source/internal/codepoint.c",
    "content": "/*\n\tCopyright (C) 2014-2016 Quinten Lansu\n\n\tPermission is hereby granted, free of charge, to any person\n\tobtaining a copy of this software and associated documentation\n\tfiles (the \"Software\"), to deal in the Software without\n\trestriction, including without limitation the rights to use,\n\tcopy, modify, merge, publish, distribute, sublicense, and/or\n\tsell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following\n\tconditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n*/\n\n#include \"codepoint.h\"\n\nconst uint8_t codepoint_decoded_length[256] = {\n\t/* Basic Latin */\n\t1, 1, 1, 1, 1, 1, 1, 1, /* 0x00 - 0x07 */\n\t1, 1, 1, 1, 1, 1, 1, 1, /* 0x08 - 0x0F */\n\t1, 1, 1, 1, 1, 1, 1, 1, /* 0x10 - 0x17 */\n\t1, 1, 1, 1, 1, 1, 1, 1, /* 0x18 - 0x1F */\n\t1, 1, 1, 1, 1, 1, 1, 1, /* 0x20 - 0x27 */\n\t1, 1, 1, 1, 1, 1, 1, 1, /* 0x28 - 0x2F */\n\t1, 1, 1, 1, 1, 1, 1, 1, /* 0x30 - 0x37 */\n\t1, 1, 1, 1, 1, 1, 1, 1, /* 0x38 - 0x3F */\n\t1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x47 */\n\t1, 1, 1, 1, 1, 1, 1, 1, /* 0x48 - 0x4F */\n\t1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 - 0x57 */\n\t1, 1, 1, 1, 1, 1, 1, 1, /* 0x58 - 0x5F */\n\t1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x67 */\n\t1, 1, 1, 1, 1, 1, 1, 1, /* 0x68 - 0x6F */\n\t1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 - 0x77 */\n\t1, 1, 1, 1, 1, 1, 1, 1, /* 0x78 - 0x7F */\n\n\t/* Malformed continuation byte */\n\t0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x87 */\n\t0, 0, 0, 0, 0, 0, 0, 0, /* 0x88 - 0x8F */\n\t0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x97 */\n\t0, 0, 0, 0, 0, 0, 0, 0, /* 0x98 - 0x9F */\n\t0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xA7 */\n\t0, 0, 0, 0, 0, 0, 0, 0, /* 0xA8 - 0xAF */\n\t0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 - 0xB7 */\n\t0, 0, 0, 0, 0, 0, 0, 0, /* 0xB8 - 0xBF */\n\n\t/* Two bytes */\n\t2, 2, 2, 2, 2, 2, 2, 2, /* 0xC0 - 0xC7 */\n\t2, 2, 2, 2, 2, 2, 2, 2, /* 0xC8 - 0xCF */\n\t2, 2, 2, 2, 2, 2, 2, 2, /* 0xD0 - 0xD7 */\n\t2, 2, 2, 2, 2, 2, 2, 2, /* 0xD8 - 0xDF */\n\n\t/* Three bytes */\n\t3, 3, 3, 3, 3, 3, 3, 3, /* 0xE0 - 0xE7 */\n\t3, 3, 3, 3, 3, 3, 3, 3, /* 0xE8 - 0xEF */\n\n\t/* Four bytes */\n\t4, 4, 4, 4, 4, 4, 4, 4, /* 0xF0 - 0xF7 */\n\n\t/* Five bytes */\n\t5, 5, 5, 5,             /* 0xF8 - 0xFB */\n\n\t/* Six bytes */\n\t6, 6,                   /* 0xFC - 0xFD */\n\n\t/* Invalid */\n\t7, 7                    /* 0xFE - 0xFF */\n};\n\nuint8_t codepoint_write(unicode_t encoded, char** target, size_t* targetSize)\n{\n\tuint8_t encoded_length;\n\n\t/* Determine encoded length of code point */\n\n\tif (encoded <= MAX_BASIC_LATIN)\n\t{\n\t\tencoded_length = 1;\n\t}\n\telse if (\n\t\tencoded <= 0x7FF)\n\t{\n\t\tencoded_length = 2;\n\t}\n\telse if (\n\t\tencoded <= MAX_BASIC_MULTILINGUAL_PLANE)\n\t{\n\t\tencoded_length = 3;\n\t}\n\telse if (\n\t\tencoded > MAX_LEGAL_UNICODE)\n\t{\n\t\tencoded = REPLACEMENT_CHARACTER;\n\t\tencoded_length = REPLACEMENT_CHARACTER_STRING_LENGTH;\n\t}\n\telse\n\t{\n\t\tencoded_length = 4;\n\t}\n\n\t/* Write to target */\n\n\tif (*target != 0)\n\t{\n\t\tchar* dst;\n\n\t\tif (*targetSize < encoded_length)\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\n\t\tdst = *target;\n\n\t\tswitch (encoded_length)\n\t\t{\n\n\t\tcase 1:\n\t\t\t*dst++ = (char)encoded;\n\t\t\tbreak;\n\n\t\tcase 2:\n\t\t\t*dst++ = (char)(encoded >>   6)         | 0xC0;\n\t\t\t*dst++ = (char)(encoded         & 0x3F) | 0x80;\n\t\t\tbreak;\n\n\t\tcase 3:\n\t\t\t*dst++ = (char)(encoded  >> 12)         | 0xE0;\n\t\t\t*dst++ = (char)((encoded >>  6) & 0x3F) | 0x80;\n\t\t\t*dst++ = (char)(encoded         & 0x3F) | 0x80;\n\t\t\tbreak;\n\n\t\tcase 4:\n\t\t\t*dst++ = (char)(encoded  >> 18)         | 0xF0;\n\t\t\t*dst++ = (char)((encoded >> 12) & 0x3F) | 0x80;\n\t\t\t*dst++ = (char)((encoded >>  6) & 0x3F) | 0x80;\n\t\t\t*dst++ = (char)(encoded         & 0x3F) | 0x80;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\n\t\t}\n\n\t\t*target += encoded_length;\n\t\t*targetSize -= encoded_length;\n\t}\n\n\treturn encoded_length;\n}\n\nuint8_t codepoint_read(const char* input, size_t inputSize, unicode_t* decoded)\n{\n\tconst uint8_t* src = (const uint8_t*)input;\n\n\tif (input == 0 ||\n\t\tinputSize == 0)\n\t{\n\t\t/* Invalid data */\n\n\t\treturn 0;\n\t}\n\n\tif (*src <= MAX_BASIC_LATIN)\n\t{\n\t\t/* Basic Latin */\n\n\t\t*decoded = (unicode_t)*src;\n\n\t\treturn 1;\n\t}\n\telse\n\t{\n\t\t/* Multi-byte sequence */\n\n\t\tstatic const uint8_t SequenceMask[7] = {\n\t\t\t0x00, 0x7F, 0x1F, 0x0F,\n\t\t\t0x07, 0x03, 0x01\n\t\t};\n\t\tstatic const unicode_t SequenceMinimum[7] = {\n\t\t\t0x0000, 0x0000, 0x0080, 0x0800,\n\t\t\t0x10000, MAX_LEGAL_UNICODE, MAX_LEGAL_UNICODE\n\t\t};\n\n\t\tsize_t src_size = inputSize;\n\t\tuint8_t src_index;\n\n\t\t/* Length of sequence is determined by first byte */\n\n\t\tuint8_t decoded_length = codepoint_decoded_length[*src];\n\t\tif (decoded_length < 1 ||\n\t\t\tdecoded_length > 6)\n\t\t{\n\t\t\t/* Not a multi-byte sequence starter */\n\n\t\t\t*decoded = REPLACEMENT_CHARACTER;\n\t\t\tdecoded_length = 1;\n\t\t}\n\t\telse if (decoded_length > 4)\n\t\t{\n\t\t\t/* Always an overlong sequence */\n\n\t\t\t*decoded = REPLACEMENT_CHARACTER;\n\n\t\t\t/* All bytes in the sequence must be processed */\n\n\t\t\tfor (src_index = 1; src_index < decoded_length; ++src_index)\n\t\t\t{\n\t\t\t\tsrc++;\n\n\t\t\t\t/* Check if next byte is valid */\n\n\t\t\t\tif (src_size == 0 ||               /* Not enough data */\n\t\t\t\t\t(*src < 0x80 || *src > 0xBF))  /* Not a continuation byte */\n\t\t\t\t{\n\t\t\t\t\treturn src_index;\n\t\t\t\t}\n\n\t\t\t\tsrc_size--;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/* Use mask to strip value from first byte */\n\n\t\t\t*decoded = (unicode_t)(*src & SequenceMask[decoded_length]);\n\n\t\t\t/* All bytes in the sequence must be processed */\n\n\t\t\tfor (src_index = 1; src_index < decoded_length; ++src_index)\n\t\t\t{\n\t\t\t\tsrc++;\n\n\t\t\t\t/* Check if next byte is valid */\n\n\t\t\t\tif (src_size == 0 ||               /* Not enough data */\n\t\t\t\t\t(*src < 0x80 || *src > 0xBF))  /* Not a continuation byte */\n\t\t\t\t{\n\t\t\t\t\t*decoded = REPLACEMENT_CHARACTER;\n\n\t\t\t\t\treturn src_index;\n\t\t\t\t}\n\n\t\t\t\tsrc_size--;\n\n\t\t\t\t/* Add value of continuation byte to codepoint */\n\n\t\t\t\t*decoded = (*decoded << 6) | (*src & 0x3F);\n\t\t\t}\n\n\t\t\t/* Check for overlong sequences and surrogate pairs */\n\n\t\t\tif (*decoded < SequenceMinimum[decoded_length] ||\n\t\t\t\t*decoded > MAX_LEGAL_UNICODE ||\n\t\t\t\t(*decoded >= SURROGATE_HIGH_START && *decoded <= SURROGATE_LOW_END))\n\t\t\t{\n\t\t\t\t*decoded = REPLACEMENT_CHARACTER;\n\t\t\t}\n\t\t}\n\n\t\treturn decoded_length;\n\t}\n}"
  },
  {
    "path": "external/utf8rewind/source/internal/codepoint.h",
    "content": "/*\n\tCopyright (C) 2014-2016 Quinten Lansu\n\n\tPermission is hereby granted, free of charge, to any person\n\tobtaining a copy of this software and associated documentation\n\tfiles (the \"Software\"), to deal in the Software without\n\trestriction, including without limitation the rights to use,\n\tcopy, modify, merge, publish, distribute, sublicense, and/or\n\tsell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following\n\tconditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n*/\n\n#ifndef _UTF8REWIND_INTERNAL_CODEPOINT_H_\n#define _UTF8REWIND_INTERNAL_CODEPOINT_H_\n\n/*!\n\t\\file\n\t\\brief Codepoint interface.\n\n\t\\cond INTERNAL\n*/\n\n#include \"../../include/utf8rewind/utf8rewind.h\"\n\n/*!\n\t\\addtogroup internal Internal functions and definitions\n\t\\{\n*/\n\n/*!\n\t\\def MAX_BASIC_LATIN\n\t\\brief The last codepoint part of Basic Latin (U+0000 - U+007F).\n*/\n#define MAX_BASIC_LATIN                      0x007F\n\n/*!\n\t\\def MAX_LATIN_1\n\t\\brief The last codepoint part of Latin-1 Supplement (U+0080 - U+00FF).\n*/\n#define MAX_LATIN_1                          0x00FF\n\n/*!\n\t\\def MAX_BASIC_MULTILINGUAL_PLANE\n\t\\brief The last legal codepoint in the Basic Multilingual Plane (BMP).\n*/\n#define MAX_BASIC_MULTILINGUAL_PLANE         0xFFFF\n\n/*!\n\t\\def MAX_LEGAL_UNICODE\n\t\\brief The last legal codepoint in Unicode.\n*/\n#define MAX_LEGAL_UNICODE                    0x10FFFF\n\n/*!\n\t\\def REPLACEMENT_CHARACTER\n\t\\brief The codepoint used to replace illegal codepoints.\n*/\n#define REPLACEMENT_CHARACTER                0xFFFD\n\n/*!\n\t\\def REPLACEMENT_CHARACTER_STRING\n\t\\brief The replacement character as a UTF-8 encoded string.\n*/\n#define REPLACEMENT_CHARACTER_STRING         \"\\xEF\\xBF\\xBD\"\n\n/*!\n\t\\def REPLACEMENT_CHARACTER_STRING_LENGTH\n\t\\brief Length of the UTF-8 encoded string of the replacment character.\n*/\n#define REPLACEMENT_CHARACTER_STRING_LENGTH  3\n\n/*!\n\t\\def SURROGATE_HIGH_START\n\t\\brief The minimum codepoint for the high member of a surrogate pair.\n*/\n#define SURROGATE_HIGH_START                 0xD800\n\n/*!\n\t\\def SURROGATE_HIGH_END\n\t\\brief The maximum codepoint for the high member of a surrogate pair.\n*/\n#define SURROGATE_HIGH_END                   0xDBFF\n\n/*!\n\t\\def SURROGATE_LOW_START\n\t\\brief The minimum codepoint for the low member of a surrogate pair.\n*/\n#define SURROGATE_LOW_START                  0xDC00\n\n/*!\n\t\\def SURROGATE_LOW_END\n\t\\brief The maximum codepoint for the low member of a surrogate pair.\n*/\n#define SURROGATE_LOW_END                    0xDFFF\n\n/*!\n\t\\def HANGUL_JAMO_FIRST\n\t\\brief The first codepoint part of the Hangul Jamo block.\n*/\n#define HANGUL_JAMO_FIRST                    0x1100\n\n/*!\n\t\\def HANGUL_JAMO_LAST\n\t\\brief The last codepoint part of the Hangul Jamo block.\n*/\n#define HANGUL_JAMO_LAST                     0x11FF\n\n/*!\n\t\\def HANGUL_L_FIRST\n\t\\brief The first codepoint part of the Hangul Jamo L section used for\n\tnormalization.\n*/\n#define HANGUL_L_FIRST                       0x1100\n\n/*!\n\t\\def HANGUL_L_LAST\n\t\\brief The last codepoint part of the Hangul Jamo L section used for\n\tnormalization.\n*/\n#define HANGUL_L_LAST                        0x1112\n\n/*!\n\t\\def HANGUL_L_COUNT\n\t\\brief The number of codepoints in the Hangul Jamo L section.\n*/\n#define HANGUL_L_COUNT                       19\n\n/*!\n\t\\def HANGUL_V_FIRST\n\t\\brief The first codepoint part of the Hangul Jamo V section used for\n\tnormalization.\n*/\n#define HANGUL_V_FIRST                       0x1161\n\n/*!\n\t\\def HANGUL_V_LAST\n\t\\brief The last codepoint part of the Hangul Jamo V section used for\n\tnormalization.\n*/\n#define HANGUL_V_LAST                        0x1175\n\n/*!\n\t\\def HANGUL_V_COUNT\n\t\\brief The number of codepoints in the Hangul Jamo V section.\n*/\n#define HANGUL_V_COUNT                       21\n\n/*!\n\t\\def HANGUL_T_FIRST\n\t\\brief The first codepoint part of the Hangul Jamo T section used for\n\tnormalization.\n*/\n#define HANGUL_T_FIRST                       0x11A7\n\n/*!\n\t\\def HANGUL_T_LAST\n\t\\brief The last codepoint part of the Hangul Jamo V section used for\n\tnormalization.\n*/\n#define HANGUL_T_LAST                        0x11C2\n\n/*!\n\t\\def HANGUL_T_COUNT\n\t\\brief The number of codepoints in the Hangul Jamo T section.\n*/\n#define HANGUL_T_COUNT                       28\n\n/*!\n\t\\def HANGUL_N_COUNT\n\t\\brief Number of codepoints part of the Hangul Jamo V and T sections.\n*/\n#define HANGUL_N_COUNT                       588 /* VCount * TCount */\n\n/*!\n\t\\def HANGUL_S_FIRST\n\t\\brief The first codepoint in the Hangul Syllables block.\n*/\n#define HANGUL_S_FIRST                       0xAC00\n\n/*!\n\t\\def HANGUL_S_LAST\n\t\\brief The last codepoint in the Hangul Syllables block.\n*/\n#define HANGUL_S_LAST                        0xD7A3\n\n/*!\n\t\\def HANGUL_S_COUNT\n\t\\brief The number of codepoints in the Hangul Syllables block.\n*/\n#define HANGUL_S_COUNT                       11172 /* LCount * NCount */\n\n#define CP_LATIN_CAPITAL_LETTER_I                 0x0049\n#define CP_LATIN_CAPITAL_LETTER_J                 0x004A\n#define CP_LATIN_SMALL_LETTER_I                   0x0069\n#define CP_LATIN_SMALL_LETTER_J                   0x006A\n#define CP_LATIN_CAPITAL_LETTER_I_WITH_GRAVE      0x00CC\n#define CP_LATIN_CAPITAL_LETTER_I_WITH_ACUTE      0x00CD\n#define CP_LATIN_CAPITAL_LETTER_I_WITH_TILDE      0x0128\n#define CP_LATIN_CAPITAL_LETTER_I_WITH_OGONEK     0x012E\n#define CP_LATIN_SMALL_LETTER_I_WITH_OGONEK       0x012F\n#define CP_LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE  0x0130\n#define CP_LATIN_SMALL_LETTER_DOTLESS_I           0x0131\n#define CP_COMBINING_GRAVE_ACCENT                 0x0300\n#define CP_COMBINING_ACUTE_ACCENT                 0x0301\n#define CP_COMBINING_TILDE_ACCENT                 0x0303\n#define CP_COMBINING_DOT_ABOVE                    0x0307\n#define CP_COMBINING_GREEK_YPOGEGRAMMENI          0x0345\n#define CP_COMBINING_GRAPHEME_JOINER              0x034F\n#define CP_GREEK_CAPITAL_LETTER_SIGMA             0x03A3\n\n#define CCC_NOT_REORDERED                         0\n#define CCC_OVERLAY                               1\n#define CCC_NUKTA                                 7\n#define CCC_KANA_VOICING                          8\n#define CCC_VIRAMA                                9\n#define CCC_FIXED_POSITION_START                  10\n#define CCC_FIXED_POSITION_END                    199\n#define CCC_ATTACHED_BELOW_LEFT                   200\n#define CCC_ATTACHED_BELOW                        202\n#define CCC_ATTACHED_BOTTOM_RIGHT                 204\n#define CCC_ATTACHED_LEFT                         208\n#define CCC_ATTACHED_RIGHT                        210\n#define CCC_ATTACHED_TOP_LEFT                     212\n#define CCC_ATTACHED_ABOVE                        214\n#define CCC_ATTACHED_ABOVE_RIGHT                  216\n#define CCC_BELOW_LEFT                            218\n#define CCC_BELOW                                 220\n#define CCC_BELOW_RIGHT                           222\n#define CCC_LEFT                                  224\n#define CCC_RIGHT                                 226\n#define CCC_ABOVE_LEFT                            228\n#define CCC_ABOVE                                 230\n#define CCC_ABOVE_RIGHT                           232\n#define CCC_DOUBLE_BELOW                          233\n#define CCC_DOUBLE_ABOVE                          234\n#define CCC_IOTA_SUBSCRIPT                        240\n#define CCC_INVALID                               255\n\n/*!\n\t\\brief Get the number of bytes used for encoding a code point.\n\n\t\\param[in]  byte  Encoded byte\n\n\t\\return Number of bytes needed for decoding or 0 if input is illegal.\n*/\nextern const uint8_t codepoint_decoded_length[256];\n\n/*!\n\t\\brief Write Unicode code point to UTF-8 encoded string.\n\n\tTarget buffer and size is modified by encoded size.\n\n\t\\param[in]      encoded     Unicode code point\n\t\\param[in,out]  target      Target buffer\n\t\\param[in,out]  targetSize  Size of output buffer in bytes\n\n\t\\return Bytes needed for encoding or 0 on error.\n*/\nuint8_t codepoint_write(unicode_t encoded, char** target, size_t* targetSize);\n\n/*!\n\t\\brief Read Unicode code point from UTF-8 encoded string.\n\n\t\\param[in]   input      Input buffer\n\t\\param[in]   inputSize  Size of input buffer in bytes\n\t\\param[out]  decoded    Unicode codepoint\n\n\t\\return Bytes read from string or 0 on error.\n*/\nuint8_t codepoint_read(const char* input, size_t inputSize, unicode_t* decoded);\n\n/*!\n\t\\}\n*/\n\n/*! \\endcond */\n\n#endif /* _UTF8REWIND_INTERNAL_CODEPOINT_H_ */"
  },
  {
    "path": "external/utf8rewind/source/internal/composition.c",
    "content": "/*\n\tCopyright (C) 2014-2016 Quinten Lansu\n\n\tPermission is hereby granted, free of charge, to any person\n\tobtaining a copy of this software and associated documentation\n\tfiles (the \"Software\"), to deal in the Software without\n\trestriction, including without limitation the rights to use,\n\tcopy, modify, merge, publish, distribute, sublicense, and/or\n\tsell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following\n\tconditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n*/\n\n#include \"composition.h\"\n\n#include \"codepoint.h\"\n#include \"database.h\"\n\nuint8_t compose_initialize(ComposeState* state, StreamState* input, StreamState* output, uint8_t compatibility)\n{\n\tmemset(state, 0, sizeof(ComposeState));\n\n\t/* Ensure streams are valid */\n\n\tif (input == 0 ||\n\t\toutput == 0)\n\t{\n\t\treturn 0;\n\t}\n\n\t/* Set up streams */\n\n\tstate->input = input;\n\n\tstate->output = output;\n\tmemset(state->output, 0, sizeof(StreamState));\n\n\t/* Set up codepoint quickcheck property */\n\n\tif (compatibility == 1)\n\t{\n\t\tstate->qc_index = QuickCheckNFKCIndexPtr;\n\t\tstate->qc_data = QuickCheckNFKCDataPtr;\n\t}\n\telse\n\t{\n\t\tstate->qc_index = QuickCheckNFCIndexPtr;\n\t\tstate->qc_data = QuickCheckNFCDataPtr;\n\t}\n\n\treturn 1;\n}\n\nuint8_t compose_readcodepoint(ComposeState* state, uint8_t index)\n{\n\tif (state->input->index == state->input->current &&\n\t\t!stream_read(state->input, state->qc_index, state->qc_data))\n\t{\n\t\t/* End of data */\n\n\t\treturn 0;\n\t}\n\n\t/* Get next codepoint from sequence */\n\n\tstate->output->codepoint[index]                  = state->input->codepoint[state->input->index];\n\tstate->output->quick_check[index]                = state->input->quick_check[state->input->index];\n\tstate->output->canonical_combining_class[index]  = state->input->canonical_combining_class[state->input->index];\n\n\tstate->input->index++;\n\tstate->output->current++;\n\n\treturn 1;\n}\n\nuint8_t compose_execute(ComposeState* state)\n{\n\tuint8_t output_index;\n\tuint8_t cursor_current;\n\tuint8_t cursor_next;\n\n\t/* Check if input is available */\n\n\tif (state->input == 0)\n\t{\n\t\treturn 0;\n\t}\n\n\t/* Reset output */\n\n\tstate->output->current = 0;\n\n\t/* Read first codepoint */\n\n\tif (!compose_readcodepoint(state, 0))\n\t{\n\t\treturn 0;\n\t}\n\n\tfor (output_index = 0; output_index < state->output->current; ++output_index)\n\t{\n\t\t/* Ensure current codepoint is a starter */\n\n\t\tcursor_current = output_index;\n\n\t\twhile (state->output->canonical_combining_class[cursor_current] != CCC_NOT_REORDERED)\n\t\t{\n\t\t\tcursor_current++;\n\n\t\t\tif (cursor_current == state->output->current &&\n\t\t\t\t!compose_readcodepoint(state, cursor_current))\n\t\t\t{\n\t\t\t\t/* Only non-starters left */\n\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}\n\n\t\t/* Get next codepoint */\n\n\t\tcursor_next = cursor_current + 1;\n\n\t\twhile (\n\t\t\tcursor_next < state->output->current ||\n\t\t\tcompose_readcodepoint(state, cursor_next))\n\t\t{\n\t\t\t/*\n\t\t\t\tTwo codepoints can be composed if the current codepoint is a starter\n\t\t\t\tand the next codepoint isn't blocked by a previous codepoint.\n\t\t\t*/\n\n\t\t\tif (state->output->canonical_combining_class[cursor_next] > state->output->canonical_combining_class[cursor_next - 1] || /* Can be composed based on CCC */\n\t\t\t\t/* Quick check value can override composition block by previous codepoint */\n\t\t\t\t(state->output->quick_check[cursor_next] != QuickCheckResult_Yes && state->output->canonical_combining_class[cursor_next - 1] == CCC_NOT_REORDERED))\n\t\t\t{\n\t\t\t\tunicode_t composed = 0;\n\n\t\t\t\t/*\n\t\t\t\t\tHangul composition\n\n\t\t\t\t\tAlgorithm adapted from Unicode Technical Report #15:\n\t\t\t\t\thttp://www.unicode.org/reports/tr15/tr15-18.html#Hangul\n\t\t\t\t*/\n\n\t\t\t\tif (state->output->codepoint[cursor_current] >= HANGUL_L_FIRST &&\n\t\t\t\t\tstate->output->codepoint[cursor_current] <= HANGUL_L_LAST)\n\t\t\t\t{\n\t\t\t\t\t/* Check for Hangul LV pair */ \n\n\t\t\t\t\tif (state->output->codepoint[cursor_next] >= HANGUL_V_FIRST &&\n\t\t\t\t\t\tstate->output->codepoint[cursor_next] <= HANGUL_V_LAST)\n\t\t\t\t\t{\n\t\t\t\t\t\tunicode_t l_index = state->output->codepoint[cursor_current] - HANGUL_L_FIRST;\n\t\t\t\t\t\tunicode_t v_index = state->output->codepoint[cursor_next] - HANGUL_V_FIRST;\n\n\t\t\t\t\t\tcomposed = HANGUL_S_FIRST + (((l_index * HANGUL_V_COUNT) + v_index) * HANGUL_T_COUNT);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (\n\t\t\t\t\tstate->output->codepoint[cursor_current] >= HANGUL_S_FIRST &&\n\t\t\t\t\tstate->output->codepoint[cursor_current] <= HANGUL_S_LAST)\n\t\t\t\t{\n\t\t\t\t\t/* Check for Hangul LV and T pair */ \n\n\t\t\t\t\tif (state->output->codepoint[cursor_next] >= HANGUL_T_FIRST &&\n\t\t\t\t\t\tstate->output->codepoint[cursor_next] <= HANGUL_T_LAST)\n\t\t\t\t\t{\n\t\t\t\t\t\tunicode_t t_index = state->output->codepoint[cursor_next] - HANGUL_T_FIRST;\n\n\t\t\t\t\t\tcomposed = state->output->codepoint[cursor_current] + t_index;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t/* Attempt to compose codepoints using the database */\n\n\t\t\t\t\tcomposed = database_querycomposition(\n\t\t\t\t\t\tstate->output->codepoint[cursor_current],\n\t\t\t\t\t\tstate->output->codepoint[cursor_next]);\n\t\t\t\t}\n\n\t\t\t\t/* Check if composition succeeded */\n\n\t\t\t\tif (composed != 0)\n\t\t\t\t{\n\t\t\t\t\t/*\n\t\t\t\t\t\tWhen we successfully compose two codepoints, the second must be removed\n\t\t\t\t\t\tfrom the sequence. The way this is accomplished is by marking the cell\n\t\t\t\t\t\tempty with a NUL codepoint.\n\n\t\t\t\t\t\tDecomposed:\n\n\t\t\t\t\t\tcodepoint   U+0044 U+0307 U+0031\n\t\t\t\t\t\t    index        0      1      2\n\n\t\t\t\t\t\tComposed:\n\n\t\t\t\t\t\tcodepoint   U+1E0A U+0000 U+0031\n\t\t\t\t\t\t    index        0      1      2\n\n\t\t\t\t\t\tIf the second codepoint was at the end of the sequence, the output \n\t\t\t\t\t\tsequence is shortened by one.\n\t\t\t\t\t*/\n\n\t\t\t\t\t/* Add composition to output */\n\n\t\t\t\t\tstate->output->codepoint[cursor_current]                  = composed;\n\t\t\t\t\tstate->output->quick_check[cursor_current]                = PROPERTY_GET(state->qc_index, state->qc_data, composed);\n\t\t\t\t\tstate->output->canonical_combining_class[cursor_current]  = PROPERTY_GET_CCC(composed);\n\n\t\t\t\t\t/* Clear next codepoint from output */\n\n\t\t\t\t\tstate->output->codepoint[cursor_next]                  = 0;\n\t\t\t\t\tstate->output->quick_check[cursor_next]                = QuickCheckResult_Yes;\n\t\t\t\t\tstate->output->canonical_combining_class[cursor_next]  = CCC_NOT_REORDERED;\n\n\t\t\t\t\tif (cursor_next == state->output->current - 1)\n\t\t\t\t\t{\n\t\t\t\t\t\t/* Next codepoint was at end of output */\n\n\t\t\t\t\t\tstate->output->current--;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Reset cursor to current output index */\n\n\t\t\t\t\tcursor_current = output_index;\n\t\t\t\t\tcursor_next = output_index;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (\n\t\t\t\tstate->output->canonical_combining_class[cursor_next] == CCC_NOT_REORDERED)\n\t\t\t{\n\t\t\t\t/* Attempt to compose starters, but do not read from the next sequence */\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/* Evaluate next codepoint */\n\n\t\t\tcursor_next++;\n\t\t}\n\n\t\t/* Fill up \"holes\" left by composing codepoints not at the end of the sequence */\n\n\t\tif (state->output->current > 1)\n\t\t{\n\t\t\tuint8_t write_index = 0;\n\t\t\tuint8_t read_index = 1;\n\n\t\t\t/*\n\t\t\t\tWe want to move valid codepoints to the left as much as possible in order to fill up\n\t\t\t\tholes left by the composition process. \n\n\t\t\t\tNote that the process does not clear unused codepoints at the end, this is a small\n\t\t\t\toptimization in order to avoid unnecessary clears. The length member is adjusted to\n\t\t\t\tthe new size.\n\t\t\t\t\n\t\t\t\tBefore reordering:\n\n\t\t\t\tcodepoint   A  B  0  0  0  D\n\t\t\t\t    index   0  1  2  3  4  5\n\t\t\t\t   length                  6\n\n\t\t\t\tAfter reordering:\n\n\t\t\t\tcodepoint   A  B  D  0  0  D\n\t\t\t\t    index   0  1  2  3  4  5\n\t\t\t\t   length         3\n\t\t\t*/\n\n\t\t\t/* Evaluate all codepoints in output sequence */\n\n\t\t\twhile (write_index < state->output->current)\n\t\t\t{\n\t\t\t\t/* Check if read cursor is on an empty cell */\n\n\t\t\t\tif (read_index < state->output->current &&\n\t\t\t\t\tstate->output->codepoint[read_index] == 0)\n\t\t\t\t{\n\t\t\t\t\t/* Skip all empty cells */\n\n\t\t\t\t\twhile (\n\t\t\t\t\t\tread_index < state->output->current &&\n\t\t\t\t\t\tstate->output->codepoint[read_index] == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tread_index++;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (read_index == state->output->current)\n\t\t\t\t\t{\n\t\t\t\t\t\t/* Reached end of data */\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Copy cell at read cursor to write cursor */\n\n\t\t\t\t\tstate->output->codepoint[write_index]                  = state->output->codepoint[read_index];\n\t\t\t\t\tstate->output->quick_check[write_index]                = state->output->quick_check[read_index];\n\t\t\t\t\tstate->output->canonical_combining_class[write_index]  = state->output->canonical_combining_class[read_index];\n\t\t\t\t}\n\n\t\t\t\t/* Move cursors */\n\n\t\t\t\twrite_index++;\n\t\t\t\tread_index++;\n\t\t\t}\n\n\t\t\t/* Adjust length of output sequence */\n\n\t\t\tstate->output->current = write_index;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/* Evaluated all sequences in output */\n\n\t\t\tstate->input = 0;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn 1;\n}"
  },
  {
    "path": "external/utf8rewind/source/internal/composition.h",
    "content": "/*\n\tCopyright (C) 2014-2016 Quinten Lansu\n\n\tPermission is hereby granted, free of charge, to any person\n\tobtaining a copy of this software and associated documentation\n\tfiles (the \"Software\"), to deal in the Software without\n\trestriction, including without limitation the rights to use,\n\tcopy, modify, merge, publish, distribute, sublicense, and/or\n\tsell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following\n\tconditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n*/\n\n#ifndef _UTF8REWIND_INTERNAL_COMPOSITION_H_\n#define _UTF8REWIND_INTERNAL_COMPOSITION_H_\n\n/*!\n\t\\file\n\t\\brief Composition interface.\n\n\t\\cond INTERNAL\n*/\n\n#include \"../../include/utf8rewind/utf8rewind.h\"\n#include \"streaming.h\"\n\ntypedef struct {\n\tStreamState* input;\n\tStreamState* output;\n\tconst size_t* qc_index;\n\tconst uint8_t* qc_data;\n} ComposeState;\n\nuint8_t compose_initialize(ComposeState* state, StreamState* input, StreamState* output, uint8_t compatibility);\n\nuint8_t compose_readcodepoint(ComposeState* state, uint8_t index);\n\nuint8_t compose_execute(ComposeState* state);\n\n/*! \\endcond */\n\n#endif /* _UTF8REWIND_INTERNAL_COMPOSITION_H_ */"
  },
  {
    "path": "external/utf8rewind/source/internal/database.c",
    "content": "/*\n\tCopyright (C) 2014-2016 Quinten Lansu\n\n\tPermission is hereby granted, free of charge, to any person\n\tobtaining a copy of this software and associated documentation\n\tfiles (the \"Software\"), to deal in the Software without\n\trestriction, including without limitation the rights to use,\n\tcopy, modify, merge, publish, distribute, sublicense, and/or\n\tsell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following\n\tconditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n*/\n\n#include \"database.h\"\n\n#include \"../unicodedatabase.h\"\n#include \"codepoint.h\"\n\n#define DECOMPOSE_INDEX1_SHIFT (12)\n#define DECOMPOSE_INDEX2_SHIFT (5)\n\nstatic const unicode_t DECOMPOSE_INDEX1_MASK = MAX_LEGAL_UNICODE;\nstatic const unicode_t DECOMPOSE_INDEX2_MASK = (1 << DECOMPOSE_INDEX1_SHIFT) - 1;\nstatic const unicode_t DECOMPOSE_DATA_MASK = (1 << DECOMPOSE_INDEX2_SHIFT) - 1;\n\nconst char* database_querydecomposition(unicode_t codepoint, const uint32_t* index1Array, const uint32_t* index2Array, const uint32_t* dataArray, uint8_t* length)\n{\n\tuint32_t index;\n\tuint32_t data;\n\n\tindex = index1Array[codepoint >> DECOMPOSE_INDEX1_SHIFT];\n\tindex = index2Array[index + ((codepoint & DECOMPOSE_INDEX2_MASK) >> DECOMPOSE_INDEX2_SHIFT)];\n\tindex = index + (codepoint & DECOMPOSE_DATA_MASK);\n\n\tif (index == 0 ||\n\t\t(data = dataArray[index]) == 0)\n\t{\n\t\t*length = 0;\n\n\t\treturn 0;\n\t}\n\n\t*length = (uint8_t)((data & 0xFF000000) >> 24);\n\n\treturn CompressedStringData + (data & 0x00FFFFFF);\n}\n\nunicode_t database_querycomposition(unicode_t left, unicode_t right)\n{\n\tuint64_t key = ((uint64_t)left << 32) + (uint64_t)right;\n\tsize_t offset_start = 0;\n\tsize_t offset_end = UnicodeCompositionRecordCount - 1;\n\tsize_t offset_pivot;\n\tsize_t i;\n\n\tif (key < UnicodeCompositionRecordPtr[offset_start].key ||\n\t\tkey > UnicodeCompositionRecordPtr[offset_end].key)\n\t{\n\t\treturn 0;\n\t}\n\n\tdo\n\t{\n\t\toffset_pivot = offset_start + ((offset_end - offset_start) / 2);\n\n\t\tif (key == UnicodeCompositionRecordPtr[offset_start].key)\n\t\t{\n\t\t\treturn UnicodeCompositionRecordPtr[offset_start].value;\n\t\t}\n\t\telse if (key == UnicodeCompositionRecordPtr[offset_end].key)\n\t\t{\n\t\t\treturn UnicodeCompositionRecordPtr[offset_end].value;\n\t\t}\n\t\telse if (key == UnicodeCompositionRecordPtr[offset_pivot].key)\n\t\t{\n\t\t\treturn UnicodeCompositionRecordPtr[offset_pivot].value;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (key > UnicodeCompositionRecordPtr[offset_pivot].key)\n\t\t\t{\n\t\t\t\toffset_start = offset_pivot;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\toffset_end = offset_pivot;\n\t\t\t}\n\t\t}\n\t}\n\twhile (offset_end - offset_start > 32);\n\n\tfor (i = offset_start; i <= offset_end; ++i)\n\t{\n\t\tif (key == UnicodeCompositionRecordPtr[i].key)\n\t\t{\n\t\t\treturn UnicodeCompositionRecordPtr[i].value;\n\t\t}\n\t}\n\n\treturn 0;\n}"
  },
  {
    "path": "external/utf8rewind/source/internal/database.h",
    "content": "/*\n\tCopyright (C) 2014-2016 Quinten Lansu\n\n\tPermission is hereby granted, free of charge, to any person\n\tobtaining a copy of this software and associated documentation\n\tfiles (the \"Software\"), to deal in the Software without\n\trestriction, including without limitation the rights to use,\n\tcopy, modify, merge, publish, distribute, sublicense, and/or\n\tsell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following\n\tconditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n*/\n\n#ifndef _UTF8REWIND_INTERNAL_DATABASE_H_\n#define _UTF8REWIND_INTERNAL_DATABASE_H_\n\n/*!\n\t\\file\n\t\\brief Database interface.\n\n\t\\cond INTERNAL\n*/\n\n#include \"../../include/utf8rewind/utf8rewind.h\"\n\n#include \"../unicodedatabase.h\"\n\nenum QuickCheckCaseMapped\n{\n\tQuickCheckCaseMapped_Uppercase = 0x01,\n\tQuickCheckCaseMapped_Lowercase = 0x02,\n\tQuickCheckCaseMapped_Titlecase = 0x04,\n\tQuickCheckCaseMapped_Casefolded = 0x08,\n};\n\nenum QuickCheckResult\n{\n\tQuickCheckResult_Yes,\n\tQuickCheckResult_Maybe,\n\tQuickCheckResult_No,\n};\n\n#define PROPERTY_INDEX_SHIFT (5)\n\nstatic const unicode_t PROPERTY_DATA_MASK = (1 << PROPERTY_INDEX_SHIFT) - 1;\n\n#define PROPERTY_GET(_indexArray, _dataArray, _cp) \\\n\t(_dataArray)[ \\\n\t\t(_indexArray)[(_cp) >> PROPERTY_INDEX_SHIFT] + \\\n\t\t((_cp) & PROPERTY_DATA_MASK)]\n\n#define PROPERTY_GET_GC(_cp) \\\n\tPROPERTY_GET(GeneralCategoryIndexPtr, GeneralCategoryDataPtr, _cp)\n\n#define PROPERTY_GET_CCC(_cp) \\\n\tPROPERTY_GET(CanonicalCombiningClassIndexPtr, CanonicalCombiningClassDataPtr, _cp)\n\n#define PROPERTY_GET_CM(_cp) \\\n\tPROPERTY_GET(QuickCheckCaseMappedIndexPtr, QuickCheckCaseMappedDataPtr, _cp)\n\n#define PROPERTY_GET_NFC(_cp) \\\n\tPROPERTY_GET(QuickCheckNFCIndexPtr, QuickCheckNFCDataPtr, _cp)\n\n#define PROPERTY_GET_NFD(_cp) \\\n\tPROPERTY_GET(QuickCheckNFDIndexPtr, QuickCheckNFDDataPtr, _cp)\n\n#define PROPERTY_GET_NFKC(_cp) \\\n\tPROPERTY_GET(QuickCheckNFKCIndexPtr, QuickCheckNFKCDataPtr, _cp)\n\n#define PROPERTY_GET_NFKD(_cp) \\\n\tPROPERTY_GET(QuickCheckNFKDIndexPtr, QuickCheckNFKDDataPtr, _cp)\n\nconst char* database_querydecomposition(unicode_t codepoint, const uint32_t* index1Array, const uint32_t* index2Array, const uint32_t* dataArray, uint8_t* length);\n\nunicode_t database_querycomposition(unicode_t left, unicode_t right);\n\n/*! \\endcond */\n\n#endif /* _UTF8REWIND_INTERNAL_DATABASE_H_ */"
  },
  {
    "path": "external/utf8rewind/source/internal/decomposition.c",
    "content": "/*\n\tCopyright (C) 2014-2016 Quinten Lansu\n\n\tPermission is hereby granted, free of charge, to any person\n\tobtaining a copy of this software and associated documentation\n\tfiles (the \"Software\"), to deal in the Software without\n\trestriction, including without limitation the rights to use,\n\tcopy, modify, merge, publish, distribute, sublicense, and/or\n\tsell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following\n\tconditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n*/\n\n#include \"decomposition.h\"\n\n#include \"codepoint.h\"\n#include \"database.h\"\n\nuint8_t decompose_initialize(\n\tDecomposeState* state,\n\tStreamState* input, StreamState* output,\n\tuint8_t compatibility)\n{\n\tmemset(state, 0, sizeof(DecomposeState));\n\n\t/* Ensure streams are valid */\n\n\tif (input == 0 ||\n\t\toutput == 0)\n\t{\n\t\treturn 0;\n\t}\n\n\t/* Set up streams */\n\n\tstate->input = input;\n\n\tstate->output = output;\n\tmemset(state->output, 0, sizeof(StreamState));\n\n\t/* Set up codepoint quickcheck property */\n\n\tif (compatibility == 1)\n\t{\n\t\tstate->property_index1 = NFKDIndex1Ptr;\n\t\tstate->property_index2 = NFKDIndex2Ptr;\n\t\tstate->property_data = NFKDDataPtr;\n\n\t\tstate->qc_index = QuickCheckNFKDIndexPtr;\n\t\tstate->qc_data = QuickCheckNFKDDataPtr;\n\t}\n\telse\n\t{\n\t\tstate->property_index1 = NFDIndex1Ptr;\n\t\tstate->property_index2 = NFDIndex2Ptr;\n\t\tstate->property_data = NFDDataPtr;\n\n\t\tstate->qc_index = QuickCheckNFDIndexPtr;\n\t\tstate->qc_data = QuickCheckNFDDataPtr;\n\t}\n\n\treturn 1;\n}\n\nuint8_t decompose_execute(DecomposeState* state)\n{\n\tunicode_t* src_codepoint;\n\tunicode_t* dst_codepoint;\n\tuint8_t* dst_canonical_combining_class;\n\tuint8_t* dst_quick_check;\n\tuint8_t uncached = 1;\n\n\t/* Check if input is valid */\n\n\tif (state->input == 0)\n\t{\n\t\treturn 0;\n\t}\n\n\t/* Set up output */\n\n\tstate->output->current = 0;\n\tstate->output->index = 0;\n\tstate->output->stable = 1;\n\n\tdst_codepoint = state->output->codepoint;\n\tdst_canonical_combining_class = state->output->canonical_combining_class;\n\tdst_quick_check = state->output->quick_check;\n\n\t/* Check cache for stored sequences */\n\n\tif (state->cache_current < state->cache_filled)\n\t{\n\t\t/* Read from cache */\n\n\t\twhile (state->cache_current < state->cache_filled)\n\t\t{\n\t\t\tif (state->output->current > 0 &&\n\t\t\t\tstate->cache_canonical_combining_class[state->cache_current] == CCC_NOT_REORDERED)\n\t\t\t{\n\t\t\t\t/* Sequence ends on next non-starter or end of data */\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t*dst_codepoint++ = state->cache_codepoint[state->cache_current];\n\t\t\t*dst_canonical_combining_class++ = state->cache_canonical_combining_class[state->cache_current];\n\t\t\t*dst_quick_check++ = QuickCheckResult_Yes;\n\n\t\t\tstate->output->current++;\n\t\t\tstate->cache_current++;\n\t\t}\n\n\t\t/* Check if cache has been emptied */\n\n\t\tif (state->cache_current == state->cache_filled)\n\t\t{\n\t\t\tstate->cache_current = 0;\n\t\t\tstate->cache_filled = 0;\n\t\t}\n\n\t\t/* Check for additional input */\n\n\t\tif (state->input->index == state->input->current)\n\t\t{\n\t\t\t/* Don't compare canonical combining classes, output will always be stable */\n\n\t\t\treturn state->output->current;\n\t\t}\n\t}\n\n\t/* Read next sequence from input */\n\n\tif (state->input->index == state->input->current &&\n\t\t!stream_read(state->input, state->qc_index, state->qc_data))\n\t{\n\t\t/* End of data */\n\n\t\tstate->input = 0;\n\n\t\treturn 0;\n\t}\n\n\t/* Read from source */\n\n\tsrc_codepoint = state->input->codepoint + state->input->index;\n\n\twhile (state->input->index < state->input->current)\n\t{\n\t\tif (*src_codepoint <= MAX_BASIC_LATIN)\n\t\t{\n\t\t\t/* Basic Latin codepoints are already decomposed */\n\n\t\t\tif (uncached)\n\t\t\t{\n\t\t\t\t*dst_codepoint++ = *src_codepoint;\n\t\t\t\t*dst_canonical_combining_class++ = CCC_NOT_REORDERED;\n\t\t\t\t*dst_quick_check++ = QuickCheckResult_Yes;\n\n\t\t\t\tstate->output->current++;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstate->cache_codepoint[state->cache_filled] = *src_codepoint;\n\t\t\t\tstate->cache_canonical_combining_class[state->cache_filled] = CCC_NOT_REORDERED;\n\n\t\t\t\tstate->cache_filled++;\n\t\t\t}\n\t\t}\n\t\telse if (\n\t\t\t*src_codepoint >= HANGUL_S_FIRST &&\n\t\t\t*src_codepoint <= HANGUL_S_LAST)\n\t\t{\n\t\t\t/*\n\t\t\t\tHangul decomposition\n\n\t\t\t\tAlgorithm adapted from Unicode Technical Report #15:\n\t\t\t\thttp://www.unicode.org/reports/tr15/tr15-18.html#Hangul\n\t\t\t*/\n\n\t\t\tunicode_t s_index = *src_codepoint - HANGUL_S_FIRST;\n\n\t\t\tif (uncached)\n\t\t\t{\n\t\t\t\t*dst_codepoint++ = HANGUL_L_FIRST + (s_index / HANGUL_N_COUNT);\n\t\t\t\t*dst_canonical_combining_class++ = CCC_NOT_REORDERED;\n\t\t\t\t*dst_quick_check++ = QuickCheckResult_Yes;\n\n\t\t\t\tstate->output->current++;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstate->cache_codepoint[state->cache_filled] = HANGUL_L_FIRST + (s_index / HANGUL_N_COUNT);\n\t\t\t\tstate->cache_canonical_combining_class[state->cache_filled] = CCC_NOT_REORDERED;\n\n\t\t\t\tstate->cache_filled++;\n\t\t\t}\n\n\t\t\t/* Store subsequent non-starters in cache */\n\n\t\t\tuncached = 0;\n\n\t\t\tstate->cache_codepoint[state->cache_filled] = HANGUL_V_FIRST + (s_index % HANGUL_N_COUNT) / HANGUL_T_COUNT;\n\t\t\tstate->cache_canonical_combining_class[state->cache_filled] = CCC_NOT_REORDERED;\n\n\t\t\tstate->cache_filled++;\n\n\t\t\tif ((s_index % HANGUL_T_COUNT) != 0)\n\t\t\t{\n\t\t\t\tstate->cache_codepoint[state->cache_filled] = HANGUL_T_FIRST + (s_index % HANGUL_T_COUNT);\n\t\t\t\tstate->cache_canonical_combining_class[state->cache_filled] = CCC_NOT_REORDERED;\n\n\t\t\t\tstate->cache_filled++;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/* Use quick check to skip stable codepoints */\n\n\t\t\tunicode_t decoded_codepoint = *src_codepoint;\n\t\t\tuint8_t decoded_quick_check = PROPERTY_GET(state->qc_index, state->qc_data, decoded_codepoint);\n\t\t\tuint8_t decoded_canonical_combining_class;\n\t\t\tuint8_t decoded_size;\n\n\t\t\tif (decoded_quick_check != QuickCheckResult_Yes)\n\t\t\t{\n\t\t\t\t/* Check database for decomposition */\n\n\t\t\t\tuint8_t src_size;\n\t\t\t\tconst char* src = database_querydecomposition(\n\t\t\t\t\tdecoded_codepoint,\n\t\t\t\t\tstate->property_index1, state->property_index2, state->property_data,\n\t\t\t\t\t&src_size);\n\n\t\t\t\twhile (src_size > 0)\n\t\t\t\t{\n\t\t\t\t\t/* Decode current codepoint */\n\n\t\t\t\t\tdecoded_size = codepoint_read(src, src_size, &decoded_codepoint);\n\t\t\t\t\tif (decoded_size == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tdecoded_canonical_combining_class = PROPERTY_GET_CCC(decoded_codepoint);\n\n\t\t\t\t\t/* Check for end of sequence */\n\n\t\t\t\t\tif (uncached &&\n\t\t\t\t\t\tstate->output->current > 0 &&\n\t\t\t\t\t\tdecoded_canonical_combining_class == CCC_NOT_REORDERED)\n\t\t\t\t\t{\n\t\t\t\t\t\tuncached = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (uncached)\n\t\t\t\t\t{\n\t\t\t\t\t\t/* Write codepoint to output */\n\n\t\t\t\t\t\t*dst_codepoint++ = decoded_codepoint;\n\t\t\t\t\t\t*dst_canonical_combining_class++ = decoded_canonical_combining_class;\n\t\t\t\t\t\t*dst_quick_check++ = QuickCheckResult_Yes;\n\n\t\t\t\t\t\tstate->output->current++;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t/* Store in cache */\n\n\t\t\t\t\t\tstate->cache_codepoint[state->cache_filled] = decoded_codepoint;\n\t\t\t\t\t\tstate->cache_canonical_combining_class[state->cache_filled] = decoded_canonical_combining_class;\n\n\t\t\t\t\t\tstate->cache_filled++;\n\t\t\t\t\t}\n\n\t\t\t\t\tsrc += decoded_size;\n\t\t\t\t\tsrc_size -= decoded_size;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tdecoded_canonical_combining_class = PROPERTY_GET_CCC(decoded_codepoint);\n\n\t\t\t\tif (uncached)\n\t\t\t\t{\n\t\t\t\t\t/* Write codepoint to output */\n\n\t\t\t\t\t*dst_codepoint++ = decoded_codepoint;\n\t\t\t\t\t*dst_canonical_combining_class++ = decoded_canonical_combining_class;\n\t\t\t\t\t*dst_quick_check++ = decoded_quick_check;\n\n\t\t\t\t\tstate->output->current++;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t/* Store in cache */\n\n\t\t\t\t\tstate->cache_codepoint[state->cache_filled] = decoded_codepoint;\n\t\t\t\t\tstate->cache_canonical_combining_class[state->cache_filled] = decoded_canonical_combining_class;\n\n\t\t\t\t\tstate->cache_filled++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrc_codepoint++;\n\t\tstate->input->index++;\n\t}\n\n\tif (state->output->current > 1)\n\t{\n\t\t/* Check if output is stable by comparing canonical combining classes */\n\n\t\tuint8_t i;\n\t\tfor (i = 1; i < state->output->current; ++i)\n\t\t{\n\t\t\tif (state->output->canonical_combining_class[i] < state->output->canonical_combining_class[i - 1])\n\t\t\t{\n\t\t\t\tstate->output->stable = 0;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn state->output->current;\n}"
  },
  {
    "path": "external/utf8rewind/source/internal/decomposition.h",
    "content": "/*\n\tCopyright (C) 2014-2016 Quinten Lansu\n\n\tPermission is hereby granted, free of charge, to any person\n\tobtaining a copy of this software and associated documentation\n\tfiles (the \"Software\"), to deal in the Software without\n\trestriction, including without limitation the rights to use,\n\tcopy, modify, merge, publish, distribute, sublicense, and/or\n\tsell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following\n\tconditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n*/\n\n#ifndef _UTF8REWIND_INTERNAL_DECOMPOSITION_H_\n#define _UTF8REWIND_INTERNAL_DECOMPOSITION_H_\n\n/*!\n\t\\file\n\t\\brief Decomposition interface.\n\n\t\\cond INTERNAL\n*/\n\n#include \"../../include/utf8rewind/utf8rewind.h\"\n#include \"streaming.h\"\n\ntypedef struct {\n\tStreamState* input;\n\tStreamState* output;\n\tconst size_t* qc_index;\n\tconst uint8_t* qc_data;\n\tconst uint32_t* property_index1;\n\tconst uint32_t* property_index2;\n\tconst uint32_t* property_data;\n\tunicode_t cache_codepoint[STREAM_BUFFER_MAX];\n\tuint8_t cache_canonical_combining_class[STREAM_BUFFER_MAX];\n\tuint8_t cache_current;\n\tuint8_t cache_filled;\n} DecomposeState;\n\nuint8_t decompose_initialize(DecomposeState* state, StreamState* input, StreamState* output, uint8_t compatibility);\n\nuint8_t decompose_execute(DecomposeState* state);\n\n/*! \\endcond */\n\n#endif /* _UTF8REWIND_INTERNAL_DECOMPOSITION_H_ */"
  },
  {
    "path": "external/utf8rewind/source/internal/seeking.c",
    "content": "/*\n\tCopyright (C) 2014-2016 Quinten Lansu\n\n\tPermission is hereby granted, free of charge, to any person\n\tobtaining a copy of this software and associated documentation\n\tfiles (the \"Software\"), to deal in the Software without\n\trestriction, including without limitation the rights to use,\n\tcopy, modify, merge, publish, distribute, sublicense, and/or\n\tsell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following\n\tconditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n*/\n\n#include \"seeking.h\"\n\n#include \"codepoint.h\"\n\nconst char* seeking_forward(const char* input, const char* inputEnd, size_t inputSize, off_t offset)\n{\n\tif (inputEnd <= input ||  /* Swapped parameters */\n\t\toffset <= 0 ||        /* Invalid offset */\n\t\tinputSize == 0)       /* Nothing to do */\n\t{\n\t\treturn input;\n\t}\n\telse if (\n\t\toffset >= (off_t)inputSize)  /* Out of bounds */\n\t{\n\t\treturn inputEnd;\n\t}\n\n\tdo\n\t{\n\t\t/* Get decoded length of next sequence */\n\n\t\tuint8_t codepoint_length = codepoint_decoded_length[(uint8_t)*input];\n\n\t\tif (codepoint_length > 1 &&\n\t\t\tcodepoint_length < 7)\n\t\t{\n\t\t\t/* Check all bytes of multi-byte sequence */\n\n\t\t\tuint8_t i;\n\n\t\t\tfor (i = 0; i < codepoint_length; ++i)\n\t\t\t{\n\t\t\t\t/* Next byte of sequence */\n\n\t\t\t\tinput++;\n\n\t\t\t\tif (input == inputEnd ||                             /* End of data */\n\t\t\t\t\tcodepoint_decoded_length[(uint8_t)*input] != 0)  /* Not a continuation byte */\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/* Skip to next sequence */\n\n\t\t\tinput++;\n\t\t}\n\t}\n\twhile (input < inputEnd &&\n\t\t--offset > 0);\n\n\treturn input;\n}\n\nconst char* seeking_rewind(const char* inputStart, const char* input, size_t inputSize, off_t offset)\n{\n\tconst char* marker;\n\tconst char* marker_valid;\n\n\tif (inputStart >= input ||  /* Swapped parameters */\n\t\toffset >= 0)            /* Invalid offset */\n\t{\n\t\treturn input;\n\t}\n\telse if (\n\t\t-offset >= (off_t)inputSize)  /* Out of bounds */\n\t{\n\t\treturn inputStart;\n\t}\n\n\t/* Set up the marker */\n\n\tmarker = input - 1;\n\tmarker_valid = marker;\n\n\tdo\n\t{\n\t\t/* Move the cursor */\n\n\t\tinput--;\n\n\t\t/* Move the marker until we encounter a valid sequence */\n\n\t\twhile (marker_valid == input)\n\t\t{\n\t\t\tuint8_t codepoint_length = codepoint_decoded_length[(uint8_t)*marker];\n\n\t\t\tif (codepoint_length == 1 ||  /* Basic Latin */\n\t\t\t\tcodepoint_length == 7)    /* Illegal byte */\n\t\t\t{\n\t\t\t\tmarker_valid = marker;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse if (\n\t\t\t\tcodepoint_length > 1)\n\t\t\t{\n\t\t\t\tif (marker == inputStart &&\n\t\t\t\t\t/* Not overlong */\n\t\t\t\t\tmarker_valid - inputStart == codepoint_length - 1)\n\t\t\t\t{\n\t\t\t\t\t/* Last sequence */\n\n\t\t\t\t\treturn marker;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t/* Multi-byte sequence */\n\n\t\t\t\t\tmarker_valid = marker + codepoint_length - 1;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (\n\t\t\t\tmarker <= inputStart)\n\t\t\t{\n\t\t\t\t/* Continuation bytes only */\n\n\t\t\t\tmarker_valid = marker;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* Move marker to next byte */\n\n\t\t\t\tmarker--;\n\t\t\t}\n\t\t}\n\n\t\t/* Read the next part of a sequence */\n\n\t\tif (input <= marker_valid)\n\t\t{\n\t\t\tif (marker == inputStart)\n\t\t\t{\n\t\t\t\t/* Last sequence */\n\n\t\t\t\treturn marker;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* Move the cursor to the start of the sequence */\n\n\t\t\t\tinput = marker;\n\n\t\t\t\t/* Reset the marker on the next byte */\n\n\t\t\t\tmarker--;\n\t\t\t\tmarker_valid = marker;\n\t\t\t}\n\t\t}\n\t}\n\twhile (input >= inputStart &&\n\t\t++offset < 0);\n\n\treturn input;\n}"
  },
  {
    "path": "external/utf8rewind/source/internal/seeking.h",
    "content": "/*\n\tCopyright (C) 2014-2016 Quinten Lansu\n\n\tPermission is hereby granted, free of charge, to any person\n\tobtaining a copy of this software and associated documentation\n\tfiles (the \"Software\"), to deal in the Software without\n\trestriction, including without limitation the rights to use,\n\tcopy, modify, merge, publish, distribute, sublicense, and/or\n\tsell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following\n\tconditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n*/\n\n#ifndef _UTF8REWIND_INTERNAL_SEEKING_H_\n#define _UTF8REWIND_INTERNAL_SEEKING_H_\n\n/*!\n\t\\file\n\t\\brief Seeking interface.\n\n\t\\cond INTERNAL\n*/\n\n#include \"../../include/utf8rewind/utf8rewind.h\"\n\nconst char* seeking_forward(const char* input, const char* inputEnd, size_t inputSize, off_t offset);\n\nconst char* seeking_rewind(const char* inputStart, const char* input, size_t inputSize, off_t offset);\n\n/*! \\endcond */\n\n#endif /* _UTF8REWIND_INTERNAL_SEEKING_H_ */"
  },
  {
    "path": "external/utf8rewind/source/internal/streaming.c",
    "content": "/*\n\tCopyright (C) 2014-2016 Quinten Lansu\n\n\tPermission is hereby granted, free of charge, to any person\n\tobtaining a copy of this software and associated documentation\n\tfiles (the \"Software\"), to deal in the Software without\n\trestriction, including without limitation the rights to use,\n\tcopy, modify, merge, publish, distribute, sublicense, and/or\n\tsell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following\n\tconditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n*/\n\n#include \"streaming.h\"\n\n#include \"codepoint.h\"\n#include \"database.h\"\n\nuint8_t stream_initialize(StreamState* state, const char* input, size_t inputSize)\n{\n\tmemset(state, 0, sizeof(StreamState));\n\n\tif (input == 0 ||\n\t\tinputSize == 0)\n\t{\n\t\treturn 0;\n\t}\n\n\tstate->src = input;\n\tstate->src_size = inputSize;\n\n\tstate->stable = 1;\n\n\treturn 1;\n}\n\nuint8_t stream_read(StreamState* state, const size_t* propertyIndex, const uint8_t* propertyData)\n{\n\t/* Ensure input is available */\n\n\tif (state->src_size == 0 ||\n\t\tpropertyIndex == 0 ||\n\t\tpropertyData == 0)\n\t{\n\t\treturn 0;\n\t}\n\n\t/* Reset sequence after the first pass */\n\n\tif (state->filled > 0)\n\t{\n\t\t/* Check for end of data */\n\n\t\tif (state->filled == state->current &&\n\t\t\tstate->src_size <= state->last_length)\n\t\t{\n\t\t\tstate->src_size = 0;\n\n\t\t\tstate->index = 0;\n\t\t\tstate->current = 0;\n\t\t\tstate->filled = 0;\n\n\t\t\treturn 0;\n\t\t}\n\n\t\t/* Copy last peeked codepoint to new sequence */\n\n\t\tstate->codepoint[0]                  = state->codepoint[state->filled - 1];\n\t\tstate->canonical_combining_class[0]  = state->canonical_combining_class[state->filled - 1];\n\t\tstate->quick_check[0]                = state->quick_check[state->filled - 1];\n\n\t\t/* New sequence always starts as stable */\n\n\t\tstate->stable = 1;\n\n\t\t/* Reset buffer members */\n\n\t\tstate->index = 0;\n\t\tstate->current = 1;\n\t\tstate->filled = 1;\n\t}\n\n\t/* Read codepoints */\n\n\twhile (state->filled < STREAM_SAFE_MAX)\n\t{\n\t\t/* Move the input cursor after peeking */\n\n\t\tif (state->last_length > 0)\n\t\t{\n\t\t\tif (state->src_size <= state->last_length)\n\t\t\t{\n\t\t\t\tstate->src += state->src_size;\n\t\t\t\tstate->src_size = 0;\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tstate->src += state->last_length;\n\t\t\tstate->src_size -= state->last_length;\n\t\t}\n\n\t\t/* Peek the next codepoint */\n\n\t\tstate->last_length = codepoint_read(state->src, state->src_size, &state->codepoint[state->filled]);\n\t\tstate->quick_check[state->filled] = PROPERTY_GET(propertyIndex, propertyData, state->codepoint[state->filled]);\n\t\tstate->canonical_combining_class[state->filled] = PROPERTY_GET_CCC(state->codepoint[state->filled]);\n\n\t\tstate->filled++;\n\n\t\tif (state->current > 0)\n\t\t{\n\t\t\t/* Sequences end on the next starter and can consist of only non-starters */\n\n\t\t\tif (state->canonical_combining_class[state->current] == 0)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/* Check if sequence is unstable by comparing canonical combining classes */\n\n\t\t\tif (state->stable &&\n\t\t\t\tstate->canonical_combining_class[state->current] < state->canonical_combining_class[state->current - 1])\n\t\t\t{\n\t\t\t\tstate->stable = 0;\n\t\t\t}\n\t\t}\n\n\t\tstate->current++;\n\t}\n\n\tif (state->filled == STREAM_SAFE_MAX)\n\t{\n\t\t/* Insert COMBINING GRAPHEME JOINER into output */\n\n\t\tstate->codepoint[state->filled]                  = CP_COMBINING_GRAPHEME_JOINER;\n\t\tstate->quick_check[state->filled]                = QuickCheckResult_Yes;\n\t\tstate->canonical_combining_class[state->filled]  = CCC_NOT_REORDERED;\n\n\t\tstate->filled++;\n\t}\n\n\treturn 1;\n}\n\nuint8_t stream_write(StreamState* state, char** output, size_t* outputSize, uint8_t* bytesWritten)\n{\n\tuint8_t i;\n\n\tif (state->current == 0)\n\t{\n\t\t/* Nothing to write */\n\n\t\t*bytesWritten = 0;\n\n\t\treturn 1;\n\t}\n\n\t/* Encode code points as UTF-8 */\n\n\tfor (i = 0; i < state->current; ++i)\n\t{\n\t\tuint8_t encoded_size = codepoint_write(state->codepoint[i], output, outputSize);\n\t\tif (encoded_size == 0)\n\t\t{\n\t\t\t/* Not enough space */\n\n\t\t\treturn 0;\n\t\t}\n\n\t\t*bytesWritten += encoded_size;\n\t}\n\n\treturn 1;\n}\n\nuint8_t stream_reorder(StreamState* state)\n{\n\tuint8_t i;\n\tuint8_t dirty = 1;\n\n\tif (state->current == 0)\n\t{\n\t\t/* Nothing to do */\n\n\t\treturn 0;\n\t}\n\n\t/* Reorder codepoints until the entire sequence is table */\n\n\tdo\n\t{\n\t\tdirty = 0;\n\n\t\tfor (i = 1; i < state->current; i++)\n\t\t{\n\t\t\t/* Sort codepoints by canonical combining class, smallest to largest */\n\n\t\t\tif (state->canonical_combining_class[i] < state->canonical_combining_class[i - 1])\n\t\t\t{\n\t\t\t\tunicode_t swap_cp;\n\t\t\t\tuint8_t swap_qc;\n\t\t\t\tuint8_t swap_ccc;\n\n\t\t\t\tswap_cp = state->codepoint[i];\n\t\t\t\tstate->codepoint[i] = state->codepoint[i - 1];\n\t\t\t\tstate->codepoint[i - 1] = swap_cp;\n\n\t\t\t\tswap_qc = state->quick_check[i];\n\t\t\t\tstate->quick_check[i] = state->quick_check[i - 1];\n\t\t\t\tstate->quick_check[i - 1] = swap_qc;\n\n\t\t\t\tswap_ccc = state->canonical_combining_class[i];\n\t\t\t\tstate->canonical_combining_class[i] = state->canonical_combining_class[i - 1];\n\t\t\t\tstate->canonical_combining_class[i - 1] = swap_ccc;\n\n\t\t\t\tdirty = 1;\n\t\t\t}\n\t\t}\n\t}\n\twhile (dirty == 1);\n\n\treturn 1;\n}"
  },
  {
    "path": "external/utf8rewind/source/internal/streaming.h",
    "content": "/*\n\tCopyright (C) 2014-2016 Quinten Lansu\n\n\tPermission is hereby granted, free of charge, to any person\n\tobtaining a copy of this software and associated documentation\n\tfiles (the \"Software\"), to deal in the Software without\n\trestriction, including without limitation the rights to use,\n\tcopy, modify, merge, publish, distribute, sublicense, and/or\n\tsell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following\n\tconditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n*/\n\n#ifndef _UTF8REWIND_INTERNAL_STREAMING_H_\n#define _UTF8REWIND_INTERNAL_STREAMING_H_\n\n/*!\n\t\\file\n\t\\brief Streaming interface.\n\n\t\\cond INTERNAL\n*/\n\n#include \"../../include/utf8rewind/utf8rewind.h\"\n\n/*\n\tUAX15-D4. Stream-Safe Text Process\n\n\tThis is the process of producing a Unicode string in Stream-Safe Text Format by processing that string\n\tfrom start to finish, inserting U+034F COMBINING GRAPHEME JOINER (CGJ) within long sequences of\n\tnon-starters. The exact position of the inserted CGJs are determined according to the following algorithm,\n\twhich describes the generation of an output string from an input string:\n\n\t* If the input string is empty, return an empty output string.\n\t* Set nonStarterCount to zero.\n\t* For each code point C in the input string:\n\t\t* Produce the NFKD decomposition S.\n\t\t* If nonStarterCount plus the number of initial non-starters in S is greater than 30, append a CGJ to\n\t\t\tthe output string and set the nonStarterCount to zero.\n\t\t* Append C to the output string.\n\t\t* If there are no starters in S, increment nonStarterCount by the number of code points in S; otherwise,\n\t\t\tset nonStarterCount to the number of trailing non-starters in S (which may be zero).\n\t* Return the output string.\n*/\n\n#define STREAM_SAFE_MAX 30\n#define STREAM_BUFFER_MAX 32\n\ntypedef struct {\n\tconst char* src;\n\tsize_t src_size;\n\tuint8_t index;\n\tuint8_t current;\n\tuint8_t filled;\n\tuint8_t stable;\n\tuint8_t last_length;\n\tunicode_t codepoint[STREAM_BUFFER_MAX];\n\tuint8_t quick_check[STREAM_BUFFER_MAX];\n\tuint8_t canonical_combining_class[STREAM_BUFFER_MAX];\n} StreamState;\n\nuint8_t stream_initialize(StreamState* state, const char* input, size_t inputSize);\n\nuint8_t stream_read(StreamState* state, const size_t* propertyIndex, const uint8_t* propertyData);\n\nuint8_t stream_write(StreamState* state, char** output, size_t* outputSize, uint8_t* bytesWritten);\n\nuint8_t stream_reorder(StreamState* state);\n\n/*! \\endcond */\n\n#endif /* _UTF8REWIND_INTERNAL_STREAMING_H_ */"
  },
  {
    "path": "external/utf8rewind/source/unicodedatabase.c",
    "content": "/*\n\tCopyright (C) 2014-2016 Quinten Lansu\n\n\tPermission is hereby granted, free of charge, to any person\n\tobtaining a copy of this software and associated documentation\n\tfiles (the \"Software\"), to deal in the Software without\n\trestriction, including without limitation the rights to use,\n\tcopy, modify, merge, publish, distribute, sublicense, and/or\n\tsell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following\n\tconditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n*/\n\n/*\n\tDO NOT MODIFY, AUTO-GENERATED\n\n\tGenerated on:\n\t\t2016-02-01T14:10:25\n\n\tCommand line:\n\t\ttools\\converter\\unicodedata.py\n*/\n\n#include \"unicodedatabase.h\"\n\nconst size_t GeneralCategoryIndex[34816] = {\n\t0, 32, 64, 96, 0, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 224, 480, 512, 544, 576, 608, 640, 672, 704, 704, 704, 736, 768, 800, 832, 864,\n\t896, 928, 527, 224, 960, 224, 992, 224, 224, 1024, 1056, 1088, 1120, 1152, 1184, 1216, 1248, 1280, 1312, 1344, 1280, 1280, 1376, 1408, 1440, 1472, 1504, 1280, 1280, 1536, 1568, 1600,\n\t1632, 1664, 1696, 1728, 1727, 1760, 1727, 1792, 1824, 1856, 1888, 1920, 1952, 1984, 2016, 2048, 2080, 2112, 2144, 2176, 2208, 2240, 2272, 2304, 2336, 2368, 2400, 2432, 2464, 2496, 2528, 2560,\n\t2592, 2624, 2656, 2688, 2720, 2752, 2784, 2816, 2720, 2848, 2880, 2912, 2944, 2976, 3008, 3040, 3072, 3104, 3136, 1727, 3168, 3200, 3232, 1727, 3264, 3296, 3328, 3360, 3392, 3424, 3456, 1727,\n\t1280, 3488, 3520, 3552, 3584, 893, 3616, 3648, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 3680, 1280, 3712, 3744, 3776, 1280, 3808, 1280, 3840, 3872, 3904, 1280, 1280, 3936,\n\t3968, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 4000, 4032, 1280, 1280, 4064, 4096, 4128, 4160, 4192, 1280, 4224, 4256, 4288,\n\t4320, 1280, 4352, 4384, 1280, 4416, 1280, 4448, 4480, 4512, 4544, 4576, 1280, 4608, 4640, 4672, 4704, 1280, 4736, 4768, 4800, 4832, 1727, 1727, 4864, 4896, 4928, 4960, 4992, 5024, 1280, 5056,\n\t1280, 5088, 5120, 5152, 1727, 1727, 5184, 5216, 527, 5248, 5280, 5312, 597, 5260, 704, 5344, 224, 224, 224, 224, 5376, 224, 224, 224, 5408, 5440, 5472, 5504, 5536, 5568, 5600, 5632,\n\t5664, 5696, 5728, 5760, 5792, 5824, 5856, 5888, 5920, 5952, 5984, 6016, 6048, 6080, 6112, 6144, 6176, 6164, 6164, 6164, 6164, 6164, 6164, 6164, 6208, 6240, 4670, 6272, 6304, 6336, 6368, 6400,\n\t4670, 6432, 6464, 6496, 6528, 4670, 4670, 6560, 4670, 4670, 4670, 4670, 4670, 6592, 6093, 6624, 4670, 4670, 4670, 6656, 4670, 4670, 4670, 4670, 4670, 4670, 4670, 6688, 6720, 4670, 6752, 6784,\n\t4670, 4670, 4670, 4670, 4670, 4670, 4670, 4670, 6164, 6164, 6164, 6164, 6816, 6164, 6848, 6880, 6164, 6164, 6164, 6164, 6164, 6164, 6164, 6164, 4670, 6912, 6944, 6976, 7008, 7040, 7072, 1727,\n\t893, 7104, 7136, 7168, 224, 224, 224, 7200, 527, 7232, 1280, 7264, 7296, 7328, 7328, 704, 7360, 7392, 7424, 1727, 7456, 4670, 4670, 7488, 4670, 4670, 4670, 4670, 4670, 4670, 7520, 7552,\n\t7584, 7616, 3336, 1280, 7648, 3968, 1280, 7680, 4427, 7712, 1280, 1280, 7744, 1200, 4670, 7776, 7808, 7840, 7872, 4670, 7840, 7904, 4670, 7808, 4670, 4670, 4670, 4670, 4670, 4670, 4670, 4670,\n\t7936, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 7968, 4670, 4670, 7936, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 8000, 1727,\n\t8032, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280,\n\t1280, 1280, 1280, 1280, 8064, 4670, 8096, 8128, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 8160, 8192, 224, 8224, 8256, 1280, 1280, 8288, 8320, 8352, 224, 8384, 8416, 8448, 1727, 8480,\n\t8512, 8544, 1280, 8576, 8608, 8640, 8672, 8704, 1568, 8736, 8768, 8800, 1824, 8832, 8864, 8896, 1280, 8928, 8960, 8992, 1280, 9024, 9056, 9088, 9120, 9152, 9184, 9216, 1727, 1727, 1280, 9248,\n\t7936, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 9280, 9312, 9344,\n\t9376, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 9408, 9376, 1727, 1727, 9440,\n\t9376, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 9440,\n\t9472, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 9504, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 9536, 1280, 1280, 9568, 1727, 9600, 9632, 9664, 1280, 1280, 9696, 9728, 1280,\n\t1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 9760, 1744, 1280, 9792, 1280, 9824, 9856, 9888, 9920, 9952, 9984, 1280, 1280, 1280, 10016, 10048, 10080, 10112, 10144, 5146, 4480, 10176, 10208,\n\t10240, 10272, 10304, 1727, 1280, 1280, 1280, 1200, 10336, 10368, 6016, 10400, 10432, 10464, 10496, 10528, 1727, 1727, 1727, 1727, 8800, 1280, 10560, 10592, 1280, 10624, 10656, 10688, 10720, 1280, 10752, 1727,\n\t893, 10784, 10816, 1280, 4560, 10848, 1727, 1727, 1280, 10880, 1280, 10912, 1727, 1727, 1727, 1727, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 7296, 9810, 10944, 1727, 1727, 1727, 1727,\n\t10976, 11008, 11040, 11072, 4480, 11104, 1727, 1727, 11136, 11168, 1727, 1727, 1280, 11200, 1727, 1727, 11232, 11264, 11296, 11328, 11360, 1727, 11392, 11424, 1280, 11456, 11488, 11520, 11552, 11584, 1727, 1727,\n\t1280, 1280, 11616, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 11648, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t11680, 11712, 11744, 11776, 4992, 11808, 11840, 11872, 11904, 11936, 11968, 12000, 4992, 12032, 12064, 12096, 12128, 12160, 1727, 1727, 1727, 1744, 12192, 12224, 2336, 12256, 12288, 12320, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1280, 12352, 12384, 1727, 1727, 1727, 1727, 1727, 1280, 12416, 12448, 1727, 1280, 12480, 12512, 1727, 1280, 12544, 10848, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 893, 527, 12576, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1280, 11856, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 11856, 1727, 1727, 1727,\n\t6016, 6016, 6016, 12608, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280,\n\t1280, 12640, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 11856, 4480, 12672, 1727, 1727, 1744, 12704, 1280, 12736, 12768, 12800, 12832, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1280, 1280, 12864, 12896, 12928, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t12960, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1280, 1280, 1280, 12992, 13024, 13056, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t4670, 4670, 4670, 4670, 4670, 4670, 4670, 7520, 4670, 6989, 4670, 13088, 13120, 13152, 13184, 1727, 4670, 4670, 13216, 1727, 1727, 1727, 1727, 1727, 4670, 4670, 8080, 13248, 1727, 1727, 1727, 1727,\n\t13280, 13312, 13344, 13324, 13376, 13408, 13440, 13472, 13504, 13536, 13568, 13600, 13632, 13280, 13664, 13696, 13324, 13304, 13728, 13760, 13792, 13824, 13856, 13888, 13920, 13952, 13984, 14016, 14048, 14080, 14112, 14144,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1280, 1280, 1280, 1280, 1280, 1280, 14176, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 14208, 14240, 14272, 14304, 14336, 14368, 1727, 14400, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t4670, 14432, 4670, 4670, 14464, 14496, 14528, 7520, 14560, 14592, 4670, 14432, 14624, 1727, 1727, 14656, 14688, 14720, 14752, 1727, 1727, 1727, 1727, 1727, 4670, 14784, 4670, 14816, 4670, 4670, 14848, 14880,\n\t4670, 4670, 4670, 4670, 4670, 4670, 4670, 7808, 4670, 4670, 14912, 7456, 4670, 14944, 4670, 4670, 4670, 4670, 6993, 4670, 4670, 4670, 14976, 15008, 4670, 4670, 4670, 15040, 4670, 4670, 14630, 1727,\n\t14432, 4670, 15072, 4670, 15104, 15136, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t7936, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 7990, 1727, 7936, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 15168, 7936, 1727, 1727, 1727, 1727, 1727,\n\t15200, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 4560, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t15232, 15264, 15264, 15264, 1727, 1727, 1727, 1727, 704, 704, 704, 704, 704, 704, 704, 15296, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t9472, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 15328,\n\t9472, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,\n\t1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 15360,\n};\nconst size_t* GeneralCategoryIndexPtr = GeneralCategoryIndex;\n\nconst uint32_t GeneralCategoryData[15392] = {\n\t0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000,\n\t0x400000, 0x20000, 0x20000, 0x20000, 0x80000, 0x20000, 0x20000, 0x20000, 0x2000, 0x4000, 0x20000, 0x40000, 0x20000, 0x1000, 0x20000, 0x20000, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x20000, 0x20000, 0x40000, 0x40000, 0x40000, 0x20000,\n\t0x20000, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x2000, 0x20000, 0x4000, 0x100000, 0x800,\n\t0x100000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x2000, 0x40000, 0x4000, 0x40000, 0x2000000,\n\t0x400000, 0x20000, 0x80000, 0x80000, 0x80000, 0x80000, 0x200000, 0x20000, 0x100000, 0x200000, 0x10, 0x8000, 0x40000, 0x4000000, 0x200000, 0x100000, 0x200000, 0x40000, 0x400, 0x400, 0x100000, 0x02, 0x20000, 0x20000, 0x100000, 0x400, 0x10, 0x10000, 0x400, 0x400, 0x400, 0x20000,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40000, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x40000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,\n\t0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,\n\t0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,\n\t0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02,\n\t0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x01,\n\t0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x10, 0x01, 0x02, 0x02, 0x02,\n\t0x10, 0x10, 0x10, 0x10, 0x01, 0x04, 0x02, 0x01, 0x04, 0x02, 0x01, 0x04, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02,\n\t0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x04, 0x02, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,\n\t0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02,\n\t0x02, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x10, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,\n\t0x08, 0x08, 0x100000, 0x100000, 0x100000, 0x100000, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000,\n\t0x08, 0x08, 0x08, 0x08, 0x08, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x08, 0x100000, 0x08, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000,\n\t0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,\n\t0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x02, 0x01, 0x02, 0x08, 0x100000, 0x01, 0x02, 0x00, 0x00, 0x08, 0x02, 0x02, 0x02, 0x20000, 0x01,\n\t0x00, 0x00, 0x00, 0x00, 0x100000, 0x100000, 0x01, 0x20000, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,\n\t0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x40000, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x01, 0x02, 0x200000, 0x20, 0x20, 0x20, 0x20, 0x20, 0x80, 0x80, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,\n\t0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,\n\t0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x08, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000,\n\t0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x20000, 0x1000, 0x00, 0x00, 0x200000, 0x200000, 0x80000, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,\n\t0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1000, 0x20,\n\t0x20000, 0x20, 0x20, 0x20000, 0x20, 0x20, 0x20000, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x40000, 0x40000, 0x40000, 0x20000, 0x20000, 0x80000, 0x20000, 0x20000, 0x200000, 0x200000, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x4000000, 0x00, 0x20000, 0x20000,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,\n\t0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x20000, 0x20000, 0x20000, 0x20000, 0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20000, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4000000, 0x200000, 0x20,\n\t0x20, 0x20, 0x20, 0x20, 0x20, 0x08, 0x08, 0x20, 0x20, 0x200000, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x10, 0x10, 0x10, 0x200000, 0x200000, 0x10,\n\t0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x4000000, 0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,\n\t0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x08, 0x08, 0x200000, 0x20000, 0x20000, 0x20000, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x08, 0x20, 0x20, 0x20, 0x20, 0x20,\n\t0x20, 0x20, 0x20, 0x20, 0x08, 0x20, 0x20, 0x20, 0x08, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x00, 0x00, 0x20000, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,\n\t0x20, 0x20, 0x20, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x40, 0x20, 0x10, 0x40, 0x40,\n\t0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40, 0x20, 0x40, 0x40, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x20, 0x20, 0x20000, 0x20000, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x20000, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x20, 0x40, 0x40, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x20, 0x10, 0x40, 0x40,\n\t0x40, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40, 0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10,\n\t0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x10, 0x10, 0x80000, 0x80000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x200000, 0x80000, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x20, 0x20, 0x40, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x20, 0x00, 0x40, 0x40,\n\t0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x20, 0x20, 0x10, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x20, 0x20, 0x40, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x20, 0x10, 0x40, 0x40,\n\t0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x20, 0x40, 0x00, 0x40, 0x40, 0x20, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x20000, 0x80000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x20, 0x40, 0x40, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x20, 0x10, 0x40, 0x20,\n\t0x40, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10,\n\t0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x200000, 0x10, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x20, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10,\n\t0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40,\n\t0x20, 0x40, 0x40, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x20, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x400, 0x400, 0x400, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x80000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x20, 0x40, 0x40, 0x40, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20,\n\t0x20, 0x40, 0x40, 0x40, 0x40, 0x00, 0x20, 0x20, 0x20, 0x00, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x200000,\n\t0x00, 0x20, 0x40, 0x40, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x20, 0x10, 0x40, 0x20,\n\t0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x20, 0x40, 0x40, 0x00, 0x40, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,\n\t0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x40, 0x40,\n\t0x40, 0x20, 0x20, 0x20, 0x20, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x200000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x00, 0x00, 0x40, 0x40, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x00, 0x20, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x40, 0x40, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x80000,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x20, 0x10, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x08, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x200000, 0x200000, 0x200000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x200000, 0x20000, 0x200000, 0x200000, 0x200000, 0x20, 0x20, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x200000, 0x20, 0x200000, 0x20, 0x200000, 0x20, 0x2000, 0x4000, 0x2000, 0x4000, 0x40, 0x40,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40,\n\t0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,\n\t0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x20, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x200000, 0x200000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x200000, 0x200000, 0x200000, 0x200000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x20, 0x20, 0x40, 0x40, 0x20, 0x20, 0x10,\n\t0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20,\n\t0x20, 0x10, 0x40, 0x40, 0x40, 0x10, 0x10, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x20, 0x40, 0x40, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x10, 0x40, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x40, 0x40, 0x40, 0x20, 0x200000, 0x200000,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20000, 0x08, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00,\n\t0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20, 0x20,\n\t0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x1000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20000, 0x20000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x400000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x2000, 0x4000, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20000, 0x20000, 0x20000, 0x200, 0x200, 0x200, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40,\n\t0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x20000, 0x20000, 0x08, 0x20000, 0x20000, 0x20000, 0x80000, 0x10, 0x20, 0x00, 0x00,\n\t0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x1000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20, 0x20, 0x20, 0x4000000, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00,\n\t0x20, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,\n\t0x200000, 0x00, 0x00, 0x00, 0x20000, 0x20000, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,\n\t0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x400, 0x00, 0x00, 0x00, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x20, 0x00, 0x00, 0x20000, 0x20000,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x20, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00,\n\t0x20, 0x40, 0x20, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x20,\n\t0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x08, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x80, 0x00,\n\t0x20, 0x20, 0x20, 0x20, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x20, 0x40, 0x40, 0x40,\n\t0x40, 0x40, 0x20, 0x40, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000,\n\t0x20000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00,\n\t0x20, 0x20, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x40, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x20, 0x20, 0x40, 0x20, 0x20, 0x20, 0x10, 0x10, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x40, 0x20, 0x20, 0x40, 0x40, 0x40, 0x20, 0x40, 0x20, 0x20, 0x20, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20000, 0x20000, 0x20000, 0x20000,\n\t0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000,\n\t0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x20000, 0x20000,\n\t0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20000, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,\n\t0x20, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x20, 0x10, 0x10, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,\n\t0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,\n\t0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x08, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20,\n\t0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x04, 0x100000, 0x02, 0x100000,\n\t0x100000, 0x100000, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x04, 0x100000, 0x100000, 0x100000, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x100000, 0x100000, 0x100000,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x100000, 0x100000, 0x100000, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x04, 0x100000, 0x100000, 0x00,\n\t0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x20000, 0x20000, 0x8000, 0x10000, 0x2000, 0x8000, 0x8000, 0x10000, 0x2000, 0x8000,\n\t0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x800000, 0x1000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x400000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x8000, 0x10000, 0x20000, 0x20000, 0x20000, 0x20000, 0x800,\n\t0x800, 0x20000, 0x20000, 0x20000, 0x40000, 0x2000, 0x4000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x40000, 0x20000, 0x800, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x400000,\n\t0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x00, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x400, 0x08, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x40000, 0x40000, 0x40000, 0x2000, 0x4000, 0x08,\n\t0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x40000, 0x40000, 0x40000, 0x2000, 0x4000, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,\n\t0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x80, 0x80, 0x80,\n\t0x80, 0x20, 0x80, 0x80, 0x80, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x200000, 0x200000, 0x01, 0x200000, 0x200000, 0x200000, 0x200000, 0x01, 0x200000, 0x200000, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x200000, 0x01, 0x200000, 0x200000, 0x40000, 0x01, 0x01, 0x01, 0x01, 0x01, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x01, 0x200000, 0x01, 0x200000, 0x01, 0x200000, 0x01, 0x01, 0x01, 0x01, 0x200000, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x10, 0x10, 0x10, 0x10, 0x02, 0x200000, 0x200000, 0x02, 0x02, 0x01, 0x01,\n\t0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x01, 0x02, 0x02, 0x02, 0x02, 0x200000, 0x40000, 0x200000, 0x200000, 0x02, 0x200000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,\n\t0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200,\n\t0x200, 0x200, 0x200, 0x01, 0x02, 0x200, 0x200, 0x200, 0x200, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x40000, 0x200000, 0x200000, 0x40000, 0x200000, 0x200000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x40000, 0x200000, 0x200000, 0x40000, 0x200000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000,\n\t0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x2000, 0x4000, 0x2000, 0x4000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x40000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x2000, 0x4000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000,\n\t0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x40000, 0x40000, 0x40000,\n\t0x40000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,\n\t0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,\n\t0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x2000, 0x4000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000,\n\t0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000,\n\t0x40000, 0x40000, 0x40000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000,\n\t0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x2000, 0x4000, 0x2000, 0x4000, 0x40000, 0x40000, 0x40000, 0x40000,\n\t0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x2000, 0x4000, 0x40000, 0x40000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000,\n\t0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x200000, 0x200000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,\n\t0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x08, 0x08, 0x01, 0x01,\n\t0x01, 0x02, 0x01, 0x02, 0x02, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x01, 0x02, 0x01, 0x02, 0x20, 0x20, 0x20, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20000, 0x20000, 0x20000, 0x20000, 0x400, 0x20000, 0x20000,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00,\n\t0x20000, 0x20000, 0x8000, 0x10000, 0x8000, 0x10000, 0x20000, 0x20000, 0x20000, 0x8000, 0x10000, 0x20000, 0x8000, 0x10000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x1000, 0x20000, 0x20000, 0x1000, 0x20000, 0x8000, 0x10000, 0x20000, 0x20000,\n\t0x8000, 0x10000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x08, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x1000, 0x1000, 0x20000, 0x20000, 0x20000, 0x20000,\n\t0x1000, 0x20000, 0x2000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00,\n\t0x400000, 0x20000, 0x20000, 0x20000, 0x200000, 0x08, 0x10, 0x200, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x200000, 0x200000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x1000, 0x2000, 0x4000, 0x4000,\n\t0x200000, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x1000, 0x08, 0x08, 0x08, 0x08, 0x08, 0x200000, 0x200000, 0x200, 0x200, 0x200, 0x08, 0x10, 0x20000, 0x200000, 0x200000,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20, 0x100000, 0x100000, 0x08, 0x08, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20000, 0x08, 0x08, 0x08, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x200000, 0x200000, 0x400, 0x400, 0x400, 0x400, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00,\n\t0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x200000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,\n\t0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x20000, 0x20000,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x20000, 0x20000, 0x20000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x10, 0x20, 0x80, 0x80, 0x80, 0x20000, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x08,\n\t0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x08, 0x08, 0x00, 0x20,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x20, 0x20, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,\n\t0x100000, 0x100000, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,\n\t0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x08, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, 0x02,\n\t0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x08, 0x100000, 0x100000, 0x01, 0x02, 0x01, 0x02, 0x00, 0x01, 0x02, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,\n\t0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x08, 0x02, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x40, 0x40, 0x20, 0x20, 0x40, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x200000, 0x200000, 0x80000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x40, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,\n\t0x40, 0x40, 0x40, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20000, 0x20000, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20000, 0x20000, 0x20000, 0x10, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x20000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20000,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x20, 0x40, 0x40, 0x40,\n\t0x40, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x08, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x20000, 0x20000,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x20, 0x20, 0x40, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x40, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x20000, 0x20000, 0x20000, 0x20000,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x200000, 0x200000, 0x200000, 0x10, 0x40, 0x20, 0x40, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x20, 0x20, 0x20, 0x10, 0x10, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20,\n\t0x10, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x20000, 0x20000,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x20, 0x20, 0x40, 0x40, 0x20000, 0x20000, 0x10, 0x08, 0x08, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x100000, 0x08, 0x08, 0x08, 0x08,\n\t0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x40, 0x40, 0x20, 0x40, 0x40, 0x20, 0x40, 0x40, 0x20000, 0x40, 0x20, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\n\t0x8000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8000000,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8000000,\n\t0x10000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10000000,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00,\n\t0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000,\n\t0x100000, 0x100000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x4000, 0x2000,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x80000, 0x200000, 0x00, 0x00,\n\t0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x2000, 0x4000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x20000, 0x1000, 0x1000, 0x800, 0x800, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000,\n\t0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x20000, 0x20000, 0x2000, 0x4000, 0x20000, 0x20000, 0x20000, 0x20000, 0x800, 0x800, 0x800, 0x20000, 0x20000, 0x20000, 0x00, 0x20000, 0x20000, 0x20000, 0x20000, 0x1000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x20000,\n\t0x20000, 0x20000, 0x40000, 0x1000, 0x40000, 0x40000, 0x40000, 0x00, 0x20000, 0x80000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x4000000,\n\t0x00, 0x20000, 0x20000, 0x20000, 0x80000, 0x20000, 0x20000, 0x20000, 0x2000, 0x4000, 0x20000, 0x40000, 0x20000, 0x1000, 0x20000, 0x20000, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x20000, 0x20000, 0x40000, 0x40000, 0x40000, 0x20000,\n\t0x20000, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x2000, 0x20000, 0x4000, 0x100000, 0x800,\n\t0x100000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x2000, 0x40000, 0x4000, 0x40000, 0x2000,\n\t0x4000, 0x20000, 0x2000, 0x4000, 0x20000, 0x20000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,\n\t0x80000, 0x80000, 0x40000, 0x100000, 0x200000, 0x80000, 0x80000, 0x00, 0x200000, 0x40000, 0x40000, 0x40000, 0x40000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4000000, 0x4000000, 0x4000000, 0x200000, 0x200000, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00,\n\t0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,\n\t0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x400, 0x400, 0x400, 0x400, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x400, 0x400, 0x200000, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00,\n\t0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x20, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x20, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00,\n\t0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x200, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x20000,\n\t0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20000, 0x200, 0x200, 0x200, 0x200, 0x200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x20000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x200000, 0x200000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x20000,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20000,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\n\t0x10, 0x20, 0x20, 0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x20,\n\t0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x400, 0x400, 0x20000,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x400, 0x400, 0x400,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x200000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00,\n\t0x40, 0x20, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,\n\t0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,\n\t0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x20, 0x20, 0x20000, 0x20000, 0x4000000, 0x20000, 0x20000,\n\t0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,\n\t0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20000, 0x20000, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40,\n\t0x40, 0x10, 0x10, 0x10, 0x10, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x20000, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x40, 0x40, 0x20, 0x40, 0x20, 0x20, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20,\n\t0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x20, 0x10, 0x40, 0x40,\n\t0x20, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x40, 0x40, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x20, 0x40, 0x40, 0x40, 0x40, 0x20,\n\t0x20, 0x40, 0x20, 0x20, 0x10, 0x10, 0x20000, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x40, 0x20,\n\t0x20, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x20, 0x40, 0x20,\n\t0x20, 0x20000, 0x20000, 0x20000, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x40, 0x20, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\n\t0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x00, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x08, 0x08, 0x08, 0x08, 0x20000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400,\n\t0x400, 0x400, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,\n\t0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,\n\t0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x200000, 0x20, 0x20, 0x20000,\n\t0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40, 0x40, 0x20, 0x20, 0x20, 0x200000, 0x200000, 0x200000, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x20, 0x20, 0x20, 0x20, 0x20,\n\t0x20, 0x20, 0x20, 0x200000, 0x200000, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x20, 0x20, 0x20, 0x20, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00,\n\t0x200000, 0x200000, 0x20, 0x20, 0x20, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01,\n\t0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t0x01, 0x40000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x40000, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40000, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x40000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x40000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x40000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x40000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,\n\t0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n\t0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10,\n\t0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00,\n\t0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40000, 0x40000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,\n\t0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,\n\t0x00, 0x4000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000,\n\t0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10000000, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10000000, 0x00, 0x00,\n};\nconst uint32_t* GeneralCategoryDataPtr = GeneralCategoryData;\n\nconst size_t CanonicalCombiningClassIndex[34816] = {\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 64, 96, 128, 0, 0, 0, 0,\n\t0, 0, 0, 0, 160, 0, 0, 0, 0, 0, 0, 0, 192, 224, 256, 0, 288, 0, 320, 352, 0, 0, 384, 416, 448, 480, 512, 0, 0, 0, 0, 544,\n\t576, 608, 640, 0, 0, 0, 0, 672, 0, 704, 736, 0, 0, 704, 768, 0, 0, 704, 800, 0, 0, 704, 832, 0, 0, 704, 864, 0, 0, 0, 896, 0,\n\t0, 0, 928, 0, 0, 704, 960, 0, 0, 0, 992, 0, 0, 0, 1024, 0, 0, 1056, 1088, 0, 0, 1120, 1152, 0, 1184, 1216, 0, 1248, 1280, 0, 1312, 0,\n\t0, 1344, 0, 0, 1376, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1408, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1440, 1440, 0, 0, 0, 0, 1472, 0,\n\t0, 0, 0, 0, 0, 1504, 0, 0, 0, 1536, 0, 0, 0, 0, 0, 0, 1568, 0, 0, 1600, 0, 1632, 0, 0, 0, 1664, 777, 1696, 0, 1728, 0, 1760,\n\t0, 1792, 0, 0, 0, 0, 1824, 1856, 0, 0, 0, 0, 0, 0, 1888, 1920, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 1952, 1984, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 1422, 0, 0, 0, 782, 0, 0, 0, 1905, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 2016, 0, 0, 2048, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2080, 2112, 0, 0, 2144, 0, 0, 0, 0, 0, 0, 0, 0,\n\t1454, 0, 0, 0, 0, 0, 777, 2176, 0, 2208, 2240, 0, 0, 2272, 781, 0, 0, 0, 0, 0, 0, 2304, 2336, 951, 0, 0, 0, 0, 0, 0, 0, 2368,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2400, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2432, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2464, 0, 0, 0, 0, 0, 0, 0, 429, 0, 0, 0, 2496, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2528, 2560, 0, 0, 0, 0, 0, 2592, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 1454, 782, 0, 2624, 0, 0, 2656, 2688, 0, 2720, 0, 0, 781, 0, 0, 2752, 0, 0, 0, 0, 0, 2784, 0, 704, 2816, 2848, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 2880, 0, 0, 0, 0, 0, 0, 782, 2739, 0, 0, 782, 0, 0, 0, 2912, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2944, 0, 2976, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 3008, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3040, 3072, 3104, 0, 0, 0, 0, 2654, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 3136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n};\nconst size_t* CanonicalCombiningClassIndexPtr = CanonicalCombiningClassIndex;\n\nconst uint8_t CanonicalCombiningClassData[3168] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE8, 0xDC, 0xDC, 0xDC, 0xDC, 0xE8, 0xD8, 0xDC, 0xDC, 0xDC, 0xDC,\n\t0xDC, 0xCA, 0xCA, 0xDC, 0xDC, 0xDC, 0xDC, 0xCA, 0xCA, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0x01, 0x01, 0x01, 0x01, 0x01, 0xDC, 0xDC, 0xDC, 0xDC, 0xE6, 0xE6, 0xE6,\n\t0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xF0, 0xE6, 0xDC, 0xDC, 0xDC, 0xE6, 0xE6, 0xE6, 0xDC, 0xDC, 0x00, 0xE6, 0xE6, 0xE6, 0xDC, 0xDC, 0xDC, 0xDC, 0xE6, 0xE8, 0xDC, 0xDC, 0xE6, 0xE9, 0xEA, 0xEA, 0xE9,\n\t0xEA, 0xEA, 0xE9, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xE6, 0xE6, 0xE6, 0xE6, 0xDC, 0xE6, 0xE6, 0xE6, 0xDE, 0xDC, 0xE6, 0xE6, 0xE6, 0xE6,\n\t0xE6, 0xE6, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xE6, 0xE6, 0xDC, 0xE6, 0xE6, 0xDE, 0xE4, 0xE6, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x13, 0x14, 0x15, 0x16, 0x00, 0x17,\n\t0x00, 0x18, 0x19, 0x00, 0xE6, 0xDC, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x1E, 0x1F, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0xE6, 0xE6, 0xDC, 0xDC, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xDC, 0xE6, 0xE6, 0xDC,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0xE6,\n\t0xE6, 0xE6, 0xE6, 0xDC, 0xE6, 0x00, 0x00, 0xE6, 0xE6, 0x00, 0xDC, 0xE6, 0xE6, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xDC, 0xE6, 0xE6, 0xDC, 0xE6, 0xE6, 0xDC, 0xDC, 0xDC, 0xE6, 0xDC, 0xDC, 0xE6, 0xDC, 0xE6,\n\t0xE6, 0xE6, 0xDC, 0xE6, 0xDC, 0xE6, 0xDC, 0xE6, 0xDC, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xDC, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,\n\t0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0xE6, 0xE6, 0xE6, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xDC, 0xE6, 0xE6, 0xDC, 0xE6, 0xE6, 0xE6, 0xDC, 0xDC, 0xDC, 0x1B, 0x1C, 0x1D, 0xE6, 0xE6, 0xE6, 0xDC, 0xE6, 0xE6, 0xDC, 0xDC, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE6, 0xDC, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x67, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x6B, 0x6B, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0x7A, 0x7A, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x00, 0xDC, 0x00, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x82, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x82, 0x82, 0x00, 0x00,\n\t0x82, 0x00, 0xE6, 0xE6, 0x09, 0x00, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xE6, 0xDC, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0xDC,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xE6, 0xE6, 0xDC, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xDC, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0x00, 0x01, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xE6, 0xE6, 0xDC, 0xDC, 0xDC, 0xDC,\n\t0xE6, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0xE6, 0xE6, 0xDC, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xDC, 0xE6, 0xE6, 0xEA, 0xD6, 0xDC, 0xCA, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,\n\t0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE9, 0xDC, 0xE6, 0xDC,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0x01, 0x01, 0xE6, 0xE6, 0xE6, 0xE6, 0x01, 0x01, 0x01, 0xE6, 0xE6, 0x00, 0x00, 0x00,\n\t0x00, 0xE6, 0x00, 0x00, 0x00, 0x01, 0x01, 0xE6, 0xDC, 0xE6, 0x01, 0x01, 0xDC, 0xDC, 0xDC, 0xDC, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDA, 0xE4, 0xE8, 0xDE, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x00, 0xE6, 0xE6, 0xDC, 0x00, 0x00, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6,\n\t0x00, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00,\n\t0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x00, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x01, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x09,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x09, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0xD8, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0xE2, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,\n\t0xDC, 0xDC, 0xDC, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xDC, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n};\nconst uint8_t* CanonicalCombiningClassDataPtr = CanonicalCombiningClassData;\n\nconst size_t QuickCheckCaseMappedIndex[34816] = {\n\t0, 0, 32, 64, 0, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 192, 448, 480, 512, 544, 0, 0, 0, 0, 0, 576, 608, 640, 672, 704, 736,\n\t768, 800, 832, 192, 864, 192, 896, 192, 192, 928, 960, 992, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 765, 1056, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1088, 0, 0, 0, 0, 192, 192, 192, 192, 1120, 192, 192, 192, 1152, 1184, 1216, 1248, 1280, 1312, 1344, 1376,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 1408, 1440, 1472, 1504, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 1536, 1472, 1568, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t765, 1600, 1632, 1664, 192, 192, 192, 1696, 816, 1728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 1760, 1792, 0, 0, 0, 0, 1824, 192, 1856, 1888, 1920, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1952, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 1984, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t765, 2016, 2048, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 765, 816, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n};\nconst size_t* QuickCheckCaseMappedIndexPtr = QuickCheckCaseMappedIndex;\n\nconst uint8_t QuickCheckCaseMappedData[2080] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0D,\n\t0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\n\t0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05,\n\t0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A,\n\t0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0D, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05,\n\t0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0D,\n\t0x05, 0x0A, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x0A, 0x05, 0x0A, 0x0A, 0x0A, 0x05, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x0A, 0x0A, 0x05, 0x0A, 0x0A, 0x0A, 0x05, 0x05, 0x00, 0x0A, 0x0A, 0x05, 0x0A,\n\t0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x0A, 0x05, 0x0A, 0x00, 0x00, 0x0A, 0x05, 0x0A, 0x0A, 0x05, 0x0A, 0x0A, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x0A, 0x05, 0x00, 0x00, 0x0A, 0x05, 0x00, 0x05,\n\t0x00, 0x00, 0x00, 0x00, 0x0E, 0x0B, 0x05, 0x0E, 0x0B, 0x05, 0x0E, 0x0B, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x05, 0x0A, 0x05,\n\t0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0D, 0x0E, 0x0B, 0x05, 0x0A, 0x05, 0x0A, 0x0A, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05,\n\t0x0A, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0A, 0x05, 0x0A, 0x0A, 0x05,\n\t0x05, 0x0A, 0x05, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x05, 0x05, 0x00, 0x05, 0x00, 0x05, 0x05, 0x00, 0x00, 0x00,\n\t0x05, 0x05, 0x00, 0x05, 0x00, 0x05, 0x05, 0x00, 0x05, 0x05, 0x00, 0x05, 0x05, 0x00, 0x00, 0x05, 0x00, 0x05, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,\n\t0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x05, 0x05, 0x05, 0x00, 0x0A,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x0A, 0x0A, 0x0A, 0x00, 0x0A, 0x00, 0x0A, 0x0A, 0x0D, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,\n\t0x0A, 0x0A, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x0D, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\n\t0x05, 0x05, 0x0D, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0A, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05,\n\t0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0D, 0x0D, 0x05, 0x05, 0x0A, 0x0D, 0x00, 0x0A, 0x05, 0x0A, 0x0A, 0x05, 0x00, 0x0A, 0x0A, 0x0A,\n\t0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,\n\t0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\n\t0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\n\t0x0A, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05,\n\t0x0A, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05,\n\t0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,\n\t0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\n\t0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,\n\t0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x0A, 0x00,\n\t0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x00,\n\t0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,\n\t0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x0D, 0x05, 0x0D, 0x05, 0x0D, 0x05, 0x0D, 0x05, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x0A,\n\t0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00,\n\t0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,\n\t0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x05, 0x05, 0x0D, 0x0D, 0x0D, 0x00, 0x0D, 0x0D, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x00, 0x0D, 0x00,\n\t0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x00, 0x0D, 0x0D, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x00, 0x00, 0x00, 0x05, 0x05, 0x0D, 0x0D, 0x00, 0x00, 0x0D, 0x0D, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00,\n\t0x05, 0x05, 0x0D, 0x0D, 0x0D, 0x05, 0x0D, 0x0D, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x00, 0x0D, 0x0D, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\n\t0x00, 0x00, 0x00, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,\n\t0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\n\t0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00,\n\t0x0A, 0x05, 0x0A, 0x0A, 0x0A, 0x05, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x0A, 0x05, 0x00, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0A,\n\t0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05,\n\t0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x0A, 0x05,\n\t0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x0A, 0x05, 0x0A, 0x00, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05,\n\t0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\n\t0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n};\nconst uint8_t* QuickCheckCaseMappedDataPtr = QuickCheckCaseMappedData;\n\nconst size_t QuickCheckNFCIndex[34816] = {\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 64, 96, 128, 160, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 256, 0, 0, 288, 320, 0, 0, 352, 384, 0, 0, 0, 0, 0, 0, 288, 416, 0, 0, 288, 448, 0,\n\t0, 0, 480, 0, 0, 0, 512, 0, 0, 288, 544, 0, 0, 0, 576, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 608, 640, 672, 704, 0, 0,\n\t0, 736, 0, 0, 0, 0, 0, 0, 0, 0, 0, 768, 0, 800, 211, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 832, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 864, 0, 896, 928, 960,\n\t286, 0, 0, 0, 0, 0, 0, 0, 0, 992, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1024, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1056, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 1088, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1152, 1184, 1120, 1216, 1120, 1120, 1248, 0, 1280, 1312, 1344, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 1376, 0, 0, 0, 1408, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 288, 1440, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 1472, 0, 0, 0, 0, 0, 0, 0, 1448, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1504, 1536, 0, 253, 167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1568, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n};\nconst size_t* QuickCheckNFCIndexPtr = QuickCheckNFCIndex;\n\nconst uint8_t QuickCheckNFCData[1600] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,\n\t0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,\n\t0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00,\n\t0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,\n};\nconst uint8_t* QuickCheckNFCDataPtr = QuickCheckNFCData;\n\nconst size_t QuickCheckNFDIndex[34816] = {\n\t0, 0, 0, 0, 0, 0, 32, 64, 96, 128, 160, 192, 0, 224, 256, 288, 320, 352, 0, 0, 0, 0, 0, 0, 0, 0, 384, 416, 448, 480, 512, 0,\n\t544, 576, 608, 640, 0, 0, 672, 704, 0, 0, 0, 0, 0, 0, 0, 0, 0, 736, 0, 0, 0, 0, 768, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 800, 832, 0, 0, 0, 864, 0, 0, 896, 928, 0, 0, 0, 0, 0, 0, 0, 960, 0, 992, 0, 1024, 0,\n\t0, 0, 1056, 0, 0, 0, 1088, 0, 0, 0, 1024, 0, 0, 0, 1120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1152, 1184, 1216, 1248, 0, 0,\n\t0, 1280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1312, 1344, 1376, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 312, 312, 312, 312, 1408, 312, 312, 1440, 1472, 312, 1504, 1536, 312, 1568, 1600, 1632,\n\t1664, 0, 0, 0, 0, 0, 0, 0, 0, 1696, 0, 0, 1728, 1760, 1792, 0, 1824, 1856, 1888, 1920, 1952, 1984, 0, 2016, 0, 2048, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2080, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 2112, 2144, 2176, 2208, 2240, 2272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,\n\t312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,\n\t312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,\n\t312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,\n\t312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,\n\t312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,\n\t312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,\n\t312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,\n\t312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,\n\t312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,\n\t312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 2304, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 312, 312, 312, 312, 312, 312, 312, 312, 2336, 2368, 312, 2400, 312, 312, 1440, 0, 2432, 2464, 2496, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 2528, 2560, 0, 0, 0, 2592, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2624, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 2656, 0, 0, 0, 0, 0, 0, 0, 2688, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1775, 2720, 0, 2752, 820, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 2784, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n};\nconst size_t* QuickCheckNFDIndexPtr = QuickCheckNFDIndex;\n\nconst uint8_t QuickCheckNFDData[2816] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,\n\t0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00,\n\t0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00,\n\t0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,\n\t0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00,\n\t0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00,\n\t0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,\n\t0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00,\n\t0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,\n};\nconst uint8_t* QuickCheckNFDDataPtr = QuickCheckNFDData;\n\nconst size_t QuickCheckNFKCIndex[34816] = {\n\t0, 0, 0, 0, 0, 32, 0, 0, 0, 64, 96, 128, 0, 0, 160, 192, 0, 0, 0, 0, 0, 224, 256, 288, 320, 352, 384, 416, 448, 0, 480, 512,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 544, 0, 0, 0, 0, 0, 576, 608, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 640, 672, 0, 0, 704, 736, 0, 0, 768, 800, 0, 0, 0, 0, 0, 0, 704, 832, 0, 0, 704, 864, 0,\n\t0, 0, 896, 0, 0, 0, 928, 0, 0, 704, 960, 0, 0, 0, 992, 0, 0, 1024, 0, 0, 0, 1024, 1056, 0, 1088, 0, 1120, 1152, 1184, 1216, 0, 0,\n\t0, 1248, 0, 0, 0, 0, 0, 1280, 0, 0, 0, 1312, 0, 1344, 595, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1376, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 1408, 1440, 1472, 669, 1504, 0, 0, 0, 0, 0, 0, 1536, 0, 0, 0, 0, 0, 0, 1568, 0, 1600, 1632, 1664,\n\t1696, 1728, 1760, 1792, 1824, 97, 0, 0, 1856, 1888, 1920, 1504, 1034, 0, 0, 0, 0, 1952, 0, 0, 0, 0, 0, 0, 0, 1984, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 1504, 1504, 1504, 1504, 2016, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1229, 0, 0, 2048, 0, 0, 2080, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 2112, 0, 0, 0, 0, 0, 0, 0, 2144, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 1024, 1504, 1504, 1504, 1504, 1504, 1504, 2176, 0,\n\t105, 2208, 0, 0, 2240, 0, 0, 249, 0, 2272, 1504, 1504, 2304, 0, 0, 0, 2336, 1504, 2368, 2400, 1504, 1504, 1504, 2432, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2464, 0, 0, 0, 0, 0, 0, 2496, 0, 0, 0, 1969,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 2528, 2560, 1504, 2592, 1504, 1504, 2624, 0, 2656, 2688, 2720, 1504, 1504, 2752, 2784, 1504,\n\t1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 2289, 2160, 1504, 2816, 1504, 696, 2848, 2880, 2160, 2912, 2944, 1504, 1504, 1504, 2976, 1503, 1504, 1504, 1504, 1504, 2432, 3008, 3040,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 3072, 0, 0, 0, 3104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 704, 3136, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 3168, 0, 0, 0, 0, 0, 0, 0, 1008, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3200, 288, 0, 669, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t1504, 1504, 3232, 1504, 3264, 3296, 3328, 1504, 3360, 3392, 3424, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 3456, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 3488, 1504,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3520, 3552, 3584, 3616, 3648, 3680, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 3712, 2416, 3744, 3776, 3808, 0, 0, 0, 3840, 3872, 3904, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 2289, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n};\nconst size_t* QuickCheckNFKCIndexPtr = QuickCheckNFKCIndex;\n\nconst uint8_t QuickCheckNFKCData[3936] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,\n\t0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,\n\t0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02,\n\t0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,\n\t0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00,\n\t0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,\n\t0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02,\n\t0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n};\nconst uint8_t* QuickCheckNFKCDataPtr = QuickCheckNFKCData;\n\nconst size_t QuickCheckNFKDIndex[34816] = {\n\t0, 0, 0, 0, 0, 32, 64, 96, 128, 160, 192, 224, 0, 256, 288, 320, 352, 384, 0, 0, 0, 416, 448, 480, 0, 0, 512, 544, 576, 608, 640, 672,\n\t704, 736, 768, 800, 0, 0, 832, 864, 0, 0, 0, 0, 896, 0, 0, 0, 0, 478, 0, 928, 0, 0, 960, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 992, 1024, 0, 0, 0, 1056, 0, 0, 1088, 1120, 0, 0, 0, 0, 0, 0, 0, 1152, 0, 1184, 0, 1216, 0,\n\t0, 0, 1248, 0, 0, 0, 1280, 0, 0, 0, 1216, 0, 0, 0, 1312, 0, 0, 1344, 0, 0, 0, 1376, 1408, 0, 1440, 0, 1472, 1504, 1536, 1568, 0, 0,\n\t0, 897, 0, 0, 0, 0, 0, 1600, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1632, 1664, 1696, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 1728, 1760, 1792, 1824, 344, 0, 0, 344, 344, 344, 344, 1775, 344, 344, 232, 1856, 344, 1888, 1920, 344, 1952, 1984, 2016,\n\t2048, 2080, 2112, 2144, 2176, 2208, 0, 0, 2240, 2272, 2304, 344, 2336, 1438, 2368, 0, 2400, 2432, 2464, 2496, 2528, 2560, 0, 2592, 0, 2624, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 344, 344, 344, 344, 2656, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1581, 0, 0, 2688, 0, 0, 2720, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 2752, 0, 0, 0, 0, 0, 0, 0, 746, 0, 0, 0, 0, 0, 0, 0, 0, 441, 0, 0, 2784, 344, 344, 344, 344, 344, 344, 2816, 0,\n\t440, 2848, 2880, 2912, 2944, 2976, 3008, 3040, 0, 3072, 344, 344, 3104, 0, 0, 0, 1919, 344, 3136, 1919, 344, 344, 344, 1919, 344, 344, 344, 344, 344, 344, 344, 344,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3168, 0, 0, 0, 0, 0, 0, 963, 0, 0, 0, 3200,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 404, 0, 0, 0, 0, 0,\n\t344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,\n\t344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,\n\t344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,\n\t344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,\n\t344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,\n\t344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,\n\t344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,\n\t344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,\n\t344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,\n\t344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,\n\t344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 400, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 344, 344, 344, 344, 344, 344, 344, 344, 3232, 3264, 344, 3296, 344, 344, 232, 0, 3328, 3360, 3392, 344, 344, 3424, 273, 344,\n\t344, 344, 344, 344, 344, 344, 344, 344, 344, 3089, 3456, 344, 326, 344, 3434, 3488, 3520, 3552, 3584, 3616, 344, 344, 344, 3648, 3397, 344, 344, 344, 344, 1919, 3680, 3712,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 3744, 2205, 0, 0, 0, 3776, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3808, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 3840, 0, 0, 0, 0, 0, 0, 0, 3198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3442, 480, 0, 3872, 440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t344, 344, 1952, 344, 3904, 3936, 3968, 344, 4000, 4032, 4064, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 4096, 344, 344, 344, 344, 344, 344, 344, 344, 4128, 344,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4160, 4192, 4224, 4256, 4288, 4320, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 4352, 4384, 3152, 4416, 963, 0, 0, 0, 4448, 4480, 4512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 3089, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n};\nconst size_t* QuickCheckNFKDIndexPtr = QuickCheckNFKDIndex;\n\nconst uint8_t QuickCheckNFKDData[4544] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00,\n\t0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00,\n\t0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00,\n\t0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,\n\t0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00,\n\t0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,\n\t0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02,\n\t0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n};\nconst uint8_t* QuickCheckNFKDDataPtr = QuickCheckNFKDData;\n\nconst uint32_t NFDIndex1[272] = {\n\t0, 128, 256, 384, 512, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 640,\n\t392, 768, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 896, 392, 392,\n\t392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 1024,\n\t392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,\n\t392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,\n\t392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,\n\t392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,\n\t392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,\n\t392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,\n\t392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,\n\t392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,\n\t392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,\n\t392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,\n\t392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,\n\t392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,\n\t392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,\n\t392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,\n};\nconst uint32_t* NFDIndex1Ptr = NFDIndex1;\n\nconst uint32_t NFDIndex2[1152] = {\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0x0, 0xE0, 0x100, 0x120,\n\t0x140, 0x160, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x180, 0x1A0, 0x1C0, 0x1E0, 0x200, 0x0,\n\t0x220, 0x240, 0x260, 0x280, 0x0, 0x0, 0x2A0, 0x2C0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x2E0, 0x0, 0x0, 0x0, 0x0, 0x300, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x320, 0x340, 0x0, 0x0, 0x0, 0x360, 0x0,\n\t0x0, 0x380, 0x3A0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3C0, 0x0, 0x3E0, 0x0, 0x400, 0x0,\n\t0x0, 0x0, 0x420, 0x0, 0x0, 0x0, 0x440, 0x0, 0x0, 0x0, 0x460, 0x0, 0x0, 0x0, 0x480, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4A0, 0x4C0, 0x4E0, 0x500, 0x0, 0x0,\n\t0x0, 0x520, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x540, 0x560, 0x580, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x5A0, 0x5C0, 0x5E0, 0x600, 0x620, 0x640, 0x660, 0x680, 0x6A0, 0x6C0, 0x6E0, 0x700, 0x720, 0x740, 0x760, 0x780,\n\t0x7A0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7C0, 0x0, 0x0, 0x7E0, 0x800, 0x820, 0x0,\n\t0x840, 0x860, 0x880, 0x8A0, 0x8C0, 0x8E0, 0x0, 0x900, 0x0, 0x920, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x940, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x960, 0x980, 0x9A0, 0x9C0, 0x9E0, 0xA00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xA20, 0xA40, 0xA60, 0xA80, 0xAA0, 0xAC0, 0xAE0, 0xB00,\n\t0xB20, 0xB40, 0xB60, 0xB80, 0xBA0, 0xBC0, 0xBE0, 0x0, 0xC00, 0xC20, 0xC40, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0xC60, 0xC80, 0x0, 0x0, 0x0, 0xCA0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xCC0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0xCE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xD00, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xD20, 0xD40, 0x0, 0xD60, 0xD80, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0xDA0, 0xDC0, 0xDE0, 0xE00, 0xE20, 0xE40, 0xE60, 0xE80, 0xEA0, 0xEC0, 0xEE0, 0xF00, 0xF20, 0xF40, 0xF60, 0xF80,\n\t0xFA0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n};\nconst uint32_t* NFDIndex2Ptr = NFDIndex2;\n\nconst uint32_t NFDData[4032] = {\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3000000, 0x3000003, 0x3000006, 0x3000009, 0x300000C, 0x300000F, 0x0, 0x3000012, 0x3000015, 0x3000018, 0x300001B, 0x300001E, 0x3000021, 0x3000024, 0x3000027, 0x300002A,\n\t0x0, 0x300002D, 0x3000030, 0x3000033, 0x3000036, 0x3000039, 0x300003C, 0x0, 0x0, 0x300003F, 0x3000042, 0x3000045, 0x3000048, 0x300004B, 0x0, 0x0,\n\t0x300004E, 0x3000051, 0x3000054, 0x3000057, 0x300005A, 0x300005D, 0x0, 0x3000060, 0x3000063, 0x3000066, 0x3000069, 0x300006C, 0x300006F, 0x3000072, 0x3000075, 0x3000078,\n\t0x0, 0x300007B, 0x300007E, 0x3000081, 0x3000084, 0x3000087, 0x300008A, 0x0, 0x0, 0x300008D, 0x3000090, 0x3000093, 0x3000096, 0x3000099, 0x0, 0x300009C,\n\t0x300009F, 0x30000A2, 0x30000A5, 0x30000A8, 0x30000AB, 0x30000AE, 0x30000B1, 0x30000B4, 0x30000B7, 0x30000BA, 0x30000BD, 0x30000C0, 0x30000C3, 0x30000C6, 0x30000C9, 0x30000CC,\n\t0x0, 0x0, 0x30000CF, 0x30000D2, 0x30000D5, 0x30000D8, 0x30000DB, 0x30000DE, 0x30000E1, 0x30000E4, 0x30000E7, 0x30000EA, 0x30000ED, 0x30000F0, 0x30000F3, 0x30000F6,\n\t0x30000F9, 0x30000FC, 0x30000FF, 0x3000102, 0x3000105, 0x3000108, 0x0, 0x0, 0x300010B, 0x300010E, 0x3000111, 0x3000114, 0x3000117, 0x300011A, 0x300011D, 0x3000120,\n\t0x3000123, 0x0, 0x0, 0x0, 0x3000126, 0x3000129, 0x300012C, 0x300012F, 0x0, 0x3000132, 0x3000135, 0x3000138, 0x300013B, 0x300013E, 0x3000141, 0x0,\n\t0x0, 0x0, 0x0, 0x3000144, 0x3000147, 0x300014A, 0x300014D, 0x3000150, 0x3000153, 0x0, 0x0, 0x0, 0x3000156, 0x3000159, 0x300015C, 0x300015F,\n\t0x3000162, 0x3000165, 0x0, 0x0, 0x3000168, 0x300016B, 0x300016E, 0x3000171, 0x3000174, 0x3000177, 0x300017A, 0x300017D, 0x3000180, 0x3000183, 0x3000186, 0x3000189,\n\t0x300018C, 0x300018F, 0x3000192, 0x3000195, 0x3000198, 0x300019B, 0x0, 0x0, 0x300019E, 0x30001A1, 0x30001A4, 0x30001A7, 0x30001AA, 0x30001AD, 0x30001B0, 0x30001B3,\n\t0x30001B6, 0x30001B9, 0x30001BC, 0x30001BF, 0x30001C2, 0x30001C5, 0x30001C8, 0x30001CB, 0x30001CE, 0x30001D1, 0x30001D4, 0x30001D7, 0x30001DA, 0x30001DD, 0x30001E0, 0x0,\n\t0x30001E3, 0x30001E6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30001E9,\n\t0x30001EC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30001EF, 0x30001F2, 0x30001F5,\n\t0x30001F8, 0x30001FB, 0x30001FE, 0x3000201, 0x3000204, 0x5000207, 0x500020C, 0x5000211, 0x5000216, 0x500021B, 0x5000220, 0x5000225, 0x500022A, 0x0, 0x500022F, 0x5000234,\n\t0x5000239, 0x500023E, 0x4000243, 0x4000247, 0x0, 0x0, 0x300024B, 0x300024E, 0x3000251, 0x3000254, 0x3000257, 0x300025A, 0x500025D, 0x5000262, 0x4000267, 0x400026B,\n\t0x300026F, 0x0, 0x0, 0x0, 0x3000272, 0x3000275, 0x0, 0x0, 0x3000278, 0x300027B, 0x500027E, 0x5000283, 0x4000288, 0x400028C, 0x4000290, 0x4000294,\n\t0x3000298, 0x300029B, 0x300029E, 0x30002A1, 0x30002A4, 0x30002A7, 0x30002AA, 0x30002AD, 0x30002B0, 0x30002B3, 0x30002B6, 0x30002B9, 0x30002BC, 0x30002BF, 0x30002C2, 0x30002C5,\n\t0x30002C8, 0x30002CB, 0x30002CE, 0x30002D1, 0x30002D4, 0x30002D7, 0x30002DA, 0x30002DD, 0x30002E0, 0x30002E3, 0x30002E6, 0x30002E9, 0x0, 0x0, 0x30002EC, 0x30002EF,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3000239, 0x300023E, 0x30002F2, 0x30002F5, 0x50002F8, 0x50002FD, 0x5000302, 0x5000307, 0x300030C, 0x300030F,\n\t0x5000312, 0x5000317, 0x300031C, 0x300031F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x2000001, 0x2000004, 0x0, 0x2000322, 0x4000212, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x2000324, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1000326, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x4000327, 0x400032B, 0x200032F, 0x4000331, 0x4000335, 0x4000339, 0x0, 0x400033D, 0x0, 0x4000341, 0x4000345,\n\t0x6000349, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x400034F, 0x4000353, 0x4000357, 0x400035B, 0x400035F, 0x4000363,\n\t0x6000367, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000349, 0x4000367, 0x400036D, 0x4000371, 0x4000375, 0x0,\n\t0x0, 0x0, 0x0, 0x4000379, 0x400037D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x4000381, 0x4000385, 0x0, 0x4000389, 0x0, 0x0, 0x0, 0x400038D, 0x0, 0x0, 0x0, 0x0, 0x4000391, 0x4000395, 0x4000399, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x400039D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40003A1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x40003A5, 0x40003A9, 0x0, 0x40003AD, 0x0, 0x0, 0x0, 0x40003B1, 0x0, 0x0, 0x0, 0x0, 0x40003B5, 0x40003B9, 0x40003BD, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40003C1, 0x40003C5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x40003C9, 0x40003CD, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x40003D1, 0x40003D5, 0x40003D9, 0x40003DD, 0x0, 0x0, 0x40003E1, 0x40003E5, 0x0, 0x0, 0x40003E9, 0x40003ED, 0x40003F1, 0x40003F5, 0x40003F9, 0x40003FD,\n\t0x0, 0x0, 0x4000401, 0x4000405, 0x4000409, 0x400040D, 0x4000411, 0x4000415, 0x0, 0x0, 0x4000419, 0x400041D, 0x4000421, 0x4000425, 0x4000429, 0x400042D,\n\t0x4000431, 0x4000435, 0x4000439, 0x400043D, 0x4000441, 0x4000445, 0x0, 0x0, 0x4000449, 0x400044D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x4000451, 0x4000455, 0x4000459, 0x400045D, 0x4000461, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x4000465, 0x0, 0x4000469, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x400046D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000471, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x6000477, 0x0, 0x0, 0x600047D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000483, 0x6000489, 0x600048F, 0x6000495, 0x600049B, 0x60004A1, 0x60004A7, 0x60004AD,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60004B3, 0x60004B9, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60004BF, 0x60004C5, 0x0, 0x60004CB,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x60004D1, 0x0, 0x0, 0x60004D7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60004DD, 0x60004E3, 0x60004E9, 0x0, 0x0, 0x60004EF, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60004F5, 0x0, 0x0, 0x60004FB, 0x6000501, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000507, 0x600050D, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x6000513, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000519, 0x600051F, 0x6000525, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x600052B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x6000531, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000537, 0x600053D, 0x0, 0x6000543, 0x9000549, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000552, 0x6000558, 0x600055E, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000564, 0x0, 0x600056A, 0x9000570, 0x6000579, 0x0,\n\t0x0, 0x0, 0x0, 0x600057F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000585, 0x0, 0x0,\n\t0x0, 0x0, 0x600058B, 0x0, 0x0, 0x0, 0x0, 0x6000591, 0x0, 0x0, 0x0, 0x0, 0x6000597, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x600059D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x60005A3, 0x0, 0x60005A9, 0x60005AF, 0x0, 0x60005B5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x60005BB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x60005C1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005C7, 0x0, 0x0,\n\t0x0, 0x0, 0x60005CD, 0x0, 0x0, 0x0, 0x0, 0x60005D3, 0x0, 0x0, 0x0, 0x0, 0x60005D9, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005DF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005E5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005EB, 0x0, 0x60005F1, 0x0, 0x60005F7, 0x0, 0x60005FD, 0x0, 0x6000603, 0x0,\n\t0x0, 0x0, 0x6000609, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x600060F, 0x0, 0x6000615, 0x0, 0x0,\n\t0x600061B, 0x6000621, 0x0, 0x6000627, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x300062D, 0x3000630, 0x3000633, 0x3000636, 0x3000639, 0x300063C, 0x300063F, 0x3000642, 0x5000645, 0x500064A, 0x300064F, 0x3000652, 0x3000655, 0x3000658, 0x300065B, 0x300065E,\n\t0x3000661, 0x3000664, 0x3000667, 0x300066A, 0x500066D, 0x5000672, 0x5000677, 0x500067C, 0x3000681, 0x3000684, 0x3000687, 0x300068A, 0x500068D, 0x5000692, 0x3000697, 0x300069A,\n\t0x300069D, 0x30006A0, 0x30006A3, 0x30006A6, 0x30006A9, 0x30006AC, 0x30006AF, 0x30006B2, 0x30006B5, 0x30006B8, 0x30006BB, 0x30006BE, 0x30006C1, 0x30006C4, 0x50006C7, 0x50006CC,\n\t0x30006D1, 0x30006D4, 0x30006D7, 0x30006DA, 0x30006DD, 0x30006E0, 0x30006E3, 0x30006E6, 0x50006E9, 0x50006EE, 0x30006F3, 0x30006F6, 0x30006F9, 0x30006FC, 0x30006FF, 0x3000702,\n\t0x3000705, 0x3000708, 0x300070B, 0x300070E, 0x3000711, 0x3000714, 0x3000717, 0x300071A, 0x300071D, 0x3000720, 0x3000723, 0x3000726, 0x5000729, 0x500072E, 0x5000733, 0x5000738,\n\t0x500073D, 0x5000742, 0x5000747, 0x500074C, 0x3000751, 0x3000754, 0x3000757, 0x300075A, 0x300075D, 0x3000760, 0x3000763, 0x3000766, 0x5000769, 0x500076E, 0x3000773, 0x3000776,\n\t0x3000779, 0x300077C, 0x300077F, 0x3000782, 0x5000785, 0x500078A, 0x500078F, 0x5000794, 0x5000799, 0x500079E, 0x30007A3, 0x30007A6, 0x30007A9, 0x30007AC, 0x30007AF, 0x30007B2,\n\t0x30007B5, 0x30007B8, 0x30007BB, 0x30007BE, 0x30007C1, 0x30007C4, 0x30007C7, 0x30007CA, 0x50007CD, 0x50007D2, 0x50007D7, 0x50007DC, 0x30007E1, 0x30007E4, 0x30007E7, 0x30007EA,\n\t0x30007ED, 0x30007F0, 0x30007F3, 0x30007F6, 0x30007F9, 0x30007FC, 0x30007FF, 0x3000802, 0x3000805, 0x3000808, 0x300080B, 0x300080E, 0x3000811, 0x3000814, 0x3000817, 0x300081A,\n\t0x300081D, 0x3000820, 0x3000823, 0x3000826, 0x3000829, 0x300082C, 0x300082F, 0x3000832, 0x3000835, 0x3000838, 0x0, 0x400083B, 0x0, 0x0, 0x0, 0x0,\n\t0x300083F, 0x3000842, 0x3000845, 0x3000848, 0x500084B, 0x5000850, 0x5000855, 0x500085A, 0x500085F, 0x5000864, 0x5000869, 0x500086E, 0x5000873, 0x5000878, 0x500087D, 0x5000882,\n\t0x5000887, 0x500088C, 0x5000891, 0x5000896, 0x500089B, 0x50008A0, 0x50008A5, 0x50008AA, 0x30008AF, 0x30008B2, 0x30008B5, 0x30008B8, 0x30008BB, 0x30008BE, 0x50008C1, 0x50008C6,\n\t0x50008CB, 0x50008D0, 0x50008D5, 0x50008DA, 0x50008DF, 0x50008E4, 0x50008E9, 0x50008EE, 0x30008F3, 0x30008F6, 0x30008F9, 0x30008FC, 0x30008FF, 0x3000902, 0x3000905, 0x3000908,\n\t0x500090B, 0x5000910, 0x5000915, 0x500091A, 0x500091F, 0x5000924, 0x5000929, 0x500092E, 0x5000933, 0x5000938, 0x500093D, 0x5000942, 0x5000947, 0x500094C, 0x5000951, 0x5000956,\n\t0x500095B, 0x5000960, 0x5000965, 0x500096A, 0x300096F, 0x3000972, 0x3000975, 0x3000978, 0x500097B, 0x5000980, 0x5000985, 0x500098A, 0x500098F, 0x5000994, 0x5000999, 0x500099E,\n\t0x50009A3, 0x50009A8, 0x30009AD, 0x30009B0, 0x30009B3, 0x30009B6, 0x30009B9, 0x30009BC, 0x30009BF, 0x30009C2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x40009C5, 0x40009C9, 0x60009CD, 0x60009D3, 0x60009D9, 0x60009DF, 0x60009E5, 0x60009EB, 0x40009F1, 0x40009F5, 0x60009F9, 0x60009FF, 0x6000A05, 0x6000A0B, 0x6000A11, 0x6000A17,\n\t0x4000A1D, 0x4000A21, 0x6000A25, 0x6000A2B, 0x6000A31, 0x6000A37, 0x0, 0x0, 0x4000A3D, 0x4000A41, 0x6000A45, 0x6000A4B, 0x6000A51, 0x6000A57, 0x0, 0x0,\n\t0x4000A5D, 0x4000A61, 0x6000A65, 0x6000A6B, 0x6000A71, 0x6000A77, 0x6000A7D, 0x6000A83, 0x4000A89, 0x4000A8D, 0x6000A91, 0x6000A97, 0x6000A9D, 0x6000AA3, 0x6000AA9, 0x6000AAF,\n\t0x4000AB5, 0x4000AB9, 0x6000ABD, 0x6000AC3, 0x6000AC9, 0x6000ACF, 0x6000AD5, 0x6000ADB, 0x4000AE1, 0x4000AE5, 0x6000AE9, 0x6000AEF, 0x6000AF5, 0x6000AFB, 0x6000B01, 0x6000B07,\n\t0x4000B0D, 0x4000B11, 0x6000B15, 0x6000B1B, 0x6000B21, 0x6000B27, 0x0, 0x0, 0x4000B2D, 0x4000B31, 0x6000B35, 0x6000B3B, 0x6000B41, 0x6000B47, 0x0, 0x0,\n\t0x4000B4D, 0x4000B51, 0x6000B55, 0x6000B5B, 0x6000B61, 0x6000B67, 0x6000B6D, 0x6000B73, 0x0, 0x4000B79, 0x0, 0x6000B7D, 0x0, 0x6000B83, 0x0, 0x6000B89,\n\t0x4000B8F, 0x4000B93, 0x6000B97, 0x6000B9D, 0x6000BA3, 0x6000BA9, 0x6000BAF, 0x6000BB5, 0x4000BBB, 0x4000BBF, 0x6000BC3, 0x6000BC9, 0x6000BCF, 0x6000BD5, 0x6000BDB, 0x6000BE1,\n\t0x4000BE7, 0x4000357, 0x4000BEB, 0x400035B, 0x4000BEF, 0x400035F, 0x4000BF3, 0x4000363, 0x4000BF7, 0x400036D, 0x4000BFB, 0x4000371, 0x4000BFF, 0x4000375, 0x0, 0x0,\n\t0x6000C03, 0x6000C09, 0x8000C0F, 0x8000C17, 0x8000C1F, 0x8000C27, 0x8000C2F, 0x8000C37, 0x6000C3F, 0x6000C45, 0x8000C4B, 0x8000C53, 0x8000C5B, 0x8000C63, 0x8000C6B, 0x8000C73,\n\t0x6000C7B, 0x6000C81, 0x8000C87, 0x8000C8F, 0x8000C97, 0x8000C9F, 0x8000CA7, 0x8000CAF, 0x6000CB7, 0x6000CBD, 0x8000CC3, 0x8000CCB, 0x8000CD3, 0x8000CDB, 0x8000CE3, 0x8000CEB,\n\t0x6000CF3, 0x6000CF9, 0x8000CFF, 0x8000D07, 0x8000D0F, 0x8000D17, 0x8000D1F, 0x8000D27, 0x6000D2F, 0x6000D35, 0x8000D3B, 0x8000D43, 0x8000D4B, 0x8000D53, 0x8000D5B, 0x8000D63,\n\t0x4000D6B, 0x4000D6F, 0x6000D73, 0x4000D79, 0x6000D7D, 0x0, 0x4000D83, 0x6000D87, 0x4000D8D, 0x4000D91, 0x4000D95, 0x400032B, 0x4000D99, 0x0, 0x2000349, 0x0,\n\t0x0, 0x4000D9D, 0x6000DA1, 0x4000DA7, 0x6000DAB, 0x0, 0x4000DB1, 0x6000DB5, 0x4000DBB, 0x4000331, 0x4000DBF, 0x4000335, 0x4000DC3, 0x5000DC7, 0x5000DCC, 0x5000DD1,\n\t0x4000DD6, 0x4000DDA, 0x6000DDE, 0x6000349, 0x0, 0x0, 0x4000DE4, 0x6000DE8, 0x4000DEE, 0x4000DF2, 0x4000DF6, 0x4000339, 0x0, 0x5000DFA, 0x5000DFF, 0x5000E04,\n\t0x4000E09, 0x4000E0D, 0x6000E11, 0x6000367, 0x4000E17, 0x4000E1B, 0x4000E1F, 0x6000E23, 0x4000E29, 0x4000E2D, 0x4000E31, 0x4000341, 0x4000E35, 0x4000E39, 0x4000327, 0x1000E3D,\n\t0x0, 0x0, 0x6000E3E, 0x4000E44, 0x6000E48, 0x0, 0x4000E4E, 0x6000E52, 0x4000E58, 0x400033D, 0x4000E5C, 0x4000345, 0x4000E60, 0x2000E64, 0x0, 0x0,\n\t0x3000E66, 0x3000E69, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2000345, 0x0, 0x0, 0x0, 0x100012C, 0x300000F, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000E6C, 0x5000E71, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000E76, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000E7B, 0x5000E80, 0x5000E85,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x5000E8A, 0x0, 0x0, 0x0, 0x0, 0x5000E8F, 0x0, 0x0, 0x5000E94, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x5000E99, 0x0, 0x5000E9E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x5000EA3, 0x0, 0x0, 0x5000EA8, 0x0, 0x0, 0x5000EAD, 0x0, 0x5000EB2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3000EB7, 0x0, 0x5000EBA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000EBF, 0x3000EC4, 0x3000EC7,\n\t0x5000ECA, 0x5000ECF, 0x0, 0x0, 0x5000ED4, 0x5000ED9, 0x0, 0x0, 0x5000EDE, 0x5000EE3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x5000EE8, 0x5000EED, 0x0, 0x0, 0x5000EF2, 0x5000EF7, 0x0, 0x0, 0x5000EFC, 0x5000F01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000F06, 0x5000F0B, 0x5000F10, 0x5000F15,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x5000F1A, 0x5000F1F, 0x5000F24, 0x5000F29, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000F2E, 0x5000F33, 0x5000F38, 0x5000F3D, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3000F42, 0x3000F45, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000F48, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000F4D, 0x0, 0x6000F53, 0x0,\n\t0x6000F59, 0x0, 0x6000F5F, 0x0, 0x6000F65, 0x0, 0x6000F6B, 0x0, 0x6000F71, 0x0, 0x6000F77, 0x0, 0x6000F7D, 0x0, 0x6000F83, 0x0,\n\t0x6000F89, 0x0, 0x6000F8F, 0x0, 0x0, 0x6000F95, 0x0, 0x6000F9B, 0x0, 0x6000FA1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x6000FA7, 0x6000FAD, 0x0, 0x6000FB3, 0x6000FB9, 0x0, 0x6000FBF, 0x6000FC5, 0x0, 0x6000FCB, 0x6000FD1, 0x0, 0x6000FD7, 0x6000FDD, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x6000FE3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000FE9, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000FEF, 0x0, 0x6000FF5, 0x0,\n\t0x6000FFB, 0x0, 0x6001001, 0x0, 0x6001007, 0x0, 0x600100D, 0x0, 0x6001013, 0x0, 0x6001019, 0x0, 0x600101F, 0x0, 0x6001025, 0x0,\n\t0x600102B, 0x0, 0x6001031, 0x0, 0x0, 0x6001037, 0x0, 0x600103D, 0x0, 0x6001043, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x6001049, 0x600104F, 0x0, 0x6001055, 0x600105B, 0x0, 0x6001061, 0x6001067, 0x0, 0x600106D, 0x6001073, 0x0, 0x6001079, 0x600107F, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x6001085, 0x0, 0x0, 0x600108B, 0x6001091, 0x6001097, 0x600109D, 0x0, 0x0, 0x0, 0x60010A3, 0x0,\n\t0x30010A9, 0x30010AC, 0x30010AF, 0x30010B2, 0x30010B5, 0x30010B8, 0x30010BB, 0x30010BE, 0x30010BE, 0x30010C1, 0x30010C4, 0x30010C7, 0x30010CA, 0x30010CD, 0x30010D0, 0x30010D3,\n\t0x30010D6, 0x30010D9, 0x30010DC, 0x30010DF, 0x30010E2, 0x30010E5, 0x30010E8, 0x30010EB, 0x30010EE, 0x30010F1, 0x30010F4, 0x30010F7, 0x30010FA, 0x30010FD, 0x3001100, 0x3001103,\n\t0x3001106, 0x3001109, 0x300110C, 0x300110F, 0x3001112, 0x3001115, 0x3001118, 0x300111B, 0x300111E, 0x3001121, 0x3001124, 0x3001127, 0x300112A, 0x300112D, 0x3001130, 0x3001133,\n\t0x3001136, 0x3001139, 0x300113C, 0x300113F, 0x3001142, 0x3001145, 0x3001148, 0x300114B, 0x300114E, 0x3001151, 0x3001154, 0x3001157, 0x300115A, 0x300115D, 0x3001160, 0x3001163,\n\t0x3001166, 0x3001169, 0x300116C, 0x300116F, 0x3001172, 0x3001175, 0x3001178, 0x300117B, 0x300117E, 0x3001181, 0x3001184, 0x3001187, 0x300118A, 0x300118D, 0x3001190, 0x3001193,\n\t0x3001196, 0x3001199, 0x300119C, 0x300119F, 0x30011A2, 0x30011A5, 0x30011A8, 0x30011AB, 0x30011AE, 0x30011B1, 0x30011B4, 0x30011B7, 0x30010E2, 0x30011BA, 0x30011BD, 0x30011C0,\n\t0x30011C3, 0x30011C6, 0x30011C9, 0x30011CC, 0x30011CF, 0x30011D2, 0x30011D5, 0x30011D8, 0x30011DB, 0x30011DE, 0x30011E1, 0x30011E4, 0x30011E7, 0x30011EA, 0x30011ED, 0x30011F0,\n\t0x30011F3, 0x30011F6, 0x30011F9, 0x30011FC, 0x30011FF, 0x3001202, 0x3001205, 0x3001208, 0x300120B, 0x300120E, 0x3001211, 0x3001214, 0x3001217, 0x300121A, 0x300121D, 0x3001220,\n\t0x3001223, 0x3001226, 0x3001229, 0x300122C, 0x300122F, 0x3001232, 0x3001235, 0x3001238, 0x300123B, 0x300123E, 0x3001241, 0x3001244, 0x3001247, 0x300124A, 0x300124D, 0x3001250,\n\t0x3001253, 0x3001256, 0x3001259, 0x300125C, 0x300125F, 0x3001262, 0x3001265, 0x3001268, 0x300126B, 0x300126E, 0x3001271, 0x3001274, 0x3001277, 0x300127A, 0x300127D, 0x3001280,\n\t0x3001283, 0x30011F0, 0x3001286, 0x3001289, 0x300128C, 0x300128F, 0x3001292, 0x3001295, 0x3001298, 0x300129B, 0x30011C0, 0x300129E, 0x30012A1, 0x30012A4, 0x30012A7, 0x30012AA,\n\t0x30012AD, 0x30012B0, 0x30012B3, 0x30012B6, 0x30012B9, 0x30012BC, 0x30012BF, 0x30012C2, 0x30012C5, 0x30012C8, 0x30012CB, 0x30012CE, 0x30012D1, 0x30012D4, 0x30012D7, 0x30010E2,\n\t0x30012DA, 0x30012DD, 0x30012E0, 0x30012E3, 0x30012E6, 0x30012E9, 0x30012EC, 0x30012EF, 0x30012F2, 0x30012F5, 0x30012F8, 0x30012FB, 0x30012FE, 0x3001301, 0x3001304, 0x3001307,\n\t0x300130A, 0x300130D, 0x3001310, 0x3001313, 0x3001316, 0x3001319, 0x300131C, 0x300131F, 0x3001322, 0x3001325, 0x3001328, 0x30011C6, 0x300132B, 0x300132E, 0x3001331, 0x3001334,\n\t0x3001337, 0x300133A, 0x300133D, 0x3001340, 0x3001343, 0x3001346, 0x3001349, 0x300134C, 0x300134F, 0x3001352, 0x3001355, 0x3001358, 0x300135B, 0x300135E, 0x3001361, 0x3001364,\n\t0x3001367, 0x300136A, 0x300136D, 0x3001370, 0x3001373, 0x3001376, 0x3001379, 0x300137C, 0x300137F, 0x3001382, 0x3001385, 0x3001388, 0x300138B, 0x300138E, 0x3001391, 0x3001394,\n\t0x3001397, 0x300139A, 0x300139D, 0x30013A0, 0x30013A3, 0x30013A6, 0x30013A9, 0x30013AC, 0x30013AF, 0x30013B2, 0x30013B5, 0x30013B8, 0x30013BB, 0x30013BE, 0x0, 0x0,\n\t0x30013C1, 0x0, 0x30013C4, 0x0, 0x0, 0x30013C7, 0x30013CA, 0x30013CD, 0x30013D0, 0x30013D3, 0x30013D6, 0x30013D9, 0x30013DC, 0x30013DF, 0x30013E2, 0x0,\n\t0x30013E5, 0x0, 0x30013E8, 0x0, 0x0, 0x30013EB, 0x30013EE, 0x0, 0x0, 0x0, 0x30013F1, 0x30013F4, 0x30013F7, 0x30013FA, 0x30013FD, 0x3001400,\n\t0x3001403, 0x3001406, 0x3001409, 0x300140C, 0x300140F, 0x3001412, 0x3001415, 0x3001418, 0x300141B, 0x300141E, 0x3001421, 0x3001424, 0x3001427, 0x300142A, 0x300142D, 0x3001430,\n\t0x3001433, 0x3001436, 0x3001439, 0x300143C, 0x300143F, 0x3001442, 0x3001445, 0x3001448, 0x300144B, 0x300144E, 0x3001451, 0x3001454, 0x3001457, 0x300145A, 0x300145D, 0x3001460,\n\t0x3001463, 0x3001466, 0x3001469, 0x300146C, 0x300146F, 0x3001472, 0x3001475, 0x3001265, 0x3001478, 0x300147B, 0x300147E, 0x3001481, 0x3001484, 0x3001487, 0x3001487, 0x300148A,\n\t0x300148D, 0x3001490, 0x3001493, 0x3001496, 0x3001499, 0x300149C, 0x300149F, 0x30013EB, 0x30014A2, 0x30014A5, 0x30014A8, 0x30014AB, 0x40014AE, 0x30014B2, 0x0, 0x0,\n\t0x30014B5, 0x30014B8, 0x30014BB, 0x30014BE, 0x30014C1, 0x30014C4, 0x30014C7, 0x30014CA, 0x3001415, 0x30014CD, 0x30014D0, 0x30014D3, 0x30013C1, 0x30014D6, 0x30014D9, 0x30014DC,\n\t0x30014DF, 0x30014E2, 0x30014E5, 0x30014E8, 0x30014EB, 0x30014EE, 0x30014F1, 0x30014F4, 0x30014F7, 0x3001430, 0x30014FA, 0x3001433, 0x30014FD, 0x3001500, 0x3001503, 0x3001506,\n\t0x3001509, 0x30013C4, 0x3001121, 0x300150C, 0x300150F, 0x3001512, 0x30011F3, 0x30012F8, 0x3001515, 0x3001518, 0x3001448, 0x300151B, 0x300144B, 0x300151E, 0x3001521, 0x3001524,\n\t0x30013CA, 0x3001527, 0x300152A, 0x300152D, 0x3001530, 0x3001533, 0x30013CD, 0x3001536, 0x3001539, 0x300153C, 0x300153F, 0x3001542, 0x3001545, 0x3001475, 0x3001548, 0x300154B,\n\t0x3001265, 0x300154E, 0x3001481, 0x3001551, 0x3001554, 0x3001557, 0x300155A, 0x300155D, 0x3001490, 0x3001560, 0x30013E8, 0x3001563, 0x3001493, 0x30011BA, 0x3001566, 0x3001496,\n\t0x3001569, 0x300149C, 0x300156C, 0x300156F, 0x3001572, 0x3001575, 0x3001578, 0x30014A2, 0x30013DC, 0x300157B, 0x30014A5, 0x300157E, 0x30014A8, 0x3001581, 0x30010BE, 0x4001584,\n\t0x4001588, 0x400158C, 0x3001590, 0x3001593, 0x3001596, 0x4001599, 0x400159D, 0x40015A1, 0x30015A5, 0x30015A8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40015AB, 0x0, 0x40015AF,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40015B3, 0x40015B7, 0x60015BB, 0x60015C1, 0x40015C7, 0x40015CB,\n\t0x40015CF, 0x40015D3, 0x40015D7, 0x40015DB, 0x40015DF, 0x40015E3, 0x40015E7, 0x0, 0x40015EB, 0x40015EF, 0x40015F3, 0x40015F7, 0x40015FB, 0x0, 0x40015FF, 0x0,\n\t0x4001603, 0x4001607, 0x0, 0x400160B, 0x400160F, 0x0, 0x4001613, 0x4001617, 0x400161B, 0x40015BB, 0x400161F, 0x4001623, 0x4001627, 0x400162B, 0x400162F, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8001633, 0x0, 0x800163B, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8001643, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800164B, 0x8001653,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800165B, 0x8001663, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800166B, 0x8001673, 0x0, 0x800167B, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8001683, 0x800168B, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8001693, 0x800169B,\n\t0xC0016A3, 0xC0016AF, 0xC0016BB, 0xC0016C7, 0xC0016D3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80016DF, 0x80016E7, 0xC0016EF, 0xC0016FB, 0xC001707,\n\t0xC001713, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x300171F, 0x3001722, 0x3001725, 0x4001728, 0x300172C, 0x3001403, 0x300172F, 0x3001732, 0x3001735, 0x3001738, 0x3001406, 0x300173B, 0x300173E, 0x4001741, 0x3001409, 0x3001745,\n\t0x3001748, 0x300174B, 0x400174E, 0x3001752, 0x3001755, 0x3001758, 0x400175B, 0x300175F, 0x3001762, 0x3001765, 0x3001768, 0x30014B8, 0x400176B, 0x300176F, 0x3001772, 0x3001775,\n\t0x3001778, 0x300177B, 0x300177E, 0x3001781, 0x3001784, 0x30014C7, 0x300140C, 0x300140F, 0x30014CA, 0x3001787, 0x300178A, 0x30011CC, 0x300178D, 0x3001412, 0x3001790, 0x3001793,\n\t0x3001796, 0x3001799, 0x3001799, 0x3001799, 0x400179C, 0x30017A0, 0x30017A3, 0x30017A6, 0x40017A9, 0x30017AD, 0x30017B0, 0x30017B3, 0x30017B6, 0x30017B9, 0x30017BC, 0x30017BF,\n\t0x30017C2, 0x30017C5, 0x30017C8, 0x30017CB, 0x30017CE, 0x30017D1, 0x30017D1, 0x30014D0, 0x30017D4, 0x30017D7, 0x30017DA, 0x30017DD, 0x3001418, 0x30017E0, 0x30017E3, 0x30017E6,\n\t0x3001397, 0x30017E9, 0x30017EC, 0x30017EF, 0x30017F2, 0x30017F5, 0x30017F8, 0x30017FB, 0x30017FE, 0x4001801, 0x3001805, 0x3001808, 0x300180B, 0x300180E, 0x3001811, 0x3001814,\n\t0x4001817, 0x400181B, 0x300181F, 0x3001822, 0x3001825, 0x3001828, 0x300182B, 0x300182E, 0x3001831, 0x3001834, 0x3001837, 0x3001837, 0x400183A, 0x300183E, 0x3001841, 0x30011C0,\n\t0x3001844, 0x4001847, 0x300184B, 0x300184E, 0x3001851, 0x3001854, 0x3001857, 0x300185A, 0x3001427, 0x300185D, 0x3001860, 0x4001863, 0x3001867, 0x400186A, 0x300186E, 0x3001871,\n\t0x3001874, 0x3001877, 0x300187A, 0x300187D, 0x3001880, 0x3001883, 0x3001886, 0x3001889, 0x300188C, 0x400188F, 0x3001893, 0x3001896, 0x3001899, 0x300189C, 0x300111E, 0x400189F,\n\t0x30018A3, 0x40018A6, 0x40018A6, 0x30018AA, 0x30018AD, 0x30018AD, 0x30018B0, 0x40018B3, 0x40018B7, 0x30018BB, 0x30018BE, 0x30018C1, 0x30018C4, 0x30018C7, 0x30018CA, 0x30018CD,\n\t0x30018D0, 0x30018D3, 0x30018D6, 0x300142A, 0x40018D9, 0x30018DD, 0x30018E0, 0x30018E3, 0x30014F4, 0x30018E3, 0x30018E6, 0x3001430, 0x30018E9, 0x30018EC, 0x30018EF, 0x30018F2,\n\t0x3001433, 0x30010CD, 0x30018F5, 0x30018F8, 0x30018FB, 0x30018FE, 0x3001901, 0x3001904, 0x4001907, 0x300190B, 0x300190E, 0x3001911, 0x3001914, 0x3001917, 0x400191A, 0x300191E,\n\t0x3001921, 0x3001924, 0x3001927, 0x300192A, 0x300192D, 0x3001930, 0x3001933, 0x3001936, 0x3001436, 0x3001939, 0x400193C, 0x3001940, 0x3001943, 0x3001946, 0x3001949, 0x300143C,\n\t0x300194C, 0x300194F, 0x3001952, 0x3001955, 0x3001958, 0x300195B, 0x300195E, 0x3001961, 0x3001121, 0x300150C, 0x3001964, 0x3001967, 0x300196A, 0x400196D, 0x3001971, 0x3001974,\n\t0x3001977, 0x300197A, 0x300143F, 0x400197D, 0x3001981, 0x3001984, 0x3001987, 0x3001590, 0x300198A, 0x300198D, 0x3001990, 0x3001993, 0x4001996, 0x300199A, 0x300199D, 0x30019A0,\n\t0x40019A3, 0x30019A7, 0x30019AA, 0x30019AD, 0x30019B0, 0x30011F3, 0x30019B3, 0x40019B6, 0x40019BA, 0x40019BE, 0x30019C2, 0x40019C5, 0x30019C9, 0x30019CC, 0x30019CF, 0x30019D2,\n\t0x30019D5, 0x3001442, 0x30012F8, 0x30019D8, 0x30019DB, 0x30019DE, 0x40019E1, 0x30019E5, 0x30019E8, 0x30019EB, 0x30019EE, 0x3001518, 0x30019F1, 0x40019F4, 0x30019F8, 0x30019FB,\n\t0x40019FE, 0x4001A02, 0x3001A06, 0x3001A09, 0x300151B, 0x3001A0C, 0x3001A0F, 0x3001A12, 0x3001A15, 0x3001A18, 0x3001A1B, 0x4001A1E, 0x3001A22, 0x4001A25, 0x3001A29, 0x4001A2C,\n\t0x3001A30, 0x3001521, 0x3001A33, 0x4001A36, 0x3001A3A, 0x3001A3D, 0x4001A40, 0x4001A44, 0x3001A48, 0x3001A4B, 0x3001A4E, 0x3001A51, 0x3001A54, 0x3001A54, 0x3001A57, 0x3001A5A,\n\t0x3001527, 0x3001A5D, 0x3001A60, 0x3001A63, 0x3001A66, 0x4001A69, 0x3001A6D, 0x4001A70, 0x30011C9, 0x4001A74, 0x3001A78, 0x4001A7B, 0x4001A7F, 0x4001A83, 0x3001A87, 0x3001A8A,\n\t0x3001539, 0x4001A8D, 0x4001A91, 0x4001A95, 0x4001A99, 0x3001A9D, 0x3001AA0, 0x3001AA0, 0x300153C, 0x3001596, 0x3001AA3, 0x3001AA6, 0x3001AA9, 0x4001AAC, 0x3001AB0, 0x3001157,\n\t0x3001542, 0x3001AB3, 0x4001AB6, 0x3001463, 0x4001ABA, 0x4001ABE, 0x30013D9, 0x3001AC2, 0x3001AC5, 0x300146F, 0x3001AC8, 0x3001ACB, 0x4001ACE, 0x4001AD2, 0x4001AD2, 0x3001AD6,\n\t0x3001AD9, 0x4001ADC, 0x3001AE0, 0x3001AE3, 0x3001AE6, 0x4001AE9, 0x3001AED, 0x3001AF0, 0x3001AF3, 0x3001AF6, 0x3001AF9, 0x4001AFC, 0x3001B00, 0x3001B03, 0x3001B06, 0x3001B09,\n\t0x3001B0C, 0x3001B0F, 0x4001B12, 0x4001B16, 0x3001B1A, 0x4001B1D, 0x3001B21, 0x4001B24, 0x3001B28, 0x3001B2B, 0x3001481, 0x4001B2E, 0x4001B32, 0x3001B36, 0x4001B39, 0x3001B3D,\n\t0x4001B40, 0x3001B44, 0x3001B47, 0x3001B4A, 0x3001B4D, 0x3001B50, 0x3001B53, 0x4001B56, 0x4001B5A, 0x4001B5E, 0x4001B62, 0x30018AA, 0x3001B66, 0x3001B69, 0x3001B6C, 0x3001B6F,\n\t0x3001B72, 0x3001B75, 0x3001B78, 0x3001B7B, 0x3001B7E, 0x3001B81, 0x3001B84, 0x4001B87, 0x30011FF, 0x3001B8B, 0x3001B8E, 0x3001B91, 0x3001B94, 0x3001B97, 0x3001B9A, 0x300148A,\n\t0x3001B9D, 0x3001BA0, 0x3001BA3, 0x3001BA6, 0x4001BA9, 0x4001BAD, 0x4001BB1, 0x3001BB5, 0x3001BB8, 0x3001BBB, 0x3001BBE, 0x4001BC1, 0x3001BC5, 0x4001BC8, 0x3001BCC, 0x3001BCF,\n\t0x4001BD2, 0x4001BD6, 0x3001BDA, 0x3001BDD, 0x3001148, 0x3001BE0, 0x3001BE3, 0x3001BE6, 0x3001BE9, 0x3001BEC, 0x3001BEF, 0x3001557, 0x3001BF2, 0x3001BF5, 0x3001BF8, 0x3001BFB,\n\t0x3001BFE, 0x3001C01, 0x3001C04, 0x3001C07, 0x3001C0A, 0x4001C0D, 0x3001C11, 0x3001C14, 0x3001C17, 0x3001C1A, 0x3001C1D, 0x4001C20, 0x4001C24, 0x3001C28, 0x3001C2B, 0x3001C2E,\n\t0x3001566, 0x3001569, 0x3001C31, 0x4001C34, 0x3001C38, 0x3001C3B, 0x3001C3E, 0x3001C41, 0x4001C44, 0x4001C48, 0x3001C4C, 0x3001C4F, 0x3001C52, 0x4001C55, 0x3001C59, 0x300156C,\n\t0x4001C5C, 0x4001C60, 0x3001C64, 0x3001C67, 0x3001C6A, 0x4001C6D, 0x3001C71, 0x3001C74, 0x3001C77, 0x3001C7A, 0x3001C7D, 0x3001C80, 0x3001C83, 0x4001C86, 0x3001C8A, 0x3001C8D,\n\t0x3001C90, 0x4001C93, 0x3001C97, 0x3001C9A, 0x3001C9D, 0x3001CA0, 0x4001CA3, 0x4001CA7, 0x3001CAB, 0x3001CAE, 0x3001CB1, 0x4001CB4, 0x3001CB8, 0x4001CBB, 0x300157E, 0x300157E,\n\t0x3001CBF, 0x4001CC2, 0x3001CC6, 0x3001CC9, 0x3001CCC, 0x3001CCF, 0x3001CD2, 0x3001CD5, 0x3001CD8, 0x4001CDB, 0x3001581, 0x3001CDF, 0x3001CE2, 0x3001CE5, 0x3001CE8, 0x3001CEB,\n\t0x4001CEE, 0x3001CF2, 0x4001CF5, 0x4001CF9, 0x4001CFD, 0x3001D01, 0x3001D04, 0x3001D07, 0x3001D0A, 0x3001D0D, 0x3001D10, 0x3001D13, 0x3001D16, 0x4001D19, 0x0, 0x0,\n};\nconst uint32_t* NFDDataPtr = NFDData;\n\nconst uint32_t NFKDIndex1[272] = {\n\t0, 128, 256, 384, 512, 416, 416, 416, 416, 416, 640, 416, 416, 416, 416, 768,\n\t416, 896, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 1024, 1152, 1280,\n\t416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 1408,\n\t416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,\n\t416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,\n\t416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,\n\t416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,\n\t416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,\n\t416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,\n\t416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,\n\t416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,\n\t416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,\n\t416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,\n\t416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,\n\t416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,\n\t416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,\n\t416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,\n};\nconst uint32_t* NFKDIndex1Ptr = NFKDIndex1;\n\nconst uint32_t NFKDIndex2[1536] = {\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0, 0x0, 0x100, 0x120, 0x140,\n\t0x160, 0x180, 0x0, 0x0, 0x0, 0x1A0, 0x1C0, 0x1E0, 0x0, 0x0, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0,\n\t0x2C0, 0x2E0, 0x300, 0x320, 0x0, 0x0, 0x340, 0x360, 0x0, 0x0, 0x0, 0x0, 0x380, 0x0, 0x0, 0x0,\n\t0x0, 0x3A0, 0x0, 0x3C0, 0x0, 0x0, 0x3E0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x400, 0x420, 0x0, 0x0, 0x0, 0x440, 0x0,\n\t0x0, 0x460, 0x480, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4A0, 0x0, 0x4C0, 0x0, 0x4E0, 0x0,\n\t0x0, 0x0, 0x500, 0x0, 0x0, 0x0, 0x520, 0x0, 0x0, 0x0, 0x540, 0x0, 0x0, 0x0, 0x560, 0x0,\n\t0x0, 0x580, 0x0, 0x0, 0x0, 0x5A0, 0x5C0, 0x0, 0x5E0, 0x0, 0x600, 0x620, 0x640, 0x660, 0x0, 0x0,\n\t0x0, 0x680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6A0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6C0, 0x6E0, 0x700, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x720, 0x740, 0x760, 0x780, 0x7A0, 0x0, 0x0,\n\t0x7C0, 0x7E0, 0x800, 0x820, 0x840, 0x860, 0x880, 0x8A0, 0x8C0, 0x8E0, 0x900, 0x920, 0x940, 0x960, 0x980, 0x9A0,\n\t0x9C0, 0x9E0, 0xA00, 0xA20, 0xA40, 0xA60, 0x0, 0x0, 0xA80, 0xAA0, 0xAC0, 0xAE0, 0xB00, 0xB20, 0xB40, 0x0,\n\t0xB60, 0xB80, 0xBA0, 0xBC0, 0xBE0, 0xC00, 0x0, 0xC20, 0x0, 0xC40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0xC60, 0xC80, 0xCA0, 0xCC0, 0xCE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0xD00, 0x0, 0x0, 0xD20, 0x0, 0x0, 0xD40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0xD60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xD80, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0xDA0, 0x0, 0x0, 0xDC0, 0xDE0, 0xE00, 0xE20, 0xE40, 0xE60, 0xE80, 0xEA0, 0x0,\n\t0xEC0, 0xEE0, 0xF00, 0xF20, 0xF40, 0xF60, 0xF80, 0xFA0, 0x0, 0xFC0, 0xFE0, 0x1000, 0x1020, 0x0, 0x0, 0x0,\n\t0x1040, 0x1060, 0x1080, 0x10A0, 0x10C0, 0x10E0, 0x1100, 0x1120, 0x1140, 0x1160, 0x1180, 0x11A0, 0x11C0, 0x11E0, 0x1200, 0x1220,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x1240, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1260, 0x0, 0x0, 0x0, 0x1280,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12A0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12C0, 0x12E0, 0x1300, 0x1320, 0x1340, 0x1360, 0x1380, 0x13A0,\n\t0x13C0, 0x13E0, 0x1400, 0x1420, 0x1440, 0x1460, 0x1480, 0x0, 0x14A0, 0x14C0, 0x14E0, 0x1500, 0x1520, 0x1540, 0x1560, 0x1580,\n\t0x15A0, 0x15C0, 0x15E0, 0x1600, 0x1620, 0x1640, 0x1660, 0x1680, 0x16A0, 0x16C0, 0x16E0, 0x1700, 0x1720, 0x1740, 0x1760, 0x1780,\n\t0x17A0, 0x17C0, 0x17E0, 0x1800, 0x1820, 0x1840, 0x1860, 0x1880, 0x18A0, 0x18C0, 0x18E0, 0x1900, 0x1920, 0x1940, 0x1960, 0x1980,\n\t0x0, 0x0, 0x0, 0x0, 0x19A0, 0x19C0, 0x0, 0x0, 0x0, 0x19E0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1A00, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x1A20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1A40, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1A60, 0x1A80, 0x0, 0x1AA0, 0x1AC0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0xCB6, 0x1AE0, 0x1B00, 0x1AEC, 0x1B20, 0x1B40, 0x1B60, 0xCC6, 0x1B80, 0x1BA0, 0x1BC0, 0x1AE8, 0xCCA, 0xCB6, 0x1AE0, 0xCC2,\n\t0x1AEC, 0x1BE0, 0xCBA, 0x1AE4, 0xCC6, 0x1C00, 0x1C20, 0x1C40, 0x1C26, 0x1C0C, 0x1C2C, 0x1C12, 0x1C32, 0x1C18, 0x1C60, 0x1C80,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x1CA0, 0x1CC0, 0x1CE0, 0x1D00, 0x1D20, 0x1D40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1D60, 0x1D80, 0x1DA0, 0x1DC0, 0x1DE0, 0x0, 0x0, 0x0,\n\t0x1E00, 0x1E20, 0x1E40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x1E60, 0x1E80, 0x1EA0, 0x1EC0, 0x1EE0, 0x1F00, 0x1F20, 0x1F40, 0x1F60, 0x1F80, 0x1FA0, 0x1FC0, 0x1FE0, 0x2000, 0x2020, 0x2040,\n\t0x2060, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n};\nconst uint32_t* NFKDIndex2Ptr = NFKDIndex2;\n\nconst uint32_t NFKDData[8320] = {\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x1001D1D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3001D1E, 0x0, 0x100004E, 0x0, 0x0, 0x0, 0x0, 0x3001D21,\n\t0x0, 0x0, 0x1001D24, 0x1001D25, 0x3001D26, 0x2001D29, 0x0, 0x0, 0x3001D2B, 0x1001D2E, 0x100007E, 0x0, 0x5001D2F, 0x5001D34, 0x5001D39, 0x0,\n\t0x3000000, 0x3000003, 0x3000006, 0x3000009, 0x300000C, 0x300000F, 0x0, 0x3000012, 0x3000015, 0x3000018, 0x300001B, 0x300001E, 0x3000021, 0x3000024, 0x3000027, 0x300002A,\n\t0x0, 0x300002D, 0x3000030, 0x3000033, 0x3000036, 0x3000039, 0x300003C, 0x0, 0x0, 0x300003F, 0x3000042, 0x3000045, 0x3000048, 0x300004B, 0x0, 0x0,\n\t0x300004E, 0x3000051, 0x3000054, 0x3000057, 0x300005A, 0x300005D, 0x0, 0x3000060, 0x3000063, 0x3000066, 0x3000069, 0x300006C, 0x300006F, 0x3000072, 0x3000075, 0x3000078,\n\t0x0, 0x300007B, 0x300007E, 0x3000081, 0x3000084, 0x3000087, 0x300008A, 0x0, 0x0, 0x300008D, 0x3000090, 0x3000093, 0x3000096, 0x3000099, 0x0, 0x300009C,\n\t0x300009F, 0x30000A2, 0x30000A5, 0x30000A8, 0x30000AB, 0x30000AE, 0x30000B1, 0x30000B4, 0x30000B7, 0x30000BA, 0x30000BD, 0x30000C0, 0x30000C3, 0x30000C6, 0x30000C9, 0x30000CC,\n\t0x0, 0x0, 0x30000CF, 0x30000D2, 0x30000D5, 0x30000D8, 0x30000DB, 0x30000DE, 0x30000E1, 0x30000E4, 0x30000E7, 0x30000EA, 0x30000ED, 0x30000F0, 0x30000F3, 0x30000F6,\n\t0x30000F9, 0x30000FC, 0x30000FF, 0x3000102, 0x3000105, 0x3000108, 0x0, 0x0, 0x300010B, 0x300010E, 0x3000111, 0x3000114, 0x3000117, 0x300011A, 0x300011D, 0x3000120,\n\t0x3000123, 0x0, 0x2001D3E, 0x2001D40, 0x3000126, 0x3000129, 0x300012C, 0x300012F, 0x0, 0x3000132, 0x3000135, 0x3000138, 0x300013B, 0x300013E, 0x3000141, 0x3001D42,\n\t0x3001D45, 0x0, 0x0, 0x3000144, 0x3000147, 0x300014A, 0x300014D, 0x3000150, 0x3000153, 0x3001D48, 0x0, 0x0, 0x3000156, 0x3000159, 0x300015C, 0x300015F,\n\t0x3000162, 0x3000165, 0x0, 0x0, 0x3000168, 0x300016B, 0x300016E, 0x3000171, 0x3000174, 0x3000177, 0x300017A, 0x300017D, 0x3000180, 0x3000183, 0x3000186, 0x3000189,\n\t0x300018C, 0x300018F, 0x3000192, 0x3000195, 0x3000198, 0x300019B, 0x0, 0x0, 0x300019E, 0x30001A1, 0x30001A4, 0x30001A7, 0x30001AA, 0x30001AD, 0x30001B0, 0x30001B3,\n\t0x30001B6, 0x30001B9, 0x30001BC, 0x30001BF, 0x30001C2, 0x30001C5, 0x30001C8, 0x30001CB, 0x30001CE, 0x30001D1, 0x30001D4, 0x30001D7, 0x30001DA, 0x30001DD, 0x30001E0, 0x100017D,\n\t0x30001E3, 0x30001E6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30001E9,\n\t0x30001EC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x4001D4B, 0x4001D4F, 0x4001D53, 0x2001D57, 0x2001D59, 0x2001D5B, 0x2001D5D, 0x2001D5F, 0x2001D61, 0x30001EF, 0x30001F2, 0x30001F5,\n\t0x30001F8, 0x30001FB, 0x30001FE, 0x3000201, 0x3000204, 0x5000207, 0x500020C, 0x5000211, 0x5000216, 0x500021B, 0x5000220, 0x5000225, 0x500022A, 0x0, 0x500022F, 0x5000234,\n\t0x5000239, 0x500023E, 0x4000243, 0x4000247, 0x0, 0x0, 0x300024B, 0x300024E, 0x3000251, 0x3000254, 0x3000257, 0x300025A, 0x500025D, 0x5000262, 0x4000267, 0x400026B,\n\t0x300026F, 0x2001D4B, 0x2001D4F, 0x2001D53, 0x3000272, 0x3000275, 0x0, 0x0, 0x3000278, 0x300027B, 0x500027E, 0x5000283, 0x4000288, 0x400028C, 0x4000290, 0x4000294,\n\t0x3000298, 0x300029B, 0x300029E, 0x30002A1, 0x30002A4, 0x30002A7, 0x30002AA, 0x30002AD, 0x30002B0, 0x30002B3, 0x30002B6, 0x30002B9, 0x30002BC, 0x30002BF, 0x30002C2, 0x30002C5,\n\t0x30002C8, 0x30002CB, 0x30002CE, 0x30002D1, 0x30002D4, 0x30002D7, 0x30002DA, 0x30002DD, 0x30002E0, 0x30002E3, 0x30002E6, 0x30002E9, 0x0, 0x0, 0x30002EC, 0x30002EF,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3000239, 0x300023E, 0x30002F2, 0x30002F5, 0x50002F8, 0x50002FD, 0x5000302, 0x5000307, 0x300030C, 0x300030F,\n\t0x5000312, 0x5000317, 0x300031C, 0x300031F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x1000108, 0x2001D63, 0x1000129, 0x100016B, 0x2001D65, 0x2001D67, 0x2001D69, 0x10001C5, 0x1000099, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3001D6B, 0x3001D6E, 0x3001D71, 0x3001D74, 0x3001D77, 0x3001D7A, 0x0, 0x0,\n\t0x2001D7D, 0x1000135, 0x100017D, 0x100080E, 0x2001D7F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x2000001, 0x2000004, 0x0, 0x2000322, 0x4000212, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x2000324, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3001D81, 0x0, 0x0, 0x0, 0x1000326, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x3001D26, 0x5001D84, 0x400032B, 0x200032F, 0x4000331, 0x4000335, 0x4000339, 0x0, 0x400033D, 0x0, 0x4000341, 0x4000345,\n\t0x6000349, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x400034F, 0x4000353, 0x4000357, 0x400035B, 0x400035F, 0x4000363,\n\t0x6000367, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000349, 0x4000367, 0x400036D, 0x4000371, 0x4000375, 0x0,\n\t0x2001D89, 0x2001D8B, 0x2000341, 0x4000341, 0x4000353, 0x2001D8D, 0x2001D8F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x2001D91, 0x2000E17, 0x2001D93, 0x0, 0x2001D95, 0x200035B, 0x0, 0x0, 0x0, 0x2001D97, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x4000381, 0x4000385, 0x0, 0x4000389, 0x0, 0x0, 0x0, 0x400038D, 0x0, 0x0, 0x0, 0x0, 0x4000391, 0x4000395, 0x4000399, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x400039D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40003A1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x40003A5, 0x40003A9, 0x0, 0x40003AD, 0x0, 0x0, 0x0, 0x40003B1, 0x0, 0x0, 0x0, 0x0, 0x40003B5, 0x40003B9, 0x40003BD, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40003C1, 0x40003C5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x40003C9, 0x40003CD, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x40003D1, 0x40003D5, 0x40003D9, 0x40003DD, 0x0, 0x0, 0x40003E1, 0x40003E5, 0x0, 0x0, 0x40003E9, 0x40003ED, 0x40003F1, 0x40003F5, 0x40003F9, 0x40003FD,\n\t0x0, 0x0, 0x4000401, 0x4000405, 0x4000409, 0x400040D, 0x4000411, 0x4000415, 0x0, 0x0, 0x4000419, 0x400041D, 0x4000421, 0x4000425, 0x4000429, 0x400042D,\n\t0x4000431, 0x4000435, 0x4000439, 0x400043D, 0x4000441, 0x4000445, 0x0, 0x0, 0x4000449, 0x400044D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4001D99, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x4000451, 0x4000455, 0x4000459, 0x400045D, 0x4000461, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x4001D9D, 0x4001DA1, 0x4001DA5, 0x4001DA9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x4000465, 0x0, 0x4000469, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x400046D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000471, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x6000477, 0x0, 0x0, 0x600047D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000483, 0x6000489, 0x600048F, 0x6000495, 0x600049B, 0x60004A1, 0x60004A7, 0x60004AD,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60004B3, 0x60004B9, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60004BF, 0x60004C5, 0x0, 0x60004CB,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x60004D1, 0x0, 0x0, 0x60004D7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60004DD, 0x60004E3, 0x60004E9, 0x0, 0x0, 0x60004EF, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60004F5, 0x0, 0x0, 0x60004FB, 0x6000501, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000507, 0x600050D, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x6000513, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000519, 0x600051F, 0x6000525, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x600052B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x6000531, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000537, 0x600053D, 0x0, 0x6000543, 0x9001DAD, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000552, 0x6000558, 0x600055E, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000564, 0x0, 0x600056A, 0x9001DB6, 0x6000579, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x6001DBF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x6001DC5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6001DCB, 0x6001DD1, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3001DD7, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x600057F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000585, 0x0, 0x0,\n\t0x0, 0x0, 0x600058B, 0x0, 0x0, 0x0, 0x0, 0x6000591, 0x0, 0x0, 0x0, 0x0, 0x6000597, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x600059D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x60005A3, 0x0, 0x60005A9, 0x60005AF, 0x9001DDA, 0x60005B5, 0x9001DE3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x60005BB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x60005C1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005C7, 0x0, 0x0,\n\t0x0, 0x0, 0x60005CD, 0x0, 0x0, 0x0, 0x0, 0x60005D3, 0x0, 0x0, 0x0, 0x0, 0x60005D9, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005DF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005E5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3001DEC, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005EB, 0x0, 0x60005F1, 0x0, 0x60005F7, 0x0, 0x60005FD, 0x0, 0x6000603, 0x0,\n\t0x0, 0x0, 0x6000609, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x600060F, 0x0, 0x6000615, 0x0, 0x0,\n\t0x600061B, 0x6000621, 0x0, 0x6000627, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1000000, 0x2000243, 0x1000633, 0x0,\n\t0x10000C9, 0x1000015, 0x2001DEF, 0x10000ED, 0x1000105, 0x1000021, 0x1000126, 0x100012C, 0x1000132, 0x10006FF, 0x100002D, 0x0, 0x1000030, 0x2001DF1, 0x1000751, 0x1000168,\n\t0x1000192, 0x100003F, 0x10001C2, 0x100004E, 0x2001DF3, 0x2001DF5, 0x3001DF7, 0x1000636, 0x10000CC, 0x1000063, 0x2001DFA, 0x2001DFC, 0x2001DFE, 0x10000F0, 0x0, 0x100012F,\n\t0x1000702, 0x2001E00, 0x100007E, 0x2001E02, 0x3001E04, 0x3001E07, 0x1000754, 0x1000195, 0x100008D, 0x3001E0A, 0x2001E0D, 0x10007E4, 0x3001E0F, 0x2001D89, 0x2001E12, 0x2001E14,\n\t0x2001D8D, 0x2001E16, 0x100006F, 0x100016B, 0x100008D, 0x10007E4, 0x2001D89, 0x2001E12, 0x2000E17, 0x2001D8D, 0x2001E16, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2001E18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2001E1A, 0x1000060, 0x2001E1C, 0x2001E1E, 0x2001DFE,\n\t0x100069A, 0x2001E20, 0x2001E22, 0x2001E24, 0x2001E26, 0x2001E28, 0x2001E2A, 0x3001E2C, 0x2001E2F, 0x2001E31, 0x3001E33, 0x2001E36, 0x2001E38, 0x2001E3A, 0x2001E3C, 0x2001E3E,\n\t0x2001E40, 0x2001E42, 0x2001E44, 0x2001E46, 0x2001E48, 0x2001E4A, 0x2001E4C, 0x2001E4E, 0x3001E50, 0x2001E53, 0x2001E55, 0x10001D4, 0x2001E57, 0x2001E59, 0x200026B, 0x2001D8B,\n\t0x300062D, 0x3000630, 0x3000633, 0x3000636, 0x3000639, 0x300063C, 0x300063F, 0x3000642, 0x5000645, 0x500064A, 0x300064F, 0x3000652, 0x3000655, 0x3000658, 0x300065B, 0x300065E,\n\t0x3000661, 0x3000664, 0x3000667, 0x300066A, 0x500066D, 0x5000672, 0x5000677, 0x500067C, 0x3000681, 0x3000684, 0x3000687, 0x300068A, 0x500068D, 0x5000692, 0x3000697, 0x300069A,\n\t0x300069D, 0x30006A0, 0x30006A3, 0x30006A6, 0x30006A9, 0x30006AC, 0x30006AF, 0x30006B2, 0x30006B5, 0x30006B8, 0x30006BB, 0x30006BE, 0x30006C1, 0x30006C4, 0x50006C7, 0x50006CC,\n\t0x30006D1, 0x30006D4, 0x30006D7, 0x30006DA, 0x30006DD, 0x30006E0, 0x30006E3, 0x30006E6, 0x50006E9, 0x50006EE, 0x30006F3, 0x30006F6, 0x30006F9, 0x30006FC, 0x30006FF, 0x3000702,\n\t0x3000705, 0x3000708, 0x300070B, 0x300070E, 0x3000711, 0x3000714, 0x3000717, 0x300071A, 0x300071D, 0x3000720, 0x3000723, 0x3000726, 0x5000729, 0x500072E, 0x5000733, 0x5000738,\n\t0x500073D, 0x5000742, 0x5000747, 0x500074C, 0x3000751, 0x3000754, 0x3000757, 0x300075A, 0x300075D, 0x3000760, 0x3000763, 0x3000766, 0x5000769, 0x500076E, 0x3000773, 0x3000776,\n\t0x3000779, 0x300077C, 0x300077F, 0x3000782, 0x5000785, 0x500078A, 0x500078F, 0x5000794, 0x5000799, 0x500079E, 0x30007A3, 0x30007A6, 0x30007A9, 0x30007AC, 0x30007AF, 0x30007B2,\n\t0x30007B5, 0x30007B8, 0x30007BB, 0x30007BE, 0x30007C1, 0x30007C4, 0x30007C7, 0x30007CA, 0x50007CD, 0x50007D2, 0x50007D7, 0x50007DC, 0x30007E1, 0x30007E4, 0x30007E7, 0x30007EA,\n\t0x30007ED, 0x30007F0, 0x30007F3, 0x30007F6, 0x30007F9, 0x30007FC, 0x30007FF, 0x3000802, 0x3000805, 0x3000808, 0x300080B, 0x300080E, 0x3000811, 0x3000814, 0x3000817, 0x300081A,\n\t0x300081D, 0x3000820, 0x3000823, 0x3000826, 0x3000829, 0x300082C, 0x300082F, 0x3000832, 0x3000835, 0x3000838, 0x3001E5B, 0x300077C, 0x0, 0x0, 0x0, 0x0,\n\t0x300083F, 0x3000842, 0x3000845, 0x3000848, 0x500084B, 0x5000850, 0x5000855, 0x500085A, 0x500085F, 0x5000864, 0x5000869, 0x500086E, 0x5000873, 0x5000878, 0x500087D, 0x5000882,\n\t0x5000887, 0x500088C, 0x5000891, 0x5000896, 0x500089B, 0x50008A0, 0x50008A5, 0x50008AA, 0x30008AF, 0x30008B2, 0x30008B5, 0x30008B8, 0x30008BB, 0x30008BE, 0x50008C1, 0x50008C6,\n\t0x50008CB, 0x50008D0, 0x50008D5, 0x50008DA, 0x50008DF, 0x50008E4, 0x50008E9, 0x50008EE, 0x30008F3, 0x30008F6, 0x30008F9, 0x30008FC, 0x30008FF, 0x3000902, 0x3000905, 0x3000908,\n\t0x500090B, 0x5000910, 0x5000915, 0x500091A, 0x500091F, 0x5000924, 0x5000929, 0x500092E, 0x5000933, 0x5000938, 0x500093D, 0x5000942, 0x5000947, 0x500094C, 0x5000951, 0x5000956,\n\t0x500095B, 0x5000960, 0x5000965, 0x500096A, 0x300096F, 0x3000972, 0x3000975, 0x3000978, 0x500097B, 0x5000980, 0x5000985, 0x500098A, 0x500098F, 0x5000994, 0x5000999, 0x500099E,\n\t0x50009A3, 0x50009A8, 0x30009AD, 0x30009B0, 0x30009B3, 0x30009B6, 0x30009B9, 0x30009BC, 0x30009BF, 0x30009C2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x40009C5, 0x40009C9, 0x60009CD, 0x60009D3, 0x60009D9, 0x60009DF, 0x60009E5, 0x60009EB, 0x40009F1, 0x40009F5, 0x60009F9, 0x60009FF, 0x6000A05, 0x6000A0B, 0x6000A11, 0x6000A17,\n\t0x4000A1D, 0x4000A21, 0x6000A25, 0x6000A2B, 0x6000A31, 0x6000A37, 0x0, 0x0, 0x4000A3D, 0x4000A41, 0x6000A45, 0x6000A4B, 0x6000A51, 0x6000A57, 0x0, 0x0,\n\t0x4000A5D, 0x4000A61, 0x6000A65, 0x6000A6B, 0x6000A71, 0x6000A77, 0x6000A7D, 0x6000A83, 0x4000A89, 0x4000A8D, 0x6000A91, 0x6000A97, 0x6000A9D, 0x6000AA3, 0x6000AA9, 0x6000AAF,\n\t0x4000AB5, 0x4000AB9, 0x6000ABD, 0x6000AC3, 0x6000AC9, 0x6000ACF, 0x6000AD5, 0x6000ADB, 0x4000AE1, 0x4000AE5, 0x6000AE9, 0x6000AEF, 0x6000AF5, 0x6000AFB, 0x6000B01, 0x6000B07,\n\t0x4000B0D, 0x4000B11, 0x6000B15, 0x6000B1B, 0x6000B21, 0x6000B27, 0x0, 0x0, 0x4000B2D, 0x4000B31, 0x6000B35, 0x6000B3B, 0x6000B41, 0x6000B47, 0x0, 0x0,\n\t0x4000B4D, 0x4000B51, 0x6000B55, 0x6000B5B, 0x6000B61, 0x6000B67, 0x6000B6D, 0x6000B73, 0x0, 0x4000B79, 0x0, 0x6001E5E, 0x0, 0x6000B83, 0x0, 0x6000B89,\n\t0x4000B8F, 0x4000B93, 0x6000B97, 0x6000B9D, 0x6000BA3, 0x6000BA9, 0x6000BAF, 0x6000BB5, 0x4000BBB, 0x4000BBF, 0x6000BC3, 0x6000BC9, 0x6000BCF, 0x6000BD5, 0x6000BDB, 0x6000BE1,\n\t0x4000BE7, 0x4000357, 0x4000BEB, 0x400035B, 0x4000BEF, 0x400035F, 0x4000BF3, 0x4000363, 0x4000BF7, 0x400036D, 0x4000BFB, 0x4000371, 0x4000BFF, 0x4000375, 0x0, 0x0,\n\t0x6000C03, 0x6000C09, 0x8000C0F, 0x8000C17, 0x8000C1F, 0x8000C27, 0x8000C2F, 0x8000C37, 0x6000C3F, 0x6000C45, 0x8000C4B, 0x8000C53, 0x8000C5B, 0x8000C63, 0x8000C6B, 0x8000C73,\n\t0x6000C7B, 0x6000C81, 0x8000C87, 0x8000C8F, 0x8000C97, 0x8000C9F, 0x8000CA7, 0x8000CAF, 0x6000CB7, 0x6000CBD, 0x8000CC3, 0x8000CCB, 0x8000CD3, 0x8000CDB, 0x8000CE3, 0x8000CEB,\n\t0x6000CF3, 0x6000CF9, 0x8000CFF, 0x8000D07, 0x8000D0F, 0x8000D17, 0x8000D1F, 0x8000D27, 0x6000D2F, 0x6000D35, 0x8000D3B, 0x8000D43, 0x8000D4B, 0x8000D53, 0x8000D5B, 0x8000D63,\n\t0x4000D6B, 0x4000D6F, 0x6000D73, 0x4000D79, 0x6000D7D, 0x0, 0x4000D83, 0x6001E64, 0x4000D8D, 0x4000D91, 0x4000D95, 0x400032B, 0x4000D99, 0x3001E6A, 0x2000349, 0x3001E6A,\n\t0x3001E6D, 0x5001E70, 0x6000DA1, 0x4000DA7, 0x6000DAB, 0x0, 0x4000DB1, 0x6001E75, 0x4000DBB, 0x4000331, 0x4000DBF, 0x4000335, 0x4000DC3, 0x5001E7B, 0x5001E80, 0x5001E85,\n\t0x4000DD6, 0x4000DDA, 0x6000DDE, 0x6000349, 0x0, 0x0, 0x4000DE4, 0x6000DE8, 0x4000DEE, 0x4000DF2, 0x4000DF6, 0x4000339, 0x0, 0x5001E8A, 0x5001E8F, 0x5001E94,\n\t0x4000E09, 0x4000E0D, 0x6000E11, 0x6000367, 0x4000E17, 0x4000E1B, 0x4000E1F, 0x6000E23, 0x4000E29, 0x4000E2D, 0x4000E31, 0x4000341, 0x4000E35, 0x5001E99, 0x5001D84, 0x1000E3D,\n\t0x0, 0x0, 0x6000E3E, 0x4000E44, 0x6000E48, 0x0, 0x4000E4E, 0x6001E9E, 0x4000E58, 0x400033D, 0x4000E5C, 0x4000345, 0x4000E60, 0x3001D26, 0x3001E8A, 0x0,\n\t0x1001D1D, 0x1001D1D, 0x1001D1D, 0x1001D1D, 0x1001D1D, 0x1001D1D, 0x1001D1D, 0x1001D1D, 0x1001D1D, 0x1001D1D, 0x1001D1D, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x3001EA4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3001EA7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x1001EAA, 0x2001EAB, 0x3001EAA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1001D1D,\n\t0x0, 0x0, 0x0, 0x6001EAD, 0x9001EB3, 0x0, 0x6001EBC, 0x9001EC2, 0x0, 0x0, 0x0, 0x0, 0x2001ECB, 0x0, 0x3001ECD, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2001ED0, 0x2001ED2, 0x2001ED4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC001EAD, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1001D1D,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x1001ED6, 0x100006F, 0x0, 0x0, 0x1001D33, 0x1001ED7, 0x1001ED8, 0x1001ED9, 0x1001EDA, 0x1001EDB, 0x1001EDC, 0x3001EDD, 0x1000EB7, 0x1001EE0, 0x1001EE1, 0x100007B,\n\t0x1001ED6, 0x1001D2E, 0x1001D24, 0x1001D25, 0x1001D33, 0x1001ED7, 0x1001ED8, 0x1001ED9, 0x1001EDA, 0x1001EDB, 0x1001EDC, 0x3001EDD, 0x1000EB7, 0x1001EE0, 0x1001EE1, 0x0,\n\t0x100004E, 0x1000063, 0x100007E, 0x100080E, 0x2001DFA, 0x1000108, 0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x1000754, 0x100017D, 0x1000195, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2001EE2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3001EE4, 0x3001EE7, 0x1000012, 0x3001EEA, 0x0, 0x3001EED, 0x3001EF0, 0x2001EF3, 0x0, 0x3001EF5, 0x10000F0, 0x1000105, 0x1000105, 0x1000105, 0x1000108, 0x2001EF8,\n\t0x1000021, 0x1000021, 0x1000132, 0x1000135, 0x0, 0x100002D, 0x2001EFA, 0x0, 0x0, 0x1000751, 0x1001EFC, 0x1000168, 0x1000168, 0x1000168, 0x0, 0x0,\n\t0x2001EFD, 0x3001EFF, 0x2001F02, 0x0, 0x10001D1, 0x0, 0x2000345, 0x0, 0x10001D1, 0x0, 0x100012C, 0x300000F, 0x1000633, 0x1000012, 0x0, 0x1000063,\n\t0x1000015, 0x1000697, 0x0, 0x10006FF, 0x100007E, 0x20015C7, 0x20015D3, 0x20015D7, 0x20015DB, 0x100006F, 0x0, 0x3001F04, 0x2001D8F, 0x2001E12, 0x2001F07, 0x2001F09,\n\t0x3001F0B, 0x0, 0x0, 0x0, 0x0, 0x10000C9, 0x10000CC, 0x1000063, 0x100006F, 0x1000129, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x5001F0E, 0x5001F13, 0x6001F18, 0x5001F1E, 0x5001F23, 0x5001F28, 0x5001F2D, 0x5001F32, 0x5001F37, 0x5001F3C, 0x5001F41, 0x5001F46, 0x5001F4B, 0x5001F50, 0x5001F55, 0x4001D34,\n\t0x1000021, 0x2001F5A, 0x3001F5C, 0x2001F5F, 0x10007E1, 0x2001F61, 0x3001F63, 0x4001F66, 0x2001F6A, 0x100080B, 0x2001F6C, 0x3001F6E, 0x1000132, 0x1000012, 0x10000C9, 0x10006FF,\n\t0x100006F, 0x2001F71, 0x3001F73, 0x2001F76, 0x10007E4, 0x2001F78, 0x3001F7A, 0x4001F7D, 0x2001F81, 0x100080E, 0x2001F83, 0x3001F85, 0x1000135, 0x1000060, 0x10000CC, 0x1000702,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5001F88, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000E6C, 0x5000E71, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000E76, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000E7B, 0x5000E80, 0x5000E85,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x5000E8A, 0x0, 0x0, 0x0, 0x0, 0x5000E8F, 0x0, 0x0, 0x5000E94, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x5000E99, 0x0, 0x5000E9E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6001F8D, 0x9001F93, 0x0, 0x6001F9C,\n\t0x9001FA2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x5000EA3, 0x0, 0x0, 0x5000EA8, 0x0, 0x0, 0x5000EAD, 0x0, 0x5000EB2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3000EB7, 0x0, 0x5000EBA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000EBF, 0x3000EC4, 0x3000EC7,\n\t0x5000ECA, 0x5000ECF, 0x0, 0x0, 0x5000ED4, 0x5000ED9, 0x0, 0x0, 0x5000EDE, 0x5000EE3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x5000EE8, 0x5000EED, 0x0, 0x0, 0x5000EF2, 0x5000EF7, 0x0, 0x0, 0x5000EFC, 0x5000F01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000F06, 0x5000F0B, 0x5000F10, 0x5000F15,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x5000F1A, 0x5000F1F, 0x5000F24, 0x5000F29, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000F2E, 0x5000F33, 0x5000F38, 0x5000F3D, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3000F42, 0x3000F45, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x1001D2E, 0x1001D24, 0x1001D25, 0x1001D33, 0x1001ED7, 0x1001ED8, 0x1001ED9, 0x1001EDA, 0x1001EDB, 0x2001F1C, 0x2001D2E, 0x2001FAB, 0x2001FAD, 0x2001FAF, 0x2001FB1, 0x2001FB3,\n\t0x2001FB5, 0x2001FB7, 0x2001FB9, 0x2001FBB, 0x3001FBD, 0x3001FC0, 0x3001FC3, 0x3001FC6, 0x3001FC9, 0x3001FCC, 0x3001FCF, 0x3001FD2, 0x3001FD5, 0x4001FD8, 0x4001FDC, 0x4001FE0,\n\t0x4001FE4, 0x4001FE8, 0x4001FEC, 0x4001FF0, 0x4001FF4, 0x4001FF8, 0x4001FFC, 0x4002000, 0x2002004, 0x2002006, 0x2002008, 0x200200A, 0x200200C, 0x200200E, 0x2002010, 0x2002012,\n\t0x2002014, 0x3002016, 0x3002019, 0x300201C, 0x300201F, 0x3002022, 0x3002025, 0x3002028, 0x300202B, 0x300202E, 0x3002031, 0x3002034, 0x3002037, 0x300203A, 0x300203D, 0x3002040,\n\t0x3002043, 0x3002046, 0x3002049, 0x300204C, 0x300204F, 0x3002052, 0x3002055, 0x3002058, 0x300205B, 0x300205E, 0x3002061, 0x3002064, 0x3002067, 0x300206A, 0x300206D, 0x3002070,\n\t0x3002073, 0x3002076, 0x3002079, 0x300207C, 0x300207F, 0x3002082, 0x1000000, 0x1000633, 0x1000012, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x1000105, 0x1000021, 0x1000126,\n\t0x100012C, 0x1000132, 0x10006FF, 0x100002D, 0x1000030, 0x1000751, 0x1001EFC, 0x1000168, 0x100017A, 0x1000192, 0x100003F, 0x10007E1, 0x10001C2, 0x100080B, 0x100004B, 0x10001D1,\n\t0x100004E, 0x1000636, 0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x100007E, 0x1000754,\n\t0x1002068, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x1001ED6, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC001F8D, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x3002085, 0x2002088, 0x3002087, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000F48, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1000129, 0x10007E1, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300208A,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300208D,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x3002090, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3002093, 0x3002096, 0x3002099, 0x300209C, 0x300209F, 0x30020A2, 0x30020A5, 0x30020A8, 0x30020AB, 0x30020AE, 0x30020B1, 0x30020B4, 0x30020B7, 0x30020BA, 0x30020BD, 0x30020C0,\n\t0x300176F, 0x30020C3, 0x3001241, 0x30020C6, 0x30020C9, 0x30020CC, 0x30020CF, 0x30020D2, 0x30020D5, 0x30020D8, 0x30020DB, 0x30020DE, 0x30020E1, 0x30020E4, 0x30020E7, 0x30020EA,\n\t0x30020ED, 0x30020F0, 0x30020F3, 0x30020F6, 0x30020F9, 0x3001226, 0x30020FC, 0x30020FF, 0x3002102, 0x3002105, 0x3001854, 0x3002108, 0x3001427, 0x300210B, 0x300210E, 0x3002111,\n\t0x3002114, 0x3002117, 0x300211A, 0x300211D, 0x3002120, 0x3002123, 0x30018A3, 0x3002126, 0x3002129, 0x300212C, 0x300212F, 0x3002132, 0x3002135, 0x3002138, 0x300213B, 0x300213E,\n\t0x3002141, 0x3002144, 0x3002147, 0x300214A, 0x300214D, 0x3002150, 0x3002153, 0x3002156, 0x3002159, 0x300215C, 0x300215F, 0x3002162, 0x3002165, 0x3001512, 0x3002168, 0x300216B,\n\t0x300216E, 0x3002171, 0x3002174, 0x3002177, 0x300217A, 0x300217D, 0x3002180, 0x3002183, 0x3002186, 0x3002189, 0x300218C, 0x300218F, 0x3002192, 0x3002195, 0x3002198, 0x300219B,\n\t0x300219E, 0x30021A1, 0x30021A4, 0x30021A7, 0x30021AA, 0x30021AD, 0x30021B0, 0x30021B3, 0x30021B6, 0x30021B9, 0x30021BC, 0x30021BF, 0x30021C2, 0x30021C5, 0x30021C8, 0x30021CB,\n\t0x30021CE, 0x30021D1, 0x30021D4, 0x30021D7, 0x300137C, 0x30021DA, 0x30021DD, 0x30021E0, 0x30021E3, 0x30021E6, 0x30021E9, 0x30013E2, 0x3001142, 0x30021EC, 0x30021EF, 0x30021F2,\n\t0x30021F5, 0x30021F8, 0x30021FB, 0x30021FE, 0x3002201, 0x3002204, 0x3002207, 0x300220A, 0x300220D, 0x3002210, 0x3002213, 0x3002216, 0x3002219, 0x300221C, 0x300221F, 0x30013AF,\n\t0x3001C0A, 0x3002222, 0x30013B5, 0x3002225, 0x3002228, 0x300222B, 0x300222E, 0x3001C31, 0x3002231, 0x3002234, 0x3002237, 0x300223A, 0x300223D, 0x3002240, 0x30010AF, 0x3002243,\n\t0x30011F6, 0x3002246, 0x3002249, 0x300224C, 0x300224F, 0x3001352, 0x30010C4, 0x3002252, 0x3002255, 0x3002258, 0x300225B, 0x300225E, 0x3002261, 0x3002264, 0x3002267, 0x300226A,\n\t0x300226D, 0x3002270, 0x3002273, 0x3002276, 0x3002279, 0x300227C, 0x300227F, 0x3002282, 0x3002285, 0x3002288, 0x300228B, 0x300228E, 0x3002291, 0x3002294, 0x3002297, 0x300229A,\n\t0x300229D, 0x30022A0, 0x30022A3, 0x30022A6, 0x30022A9, 0x3001166, 0x30022AC, 0x3001D01, 0x30022AF, 0x30022B2, 0x30022B5, 0x3001D07, 0x30022B8, 0x30022BB, 0x30022BE, 0x30022C1,\n\t0x3001D16, 0x30022C4, 0x30022C7, 0x30012E6, 0x30010BE, 0x30022CA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x1001D1D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30022CD, 0x0, 0x30020D2, 0x30022D0, 0x30022D3, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000F4D, 0x0, 0x6000F53, 0x0,\n\t0x6000F59, 0x0, 0x6000F5F, 0x0, 0x6000F65, 0x0, 0x6000F6B, 0x0, 0x6000F71, 0x0, 0x6000F77, 0x0, 0x6000F7D, 0x0, 0x6000F83, 0x0,\n\t0x6000F89, 0x0, 0x6000F8F, 0x0, 0x0, 0x6000F95, 0x0, 0x6000F9B, 0x0, 0x6000FA1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x6000FA7, 0x6000FAD, 0x0, 0x6000FB3, 0x6000FB9, 0x0, 0x6000FBF, 0x6000FC5, 0x0, 0x6000FCB, 0x6000FD1, 0x0, 0x6000FD7, 0x6000FDD, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x6000FE3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40022D6, 0x40022DA, 0x0, 0x6000FE9, 0x60022DE,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000FEF, 0x0, 0x6000FF5, 0x0,\n\t0x6000FFB, 0x0, 0x6001001, 0x0, 0x6001007, 0x0, 0x600100D, 0x0, 0x6001013, 0x0, 0x6001019, 0x0, 0x600101F, 0x0, 0x6001025, 0x0,\n\t0x600102B, 0x0, 0x6001031, 0x0, 0x0, 0x6001037, 0x0, 0x600103D, 0x0, 0x6001043, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x6001049, 0x600104F, 0x0, 0x6001055, 0x600105B, 0x0, 0x6001061, 0x6001067, 0x0, 0x600106D, 0x6001073, 0x0, 0x6001079, 0x600107F, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x6001085, 0x0, 0x0, 0x600108B, 0x6001091, 0x6001097, 0x600109D, 0x0, 0x0, 0x0, 0x60010A3, 0x60022E4,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x30022EA, 0x30022ED, 0x30022F0, 0x30022F3, 0x30022F6, 0x30022F9, 0x30022FC, 0x30022FF, 0x3002302, 0x3002305, 0x3002308, 0x300230B, 0x300230E, 0x3002311, 0x3002314,\n\t0x3002317, 0x300231A, 0x300231D, 0x3002320, 0x3002323, 0x3002326, 0x3002329, 0x300232C, 0x300232F, 0x3002332, 0x3002335, 0x3002338, 0x300233B, 0x300233E, 0x3002341, 0x3002344,\n\t0x3002347, 0x300234A, 0x300234D, 0x3002350, 0x3002353, 0x3002356, 0x3002359, 0x300235C, 0x300235F, 0x3002362, 0x3002365, 0x3002368, 0x300236B, 0x300236E, 0x3002371, 0x3002374,\n\t0x3002377, 0x300237A, 0x300237D, 0x3002380, 0x3002383, 0x3002386, 0x3002389, 0x300238C, 0x300238F, 0x3002392, 0x3002395, 0x3002398, 0x300239B, 0x300239E, 0x30023A1, 0x30023A4,\n\t0x30023A7, 0x30023AA, 0x30023AD, 0x30023B0, 0x30023B3, 0x30023B6, 0x30023B9, 0x30023BC, 0x30023BF, 0x30023C2, 0x30023C5, 0x30023C8, 0x30023CB, 0x30023CE, 0x30023D1, 0x30023D4,\n\t0x30023D7, 0x30023DA, 0x30023DD, 0x30023E0, 0x30023E3, 0x30023E6, 0x30023E9, 0x30023EC, 0x30023EF, 0x30023F2, 0x30023F5, 0x30023F8, 0x30023FB, 0x30023FE, 0x3002401, 0x0,\n\t0x0, 0x0, 0x3002093, 0x30020A5, 0x3002404, 0x3002407, 0x300240A, 0x300240D, 0x3002410, 0x3002413, 0x300209F, 0x3002416, 0x3002419, 0x300241C, 0x300241F, 0x30020AB,\n\t0x5002422, 0x5002427, 0x500242C, 0x5002431, 0x5002436, 0x500243B, 0x5002440, 0x5002445, 0x500244A, 0x500244F, 0x5002454, 0x5002459, 0x500245E, 0x5002463, 0x8002468, 0x8002470,\n\t0x8002478, 0x8002480, 0x8002488, 0x8002490, 0x8002498, 0x80024A0, 0x80024A8, 0x80024B0, 0x80024B8, 0x80024C0, 0x80024C8, 0x80024D0, 0x80024D8, 0x110024E0, 0xE0024F1, 0x0,\n\t0x50024FF, 0x5002504, 0x5002509, 0x500250E, 0x5002513, 0x5002518, 0x500251D, 0x5002522, 0x5002527, 0x500252C, 0x5002531, 0x5002536, 0x500253B, 0x5002540, 0x5002545, 0x500254A,\n\t0x500254F, 0x5002554, 0x5002559, 0x500255E, 0x5002563, 0x5002568, 0x500256D, 0x5002572, 0x5002577, 0x500257C, 0x5002581, 0x5002586, 0x500258B, 0x5002590, 0x5002595, 0x500259A,\n\t0x500259F, 0x50025A4, 0x50025A9, 0x50025AE, 0x30025B3, 0x30025B6, 0x3002147, 0x30025B9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x30025BC, 0x2001FAC, 0x20025BF, 0x2001D24, 0x20025C1, 0x20025C3, 0x20025C5, 0x20025C7, 0x20025C9, 0x20025CB, 0x20025CD, 0x2001F27, 0x2001F22, 0x20025CF, 0x20025D1, 0x20025D3,\n\t0x30022EA, 0x30022F3, 0x30022FC, 0x3002302, 0x300231A, 0x300231D, 0x3002326, 0x300232C, 0x300232F, 0x3002335, 0x3002338, 0x300233B, 0x300233E, 0x3002341, 0x6002469, 0x6002471,\n\t0x6002479, 0x6002481, 0x6002489, 0x6002491, 0x6002499, 0x60024A1, 0x60024A9, 0x60024B1, 0x60024B9, 0x60024C1, 0x60024C9, 0x6002341, 0xF0025D5, 0xC0025E4, 0x60025F0, 0x0,\n\t0x3002093, 0x30020A5, 0x3002404, 0x3002407, 0x3002514, 0x300130D, 0x300251E, 0x30020B4, 0x3002528, 0x30020D2, 0x300215C, 0x300217D, 0x300217A, 0x300215F, 0x30010C4, 0x30020EA,\n\t0x3002156, 0x3002555, 0x300255A, 0x3001457, 0x3002564, 0x3002569, 0x300256E, 0x3001466, 0x3002578, 0x30025F6, 0x30025F9, 0x3001226, 0x30025FC, 0x30025FF, 0x3002602, 0x3002605,\n\t0x3002608, 0x30025A5, 0x300260B, 0x300260E, 0x300240A, 0x300240D, 0x3002410, 0x3002611, 0x3002614, 0x3002617, 0x300261A, 0x3002587, 0x300258C, 0x3002591, 0x3002596, 0x300259B,\n\t0x300261D, 0x2002620, 0x2002622, 0x2002624, 0x2002626, 0x2002628, 0x2001D33, 0x20025C2, 0x20025D2, 0x200262A, 0x200262C, 0x200262E, 0x2002630, 0x2002632, 0x2002634, 0x2002636,\n\t0x4002638, 0x400263C, 0x4002640, 0x4002644, 0x4002648, 0x400264C, 0x4002650, 0x4002654, 0x4002658, 0x500265C, 0x5002661, 0x5002666, 0x200266B, 0x300266D, 0x2002670, 0x3002672,\n\t0x3002675, 0x3002678, 0x3001085, 0x300267B, 0x300267E, 0x3000FEF, 0x3000FF5, 0x3000FFB, 0x3001001, 0x3001007, 0x300100D, 0x3001013, 0x3001019, 0x300101F, 0x3001025, 0x300102B,\n\t0x3001031, 0x3001037, 0x300103D, 0x3001043, 0x3002681, 0x3002684, 0x3002687, 0x300268A, 0x300268D, 0x3001049, 0x3001055, 0x3001061, 0x300106D, 0x3001079, 0x3002690, 0x3002693,\n\t0x3002696, 0x3002699, 0x300269C, 0x300269F, 0x30026A2, 0x30026A5, 0x30026A8, 0x30026AB, 0x30026AE, 0x30026B1, 0x30026B4, 0x300108B, 0x3001091, 0x3001097, 0x300109D, 0x0,\n\t0xF0026B7, 0xC0026C6, 0xF0026D2, 0x90026E1, 0xF0026EA, 0x90026F9, 0x9002702, 0x1200270B, 0xC00271D, 0x9002729, 0x9002732, 0x900273B, 0xC002744, 0xC002750, 0xC00275C, 0xC002768,\n\t0xC002774, 0xC002780, 0xC00278C, 0x12002798, 0x60027AA, 0x120027B0, 0x120027C2, 0xF0027D4, 0xC0027B6, 0x120027E3, 0x120027F5, 0xC002807, 0x9002813, 0x900281C, 0xC002825, 0xC002831,\n\t0xF00283D, 0xF00284C, 0x900285B, 0x9002864, 0xC00286D, 0x9002879, 0x9002882, 0x60027EF, 0x600288B, 0x9002891, 0x900289A, 0x120028A3, 0xC0028B5, 0xF0028C1, 0x120028D0, 0xC0028E2,\n\t0x90028EE, 0x90028F7, 0x12002900, 0xC002912, 0x1200291E, 0x9002930, 0xF002939, 0x9002948, 0xC002951, 0x900295D, 0xC002966, 0xF002972, 0xC002981, 0xF00298D, 0xC00299C, 0x60029A8,\n\t0xF0029AE, 0x90029BD, 0x90029C6, 0xC0029CF, 0x90029DB, 0x90029E4, 0x90029ED, 0xF0029F6, 0xC002A05, 0x6002A11, 0x12002A17, 0x9002A29, 0xF002A32, 0xC0027C8, 0xC002A41, 0x9002A4D,\n\t0x9002A56, 0xC002A5F, 0x6002A6B, 0xC002A71, 0xF002A7D, 0x6002A8C, 0x12002A92, 0x90027DA, 0x4002AA4, 0x4002AA8, 0x4002AAC, 0x4002AB0, 0x4002AB4, 0x4002AB8, 0x4002ABC, 0x4002AC0,\n\t0x4002AC4, 0x4002AC8, 0x5002ACC, 0x5002AD1, 0x5002AD6, 0x5002ADB, 0x5002AE0, 0x5002AE5, 0x5002AEA, 0x5002AEF, 0x5002AF4, 0x5002AF9, 0x5002AFE, 0x5002B03, 0x5002B08, 0x5002B0D,\n\t0x5002B12, 0x3002B17, 0x2002B1A, 0x2002B1C, 0x3002B1E, 0x2002B21, 0x2002B23, 0x2002B25, 0x3002B27, 0x3002B2A, 0x2002B2D, 0x6002B2F, 0x6002B35, 0x6002B3B, 0x6002B41, 0xC002B47,\n\t0x2002B53, 0x2002B55, 0x3002B57, 0x2002B5A, 0x2002B5C, 0x2002B5E, 0x2002B60, 0x2002B62, 0x3002B64, 0x4002B67, 0x2002B6B, 0x2002B6D, 0x3002B6F, 0x3002B72, 0x2002B75, 0x2002B77,\n\t0x2002B79, 0x3002B7B, 0x3002B7E, 0x3002B81, 0x3002B84, 0x3002B87, 0x2002B8A, 0x2002B8C, 0x2002B8E, 0x2002B90, 0x2002B92, 0x3002B94, 0x2002B97, 0x2002B99, 0x2002B9B, 0x3002B9D,\n\t0x3002BA0, 0x2002B28, 0x3002BA3, 0x3002BA6, 0x3002BA9, 0x2002B2B, 0x3002BAC, 0x5002BAF, 0x6002BB4, 0x2002B18, 0x3002BBA, 0x3002BBD, 0x3002BC0, 0x3002BC3, 0x7002BC6, 0x8002BCD,\n\t0x2002BD5, 0x2002BD7, 0x3002BD9, 0x2002BDC, 0x2002BDE, 0x2002BE0, 0x3002BE2, 0x2002BE5, 0x2002BE7, 0x2002BE9, 0x2002BEB, 0x2002BED, 0x3002BEF, 0x2002BF2, 0x2002BF4, 0x2002BF6,\n\t0x3002BF8, 0x3002BFB, 0x4002BFE, 0x2002C02, 0x2002C04, 0x2002B24, 0x6002C06, 0x3002C0C, 0x2002C0F, 0x2002C11, 0x2002C13, 0x2002C15, 0x2002C17, 0x2002C19, 0x2002C1B, 0x2002C1D,\n\t0x2002B89, 0x2002C1F, 0x3002C21, 0x2002C24, 0x2002C26, 0x3002C28, 0x3002C2B, 0x2002C2E, 0x4002C30, 0x3002C34, 0x2002C37, 0x2002BCC, 0x2002C39, 0x2002C3B, 0x5002C3D, 0x5002C42,\n\t0x4002C47, 0x4002C4B, 0x4002C4F, 0x4002C53, 0x4002C57, 0x4002C5B, 0x4002C5F, 0x4002C63, 0x4002C67, 0x5002C6B, 0x5002C70, 0x5002C75, 0x5002C7A, 0x5002C7F, 0x5002C84, 0x5002C89,\n\t0x5002C8E, 0x5002C93, 0x5002C98, 0x5002C9D, 0x5002CA2, 0x5002CA7, 0x5002CAC, 0x5002CB1, 0x5002CB6, 0x5002CBB, 0x5002CC0, 0x5002CC5, 0x5002CCA, 0x5002CCF, 0x5002CD4, 0x3002CD9,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2002CDC, 0x2002CDE, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3002CE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2002CE3, 0x2002CE5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3002CE7, 0x3002CEA, 0x2002CED, 0x3002CEF,\n\t0x30010A9, 0x30010AC, 0x30010AF, 0x30010B2, 0x30010B5, 0x30010B8, 0x30010BB, 0x30010BE, 0x30010BE, 0x30010C1, 0x30010C4, 0x30010C7, 0x30010CA, 0x30010CD, 0x30010D0, 0x30010D3,\n\t0x30010D6, 0x30010D9, 0x30010DC, 0x30010DF, 0x30010E2, 0x30010E5, 0x30010E8, 0x30010EB, 0x30010EE, 0x30010F1, 0x30010F4, 0x30010F7, 0x30010FA, 0x30010FD, 0x3001100, 0x3001103,\n\t0x3001106, 0x3001109, 0x300110C, 0x300110F, 0x3001112, 0x3001115, 0x3001118, 0x300111B, 0x300111E, 0x3001121, 0x3001124, 0x3001127, 0x300112A, 0x300112D, 0x3001130, 0x3001133,\n\t0x3001136, 0x3001139, 0x300113C, 0x300113F, 0x3001142, 0x3001145, 0x3001148, 0x300114B, 0x300114E, 0x3001151, 0x3001154, 0x3001157, 0x300115A, 0x300115D, 0x3001160, 0x3001163,\n\t0x3001166, 0x3001169, 0x300116C, 0x300116F, 0x3001172, 0x3001175, 0x3001178, 0x300117B, 0x300117E, 0x3001181, 0x3001184, 0x3001187, 0x300118A, 0x300118D, 0x3001190, 0x3001193,\n\t0x3001196, 0x3001199, 0x300119C, 0x300119F, 0x30011A2, 0x30011A5, 0x30011A8, 0x30011AB, 0x30011AE, 0x30011B1, 0x30011B4, 0x30011B7, 0x30010E2, 0x30011BA, 0x30011BD, 0x30011C0,\n\t0x30011C3, 0x30011C6, 0x30011C9, 0x30011CC, 0x30011CF, 0x30011D2, 0x30011D5, 0x30011D8, 0x30011DB, 0x30011DE, 0x30011E1, 0x30011E4, 0x30011E7, 0x30011EA, 0x30011ED, 0x30011F0,\n\t0x30011F3, 0x30011F6, 0x30011F9, 0x30011FC, 0x30011FF, 0x3001202, 0x3001205, 0x3001208, 0x300120B, 0x300120E, 0x3001211, 0x3001214, 0x3001217, 0x300121A, 0x300121D, 0x3001220,\n\t0x3001223, 0x3001226, 0x3001229, 0x300122C, 0x300122F, 0x3001232, 0x3001235, 0x3001238, 0x300123B, 0x300123E, 0x3001241, 0x3001244, 0x3001247, 0x300124A, 0x300124D, 0x3001250,\n\t0x3001253, 0x3001256, 0x3001259, 0x300125C, 0x300125F, 0x3001262, 0x3001265, 0x3001268, 0x300126B, 0x300126E, 0x3001271, 0x3001274, 0x3001277, 0x300127A, 0x300127D, 0x3001280,\n\t0x3001283, 0x30011F0, 0x3001286, 0x3001289, 0x300128C, 0x300128F, 0x3001292, 0x3001295, 0x3001298, 0x300129B, 0x30011C0, 0x300129E, 0x30012A1, 0x30012A4, 0x30012A7, 0x30012AA,\n\t0x30012AD, 0x30012B0, 0x30012B3, 0x30012B6, 0x30012B9, 0x30012BC, 0x30012BF, 0x30012C2, 0x30012C5, 0x30012C8, 0x30012CB, 0x30012CE, 0x30012D1, 0x30012D4, 0x30012D7, 0x30010E2,\n\t0x30012DA, 0x30012DD, 0x30012E0, 0x30012E3, 0x30012E6, 0x30012E9, 0x30012EC, 0x30012EF, 0x30012F2, 0x30012F5, 0x30012F8, 0x30012FB, 0x30012FE, 0x3001301, 0x3001304, 0x3001307,\n\t0x300130A, 0x300130D, 0x3001310, 0x3001313, 0x3001316, 0x3001319, 0x300131C, 0x300131F, 0x3001322, 0x3001325, 0x3001328, 0x30011C6, 0x300132B, 0x300132E, 0x3001331, 0x3001334,\n\t0x3001337, 0x300133A, 0x300133D, 0x3001340, 0x3001343, 0x3001346, 0x3001349, 0x300134C, 0x300134F, 0x3001352, 0x3001355, 0x3001358, 0x300135B, 0x300135E, 0x3001361, 0x3001364,\n\t0x3001367, 0x300136A, 0x300136D, 0x3001370, 0x3001373, 0x3001376, 0x3001379, 0x300137C, 0x300137F, 0x3001382, 0x3001385, 0x3001388, 0x300138B, 0x300138E, 0x3001391, 0x3001394,\n\t0x3001397, 0x300139A, 0x300139D, 0x30013A0, 0x30013A3, 0x30013A6, 0x30013A9, 0x30013AC, 0x30013AF, 0x30013B2, 0x30013B5, 0x30013B8, 0x30013BB, 0x30013BE, 0x0, 0x0,\n\t0x30013C1, 0x0, 0x30013C4, 0x0, 0x0, 0x30013C7, 0x30013CA, 0x30013CD, 0x30013D0, 0x30013D3, 0x30013D6, 0x30013D9, 0x30013DC, 0x30013DF, 0x30013E2, 0x0,\n\t0x30013E5, 0x0, 0x30013E8, 0x0, 0x0, 0x30013EB, 0x30013EE, 0x0, 0x0, 0x0, 0x30013F1, 0x30013F4, 0x30013F7, 0x30013FA, 0x30013FD, 0x3001400,\n\t0x3001403, 0x3001406, 0x3001409, 0x300140C, 0x300140F, 0x3001412, 0x3001415, 0x3001418, 0x300141B, 0x300141E, 0x3001421, 0x3001424, 0x3001427, 0x300142A, 0x300142D, 0x3001430,\n\t0x3001433, 0x3001436, 0x3001439, 0x300143C, 0x300143F, 0x3001442, 0x3001445, 0x3001448, 0x300144B, 0x300144E, 0x3001451, 0x3001454, 0x3001457, 0x300145A, 0x300145D, 0x3001460,\n\t0x3001463, 0x3001466, 0x3001469, 0x300146C, 0x300146F, 0x3001472, 0x3001475, 0x3001265, 0x3001478, 0x300147B, 0x300147E, 0x3001481, 0x3001484, 0x3001487, 0x3001487, 0x300148A,\n\t0x300148D, 0x3001490, 0x3001493, 0x3001496, 0x3001499, 0x300149C, 0x300149F, 0x30013EB, 0x30014A2, 0x30014A5, 0x30014A8, 0x30014AB, 0x40014AE, 0x30014B2, 0x0, 0x0,\n\t0x30014B5, 0x30014B8, 0x30014BB, 0x30014BE, 0x30014C1, 0x30014C4, 0x30014C7, 0x30014CA, 0x3001415, 0x30014CD, 0x30014D0, 0x30014D3, 0x30013C1, 0x30014D6, 0x30014D9, 0x30014DC,\n\t0x30014DF, 0x30014E2, 0x30014E5, 0x30014E8, 0x30014EB, 0x30014EE, 0x30014F1, 0x30014F4, 0x30014F7, 0x3001430, 0x30014FA, 0x3001433, 0x30014FD, 0x3001500, 0x3001503, 0x3001506,\n\t0x3001509, 0x30013C4, 0x3001121, 0x300150C, 0x300150F, 0x3001512, 0x30011F3, 0x30012F8, 0x3001515, 0x3001518, 0x3001448, 0x300151B, 0x300144B, 0x300151E, 0x3001521, 0x3001524,\n\t0x30013CA, 0x3001527, 0x300152A, 0x300152D, 0x3001530, 0x3001533, 0x30013CD, 0x3001536, 0x3001539, 0x300153C, 0x300153F, 0x3001542, 0x3001545, 0x3001475, 0x3001548, 0x300154B,\n\t0x3001265, 0x300154E, 0x3001481, 0x3001551, 0x3001554, 0x3001557, 0x300155A, 0x300155D, 0x3001490, 0x3001560, 0x30013E8, 0x3001563, 0x3001493, 0x30011BA, 0x3001566, 0x3001496,\n\t0x3001569, 0x300149C, 0x300156C, 0x300156F, 0x3001572, 0x3001575, 0x3001578, 0x30014A2, 0x30013DC, 0x300157B, 0x30014A5, 0x300157E, 0x30014A8, 0x3001581, 0x30010BE, 0x4001584,\n\t0x4001588, 0x400158C, 0x3001590, 0x3001593, 0x3001596, 0x4001599, 0x400159D, 0x40015A1, 0x30015A5, 0x30015A8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x2002CF2, 0x2002CF4, 0x2002CF6, 0x3002CF8, 0x3002CFB, 0x2002CFE, 0x2002CFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x4002D00, 0x4002D04, 0x4002D08, 0x4002D0C, 0x4002D10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40015AB, 0x0, 0x40015AF,\n\t0x2002D14, 0x20015C7, 0x20015DB, 0x20015DF, 0x20015F7, 0x20015FB, 0x2002D16, 0x200161B, 0x200161F, 0x1001EDC, 0x40015B3, 0x40015B7, 0x60015BB, 0x60015C1, 0x40015C7, 0x40015CB,\n\t0x40015CF, 0x40015D3, 0x40015D7, 0x40015DB, 0x40015DF, 0x40015E3, 0x40015E7, 0x0, 0x40015EB, 0x40015EF, 0x40015F3, 0x40015F7, 0x40015FB, 0x0, 0x40015FF, 0x0,\n\t0x4001603, 0x4001607, 0x0, 0x400160B, 0x400160F, 0x0, 0x4001613, 0x4001617, 0x400161B, 0x40015BB, 0x400161F, 0x4001623, 0x4001627, 0x400162B, 0x400162F, 0x4002D18,\n\t0x2002D1C, 0x2002D1C, 0x2002D1E, 0x2002D1E, 0x2002D1E, 0x2002D1E, 0x2002D20, 0x2002D20, 0x2002D20, 0x2002D20, 0x2002D22, 0x2002D22, 0x2002D22, 0x2002D22, 0x2002D24, 0x2002D24,\n\t0x2002D24, 0x2002D24, 0x2002D26, 0x2002D26, 0x2002D26, 0x2002D26, 0x2002D28, 0x2002D28, 0x2002D28, 0x2002D28, 0x2002D2A, 0x2002D2A, 0x2002D2A, 0x2002D2A, 0x2002D2C, 0x2002D2C,\n\t0x2002D2C, 0x2002D2C, 0x2002D2E, 0x2002D2E, 0x2002D2E, 0x2002D2E, 0x2002D30, 0x2002D30, 0x2002D30, 0x2002D30, 0x2002D32, 0x2002D32, 0x2002D32, 0x2002D32, 0x2002D34, 0x2002D34,\n\t0x2002D34, 0x2002D34, 0x2002D36, 0x2002D36, 0x2002D38, 0x2002D38, 0x2002D3A, 0x2002D3A, 0x2002D3C, 0x2002D3C, 0x2002D3E, 0x2002D3E, 0x2002D40, 0x2002D40, 0x2002D42, 0x2002D42,\n\t0x2002D42, 0x2002D42, 0x2002D44, 0x2002D44, 0x2002D44, 0x2002D44, 0x2002D46, 0x2002D46, 0x2002D46, 0x2002D46, 0x2002D48, 0x2002D48, 0x2002D48, 0x2002D48, 0x2002D4A, 0x2002D4A,\n\t0x2002D4C, 0x2002D4C, 0x2002D4C, 0x2002D4C, 0x4000465, 0x4000465, 0x2000469, 0x2000469, 0x2000469, 0x2000469, 0x2002D4E, 0x2002D4E, 0x2002D4E, 0x2002D4E, 0x200046D, 0x200046D,\n\t0x400046D, 0x400046D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x2002D50, 0x2002D50, 0x2002D50, 0x2002D50, 0x2001DA5, 0x2001DA5, 0x2002D52, 0x2002D52, 0x2002D54, 0x2002D54, 0x4001DA5, 0x2002D56, 0x2002D56,\n\t0x2002D58, 0x2002D58, 0x2002D5A, 0x2002D5A, 0x2002D5C, 0x2002D5C, 0x2002D5C, 0x2002D5C, 0x2002D5E, 0x2002D5E, 0x6002D60, 0x6002D60, 0x6000461, 0x6000461, 0x6002D66, 0x6002D66,\n\t0x6002D6C, 0x6002D6C, 0x6002D72, 0x6002D72, 0x6002D78, 0x6002D78, 0x6002D7E, 0x6002D7E, 0x6002D7E, 0x6002D84, 0x6002D84, 0x6002D84, 0x2002D8A, 0x2002D8A, 0x2002D8A, 0x2002D8A,\n\t0x6002D8C, 0x6002D92, 0x6002D98, 0x6002D84, 0x6002D9E, 0x4002DA4, 0x4002DA8, 0x4002DAC, 0x4002DB0, 0x4002DB4, 0x4002DB8, 0x4002DBC, 0x4002DC0, 0x4002DC4, 0x4002DC8, 0x4002DCC,\n\t0x4002DD0, 0x4002DD4, 0x4002DD8, 0x4002DDC, 0x4002DE0, 0x4002DE4, 0x4002DE8, 0x4002DE6, 0x4002DEC, 0x4002DF0, 0x4002DF4, 0x4002DF8, 0x4002DFC, 0x4002E00, 0x4002E04, 0x4002E08,\n\t0x4002E0C, 0x4002E10, 0x4002E14, 0x4002E18, 0x4002E1C, 0x4002E20, 0x4002E24, 0x4002E28, 0x4002E2C, 0x4002E30, 0x4002E34, 0x4002E38, 0x4002E3C, 0x4002E40, 0x4002E44, 0x4002E48,\n\t0x4002E4C, 0x4002E50, 0x4002E54, 0x4002E58, 0x4002E5C, 0x4002E60, 0x4002E64, 0x4002E68, 0x4002E6C, 0x4002E70, 0x4002E74, 0x4002E78, 0x4002E7C, 0x4002E80, 0x4002E84, 0x4002E88,\n\t0x4002E8C, 0x4002E90, 0x4002E94, 0x4002E98, 0x4002E9C, 0x4002EA0, 0x4002DEA, 0x4002DEE, 0x4002EA4, 0x4002EA8, 0x4002D9C, 0x4002EAC, 0x4002EB0, 0x4002EB4, 0x4002EB8, 0x4002EBC,\n\t0x4002EC0, 0x4002EC4, 0x4002EC8, 0x4002ECC, 0x4002ED0, 0x4002DE2, 0x4002ED4, 0x4002ED8, 0x4002E9E, 0x4002EDC, 0x4002ED2, 0x4002EE0, 0x4002EE4, 0x4002EE8, 0x5002EEC, 0x5002EF1,\n\t0x5002EF6, 0x5002EFB, 0x5002F00, 0x5002F05, 0x6002F0A, 0x6002F10, 0x6002D98, 0x6002F16, 0x6002D84, 0x6002D9E, 0x4002F1C, 0x4002F20, 0x4002DB0, 0x4002F24, 0x4002DB4, 0x4002DB8,\n\t0x4002F28, 0x4002F2C, 0x4002DC8, 0x4002F30, 0x4002DCC, 0x4002DD0, 0x4002F34, 0x4002F38, 0x4002DD8, 0x4002F3C, 0x4002DDC, 0x4002DE0, 0x4002E50, 0x4002E54, 0x4002E60, 0x4002E64,\n\t0x4002E68, 0x4002E78, 0x4002E7C, 0x4002E80, 0x4002E84, 0x4002E94, 0x4002E98, 0x4002E9C, 0x4002F40, 0x4002EA4, 0x4002F44, 0x4002F48, 0x4002EB8, 0x4002F4C, 0x4002EBC, 0x4002EC0,\n\t0x4002EE8, 0x4002F50, 0x4002F54, 0x4002E9E, 0x4002F58, 0x4002EDC, 0x4002ED2, 0x6002D8C, 0x6002D92, 0x6002F5C, 0x6002D98, 0x6002F62, 0x4002DA4, 0x4002DA8, 0x4002DAC, 0x4002DB0,\n\t0x4002F68, 0x4002DBC, 0x4002DC0, 0x4002DC4, 0x4002DC8, 0x4002F6C, 0x4002DD8, 0x4002DE4, 0x4002DE8, 0x4002DE6, 0x4002DEC, 0x4002DF0, 0x4002DF8, 0x4002DFC, 0x4002E00, 0x4002E04,\n\t0x4002E08, 0x4002E0C, 0x4002F70, 0x4002E10, 0x4002E14, 0x4002E18, 0x4002E1C, 0x4002E20, 0x4002E24, 0x4002E2C, 0x4002E30, 0x4002E34, 0x4002E38, 0x4002E3C, 0x4002E40, 0x4002E44,\n\t0x4002E48, 0x4002E4C, 0x4002E58, 0x4002E5C, 0x4002E6C, 0x4002E70, 0x4002E74, 0x4002E78, 0x4002E7C, 0x4002E88, 0x4002E8C, 0x4002E90, 0x4002E94, 0x4002F74, 0x4002EA0, 0x4002DEA,\n\t0x4002DEE, 0x4002EA4, 0x4002EAC, 0x4002EB0, 0x4002EB4, 0x4002EB8, 0x4002F78, 0x4002EC4, 0x4002EC8, 0x4002F7C, 0x4002DE2, 0x4002F80, 0x4002ED8, 0x4002E9E, 0x4002EC2, 0x6002D98,\n\t0x6002F62, 0x4002DB0, 0x4002F68, 0x4002DC8, 0x4002F6C, 0x4002DD8, 0x4002F84, 0x4002E08, 0x4002F88, 0x4002F8C, 0x4002F90, 0x4002E78, 0x4002E7C, 0x4002E94, 0x4002EB8, 0x4002F78,\n\t0x4002E9E, 0x4002EC2, 0x6002F94, 0x6002F9A, 0x6002FA0, 0x4002FA6, 0x4002FAA, 0x4002FAE, 0x4002FB2, 0x4002FB6, 0x4002FBA, 0x4002FBE, 0x4002FC2, 0x4002FC6, 0x4002FCA, 0x4002FCE,\n\t0x4002D96, 0x4002FD2, 0x4002D90, 0x4002FD6, 0x4002EDA, 0x4002FDA, 0x4002FDE, 0x4002FE2, 0x4002FE6, 0x4002FEA, 0x4002FEE, 0x4002FF2, 0x4002F8C, 0x4002FF6, 0x4002FFA, 0x4002FFE,\n\t0x4003002, 0x4002FA6, 0x4002FAA, 0x4002FAE, 0x4002FB2, 0x4002FB6, 0x4002FBA, 0x4002FBE, 0x4002FC2, 0x4002FC6, 0x4002FCA, 0x4002FCE, 0x4002D96, 0x4002FD2, 0x4002D90, 0x4002FD6,\n\t0x4002EDA, 0x4002FDA, 0x4002FDE, 0x4002FE2, 0x4002FE6, 0x4002FEA, 0x4002FEE, 0x4002FF2, 0x4002F8C, 0x4002FF6, 0x4002FFA, 0x4002FFE, 0x4003002, 0x4002FEA, 0x4002FEE, 0x4002FF2,\n\t0x4002F8C, 0x4002F88, 0x4002F90, 0x4002E28, 0x4002DFC, 0x4002E00, 0x4002E04, 0x4002FEA, 0x4002FEE, 0x4002FF2, 0x4002E28, 0x4002E2C, 0x4003006, 0x4003006, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x600300A, 0x6003010, 0x6003010, 0x6003016, 0x600301C, 0x6003022, 0x6003028, 0x600302E, 0x6002DE8, 0x6002DE8, 0x6003034, 0x600303A, 0x6003040, 0x6003046, 0x600304C, 0x6003052,\n\t0x6003052, 0x6003058, 0x600305E, 0x600305E, 0x6003064, 0x6003064, 0x600306A, 0x6003070, 0x6003070, 0x6003076, 0x600307C, 0x600307C, 0x6003082, 0x6003082, 0x6003088, 0x600308E,\n\t0x600308E, 0x6003094, 0x6003094, 0x600309A, 0x60030A0, 0x60030A6, 0x60030AC, 0x60030AC, 0x60030B2, 0x60030B8, 0x60030BE, 0x60030C4, 0x60030CA, 0x60030CA, 0x60030D0, 0x60030D6,\n\t0x60030DC, 0x60030E2, 0x60030E8, 0x60030EE, 0x60030EE, 0x60030F4, 0x60030F4, 0x60030FA, 0x60030FA, 0x6003100, 0x6002DEA, 0x6003106, 0x600310C, 0x6002EA0, 0x6002DEE, 0x6003112,\n\t0x0, 0x0, 0x6003118, 0x600311E, 0x6003124, 0x600312A, 0x6003130, 0x6003136, 0x6003136, 0x600313C, 0x6003142, 0x6003148, 0x600314E, 0x600314E, 0x6003154, 0x600315A,\n\t0x6003160, 0x6003166, 0x600316C, 0x6003172, 0x6003178, 0x600317E, 0x6003184, 0x600318A, 0x6003190, 0x6003196, 0x600319C, 0x60031A2, 0x60031A8, 0x60031AE, 0x60031B4, 0x60031BA,\n\t0x60031C0, 0x60031C6, 0x60031CC, 0x60031D2, 0x60030D0, 0x60030DC, 0x60031D8, 0x60031DE, 0x60031E4, 0x60031EA, 0x60031F0, 0x60031F6, 0x60031F0, 0x60031E4, 0x60031FC, 0x6003202,\n\t0x6003208, 0x600320E, 0x6003214, 0x60031F6, 0x60030A6, 0x600306A, 0x600321A, 0x6003220, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x6003226, 0x600322C, 0x8003232, 0x800323A, 0x8003242, 0x800324A, 0x8003252, 0x800325A, 0x8003262, 0x600326A, 0x21003270, 0xF003291, 0x80032A0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x10032A8, 0x30032A9, 0x30032AC, 0x1002085, 0x1000326, 0x1001ECB, 0x1001ED0, 0x30032AF, 0x30032B2, 0x3001EAA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x2001EAA, 0x30032B5, 0x30032B8, 0x10032BB, 0x10032BB, 0x1001EE0, 0x1001EE1, 0x10032BC, 0x10032BD, 0x30032BE, 0x30032C1, 0x30032C4, 0x30032C7, 0x30032CA, 0x30032CD, 0x3000F42,\n\t0x3000F45, 0x30032D0, 0x30032D3, 0x30032D6, 0x30032D9, 0x0, 0x0, 0x10032DC, 0x10032DD, 0x3001ECD, 0x3001ECD, 0x3001ECD, 0x3001ECD, 0x10032BB, 0x10032BB, 0x10032BB,\n\t0x10032A8, 0x30032A9, 0x1001EAA, 0x0, 0x1000326, 0x1002085, 0x1001ED0, 0x1001ECB, 0x30032B5, 0x1001EE0, 0x1001EE1, 0x10032BC, 0x10032BD, 0x30032BE, 0x30032C1, 0x10032DE,\n\t0x10032DF, 0x10032E0, 0x1001EDC, 0x10032E1, 0x1000EC4, 0x1000EC7, 0x1000EB7, 0x0, 0x10032E2, 0x10032E3, 0x10032E4, 0x10032E5, 0x0, 0x0, 0x0, 0x0,\n\t0x30032E6, 0x40032E9, 0x3002EEC, 0x0, 0x3002EF1, 0x0, 0x3002EF6, 0x4002F94, 0x3002EFB, 0x4002F9A, 0x3002F00, 0x4002FA0, 0x3002F05, 0x40032ED, 0x30032F1, 0x40032F4,\n\t0x20032F8, 0x4000451, 0x4000451, 0x4000455, 0x4000455, 0x4000459, 0x4000459, 0x400045D, 0x400045D, 0x4000461, 0x4000461, 0x4000461, 0x4000461, 0x2000451, 0x2000451, 0x2002DA4,\n\t0x2002DA4, 0x2002DA4, 0x2002DA4, 0x20032FA, 0x20032FA, 0x2002DBC, 0x2002DBC, 0x2002DBC, 0x2002DBC, 0x2002DD4, 0x2002DD4, 0x2002DD4, 0x2002DD4, 0x2002D90, 0x2002D90, 0x2002D90,\n\t0x2002D90, 0x2002D96, 0x2002D96, 0x2002D96, 0x2002D96, 0x2002DAE, 0x2002DAE, 0x2002DAE, 0x2002DAE, 0x2003248, 0x2003248, 0x2002EE0, 0x2002EE0, 0x2002EE4, 0x2002EE4, 0x2002F14,\n\t0x2002F14, 0x2002DFC, 0x2002DFC, 0x2002DFC, 0x2002DFC, 0x2002F8C, 0x2002F8C, 0x2002F8C, 0x2002F8C, 0x2002E0C, 0x2002E0C, 0x2002E0C, 0x2002E0C, 0x2002E14, 0x2002E14, 0x2002E14,\n\t0x2002E14, 0x2002E24, 0x2002E24, 0x2002E24, 0x2002E24, 0x2002E2C, 0x2002E2C, 0x2002E2C, 0x2002E2C, 0x2002E30, 0x2002E30, 0x2002E30, 0x2002E30, 0x2002E38, 0x2002E38, 0x2002E38,\n\t0x2002E38, 0x2002E40, 0x2002E40, 0x2002E40, 0x2002E40, 0x2002E58, 0x2002E58, 0x2002E58, 0x2002E58, 0x2002E68, 0x2002E68, 0x2002E68, 0x2002E68, 0x2002E7A, 0x2002E7A, 0x2002E7A,\n\t0x2002E7A, 0x2002D9C, 0x2002D9C, 0x2002D9C, 0x2002D9C, 0x2002EAC, 0x2002EAC, 0x2002EAC, 0x2002EAC, 0x2002EC4, 0x2002EC4, 0x2002EC4, 0x2002EC4, 0x2000459, 0x2000459, 0x2002D5E,\n\t0x2002D5E, 0x2000461, 0x2000461, 0x2000461, 0x2000461, 0x60032FC, 0x60032FC, 0x6003302, 0x6003302, 0x6003308, 0x6003308, 0x4003298, 0x4003298, 0x0, 0x0, 0x0,\n\t0x0, 0x1001ECB, 0x100330E, 0x10032DE, 0x10032E3, 0x10032E4, 0x10032DF, 0x100330F, 0x1001EE0, 0x1001EE1, 0x10032E0, 0x1001EDC, 0x10032A8, 0x10032E1, 0x1001EAA, 0x1001EE5,\n\t0x1001ED6, 0x1001D2E, 0x1001D24, 0x1001D25, 0x1001D33, 0x1001ED7, 0x1001ED8, 0x1001ED9, 0x1001EDA, 0x1001EDB, 0x1002085, 0x1000326, 0x1000EC4, 0x1000EB7, 0x1000EC7, 0x1001ED0,\n\t0x10032E5, 0x1000000, 0x1000633, 0x1000012, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x1000105, 0x1000021, 0x1000126, 0x100012C, 0x1000132, 0x10006FF, 0x100002D, 0x1000030,\n\t0x1000751, 0x1001EFC, 0x1000168, 0x100017A, 0x1000192, 0x100003F, 0x10007E1, 0x10001C2, 0x100080B, 0x100004B, 0x10001D1, 0x10032DC, 0x10032E2, 0x10032DD, 0x1003310, 0x10032BB,\n\t0x1000E3D, 0x100004E, 0x1000636, 0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x100007E,\n\t0x1000754, 0x1002068, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x10032BC, 0x1003311, 0x10032BD, 0x1003312, 0x3003313,\n\t0x3003316, 0x30032AC, 0x30032D0, 0x30032D3, 0x30032A9, 0x3003319, 0x300109D, 0x30026CF, 0x3002915, 0x300331C, 0x300292A, 0x3002705, 0x300331F, 0x300278F, 0x30029FF, 0x300274A,\n\t0x30026C0, 0x3002675, 0x3002678, 0x3001085, 0x300267B, 0x300267E, 0x3000FEF, 0x3000FF5, 0x3000FFB, 0x3001001, 0x3001007, 0x300100D, 0x3001013, 0x3001019, 0x300101F, 0x3001025,\n\t0x300102B, 0x3001031, 0x3001037, 0x300103D, 0x3001043, 0x3002681, 0x3002684, 0x3002687, 0x300268A, 0x300268D, 0x3001049, 0x3001055, 0x3001061, 0x300106D, 0x3001079, 0x3002690,\n\t0x3002693, 0x3002696, 0x3002699, 0x300269C, 0x300269F, 0x30026A2, 0x30026A5, 0x30026A8, 0x30026AB, 0x30026AE, 0x30026B1, 0x30026B4, 0x300108B, 0x30026D5, 0x3000F50, 0x3000FB0,\n\t0x3002383, 0x30022EA, 0x30022ED, 0x30022F0, 0x30022F3, 0x30022F6, 0x30022F9, 0x30022FC, 0x30022FF, 0x3002302, 0x3002305, 0x3002308, 0x300230B, 0x300230E, 0x3002311, 0x3002314,\n\t0x3002317, 0x300231A, 0x300231D, 0x3002320, 0x3002323, 0x3002326, 0x3002329, 0x300232C, 0x300232F, 0x3002332, 0x3002335, 0x3002338, 0x300233B, 0x300233E, 0x3002341, 0x0,\n\t0x0, 0x0, 0x3002344, 0x3002347, 0x300234A, 0x300234D, 0x3002350, 0x3002353, 0x0, 0x0, 0x3002356, 0x3002359, 0x300235C, 0x300235F, 0x3002362, 0x3002365,\n\t0x0, 0x0, 0x3002368, 0x300236B, 0x300236E, 0x3002371, 0x3002374, 0x3002377, 0x0, 0x0, 0x300237A, 0x300237D, 0x3002380, 0x0, 0x0, 0x0,\n\t0x2003322, 0x2003324, 0x2003326, 0x3001D21, 0x2003328, 0x200332A, 0x300332C, 0x0, 0x300332F, 0x3000E6C, 0x3003332, 0x3000E71, 0x3003335, 0x3003338, 0x300333B, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8001633, 0x0, 0x800163B, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8001643, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800164B, 0x8001653,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800165B, 0x8001663, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800166B, 0x8001673, 0x0, 0x800167B, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8001683, 0x800168B, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8001693, 0x800169B,\n\t0xC00333E, 0xC0016AF, 0xC0016BB, 0xC0016C7, 0xC0016D3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80016DF, 0x80016E7, 0xC0016EF, 0xC0016FB, 0xC001707,\n\t0xC001713, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x100007E, 0x1000754, 0x1002068, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4,\n\t0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x1000000, 0x1000633, 0x1000012, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x1000105, 0x1000021, 0x1000126, 0x100012C, 0x1000132,\n\t0x10006FF, 0x100002D, 0x1000030, 0x1000751, 0x1001EFC, 0x1000168, 0x100017A, 0x1000192, 0x100003F, 0x10007E1, 0x10001C2, 0x100080B, 0x100004B, 0x10001D1, 0x100004E, 0x1000636,\n\t0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x0, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x100007E, 0x1000754, 0x1002068, 0x100016B,\n\t0x100004B, 0x10001D1, 0x100004E, 0x1000636, 0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B,\n\t0x100007E, 0x1000754, 0x1002068, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x1000000, 0x0, 0x1000012, 0x10000C9,\n\t0x0, 0x0, 0x10000ED, 0x0, 0x0, 0x1000126, 0x100012C, 0x0, 0x0, 0x100002D, 0x1000030, 0x1000751, 0x1001EFC, 0x0, 0x100017A, 0x1000192,\n\t0x100003F, 0x10007E1, 0x10001C2, 0x100080B, 0x100004B, 0x10001D1, 0x100004E, 0x1000636, 0x1000060, 0x10000CC, 0x0, 0x100069A, 0x0, 0x1000108, 0x100006F, 0x1000129,\n\t0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x0, 0x1000754, 0x1002068, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4,\n\t0x1000000, 0x1000633, 0x1000012, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x1000105, 0x1000021, 0x1000126, 0x100012C, 0x1000132, 0x10006FF, 0x100002D, 0x1000030, 0x1000751,\n\t0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x1000000, 0x1000633, 0x0, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x0, 0x0, 0x1000126, 0x100012C, 0x1000132,\n\t0x10006FF, 0x100002D, 0x1000030, 0x1000751, 0x1001EFC, 0x0, 0x100017A, 0x1000192, 0x100003F, 0x10007E1, 0x10001C2, 0x100080B, 0x100004B, 0x0, 0x100004E, 0x1000636,\n\t0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x100007E, 0x1000754, 0x1002068, 0x100016B,\n\t0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x1000000, 0x1000633, 0x0, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x0,\n\t0x1000021, 0x1000126, 0x100012C, 0x1000132, 0x10006FF, 0x0, 0x1000030, 0x0, 0x0, 0x0, 0x100017A, 0x1000192, 0x100003F, 0x10007E1, 0x10001C2, 0x100080B,\n\t0x100004B, 0x0, 0x100004E, 0x1000636, 0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B,\n\t0x100004B, 0x10001D1, 0x100004E, 0x1000636, 0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B,\n\t0x100007E, 0x1000754, 0x1002068, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x1000000, 0x1000633, 0x1000012, 0x10000C9,\n\t0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x200334A, 0x200334C, 0x0, 0x0, 0x200032B, 0x200334E, 0x2001F07, 0x2003350, 0x2000331, 0x2003352, 0x2000335, 0x2001D95,\n\t0x2000339, 0x2003354, 0x2003356, 0x2003358, 0x200335A, 0x200335C, 0x200033D, 0x2001F09, 0x2000E35, 0x2001D95, 0x2001D97, 0x200335E, 0x2000341, 0x2003360, 0x2003362, 0x2003364,\n\t0x2000345, 0x3003366, 0x2000357, 0x2001D89, 0x2001E12, 0x2001E14, 0x200035B, 0x2003369, 0x200035F, 0x2001D8B, 0x2000349, 0x2001D91, 0x200336B, 0x2001D29, 0x200336D, 0x200336F,\n\t0x200036D, 0x2001D8F, 0x2000E17, 0x2001D93, 0x2003371, 0x2003373, 0x2000367, 0x2001D8D, 0x2001E16, 0x2003375, 0x2000375, 0x3003377, 0x200035B, 0x2001D8B, 0x2001D91, 0x2001D8D,\n\t0x2000E17, 0x2001D8F, 0x200032B, 0x200334E, 0x2001F07, 0x2003350, 0x2000331, 0x2003352, 0x2000335, 0x2001D95, 0x2000339, 0x2003354, 0x2003356, 0x2003358, 0x200335A, 0x200335C,\n\t0x200033D, 0x2001F09, 0x2000E35, 0x2001D95, 0x2001D97, 0x200335E, 0x2000341, 0x2003360, 0x2003362, 0x2003364, 0x2000345, 0x3003366, 0x2000357, 0x2001D89, 0x2001E12, 0x2001E14,\n\t0x2001E16, 0x2003375, 0x2000375, 0x3003377, 0x200035B, 0x2001D8B, 0x2001D91, 0x2001D8D, 0x2000E17, 0x2001D8F, 0x200337A, 0x200337C, 0x0, 0x0, 0x1001ED6, 0x1001D2E,\n\t0x1001D24, 0x1001D25, 0x1001D33, 0x1001ED7, 0x1001ED8, 0x1001ED9, 0x1001EDA, 0x1001EDB, 0x1001ED6, 0x1001D2E, 0x1001D24, 0x1001D25, 0x1001D33, 0x1001ED7, 0x1001ED8, 0x1001ED9,\n\t0x1001EDA, 0x1001EDB, 0x1001ED6, 0x1001D2E, 0x1001D24, 0x1001D25, 0x1001D33, 0x1001ED7, 0x1001ED8, 0x1001ED9, 0x1001EDA, 0x1001EDB, 0x1001ED6, 0x1001D2E, 0x1001D24, 0x1001D25,\n\t0x1001D33, 0x1001ED7, 0x1001ED8, 0x1001ED9, 0x1001EDA, 0x1001EDB, 0x1001ED6, 0x1001D2E, 0x1001D24, 0x1001D25, 0x1001D33, 0x1001ED7, 0x1001ED8, 0x1001ED9, 0x1001EDA, 0x1001EDB,\n\t0x2000451, 0x2002DA4, 0x2002D90, 0x2003248, 0x0, 0x2000459, 0x2002F14, 0x2002D96, 0x2002E24, 0x2000461, 0x2002E68, 0x2002E7A, 0x2002D9C, 0x2002EAC, 0x2002DFC, 0x2002E30,\n\t0x2002E40, 0x2002E0C, 0x2002E58, 0x2002EE4, 0x2002F8C, 0x2002DBC, 0x2002DD4, 0x2002DAE, 0x2002EE0, 0x2002E14, 0x2002E2C, 0x2002E38, 0x200337E, 0x2002D4A, 0x2003380, 0x2003382,\n\t0x0, 0x2002DA4, 0x2002D90, 0x0, 0x2002EC4, 0x0, 0x0, 0x2002D96, 0x0, 0x2000461, 0x2002E68, 0x2002E7A, 0x2002D9C, 0x2002EAC, 0x2002DFC, 0x2002E30,\n\t0x2002E40, 0x2002E0C, 0x2002E58, 0x0, 0x2002F8C, 0x2002DBC, 0x2002DD4, 0x2002DAE, 0x0, 0x2002E14, 0x0, 0x2002E38, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x2002D90, 0x0, 0x0, 0x0, 0x0, 0x2002D96, 0x0, 0x2000461, 0x0, 0x2002E7A, 0x0, 0x2002EAC, 0x2002DFC, 0x2002E30,\n\t0x0, 0x2002E0C, 0x2002E58, 0x0, 0x2002F8C, 0x0, 0x0, 0x2002DAE, 0x0, 0x2002E14, 0x0, 0x2002E38, 0x0, 0x2002D4A, 0x0, 0x2003382,\n\t0x0, 0x2002DA4, 0x2002D90, 0x0, 0x2002EC4, 0x0, 0x0, 0x2002D96, 0x2002E24, 0x2000461, 0x2002E68, 0x0, 0x2002D9C, 0x2002EAC, 0x2002DFC, 0x2002E30,\n\t0x2002E40, 0x2002E0C, 0x2002E58, 0x0, 0x2002F8C, 0x2002DBC, 0x2002DD4, 0x2002DAE, 0x0, 0x2002E14, 0x2002E2C, 0x2002E38, 0x200337E, 0x0, 0x2003380, 0x0,\n\t0x2000451, 0x2002DA4, 0x2002D90, 0x2003248, 0x2002EC4, 0x2000459, 0x2002F14, 0x2002D96, 0x2002E24, 0x2000461, 0x0, 0x2002E7A, 0x2002D9C, 0x2002EAC, 0x2002DFC, 0x2002E30,\n\t0x2002E40, 0x2002E0C, 0x2002E58, 0x2002EE4, 0x2002F8C, 0x2002DBC, 0x2002DD4, 0x2002DAE, 0x2002EE0, 0x2002E14, 0x2002E2C, 0x2002E38, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x2002DA4, 0x2002D90, 0x2003248, 0x0, 0x2000459, 0x2002F14, 0x2002D96, 0x2002E24, 0x2000461, 0x0, 0x2002E7A, 0x2002D9C, 0x2002EAC, 0x2002DFC, 0x2002E30,\n\t0x2002E40, 0x2002E0C, 0x2002E58, 0x2002EE4, 0x2002F8C, 0x2002DBC, 0x2002DD4, 0x2002DAE, 0x2002EE0, 0x2002E14, 0x2002E2C, 0x2002E38, 0x0, 0x0, 0x0, 0x0,\n\t0x2002017, 0x2003384, 0x2003386, 0x2003388, 0x200338A, 0x200338C, 0x200338E, 0x2003390, 0x2003392, 0x2003394, 0x2003396, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3003398, 0x300339B, 0x300339E, 0x30033A1, 0x30033A4, 0x30033A7, 0x30033AA, 0x30033AD, 0x30033B0, 0x30033B3, 0x30033B6, 0x30033B9, 0x30033BC, 0x30033BF, 0x30033C2, 0x30033C5,\n\t0x30033C8, 0x30033CB, 0x30033CE, 0x30033D1, 0x30033D4, 0x30033D7, 0x30033DA, 0x30033DD, 0x30033E0, 0x30033E3, 0x70033E6, 0x1000012, 0x1000168, 0x20033ED, 0x20033EF, 0x0,\n\t0x1000000, 0x1000633, 0x1000012, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x1000105, 0x1000021, 0x1000126, 0x100012C, 0x1000132, 0x10006FF, 0x100002D, 0x1000030, 0x1000751,\n\t0x1001EFC, 0x1000168, 0x100017A, 0x1000192, 0x100003F, 0x10007E1, 0x10001C2, 0x100080B, 0x100004B, 0x10001D1, 0x20033F1, 0x2002BE9, 0x20033F3, 0x20033F5, 0x30033F7, 0x20033FA,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20033FC, 0x20033FE, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x2003400, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x6003402, 0x6003408, 0x300100D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x300213E, 0x300340E, 0x3003411, 0x600103D, 0x30020A5, 0x300180E, 0x3003414, 0x300241C, 0x3003417, 0x300341A, 0x300341D, 0x30012D7, 0x3003420, 0x3003423, 0x3001758, 0x3003426,\n\t0x3003429, 0x300342C, 0x30021A7, 0x300342F, 0x3003432, 0x3003435, 0x3003438, 0x300343B, 0x300343E, 0x3002093, 0x3002404, 0x3003441, 0x3002611, 0x300240D, 0x3002614, 0x3003444,\n\t0x300223A, 0x3003447, 0x300344A, 0x300344D, 0x3003450, 0x3003453, 0x300255A, 0x300215C, 0x3003456, 0x300177E, 0x3003459, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x900345C, 0x9003465, 0x900346E, 0x9003477, 0x9003480, 0x9003489, 0x9003492, 0x900349B, 0x90034A4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x30034AD, 0x30034B0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x300171F, 0x3001722, 0x3001725, 0x4001728, 0x300172C, 0x3001403, 0x300172F, 0x3001732, 0x3001735, 0x3001738, 0x3001406, 0x300173B, 0x300173E, 0x4001741, 0x3001409, 0x3001745,\n\t0x3001748, 0x300174B, 0x400174E, 0x3001752, 0x3001755, 0x3001758, 0x400175B, 0x300175F, 0x3001762, 0x3001765, 0x3001768, 0x30014B8, 0x400176B, 0x300176F, 0x3001772, 0x3001775,\n\t0x3001778, 0x300177B, 0x300177E, 0x3001781, 0x3001784, 0x30014C7, 0x300140C, 0x300140F, 0x30014CA, 0x3001787, 0x300178A, 0x30011CC, 0x300178D, 0x3001412, 0x3001790, 0x3001793,\n\t0x3001796, 0x3001799, 0x3001799, 0x3001799, 0x400179C, 0x30017A0, 0x30017A3, 0x30017A6, 0x40017A9, 0x30017AD, 0x30017B0, 0x30017B3, 0x30017B6, 0x30017B9, 0x30017BC, 0x30017BF,\n\t0x30017C2, 0x30017C5, 0x30017C8, 0x30017CB, 0x30017CE, 0x30017D1, 0x30017D1, 0x30014D0, 0x30017D4, 0x30017D7, 0x30017DA, 0x30017DD, 0x3001418, 0x30017E0, 0x30017E3, 0x30017E6,\n\t0x3001397, 0x30017E9, 0x30017EC, 0x30017EF, 0x30017F2, 0x30017F5, 0x30017F8, 0x30017FB, 0x30017FE, 0x4001801, 0x3001805, 0x3001808, 0x300180B, 0x300180E, 0x3001811, 0x3001814,\n\t0x4001817, 0x400181B, 0x300181F, 0x3001822, 0x3001825, 0x3001828, 0x300182B, 0x300182E, 0x3001831, 0x3001834, 0x3001837, 0x3001837, 0x400183A, 0x300183E, 0x3001841, 0x30011C0,\n\t0x3001844, 0x4001847, 0x300184B, 0x300184E, 0x3001851, 0x3001854, 0x3001857, 0x300185A, 0x3001427, 0x300185D, 0x3001860, 0x4001863, 0x3001867, 0x400186A, 0x300186E, 0x3001871,\n\t0x3001874, 0x3001877, 0x300187A, 0x300187D, 0x3001880, 0x3001883, 0x3001886, 0x3001889, 0x300188C, 0x400188F, 0x3001893, 0x3001896, 0x3001899, 0x300189C, 0x300111E, 0x400189F,\n\t0x30018A3, 0x40018A6, 0x40018A6, 0x30018AA, 0x30018AD, 0x30018AD, 0x30018B0, 0x40018B3, 0x40018B7, 0x30018BB, 0x30018BE, 0x30018C1, 0x30018C4, 0x30018C7, 0x30018CA, 0x30018CD,\n\t0x30018D0, 0x30018D3, 0x30018D6, 0x300142A, 0x40018D9, 0x30018DD, 0x30018E0, 0x30018E3, 0x30014F4, 0x30018E3, 0x30018E6, 0x3001430, 0x30018E9, 0x30018EC, 0x30018EF, 0x30018F2,\n\t0x3001433, 0x30010CD, 0x30018F5, 0x30018F8, 0x30018FB, 0x30018FE, 0x3001901, 0x3001904, 0x4001907, 0x300190B, 0x300190E, 0x3001911, 0x3001914, 0x3001917, 0x400191A, 0x300191E,\n\t0x3001921, 0x3001924, 0x3001927, 0x300192A, 0x300192D, 0x3001930, 0x3001933, 0x3001936, 0x3001436, 0x3001939, 0x400193C, 0x3001940, 0x3001943, 0x3001946, 0x3001949, 0x300143C,\n\t0x300194C, 0x300194F, 0x3001952, 0x3001955, 0x3001958, 0x300195B, 0x300195E, 0x3001961, 0x3001121, 0x300150C, 0x3001964, 0x3001967, 0x300196A, 0x400196D, 0x3001971, 0x3001974,\n\t0x3001977, 0x300197A, 0x300143F, 0x400197D, 0x3001981, 0x3001984, 0x3001987, 0x3001590, 0x300198A, 0x300198D, 0x3001990, 0x3001993, 0x4001996, 0x300199A, 0x300199D, 0x30019A0,\n\t0x40019A3, 0x30019A7, 0x30019AA, 0x30019AD, 0x30019B0, 0x30011F3, 0x30019B3, 0x40019B6, 0x40019BA, 0x40019BE, 0x30019C2, 0x40019C5, 0x30019C9, 0x30019CC, 0x30019CF, 0x30019D2,\n\t0x30019D5, 0x3001442, 0x30012F8, 0x30019D8, 0x30019DB, 0x30019DE, 0x40019E1, 0x30019E5, 0x30019E8, 0x30019EB, 0x30019EE, 0x3001518, 0x30019F1, 0x40019F4, 0x30019F8, 0x30019FB,\n\t0x40019FE, 0x4001A02, 0x3001A06, 0x3001A09, 0x300151B, 0x3001A0C, 0x3001A0F, 0x3001A12, 0x3001A15, 0x3001A18, 0x3001A1B, 0x4001A1E, 0x3001A22, 0x4001A25, 0x3001A29, 0x4001A2C,\n\t0x3001A30, 0x3001521, 0x3001A33, 0x4001A36, 0x3001A3A, 0x3001A3D, 0x4001A40, 0x4001A44, 0x3001A48, 0x3001A4B, 0x3001A4E, 0x3001A51, 0x3001A54, 0x3001A54, 0x3001A57, 0x3001A5A,\n\t0x3001527, 0x3001A5D, 0x3001A60, 0x3001A63, 0x3001A66, 0x4001A69, 0x3001A6D, 0x4001A70, 0x30011C9, 0x4001A74, 0x3001A78, 0x4001A7B, 0x4001A7F, 0x4001A83, 0x3001A87, 0x3001A8A,\n\t0x3001539, 0x4001A8D, 0x4001A91, 0x4001A95, 0x4001A99, 0x3001A9D, 0x3001AA0, 0x3001AA0, 0x300153C, 0x3001596, 0x3001AA3, 0x3001AA6, 0x3001AA9, 0x4001AAC, 0x3001AB0, 0x3001157,\n\t0x3001542, 0x3001AB3, 0x4001AB6, 0x3001463, 0x4001ABA, 0x4001ABE, 0x30013D9, 0x3001AC2, 0x3001AC5, 0x300146F, 0x3001AC8, 0x3001ACB, 0x4001ACE, 0x4001AD2, 0x4001AD2, 0x3001AD6,\n\t0x3001AD9, 0x4001ADC, 0x3001AE0, 0x3001AE3, 0x3001AE6, 0x4001AE9, 0x3001AED, 0x3001AF0, 0x3001AF3, 0x3001AF6, 0x3001AF9, 0x4001AFC, 0x3001B00, 0x3001B03, 0x3001B06, 0x3001B09,\n\t0x3001B0C, 0x3001B0F, 0x4001B12, 0x4001B16, 0x3001B1A, 0x4001B1D, 0x3001B21, 0x4001B24, 0x3001B28, 0x3001B2B, 0x3001481, 0x4001B2E, 0x4001B32, 0x3001B36, 0x4001B39, 0x3001B3D,\n\t0x4001B40, 0x3001B44, 0x3001B47, 0x3001B4A, 0x3001B4D, 0x3001B50, 0x3001B53, 0x4001B56, 0x4001B5A, 0x4001B5E, 0x4001B62, 0x30018AA, 0x3001B66, 0x3001B69, 0x3001B6C, 0x3001B6F,\n\t0x3001B72, 0x3001B75, 0x3001B78, 0x3001B7B, 0x3001B7E, 0x3001B81, 0x3001B84, 0x4001B87, 0x30011FF, 0x3001B8B, 0x3001B8E, 0x3001B91, 0x3001B94, 0x3001B97, 0x3001B9A, 0x300148A,\n\t0x3001B9D, 0x3001BA0, 0x3001BA3, 0x3001BA6, 0x4001BA9, 0x4001BAD, 0x4001BB1, 0x3001BB5, 0x3001BB8, 0x3001BBB, 0x3001BBE, 0x4001BC1, 0x3001BC5, 0x4001BC8, 0x3001BCC, 0x3001BCF,\n\t0x4001BD2, 0x4001BD6, 0x3001BDA, 0x3001BDD, 0x3001148, 0x3001BE0, 0x3001BE3, 0x3001BE6, 0x3001BE9, 0x3001BEC, 0x3001BEF, 0x3001557, 0x3001BF2, 0x3001BF5, 0x3001BF8, 0x3001BFB,\n\t0x3001BFE, 0x3001C01, 0x3001C04, 0x3001C07, 0x3001C0A, 0x4001C0D, 0x3001C11, 0x3001C14, 0x3001C17, 0x3001C1A, 0x3001C1D, 0x4001C20, 0x4001C24, 0x3001C28, 0x3001C2B, 0x3001C2E,\n\t0x3001566, 0x3001569, 0x3001C31, 0x4001C34, 0x3001C38, 0x3001C3B, 0x3001C3E, 0x3001C41, 0x4001C44, 0x4001C48, 0x3001C4C, 0x3001C4F, 0x3001C52, 0x4001C55, 0x3001C59, 0x300156C,\n\t0x4001C5C, 0x4001C60, 0x3001C64, 0x3001C67, 0x3001C6A, 0x4001C6D, 0x3001C71, 0x3001C74, 0x3001C77, 0x3001C7A, 0x3001C7D, 0x3001C80, 0x3001C83, 0x4001C86, 0x3001C8A, 0x3001C8D,\n\t0x3001C90, 0x4001C93, 0x3001C97, 0x3001C9A, 0x3001C9D, 0x3001CA0, 0x4001CA3, 0x4001CA7, 0x3001CAB, 0x3001CAE, 0x3001CB1, 0x4001CB4, 0x3001CB8, 0x4001CBB, 0x300157E, 0x300157E,\n\t0x3001CBF, 0x4001CC2, 0x3001CC6, 0x3001CC9, 0x3001CCC, 0x3001CCF, 0x3001CD2, 0x3001CD5, 0x3001CD8, 0x4001CDB, 0x3001581, 0x3001CDF, 0x3001CE2, 0x3001CE5, 0x3001CE8, 0x3001CEB,\n\t0x4001CEE, 0x3001CF2, 0x4001CF5, 0x4001CF9, 0x4001CFD, 0x3001D01, 0x3001D04, 0x3001D07, 0x3001D0A, 0x3001D0D, 0x3001D10, 0x3001D13, 0x3001D16, 0x4001D19, 0x0, 0x0,\n};\nconst uint32_t* NFKDDataPtr = NFKDData;\n\nconst uint32_t UppercaseIndex1[272] = {\n\t0, 128, 256, 45, 45, 45, 45, 45, 45, 45, 384, 45, 45, 45, 45, 512,\n\t640, 768, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n};\nconst uint32_t* UppercaseIndex1Ptr = UppercaseIndex1;\n\nconst uint32_t UppercaseIndex2[896] = {\n\t0x0, 0x0, 0x0, 0x20, 0x0, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0, 0x100, 0x120, 0x140, 0x160, 0x180,\n\t0x1A0, 0x1C0, 0x1E0, 0x200, 0x220, 0x0, 0x0, 0x0, 0x0, 0x0, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,\n\t0x0, 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0x400, 0x0, 0x420, 0x440, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x460, 0x0, 0x0, 0x0, 0x0,\n\t0x480, 0x4A0, 0x4C0, 0x4E0, 0x500, 0x520, 0x540, 0x560, 0x580, 0x5A0, 0x5C0, 0x5E0, 0x600, 0x620, 0x640, 0x660,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x680, 0x6A0, 0x6C0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6E0, 0x700, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x720, 0x740, 0x760, 0x780, 0x7A0, 0x7C0, 0x7E0, 0x800, 0x820, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x840, 0x860, 0x880, 0x0, 0x0, 0x0, 0x0, 0x8A0, 0x8C0, 0x8E0, 0x900, 0x920, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x940, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x960, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x980, 0x9A0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9C0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n};\nconst uint32_t* UppercaseIndex2Ptr = UppercaseIndex2;\n\nconst uint32_t UppercaseData[2528] = {\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x1000000, 0x1000633, 0x1000012, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x1000105, 0x1000021, 0x1000126, 0x100012C, 0x1000132, 0x10006FF, 0x100002D, 0x1000030,\n\t0x1000751, 0x1001EFC, 0x1000168, 0x100017A, 0x1000192, 0x100003F, 0x10007E1, 0x10001C2, 0x100080B, 0x100004B, 0x10001D1, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x2003358, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20033F5,\n\t0x20034B3, 0x20034B5, 0x20034B7, 0x20034B9, 0x20034BB, 0x20034BD, 0x2000243, 0x20034BF, 0x20034C1, 0x20034C3, 0x20034C5, 0x20034C7, 0x20034C9, 0x20034CB, 0x20034CD, 0x20034CF,\n\t0x20034D1, 0x20034D3, 0x20034D5, 0x20034D7, 0x20034D9, 0x20034DB, 0x20034DD, 0x0, 0x2000290, 0x20034DF, 0x20034E1, 0x20034E3, 0x20034E5, 0x20034E7, 0x20034E9, 0x20034EB,\n\t0x0, 0x20034ED, 0x0, 0x20034EF, 0x0, 0x20034F1, 0x0, 0x20034F3, 0x0, 0x20034F5, 0x0, 0x20034F7, 0x0, 0x20034F9, 0x0, 0x20034FB,\n\t0x0, 0x20034FD, 0x0, 0x20034FF, 0x0, 0x2003501, 0x0, 0x2003503, 0x0, 0x2003505, 0x0, 0x2003507, 0x0, 0x2003509, 0x0, 0x200350B,\n\t0x0, 0x200350D, 0x0, 0x200350F, 0x0, 0x2003511, 0x0, 0x2002CE3, 0x0, 0x2003513, 0x0, 0x2003515, 0x0, 0x2003517, 0x0, 0x2003519,\n\t0x0, 0x1000021, 0x0, 0x200351B, 0x0, 0x200351D, 0x0, 0x200351F, 0x0, 0x0, 0x2003521, 0x0, 0x2003523, 0x0, 0x2003525, 0x0,\n\t0x2003527, 0x0, 0x2003529, 0x0, 0x200352B, 0x0, 0x200352D, 0x0, 0x200352F, 0x3003531, 0x0, 0x2003534, 0x0, 0x2003536, 0x0, 0x2003538,\n\t0x0, 0x200353A, 0x0, 0x200353C, 0x0, 0x200353E, 0x0, 0x2003540, 0x0, 0x2003542, 0x0, 0x2003544, 0x0, 0x2003546, 0x0, 0x2003548,\n\t0x0, 0x200354A, 0x0, 0x200354C, 0x0, 0x200354E, 0x0, 0x2003550, 0x0, 0x2003552, 0x0, 0x2003554, 0x0, 0x2003556, 0x0, 0x2003558,\n\t0x0, 0x200355A, 0x0, 0x200355C, 0x0, 0x200355E, 0x0, 0x2003560, 0x0, 0x0, 0x2003562, 0x0, 0x2003564, 0x0, 0x2003566, 0x100017A,\n\t0x2003568, 0x0, 0x0, 0x200356A, 0x0, 0x200356C, 0x0, 0x0, 0x200356E, 0x0, 0x0, 0x0, 0x2003570, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x2003572, 0x0, 0x0, 0x2003574, 0x0, 0x0, 0x0, 0x2003576, 0x2003578, 0x0, 0x0, 0x0, 0x200357A, 0x0,\n\t0x0, 0x200357C, 0x0, 0x200357E, 0x0, 0x2003580, 0x0, 0x0, 0x2003582, 0x0, 0x0, 0x0, 0x0, 0x2003584, 0x0, 0x0,\n\t0x2003586, 0x0, 0x0, 0x0, 0x2003588, 0x0, 0x200358A, 0x0, 0x0, 0x200358C, 0x0, 0x0, 0x0, 0x200358E, 0x0, 0x2003590,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x2003592, 0x2003592, 0x0, 0x2003594, 0x2003594, 0x0, 0x2003596, 0x2003596, 0x0, 0x2003598, 0x0,\n\t0x200359A, 0x0, 0x200359C, 0x0, 0x200359E, 0x0, 0x20035A0, 0x0, 0x20035A2, 0x0, 0x20035A4, 0x0, 0x20035A6, 0x2001DEF, 0x0, 0x20035A8,\n\t0x0, 0x20035AA, 0x0, 0x20035AC, 0x0, 0x20035AE, 0x0, 0x20035B0, 0x0, 0x20035B2, 0x0, 0x20035B4, 0x0, 0x20035B6, 0x0, 0x20035B8,\n\t0x30035BA, 0x0, 0x20035BD, 0x20035BD, 0x0, 0x20035BF, 0x0, 0x0, 0x0, 0x20035C1, 0x0, 0x20035C3, 0x0, 0x20035C5, 0x0, 0x20035C7,\n\t0x0, 0x20035C9, 0x0, 0x20035CB, 0x0, 0x20035CD, 0x0, 0x20035CF, 0x0, 0x20035D1, 0x0, 0x20035D3, 0x0, 0x20035D5, 0x0, 0x20035D7,\n\t0x0, 0x20035D9, 0x0, 0x20035DB, 0x0, 0x20035DD, 0x0, 0x20035DF, 0x0, 0x20035E1, 0x0, 0x20035E3, 0x0, 0x20035E5, 0x0, 0x20035E7,\n\t0x0, 0x0, 0x0, 0x2001DF1, 0x0, 0x20035E9, 0x0, 0x20035EB, 0x0, 0x20035ED, 0x0, 0x20035EF, 0x0, 0x20035F1, 0x0, 0x20035F3,\n\t0x0, 0x20035F5, 0x0, 0x20035F7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20035F9, 0x0, 0x0, 0x30035FB,\n\t0x30035FE, 0x0, 0x2003601, 0x0, 0x0, 0x0, 0x0, 0x2003603, 0x0, 0x2003605, 0x0, 0x2003607, 0x0, 0x2003609, 0x0, 0x200360B,\n\t0x300360D, 0x3003610, 0x3003613, 0x2003616, 0x2003618, 0x0, 0x200361A, 0x200361C, 0x0, 0x200361E, 0x0, 0x2001EF3, 0x3003620, 0x0, 0x0, 0x0,\n\t0x2003623, 0x3003625, 0x0, 0x2003628, 0x0, 0x300362A, 0x300362D, 0x0, 0x2003630, 0x2003632, 0x0, 0x3003634, 0x3003637, 0x0, 0x0, 0x200363A,\n\t0x0, 0x300363C, 0x200363F, 0x0, 0x0, 0x2003641, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003643, 0x0, 0x0,\n\t0x2003646, 0x0, 0x0, 0x2003648, 0x0, 0x0, 0x0, 0x300364A, 0x200364D, 0x200364F, 0x2003651, 0x2003653, 0x2003655, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x2000267, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003657, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x2000339, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x200365A, 0x0, 0x200365C, 0x0, 0x0, 0x0, 0x200365E, 0x0, 0x0, 0x0, 0x2003660, 0x2003662, 0x2003664, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x6003666, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200366C, 0x200366E, 0x2003670, 0x2003672,\n\t0x6003674, 0x200032B, 0x200334E, 0x2001F07, 0x2003350, 0x2000331, 0x2003352, 0x2000335, 0x2001D95, 0x2000339, 0x2003354, 0x2003356, 0x2003358, 0x200335A, 0x200335C, 0x200033D,\n\t0x2001F09, 0x2000E35, 0x2001D97, 0x2001D97, 0x200335E, 0x2000341, 0x2003360, 0x2003362, 0x2003364, 0x2000345, 0x200367A, 0x200367C, 0x200367E, 0x2003680, 0x2003682, 0x0,\n\t0x200334E, 0x2001D95, 0x0, 0x0, 0x0, 0x2003360, 0x2001F09, 0x2003684, 0x0, 0x2003686, 0x0, 0x2003688, 0x0, 0x200337A, 0x0, 0x200368A,\n\t0x0, 0x200368C, 0x0, 0x200368E, 0x0, 0x2003690, 0x0, 0x2003692, 0x0, 0x2003694, 0x0, 0x2003696, 0x0, 0x2003698, 0x0, 0x200369A,\n\t0x2003354, 0x2000E35, 0x200369C, 0x200369E, 0x0, 0x2000331, 0x0, 0x0, 0x20036A0, 0x0, 0x0, 0x20036A2, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x20003D1, 0x20036A4, 0x20036A6, 0x2000389, 0x20036A8, 0x2000381, 0x20003C9, 0x20003F9, 0x2000395, 0x20036AA, 0x2000391, 0x20036AC, 0x20036AE, 0x20036B0, 0x2000411, 0x20036B2,\n\t0x20036B4, 0x20036B6, 0x20036B8, 0x2000399, 0x20036BA, 0x20036BC, 0x20036BE, 0x2000441, 0x20036C0, 0x20036C2, 0x20036C4, 0x2000449, 0x20036C6, 0x2000421, 0x20036C8, 0x20036CA,\n\t0x20036CC, 0x20036CE, 0x20036D0, 0x20036D2, 0x20036D4, 0x20036D6, 0x200038D, 0x20036D8, 0x20036DA, 0x20036DC, 0x20036DE, 0x20036E0, 0x20036E2, 0x20036E4, 0x20036E6, 0x20036E8,\n\t0x0, 0x20036EA, 0x0, 0x20036EC, 0x0, 0x20036EE, 0x0, 0x20036F0, 0x0, 0x20036F2, 0x0, 0x20036F4, 0x0, 0x20036F6, 0x0, 0x20036F8,\n\t0x0, 0x20036FA, 0x0, 0x20036FC, 0x0, 0x20003C1, 0x0, 0x20036FE, 0x0, 0x2003700, 0x0, 0x2003702, 0x0, 0x2003704, 0x0, 0x2003706,\n\t0x0, 0x2003708, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200370A, 0x0, 0x200370C, 0x0, 0x200370E,\n\t0x0, 0x2003710, 0x0, 0x2003712, 0x0, 0x2003714, 0x0, 0x2003716, 0x0, 0x2003718, 0x0, 0x200371A, 0x0, 0x200371C, 0x0, 0x200371E,\n\t0x0, 0x2003720, 0x0, 0x2003722, 0x0, 0x2003724, 0x0, 0x2003726, 0x0, 0x2003728, 0x0, 0x200372A, 0x0, 0x200372C, 0x0, 0x200372E,\n\t0x0, 0x2003730, 0x0, 0x2003732, 0x0, 0x2003734, 0x0, 0x2003736, 0x0, 0x2003738, 0x0, 0x200373A, 0x0, 0x200373C, 0x0, 0x200373E,\n\t0x0, 0x0, 0x2003740, 0x0, 0x2003742, 0x0, 0x2003744, 0x0, 0x2003746, 0x0, 0x2003748, 0x0, 0x200374A, 0x0, 0x200374C, 0x200374E,\n\t0x0, 0x2003750, 0x0, 0x2003752, 0x0, 0x2003754, 0x0, 0x2003756, 0x0, 0x20003E9, 0x0, 0x2003758, 0x0, 0x200375A, 0x0, 0x200375C,\n\t0x0, 0x200375E, 0x0, 0x2003760, 0x0, 0x2003762, 0x0, 0x2003764, 0x0, 0x2000419, 0x0, 0x2003766, 0x0, 0x2003768, 0x0, 0x200376A,\n\t0x0, 0x200376C, 0x0, 0x200376E, 0x0, 0x2003770, 0x0, 0x2003772, 0x0, 0x2003774, 0x0, 0x2003776, 0x0, 0x2003778, 0x0, 0x200377A,\n\t0x0, 0x200377C, 0x0, 0x200377E, 0x0, 0x2003780, 0x0, 0x2003782, 0x0, 0x2003784, 0x0, 0x2003786, 0x0, 0x2003788, 0x0, 0x200378A,\n\t0x0, 0x200378C, 0x0, 0x200378E, 0x0, 0x2003790, 0x0, 0x2003792, 0x0, 0x2003794, 0x0, 0x2003796, 0x0, 0x2003798, 0x0, 0x200379A,\n\t0x0, 0x200379C, 0x0, 0x200379E, 0x0, 0x20037A0, 0x0, 0x20037A2, 0x0, 0x20037A4, 0x0, 0x20037A6, 0x0, 0x20037A8, 0x0, 0x20037AA,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x20037AC, 0x20037AE, 0x20037B0, 0x20037B2, 0x20037B4, 0x20037B6, 0x20037B8, 0x20037BA, 0x20037BC, 0x20037BE, 0x20037C0, 0x20037C2, 0x20037C4, 0x20037C6, 0x20037C8,\n\t0x20037CA, 0x20037CC, 0x20037CE, 0x20037D0, 0x20037D2, 0x20037D4, 0x20037D6, 0x20037D8, 0x20037DA, 0x20037DC, 0x20037DE, 0x20037E0, 0x20037E2, 0x20037E4, 0x20037E6, 0x20037E8,\n\t0x20037EA, 0x20037EC, 0x20037EE, 0x20037F0, 0x20037F2, 0x20037F4, 0x20037F6, 0x40037F8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30037FC, 0x0, 0x0, 0x0, 0x30037FF, 0x0, 0x0,\n\t0x0, 0x3003802, 0x0, 0x3003805, 0x0, 0x3003808, 0x0, 0x300380B, 0x0, 0x300380E, 0x0, 0x3003811, 0x0, 0x3003814, 0x0, 0x3003817,\n\t0x0, 0x300381A, 0x0, 0x300381D, 0x0, 0x3003820, 0x0, 0x3003823, 0x0, 0x3003826, 0x0, 0x3003829, 0x0, 0x300382C, 0x0, 0x300382F,\n\t0x0, 0x3003832, 0x0, 0x3003835, 0x0, 0x3003838, 0x0, 0x300383B, 0x0, 0x300383E, 0x0, 0x3003841, 0x0, 0x3003844, 0x0, 0x3003847,\n\t0x0, 0x300384A, 0x0, 0x300384D, 0x0, 0x3003850, 0x0, 0x3003853, 0x0, 0x3003856, 0x0, 0x3003859, 0x0, 0x300385C, 0x0, 0x300385F,\n\t0x0, 0x3003862, 0x0, 0x3003865, 0x0, 0x3003868, 0x0, 0x300386B, 0x0, 0x300386E, 0x0, 0x3003871, 0x0, 0x3003874, 0x0, 0x3003877,\n\t0x0, 0x300387A, 0x0, 0x300387D, 0x0, 0x3003880, 0x0, 0x3003883, 0x0, 0x3003886, 0x0, 0x3003889, 0x0, 0x300388C, 0x0, 0x300388F,\n\t0x0, 0x3003892, 0x0, 0x3003895, 0x0, 0x3003898, 0x0, 0x300389B, 0x0, 0x300389E, 0x0, 0x30038A1, 0x0, 0x30038A4, 0x0, 0x30038A7,\n\t0x0, 0x30038AA, 0x0, 0x30038AD, 0x0, 0x30038B0, 0x0, 0x30038B3, 0x0, 0x30038B6, 0x0, 0x30038B9, 0x0, 0x30038BC, 0x0, 0x30038BF,\n\t0x0, 0x30038C2, 0x0, 0x30038C5, 0x0, 0x30038C8, 0x0, 0x30038CB, 0x0, 0x30038CE, 0x0, 0x30038D1, 0x0, 0x30038D4, 0x0, 0x30038D7,\n\t0x0, 0x30038DA, 0x0, 0x30038DD, 0x0, 0x30038E0, 0x30038E3, 0x30038E6, 0x30038E9, 0x30038EC, 0x30038EF, 0x3003892, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x30038F2, 0x0, 0x30038F5, 0x0, 0x30038F8, 0x0, 0x30038FB, 0x0, 0x30038FE, 0x0, 0x3003901, 0x0, 0x3003904, 0x0, 0x3003907,\n\t0x0, 0x300390A, 0x0, 0x300390D, 0x0, 0x3003910, 0x0, 0x3003913, 0x0, 0x3003916, 0x0, 0x3003919, 0x0, 0x300391C, 0x0, 0x300391F,\n\t0x0, 0x3003922, 0x0, 0x3003925, 0x0, 0x3003928, 0x0, 0x300392B, 0x0, 0x300392E, 0x0, 0x3003931, 0x0, 0x3003934, 0x0, 0x3003937,\n\t0x0, 0x300393A, 0x0, 0x300393D, 0x0, 0x3003940, 0x0, 0x3003943, 0x0, 0x3003946, 0x0, 0x3003949, 0x0, 0x300394C, 0x0, 0x300394F,\n\t0x0, 0x3003952, 0x0, 0x3003955, 0x0, 0x3003958, 0x0, 0x300395B, 0x0, 0x300395E, 0x0, 0x3003961, 0x0, 0x3003964, 0x0, 0x3003967,\n\t0x0, 0x300396A, 0x0, 0x300396D, 0x0, 0x3003970, 0x0, 0x3003973, 0x0, 0x3003976, 0x0, 0x3003979, 0x0, 0x300397C, 0x0, 0x300397F,\n\t0x3003982, 0x3003985, 0x3003988, 0x300398B, 0x300398E, 0x3003991, 0x3003994, 0x3003997, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x300399A, 0x300399D, 0x30039A0, 0x30039A3, 0x30039A6, 0x30039A9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x30039AC, 0x30039AF, 0x30039B2, 0x30039B5, 0x30039B8, 0x30039BB, 0x30039BE, 0x30039C1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x30039C4, 0x30039C7, 0x30039CA, 0x30039CD, 0x30039D0, 0x30039D3, 0x30039D6, 0x30039D9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x30039DC, 0x30039DF, 0x30039E2, 0x30039E5, 0x30039E8, 0x30039EB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x40039EE, 0x30039F2, 0x60039F5, 0x30039FB, 0x60039FE, 0x3003A04, 0x6003A07, 0x3003A0D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3003A10, 0x3003A13, 0x3003A16, 0x3003A19, 0x3003A1C, 0x3003A1F, 0x3003A22, 0x3003A25, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3003A28, 0x3003A2B, 0x3003A2E, 0x3003A31, 0x3003A34, 0x3003A37, 0x3003A3A, 0x3003A3D, 0x3003A40, 0x3003A43, 0x3003A46, 0x3003A49, 0x3003A4C, 0x3003A4F, 0x0, 0x0,\n\t0x5003A52, 0x5003A57, 0x5003A5C, 0x5003A61, 0x5003A66, 0x5003A6B, 0x5003A70, 0x5003A75, 0x5003A52, 0x5003A57, 0x5003A5C, 0x5003A61, 0x5003A66, 0x5003A6B, 0x5003A70, 0x5003A75,\n\t0x5003A7A, 0x5003A7F, 0x5003A84, 0x5003A89, 0x5003A8E, 0x5003A93, 0x5003A98, 0x5003A9D, 0x5003A7A, 0x5003A7F, 0x5003A84, 0x5003A89, 0x5003A8E, 0x5003A93, 0x5003A98, 0x5003A9D,\n\t0x5003AA2, 0x5003AA7, 0x5003AAC, 0x5003AB1, 0x5003AB6, 0x5003ABB, 0x5003AC0, 0x5003AC5, 0x5003AA2, 0x5003AA7, 0x5003AAC, 0x5003AB1, 0x5003AB6, 0x5003ABB, 0x5003AC0, 0x5003AC5,\n\t0x3003ACA, 0x3003ACD, 0x5003AD0, 0x4003AD5, 0x4003AD9, 0x0, 0x4003ADD, 0x6003AE1, 0x0, 0x0, 0x0, 0x0, 0x4003AD5, 0x0, 0x2000339, 0x0,\n\t0x0, 0x0, 0x5003AE7, 0x4003AEC, 0x4003AF0, 0x0, 0x4003AF4, 0x6003AF8, 0x0, 0x0, 0x0, 0x0, 0x4003AEC, 0x0, 0x0, 0x0,\n\t0x3003AFE, 0x3003B01, 0x6003B04, 0x6003666, 0x0, 0x0, 0x4003B0A, 0x6003B0E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3003B14, 0x3003B17, 0x6003B1A, 0x6003674, 0x4003B20, 0x3003B24, 0x4003B27, 0x6003B2B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x5003B31, 0x4003B36, 0x4003B3A, 0x0, 0x4003B3E, 0x6003B42, 0x0, 0x0, 0x0, 0x0, 0x4003B36, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003B48, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3003B4B, 0x3003B4E, 0x3003B51, 0x3003B54, 0x3003B57, 0x3003B5A, 0x3003B5D, 0x3003B60, 0x3003B63, 0x3003B66, 0x3003B69, 0x3003B6C, 0x3003B6F, 0x3003B72, 0x3003B75, 0x3003B78,\n\t0x0, 0x0, 0x0, 0x0, 0x3003B7B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3003B7E, 0x3003B81, 0x3003B84, 0x3003B87, 0x3003B8A, 0x3003B8D, 0x3003B90, 0x3003B93, 0x3003B96, 0x3003B99, 0x3003B9C, 0x3003B9F, 0x3003BA2, 0x3003BA5, 0x3003BA8, 0x3003BAB,\n\t0x3003BAE, 0x3003BB1, 0x3003BB4, 0x3003BB7, 0x3003BBA, 0x3003BBD, 0x3003BC0, 0x3003BC3, 0x3003BC6, 0x3003BC9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3003BCC, 0x3003BCF, 0x3003BD2, 0x3003BD5, 0x3003BD8, 0x3003BDB, 0x3003BDE, 0x3003BE1, 0x3003BE4, 0x3003BE7, 0x3003BEA, 0x3003BED, 0x3003BF0, 0x3003BF3, 0x3003BF6, 0x3003BF9,\n\t0x3003BFC, 0x3003BFF, 0x3003C02, 0x3003C05, 0x3003C08, 0x3003C0B, 0x3003C0E, 0x3003C11, 0x3003C14, 0x3003C17, 0x3003C1A, 0x3003C1D, 0x3003C20, 0x3003C23, 0x3003C26, 0x3003C29,\n\t0x3003C2C, 0x3003C2F, 0x3003C32, 0x3003C35, 0x3003C38, 0x3003C3B, 0x3003C3E, 0x3003C41, 0x3003C44, 0x3003C47, 0x3003C4A, 0x3003C4D, 0x3003C50, 0x3003C53, 0x3003C56, 0x0,\n\t0x0, 0x3003C59, 0x0, 0x0, 0x0, 0x2003C5C, 0x2003C5E, 0x0, 0x3003C60, 0x0, 0x3003C63, 0x0, 0x3003C66, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x3003C69, 0x0, 0x0, 0x3003C6C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x3003C6F, 0x0, 0x3003C72, 0x0, 0x3003C75, 0x0, 0x3003C78, 0x0, 0x3003C7B, 0x0, 0x3003C7E, 0x0, 0x3003C81, 0x0, 0x3003C84,\n\t0x0, 0x3003C87, 0x0, 0x3003C8A, 0x0, 0x3003C8D, 0x0, 0x3003C90, 0x0, 0x3003C93, 0x0, 0x3003C96, 0x0, 0x3003C99, 0x0, 0x3003C9C,\n\t0x0, 0x3003C9F, 0x0, 0x3003CA2, 0x0, 0x3003CA5, 0x0, 0x3003CA8, 0x0, 0x3003CAB, 0x0, 0x3003CAE, 0x0, 0x3003CB1, 0x0, 0x3003CB4,\n\t0x0, 0x3003CB7, 0x0, 0x3003CBA, 0x0, 0x3003CBD, 0x0, 0x3003CC0, 0x0, 0x3003CC3, 0x0, 0x3003CC6, 0x0, 0x3003CC9, 0x0, 0x3003CCC,\n\t0x0, 0x3003CCF, 0x0, 0x3003CD2, 0x0, 0x3003CD5, 0x0, 0x3003CD8, 0x0, 0x3003CDB, 0x0, 0x3003CDE, 0x0, 0x3003CE1, 0x0, 0x3003CE4,\n\t0x0, 0x3003CE7, 0x0, 0x3003CEA, 0x0, 0x3003CED, 0x0, 0x3003CF0, 0x0, 0x3003CF3, 0x0, 0x3003CF6, 0x0, 0x3003CF9, 0x0, 0x3003CFC,\n\t0x0, 0x3003CFF, 0x0, 0x3003D02, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003D05, 0x0, 0x3003D08, 0x0,\n\t0x0, 0x0, 0x0, 0x3003D0B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3003D0E, 0x3003D11, 0x3003D14, 0x3003D17, 0x3003D1A, 0x3003D1D, 0x3003D20, 0x3003D23, 0x3003D26, 0x3003D29, 0x3003D2C, 0x3003D2F, 0x3003D32, 0x3003D35, 0x3003D38, 0x3003D3B,\n\t0x3003D3E, 0x3003D41, 0x3003D44, 0x3003D47, 0x3003D4A, 0x3003D4D, 0x3003D50, 0x3003D53, 0x3003D56, 0x3003D59, 0x3003D5C, 0x3003D5F, 0x3003D62, 0x3003D65, 0x3003D68, 0x3003D6B,\n\t0x3003D6E, 0x3003D71, 0x3003D74, 0x3003D77, 0x3003D7A, 0x3003D7D, 0x0, 0x3003D80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003D83, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x3003D86, 0x0, 0x3003D89, 0x0, 0x3003D8C, 0x0, 0x3003D8F, 0x0, 0x3003D92, 0x0, 0x3003D95, 0x0, 0x3003D98, 0x0, 0x3003D9B,\n\t0x0, 0x3003D9E, 0x0, 0x3003DA1, 0x0, 0x3003DA4, 0x0, 0x3003DA7, 0x0, 0x3003DAA, 0x0, 0x3003DAD, 0x0, 0x3003DB0, 0x0, 0x3003DB3,\n\t0x0, 0x3003DB6, 0x0, 0x3003DB9, 0x0, 0x3003DBC, 0x0, 0x3003DBF, 0x0, 0x3003DC2, 0x0, 0x3003DC5, 0x0, 0x3003DC8, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x3003DCB, 0x0, 0x3003DCE, 0x0, 0x3003DD1, 0x0, 0x3003DD4, 0x0, 0x3003DD7, 0x0, 0x3003DDA, 0x0, 0x3003DDD, 0x0, 0x3003DE0,\n\t0x0, 0x3003DE3, 0x0, 0x3003DE6, 0x0, 0x3003DE9, 0x0, 0x3003DEC, 0x0, 0x3003DEF, 0x0, 0x3003DF2, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x3003DF5, 0x0, 0x3003DF8, 0x0, 0x3003DFB, 0x0, 0x3003DFE, 0x0, 0x3003E01, 0x0, 0x3003E04, 0x0, 0x3003E07,\n\t0x0, 0x0, 0x0, 0x3003E0A, 0x0, 0x3003E0D, 0x0, 0x3003E10, 0x0, 0x3003E13, 0x0, 0x3003E16, 0x0, 0x3003E19, 0x0, 0x3003E1C,\n\t0x0, 0x3003E1F, 0x0, 0x3003E22, 0x0, 0x3003E25, 0x0, 0x3003E28, 0x0, 0x3003E2B, 0x0, 0x3003E2E, 0x0, 0x3003E31, 0x0, 0x3003E34,\n\t0x0, 0x3003E37, 0x0, 0x3003E3A, 0x0, 0x3003E3D, 0x0, 0x3003E40, 0x0, 0x3003E43, 0x0, 0x3003E46, 0x0, 0x3003E49, 0x0, 0x3003E4C,\n\t0x0, 0x3003E4F, 0x0, 0x3003E52, 0x0, 0x3003E55, 0x0, 0x3003E58, 0x0, 0x3003E5B, 0x0, 0x3003E5E, 0x0, 0x3003E61, 0x0, 0x3003E64,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003E67, 0x0, 0x3003E6A, 0x0, 0x0, 0x3003E6D,\n\t0x0, 0x3003E70, 0x0, 0x3003E73, 0x0, 0x3003E76, 0x0, 0x3003E79, 0x0, 0x0, 0x0, 0x0, 0x3003E7C, 0x0, 0x0, 0x0,\n\t0x0, 0x3003E7F, 0x0, 0x3003E82, 0x0, 0x0, 0x0, 0x3003E85, 0x0, 0x3003E88, 0x0, 0x3003E8B, 0x0, 0x3003E8E, 0x0, 0x3003E91,\n\t0x0, 0x3003E94, 0x0, 0x3003E97, 0x0, 0x3003E9A, 0x0, 0x3003E9D, 0x0, 0x3003EA0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x2003EA3, 0x2003EA5, 0x2003EA7, 0x3003EA9, 0x3003EAC, 0x2003EAF, 0x2003EAF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x4003EB1, 0x4003EB5, 0x4003EB9, 0x4003EBD, 0x4003EC1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x3003EC5, 0x3003EC8, 0x3003ECB, 0x3003ECE, 0x3003ED1, 0x3003ED4, 0x3003ED7, 0x3003EDA, 0x3003EDD, 0x3003EE0, 0x3003EE3, 0x3003EE6, 0x3003EE9, 0x3003EEC, 0x3003EEF,\n\t0x3003EF2, 0x3003EF5, 0x3003EF8, 0x3003EFB, 0x3003EFE, 0x3003F01, 0x3003F04, 0x3003F07, 0x3003F0A, 0x3003F0D, 0x3003F10, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4003F13, 0x4003F17, 0x4003F1B, 0x4003F1F, 0x4003F23, 0x4003F27, 0x4003F2B, 0x4003F2F,\n\t0x4003F33, 0x4003F37, 0x4003F3B, 0x4003F3F, 0x4003F43, 0x4003F47, 0x4003F4B, 0x4003F4F, 0x4003F53, 0x4003F57, 0x4003F5B, 0x4003F5F, 0x4003F63, 0x4003F67, 0x4003F6B, 0x4003F6F,\n\t0x4003F73, 0x4003F77, 0x4003F7B, 0x4003F7F, 0x4003F83, 0x4003F87, 0x4003F8B, 0x4003F8F, 0x4003F93, 0x4003F97, 0x4003F9B, 0x4003F9F, 0x4003FA3, 0x4003FA7, 0x4003FAB, 0x4003FAF,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x4003FB3, 0x4003FB7, 0x4003FBB, 0x4003FBF, 0x4003FC3, 0x4003FC7, 0x4003FCB, 0x4003FCF, 0x4003FD3, 0x4003FD7, 0x4003FDB, 0x4003FDF, 0x4003FE3, 0x4003FE7, 0x4003FEB, 0x4003FEF,\n\t0x4003FF3, 0x4003FF7, 0x4003FFB, 0x4003FFF, 0x4004003, 0x4004007, 0x400400B, 0x400400F, 0x4004013, 0x4004017, 0x400401B, 0x400401F, 0x4004023, 0x4004027, 0x400402B, 0x400402F,\n};\nconst uint32_t* UppercaseDataPtr = UppercaseData;\n\nconst uint32_t LowercaseIndex1[272] = {\n\t0, 128, 256, 384, 360, 360, 360, 360, 360, 360, 512, 360, 360, 360, 360, 640,\n\t768, 896, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n};\nconst uint32_t* LowercaseIndex1Ptr = LowercaseIndex1;\n\nconst uint32_t LowercaseIndex2[1024] = {\n\t0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x40, 0x0, 0x60, 0x80, 0xA0, 0xC0, 0xE0, 0x100, 0x120, 0x140,\n\t0x160, 0x180, 0x1A0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1C0, 0x1E0, 0x200, 0x220, 0x240,\n\t0x260, 0x280, 0x0, 0x2A0, 0x2C0, 0x2E0, 0x300, 0x320, 0x340, 0x360, 0x380, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x3A0, 0x3C0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3E0, 0x400, 0x420, 0x440, 0x460, 0x480, 0x4A0, 0x4C0, 0x4E0, 0x500, 0x520, 0x540, 0x560, 0x580, 0x5A0, 0x5C0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5E0, 0x0, 0x600, 0x620, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x640, 0x660, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x680, 0x6A0, 0x0, 0x6C0, 0x6E0, 0x700, 0x720, 0x740, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x760, 0x780, 0x7A0, 0x0, 0x0, 0x0, 0x0, 0x7C0, 0x7E0, 0x800, 0x820, 0x840, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x860, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x880, 0x8A0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x8C0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n};\nconst uint32_t* LowercaseIndex2Ptr = LowercaseIndex2;\n\nconst uint32_t LowercaseData[2272] = {\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x100004E, 0x1000636, 0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x100007E,\n\t0x1000754, 0x1002068, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x2004033, 0x2004035, 0x2004037, 0x2004039, 0x200403B, 0x200403D, 0x2000247, 0x200403F, 0x2004041, 0x2004043, 0x2004045, 0x2004047, 0x2004049, 0x200404B, 0x200404D, 0x200404F,\n\t0x2001E1E, 0x2004051, 0x2004053, 0x2004055, 0x2004057, 0x2004059, 0x200405B, 0x0, 0x2000294, 0x200405D, 0x200405F, 0x2004061, 0x2004063, 0x2004065, 0x2004067, 0x0,\n\t0x2004069, 0x0, 0x200406B, 0x0, 0x200406D, 0x0, 0x200406F, 0x0, 0x2004071, 0x0, 0x2004073, 0x0, 0x2004075, 0x0, 0x2004077, 0x0,\n\t0x2004079, 0x0, 0x200407B, 0x0, 0x200407D, 0x0, 0x200407F, 0x0, 0x2004081, 0x0, 0x2004083, 0x0, 0x2004085, 0x0, 0x2004087, 0x0,\n\t0x2004089, 0x0, 0x200408B, 0x0, 0x200408D, 0x0, 0x2001EF8, 0x0, 0x200408F, 0x0, 0x2004091, 0x0, 0x2004093, 0x0, 0x2004095, 0x0,\n\t0x3004097, 0x0, 0x200409A, 0x0, 0x200409C, 0x0, 0x200409E, 0x0, 0x0, 0x20040A0, 0x0, 0x20040A2, 0x0, 0x20040A4, 0x0, 0x20040A6,\n\t0x0, 0x20040A8, 0x0, 0x20040AA, 0x0, 0x20040AC, 0x0, 0x20040AE, 0x0, 0x0, 0x2001E00, 0x0, 0x20040B0, 0x0, 0x20040B2, 0x0,\n\t0x20040B4, 0x0, 0x2002CE5, 0x0, 0x20040B6, 0x0, 0x20040B8, 0x0, 0x20040BA, 0x0, 0x20040BC, 0x0, 0x20040BE, 0x0, 0x20040C0, 0x0,\n\t0x20040C2, 0x0, 0x20040C4, 0x0, 0x20040C6, 0x0, 0x20040C8, 0x0, 0x20040CA, 0x0, 0x20040CC, 0x0, 0x20040CE, 0x0, 0x20040D0, 0x0,\n\t0x20040D2, 0x0, 0x20040D4, 0x0, 0x20040D6, 0x0, 0x20040D8, 0x0, 0x20040DA, 0x20040DC, 0x0, 0x20040DE, 0x0, 0x20040E0, 0x0, 0x0,\n\t0x0, 0x20040E2, 0x20040E4, 0x0, 0x20040E6, 0x0, 0x2001E02, 0x20040E8, 0x0, 0x20040EA, 0x20040EC, 0x20040EE, 0x0, 0x0, 0x20040F0, 0x2001DFA,\n\t0x2001DFC, 0x20040F2, 0x0, 0x20040F4, 0x2001D7D, 0x0, 0x2001E28, 0x2001E26, 0x20040F6, 0x0, 0x0, 0x0, 0x2001E0D, 0x2001E3C, 0x0, 0x2001E42,\n\t0x20040F8, 0x0, 0x20040FA, 0x0, 0x20040FC, 0x0, 0x20040FE, 0x2004100, 0x0, 0x2001E48, 0x0, 0x0, 0x2004102, 0x0, 0x2004104, 0x2004106,\n\t0x0, 0x2001E4E, 0x2001E53, 0x2004108, 0x0, 0x200410A, 0x0, 0x200026B, 0x200410C, 0x0, 0x0, 0x0, 0x200410E, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x2004110, 0x2004110, 0x0, 0x2004112, 0x2004112, 0x0, 0x2004114, 0x2004114, 0x0, 0x2004116, 0x0, 0x2004118,\n\t0x0, 0x200411A, 0x0, 0x200411C, 0x0, 0x200411E, 0x0, 0x2004120, 0x0, 0x2004122, 0x0, 0x2004124, 0x0, 0x0, 0x2004126, 0x0,\n\t0x2004128, 0x0, 0x200412A, 0x0, 0x200412C, 0x0, 0x200412E, 0x0, 0x2004130, 0x0, 0x2004132, 0x0, 0x2004134, 0x0, 0x2004136, 0x0,\n\t0x0, 0x2004138, 0x2004138, 0x0, 0x200413A, 0x0, 0x200413C, 0x200413E, 0x2004140, 0x0, 0x2004142, 0x0, 0x2004144, 0x0, 0x2004146, 0x0,\n\t0x2004148, 0x0, 0x200414A, 0x0, 0x200414C, 0x0, 0x200414E, 0x0, 0x2004150, 0x0, 0x2004152, 0x0, 0x2004154, 0x0, 0x2004156, 0x0,\n\t0x2004158, 0x0, 0x200415A, 0x0, 0x200415C, 0x0, 0x200415E, 0x0, 0x2004160, 0x0, 0x2004162, 0x0, 0x2004164, 0x0, 0x2004166, 0x0,\n\t0x2004168, 0x0, 0x200416A, 0x0, 0x200416C, 0x0, 0x200416E, 0x0, 0x2004170, 0x0, 0x2004172, 0x0, 0x2004174, 0x0, 0x2004176, 0x0,\n\t0x2004178, 0x0, 0x200417A, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300417C, 0x200417F, 0x0, 0x2004181, 0x3004183, 0x0,\n\t0x0, 0x2004186, 0x0, 0x2004188, 0x2001E4C, 0x2001E55, 0x200418A, 0x0, 0x200418C, 0x0, 0x200418E, 0x0, 0x2004190, 0x0, 0x2004192, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x2004194, 0x0, 0x2004196, 0x0, 0x0, 0x0, 0x2004198, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200419A,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200419C, 0x0, 0x200419E, 0x20041A0, 0x20041A2, 0x0, 0x20041A4, 0x0, 0x20041A6, 0x20041A8,\n\t0x0, 0x2000357, 0x2001D89, 0x2001E12, 0x2001E14, 0x200035B, 0x2003369, 0x200035F, 0x2001D8B, 0x2000349, 0x2001D91, 0x200336B, 0x2001D29, 0x200336D, 0x200336F, 0x200036D,\n\t0x2001D8F, 0x2000E17, 0x0, 0x2003371, 0x2003373, 0x2000367, 0x2001D8D, 0x2001E16, 0x2003375, 0x2000375, 0x20041AA, 0x20041AC, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20041AE,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20041B0, 0x0, 0x20041B2, 0x0, 0x200337C, 0x0, 0x20041B4, 0x0,\n\t0x20041B6, 0x0, 0x20041B8, 0x0, 0x20041BA, 0x0, 0x20041BC, 0x0, 0x20041BE, 0x0, 0x20041C0, 0x0, 0x20041C2, 0x0, 0x20041C4, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x2001D8B, 0x0, 0x0, 0x20041C6, 0x0, 0x20041C8, 0x20041CA, 0x0, 0x0, 0x20041CC, 0x20041CE, 0x20041D0,\n\t0x20041D2, 0x20041D4, 0x20041D6, 0x20041D8, 0x20041DA, 0x20041DC, 0x20003B1, 0x20041DE, 0x20041E0, 0x20041E2, 0x20041E4, 0x20041E6, 0x20041E8, 0x20041EA, 0x20041EC, 0x20041EE,\n\t0x20003D5, 0x20041F0, 0x20041F2, 0x20003AD, 0x20041F4, 0x20003A5, 0x20003CD, 0x20003FD, 0x20003A1, 0x20041F6, 0x20003B5, 0x20041F8, 0x20041FA, 0x2001E18, 0x2000415, 0x20041FC,\n\t0x20041FE, 0x2004200, 0x2004202, 0x20003BD, 0x2004204, 0x2004206, 0x2004208, 0x2000445, 0x200420A, 0x200420C, 0x2002CDC, 0x200044D, 0x2002CDE, 0x2000425, 0x200420E, 0x2004210,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x2004212, 0x0, 0x2004214, 0x0, 0x2004216, 0x0, 0x2004218, 0x0, 0x200421A, 0x0, 0x200421C, 0x0, 0x200421E, 0x0, 0x2004220, 0x0,\n\t0x2004222, 0x0, 0x2004224, 0x0, 0x20003C5, 0x0, 0x2004226, 0x0, 0x2004228, 0x0, 0x200422A, 0x0, 0x200422C, 0x0, 0x200422E, 0x0,\n\t0x2004230, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2004232, 0x0, 0x2004234, 0x0, 0x2004236, 0x0,\n\t0x2004238, 0x0, 0x200423A, 0x0, 0x200423C, 0x0, 0x200423E, 0x0, 0x2004240, 0x0, 0x2004242, 0x0, 0x2004244, 0x0, 0x2004246, 0x0,\n\t0x2004248, 0x0, 0x200424A, 0x0, 0x200424C, 0x0, 0x200424E, 0x0, 0x2004250, 0x0, 0x2004252, 0x0, 0x2004254, 0x0, 0x2004256, 0x0,\n\t0x2004258, 0x0, 0x200425A, 0x0, 0x200425C, 0x0, 0x200425E, 0x0, 0x2004260, 0x0, 0x2004262, 0x0, 0x2004264, 0x0, 0x2004266, 0x0,\n\t0x2004268, 0x200426A, 0x0, 0x200426C, 0x0, 0x200426E, 0x0, 0x2004270, 0x0, 0x2004272, 0x0, 0x2004274, 0x0, 0x2004276, 0x0, 0x0,\n\t0x2004278, 0x0, 0x200427A, 0x0, 0x200427C, 0x0, 0x200427E, 0x0, 0x20003ED, 0x0, 0x2004280, 0x0, 0x2004282, 0x0, 0x2004284, 0x0,\n\t0x2004286, 0x0, 0x2004288, 0x0, 0x200428A, 0x0, 0x200428C, 0x0, 0x200041D, 0x0, 0x200428E, 0x0, 0x2004290, 0x0, 0x2004292, 0x0,\n\t0x2004294, 0x0, 0x2004296, 0x0, 0x2004298, 0x0, 0x200429A, 0x0, 0x200429C, 0x0, 0x200429E, 0x0, 0x20042A0, 0x0, 0x20042A2, 0x0,\n\t0x20042A4, 0x0, 0x20042A6, 0x0, 0x20042A8, 0x0, 0x20042AA, 0x0, 0x20042AC, 0x0, 0x20042AE, 0x0, 0x20042B0, 0x0, 0x20042B2, 0x0,\n\t0x20042B4, 0x0, 0x20042B6, 0x0, 0x20042B8, 0x0, 0x20042BA, 0x0, 0x20042BC, 0x0, 0x20042BE, 0x0, 0x20042C0, 0x0, 0x20042C2, 0x0,\n\t0x20042C4, 0x0, 0x20042C6, 0x0, 0x20042C8, 0x0, 0x20042CA, 0x0, 0x20042CC, 0x0, 0x20042CE, 0x0, 0x20042D0, 0x0, 0x20042D2, 0x0,\n\t0x0, 0x20042D4, 0x20042D6, 0x20042D8, 0x20042DA, 0x2001D99, 0x20042DC, 0x20042DE, 0x20042E0, 0x20042E2, 0x20042E4, 0x2002D0A, 0x20042E6, 0x2002D12, 0x20042E8, 0x20042EA,\n\t0x20042EC, 0x20042EE, 0x20042F0, 0x20042F2, 0x2002D00, 0x20042F4, 0x2002D02, 0x20042F6, 0x20042F8, 0x20042FA, 0x20042FC, 0x20042FE, 0x2004300, 0x2004302, 0x2002D0C, 0x2004304,\n\t0x2004306, 0x2004308, 0x2001D9B, 0x200430A, 0x200430C, 0x200430E, 0x2004310, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3004312, 0x3004315, 0x3004318, 0x300431B, 0x300431E, 0x3004321, 0x3004324, 0x3004327, 0x300432A, 0x300432D, 0x3004330, 0x3004333, 0x3004336, 0x3004339, 0x300433C, 0x300433F,\n\t0x3004342, 0x3004345, 0x3004348, 0x300434B, 0x300434E, 0x3004351, 0x3004354, 0x3004357, 0x300435A, 0x300435D, 0x3004360, 0x3004363, 0x3004366, 0x3004369, 0x300436C, 0x300436F,\n\t0x3004372, 0x3004375, 0x3004378, 0x300437B, 0x300437E, 0x3004381, 0x0, 0x3004384, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004387, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x300438A, 0x0, 0x300438D, 0x0, 0x3004390, 0x0, 0x3004393, 0x0, 0x3004396, 0x0, 0x3004399, 0x0, 0x300439C, 0x0, 0x300439F, 0x0,\n\t0x30043A2, 0x0, 0x30043A5, 0x0, 0x30043A8, 0x0, 0x30043AB, 0x0, 0x30043AE, 0x0, 0x30043B1, 0x0, 0x30043B4, 0x0, 0x30043B7, 0x0,\n\t0x30043BA, 0x0, 0x30043BD, 0x0, 0x30043C0, 0x0, 0x30043C3, 0x0, 0x30043C6, 0x0, 0x30043C9, 0x0, 0x30043CC, 0x0, 0x30043CF, 0x0,\n\t0x30043D2, 0x0, 0x30043D5, 0x0, 0x30043D8, 0x0, 0x30043DB, 0x0, 0x30043DE, 0x0, 0x30043E1, 0x0, 0x30043E4, 0x0, 0x30043E7, 0x0,\n\t0x30043EA, 0x0, 0x30043ED, 0x0, 0x30043F0, 0x0, 0x30043F3, 0x0, 0x30043F6, 0x0, 0x30043F9, 0x0, 0x30043FC, 0x0, 0x30043FF, 0x0,\n\t0x3004402, 0x0, 0x3004405, 0x0, 0x3004408, 0x0, 0x300440B, 0x0, 0x300440E, 0x0, 0x3004411, 0x0, 0x3004414, 0x0, 0x3004417, 0x0,\n\t0x300441A, 0x0, 0x300441D, 0x0, 0x3004420, 0x0, 0x3004423, 0x0, 0x3004426, 0x0, 0x3004429, 0x0, 0x300442C, 0x0, 0x300442F, 0x0,\n\t0x3004432, 0x0, 0x3004435, 0x0, 0x3004438, 0x0, 0x300443B, 0x0, 0x300443E, 0x0, 0x3004441, 0x0, 0x3004444, 0x0, 0x3004447, 0x0,\n\t0x300444A, 0x0, 0x300444D, 0x0, 0x3004450, 0x0, 0x3004453, 0x0, 0x3004456, 0x0, 0x3004459, 0x0, 0x300445C, 0x0, 0x300445F, 0x0,\n\t0x3004462, 0x0, 0x3004465, 0x0, 0x3004468, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200446B, 0x0,\n\t0x300446D, 0x0, 0x3004470, 0x0, 0x3004473, 0x0, 0x3004476, 0x0, 0x3004479, 0x0, 0x300447C, 0x0, 0x300447F, 0x0, 0x3004482, 0x0,\n\t0x3004485, 0x0, 0x3004488, 0x0, 0x300448B, 0x0, 0x300448E, 0x0, 0x3004491, 0x0, 0x3004494, 0x0, 0x3004497, 0x0, 0x300449A, 0x0,\n\t0x300449D, 0x0, 0x30044A0, 0x0, 0x30044A3, 0x0, 0x30044A6, 0x0, 0x30044A9, 0x0, 0x30044AC, 0x0, 0x30044AF, 0x0, 0x30044B2, 0x0,\n\t0x30044B5, 0x0, 0x30044B8, 0x0, 0x30044BB, 0x0, 0x30044BE, 0x0, 0x30044C1, 0x0, 0x30044C4, 0x0, 0x30044C7, 0x0, 0x30044CA, 0x0,\n\t0x30044CD, 0x0, 0x30044D0, 0x0, 0x30044D3, 0x0, 0x30044D6, 0x0, 0x30044D9, 0x0, 0x30044DC, 0x0, 0x30044DF, 0x0, 0x30044E2, 0x0,\n\t0x30044E5, 0x0, 0x30044E8, 0x0, 0x30044EB, 0x0, 0x30044EE, 0x0, 0x30044F1, 0x0, 0x30044F4, 0x0, 0x30044F7, 0x0, 0x30044FA, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30044FD, 0x3004500, 0x3004503, 0x3004506, 0x3004509, 0x300450C, 0x300450F, 0x3004512,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004515, 0x3004518, 0x300451B, 0x300451E, 0x3004521, 0x3004524, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004527, 0x300452A, 0x300452D, 0x3004530, 0x3004533, 0x3004536, 0x3004539, 0x300453C,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300453F, 0x3004542, 0x3004545, 0x3004548, 0x300454B, 0x300454E, 0x3004551, 0x3004554,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004557, 0x300455A, 0x300455D, 0x3004560, 0x3004563, 0x3004566, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004569, 0x0, 0x300456C, 0x0, 0x300456F, 0x0, 0x3004572,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004575, 0x3004578, 0x300457B, 0x300457E, 0x3004581, 0x3004584, 0x3004587, 0x300458A,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300458D, 0x3004590, 0x3004593, 0x3004596, 0x3004599, 0x300459C, 0x300459F, 0x30045A2,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30045A5, 0x30045A8, 0x30045AB, 0x30045AE, 0x30045B1, 0x30045B4, 0x30045B7, 0x30045BA,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30045BD, 0x30045C0, 0x30045C3, 0x30045C6, 0x30045C9, 0x30045CC, 0x30045CF, 0x30045D2,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30045D5, 0x30045D8, 0x30045DB, 0x30045DE, 0x30045E1, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30045E4, 0x30045E7, 0x30045EA, 0x30045ED, 0x30045F0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30045F3, 0x30045F6, 0x30045F9, 0x30045FC, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30045FF, 0x3004602, 0x3004605, 0x3004608, 0x300460B, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300460E, 0x3004611, 0x3004614, 0x3004617, 0x300461A, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2000375, 0x0, 0x0, 0x0, 0x100012F, 0x200403D, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x300461D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3004620, 0x3004623, 0x3004626, 0x3004629, 0x300462C, 0x300462F, 0x3004632, 0x3004635, 0x3004638, 0x300463B, 0x300463E, 0x3004641, 0x3004644, 0x3004647, 0x300464A, 0x300464D,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x3004650, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004653, 0x3004656, 0x3004659, 0x300465C, 0x300465F, 0x3004662, 0x3004665, 0x3004668, 0x300466B, 0x300466E,\n\t0x3004671, 0x3004674, 0x3004677, 0x300467A, 0x300467D, 0x3004680, 0x3004683, 0x3004686, 0x3004689, 0x300468C, 0x300468F, 0x3004692, 0x3004695, 0x3004698, 0x300469B, 0x300469E,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x30046A1, 0x30046A4, 0x30046A7, 0x30046AA, 0x30046AD, 0x30046B0, 0x30046B3, 0x30046B6, 0x30046B9, 0x30046BC, 0x30046BF, 0x30046C2, 0x30046C5, 0x30046C8, 0x30046CB, 0x30046CE,\n\t0x30046D1, 0x30046D4, 0x30046D7, 0x30046DA, 0x30046DD, 0x30046E0, 0x30046E3, 0x30046E6, 0x30046E9, 0x30046EC, 0x30046EF, 0x30046F2, 0x30046F5, 0x30046F8, 0x30046FB, 0x30046FE,\n\t0x3004701, 0x3004704, 0x3004707, 0x300470A, 0x300470D, 0x3004710, 0x3004713, 0x3004716, 0x3004719, 0x300471C, 0x300471F, 0x3004722, 0x3004725, 0x3004728, 0x300472B, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x300472E, 0x0, 0x2002CED, 0x3004731, 0x2004734, 0x0, 0x0, 0x3004736, 0x0, 0x3004739, 0x0, 0x300473C, 0x0, 0x2001DF5, 0x2001E38, 0x2001DF3,\n\t0x2001E1A, 0x0, 0x300473F, 0x0, 0x0, 0x3004742, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2004745, 0x2004747,\n\t0x3004749, 0x0, 0x300474C, 0x0, 0x300474F, 0x0, 0x3004752, 0x0, 0x3004755, 0x0, 0x3004758, 0x0, 0x300475B, 0x0, 0x300475E, 0x0,\n\t0x3004761, 0x0, 0x3004764, 0x0, 0x3004767, 0x0, 0x300476A, 0x0, 0x300476D, 0x0, 0x3004770, 0x0, 0x3004773, 0x0, 0x3004776, 0x0,\n\t0x3004779, 0x0, 0x300477C, 0x0, 0x300477F, 0x0, 0x3004782, 0x0, 0x3004785, 0x0, 0x3004788, 0x0, 0x300478B, 0x0, 0x300478E, 0x0,\n\t0x3004791, 0x0, 0x3004794, 0x0, 0x3004797, 0x0, 0x300479A, 0x0, 0x300479D, 0x0, 0x30047A0, 0x0, 0x30047A3, 0x0, 0x30047A6, 0x0,\n\t0x30047A9, 0x0, 0x30047AC, 0x0, 0x30047AF, 0x0, 0x30047B2, 0x0, 0x30047B5, 0x0, 0x30047B8, 0x0, 0x30047BB, 0x0, 0x30047BE, 0x0,\n\t0x30047C1, 0x0, 0x30047C4, 0x0, 0x30047C7, 0x0, 0x30047CA, 0x0, 0x30047CD, 0x0, 0x30047D0, 0x0, 0x30047D3, 0x0, 0x30047D6, 0x0,\n\t0x30047D9, 0x0, 0x30047DC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30047DF, 0x0, 0x30047E2, 0x0, 0x0,\n\t0x0, 0x0, 0x30047E5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x30047E8, 0x0, 0x30047EB, 0x0, 0x30047EE, 0x0, 0x30047F1, 0x0, 0x30047F4, 0x0, 0x30047F7, 0x0, 0x30047FA, 0x0, 0x30047FD, 0x0,\n\t0x3004800, 0x0, 0x3004803, 0x0, 0x3004806, 0x0, 0x3004809, 0x0, 0x300480C, 0x0, 0x300480F, 0x0, 0x3004812, 0x0, 0x3004815, 0x0,\n\t0x3004818, 0x0, 0x300481B, 0x0, 0x300481E, 0x0, 0x3004821, 0x0, 0x3004824, 0x0, 0x3004827, 0x0, 0x300482A, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x300482D, 0x0, 0x3004830, 0x0, 0x3004833, 0x0, 0x3004836, 0x0, 0x3004839, 0x0, 0x300483C, 0x0, 0x300483F, 0x0, 0x3004842, 0x0,\n\t0x3004845, 0x0, 0x3004848, 0x0, 0x300484B, 0x0, 0x300484E, 0x0, 0x3004851, 0x0, 0x3004854, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x3004857, 0x0, 0x300485A, 0x0, 0x3002CE7, 0x0, 0x300485D, 0x0, 0x3004860, 0x0, 0x3004863, 0x0, 0x3004866, 0x0,\n\t0x0, 0x0, 0x3004869, 0x0, 0x300486C, 0x0, 0x300486F, 0x0, 0x3004872, 0x0, 0x3004875, 0x0, 0x3004878, 0x0, 0x300487B, 0x0,\n\t0x300487E, 0x0, 0x3004881, 0x0, 0x3004884, 0x0, 0x3004887, 0x0, 0x300488A, 0x0, 0x300488D, 0x0, 0x3004890, 0x0, 0x3004893, 0x0,\n\t0x3004896, 0x0, 0x3004899, 0x0, 0x300489C, 0x0, 0x300489F, 0x0, 0x30048A2, 0x0, 0x30048A5, 0x0, 0x30048A8, 0x0, 0x30048AB, 0x0,\n\t0x30048AE, 0x0, 0x30048B1, 0x0, 0x30048B4, 0x0, 0x30048B7, 0x0, 0x30048BA, 0x0, 0x30048BD, 0x0, 0x30048C0, 0x0, 0x3002CE0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30048C3, 0x0, 0x30048C6, 0x0, 0x30048C9, 0x30048CC, 0x0,\n\t0x30048CF, 0x0, 0x30048D2, 0x0, 0x30048D5, 0x0, 0x30048D8, 0x0, 0x0, 0x0, 0x0, 0x30048DB, 0x0, 0x2001E24, 0x0, 0x0,\n\t0x30048DE, 0x0, 0x30048E1, 0x0, 0x0, 0x0, 0x30048E4, 0x0, 0x30048E7, 0x0, 0x30048EA, 0x0, 0x30048ED, 0x0, 0x30048F0, 0x0,\n\t0x30048F3, 0x0, 0x30048F6, 0x0, 0x30048F9, 0x0, 0x30048FC, 0x0, 0x30048FF, 0x0, 0x2001D63, 0x2001DFE, 0x2001E22, 0x2004902, 0x0, 0x0,\n\t0x2004904, 0x2004906, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x3004908, 0x300490B, 0x300490E, 0x3004911, 0x3004914, 0x3004917, 0x300491A, 0x300491D, 0x3004920, 0x3004923, 0x3004926, 0x3004929, 0x300492C, 0x300492F, 0x3004932,\n\t0x3004935, 0x3004938, 0x300493B, 0x300493E, 0x3004941, 0x3004944, 0x3004947, 0x300494A, 0x300494D, 0x3004950, 0x3004953, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x4004956, 0x400495A, 0x400495E, 0x4004962, 0x4004966, 0x400496A, 0x400496E, 0x4004972, 0x4004976, 0x400497A, 0x400497E, 0x4004982, 0x4004986, 0x400498A, 0x400498E, 0x4004992,\n\t0x4004996, 0x400499A, 0x400499E, 0x40049A2, 0x40049A6, 0x40049AA, 0x40049AE, 0x40049B2, 0x40049B6, 0x40049BA, 0x40049BE, 0x40049C2, 0x40049C6, 0x40049CA, 0x40049CE, 0x40049D2,\n\t0x40049D6, 0x40049DA, 0x40049DE, 0x40049E2, 0x40049E6, 0x40049EA, 0x40049EE, 0x40049F2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x40049F6, 0x40049FA, 0x40049FE, 0x4004A02, 0x4004A06, 0x4004A0A, 0x4004A0E, 0x4004A12, 0x4004A16, 0x4004A1A, 0x4004A1E, 0x4004A22, 0x4004A26, 0x4004A2A, 0x4004A2E, 0x4004A32,\n\t0x4004A36, 0x4004A3A, 0x4004A3E, 0x4004A42, 0x4004A46, 0x4004A4A, 0x4004A4E, 0x4004A52, 0x4004A56, 0x4004A5A, 0x4004A5E, 0x4004A62, 0x4004A66, 0x4004A6A, 0x4004A6E, 0x4004A72,\n};\nconst uint32_t* LowercaseDataPtr = LowercaseData;\n\nconst uint32_t TitlecaseIndex1[272] = {\n\t0, 128, 256, 45, 45, 45, 45, 45, 45, 45, 384, 45, 45, 45, 45, 512,\n\t640, 768, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n\t45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\n};\nconst uint32_t* TitlecaseIndex1Ptr = TitlecaseIndex1;\n\nconst uint32_t TitlecaseIndex2[896] = {\n\t0x0, 0x0, 0x0, 0x20, 0x0, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0, 0x100, 0x120, 0x140, 0x160, 0x180,\n\t0x1A0, 0x1C0, 0x1E0, 0x200, 0x220, 0x0, 0x0, 0x0, 0x0, 0x0, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,\n\t0x0, 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0x400, 0x0, 0x420, 0x440, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x460, 0x0, 0x0, 0x0, 0x0,\n\t0x480, 0x4A0, 0x4C0, 0x4E0, 0x500, 0x520, 0x540, 0x560, 0x580, 0x5A0, 0x5C0, 0x5E0, 0x600, 0x620, 0x640, 0x660,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x680, 0x6A0, 0x6C0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6E0, 0x700, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x720, 0x740, 0x760, 0x780, 0x7A0, 0x7C0, 0x7E0, 0x800, 0x820, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x840, 0x860, 0x880, 0x0, 0x0, 0x0, 0x0, 0x8A0, 0x8C0, 0x8E0, 0x900, 0x920, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x940, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x960, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x980, 0x9A0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9C0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n};\nconst uint32_t* TitlecaseIndex2Ptr = TitlecaseIndex2;\n\nconst uint32_t TitlecaseData[2528] = {\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x1000000, 0x1000633, 0x1000012, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x1000105, 0x1000021, 0x1000126, 0x100012C, 0x1000132, 0x10006FF, 0x100002D, 0x1000030,\n\t0x1000751, 0x1001EFC, 0x1000168, 0x100017A, 0x1000192, 0x100003F, 0x10007E1, 0x10001C2, 0x100080B, 0x100004B, 0x10001D1, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x2003358, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2004A76,\n\t0x20034B3, 0x20034B5, 0x20034B7, 0x20034B9, 0x20034BB, 0x20034BD, 0x2000243, 0x20034BF, 0x20034C1, 0x20034C3, 0x20034C5, 0x20034C7, 0x20034C9, 0x20034CB, 0x20034CD, 0x20034CF,\n\t0x20034D1, 0x20034D3, 0x20034D5, 0x20034D7, 0x20034D9, 0x20034DB, 0x20034DD, 0x0, 0x2000290, 0x20034DF, 0x20034E1, 0x20034E3, 0x20034E5, 0x20034E7, 0x20034E9, 0x20034EB,\n\t0x0, 0x20034ED, 0x0, 0x20034EF, 0x0, 0x20034F1, 0x0, 0x20034F3, 0x0, 0x20034F5, 0x0, 0x20034F7, 0x0, 0x20034F9, 0x0, 0x20034FB,\n\t0x0, 0x20034FD, 0x0, 0x20034FF, 0x0, 0x2003501, 0x0, 0x2003503, 0x0, 0x2003505, 0x0, 0x2003507, 0x0, 0x2003509, 0x0, 0x200350B,\n\t0x0, 0x200350D, 0x0, 0x200350F, 0x0, 0x2003511, 0x0, 0x2002CE3, 0x0, 0x2003513, 0x0, 0x2003515, 0x0, 0x2003517, 0x0, 0x2003519,\n\t0x0, 0x1000021, 0x0, 0x200351B, 0x0, 0x200351D, 0x0, 0x200351F, 0x0, 0x0, 0x2003521, 0x0, 0x2003523, 0x0, 0x2003525, 0x0,\n\t0x2003527, 0x0, 0x2003529, 0x0, 0x200352B, 0x0, 0x200352D, 0x0, 0x200352F, 0x3003531, 0x0, 0x2003534, 0x0, 0x2003536, 0x0, 0x2003538,\n\t0x0, 0x200353A, 0x0, 0x200353C, 0x0, 0x200353E, 0x0, 0x2003540, 0x0, 0x2003542, 0x0, 0x2003544, 0x0, 0x2003546, 0x0, 0x2003548,\n\t0x0, 0x200354A, 0x0, 0x200354C, 0x0, 0x200354E, 0x0, 0x2003550, 0x0, 0x2003552, 0x0, 0x2003554, 0x0, 0x2003556, 0x0, 0x2003558,\n\t0x0, 0x200355A, 0x0, 0x200355C, 0x0, 0x200355E, 0x0, 0x2003560, 0x0, 0x0, 0x2003562, 0x0, 0x2003564, 0x0, 0x2003566, 0x100017A,\n\t0x2003568, 0x0, 0x0, 0x200356A, 0x0, 0x200356C, 0x0, 0x0, 0x200356E, 0x0, 0x0, 0x0, 0x2003570, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x2003572, 0x0, 0x0, 0x2003574, 0x0, 0x0, 0x0, 0x2003576, 0x2003578, 0x0, 0x0, 0x0, 0x200357A, 0x0,\n\t0x0, 0x200357C, 0x0, 0x200357E, 0x0, 0x2003580, 0x0, 0x0, 0x2003582, 0x0, 0x0, 0x0, 0x0, 0x2003584, 0x0, 0x0,\n\t0x2003586, 0x0, 0x0, 0x0, 0x2003588, 0x0, 0x200358A, 0x0, 0x0, 0x200358C, 0x0, 0x0, 0x0, 0x200358E, 0x0, 0x2003590,\n\t0x0, 0x0, 0x0, 0x0, 0x2004A78, 0x0, 0x2004A78, 0x2004A7A, 0x0, 0x2004A7A, 0x2004A7C, 0x0, 0x2004A7C, 0x0, 0x2003598, 0x0,\n\t0x200359A, 0x0, 0x200359C, 0x0, 0x200359E, 0x0, 0x20035A0, 0x0, 0x20035A2, 0x0, 0x20035A4, 0x0, 0x20035A6, 0x2001DEF, 0x0, 0x20035A8,\n\t0x0, 0x20035AA, 0x0, 0x20035AC, 0x0, 0x20035AE, 0x0, 0x20035B0, 0x0, 0x20035B2, 0x0, 0x20035B4, 0x0, 0x20035B6, 0x0, 0x20035B8,\n\t0x30035BA, 0x2004A7E, 0x0, 0x2004A7E, 0x0, 0x20035BF, 0x0, 0x0, 0x0, 0x20035C1, 0x0, 0x20035C3, 0x0, 0x20035C5, 0x0, 0x20035C7,\n\t0x0, 0x20035C9, 0x0, 0x20035CB, 0x0, 0x20035CD, 0x0, 0x20035CF, 0x0, 0x20035D1, 0x0, 0x20035D3, 0x0, 0x20035D5, 0x0, 0x20035D7,\n\t0x0, 0x20035D9, 0x0, 0x20035DB, 0x0, 0x20035DD, 0x0, 0x20035DF, 0x0, 0x20035E1, 0x0, 0x20035E3, 0x0, 0x20035E5, 0x0, 0x20035E7,\n\t0x0, 0x0, 0x0, 0x2001DF1, 0x0, 0x20035E9, 0x0, 0x20035EB, 0x0, 0x20035ED, 0x0, 0x20035EF, 0x0, 0x20035F1, 0x0, 0x20035F3,\n\t0x0, 0x20035F5, 0x0, 0x20035F7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20035F9, 0x0, 0x0, 0x30035FB,\n\t0x30035FE, 0x0, 0x2003601, 0x0, 0x0, 0x0, 0x0, 0x2003603, 0x0, 0x2003605, 0x0, 0x2003607, 0x0, 0x2003609, 0x0, 0x200360B,\n\t0x300360D, 0x3003610, 0x3003613, 0x2003616, 0x2003618, 0x0, 0x200361A, 0x200361C, 0x0, 0x200361E, 0x0, 0x2001EF3, 0x3003620, 0x0, 0x0, 0x0,\n\t0x2003623, 0x3003625, 0x0, 0x2003628, 0x0, 0x300362A, 0x300362D, 0x0, 0x2003630, 0x2003632, 0x0, 0x3003634, 0x3003637, 0x0, 0x0, 0x200363A,\n\t0x0, 0x300363C, 0x200363F, 0x0, 0x0, 0x2003641, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003643, 0x0, 0x0,\n\t0x2003646, 0x0, 0x0, 0x2003648, 0x0, 0x0, 0x0, 0x300364A, 0x200364D, 0x200364F, 0x2003651, 0x2003653, 0x2003655, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x2000267, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003657, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x2000339, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x200365A, 0x0, 0x200365C, 0x0, 0x0, 0x0, 0x200365E, 0x0, 0x0, 0x0, 0x2003660, 0x2003662, 0x2003664, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x6003666, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200366C, 0x200366E, 0x2003670, 0x2003672,\n\t0x6003674, 0x200032B, 0x200334E, 0x2001F07, 0x2003350, 0x2000331, 0x2003352, 0x2000335, 0x2001D95, 0x2000339, 0x2003354, 0x2003356, 0x2003358, 0x200335A, 0x200335C, 0x200033D,\n\t0x2001F09, 0x2000E35, 0x2001D97, 0x2001D97, 0x200335E, 0x2000341, 0x2003360, 0x2003362, 0x2003364, 0x2000345, 0x200367A, 0x200367C, 0x200367E, 0x2003680, 0x2003682, 0x0,\n\t0x200334E, 0x2001D95, 0x0, 0x0, 0x0, 0x2003360, 0x2001F09, 0x2003684, 0x0, 0x2003686, 0x0, 0x2003688, 0x0, 0x200337A, 0x0, 0x200368A,\n\t0x0, 0x200368C, 0x0, 0x200368E, 0x0, 0x2003690, 0x0, 0x2003692, 0x0, 0x2003694, 0x0, 0x2003696, 0x0, 0x2003698, 0x0, 0x200369A,\n\t0x2003354, 0x2000E35, 0x200369C, 0x200369E, 0x0, 0x2000331, 0x0, 0x0, 0x20036A0, 0x0, 0x0, 0x20036A2, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x20003D1, 0x20036A4, 0x20036A6, 0x2000389, 0x20036A8, 0x2000381, 0x20003C9, 0x20003F9, 0x2000395, 0x20036AA, 0x2000391, 0x20036AC, 0x20036AE, 0x20036B0, 0x2000411, 0x20036B2,\n\t0x20036B4, 0x20036B6, 0x20036B8, 0x2000399, 0x20036BA, 0x20036BC, 0x20036BE, 0x2000441, 0x20036C0, 0x20036C2, 0x20036C4, 0x2000449, 0x20036C6, 0x2000421, 0x20036C8, 0x20036CA,\n\t0x20036CC, 0x20036CE, 0x20036D0, 0x20036D2, 0x20036D4, 0x20036D6, 0x200038D, 0x20036D8, 0x20036DA, 0x20036DC, 0x20036DE, 0x20036E0, 0x20036E2, 0x20036E4, 0x20036E6, 0x20036E8,\n\t0x0, 0x20036EA, 0x0, 0x20036EC, 0x0, 0x20036EE, 0x0, 0x20036F0, 0x0, 0x20036F2, 0x0, 0x20036F4, 0x0, 0x20036F6, 0x0, 0x20036F8,\n\t0x0, 0x20036FA, 0x0, 0x20036FC, 0x0, 0x20003C1, 0x0, 0x20036FE, 0x0, 0x2003700, 0x0, 0x2003702, 0x0, 0x2003704, 0x0, 0x2003706,\n\t0x0, 0x2003708, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200370A, 0x0, 0x200370C, 0x0, 0x200370E,\n\t0x0, 0x2003710, 0x0, 0x2003712, 0x0, 0x2003714, 0x0, 0x2003716, 0x0, 0x2003718, 0x0, 0x200371A, 0x0, 0x200371C, 0x0, 0x200371E,\n\t0x0, 0x2003720, 0x0, 0x2003722, 0x0, 0x2003724, 0x0, 0x2003726, 0x0, 0x2003728, 0x0, 0x200372A, 0x0, 0x200372C, 0x0, 0x200372E,\n\t0x0, 0x2003730, 0x0, 0x2003732, 0x0, 0x2003734, 0x0, 0x2003736, 0x0, 0x2003738, 0x0, 0x200373A, 0x0, 0x200373C, 0x0, 0x200373E,\n\t0x0, 0x0, 0x2003740, 0x0, 0x2003742, 0x0, 0x2003744, 0x0, 0x2003746, 0x0, 0x2003748, 0x0, 0x200374A, 0x0, 0x200374C, 0x200374E,\n\t0x0, 0x2003750, 0x0, 0x2003752, 0x0, 0x2003754, 0x0, 0x2003756, 0x0, 0x20003E9, 0x0, 0x2003758, 0x0, 0x200375A, 0x0, 0x200375C,\n\t0x0, 0x200375E, 0x0, 0x2003760, 0x0, 0x2003762, 0x0, 0x2003764, 0x0, 0x2000419, 0x0, 0x2003766, 0x0, 0x2003768, 0x0, 0x200376A,\n\t0x0, 0x200376C, 0x0, 0x200376E, 0x0, 0x2003770, 0x0, 0x2003772, 0x0, 0x2003774, 0x0, 0x2003776, 0x0, 0x2003778, 0x0, 0x200377A,\n\t0x0, 0x200377C, 0x0, 0x200377E, 0x0, 0x2003780, 0x0, 0x2003782, 0x0, 0x2003784, 0x0, 0x2003786, 0x0, 0x2003788, 0x0, 0x200378A,\n\t0x0, 0x200378C, 0x0, 0x200378E, 0x0, 0x2003790, 0x0, 0x2003792, 0x0, 0x2003794, 0x0, 0x2003796, 0x0, 0x2003798, 0x0, 0x200379A,\n\t0x0, 0x200379C, 0x0, 0x200379E, 0x0, 0x20037A0, 0x0, 0x20037A2, 0x0, 0x20037A4, 0x0, 0x20037A6, 0x0, 0x20037A8, 0x0, 0x20037AA,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x20037AC, 0x20037AE, 0x20037B0, 0x20037B2, 0x20037B4, 0x20037B6, 0x20037B8, 0x20037BA, 0x20037BC, 0x20037BE, 0x20037C0, 0x20037C2, 0x20037C4, 0x20037C6, 0x20037C8,\n\t0x20037CA, 0x20037CC, 0x20037CE, 0x20037D0, 0x20037D2, 0x20037D4, 0x20037D6, 0x20037D8, 0x20037DA, 0x20037DC, 0x20037DE, 0x20037E0, 0x20037E2, 0x20037E4, 0x20037E6, 0x20037E8,\n\t0x20037EA, 0x20037EC, 0x20037EE, 0x20037F0, 0x20037F2, 0x20037F4, 0x20037F6, 0x4004A80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30037FC, 0x0, 0x0, 0x0, 0x30037FF, 0x0, 0x0,\n\t0x0, 0x3003802, 0x0, 0x3003805, 0x0, 0x3003808, 0x0, 0x300380B, 0x0, 0x300380E, 0x0, 0x3003811, 0x0, 0x3003814, 0x0, 0x3003817,\n\t0x0, 0x300381A, 0x0, 0x300381D, 0x0, 0x3003820, 0x0, 0x3003823, 0x0, 0x3003826, 0x0, 0x3003829, 0x0, 0x300382C, 0x0, 0x300382F,\n\t0x0, 0x3003832, 0x0, 0x3003835, 0x0, 0x3003838, 0x0, 0x300383B, 0x0, 0x300383E, 0x0, 0x3003841, 0x0, 0x3003844, 0x0, 0x3003847,\n\t0x0, 0x300384A, 0x0, 0x300384D, 0x0, 0x3003850, 0x0, 0x3003853, 0x0, 0x3003856, 0x0, 0x3003859, 0x0, 0x300385C, 0x0, 0x300385F,\n\t0x0, 0x3003862, 0x0, 0x3003865, 0x0, 0x3003868, 0x0, 0x300386B, 0x0, 0x300386E, 0x0, 0x3003871, 0x0, 0x3003874, 0x0, 0x3003877,\n\t0x0, 0x300387A, 0x0, 0x300387D, 0x0, 0x3003880, 0x0, 0x3003883, 0x0, 0x3003886, 0x0, 0x3003889, 0x0, 0x300388C, 0x0, 0x300388F,\n\t0x0, 0x3003892, 0x0, 0x3003895, 0x0, 0x3003898, 0x0, 0x300389B, 0x0, 0x300389E, 0x0, 0x30038A1, 0x0, 0x30038A4, 0x0, 0x30038A7,\n\t0x0, 0x30038AA, 0x0, 0x30038AD, 0x0, 0x30038B0, 0x0, 0x30038B3, 0x0, 0x30038B6, 0x0, 0x30038B9, 0x0, 0x30038BC, 0x0, 0x30038BF,\n\t0x0, 0x30038C2, 0x0, 0x30038C5, 0x0, 0x30038C8, 0x0, 0x30038CB, 0x0, 0x30038CE, 0x0, 0x30038D1, 0x0, 0x30038D4, 0x0, 0x30038D7,\n\t0x0, 0x30038DA, 0x0, 0x30038DD, 0x0, 0x30038E0, 0x30038E3, 0x30038E6, 0x30038E9, 0x30038EC, 0x30038EF, 0x3003892, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x30038F2, 0x0, 0x30038F5, 0x0, 0x30038F8, 0x0, 0x30038FB, 0x0, 0x30038FE, 0x0, 0x3003901, 0x0, 0x3003904, 0x0, 0x3003907,\n\t0x0, 0x300390A, 0x0, 0x300390D, 0x0, 0x3003910, 0x0, 0x3003913, 0x0, 0x3003916, 0x0, 0x3003919, 0x0, 0x300391C, 0x0, 0x300391F,\n\t0x0, 0x3003922, 0x0, 0x3003925, 0x0, 0x3003928, 0x0, 0x300392B, 0x0, 0x300392E, 0x0, 0x3003931, 0x0, 0x3003934, 0x0, 0x3003937,\n\t0x0, 0x300393A, 0x0, 0x300393D, 0x0, 0x3003940, 0x0, 0x3003943, 0x0, 0x3003946, 0x0, 0x3003949, 0x0, 0x300394C, 0x0, 0x300394F,\n\t0x0, 0x3003952, 0x0, 0x3003955, 0x0, 0x3003958, 0x0, 0x300395B, 0x0, 0x300395E, 0x0, 0x3003961, 0x0, 0x3003964, 0x0, 0x3003967,\n\t0x0, 0x300396A, 0x0, 0x300396D, 0x0, 0x3003970, 0x0, 0x3003973, 0x0, 0x3003976, 0x0, 0x3003979, 0x0, 0x300397C, 0x0, 0x300397F,\n\t0x3003982, 0x3003985, 0x3003988, 0x300398B, 0x300398E, 0x3003991, 0x3003994, 0x3003997, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x300399A, 0x300399D, 0x30039A0, 0x30039A3, 0x30039A6, 0x30039A9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x30039AC, 0x30039AF, 0x30039B2, 0x30039B5, 0x30039B8, 0x30039BB, 0x30039BE, 0x30039C1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x30039C4, 0x30039C7, 0x30039CA, 0x30039CD, 0x30039D0, 0x30039D3, 0x30039D6, 0x30039D9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x30039DC, 0x30039DF, 0x30039E2, 0x30039E5, 0x30039E8, 0x30039EB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x40039EE, 0x30039F2, 0x60039F5, 0x30039FB, 0x60039FE, 0x3003A04, 0x6003A07, 0x3003A0D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3003A10, 0x3003A13, 0x3003A16, 0x3003A19, 0x3003A1C, 0x3003A1F, 0x3003A22, 0x3003A25, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3003A28, 0x3003A2B, 0x3003A2E, 0x3003A31, 0x3003A34, 0x3003A37, 0x3003A3A, 0x3003A3D, 0x3003A40, 0x3003A43, 0x3003A46, 0x3003A49, 0x3003A4C, 0x3003A4F, 0x0, 0x0,\n\t0x3004A84, 0x3004A87, 0x3004A8A, 0x3004A8D, 0x3004A90, 0x3004A93, 0x3004A96, 0x3004A99, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3004A9C, 0x3004A9F, 0x3004AA2, 0x3004AA5, 0x3004AA8, 0x3004AAB, 0x3004AAE, 0x3004AB1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3004AB4, 0x3004AB7, 0x3004ABA, 0x3004ABD, 0x3004AC0, 0x3004AC3, 0x3004AC6, 0x3004AC9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3003ACA, 0x3003ACD, 0x5004ACC, 0x3004AD1, 0x4004AD4, 0x0, 0x4003ADD, 0x6004AD8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2000339, 0x0,\n\t0x0, 0x0, 0x5004ADE, 0x3004AE3, 0x4004AE6, 0x0, 0x4003AF4, 0x6004AEA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3003AFE, 0x3003B01, 0x6003B04, 0x6003666, 0x0, 0x0, 0x4003B0A, 0x6003B0E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3003B14, 0x3003B17, 0x6003B1A, 0x6003674, 0x4003B20, 0x3003B24, 0x4003B27, 0x6003B2B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x5004AF0, 0x3004AF5, 0x4004AF8, 0x0, 0x4003B3E, 0x6004AFC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003B48, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3003B4B, 0x3003B4E, 0x3003B51, 0x3003B54, 0x3003B57, 0x3003B5A, 0x3003B5D, 0x3003B60, 0x3003B63, 0x3003B66, 0x3003B69, 0x3003B6C, 0x3003B6F, 0x3003B72, 0x3003B75, 0x3003B78,\n\t0x0, 0x0, 0x0, 0x0, 0x3003B7B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3003B7E, 0x3003B81, 0x3003B84, 0x3003B87, 0x3003B8A, 0x3003B8D, 0x3003B90, 0x3003B93, 0x3003B96, 0x3003B99, 0x3003B9C, 0x3003B9F, 0x3003BA2, 0x3003BA5, 0x3003BA8, 0x3003BAB,\n\t0x3003BAE, 0x3003BB1, 0x3003BB4, 0x3003BB7, 0x3003BBA, 0x3003BBD, 0x3003BC0, 0x3003BC3, 0x3003BC6, 0x3003BC9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3003BCC, 0x3003BCF, 0x3003BD2, 0x3003BD5, 0x3003BD8, 0x3003BDB, 0x3003BDE, 0x3003BE1, 0x3003BE4, 0x3003BE7, 0x3003BEA, 0x3003BED, 0x3003BF0, 0x3003BF3, 0x3003BF6, 0x3003BF9,\n\t0x3003BFC, 0x3003BFF, 0x3003C02, 0x3003C05, 0x3003C08, 0x3003C0B, 0x3003C0E, 0x3003C11, 0x3003C14, 0x3003C17, 0x3003C1A, 0x3003C1D, 0x3003C20, 0x3003C23, 0x3003C26, 0x3003C29,\n\t0x3003C2C, 0x3003C2F, 0x3003C32, 0x3003C35, 0x3003C38, 0x3003C3B, 0x3003C3E, 0x3003C41, 0x3003C44, 0x3003C47, 0x3003C4A, 0x3003C4D, 0x3003C50, 0x3003C53, 0x3003C56, 0x0,\n\t0x0, 0x3003C59, 0x0, 0x0, 0x0, 0x2003C5C, 0x2003C5E, 0x0, 0x3003C60, 0x0, 0x3003C63, 0x0, 0x3003C66, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x3003C69, 0x0, 0x0, 0x3003C6C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x3003C6F, 0x0, 0x3003C72, 0x0, 0x3003C75, 0x0, 0x3003C78, 0x0, 0x3003C7B, 0x0, 0x3003C7E, 0x0, 0x3003C81, 0x0, 0x3003C84,\n\t0x0, 0x3003C87, 0x0, 0x3003C8A, 0x0, 0x3003C8D, 0x0, 0x3003C90, 0x0, 0x3003C93, 0x0, 0x3003C96, 0x0, 0x3003C99, 0x0, 0x3003C9C,\n\t0x0, 0x3003C9F, 0x0, 0x3003CA2, 0x0, 0x3003CA5, 0x0, 0x3003CA8, 0x0, 0x3003CAB, 0x0, 0x3003CAE, 0x0, 0x3003CB1, 0x0, 0x3003CB4,\n\t0x0, 0x3003CB7, 0x0, 0x3003CBA, 0x0, 0x3003CBD, 0x0, 0x3003CC0, 0x0, 0x3003CC3, 0x0, 0x3003CC6, 0x0, 0x3003CC9, 0x0, 0x3003CCC,\n\t0x0, 0x3003CCF, 0x0, 0x3003CD2, 0x0, 0x3003CD5, 0x0, 0x3003CD8, 0x0, 0x3003CDB, 0x0, 0x3003CDE, 0x0, 0x3003CE1, 0x0, 0x3003CE4,\n\t0x0, 0x3003CE7, 0x0, 0x3003CEA, 0x0, 0x3003CED, 0x0, 0x3003CF0, 0x0, 0x3003CF3, 0x0, 0x3003CF6, 0x0, 0x3003CF9, 0x0, 0x3003CFC,\n\t0x0, 0x3003CFF, 0x0, 0x3003D02, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003D05, 0x0, 0x3003D08, 0x0,\n\t0x0, 0x0, 0x0, 0x3003D0B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3003D0E, 0x3003D11, 0x3003D14, 0x3003D17, 0x3003D1A, 0x3003D1D, 0x3003D20, 0x3003D23, 0x3003D26, 0x3003D29, 0x3003D2C, 0x3003D2F, 0x3003D32, 0x3003D35, 0x3003D38, 0x3003D3B,\n\t0x3003D3E, 0x3003D41, 0x3003D44, 0x3003D47, 0x3003D4A, 0x3003D4D, 0x3003D50, 0x3003D53, 0x3003D56, 0x3003D59, 0x3003D5C, 0x3003D5F, 0x3003D62, 0x3003D65, 0x3003D68, 0x3003D6B,\n\t0x3003D6E, 0x3003D71, 0x3003D74, 0x3003D77, 0x3003D7A, 0x3003D7D, 0x0, 0x3003D80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003D83, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x3003D86, 0x0, 0x3003D89, 0x0, 0x3003D8C, 0x0, 0x3003D8F, 0x0, 0x3003D92, 0x0, 0x3003D95, 0x0, 0x3003D98, 0x0, 0x3003D9B,\n\t0x0, 0x3003D9E, 0x0, 0x3003DA1, 0x0, 0x3003DA4, 0x0, 0x3003DA7, 0x0, 0x3003DAA, 0x0, 0x3003DAD, 0x0, 0x3003DB0, 0x0, 0x3003DB3,\n\t0x0, 0x3003DB6, 0x0, 0x3003DB9, 0x0, 0x3003DBC, 0x0, 0x3003DBF, 0x0, 0x3003DC2, 0x0, 0x3003DC5, 0x0, 0x3003DC8, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x3003DCB, 0x0, 0x3003DCE, 0x0, 0x3003DD1, 0x0, 0x3003DD4, 0x0, 0x3003DD7, 0x0, 0x3003DDA, 0x0, 0x3003DDD, 0x0, 0x3003DE0,\n\t0x0, 0x3003DE3, 0x0, 0x3003DE6, 0x0, 0x3003DE9, 0x0, 0x3003DEC, 0x0, 0x3003DEF, 0x0, 0x3003DF2, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x3003DF5, 0x0, 0x3003DF8, 0x0, 0x3003DFB, 0x0, 0x3003DFE, 0x0, 0x3003E01, 0x0, 0x3003E04, 0x0, 0x3003E07,\n\t0x0, 0x0, 0x0, 0x3003E0A, 0x0, 0x3003E0D, 0x0, 0x3003E10, 0x0, 0x3003E13, 0x0, 0x3003E16, 0x0, 0x3003E19, 0x0, 0x3003E1C,\n\t0x0, 0x3003E1F, 0x0, 0x3003E22, 0x0, 0x3003E25, 0x0, 0x3003E28, 0x0, 0x3003E2B, 0x0, 0x3003E2E, 0x0, 0x3003E31, 0x0, 0x3003E34,\n\t0x0, 0x3003E37, 0x0, 0x3003E3A, 0x0, 0x3003E3D, 0x0, 0x3003E40, 0x0, 0x3003E43, 0x0, 0x3003E46, 0x0, 0x3003E49, 0x0, 0x3003E4C,\n\t0x0, 0x3003E4F, 0x0, 0x3003E52, 0x0, 0x3003E55, 0x0, 0x3003E58, 0x0, 0x3003E5B, 0x0, 0x3003E5E, 0x0, 0x3003E61, 0x0, 0x3003E64,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003E67, 0x0, 0x3003E6A, 0x0, 0x0, 0x3003E6D,\n\t0x0, 0x3003E70, 0x0, 0x3003E73, 0x0, 0x3003E76, 0x0, 0x3003E79, 0x0, 0x0, 0x0, 0x0, 0x3003E7C, 0x0, 0x0, 0x0,\n\t0x0, 0x3003E7F, 0x0, 0x3003E82, 0x0, 0x0, 0x0, 0x3003E85, 0x0, 0x3003E88, 0x0, 0x3003E8B, 0x0, 0x3003E8E, 0x0, 0x3003E91,\n\t0x0, 0x3003E94, 0x0, 0x3003E97, 0x0, 0x3003E9A, 0x0, 0x3003E9D, 0x0, 0x3003EA0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x2004B02, 0x2004B04, 0x2004B06, 0x3004B08, 0x3004B0B, 0x2004B0E, 0x2004B0E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x4004B10, 0x4004B14, 0x4004B18, 0x4004B1C, 0x4004B20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x3003EC5, 0x3003EC8, 0x3003ECB, 0x3003ECE, 0x3003ED1, 0x3003ED4, 0x3003ED7, 0x3003EDA, 0x3003EDD, 0x3003EE0, 0x3003EE3, 0x3003EE6, 0x3003EE9, 0x3003EEC, 0x3003EEF,\n\t0x3003EF2, 0x3003EF5, 0x3003EF8, 0x3003EFB, 0x3003EFE, 0x3003F01, 0x3003F04, 0x3003F07, 0x3003F0A, 0x3003F0D, 0x3003F10, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4003F13, 0x4003F17, 0x4003F1B, 0x4003F1F, 0x4003F23, 0x4003F27, 0x4003F2B, 0x4003F2F,\n\t0x4003F33, 0x4003F37, 0x4003F3B, 0x4003F3F, 0x4003F43, 0x4003F47, 0x4003F4B, 0x4003F4F, 0x4003F53, 0x4003F57, 0x4003F5B, 0x4003F5F, 0x4003F63, 0x4003F67, 0x4003F6B, 0x4003F6F,\n\t0x4003F73, 0x4003F77, 0x4003F7B, 0x4003F7F, 0x4003F83, 0x4003F87, 0x4003F8B, 0x4003F8F, 0x4003F93, 0x4003F97, 0x4003F9B, 0x4003F9F, 0x4003FA3, 0x4003FA7, 0x4003FAB, 0x4003FAF,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x4003FB3, 0x4003FB7, 0x4003FBB, 0x4003FBF, 0x4003FC3, 0x4003FC7, 0x4003FCB, 0x4003FCF, 0x4003FD3, 0x4003FD7, 0x4003FDB, 0x4003FDF, 0x4003FE3, 0x4003FE7, 0x4003FEB, 0x4003FEF,\n\t0x4003FF3, 0x4003FF7, 0x4003FFB, 0x4003FFF, 0x4004003, 0x4004007, 0x400400B, 0x400400F, 0x4004013, 0x4004017, 0x400401B, 0x400401F, 0x4004023, 0x4004027, 0x400402B, 0x400402F,\n};\nconst uint32_t* TitlecaseDataPtr = TitlecaseData;\n\nconst uint32_t CaseFoldingIndex1[272] = {\n\t0, 128, 256, 384, 360, 360, 360, 360, 360, 360, 512, 360, 360, 360, 360, 640,\n\t768, 896, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n\t360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,\n};\nconst uint32_t* CaseFoldingIndex1Ptr = CaseFoldingIndex1;\n\nconst uint32_t CaseFoldingIndex2[1024] = {\n\t0x0, 0x0, 0x20, 0x0, 0x0, 0x40, 0x60, 0x0, 0x80, 0xA0, 0xC0, 0xE0, 0x100, 0x120, 0x140, 0x160,\n\t0x180, 0x1A0, 0x1C0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1E0, 0x200, 0x220, 0x240, 0x260, 0x280,\n\t0x2A0, 0x2C0, 0x0, 0x2E0, 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x0, 0x3E0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x400, 0x420, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x440, 0x460, 0x480, 0x4A0, 0x4C0, 0x4E0, 0x500, 0x520, 0x540, 0x560, 0x580, 0x5A0, 0x5C0, 0x5E0, 0x600, 0x620,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x640, 0x0, 0x660, 0x680, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x6A0, 0x6C0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x6E0, 0x700, 0x0, 0x720, 0x740, 0x760, 0x780, 0x7A0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x7C0, 0x7E0, 0x800, 0x0, 0x0, 0x0, 0x0, 0x820, 0x840, 0x860, 0x880, 0x8A0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8C0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8E0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x900, 0x920, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x940, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n};\nconst uint32_t* CaseFoldingIndex2Ptr = CaseFoldingIndex2;\n\nconst uint32_t CaseFoldingData[2400] = {\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x100004E, 0x1000636, 0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x100007E,\n\t0x1000754, 0x1002068, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x2001D29, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x2004033, 0x2004035, 0x2004037, 0x2004039, 0x200403B, 0x200403D, 0x2000247, 0x200403F, 0x2004041, 0x2004043, 0x2004045, 0x2004047, 0x2004049, 0x200404B, 0x200404D, 0x200404F,\n\t0x2001E1E, 0x2004051, 0x2004053, 0x2004055, 0x2004057, 0x2004059, 0x200405B, 0x0, 0x2000294, 0x200405D, 0x200405F, 0x2004061, 0x2004063, 0x2004065, 0x2004067, 0x2004B24,\n\t0x2004069, 0x0, 0x200406B, 0x0, 0x200406D, 0x0, 0x200406F, 0x0, 0x2004071, 0x0, 0x2004073, 0x0, 0x2004075, 0x0, 0x2004077, 0x0,\n\t0x2004079, 0x0, 0x200407B, 0x0, 0x200407D, 0x0, 0x200407F, 0x0, 0x2004081, 0x0, 0x2004083, 0x0, 0x2004085, 0x0, 0x2004087, 0x0,\n\t0x2004089, 0x0, 0x200408B, 0x0, 0x200408D, 0x0, 0x2001EF8, 0x0, 0x200408F, 0x0, 0x2004091, 0x0, 0x2004093, 0x0, 0x2004095, 0x0,\n\t0x3004097, 0x0, 0x200409A, 0x0, 0x200409C, 0x0, 0x200409E, 0x0, 0x0, 0x20040A0, 0x0, 0x20040A2, 0x0, 0x20040A4, 0x0, 0x20040A6,\n\t0x0, 0x20040A8, 0x0, 0x20040AA, 0x0, 0x20040AC, 0x0, 0x20040AE, 0x0, 0x3001D48, 0x2001E00, 0x0, 0x20040B0, 0x0, 0x20040B2, 0x0,\n\t0x20040B4, 0x0, 0x2002CE5, 0x0, 0x20040B6, 0x0, 0x20040B8, 0x0, 0x20040BA, 0x0, 0x20040BC, 0x0, 0x20040BE, 0x0, 0x20040C0, 0x0,\n\t0x20040C2, 0x0, 0x20040C4, 0x0, 0x20040C6, 0x0, 0x20040C8, 0x0, 0x20040CA, 0x0, 0x20040CC, 0x0, 0x20040CE, 0x0, 0x20040D0, 0x0,\n\t0x20040D2, 0x0, 0x20040D4, 0x0, 0x20040D6, 0x0, 0x20040D8, 0x0, 0x20040DA, 0x20040DC, 0x0, 0x20040DE, 0x0, 0x20040E0, 0x0, 0x100017D,\n\t0x0, 0x20040E2, 0x20040E4, 0x0, 0x20040E6, 0x0, 0x2001E02, 0x20040E8, 0x0, 0x20040EA, 0x20040EC, 0x20040EE, 0x0, 0x0, 0x20040F0, 0x2001DFA,\n\t0x2001DFC, 0x20040F2, 0x0, 0x20040F4, 0x2001D7D, 0x0, 0x2001E28, 0x2001E26, 0x20040F6, 0x0, 0x0, 0x0, 0x2001E0D, 0x2001E3C, 0x0, 0x2001E42,\n\t0x20040F8, 0x0, 0x20040FA, 0x0, 0x20040FC, 0x0, 0x20040FE, 0x2004100, 0x0, 0x2001E48, 0x0, 0x0, 0x2004102, 0x0, 0x2004104, 0x2004106,\n\t0x0, 0x2001E4E, 0x2001E53, 0x2004108, 0x0, 0x200410A, 0x0, 0x200026B, 0x200410C, 0x0, 0x0, 0x0, 0x200410E, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x2004110, 0x2004110, 0x0, 0x2004112, 0x2004112, 0x0, 0x2004114, 0x2004114, 0x0, 0x2004116, 0x0, 0x2004118,\n\t0x0, 0x200411A, 0x0, 0x200411C, 0x0, 0x200411E, 0x0, 0x2004120, 0x0, 0x2004122, 0x0, 0x2004124, 0x0, 0x0, 0x2004126, 0x0,\n\t0x2004128, 0x0, 0x200412A, 0x0, 0x200412C, 0x0, 0x200412E, 0x0, 0x2004130, 0x0, 0x2004132, 0x0, 0x2004134, 0x0, 0x2004136, 0x0,\n\t0x300026F, 0x2004138, 0x2004138, 0x0, 0x200413A, 0x0, 0x200413C, 0x200413E, 0x2004140, 0x0, 0x2004142, 0x0, 0x2004144, 0x0, 0x2004146, 0x0,\n\t0x2004148, 0x0, 0x200414A, 0x0, 0x200414C, 0x0, 0x200414E, 0x0, 0x2004150, 0x0, 0x2004152, 0x0, 0x2004154, 0x0, 0x2004156, 0x0,\n\t0x2004158, 0x0, 0x200415A, 0x0, 0x200415C, 0x0, 0x200415E, 0x0, 0x2004160, 0x0, 0x2004162, 0x0, 0x2004164, 0x0, 0x2004166, 0x0,\n\t0x2004168, 0x0, 0x200416A, 0x0, 0x200416C, 0x0, 0x200416E, 0x0, 0x2004170, 0x0, 0x2004172, 0x0, 0x2004174, 0x0, 0x2004176, 0x0,\n\t0x2004178, 0x0, 0x200417A, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300417C, 0x200417F, 0x0, 0x2004181, 0x3004183, 0x0,\n\t0x0, 0x2004186, 0x0, 0x2004188, 0x2001E4C, 0x2001E55, 0x200418A, 0x0, 0x200418C, 0x0, 0x200418E, 0x0, 0x2004190, 0x0, 0x2004192, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x2000349, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x2004194, 0x0, 0x2004196, 0x0, 0x0, 0x0, 0x2004198, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200419A,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200419C, 0x0, 0x200419E, 0x20041A0, 0x20041A2, 0x0, 0x20041A4, 0x0, 0x20041A6, 0x20041A8,\n\t0x6000349, 0x2000357, 0x2001D89, 0x2001E12, 0x2001E14, 0x200035B, 0x2003369, 0x200035F, 0x2001D8B, 0x2000349, 0x2001D91, 0x200336B, 0x2001D29, 0x200336D, 0x200336F, 0x200036D,\n\t0x2001D8F, 0x2000E17, 0x0, 0x2003371, 0x2003373, 0x2000367, 0x2001D8D, 0x2001E16, 0x2003375, 0x2000375, 0x20041AA, 0x20041AC, 0x0, 0x0, 0x0, 0x0,\n\t0x6000367, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x2003371, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20041AE,\n\t0x2001D89, 0x2001D8B, 0x0, 0x0, 0x0, 0x2001D8D, 0x2001D8F, 0x0, 0x20041B0, 0x0, 0x20041B2, 0x0, 0x200337C, 0x0, 0x20041B4, 0x0,\n\t0x20041B6, 0x0, 0x20041B8, 0x0, 0x20041BA, 0x0, 0x20041BC, 0x0, 0x20041BE, 0x0, 0x20041C0, 0x0, 0x20041C2, 0x0, 0x20041C4, 0x0,\n\t0x2001D91, 0x2000E17, 0x0, 0x0, 0x2001D8B, 0x200035B, 0x0, 0x20041C6, 0x0, 0x20041C8, 0x20041CA, 0x0, 0x0, 0x20041CC, 0x20041CE, 0x20041D0,\n\t0x20041D2, 0x20041D4, 0x20041D6, 0x20041D8, 0x20041DA, 0x20041DC, 0x20003B1, 0x20041DE, 0x20041E0, 0x20041E2, 0x20041E4, 0x20041E6, 0x20041E8, 0x20041EA, 0x20041EC, 0x20041EE,\n\t0x20003D5, 0x20041F0, 0x20041F2, 0x20003AD, 0x20041F4, 0x20003A5, 0x20003CD, 0x20003FD, 0x20003A1, 0x20041F6, 0x20003B5, 0x20041F8, 0x20041FA, 0x2001E18, 0x2000415, 0x20041FC,\n\t0x20041FE, 0x2004200, 0x2004202, 0x20003BD, 0x2004204, 0x2004206, 0x2004208, 0x2000445, 0x200420A, 0x200420C, 0x2002CDC, 0x200044D, 0x2002CDE, 0x2000425, 0x200420E, 0x2004210,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x2004212, 0x0, 0x2004214, 0x0, 0x2004216, 0x0, 0x2004218, 0x0, 0x200421A, 0x0, 0x200421C, 0x0, 0x200421E, 0x0, 0x2004220, 0x0,\n\t0x2004222, 0x0, 0x2004224, 0x0, 0x20003C5, 0x0, 0x2004226, 0x0, 0x2004228, 0x0, 0x200422A, 0x0, 0x200422C, 0x0, 0x200422E, 0x0,\n\t0x2004230, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2004232, 0x0, 0x2004234, 0x0, 0x2004236, 0x0,\n\t0x2004238, 0x0, 0x200423A, 0x0, 0x200423C, 0x0, 0x200423E, 0x0, 0x2004240, 0x0, 0x2004242, 0x0, 0x2004244, 0x0, 0x2004246, 0x0,\n\t0x2004248, 0x0, 0x200424A, 0x0, 0x200424C, 0x0, 0x200424E, 0x0, 0x2004250, 0x0, 0x2004252, 0x0, 0x2004254, 0x0, 0x2004256, 0x0,\n\t0x2004258, 0x0, 0x200425A, 0x0, 0x200425C, 0x0, 0x200425E, 0x0, 0x2004260, 0x0, 0x2004262, 0x0, 0x2004264, 0x0, 0x2004266, 0x0,\n\t0x2004268, 0x200426A, 0x0, 0x200426C, 0x0, 0x200426E, 0x0, 0x2004270, 0x0, 0x2004272, 0x0, 0x2004274, 0x0, 0x2004276, 0x0, 0x0,\n\t0x2004278, 0x0, 0x200427A, 0x0, 0x200427C, 0x0, 0x200427E, 0x0, 0x20003ED, 0x0, 0x2004280, 0x0, 0x2004282, 0x0, 0x2004284, 0x0,\n\t0x2004286, 0x0, 0x2004288, 0x0, 0x200428A, 0x0, 0x200428C, 0x0, 0x200041D, 0x0, 0x200428E, 0x0, 0x2004290, 0x0, 0x2004292, 0x0,\n\t0x2004294, 0x0, 0x2004296, 0x0, 0x2004298, 0x0, 0x200429A, 0x0, 0x200429C, 0x0, 0x200429E, 0x0, 0x20042A0, 0x0, 0x20042A2, 0x0,\n\t0x20042A4, 0x0, 0x20042A6, 0x0, 0x20042A8, 0x0, 0x20042AA, 0x0, 0x20042AC, 0x0, 0x20042AE, 0x0, 0x20042B0, 0x0, 0x20042B2, 0x0,\n\t0x20042B4, 0x0, 0x20042B6, 0x0, 0x20042B8, 0x0, 0x20042BA, 0x0, 0x20042BC, 0x0, 0x20042BE, 0x0, 0x20042C0, 0x0, 0x20042C2, 0x0,\n\t0x20042C4, 0x0, 0x20042C6, 0x0, 0x20042C8, 0x0, 0x20042CA, 0x0, 0x20042CC, 0x0, 0x20042CE, 0x0, 0x20042D0, 0x0, 0x20042D2, 0x0,\n\t0x0, 0x20042D4, 0x20042D6, 0x20042D8, 0x20042DA, 0x2001D99, 0x20042DC, 0x20042DE, 0x20042E0, 0x20042E2, 0x20042E4, 0x2002D0A, 0x20042E6, 0x2002D12, 0x20042E8, 0x20042EA,\n\t0x20042EC, 0x20042EE, 0x20042F0, 0x20042F2, 0x2002D00, 0x20042F4, 0x2002D02, 0x20042F6, 0x20042F8, 0x20042FA, 0x20042FC, 0x20042FE, 0x2004300, 0x2004302, 0x2002D0C, 0x2004304,\n\t0x2004306, 0x2004308, 0x2001D9B, 0x200430A, 0x200430C, 0x200430E, 0x2004310, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4001D99, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3004312, 0x3004315, 0x3004318, 0x300431B, 0x300431E, 0x3004321, 0x3004324, 0x3004327, 0x300432A, 0x300432D, 0x3004330, 0x3004333, 0x3004336, 0x3004339, 0x300433C, 0x300433F,\n\t0x3004342, 0x3004345, 0x3004348, 0x300434B, 0x300434E, 0x3004351, 0x3004354, 0x3004357, 0x300435A, 0x300435D, 0x3004360, 0x3004363, 0x3004366, 0x3004369, 0x300436C, 0x300436F,\n\t0x3004372, 0x3004375, 0x3004378, 0x300437B, 0x300437E, 0x3004381, 0x0, 0x3004384, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004387, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x300438A, 0x0, 0x300438D, 0x0, 0x3004390, 0x0, 0x3004393, 0x0, 0x3004396, 0x0, 0x3004399, 0x0, 0x300439C, 0x0, 0x300439F, 0x0,\n\t0x30043A2, 0x0, 0x30043A5, 0x0, 0x30043A8, 0x0, 0x30043AB, 0x0, 0x30043AE, 0x0, 0x30043B1, 0x0, 0x30043B4, 0x0, 0x30043B7, 0x0,\n\t0x30043BA, 0x0, 0x30043BD, 0x0, 0x30043C0, 0x0, 0x30043C3, 0x0, 0x30043C6, 0x0, 0x30043C9, 0x0, 0x30043CC, 0x0, 0x30043CF, 0x0,\n\t0x30043D2, 0x0, 0x30043D5, 0x0, 0x30043D8, 0x0, 0x30043DB, 0x0, 0x30043DE, 0x0, 0x30043E1, 0x0, 0x30043E4, 0x0, 0x30043E7, 0x0,\n\t0x30043EA, 0x0, 0x30043ED, 0x0, 0x30043F0, 0x0, 0x30043F3, 0x0, 0x30043F6, 0x0, 0x30043F9, 0x0, 0x30043FC, 0x0, 0x30043FF, 0x0,\n\t0x3004402, 0x0, 0x3004405, 0x0, 0x3004408, 0x0, 0x300440B, 0x0, 0x300440E, 0x0, 0x3004411, 0x0, 0x3004414, 0x0, 0x3004417, 0x0,\n\t0x300441A, 0x0, 0x300441D, 0x0, 0x3004420, 0x0, 0x3004423, 0x0, 0x3004426, 0x0, 0x3004429, 0x0, 0x300442C, 0x0, 0x300442F, 0x0,\n\t0x3004432, 0x0, 0x3004435, 0x0, 0x3004438, 0x0, 0x300443B, 0x0, 0x300443E, 0x0, 0x3004441, 0x0, 0x3004444, 0x0, 0x3004447, 0x0,\n\t0x300444A, 0x0, 0x300444D, 0x0, 0x3004450, 0x0, 0x3004453, 0x0, 0x3004456, 0x0, 0x3004459, 0x0, 0x300445C, 0x0, 0x300445F, 0x0,\n\t0x3004462, 0x0, 0x3004465, 0x0, 0x3004468, 0x0, 0x300082F, 0x3000832, 0x3000835, 0x3000838, 0x3001E5B, 0x300441A, 0x0, 0x0, 0x2004B24, 0x0,\n\t0x300446D, 0x0, 0x3004470, 0x0, 0x3004473, 0x0, 0x3004476, 0x0, 0x3004479, 0x0, 0x300447C, 0x0, 0x300447F, 0x0, 0x3004482, 0x0,\n\t0x3004485, 0x0, 0x3004488, 0x0, 0x300448B, 0x0, 0x300448E, 0x0, 0x3004491, 0x0, 0x3004494, 0x0, 0x3004497, 0x0, 0x300449A, 0x0,\n\t0x300449D, 0x0, 0x30044A0, 0x0, 0x30044A3, 0x0, 0x30044A6, 0x0, 0x30044A9, 0x0, 0x30044AC, 0x0, 0x30044AF, 0x0, 0x30044B2, 0x0,\n\t0x30044B5, 0x0, 0x30044B8, 0x0, 0x30044BB, 0x0, 0x30044BE, 0x0, 0x30044C1, 0x0, 0x30044C4, 0x0, 0x30044C7, 0x0, 0x30044CA, 0x0,\n\t0x30044CD, 0x0, 0x30044D0, 0x0, 0x30044D3, 0x0, 0x30044D6, 0x0, 0x30044D9, 0x0, 0x30044DC, 0x0, 0x30044DF, 0x0, 0x30044E2, 0x0,\n\t0x30044E5, 0x0, 0x30044E8, 0x0, 0x30044EB, 0x0, 0x30044EE, 0x0, 0x30044F1, 0x0, 0x30044F4, 0x0, 0x30044F7, 0x0, 0x30044FA, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30044FD, 0x3004500, 0x3004503, 0x3004506, 0x3004509, 0x300450C, 0x300450F, 0x3004512,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004515, 0x3004518, 0x300451B, 0x300451E, 0x3004521, 0x3004524, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004527, 0x300452A, 0x300452D, 0x3004530, 0x3004533, 0x3004536, 0x3004539, 0x300453C,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300453F, 0x3004542, 0x3004545, 0x3004548, 0x300454B, 0x300454E, 0x3004551, 0x3004554,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004557, 0x300455A, 0x300455D, 0x3004560, 0x3004563, 0x3004566, 0x0, 0x0,\n\t0x4000B4D, 0x0, 0x6000B55, 0x0, 0x6000B61, 0x0, 0x6000B6D, 0x0, 0x0, 0x3004569, 0x0, 0x300456C, 0x0, 0x300456F, 0x0, 0x3004572,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004575, 0x3004578, 0x300457B, 0x300457E, 0x3004581, 0x3004584, 0x3004587, 0x300458A,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x5004B26, 0x5004B2B, 0x5004B30, 0x5004B35, 0x5004B3A, 0x5004B3F, 0x5004B44, 0x5004B49, 0x5004B26, 0x5004B2B, 0x5004B30, 0x5004B35, 0x5004B3A, 0x5004B3F, 0x5004B44, 0x5004B49,\n\t0x5004B4E, 0x5004B53, 0x5004B58, 0x5004B5D, 0x5004B62, 0x5004B67, 0x5004B6C, 0x5004B71, 0x5004B4E, 0x5004B53, 0x5004B58, 0x5004B5D, 0x5004B62, 0x5004B67, 0x5004B6C, 0x5004B71,\n\t0x5004B76, 0x5004B7B, 0x5004B80, 0x5004B85, 0x5004B8A, 0x5004B8F, 0x5004B94, 0x5004B99, 0x5004B76, 0x5004B7B, 0x5004B80, 0x5004B85, 0x5004B8A, 0x5004B8F, 0x5004B94, 0x5004B99,\n\t0x0, 0x0, 0x5004B9E, 0x4004BA3, 0x4004BA7, 0x0, 0x4000D83, 0x6004BAB, 0x30045D5, 0x30045D8, 0x30045DB, 0x30045DE, 0x4004BA3, 0x0, 0x2000349, 0x0,\n\t0x0, 0x0, 0x5004BB1, 0x4004BB6, 0x4004BBA, 0x0, 0x4000DB1, 0x6004BBE, 0x30045E4, 0x30045E7, 0x30045EA, 0x30045ED, 0x4004BB6, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x6000DDE, 0x6000349, 0x0, 0x0, 0x4000DE4, 0x6000DE8, 0x30045F3, 0x30045F6, 0x30045F9, 0x30045FC, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x6000E11, 0x6000367, 0x4000E17, 0x0, 0x4000E1F, 0x6000E23, 0x30045FF, 0x3004602, 0x3004605, 0x3004608, 0x300460B, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x5004BC4, 0x4004BC9, 0x4004BCD, 0x0, 0x4000E4E, 0x6004BD1, 0x300460E, 0x3004611, 0x3004614, 0x3004617, 0x4004BC9, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2000375, 0x0, 0x0, 0x0, 0x100012F, 0x200403D, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x300461D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x3004620, 0x3004623, 0x3004626, 0x3004629, 0x300462C, 0x300462F, 0x3004632, 0x3004635, 0x3004638, 0x300463B, 0x300463E, 0x3004641, 0x3004644, 0x3004647, 0x300464A, 0x300464D,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x3004650, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004653, 0x3004656, 0x3004659, 0x300465C, 0x300465F, 0x3004662, 0x3004665, 0x3004668, 0x300466B, 0x300466E,\n\t0x3004671, 0x3004674, 0x3004677, 0x300467A, 0x300467D, 0x3004680, 0x3004683, 0x3004686, 0x3004689, 0x300468C, 0x300468F, 0x3004692, 0x3004695, 0x3004698, 0x300469B, 0x300469E,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x30046A1, 0x30046A4, 0x30046A7, 0x30046AA, 0x30046AD, 0x30046B0, 0x30046B3, 0x30046B6, 0x30046B9, 0x30046BC, 0x30046BF, 0x30046C2, 0x30046C5, 0x30046C8, 0x30046CB, 0x30046CE,\n\t0x30046D1, 0x30046D4, 0x30046D7, 0x30046DA, 0x30046DD, 0x30046E0, 0x30046E3, 0x30046E6, 0x30046E9, 0x30046EC, 0x30046EF, 0x30046F2, 0x30046F5, 0x30046F8, 0x30046FB, 0x30046FE,\n\t0x3004701, 0x3004704, 0x3004707, 0x300470A, 0x300470D, 0x3004710, 0x3004713, 0x3004716, 0x3004719, 0x300471C, 0x300471F, 0x3004722, 0x3004725, 0x3004728, 0x300472B, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x300472E, 0x0, 0x2002CED, 0x3004731, 0x2004734, 0x0, 0x0, 0x3004736, 0x0, 0x3004739, 0x0, 0x300473C, 0x0, 0x2001DF5, 0x2001E38, 0x2001DF3,\n\t0x2001E1A, 0x0, 0x300473F, 0x0, 0x0, 0x3004742, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2004745, 0x2004747,\n\t0x3004749, 0x0, 0x300474C, 0x0, 0x300474F, 0x0, 0x3004752, 0x0, 0x3004755, 0x0, 0x3004758, 0x0, 0x300475B, 0x0, 0x300475E, 0x0,\n\t0x3004761, 0x0, 0x3004764, 0x0, 0x3004767, 0x0, 0x300476A, 0x0, 0x300476D, 0x0, 0x3004770, 0x0, 0x3004773, 0x0, 0x3004776, 0x0,\n\t0x3004779, 0x0, 0x300477C, 0x0, 0x300477F, 0x0, 0x3004782, 0x0, 0x3004785, 0x0, 0x3004788, 0x0, 0x300478B, 0x0, 0x300478E, 0x0,\n\t0x3004791, 0x0, 0x3004794, 0x0, 0x3004797, 0x0, 0x300479A, 0x0, 0x300479D, 0x0, 0x30047A0, 0x0, 0x30047A3, 0x0, 0x30047A6, 0x0,\n\t0x30047A9, 0x0, 0x30047AC, 0x0, 0x30047AF, 0x0, 0x30047B2, 0x0, 0x30047B5, 0x0, 0x30047B8, 0x0, 0x30047BB, 0x0, 0x30047BE, 0x0,\n\t0x30047C1, 0x0, 0x30047C4, 0x0, 0x30047C7, 0x0, 0x30047CA, 0x0, 0x30047CD, 0x0, 0x30047D0, 0x0, 0x30047D3, 0x0, 0x30047D6, 0x0,\n\t0x30047D9, 0x0, 0x30047DC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30047DF, 0x0, 0x30047E2, 0x0, 0x0,\n\t0x0, 0x0, 0x30047E5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x30047E8, 0x0, 0x30047EB, 0x0, 0x30047EE, 0x0, 0x30047F1, 0x0, 0x30047F4, 0x0, 0x30047F7, 0x0, 0x30047FA, 0x0, 0x30047FD, 0x0,\n\t0x3004800, 0x0, 0x3004803, 0x0, 0x3004806, 0x0, 0x3004809, 0x0, 0x300480C, 0x0, 0x300480F, 0x0, 0x3004812, 0x0, 0x3004815, 0x0,\n\t0x3004818, 0x0, 0x300481B, 0x0, 0x300481E, 0x0, 0x3004821, 0x0, 0x3004824, 0x0, 0x3004827, 0x0, 0x300482A, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x300482D, 0x0, 0x3004830, 0x0, 0x3004833, 0x0, 0x3004836, 0x0, 0x3004839, 0x0, 0x300483C, 0x0, 0x300483F, 0x0, 0x3004842, 0x0,\n\t0x3004845, 0x0, 0x3004848, 0x0, 0x300484B, 0x0, 0x300484E, 0x0, 0x3004851, 0x0, 0x3004854, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x3004857, 0x0, 0x300485A, 0x0, 0x3002CE7, 0x0, 0x300485D, 0x0, 0x3004860, 0x0, 0x3004863, 0x0, 0x3004866, 0x0,\n\t0x0, 0x0, 0x3004869, 0x0, 0x300486C, 0x0, 0x300486F, 0x0, 0x3004872, 0x0, 0x3004875, 0x0, 0x3004878, 0x0, 0x300487B, 0x0,\n\t0x300487E, 0x0, 0x3004881, 0x0, 0x3004884, 0x0, 0x3004887, 0x0, 0x300488A, 0x0, 0x300488D, 0x0, 0x3004890, 0x0, 0x3004893, 0x0,\n\t0x3004896, 0x0, 0x3004899, 0x0, 0x300489C, 0x0, 0x300489F, 0x0, 0x30048A2, 0x0, 0x30048A5, 0x0, 0x30048A8, 0x0, 0x30048AB, 0x0,\n\t0x30048AE, 0x0, 0x30048B1, 0x0, 0x30048B4, 0x0, 0x30048B7, 0x0, 0x30048BA, 0x0, 0x30048BD, 0x0, 0x30048C0, 0x0, 0x3002CE0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30048C3, 0x0, 0x30048C6, 0x0, 0x30048C9, 0x30048CC, 0x0,\n\t0x30048CF, 0x0, 0x30048D2, 0x0, 0x30048D5, 0x0, 0x30048D8, 0x0, 0x0, 0x0, 0x0, 0x30048DB, 0x0, 0x2001E24, 0x0, 0x0,\n\t0x30048DE, 0x0, 0x30048E1, 0x0, 0x0, 0x0, 0x30048E4, 0x0, 0x30048E7, 0x0, 0x30048EA, 0x0, 0x30048ED, 0x0, 0x30048F0, 0x0,\n\t0x30048F3, 0x0, 0x30048F6, 0x0, 0x30048F9, 0x0, 0x30048FC, 0x0, 0x30048FF, 0x0, 0x2001D63, 0x2001DFE, 0x2001E22, 0x2004902, 0x0, 0x0,\n\t0x2004904, 0x2004906, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x2002CF2, 0x2002CF4, 0x2002CF6, 0x3002CF8, 0x3002CFB, 0x2002CFE, 0x2002CFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x4002D00, 0x4002D04, 0x4002D08, 0x4002D0C, 0x4002D10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x3004908, 0x300490B, 0x300490E, 0x3004911, 0x3004914, 0x3004917, 0x300491A, 0x300491D, 0x3004920, 0x3004923, 0x3004926, 0x3004929, 0x300492C, 0x300492F, 0x3004932,\n\t0x3004935, 0x3004938, 0x300493B, 0x300493E, 0x3004941, 0x3004944, 0x3004947, 0x300494A, 0x300494D, 0x3004950, 0x3004953, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x4004956, 0x400495A, 0x400495E, 0x4004962, 0x4004966, 0x400496A, 0x400496E, 0x4004972, 0x4004976, 0x400497A, 0x400497E, 0x4004982, 0x4004986, 0x400498A, 0x400498E, 0x4004992,\n\t0x4004996, 0x400499A, 0x400499E, 0x40049A2, 0x40049A6, 0x40049AA, 0x40049AE, 0x40049B2, 0x40049B6, 0x40049BA, 0x40049BE, 0x40049C2, 0x40049C6, 0x40049CA, 0x40049CE, 0x40049D2,\n\t0x40049D6, 0x40049DA, 0x40049DE, 0x40049E2, 0x40049E6, 0x40049EA, 0x40049EE, 0x40049F2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,\n\t0x40049F6, 0x40049FA, 0x40049FE, 0x4004A02, 0x4004A06, 0x4004A0A, 0x4004A0E, 0x4004A12, 0x4004A16, 0x4004A1A, 0x4004A1E, 0x4004A22, 0x4004A26, 0x4004A2A, 0x4004A2E, 0x4004A32,\n\t0x4004A36, 0x4004A3A, 0x4004A3E, 0x4004A42, 0x4004A46, 0x4004A4A, 0x4004A4E, 0x4004A52, 0x4004A56, 0x4004A5A, 0x4004A5E, 0x4004A62, 0x4004A66, 0x4004A6A, 0x4004A6E, 0x4004A72,\n};\nconst uint32_t* CaseFoldingDataPtr = CaseFoldingData;\n\nconst size_t UnicodeCompositionRecordCount = 940;\nconst CompositionRecord UnicodeCompositionRecord[940] = {\n\t{ 0x3c00000338, 0x226e }, { 0x3d00000338, 0x2260 }, { 0x3e00000338, 0x226f }, { 0x4100000300, 0xc0 },\n\t{ 0x4100000301, 0xc1 }, { 0x4100000302, 0xc2 }, { 0x4100000303, 0xc3 }, { 0x4100000304, 0x100 },\n\t{ 0x4100000306, 0x102 }, { 0x4100000307, 0x226 }, { 0x4100000308, 0xc4 }, { 0x4100000309, 0x1ea2 },\n\t{ 0x410000030a, 0xc5 }, { 0x410000030c, 0x1cd }, { 0x410000030f, 0x200 }, { 0x4100000311, 0x202 },\n\t{ 0x4100000323, 0x1ea0 }, { 0x4100000325, 0x1e00 }, { 0x4100000328, 0x104 }, { 0x4200000307, 0x1e02 },\n\t{ 0x4200000323, 0x1e04 }, { 0x4200000331, 0x1e06 }, { 0x4300000301, 0x106 }, { 0x4300000302, 0x108 },\n\t{ 0x4300000307, 0x10a }, { 0x430000030c, 0x10c }, { 0x4300000327, 0xc7 }, { 0x4400000307, 0x1e0a },\n\t{ 0x440000030c, 0x10e }, { 0x4400000323, 0x1e0c }, { 0x4400000327, 0x1e10 }, { 0x440000032d, 0x1e12 },\n\t{ 0x4400000331, 0x1e0e }, { 0x4500000300, 0xc8 }, { 0x4500000301, 0xc9 }, { 0x4500000302, 0xca },\n\t{ 0x4500000303, 0x1ebc }, { 0x4500000304, 0x112 }, { 0x4500000306, 0x114 }, { 0x4500000307, 0x116 },\n\t{ 0x4500000308, 0xcb }, { 0x4500000309, 0x1eba }, { 0x450000030c, 0x11a }, { 0x450000030f, 0x204 },\n\t{ 0x4500000311, 0x206 }, { 0x4500000323, 0x1eb8 }, { 0x4500000327, 0x228 }, { 0x4500000328, 0x118 },\n\t{ 0x450000032d, 0x1e18 }, { 0x4500000330, 0x1e1a }, { 0x4600000307, 0x1e1e }, { 0x4700000301, 0x1f4 },\n\t{ 0x4700000302, 0x11c }, { 0x4700000304, 0x1e20 }, { 0x4700000306, 0x11e }, { 0x4700000307, 0x120 },\n\t{ 0x470000030c, 0x1e6 }, { 0x4700000327, 0x122 }, { 0x4800000302, 0x124 }, { 0x4800000307, 0x1e22 },\n\t{ 0x4800000308, 0x1e26 }, { 0x480000030c, 0x21e }, { 0x4800000323, 0x1e24 }, { 0x4800000327, 0x1e28 },\n\t{ 0x480000032e, 0x1e2a }, { 0x4900000300, 0xcc }, { 0x4900000301, 0xcd }, { 0x4900000302, 0xce },\n\t{ 0x4900000303, 0x128 }, { 0x4900000304, 0x12a }, { 0x4900000306, 0x12c }, { 0x4900000307, 0x130 },\n\t{ 0x4900000308, 0xcf }, { 0x4900000309, 0x1ec8 }, { 0x490000030c, 0x1cf }, { 0x490000030f, 0x208 },\n\t{ 0x4900000311, 0x20a }, { 0x4900000323, 0x1eca }, { 0x4900000328, 0x12e }, { 0x4900000330, 0x1e2c },\n\t{ 0x4a00000302, 0x134 }, { 0x4b00000301, 0x1e30 }, { 0x4b0000030c, 0x1e8 }, { 0x4b00000323, 0x1e32 },\n\t{ 0x4b00000327, 0x136 }, { 0x4b00000331, 0x1e34 }, { 0x4c00000301, 0x139 }, { 0x4c0000030c, 0x13d },\n\t{ 0x4c00000323, 0x1e36 }, { 0x4c00000327, 0x13b }, { 0x4c0000032d, 0x1e3c }, { 0x4c00000331, 0x1e3a },\n\t{ 0x4d00000301, 0x1e3e }, { 0x4d00000307, 0x1e40 }, { 0x4d00000323, 0x1e42 }, { 0x4e00000300, 0x1f8 },\n\t{ 0x4e00000301, 0x143 }, { 0x4e00000303, 0xd1 }, { 0x4e00000307, 0x1e44 }, { 0x4e0000030c, 0x147 },\n\t{ 0x4e00000323, 0x1e46 }, { 0x4e00000327, 0x145 }, { 0x4e0000032d, 0x1e4a }, { 0x4e00000331, 0x1e48 },\n\t{ 0x4f00000300, 0xd2 }, { 0x4f00000301, 0xd3 }, { 0x4f00000302, 0xd4 }, { 0x4f00000303, 0xd5 },\n\t{ 0x4f00000304, 0x14c }, { 0x4f00000306, 0x14e }, { 0x4f00000307, 0x22e }, { 0x4f00000308, 0xd6 },\n\t{ 0x4f00000309, 0x1ece }, { 0x4f0000030b, 0x150 }, { 0x4f0000030c, 0x1d1 }, { 0x4f0000030f, 0x20c },\n\t{ 0x4f00000311, 0x20e }, { 0x4f0000031b, 0x1a0 }, { 0x4f00000323, 0x1ecc }, { 0x4f00000328, 0x1ea },\n\t{ 0x5000000301, 0x1e54 }, { 0x5000000307, 0x1e56 }, { 0x5200000301, 0x154 }, { 0x5200000307, 0x1e58 },\n\t{ 0x520000030c, 0x158 }, { 0x520000030f, 0x210 }, { 0x5200000311, 0x212 }, { 0x5200000323, 0x1e5a },\n\t{ 0x5200000327, 0x156 }, { 0x5200000331, 0x1e5e }, { 0x5300000301, 0x15a }, { 0x5300000302, 0x15c },\n\t{ 0x5300000307, 0x1e60 }, { 0x530000030c, 0x160 }, { 0x5300000323, 0x1e62 }, { 0x5300000326, 0x218 },\n\t{ 0x5300000327, 0x15e }, { 0x5400000307, 0x1e6a }, { 0x540000030c, 0x164 }, { 0x5400000323, 0x1e6c },\n\t{ 0x5400000326, 0x21a }, { 0x5400000327, 0x162 }, { 0x540000032d, 0x1e70 }, { 0x5400000331, 0x1e6e },\n\t{ 0x5500000300, 0xd9 }, { 0x5500000301, 0xda }, { 0x5500000302, 0xdb }, { 0x5500000303, 0x168 },\n\t{ 0x5500000304, 0x16a }, { 0x5500000306, 0x16c }, { 0x5500000308, 0xdc }, { 0x5500000309, 0x1ee6 },\n\t{ 0x550000030a, 0x16e }, { 0x550000030b, 0x170 }, { 0x550000030c, 0x1d3 }, { 0x550000030f, 0x214 },\n\t{ 0x5500000311, 0x216 }, { 0x550000031b, 0x1af }, { 0x5500000323, 0x1ee4 }, { 0x5500000324, 0x1e72 },\n\t{ 0x5500000328, 0x172 }, { 0x550000032d, 0x1e76 }, { 0x5500000330, 0x1e74 }, { 0x5600000303, 0x1e7c },\n\t{ 0x5600000323, 0x1e7e }, { 0x5700000300, 0x1e80 }, { 0x5700000301, 0x1e82 }, { 0x5700000302, 0x174 },\n\t{ 0x5700000307, 0x1e86 }, { 0x5700000308, 0x1e84 }, { 0x5700000323, 0x1e88 }, { 0x5800000307, 0x1e8a },\n\t{ 0x5800000308, 0x1e8c }, { 0x5900000300, 0x1ef2 }, { 0x5900000301, 0xdd }, { 0x5900000302, 0x176 },\n\t{ 0x5900000303, 0x1ef8 }, { 0x5900000304, 0x232 }, { 0x5900000307, 0x1e8e }, { 0x5900000308, 0x178 },\n\t{ 0x5900000309, 0x1ef6 }, { 0x5900000323, 0x1ef4 }, { 0x5a00000301, 0x179 }, { 0x5a00000302, 0x1e90 },\n\t{ 0x5a00000307, 0x17b }, { 0x5a0000030c, 0x17d }, { 0x5a00000323, 0x1e92 }, { 0x5a00000331, 0x1e94 },\n\t{ 0x6100000300, 0xe0 }, { 0x6100000301, 0xe1 }, { 0x6100000302, 0xe2 }, { 0x6100000303, 0xe3 },\n\t{ 0x6100000304, 0x101 }, { 0x6100000306, 0x103 }, { 0x6100000307, 0x227 }, { 0x6100000308, 0xe4 },\n\t{ 0x6100000309, 0x1ea3 }, { 0x610000030a, 0xe5 }, { 0x610000030c, 0x1ce }, { 0x610000030f, 0x201 },\n\t{ 0x6100000311, 0x203 }, { 0x6100000323, 0x1ea1 }, { 0x6100000325, 0x1e01 }, { 0x6100000328, 0x105 },\n\t{ 0x6200000307, 0x1e03 }, { 0x6200000323, 0x1e05 }, { 0x6200000331, 0x1e07 }, { 0x6300000301, 0x107 },\n\t{ 0x6300000302, 0x109 }, { 0x6300000307, 0x10b }, { 0x630000030c, 0x10d }, { 0x6300000327, 0xe7 },\n\t{ 0x6400000307, 0x1e0b }, { 0x640000030c, 0x10f }, { 0x6400000323, 0x1e0d }, { 0x6400000327, 0x1e11 },\n\t{ 0x640000032d, 0x1e13 }, { 0x6400000331, 0x1e0f }, { 0x6500000300, 0xe8 }, { 0x6500000301, 0xe9 },\n\t{ 0x6500000302, 0xea }, { 0x6500000303, 0x1ebd }, { 0x6500000304, 0x113 }, { 0x6500000306, 0x115 },\n\t{ 0x6500000307, 0x117 }, { 0x6500000308, 0xeb }, { 0x6500000309, 0x1ebb }, { 0x650000030c, 0x11b },\n\t{ 0x650000030f, 0x205 }, { 0x6500000311, 0x207 }, { 0x6500000323, 0x1eb9 }, { 0x6500000327, 0x229 },\n\t{ 0x6500000328, 0x119 }, { 0x650000032d, 0x1e19 }, { 0x6500000330, 0x1e1b }, { 0x6600000307, 0x1e1f },\n\t{ 0x6700000301, 0x1f5 }, { 0x6700000302, 0x11d }, { 0x6700000304, 0x1e21 }, { 0x6700000306, 0x11f },\n\t{ 0x6700000307, 0x121 }, { 0x670000030c, 0x1e7 }, { 0x6700000327, 0x123 }, { 0x6800000302, 0x125 },\n\t{ 0x6800000307, 0x1e23 }, { 0x6800000308, 0x1e27 }, { 0x680000030c, 0x21f }, { 0x6800000323, 0x1e25 },\n\t{ 0x6800000327, 0x1e29 }, { 0x680000032e, 0x1e2b }, { 0x6800000331, 0x1e96 }, { 0x6900000300, 0xec },\n\t{ 0x6900000301, 0xed }, { 0x6900000302, 0xee }, { 0x6900000303, 0x129 }, { 0x6900000304, 0x12b },\n\t{ 0x6900000306, 0x12d }, { 0x6900000308, 0xef }, { 0x6900000309, 0x1ec9 }, { 0x690000030c, 0x1d0 },\n\t{ 0x690000030f, 0x209 }, { 0x6900000311, 0x20b }, { 0x6900000323, 0x1ecb }, { 0x6900000328, 0x12f },\n\t{ 0x6900000330, 0x1e2d }, { 0x6a00000302, 0x135 }, { 0x6a0000030c, 0x1f0 }, { 0x6b00000301, 0x1e31 },\n\t{ 0x6b0000030c, 0x1e9 }, { 0x6b00000323, 0x1e33 }, { 0x6b00000327, 0x137 }, { 0x6b00000331, 0x1e35 },\n\t{ 0x6c00000301, 0x13a }, { 0x6c0000030c, 0x13e }, { 0x6c00000323, 0x1e37 }, { 0x6c00000327, 0x13c },\n\t{ 0x6c0000032d, 0x1e3d }, { 0x6c00000331, 0x1e3b }, { 0x6d00000301, 0x1e3f }, { 0x6d00000307, 0x1e41 },\n\t{ 0x6d00000323, 0x1e43 }, { 0x6e00000300, 0x1f9 }, { 0x6e00000301, 0x144 }, { 0x6e00000303, 0xf1 },\n\t{ 0x6e00000307, 0x1e45 }, { 0x6e0000030c, 0x148 }, { 0x6e00000323, 0x1e47 }, { 0x6e00000327, 0x146 },\n\t{ 0x6e0000032d, 0x1e4b }, { 0x6e00000331, 0x1e49 }, { 0x6f00000300, 0xf2 }, { 0x6f00000301, 0xf3 },\n\t{ 0x6f00000302, 0xf4 }, { 0x6f00000303, 0xf5 }, { 0x6f00000304, 0x14d }, { 0x6f00000306, 0x14f },\n\t{ 0x6f00000307, 0x22f }, { 0x6f00000308, 0xf6 }, { 0x6f00000309, 0x1ecf }, { 0x6f0000030b, 0x151 },\n\t{ 0x6f0000030c, 0x1d2 }, { 0x6f0000030f, 0x20d }, { 0x6f00000311, 0x20f }, { 0x6f0000031b, 0x1a1 },\n\t{ 0x6f00000323, 0x1ecd }, { 0x6f00000328, 0x1eb }, { 0x7000000301, 0x1e55 }, { 0x7000000307, 0x1e57 },\n\t{ 0x7200000301, 0x155 }, { 0x7200000307, 0x1e59 }, { 0x720000030c, 0x159 }, { 0x720000030f, 0x211 },\n\t{ 0x7200000311, 0x213 }, { 0x7200000323, 0x1e5b }, { 0x7200000327, 0x157 }, { 0x7200000331, 0x1e5f },\n\t{ 0x7300000301, 0x15b }, { 0x7300000302, 0x15d }, { 0x7300000307, 0x1e61 }, { 0x730000030c, 0x161 },\n\t{ 0x7300000323, 0x1e63 }, { 0x7300000326, 0x219 }, { 0x7300000327, 0x15f }, { 0x7400000307, 0x1e6b },\n\t{ 0x7400000308, 0x1e97 }, { 0x740000030c, 0x165 }, { 0x7400000323, 0x1e6d }, { 0x7400000326, 0x21b },\n\t{ 0x7400000327, 0x163 }, { 0x740000032d, 0x1e71 }, { 0x7400000331, 0x1e6f }, { 0x7500000300, 0xf9 },\n\t{ 0x7500000301, 0xfa }, { 0x7500000302, 0xfb }, { 0x7500000303, 0x169 }, { 0x7500000304, 0x16b },\n\t{ 0x7500000306, 0x16d }, { 0x7500000308, 0xfc }, { 0x7500000309, 0x1ee7 }, { 0x750000030a, 0x16f },\n\t{ 0x750000030b, 0x171 }, { 0x750000030c, 0x1d4 }, { 0x750000030f, 0x215 }, { 0x7500000311, 0x217 },\n\t{ 0x750000031b, 0x1b0 }, { 0x7500000323, 0x1ee5 }, { 0x7500000324, 0x1e73 }, { 0x7500000328, 0x173 },\n\t{ 0x750000032d, 0x1e77 }, { 0x7500000330, 0x1e75 }, { 0x7600000303, 0x1e7d }, { 0x7600000323, 0x1e7f },\n\t{ 0x7700000300, 0x1e81 }, { 0x7700000301, 0x1e83 }, { 0x7700000302, 0x175 }, { 0x7700000307, 0x1e87 },\n\t{ 0x7700000308, 0x1e85 }, { 0x770000030a, 0x1e98 }, { 0x7700000323, 0x1e89 }, { 0x7800000307, 0x1e8b },\n\t{ 0x7800000308, 0x1e8d }, { 0x7900000300, 0x1ef3 }, { 0x7900000301, 0xfd }, { 0x7900000302, 0x177 },\n\t{ 0x7900000303, 0x1ef9 }, { 0x7900000304, 0x233 }, { 0x7900000307, 0x1e8f }, { 0x7900000308, 0xff },\n\t{ 0x7900000309, 0x1ef7 }, { 0x790000030a, 0x1e99 }, { 0x7900000323, 0x1ef5 }, { 0x7a00000301, 0x17a },\n\t{ 0x7a00000302, 0x1e91 }, { 0x7a00000307, 0x17c }, { 0x7a0000030c, 0x17e }, { 0x7a00000323, 0x1e93 },\n\t{ 0x7a00000331, 0x1e95 }, { 0xa800000300, 0x1fed }, { 0xa800000301, 0x385 }, { 0xa800000342, 0x1fc1 },\n\t{ 0xc200000300, 0x1ea6 }, { 0xc200000301, 0x1ea4 }, { 0xc200000303, 0x1eaa }, { 0xc200000309, 0x1ea8 },\n\t{ 0xc400000304, 0x1de }, { 0xc500000301, 0x1fa }, { 0xc600000301, 0x1fc }, { 0xc600000304, 0x1e2 },\n\t{ 0xc700000301, 0x1e08 }, { 0xca00000300, 0x1ec0 }, { 0xca00000301, 0x1ebe }, { 0xca00000303, 0x1ec4 },\n\t{ 0xca00000309, 0x1ec2 }, { 0xcf00000301, 0x1e2e }, { 0xd400000300, 0x1ed2 }, { 0xd400000301, 0x1ed0 },\n\t{ 0xd400000303, 0x1ed6 }, { 0xd400000309, 0x1ed4 }, { 0xd500000301, 0x1e4c }, { 0xd500000304, 0x22c },\n\t{ 0xd500000308, 0x1e4e }, { 0xd600000304, 0x22a }, { 0xd800000301, 0x1fe }, { 0xdc00000300, 0x1db },\n\t{ 0xdc00000301, 0x1d7 }, { 0xdc00000304, 0x1d5 }, { 0xdc0000030c, 0x1d9 }, { 0xe200000300, 0x1ea7 },\n\t{ 0xe200000301, 0x1ea5 }, { 0xe200000303, 0x1eab }, { 0xe200000309, 0x1ea9 }, { 0xe400000304, 0x1df },\n\t{ 0xe500000301, 0x1fb }, { 0xe600000301, 0x1fd }, { 0xe600000304, 0x1e3 }, { 0xe700000301, 0x1e09 },\n\t{ 0xea00000300, 0x1ec1 }, { 0xea00000301, 0x1ebf }, { 0xea00000303, 0x1ec5 }, { 0xea00000309, 0x1ec3 },\n\t{ 0xef00000301, 0x1e2f }, { 0xf400000300, 0x1ed3 }, { 0xf400000301, 0x1ed1 }, { 0xf400000303, 0x1ed7 },\n\t{ 0xf400000309, 0x1ed5 }, { 0xf500000301, 0x1e4d }, { 0xf500000304, 0x22d }, { 0xf500000308, 0x1e4f },\n\t{ 0xf600000304, 0x22b }, { 0xf800000301, 0x1ff }, { 0xfc00000300, 0x1dc }, { 0xfc00000301, 0x1d8 },\n\t{ 0xfc00000304, 0x1d6 }, { 0xfc0000030c, 0x1da }, { 0x10200000300, 0x1eb0 }, { 0x10200000301, 0x1eae },\n\t{ 0x10200000303, 0x1eb4 }, { 0x10200000309, 0x1eb2 }, { 0x10300000300, 0x1eb1 }, { 0x10300000301, 0x1eaf },\n\t{ 0x10300000303, 0x1eb5 }, { 0x10300000309, 0x1eb3 }, { 0x11200000300, 0x1e14 }, { 0x11200000301, 0x1e16 },\n\t{ 0x11300000300, 0x1e15 }, { 0x11300000301, 0x1e17 }, { 0x14c00000300, 0x1e50 }, { 0x14c00000301, 0x1e52 },\n\t{ 0x14d00000300, 0x1e51 }, { 0x14d00000301, 0x1e53 }, { 0x15a00000307, 0x1e64 }, { 0x15b00000307, 0x1e65 },\n\t{ 0x16000000307, 0x1e66 }, { 0x16100000307, 0x1e67 }, { 0x16800000301, 0x1e78 }, { 0x16900000301, 0x1e79 },\n\t{ 0x16a00000308, 0x1e7a }, { 0x16b00000308, 0x1e7b }, { 0x17f00000307, 0x1e9b }, { 0x1a000000300, 0x1edc },\n\t{ 0x1a000000301, 0x1eda }, { 0x1a000000303, 0x1ee0 }, { 0x1a000000309, 0x1ede }, { 0x1a000000323, 0x1ee2 },\n\t{ 0x1a100000300, 0x1edd }, { 0x1a100000301, 0x1edb }, { 0x1a100000303, 0x1ee1 }, { 0x1a100000309, 0x1edf },\n\t{ 0x1a100000323, 0x1ee3 }, { 0x1af00000300, 0x1eea }, { 0x1af00000301, 0x1ee8 }, { 0x1af00000303, 0x1eee },\n\t{ 0x1af00000309, 0x1eec }, { 0x1af00000323, 0x1ef0 }, { 0x1b000000300, 0x1eeb }, { 0x1b000000301, 0x1ee9 },\n\t{ 0x1b000000303, 0x1eef }, { 0x1b000000309, 0x1eed }, { 0x1b000000323, 0x1ef1 }, { 0x1b70000030c, 0x1ee },\n\t{ 0x1ea00000304, 0x1ec }, { 0x1eb00000304, 0x1ed }, { 0x22600000304, 0x1e0 }, { 0x22700000304, 0x1e1 },\n\t{ 0x22800000306, 0x1e1c }, { 0x22900000306, 0x1e1d }, { 0x22e00000304, 0x230 }, { 0x22f00000304, 0x231 },\n\t{ 0x2920000030c, 0x1ef }, { 0x39100000300, 0x1fba }, { 0x39100000301, 0x386 }, { 0x39100000304, 0x1fb9 },\n\t{ 0x39100000306, 0x1fb8 }, { 0x39100000313, 0x1f08 }, { 0x39100000314, 0x1f09 }, { 0x39100000345, 0x1fbc },\n\t{ 0x39500000300, 0x1fc8 }, { 0x39500000301, 0x388 }, { 0x39500000313, 0x1f18 }, { 0x39500000314, 0x1f19 },\n\t{ 0x39700000300, 0x1fca }, { 0x39700000301, 0x389 }, { 0x39700000313, 0x1f28 }, { 0x39700000314, 0x1f29 },\n\t{ 0x39700000345, 0x1fcc }, { 0x39900000300, 0x1fda }, { 0x39900000301, 0x38a }, { 0x39900000304, 0x1fd9 },\n\t{ 0x39900000306, 0x1fd8 }, { 0x39900000308, 0x3aa }, { 0x39900000313, 0x1f38 }, { 0x39900000314, 0x1f39 },\n\t{ 0x39f00000300, 0x1ff8 }, { 0x39f00000301, 0x38c }, { 0x39f00000313, 0x1f48 }, { 0x39f00000314, 0x1f49 },\n\t{ 0x3a100000314, 0x1fec }, { 0x3a500000300, 0x1fea }, { 0x3a500000301, 0x38e }, { 0x3a500000304, 0x1fe9 },\n\t{ 0x3a500000306, 0x1fe8 }, { 0x3a500000308, 0x3ab }, { 0x3a500000314, 0x1f59 }, { 0x3a900000300, 0x1ffa },\n\t{ 0x3a900000301, 0x38f }, { 0x3a900000313, 0x1f68 }, { 0x3a900000314, 0x1f69 }, { 0x3a900000345, 0x1ffc },\n\t{ 0x3ac00000345, 0x1fb4 }, { 0x3ae00000345, 0x1fc4 }, { 0x3b100000300, 0x1f70 }, { 0x3b100000301, 0x3ac },\n\t{ 0x3b100000304, 0x1fb1 }, { 0x3b100000306, 0x1fb0 }, { 0x3b100000313, 0x1f00 }, { 0x3b100000314, 0x1f01 },\n\t{ 0x3b100000342, 0x1fb6 }, { 0x3b100000345, 0x1fb3 }, { 0x3b500000300, 0x1f72 }, { 0x3b500000301, 0x3ad },\n\t{ 0x3b500000313, 0x1f10 }, { 0x3b500000314, 0x1f11 }, { 0x3b700000300, 0x1f74 }, { 0x3b700000301, 0x3ae },\n\t{ 0x3b700000313, 0x1f20 }, { 0x3b700000314, 0x1f21 }, { 0x3b700000342, 0x1fc6 }, { 0x3b700000345, 0x1fc3 },\n\t{ 0x3b900000300, 0x1f76 }, { 0x3b900000301, 0x3af }, { 0x3b900000304, 0x1fd1 }, { 0x3b900000306, 0x1fd0 },\n\t{ 0x3b900000308, 0x3ca }, { 0x3b900000313, 0x1f30 }, { 0x3b900000314, 0x1f31 }, { 0x3b900000342, 0x1fd6 },\n\t{ 0x3bf00000300, 0x1f78 }, { 0x3bf00000301, 0x3cc }, { 0x3bf00000313, 0x1f40 }, { 0x3bf00000314, 0x1f41 },\n\t{ 0x3c100000313, 0x1fe4 }, { 0x3c100000314, 0x1fe5 }, { 0x3c500000300, 0x1f7a }, { 0x3c500000301, 0x3cd },\n\t{ 0x3c500000304, 0x1fe1 }, { 0x3c500000306, 0x1fe0 }, { 0x3c500000308, 0x3cb }, { 0x3c500000313, 0x1f50 },\n\t{ 0x3c500000314, 0x1f51 }, { 0x3c500000342, 0x1fe6 }, { 0x3c900000300, 0x1f7c }, { 0x3c900000301, 0x3ce },\n\t{ 0x3c900000313, 0x1f60 }, { 0x3c900000314, 0x1f61 }, { 0x3c900000342, 0x1ff6 }, { 0x3c900000345, 0x1ff3 },\n\t{ 0x3ca00000300, 0x1fd2 }, { 0x3ca00000301, 0x390 }, { 0x3ca00000342, 0x1fd7 }, { 0x3cb00000300, 0x1fe2 },\n\t{ 0x3cb00000301, 0x3b0 }, { 0x3cb00000342, 0x1fe7 }, { 0x3ce00000345, 0x1ff4 }, { 0x3d200000301, 0x3d3 },\n\t{ 0x3d200000308, 0x3d4 }, { 0x40600000308, 0x407 }, { 0x41000000306, 0x4d0 }, { 0x41000000308, 0x4d2 },\n\t{ 0x41300000301, 0x403 }, { 0x41500000300, 0x400 }, { 0x41500000306, 0x4d6 }, { 0x41500000308, 0x401 },\n\t{ 0x41600000306, 0x4c1 }, { 0x41600000308, 0x4dc }, { 0x41700000308, 0x4de }, { 0x41800000300, 0x40d },\n\t{ 0x41800000304, 0x4e2 }, { 0x41800000306, 0x419 }, { 0x41800000308, 0x4e4 }, { 0x41a00000301, 0x40c },\n\t{ 0x41e00000308, 0x4e6 }, { 0x42300000304, 0x4ee }, { 0x42300000306, 0x40e }, { 0x42300000308, 0x4f0 },\n\t{ 0x4230000030b, 0x4f2 }, { 0x42700000308, 0x4f4 }, { 0x42b00000308, 0x4f8 }, { 0x42d00000308, 0x4ec },\n\t{ 0x43000000306, 0x4d1 }, { 0x43000000308, 0x4d3 }, { 0x43300000301, 0x453 }, { 0x43500000300, 0x450 },\n\t{ 0x43500000306, 0x4d7 }, { 0x43500000308, 0x451 }, { 0x43600000306, 0x4c2 }, { 0x43600000308, 0x4dd },\n\t{ 0x43700000308, 0x4df }, { 0x43800000300, 0x45d }, { 0x43800000304, 0x4e3 }, { 0x43800000306, 0x439 },\n\t{ 0x43800000308, 0x4e5 }, { 0x43a00000301, 0x45c }, { 0x43e00000308, 0x4e7 }, { 0x44300000304, 0x4ef },\n\t{ 0x44300000306, 0x45e }, { 0x44300000308, 0x4f1 }, { 0x4430000030b, 0x4f3 }, { 0x44700000308, 0x4f5 },\n\t{ 0x44b00000308, 0x4f9 }, { 0x44d00000308, 0x4ed }, { 0x45600000308, 0x457 }, { 0x4740000030f, 0x476 },\n\t{ 0x4750000030f, 0x477 }, { 0x4d800000308, 0x4da }, { 0x4d900000308, 0x4db }, { 0x4e800000308, 0x4ea },\n\t{ 0x4e900000308, 0x4eb }, { 0x62700000653, 0x622 }, { 0x62700000654, 0x623 }, { 0x62700000655, 0x625 },\n\t{ 0x64800000654, 0x624 }, { 0x64a00000654, 0x626 }, { 0x6c100000654, 0x6c2 }, { 0x6d200000654, 0x6d3 },\n\t{ 0x6d500000654, 0x6c0 }, { 0x9280000093c, 0x929 }, { 0x9300000093c, 0x931 }, { 0x9330000093c, 0x934 },\n\t{ 0x9c7000009be, 0x9cb }, { 0x9c7000009d7, 0x9cc }, { 0xb4700000b3e, 0xb4b }, { 0xb4700000b56, 0xb48 },\n\t{ 0xb4700000b57, 0xb4c }, { 0xb9200000bd7, 0xb94 }, { 0xbc600000bbe, 0xbca }, { 0xbc600000bd7, 0xbcc },\n\t{ 0xbc700000bbe, 0xbcb }, { 0xc4600000c56, 0xc48 }, { 0xcbf00000cd5, 0xcc0 }, { 0xcc600000cc2, 0xcca },\n\t{ 0xcc600000cd5, 0xcc7 }, { 0xcc600000cd6, 0xcc8 }, { 0xcca00000cd5, 0xccb }, { 0xd4600000d3e, 0xd4a },\n\t{ 0xd4600000d57, 0xd4c }, { 0xd4700000d3e, 0xd4b }, { 0xdd900000dca, 0xdda }, { 0xdd900000dcf, 0xddc },\n\t{ 0xdd900000ddf, 0xdde }, { 0xddc00000dca, 0xddd }, { 0x10250000102e, 0x1026 }, { 0x1b0500001b35, 0x1b06 },\n\t{ 0x1b0700001b35, 0x1b08 }, { 0x1b0900001b35, 0x1b0a }, { 0x1b0b00001b35, 0x1b0c }, { 0x1b0d00001b35, 0x1b0e },\n\t{ 0x1b1100001b35, 0x1b12 }, { 0x1b3a00001b35, 0x1b3b }, { 0x1b3c00001b35, 0x1b3d }, { 0x1b3e00001b35, 0x1b40 },\n\t{ 0x1b3f00001b35, 0x1b41 }, { 0x1b4200001b35, 0x1b43 }, { 0x1e3600000304, 0x1e38 }, { 0x1e3700000304, 0x1e39 },\n\t{ 0x1e5a00000304, 0x1e5c }, { 0x1e5b00000304, 0x1e5d }, { 0x1e6200000307, 0x1e68 }, { 0x1e6300000307, 0x1e69 },\n\t{ 0x1ea000000302, 0x1eac }, { 0x1ea000000306, 0x1eb6 }, { 0x1ea100000302, 0x1ead }, { 0x1ea100000306, 0x1eb7 },\n\t{ 0x1eb800000302, 0x1ec6 }, { 0x1eb900000302, 0x1ec7 }, { 0x1ecc00000302, 0x1ed8 }, { 0x1ecd00000302, 0x1ed9 },\n\t{ 0x1f0000000300, 0x1f02 }, { 0x1f0000000301, 0x1f04 }, { 0x1f0000000342, 0x1f06 }, { 0x1f0000000345, 0x1f80 },\n\t{ 0x1f0100000300, 0x1f03 }, { 0x1f0100000301, 0x1f05 }, { 0x1f0100000342, 0x1f07 }, { 0x1f0100000345, 0x1f81 },\n\t{ 0x1f0200000345, 0x1f82 }, { 0x1f0300000345, 0x1f83 }, { 0x1f0400000345, 0x1f84 }, { 0x1f0500000345, 0x1f85 },\n\t{ 0x1f0600000345, 0x1f86 }, { 0x1f0700000345, 0x1f87 }, { 0x1f0800000300, 0x1f0a }, { 0x1f0800000301, 0x1f0c },\n\t{ 0x1f0800000342, 0x1f0e }, { 0x1f0800000345, 0x1f88 }, { 0x1f0900000300, 0x1f0b }, { 0x1f0900000301, 0x1f0d },\n\t{ 0x1f0900000342, 0x1f0f }, { 0x1f0900000345, 0x1f89 }, { 0x1f0a00000345, 0x1f8a }, { 0x1f0b00000345, 0x1f8b },\n\t{ 0x1f0c00000345, 0x1f8c }, { 0x1f0d00000345, 0x1f8d }, { 0x1f0e00000345, 0x1f8e }, { 0x1f0f00000345, 0x1f8f },\n\t{ 0x1f1000000300, 0x1f12 }, { 0x1f1000000301, 0x1f14 }, { 0x1f1100000300, 0x1f13 }, { 0x1f1100000301, 0x1f15 },\n\t{ 0x1f1800000300, 0x1f1a }, { 0x1f1800000301, 0x1f1c }, { 0x1f1900000300, 0x1f1b }, { 0x1f1900000301, 0x1f1d },\n\t{ 0x1f2000000300, 0x1f22 }, { 0x1f2000000301, 0x1f24 }, { 0x1f2000000342, 0x1f26 }, { 0x1f2000000345, 0x1f90 },\n\t{ 0x1f2100000300, 0x1f23 }, { 0x1f2100000301, 0x1f25 }, { 0x1f2100000342, 0x1f27 }, { 0x1f2100000345, 0x1f91 },\n\t{ 0x1f2200000345, 0x1f92 }, { 0x1f2300000345, 0x1f93 }, { 0x1f2400000345, 0x1f94 }, { 0x1f2500000345, 0x1f95 },\n\t{ 0x1f2600000345, 0x1f96 }, { 0x1f2700000345, 0x1f97 }, { 0x1f2800000300, 0x1f2a }, { 0x1f2800000301, 0x1f2c },\n\t{ 0x1f2800000342, 0x1f2e }, { 0x1f2800000345, 0x1f98 }, { 0x1f2900000300, 0x1f2b }, { 0x1f2900000301, 0x1f2d },\n\t{ 0x1f2900000342, 0x1f2f }, { 0x1f2900000345, 0x1f99 }, { 0x1f2a00000345, 0x1f9a }, { 0x1f2b00000345, 0x1f9b },\n\t{ 0x1f2c00000345, 0x1f9c }, { 0x1f2d00000345, 0x1f9d }, { 0x1f2e00000345, 0x1f9e }, { 0x1f2f00000345, 0x1f9f },\n\t{ 0x1f3000000300, 0x1f32 }, { 0x1f3000000301, 0x1f34 }, { 0x1f3000000342, 0x1f36 }, { 0x1f3100000300, 0x1f33 },\n\t{ 0x1f3100000301, 0x1f35 }, { 0x1f3100000342, 0x1f37 }, { 0x1f3800000300, 0x1f3a }, { 0x1f3800000301, 0x1f3c },\n\t{ 0x1f3800000342, 0x1f3e }, { 0x1f3900000300, 0x1f3b }, { 0x1f3900000301, 0x1f3d }, { 0x1f3900000342, 0x1f3f },\n\t{ 0x1f4000000300, 0x1f42 }, { 0x1f4000000301, 0x1f44 }, { 0x1f4100000300, 0x1f43 }, { 0x1f4100000301, 0x1f45 },\n\t{ 0x1f4800000300, 0x1f4a }, { 0x1f4800000301, 0x1f4c }, { 0x1f4900000300, 0x1f4b }, { 0x1f4900000301, 0x1f4d },\n\t{ 0x1f5000000300, 0x1f52 }, { 0x1f5000000301, 0x1f54 }, { 0x1f5000000342, 0x1f56 }, { 0x1f5100000300, 0x1f53 },\n\t{ 0x1f5100000301, 0x1f55 }, { 0x1f5100000342, 0x1f57 }, { 0x1f5900000300, 0x1f5b }, { 0x1f5900000301, 0x1f5d },\n\t{ 0x1f5900000342, 0x1f5f }, { 0x1f6000000300, 0x1f62 }, { 0x1f6000000301, 0x1f64 }, { 0x1f6000000342, 0x1f66 },\n\t{ 0x1f6000000345, 0x1fa0 }, { 0x1f6100000300, 0x1f63 }, { 0x1f6100000301, 0x1f65 }, { 0x1f6100000342, 0x1f67 },\n\t{ 0x1f6100000345, 0x1fa1 }, { 0x1f6200000345, 0x1fa2 }, { 0x1f6300000345, 0x1fa3 }, { 0x1f6400000345, 0x1fa4 },\n\t{ 0x1f6500000345, 0x1fa5 }, { 0x1f6600000345, 0x1fa6 }, { 0x1f6700000345, 0x1fa7 }, { 0x1f6800000300, 0x1f6a },\n\t{ 0x1f6800000301, 0x1f6c }, { 0x1f6800000342, 0x1f6e }, { 0x1f6800000345, 0x1fa8 }, { 0x1f6900000300, 0x1f6b },\n\t{ 0x1f6900000301, 0x1f6d }, { 0x1f6900000342, 0x1f6f }, { 0x1f6900000345, 0x1fa9 }, { 0x1f6a00000345, 0x1faa },\n\t{ 0x1f6b00000345, 0x1fab }, { 0x1f6c00000345, 0x1fac }, { 0x1f6d00000345, 0x1fad }, { 0x1f6e00000345, 0x1fae },\n\t{ 0x1f6f00000345, 0x1faf }, { 0x1f7000000345, 0x1fb2 }, { 0x1f7400000345, 0x1fc2 }, { 0x1f7c00000345, 0x1ff2 },\n\t{ 0x1fb600000345, 0x1fb7 }, { 0x1fbf00000300, 0x1fcd }, { 0x1fbf00000301, 0x1fce }, { 0x1fbf00000342, 0x1fcf },\n\t{ 0x1fc600000345, 0x1fc7 }, { 0x1ff600000345, 0x1ff7 }, { 0x1ffe00000300, 0x1fdd }, { 0x1ffe00000301, 0x1fde },\n\t{ 0x1ffe00000342, 0x1fdf }, { 0x219000000338, 0x219a }, { 0x219200000338, 0x219b }, { 0x219400000338, 0x21ae },\n\t{ 0x21d000000338, 0x21cd }, { 0x21d200000338, 0x21cf }, { 0x21d400000338, 0x21ce }, { 0x220300000338, 0x2204 },\n\t{ 0x220800000338, 0x2209 }, { 0x220b00000338, 0x220c }, { 0x222300000338, 0x2224 }, { 0x222500000338, 0x2226 },\n\t{ 0x223c00000338, 0x2241 }, { 0x224300000338, 0x2244 }, { 0x224500000338, 0x2247 }, { 0x224800000338, 0x2249 },\n\t{ 0x224d00000338, 0x226d }, { 0x226100000338, 0x2262 }, { 0x226400000338, 0x2270 }, { 0x226500000338, 0x2271 },\n\t{ 0x227200000338, 0x2274 }, { 0x227300000338, 0x2275 }, { 0x227600000338, 0x2278 }, { 0x227700000338, 0x2279 },\n\t{ 0x227a00000338, 0x2280 }, { 0x227b00000338, 0x2281 }, { 0x227c00000338, 0x22e0 }, { 0x227d00000338, 0x22e1 },\n\t{ 0x228200000338, 0x2284 }, { 0x228300000338, 0x2285 }, { 0x228600000338, 0x2288 }, { 0x228700000338, 0x2289 },\n\t{ 0x229100000338, 0x22e2 }, { 0x229200000338, 0x22e3 }, { 0x22a200000338, 0x22ac }, { 0x22a800000338, 0x22ad },\n\t{ 0x22a900000338, 0x22ae }, { 0x22ab00000338, 0x22af }, { 0x22b200000338, 0x22ea }, { 0x22b300000338, 0x22eb },\n\t{ 0x22b400000338, 0x22ec }, { 0x22b500000338, 0x22ed }, { 0x304600003099, 0x3094 }, { 0x304b00003099, 0x304c },\n\t{ 0x304d00003099, 0x304e }, { 0x304f00003099, 0x3050 }, { 0x305100003099, 0x3052 }, { 0x305300003099, 0x3054 },\n\t{ 0x305500003099, 0x3056 }, { 0x305700003099, 0x3058 }, { 0x305900003099, 0x305a }, { 0x305b00003099, 0x305c },\n\t{ 0x305d00003099, 0x305e }, { 0x305f00003099, 0x3060 }, { 0x306100003099, 0x3062 }, { 0x306400003099, 0x3065 },\n\t{ 0x306600003099, 0x3067 }, { 0x306800003099, 0x3069 }, { 0x306f00003099, 0x3070 }, { 0x306f0000309a, 0x3071 },\n\t{ 0x307200003099, 0x3073 }, { 0x30720000309a, 0x3074 }, { 0x307500003099, 0x3076 }, { 0x30750000309a, 0x3077 },\n\t{ 0x307800003099, 0x3079 }, { 0x30780000309a, 0x307a }, { 0x307b00003099, 0x307c }, { 0x307b0000309a, 0x307d },\n\t{ 0x309d00003099, 0x309e }, { 0x30a600003099, 0x30f4 }, { 0x30ab00003099, 0x30ac }, { 0x30ad00003099, 0x30ae },\n\t{ 0x30af00003099, 0x30b0 }, { 0x30b100003099, 0x30b2 }, { 0x30b300003099, 0x30b4 }, { 0x30b500003099, 0x30b6 },\n\t{ 0x30b700003099, 0x30b8 }, { 0x30b900003099, 0x30ba }, { 0x30bb00003099, 0x30bc }, { 0x30bd00003099, 0x30be },\n\t{ 0x30bf00003099, 0x30c0 }, { 0x30c100003099, 0x30c2 }, { 0x30c400003099, 0x30c5 }, { 0x30c600003099, 0x30c7 },\n\t{ 0x30c800003099, 0x30c9 }, { 0x30cf00003099, 0x30d0 }, { 0x30cf0000309a, 0x30d1 }, { 0x30d200003099, 0x30d3 },\n\t{ 0x30d20000309a, 0x30d4 }, { 0x30d500003099, 0x30d6 }, { 0x30d50000309a, 0x30d7 }, { 0x30d800003099, 0x30d9 },\n\t{ 0x30d80000309a, 0x30da }, { 0x30db00003099, 0x30dc }, { 0x30db0000309a, 0x30dd }, { 0x30ef00003099, 0x30f7 },\n\t{ 0x30f000003099, 0x30f8 }, { 0x30f100003099, 0x30f9 }, { 0x30f200003099, 0x30fa }, { 0x30fd00003099, 0x30fe },\n\t{ 0x11099000110ba, 0x1109a }, { 0x1109b000110ba, 0x1109c }, { 0x110a5000110ba, 0x110ab }, { 0x1113100011127, 0x1112e },\n\t{ 0x1113200011127, 0x1112f }, { 0x113470001133e, 0x1134b }, { 0x1134700011357, 0x1134c }, { 0x114b9000114b0, 0x114bc },\n\t{ 0x114b9000114ba, 0x114bb }, { 0x114b9000114bd, 0x114be }, { 0x115b8000115af, 0x115ba }, { 0x115b9000115af, 0x115bb },\n};\nconst CompositionRecord* UnicodeCompositionRecordPtr = UnicodeCompositionRecord;\n\nconst char* CompressedStringData =\n\t\"\\x41\\xCC\\x80\\x41\\xCC\\x81\\x41\\xCC\\x82\\x41\\xCC\\x83\\x41\\xCC\\x88\\x41\\xCC\\x8A\\x43\\xCC\\xA7\\x45\\xCC\\x80\\x45\"\n\t\"\\xCC\\x81\\x45\\xCC\\x82\\x45\\xCC\\x88\\x49\\xCC\\x80\\x49\\xCC\\x81\\x49\\xCC\\x82\\x49\\xCC\\x88\\x4E\\xCC\\x83\\x4F\\xCC\"\n\t\"\\x80\\x4F\\xCC\\x81\\x4F\\xCC\\x82\\x4F\\xCC\\x83\\x4F\\xCC\\x88\\x55\\xCC\\x80\\x55\\xCC\\x81\\x55\\xCC\\x82\\x55\\xCC\\x88\"\n\t\"\\x59\\xCC\\x81\\x61\\xCC\\x80\\x61\\xCC\\x81\\x61\\xCC\\x82\\x61\\xCC\\x83\\x61\\xCC\\x88\\x61\\xCC\\x8A\\x63\\xCC\\xA7\\x65\"\n\t\"\\xCC\\x80\\x65\\xCC\\x81\\x65\\xCC\\x82\\x65\\xCC\\x88\\x69\\xCC\\x80\\x69\\xCC\\x81\\x69\\xCC\\x82\\x69\\xCC\\x88\\x6E\\xCC\"\n\t\"\\x83\\x6F\\xCC\\x80\\x6F\\xCC\\x81\\x6F\\xCC\\x82\\x6F\\xCC\\x83\\x6F\\xCC\\x88\\x75\\xCC\\x80\\x75\\xCC\\x81\\x75\\xCC\\x82\"\n\t\"\\x75\\xCC\\x88\\x79\\xCC\\x81\\x79\\xCC\\x88\\x41\\xCC\\x84\\x61\\xCC\\x84\\x41\\xCC\\x86\\x61\\xCC\\x86\\x41\\xCC\\xA8\\x61\"\n\t\"\\xCC\\xA8\\x43\\xCC\\x81\\x63\\xCC\\x81\\x43\\xCC\\x82\\x63\\xCC\\x82\\x43\\xCC\\x87\\x63\\xCC\\x87\\x43\\xCC\\x8C\\x63\\xCC\"\n\t\"\\x8C\\x44\\xCC\\x8C\\x64\\xCC\\x8C\\x45\\xCC\\x84\\x65\\xCC\\x84\\x45\\xCC\\x86\\x65\\xCC\\x86\\x45\\xCC\\x87\\x65\\xCC\\x87\"\n\t\"\\x45\\xCC\\xA8\\x65\\xCC\\xA8\\x45\\xCC\\x8C\\x65\\xCC\\x8C\\x47\\xCC\\x82\\x67\\xCC\\x82\\x47\\xCC\\x86\\x67\\xCC\\x86\\x47\"\n\t\"\\xCC\\x87\\x67\\xCC\\x87\\x47\\xCC\\xA7\\x67\\xCC\\xA7\\x48\\xCC\\x82\\x68\\xCC\\x82\\x49\\xCC\\x83\\x69\\xCC\\x83\\x49\\xCC\"\n\t\"\\x84\\x69\\xCC\\x84\\x49\\xCC\\x86\\x69\\xCC\\x86\\x49\\xCC\\xA8\\x69\\xCC\\xA8\\x49\\xCC\\x87\\x4A\\xCC\\x82\\x6A\\xCC\\x82\"\n\t\"\\x4B\\xCC\\xA7\\x6B\\xCC\\xA7\\x4C\\xCC\\x81\\x6C\\xCC\\x81\\x4C\\xCC\\xA7\\x6C\\xCC\\xA7\\x4C\\xCC\\x8C\\x6C\\xCC\\x8C\\x4E\"\n\t\"\\xCC\\x81\\x6E\\xCC\\x81\\x4E\\xCC\\xA7\\x6E\\xCC\\xA7\\x4E\\xCC\\x8C\\x6E\\xCC\\x8C\\x4F\\xCC\\x84\\x6F\\xCC\\x84\\x4F\\xCC\"\n\t\"\\x86\\x6F\\xCC\\x86\\x4F\\xCC\\x8B\\x6F\\xCC\\x8B\\x52\\xCC\\x81\\x72\\xCC\\x81\\x52\\xCC\\xA7\\x72\\xCC\\xA7\\x52\\xCC\\x8C\"\n\t\"\\x72\\xCC\\x8C\\x53\\xCC\\x81\\x73\\xCC\\x81\\x53\\xCC\\x82\\x73\\xCC\\x82\\x53\\xCC\\xA7\\x73\\xCC\\xA7\\x53\\xCC\\x8C\\x73\"\n\t\"\\xCC\\x8C\\x54\\xCC\\xA7\\x74\\xCC\\xA7\\x54\\xCC\\x8C\\x74\\xCC\\x8C\\x55\\xCC\\x83\\x75\\xCC\\x83\\x55\\xCC\\x84\\x75\\xCC\"\n\t\"\\x84\\x55\\xCC\\x86\\x75\\xCC\\x86\\x55\\xCC\\x8A\\x75\\xCC\\x8A\\x55\\xCC\\x8B\\x75\\xCC\\x8B\\x55\\xCC\\xA8\\x75\\xCC\\xA8\"\n\t\"\\x57\\xCC\\x82\\x77\\xCC\\x82\\x59\\xCC\\x82\\x79\\xCC\\x82\\x59\\xCC\\x88\\x5A\\xCC\\x81\\x7A\\xCC\\x81\\x5A\\xCC\\x87\\x7A\"\n\t\"\\xCC\\x87\\x5A\\xCC\\x8C\\x7A\\xCC\\x8C\\x4F\\xCC\\x9B\\x6F\\xCC\\x9B\\x55\\xCC\\x9B\\x75\\xCC\\x9B\\x41\\xCC\\x8C\\x61\\xCC\"\n\t\"\\x8C\\x49\\xCC\\x8C\\x69\\xCC\\x8C\\x4F\\xCC\\x8C\\x6F\\xCC\\x8C\\x55\\xCC\\x8C\\x75\\xCC\\x8C\\x55\\xCC\\x88\\xCC\\x84\\x75\"\n\t\"\\xCC\\x88\\xCC\\x84\\x55\\xCC\\x88\\xCC\\x81\\x75\\xCC\\x88\\xCC\\x81\\x55\\xCC\\x88\\xCC\\x8C\\x75\\xCC\\x88\\xCC\\x8C\\x55\"\n\t\"\\xCC\\x88\\xCC\\x80\\x75\\xCC\\x88\\xCC\\x80\\x41\\xCC\\x88\\xCC\\x84\\x61\\xCC\\x88\\xCC\\x84\\x41\\xCC\\x87\\xCC\\x84\\x61\"\n\t\"\\xCC\\x87\\xCC\\x84\\xC3\\x86\\xCC\\x84\\xC3\\xA6\\xCC\\x84\\x47\\xCC\\x8C\\x67\\xCC\\x8C\\x4B\\xCC\\x8C\\x6B\\xCC\\x8C\\x4F\"\n\t\"\\xCC\\xA8\\x6F\\xCC\\xA8\\x4F\\xCC\\xA8\\xCC\\x84\\x6F\\xCC\\xA8\\xCC\\x84\\xC6\\xB7\\xCC\\x8C\\xCA\\x92\\xCC\\x8C\\x6A\\xCC\"\n\t\"\\x8C\\x47\\xCC\\x81\\x67\\xCC\\x81\\x4E\\xCC\\x80\\x6E\\xCC\\x80\\x41\\xCC\\x8A\\xCC\\x81\\x61\\xCC\\x8A\\xCC\\x81\\xC3\\x86\"\n\t\"\\xCC\\x81\\xC3\\xA6\\xCC\\x81\\xC3\\x98\\xCC\\x81\\xC3\\xB8\\xCC\\x81\\x41\\xCC\\x8F\\x61\\xCC\\x8F\\x41\\xCC\\x91\\x61\\xCC\"\n\t\"\\x91\\x45\\xCC\\x8F\\x65\\xCC\\x8F\\x45\\xCC\\x91\\x65\\xCC\\x91\\x49\\xCC\\x8F\\x69\\xCC\\x8F\\x49\\xCC\\x91\\x69\\xCC\\x91\"\n\t\"\\x4F\\xCC\\x8F\\x6F\\xCC\\x8F\\x4F\\xCC\\x91\\x6F\\xCC\\x91\\x52\\xCC\\x8F\\x72\\xCC\\x8F\\x52\\xCC\\x91\\x72\\xCC\\x91\\x55\"\n\t\"\\xCC\\x8F\\x75\\xCC\\x8F\\x55\\xCC\\x91\\x75\\xCC\\x91\\x53\\xCC\\xA6\\x73\\xCC\\xA6\\x54\\xCC\\xA6\\x74\\xCC\\xA6\\x48\\xCC\"\n\t\"\\x8C\\x68\\xCC\\x8C\\x45\\xCC\\xA7\\x65\\xCC\\xA7\\x4F\\xCC\\x88\\xCC\\x84\\x6F\\xCC\\x88\\xCC\\x84\\x4F\\xCC\\x83\\xCC\\x84\"\n\t\"\\x6F\\xCC\\x83\\xCC\\x84\\x4F\\xCC\\x87\\x6F\\xCC\\x87\\x4F\\xCC\\x87\\xCC\\x84\\x6F\\xCC\\x87\\xCC\\x84\\x59\\xCC\\x84\\x79\"\n\t\"\\xCC\\x84\\xCC\\x93\\xCA\\xB9\\x3B\\xC2\\xA8\\xCC\\x81\\xCE\\x91\\xCC\\x81\\xC2\\xB7\\xCE\\x95\\xCC\\x81\\xCE\\x97\\xCC\\x81\"\n\t\"\\xCE\\x99\\xCC\\x81\\xCE\\x9F\\xCC\\x81\\xCE\\xA5\\xCC\\x81\\xCE\\xA9\\xCC\\x81\\xCE\\xB9\\xCC\\x88\\xCC\\x81\\xCE\\x99\\xCC\"\n\t\"\\x88\\xCE\\xA5\\xCC\\x88\\xCE\\xB1\\xCC\\x81\\xCE\\xB5\\xCC\\x81\\xCE\\xB7\\xCC\\x81\\xCE\\xB9\\xCC\\x81\\xCF\\x85\\xCC\\x88\"\n\t\"\\xCC\\x81\\xCE\\xBF\\xCC\\x81\\xCF\\x85\\xCC\\x81\\xCF\\x89\\xCC\\x81\\xCF\\x92\\xCC\\x81\\xCF\\x92\\xCC\\x88\\xD0\\x95\\xCC\"\n\t\"\\x80\\xD0\\x95\\xCC\\x88\\xD0\\x93\\xCC\\x81\\xD0\\x86\\xCC\\x88\\xD0\\x9A\\xCC\\x81\\xD0\\x98\\xCC\\x80\\xD0\\xA3\\xCC\\x86\"\n\t\"\\xD0\\x98\\xCC\\x86\\xD0\\xB8\\xCC\\x86\\xD0\\xB5\\xCC\\x80\\xD0\\xB5\\xCC\\x88\\xD0\\xB3\\xCC\\x81\\xD1\\x96\\xCC\\x88\\xD0\"\n\t\"\\xBA\\xCC\\x81\\xD0\\xB8\\xCC\\x80\\xD1\\x83\\xCC\\x86\\xD1\\xB4\\xCC\\x8F\\xD1\\xB5\\xCC\\x8F\\xD0\\x96\\xCC\\x86\\xD0\\xB6\"\n\t\"\\xCC\\x86\\xD0\\x90\\xCC\\x86\\xD0\\xB0\\xCC\\x86\\xD0\\x90\\xCC\\x88\\xD0\\xB0\\xCC\\x88\\xD0\\x95\\xCC\\x86\\xD0\\xB5\\xCC\"\n\t\"\\x86\\xD3\\x98\\xCC\\x88\\xD3\\x99\\xCC\\x88\\xD0\\x96\\xCC\\x88\\xD0\\xB6\\xCC\\x88\\xD0\\x97\\xCC\\x88\\xD0\\xB7\\xCC\\x88\"\n\t\"\\xD0\\x98\\xCC\\x84\\xD0\\xB8\\xCC\\x84\\xD0\\x98\\xCC\\x88\\xD0\\xB8\\xCC\\x88\\xD0\\x9E\\xCC\\x88\\xD0\\xBE\\xCC\\x88\\xD3\"\n\t\"\\xA8\\xCC\\x88\\xD3\\xA9\\xCC\\x88\\xD0\\xAD\\xCC\\x88\\xD1\\x8D\\xCC\\x88\\xD0\\xA3\\xCC\\x84\\xD1\\x83\\xCC\\x84\\xD0\\xA3\"\n\t\"\\xCC\\x88\\xD1\\x83\\xCC\\x88\\xD0\\xA3\\xCC\\x8B\\xD1\\x83\\xCC\\x8B\\xD0\\xA7\\xCC\\x88\\xD1\\x87\\xCC\\x88\\xD0\\xAB\\xCC\"\n\t\"\\x88\\xD1\\x8B\\xCC\\x88\\xD8\\xA7\\xD9\\x93\\xD8\\xA7\\xD9\\x94\\xD9\\x88\\xD9\\x94\\xD8\\xA7\\xD9\\x95\\xD9\\x8A\\xD9\\x94\"\n\t\"\\xDB\\x95\\xD9\\x94\\xDB\\x81\\xD9\\x94\\xDB\\x92\\xD9\\x94\\xE0\\xA4\\xA8\\xE0\\xA4\\xBC\\xE0\\xA4\\xB0\\xE0\\xA4\\xBC\\xE0\"\n\t\"\\xA4\\xB3\\xE0\\xA4\\xBC\\xE0\\xA4\\x95\\xE0\\xA4\\xBC\\xE0\\xA4\\x96\\xE0\\xA4\\xBC\\xE0\\xA4\\x97\\xE0\\xA4\\xBC\\xE0\\xA4\"\n\t\"\\x9C\\xE0\\xA4\\xBC\\xE0\\xA4\\xA1\\xE0\\xA4\\xBC\\xE0\\xA4\\xA2\\xE0\\xA4\\xBC\\xE0\\xA4\\xAB\\xE0\\xA4\\xBC\\xE0\\xA4\\xAF\"\n\t\"\\xE0\\xA4\\xBC\\xE0\\xA7\\x87\\xE0\\xA6\\xBE\\xE0\\xA7\\x87\\xE0\\xA7\\x97\\xE0\\xA6\\xA1\\xE0\\xA6\\xBC\\xE0\\xA6\\xA2\\xE0\"\n\t\"\\xA6\\xBC\\xE0\\xA6\\xAF\\xE0\\xA6\\xBC\\xE0\\xA8\\xB2\\xE0\\xA8\\xBC\\xE0\\xA8\\xB8\\xE0\\xA8\\xBC\\xE0\\xA8\\x96\\xE0\\xA8\"\n\t\"\\xBC\\xE0\\xA8\\x97\\xE0\\xA8\\xBC\\xE0\\xA8\\x9C\\xE0\\xA8\\xBC\\xE0\\xA8\\xAB\\xE0\\xA8\\xBC\\xE0\\xAD\\x87\\xE0\\xAD\\x96\"\n\t\"\\xE0\\xAD\\x87\\xE0\\xAC\\xBE\\xE0\\xAD\\x87\\xE0\\xAD\\x97\\xE0\\xAC\\xA1\\xE0\\xAC\\xBC\\xE0\\xAC\\xA2\\xE0\\xAC\\xBC\\xE0\"\n\t\"\\xAE\\x92\\xE0\\xAF\\x97\\xE0\\xAF\\x86\\xE0\\xAE\\xBE\\xE0\\xAF\\x87\\xE0\\xAE\\xBE\\xE0\\xAF\\x86\\xE0\\xAF\\x97\\xE0\\xB1\"\n\t\"\\x86\\xE0\\xB1\\x96\\xE0\\xB2\\xBF\\xE0\\xB3\\x95\\xE0\\xB3\\x86\\xE0\\xB3\\x95\\xE0\\xB3\\x86\\xE0\\xB3\\x96\\xE0\\xB3\\x86\"\n\t\"\\xE0\\xB3\\x82\\xE0\\xB3\\x86\\xE0\\xB3\\x82\\xE0\\xB3\\x95\\xE0\\xB5\\x86\\xE0\\xB4\\xBE\\xE0\\xB5\\x87\\xE0\\xB4\\xBE\\xE0\"\n\t\"\\xB5\\x86\\xE0\\xB5\\x97\\xE0\\xB7\\x99\\xE0\\xB7\\x8A\\xE0\\xB7\\x99\\xE0\\xB7\\x8F\\xE0\\xB7\\x99\\xE0\\xB7\\x8F\\xE0\\xB7\"\n\t\"\\x8A\\xE0\\xB7\\x99\\xE0\\xB7\\x9F\\xE0\\xBD\\x82\\xE0\\xBE\\xB7\\xE0\\xBD\\x8C\\xE0\\xBE\\xB7\\xE0\\xBD\\x91\\xE0\\xBE\\xB7\"\n\t\"\\xE0\\xBD\\x96\\xE0\\xBE\\xB7\\xE0\\xBD\\x9B\\xE0\\xBE\\xB7\\xE0\\xBD\\x80\\xE0\\xBE\\xB5\\xE0\\xBD\\xB1\\xE0\\xBD\\xB2\\xE0\"\n\t\"\\xBD\\xB1\\xE0\\xBD\\xB4\\xE0\\xBE\\xB2\\xE0\\xBE\\x80\\xE0\\xBE\\xB3\\xE0\\xBE\\x80\\xE0\\xBD\\xB1\\xE0\\xBE\\x80\\xE0\\xBE\"\n\t\"\\x92\\xE0\\xBE\\xB7\\xE0\\xBE\\x9C\\xE0\\xBE\\xB7\\xE0\\xBE\\xA1\\xE0\\xBE\\xB7\\xE0\\xBE\\xA6\\xE0\\xBE\\xB7\\xE0\\xBE\\xAB\"\n\t\"\\xE0\\xBE\\xB7\\xE0\\xBE\\x90\\xE0\\xBE\\xB5\\xE1\\x80\\xA5\\xE1\\x80\\xAE\\xE1\\xAC\\x85\\xE1\\xAC\\xB5\\xE1\\xAC\\x87\\xE1\"\n\t\"\\xAC\\xB5\\xE1\\xAC\\x89\\xE1\\xAC\\xB5\\xE1\\xAC\\x8B\\xE1\\xAC\\xB5\\xE1\\xAC\\x8D\\xE1\\xAC\\xB5\\xE1\\xAC\\x91\\xE1\\xAC\"\n\t\"\\xB5\\xE1\\xAC\\xBA\\xE1\\xAC\\xB5\\xE1\\xAC\\xBC\\xE1\\xAC\\xB5\\xE1\\xAC\\xBE\\xE1\\xAC\\xB5\\xE1\\xAC\\xBF\\xE1\\xAC\\xB5\"\n\t\"\\xE1\\xAD\\x82\\xE1\\xAC\\xB5\\x41\\xCC\\xA5\\x61\\xCC\\xA5\\x42\\xCC\\x87\\x62\\xCC\\x87\\x42\\xCC\\xA3\\x62\\xCC\\xA3\\x42\"\n\t\"\\xCC\\xB1\\x62\\xCC\\xB1\\x43\\xCC\\xA7\\xCC\\x81\\x63\\xCC\\xA7\\xCC\\x81\\x44\\xCC\\x87\\x64\\xCC\\x87\\x44\\xCC\\xA3\\x64\"\n\t\"\\xCC\\xA3\\x44\\xCC\\xB1\\x64\\xCC\\xB1\\x44\\xCC\\xA7\\x64\\xCC\\xA7\\x44\\xCC\\xAD\\x64\\xCC\\xAD\\x45\\xCC\\x84\\xCC\\x80\"\n\t\"\\x65\\xCC\\x84\\xCC\\x80\\x45\\xCC\\x84\\xCC\\x81\\x65\\xCC\\x84\\xCC\\x81\\x45\\xCC\\xAD\\x65\\xCC\\xAD\\x45\\xCC\\xB0\\x65\"\n\t\"\\xCC\\xB0\\x45\\xCC\\xA7\\xCC\\x86\\x65\\xCC\\xA7\\xCC\\x86\\x46\\xCC\\x87\\x66\\xCC\\x87\\x47\\xCC\\x84\\x67\\xCC\\x84\\x48\"\n\t\"\\xCC\\x87\\x68\\xCC\\x87\\x48\\xCC\\xA3\\x68\\xCC\\xA3\\x48\\xCC\\x88\\x68\\xCC\\x88\\x48\\xCC\\xA7\\x68\\xCC\\xA7\\x48\\xCC\"\n\t\"\\xAE\\x68\\xCC\\xAE\\x49\\xCC\\xB0\\x69\\xCC\\xB0\\x49\\xCC\\x88\\xCC\\x81\\x69\\xCC\\x88\\xCC\\x81\\x4B\\xCC\\x81\\x6B\\xCC\"\n\t\"\\x81\\x4B\\xCC\\xA3\\x6B\\xCC\\xA3\\x4B\\xCC\\xB1\\x6B\\xCC\\xB1\\x4C\\xCC\\xA3\\x6C\\xCC\\xA3\\x4C\\xCC\\xA3\\xCC\\x84\\x6C\"\n\t\"\\xCC\\xA3\\xCC\\x84\\x4C\\xCC\\xB1\\x6C\\xCC\\xB1\\x4C\\xCC\\xAD\\x6C\\xCC\\xAD\\x4D\\xCC\\x81\\x6D\\xCC\\x81\\x4D\\xCC\\x87\"\n\t\"\\x6D\\xCC\\x87\\x4D\\xCC\\xA3\\x6D\\xCC\\xA3\\x4E\\xCC\\x87\\x6E\\xCC\\x87\\x4E\\xCC\\xA3\\x6E\\xCC\\xA3\\x4E\\xCC\\xB1\\x6E\"\n\t\"\\xCC\\xB1\\x4E\\xCC\\xAD\\x6E\\xCC\\xAD\\x4F\\xCC\\x83\\xCC\\x81\\x6F\\xCC\\x83\\xCC\\x81\\x4F\\xCC\\x83\\xCC\\x88\\x6F\\xCC\"\n\t\"\\x83\\xCC\\x88\\x4F\\xCC\\x84\\xCC\\x80\\x6F\\xCC\\x84\\xCC\\x80\\x4F\\xCC\\x84\\xCC\\x81\\x6F\\xCC\\x84\\xCC\\x81\\x50\\xCC\"\n\t\"\\x81\\x70\\xCC\\x81\\x50\\xCC\\x87\\x70\\xCC\\x87\\x52\\xCC\\x87\\x72\\xCC\\x87\\x52\\xCC\\xA3\\x72\\xCC\\xA3\\x52\\xCC\\xA3\"\n\t\"\\xCC\\x84\\x72\\xCC\\xA3\\xCC\\x84\\x52\\xCC\\xB1\\x72\\xCC\\xB1\\x53\\xCC\\x87\\x73\\xCC\\x87\\x53\\xCC\\xA3\\x73\\xCC\\xA3\"\n\t\"\\x53\\xCC\\x81\\xCC\\x87\\x73\\xCC\\x81\\xCC\\x87\\x53\\xCC\\x8C\\xCC\\x87\\x73\\xCC\\x8C\\xCC\\x87\\x53\\xCC\\xA3\\xCC\\x87\"\n\t\"\\x73\\xCC\\xA3\\xCC\\x87\\x54\\xCC\\x87\\x74\\xCC\\x87\\x54\\xCC\\xA3\\x74\\xCC\\xA3\\x54\\xCC\\xB1\\x74\\xCC\\xB1\\x54\\xCC\"\n\t\"\\xAD\\x74\\xCC\\xAD\\x55\\xCC\\xA4\\x75\\xCC\\xA4\\x55\\xCC\\xB0\\x75\\xCC\\xB0\\x55\\xCC\\xAD\\x75\\xCC\\xAD\\x55\\xCC\\x83\"\n\t\"\\xCC\\x81\\x75\\xCC\\x83\\xCC\\x81\\x55\\xCC\\x84\\xCC\\x88\\x75\\xCC\\x84\\xCC\\x88\\x56\\xCC\\x83\\x76\\xCC\\x83\\x56\\xCC\"\n\t\"\\xA3\\x76\\xCC\\xA3\\x57\\xCC\\x80\\x77\\xCC\\x80\\x57\\xCC\\x81\\x77\\xCC\\x81\\x57\\xCC\\x88\\x77\\xCC\\x88\\x57\\xCC\\x87\"\n\t\"\\x77\\xCC\\x87\\x57\\xCC\\xA3\\x77\\xCC\\xA3\\x58\\xCC\\x87\\x78\\xCC\\x87\\x58\\xCC\\x88\\x78\\xCC\\x88\\x59\\xCC\\x87\\x79\"\n\t\"\\xCC\\x87\\x5A\\xCC\\x82\\x7A\\xCC\\x82\\x5A\\xCC\\xA3\\x7A\\xCC\\xA3\\x5A\\xCC\\xB1\\x7A\\xCC\\xB1\\x68\\xCC\\xB1\\x74\\xCC\"\n\t\"\\x88\\x77\\xCC\\x8A\\x79\\xCC\\x8A\\xC5\\xBF\\xCC\\x87\\x41\\xCC\\xA3\\x61\\xCC\\xA3\\x41\\xCC\\x89\\x61\\xCC\\x89\\x41\\xCC\"\n\t\"\\x82\\xCC\\x81\\x61\\xCC\\x82\\xCC\\x81\\x41\\xCC\\x82\\xCC\\x80\\x61\\xCC\\x82\\xCC\\x80\\x41\\xCC\\x82\\xCC\\x89\\x61\\xCC\"\n\t\"\\x82\\xCC\\x89\\x41\\xCC\\x82\\xCC\\x83\\x61\\xCC\\x82\\xCC\\x83\\x41\\xCC\\xA3\\xCC\\x82\\x61\\xCC\\xA3\\xCC\\x82\\x41\\xCC\"\n\t\"\\x86\\xCC\\x81\\x61\\xCC\\x86\\xCC\\x81\\x41\\xCC\\x86\\xCC\\x80\\x61\\xCC\\x86\\xCC\\x80\\x41\\xCC\\x86\\xCC\\x89\\x61\\xCC\"\n\t\"\\x86\\xCC\\x89\\x41\\xCC\\x86\\xCC\\x83\\x61\\xCC\\x86\\xCC\\x83\\x41\\xCC\\xA3\\xCC\\x86\\x61\\xCC\\xA3\\xCC\\x86\\x45\\xCC\"\n\t\"\\xA3\\x65\\xCC\\xA3\\x45\\xCC\\x89\\x65\\xCC\\x89\\x45\\xCC\\x83\\x65\\xCC\\x83\\x45\\xCC\\x82\\xCC\\x81\\x65\\xCC\\x82\\xCC\"\n\t\"\\x81\\x45\\xCC\\x82\\xCC\\x80\\x65\\xCC\\x82\\xCC\\x80\\x45\\xCC\\x82\\xCC\\x89\\x65\\xCC\\x82\\xCC\\x89\\x45\\xCC\\x82\\xCC\"\n\t\"\\x83\\x65\\xCC\\x82\\xCC\\x83\\x45\\xCC\\xA3\\xCC\\x82\\x65\\xCC\\xA3\\xCC\\x82\\x49\\xCC\\x89\\x69\\xCC\\x89\\x49\\xCC\\xA3\"\n\t\"\\x69\\xCC\\xA3\\x4F\\xCC\\xA3\\x6F\\xCC\\xA3\\x4F\\xCC\\x89\\x6F\\xCC\\x89\\x4F\\xCC\\x82\\xCC\\x81\\x6F\\xCC\\x82\\xCC\\x81\"\n\t\"\\x4F\\xCC\\x82\\xCC\\x80\\x6F\\xCC\\x82\\xCC\\x80\\x4F\\xCC\\x82\\xCC\\x89\\x6F\\xCC\\x82\\xCC\\x89\\x4F\\xCC\\x82\\xCC\\x83\"\n\t\"\\x6F\\xCC\\x82\\xCC\\x83\\x4F\\xCC\\xA3\\xCC\\x82\\x6F\\xCC\\xA3\\xCC\\x82\\x4F\\xCC\\x9B\\xCC\\x81\\x6F\\xCC\\x9B\\xCC\\x81\"\n\t\"\\x4F\\xCC\\x9B\\xCC\\x80\\x6F\\xCC\\x9B\\xCC\\x80\\x4F\\xCC\\x9B\\xCC\\x89\\x6F\\xCC\\x9B\\xCC\\x89\\x4F\\xCC\\x9B\\xCC\\x83\"\n\t\"\\x6F\\xCC\\x9B\\xCC\\x83\\x4F\\xCC\\x9B\\xCC\\xA3\\x6F\\xCC\\x9B\\xCC\\xA3\\x55\\xCC\\xA3\\x75\\xCC\\xA3\\x55\\xCC\\x89\\x75\"\n\t\"\\xCC\\x89\\x55\\xCC\\x9B\\xCC\\x81\\x75\\xCC\\x9B\\xCC\\x81\\x55\\xCC\\x9B\\xCC\\x80\\x75\\xCC\\x9B\\xCC\\x80\\x55\\xCC\\x9B\"\n\t\"\\xCC\\x89\\x75\\xCC\\x9B\\xCC\\x89\\x55\\xCC\\x9B\\xCC\\x83\\x75\\xCC\\x9B\\xCC\\x83\\x55\\xCC\\x9B\\xCC\\xA3\\x75\\xCC\\x9B\"\n\t\"\\xCC\\xA3\\x59\\xCC\\x80\\x79\\xCC\\x80\\x59\\xCC\\xA3\\x79\\xCC\\xA3\\x59\\xCC\\x89\\x79\\xCC\\x89\\x59\\xCC\\x83\\x79\\xCC\"\n\t\"\\x83\\xCE\\xB1\\xCC\\x93\\xCE\\xB1\\xCC\\x94\\xCE\\xB1\\xCC\\x93\\xCC\\x80\\xCE\\xB1\\xCC\\x94\\xCC\\x80\\xCE\\xB1\\xCC\\x93\"\n\t\"\\xCC\\x81\\xCE\\xB1\\xCC\\x94\\xCC\\x81\\xCE\\xB1\\xCC\\x93\\xCD\\x82\\xCE\\xB1\\xCC\\x94\\xCD\\x82\\xCE\\x91\\xCC\\x93\\xCE\"\n\t\"\\x91\\xCC\\x94\\xCE\\x91\\xCC\\x93\\xCC\\x80\\xCE\\x91\\xCC\\x94\\xCC\\x80\\xCE\\x91\\xCC\\x93\\xCC\\x81\\xCE\\x91\\xCC\\x94\"\n\t\"\\xCC\\x81\\xCE\\x91\\xCC\\x93\\xCD\\x82\\xCE\\x91\\xCC\\x94\\xCD\\x82\\xCE\\xB5\\xCC\\x93\\xCE\\xB5\\xCC\\x94\\xCE\\xB5\\xCC\"\n\t\"\\x93\\xCC\\x80\\xCE\\xB5\\xCC\\x94\\xCC\\x80\\xCE\\xB5\\xCC\\x93\\xCC\\x81\\xCE\\xB5\\xCC\\x94\\xCC\\x81\\xCE\\x95\\xCC\\x93\"\n\t\"\\xCE\\x95\\xCC\\x94\\xCE\\x95\\xCC\\x93\\xCC\\x80\\xCE\\x95\\xCC\\x94\\xCC\\x80\\xCE\\x95\\xCC\\x93\\xCC\\x81\\xCE\\x95\\xCC\"\n\t\"\\x94\\xCC\\x81\\xCE\\xB7\\xCC\\x93\\xCE\\xB7\\xCC\\x94\\xCE\\xB7\\xCC\\x93\\xCC\\x80\\xCE\\xB7\\xCC\\x94\\xCC\\x80\\xCE\\xB7\"\n\t\"\\xCC\\x93\\xCC\\x81\\xCE\\xB7\\xCC\\x94\\xCC\\x81\\xCE\\xB7\\xCC\\x93\\xCD\\x82\\xCE\\xB7\\xCC\\x94\\xCD\\x82\\xCE\\x97\\xCC\"\n\t\"\\x93\\xCE\\x97\\xCC\\x94\\xCE\\x97\\xCC\\x93\\xCC\\x80\\xCE\\x97\\xCC\\x94\\xCC\\x80\\xCE\\x97\\xCC\\x93\\xCC\\x81\\xCE\\x97\"\n\t\"\\xCC\\x94\\xCC\\x81\\xCE\\x97\\xCC\\x93\\xCD\\x82\\xCE\\x97\\xCC\\x94\\xCD\\x82\\xCE\\xB9\\xCC\\x93\\xCE\\xB9\\xCC\\x94\\xCE\"\n\t\"\\xB9\\xCC\\x93\\xCC\\x80\\xCE\\xB9\\xCC\\x94\\xCC\\x80\\xCE\\xB9\\xCC\\x93\\xCC\\x81\\xCE\\xB9\\xCC\\x94\\xCC\\x81\\xCE\\xB9\"\n\t\"\\xCC\\x93\\xCD\\x82\\xCE\\xB9\\xCC\\x94\\xCD\\x82\\xCE\\x99\\xCC\\x93\\xCE\\x99\\xCC\\x94\\xCE\\x99\\xCC\\x93\\xCC\\x80\\xCE\"\n\t\"\\x99\\xCC\\x94\\xCC\\x80\\xCE\\x99\\xCC\\x93\\xCC\\x81\\xCE\\x99\\xCC\\x94\\xCC\\x81\\xCE\\x99\\xCC\\x93\\xCD\\x82\\xCE\\x99\"\n\t\"\\xCC\\x94\\xCD\\x82\\xCE\\xBF\\xCC\\x93\\xCE\\xBF\\xCC\\x94\\xCE\\xBF\\xCC\\x93\\xCC\\x80\\xCE\\xBF\\xCC\\x94\\xCC\\x80\\xCE\"\n\t\"\\xBF\\xCC\\x93\\xCC\\x81\\xCE\\xBF\\xCC\\x94\\xCC\\x81\\xCE\\x9F\\xCC\\x93\\xCE\\x9F\\xCC\\x94\\xCE\\x9F\\xCC\\x93\\xCC\\x80\"\n\t\"\\xCE\\x9F\\xCC\\x94\\xCC\\x80\\xCE\\x9F\\xCC\\x93\\xCC\\x81\\xCE\\x9F\\xCC\\x94\\xCC\\x81\\xCF\\x85\\xCC\\x93\\xCF\\x85\\xCC\"\n\t\"\\x94\\xCF\\x85\\xCC\\x93\\xCC\\x80\\xCF\\x85\\xCC\\x94\\xCC\\x80\\xCF\\x85\\xCC\\x93\\xCC\\x81\\xCF\\x85\\xCC\\x94\\xCC\\x81\"\n\t\"\\xCF\\x85\\xCC\\x93\\xCD\\x82\\xCF\\x85\\xCC\\x94\\xCD\\x82\\xCE\\xA5\\xCC\\x94\\xCE\\xA5\\xCC\\x94\\xCC\\x80\\xCE\\xA5\\xCC\"\n\t\"\\x94\\xCC\\x81\\xCE\\xA5\\xCC\\x94\\xCD\\x82\\xCF\\x89\\xCC\\x93\\xCF\\x89\\xCC\\x94\\xCF\\x89\\xCC\\x93\\xCC\\x80\\xCF\\x89\"\n\t\"\\xCC\\x94\\xCC\\x80\\xCF\\x89\\xCC\\x93\\xCC\\x81\\xCF\\x89\\xCC\\x94\\xCC\\x81\\xCF\\x89\\xCC\\x93\\xCD\\x82\\xCF\\x89\\xCC\"\n\t\"\\x94\\xCD\\x82\\xCE\\xA9\\xCC\\x93\\xCE\\xA9\\xCC\\x94\\xCE\\xA9\\xCC\\x93\\xCC\\x80\\xCE\\xA9\\xCC\\x94\\xCC\\x80\\xCE\\xA9\"\n\t\"\\xCC\\x93\\xCC\\x81\\xCE\\xA9\\xCC\\x94\\xCC\\x81\\xCE\\xA9\\xCC\\x93\\xCD\\x82\\xCE\\xA9\\xCC\\x94\\xCD\\x82\\xCE\\xB1\\xCC\"\n\t\"\\x80\\xCE\\xB5\\xCC\\x80\\xCE\\xB7\\xCC\\x80\\xCE\\xB9\\xCC\\x80\\xCE\\xBF\\xCC\\x80\\xCF\\x85\\xCC\\x80\\xCF\\x89\\xCC\\x80\"\n\t\"\\xCE\\xB1\\xCC\\x93\\xCD\\x85\\xCE\\xB1\\xCC\\x94\\xCD\\x85\\xCE\\xB1\\xCC\\x93\\xCC\\x80\\xCD\\x85\\xCE\\xB1\\xCC\\x94\\xCC\"\n\t\"\\x80\\xCD\\x85\\xCE\\xB1\\xCC\\x93\\xCC\\x81\\xCD\\x85\\xCE\\xB1\\xCC\\x94\\xCC\\x81\\xCD\\x85\\xCE\\xB1\\xCC\\x93\\xCD\\x82\"\n\t\"\\xCD\\x85\\xCE\\xB1\\xCC\\x94\\xCD\\x82\\xCD\\x85\\xCE\\x91\\xCC\\x93\\xCD\\x85\\xCE\\x91\\xCC\\x94\\xCD\\x85\\xCE\\x91\\xCC\"\n\t\"\\x93\\xCC\\x80\\xCD\\x85\\xCE\\x91\\xCC\\x94\\xCC\\x80\\xCD\\x85\\xCE\\x91\\xCC\\x93\\xCC\\x81\\xCD\\x85\\xCE\\x91\\xCC\\x94\"\n\t\"\\xCC\\x81\\xCD\\x85\\xCE\\x91\\xCC\\x93\\xCD\\x82\\xCD\\x85\\xCE\\x91\\xCC\\x94\\xCD\\x82\\xCD\\x85\\xCE\\xB7\\xCC\\x93\\xCD\"\n\t\"\\x85\\xCE\\xB7\\xCC\\x94\\xCD\\x85\\xCE\\xB7\\xCC\\x93\\xCC\\x80\\xCD\\x85\\xCE\\xB7\\xCC\\x94\\xCC\\x80\\xCD\\x85\\xCE\\xB7\"\n\t\"\\xCC\\x93\\xCC\\x81\\xCD\\x85\\xCE\\xB7\\xCC\\x94\\xCC\\x81\\xCD\\x85\\xCE\\xB7\\xCC\\x93\\xCD\\x82\\xCD\\x85\\xCE\\xB7\\xCC\"\n\t\"\\x94\\xCD\\x82\\xCD\\x85\\xCE\\x97\\xCC\\x93\\xCD\\x85\\xCE\\x97\\xCC\\x94\\xCD\\x85\\xCE\\x97\\xCC\\x93\\xCC\\x80\\xCD\\x85\"\n\t\"\\xCE\\x97\\xCC\\x94\\xCC\\x80\\xCD\\x85\\xCE\\x97\\xCC\\x93\\xCC\\x81\\xCD\\x85\\xCE\\x97\\xCC\\x94\\xCC\\x81\\xCD\\x85\\xCE\"\n\t\"\\x97\\xCC\\x93\\xCD\\x82\\xCD\\x85\\xCE\\x97\\xCC\\x94\\xCD\\x82\\xCD\\x85\\xCF\\x89\\xCC\\x93\\xCD\\x85\\xCF\\x89\\xCC\\x94\"\n\t\"\\xCD\\x85\\xCF\\x89\\xCC\\x93\\xCC\\x80\\xCD\\x85\\xCF\\x89\\xCC\\x94\\xCC\\x80\\xCD\\x85\\xCF\\x89\\xCC\\x93\\xCC\\x81\\xCD\"\n\t\"\\x85\\xCF\\x89\\xCC\\x94\\xCC\\x81\\xCD\\x85\\xCF\\x89\\xCC\\x93\\xCD\\x82\\xCD\\x85\\xCF\\x89\\xCC\\x94\\xCD\\x82\\xCD\\x85\"\n\t\"\\xCE\\xA9\\xCC\\x93\\xCD\\x85\\xCE\\xA9\\xCC\\x94\\xCD\\x85\\xCE\\xA9\\xCC\\x93\\xCC\\x80\\xCD\\x85\\xCE\\xA9\\xCC\\x94\\xCC\"\n\t\"\\x80\\xCD\\x85\\xCE\\xA9\\xCC\\x93\\xCC\\x81\\xCD\\x85\\xCE\\xA9\\xCC\\x94\\xCC\\x81\\xCD\\x85\\xCE\\xA9\\xCC\\x93\\xCD\\x82\"\n\t\"\\xCD\\x85\\xCE\\xA9\\xCC\\x94\\xCD\\x82\\xCD\\x85\\xCE\\xB1\\xCC\\x86\\xCE\\xB1\\xCC\\x84\\xCE\\xB1\\xCC\\x80\\xCD\\x85\\xCE\"\n\t\"\\xB1\\xCD\\x85\\xCE\\xB1\\xCC\\x81\\xCD\\x85\\xCE\\xB1\\xCD\\x82\\xCE\\xB1\\xCD\\x82\\xCD\\x85\\xCE\\x91\\xCC\\x86\\xCE\\x91\"\n\t\"\\xCC\\x84\\xCE\\x91\\xCC\\x80\\xCE\\x91\\xCD\\x85\\xC2\\xA8\\xCD\\x82\\xCE\\xB7\\xCC\\x80\\xCD\\x85\\xCE\\xB7\\xCD\\x85\\xCE\"\n\t\"\\xB7\\xCC\\x81\\xCD\\x85\\xCE\\xB7\\xCD\\x82\\xCE\\xB7\\xCD\\x82\\xCD\\x85\\xCE\\x95\\xCC\\x80\\xCE\\x97\\xCC\\x80\\xCE\\x97\"\n\t\"\\xCD\\x85\\xE1\\xBE\\xBF\\xCC\\x80\\xE1\\xBE\\xBF\\xCC\\x81\\xE1\\xBE\\xBF\\xCD\\x82\\xCE\\xB9\\xCC\\x86\\xCE\\xB9\\xCC\\x84\"\n\t\"\\xCE\\xB9\\xCC\\x88\\xCC\\x80\\xCE\\xB9\\xCD\\x82\\xCE\\xB9\\xCC\\x88\\xCD\\x82\\xCE\\x99\\xCC\\x86\\xCE\\x99\\xCC\\x84\\xCE\"\n\t\"\\x99\\xCC\\x80\\xE1\\xBF\\xBE\\xCC\\x80\\xE1\\xBF\\xBE\\xCC\\x81\\xE1\\xBF\\xBE\\xCD\\x82\\xCF\\x85\\xCC\\x86\\xCF\\x85\\xCC\"\n\t\"\\x84\\xCF\\x85\\xCC\\x88\\xCC\\x80\\xCF\\x81\\xCC\\x93\\xCF\\x81\\xCC\\x94\\xCF\\x85\\xCD\\x82\\xCF\\x85\\xCC\\x88\\xCD\\x82\"\n\t\"\\xCE\\xA5\\xCC\\x86\\xCE\\xA5\\xCC\\x84\\xCE\\xA5\\xCC\\x80\\xCE\\xA1\\xCC\\x94\\xC2\\xA8\\xCC\\x80\\x60\\xCF\\x89\\xCC\\x80\"\n\t\"\\xCD\\x85\\xCF\\x89\\xCD\\x85\\xCF\\x89\\xCC\\x81\\xCD\\x85\\xCF\\x89\\xCD\\x82\\xCF\\x89\\xCD\\x82\\xCD\\x85\\xCE\\x9F\\xCC\"\n\t\"\\x80\\xCE\\xA9\\xCC\\x80\\xCE\\xA9\\xCD\\x85\\xC2\\xB4\\xE2\\x80\\x82\\xE2\\x80\\x83\\xE2\\x86\\x90\\xCC\\xB8\\xE2\\x86\\x92\"\n\t\"\\xCC\\xB8\\xE2\\x86\\x94\\xCC\\xB8\\xE2\\x87\\x90\\xCC\\xB8\\xE2\\x87\\x94\\xCC\\xB8\\xE2\\x87\\x92\\xCC\\xB8\\xE2\\x88\\x83\"\n\t\"\\xCC\\xB8\\xE2\\x88\\x88\\xCC\\xB8\\xE2\\x88\\x8B\\xCC\\xB8\\xE2\\x88\\xA3\\xCC\\xB8\\xE2\\x88\\xA5\\xCC\\xB8\\xE2\\x88\\xBC\"\n\t\"\\xCC\\xB8\\xE2\\x89\\x83\\xCC\\xB8\\xE2\\x89\\x85\\xCC\\xB8\\xE2\\x89\\x88\\xCC\\xB8\\x3D\\xCC\\xB8\\xE2\\x89\\xA1\\xCC\\xB8\"\n\t\"\\xE2\\x89\\x8D\\xCC\\xB8\\x3C\\xCC\\xB8\\x3E\\xCC\\xB8\\xE2\\x89\\xA4\\xCC\\xB8\\xE2\\x89\\xA5\\xCC\\xB8\\xE2\\x89\\xB2\\xCC\"\n\t\"\\xB8\\xE2\\x89\\xB3\\xCC\\xB8\\xE2\\x89\\xB6\\xCC\\xB8\\xE2\\x89\\xB7\\xCC\\xB8\\xE2\\x89\\xBA\\xCC\\xB8\\xE2\\x89\\xBB\\xCC\"\n\t\"\\xB8\\xE2\\x8A\\x82\\xCC\\xB8\\xE2\\x8A\\x83\\xCC\\xB8\\xE2\\x8A\\x86\\xCC\\xB8\\xE2\\x8A\\x87\\xCC\\xB8\\xE2\\x8A\\xA2\\xCC\"\n\t\"\\xB8\\xE2\\x8A\\xA8\\xCC\\xB8\\xE2\\x8A\\xA9\\xCC\\xB8\\xE2\\x8A\\xAB\\xCC\\xB8\\xE2\\x89\\xBC\\xCC\\xB8\\xE2\\x89\\xBD\\xCC\"\n\t\"\\xB8\\xE2\\x8A\\x91\\xCC\\xB8\\xE2\\x8A\\x92\\xCC\\xB8\\xE2\\x8A\\xB2\\xCC\\xB8\\xE2\\x8A\\xB3\\xCC\\xB8\\xE2\\x8A\\xB4\\xCC\"\n\t\"\\xB8\\xE2\\x8A\\xB5\\xCC\\xB8\\xE3\\x80\\x88\\xE3\\x80\\x89\\xE2\\xAB\\x9D\\xCC\\xB8\\xE3\\x81\\x8B\\xE3\\x82\\x99\\xE3\\x81\"\n\t\"\\x8D\\xE3\\x82\\x99\\xE3\\x81\\x8F\\xE3\\x82\\x99\\xE3\\x81\\x91\\xE3\\x82\\x99\\xE3\\x81\\x93\\xE3\\x82\\x99\\xE3\\x81\\x95\"\n\t\"\\xE3\\x82\\x99\\xE3\\x81\\x97\\xE3\\x82\\x99\\xE3\\x81\\x99\\xE3\\x82\\x99\\xE3\\x81\\x9B\\xE3\\x82\\x99\\xE3\\x81\\x9D\\xE3\"\n\t\"\\x82\\x99\\xE3\\x81\\x9F\\xE3\\x82\\x99\\xE3\\x81\\xA1\\xE3\\x82\\x99\\xE3\\x81\\xA4\\xE3\\x82\\x99\\xE3\\x81\\xA6\\xE3\\x82\"\n\t\"\\x99\\xE3\\x81\\xA8\\xE3\\x82\\x99\\xE3\\x81\\xAF\\xE3\\x82\\x99\\xE3\\x81\\xAF\\xE3\\x82\\x9A\\xE3\\x81\\xB2\\xE3\\x82\\x99\"\n\t\"\\xE3\\x81\\xB2\\xE3\\x82\\x9A\\xE3\\x81\\xB5\\xE3\\x82\\x99\\xE3\\x81\\xB5\\xE3\\x82\\x9A\\xE3\\x81\\xB8\\xE3\\x82\\x99\\xE3\"\n\t\"\\x81\\xB8\\xE3\\x82\\x9A\\xE3\\x81\\xBB\\xE3\\x82\\x99\\xE3\\x81\\xBB\\xE3\\x82\\x9A\\xE3\\x81\\x86\\xE3\\x82\\x99\\xE3\\x82\"\n\t\"\\x9D\\xE3\\x82\\x99\\xE3\\x82\\xAB\\xE3\\x82\\x99\\xE3\\x82\\xAD\\xE3\\x82\\x99\\xE3\\x82\\xAF\\xE3\\x82\\x99\\xE3\\x82\\xB1\"\n\t\"\\xE3\\x82\\x99\\xE3\\x82\\xB3\\xE3\\x82\\x99\\xE3\\x82\\xB5\\xE3\\x82\\x99\\xE3\\x82\\xB7\\xE3\\x82\\x99\\xE3\\x82\\xB9\\xE3\"\n\t\"\\x82\\x99\\xE3\\x82\\xBB\\xE3\\x82\\x99\\xE3\\x82\\xBD\\xE3\\x82\\x99\\xE3\\x82\\xBF\\xE3\\x82\\x99\\xE3\\x83\\x81\\xE3\\x82\"\n\t\"\\x99\\xE3\\x83\\x84\\xE3\\x82\\x99\\xE3\\x83\\x86\\xE3\\x82\\x99\\xE3\\x83\\x88\\xE3\\x82\\x99\\xE3\\x83\\x8F\\xE3\\x82\\x99\"\n\t\"\\xE3\\x83\\x8F\\xE3\\x82\\x9A\\xE3\\x83\\x92\\xE3\\x82\\x99\\xE3\\x83\\x92\\xE3\\x82\\x9A\\xE3\\x83\\x95\\xE3\\x82\\x99\\xE3\"\n\t\"\\x83\\x95\\xE3\\x82\\x9A\\xE3\\x83\\x98\\xE3\\x82\\x99\\xE3\\x83\\x98\\xE3\\x82\\x9A\\xE3\\x83\\x9B\\xE3\\x82\\x99\\xE3\\x83\"\n\t\"\\x9B\\xE3\\x82\\x9A\\xE3\\x82\\xA6\\xE3\\x82\\x99\\xE3\\x83\\xAF\\xE3\\x82\\x99\\xE3\\x83\\xB0\\xE3\\x82\\x99\\xE3\\x83\\xB1\"\n\t\"\\xE3\\x82\\x99\\xE3\\x83\\xB2\\xE3\\x82\\x99\\xE3\\x83\\xBD\\xE3\\x82\\x99\\xE8\\xB1\\x88\\xE6\\x9B\\xB4\\xE8\\xBB\\x8A\\xE8\"\n\t\"\\xB3\\x88\\xE6\\xBB\\x91\\xE4\\xB8\\xB2\\xE5\\x8F\\xA5\\xE9\\xBE\\x9C\\xE5\\xA5\\x91\\xE9\\x87\\x91\\xE5\\x96\\x87\\xE5\\xA5\"\n\t\"\\x88\\xE6\\x87\\xB6\\xE7\\x99\\xA9\\xE7\\xBE\\x85\\xE8\\x98\\xBF\\xE8\\x9E\\xBA\\xE8\\xA3\\xB8\\xE9\\x82\\x8F\\xE6\\xA8\\x82\"\n\t\"\\xE6\\xB4\\x9B\\xE7\\x83\\x99\\xE7\\x8F\\x9E\\xE8\\x90\\xBD\\xE9\\x85\\xAA\\xE9\\xA7\\xB1\\xE4\\xBA\\x82\\xE5\\x8D\\xB5\\xE6\"\n\t\"\\xAC\\x84\\xE7\\x88\\x9B\\xE8\\x98\\xAD\\xE9\\xB8\\x9E\\xE5\\xB5\\x90\\xE6\\xBF\\xAB\\xE8\\x97\\x8D\\xE8\\xA5\\xA4\\xE6\\x8B\"\n\t\"\\x89\\xE8\\x87\\x98\\xE8\\xA0\\x9F\\xE5\\xBB\\x8A\\xE6\\x9C\\x97\\xE6\\xB5\\xAA\\xE7\\x8B\\xBC\\xE9\\x83\\x8E\\xE4\\xBE\\x86\"\n\t\"\\xE5\\x86\\xB7\\xE5\\x8B\\x9E\\xE6\\x93\\x84\\xE6\\xAB\\x93\\xE7\\x88\\x90\\xE7\\x9B\\xA7\\xE8\\x80\\x81\\xE8\\x98\\x86\\xE8\"\n\t\"\\x99\\x9C\\xE8\\xB7\\xAF\\xE9\\x9C\\xB2\\xE9\\xAD\\xAF\\xE9\\xB7\\xBA\\xE7\\xA2\\x8C\\xE7\\xA5\\xBF\\xE7\\xB6\\xA0\\xE8\\x8F\"\n\t\"\\x89\\xE9\\x8C\\x84\\xE9\\xB9\\xBF\\xE8\\xAB\\x96\\xE5\\xA3\\x9F\\xE5\\xBC\\x84\\xE7\\xB1\\xA0\\xE8\\x81\\xBE\\xE7\\x89\\xA2\"\n\t\"\\xE7\\xA3\\x8A\\xE8\\xB3\\x82\\xE9\\x9B\\xB7\\xE5\\xA3\\x98\\xE5\\xB1\\xA2\\xE6\\xA8\\x93\\xE6\\xB7\\x9A\\xE6\\xBC\\x8F\\xE7\"\n\t\"\\xB4\\xAF\\xE7\\xB8\\xB7\\xE9\\x99\\x8B\\xE5\\x8B\\x92\\xE8\\x82\\x8B\\xE5\\x87\\x9C\\xE5\\x87\\x8C\\xE7\\xA8\\x9C\\xE7\\xB6\"\n\t\"\\xBE\\xE8\\x8F\\xB1\\xE9\\x99\\xB5\\xE8\\xAE\\x80\\xE6\\x8B\\x8F\\xE8\\xAB\\xBE\\xE4\\xB8\\xB9\\xE5\\xAF\\xA7\\xE6\\x80\\x92\"\n\t\"\\xE7\\x8E\\x87\\xE7\\x95\\xB0\\xE5\\x8C\\x97\\xE7\\xA3\\xBB\\xE4\\xBE\\xBF\\xE5\\xBE\\xA9\\xE4\\xB8\\x8D\\xE6\\xB3\\x8C\\xE6\"\n\t\"\\x95\\xB8\\xE7\\xB4\\xA2\\xE5\\x8F\\x83\\xE5\\xA1\\x9E\\xE7\\x9C\\x81\\xE8\\x91\\x89\\xE8\\xAA\\xAA\\xE6\\xAE\\xBA\\xE8\\xBE\"\n\t\"\\xB0\\xE6\\xB2\\x88\\xE6\\x8B\\xBE\\xE8\\x8B\\xA5\\xE6\\x8E\\xA0\\xE7\\x95\\xA5\\xE4\\xBA\\xAE\\xE5\\x85\\xA9\\xE5\\x87\\x89\"\n\t\"\\xE6\\xA2\\x81\\xE7\\xB3\\xA7\\xE8\\x89\\xAF\\xE8\\xAB\\x92\\xE9\\x87\\x8F\\xE5\\x8B\\xB5\\xE5\\x91\\x82\\xE5\\xA5\\xB3\\xE5\"\n\t\"\\xBB\\xAC\\xE6\\x97\\x85\\xE6\\xBF\\xBE\\xE7\\xA4\\xAA\\xE9\\x96\\xAD\\xE9\\xA9\\xAA\\xE9\\xBA\\x97\\xE9\\xBB\\x8E\\xE5\\x8A\"\n\t\"\\x9B\\xE6\\x9B\\x86\\xE6\\xAD\\xB7\\xE8\\xBD\\xA2\\xE5\\xB9\\xB4\\xE6\\x86\\x90\\xE6\\x88\\x80\\xE6\\x92\\x9A\\xE6\\xBC\\xA3\"\n\t\"\\xE7\\x85\\x89\\xE7\\x92\\x89\\xE7\\xA7\\x8A\\xE7\\xB7\\xB4\\xE8\\x81\\xAF\\xE8\\xBC\\xA6\\xE8\\x93\\xAE\\xE9\\x80\\xA3\\xE9\"\n\t\"\\x8D\\x8A\\xE5\\x88\\x97\\xE5\\x8A\\xA3\\xE5\\x92\\xBD\\xE7\\x83\\x88\\xE8\\xA3\\x82\\xE5\\xBB\\x89\\xE5\\xBF\\xB5\\xE6\\x8D\"\n\t\"\\xBB\\xE6\\xAE\\xAE\\xE7\\xB0\\xBE\\xE7\\x8D\\xB5\\xE4\\xBB\\xA4\\xE5\\x9B\\xB9\\xE5\\xB6\\xBA\\xE6\\x80\\x9C\\xE7\\x8E\\xB2\"\n\t\"\\xE7\\x91\\xA9\\xE7\\xBE\\x9A\\xE8\\x81\\x86\\xE9\\x88\\xB4\\xE9\\x9B\\xB6\\xE9\\x9D\\x88\\xE9\\xA0\\x98\\xE4\\xBE\\x8B\\xE7\"\n\t\"\\xA6\\xAE\\xE9\\x86\\xB4\\xE9\\x9A\\xB8\\xE6\\x83\\xA1\\xE4\\xBA\\x86\\xE5\\x83\\x9A\\xE5\\xAF\\xAE\\xE5\\xB0\\xBF\\xE6\\x96\"\n\t\"\\x99\\xE7\\x87\\x8E\\xE7\\x99\\x82\\xE8\\x93\\xBC\\xE9\\x81\\xBC\\xE9\\xBE\\x8D\\xE6\\x9A\\x88\\xE9\\x98\\xAE\\xE5\\x8A\\x89\"\n\t\"\\xE6\\x9D\\xBB\\xE6\\x9F\\xB3\\xE6\\xB5\\x81\\xE6\\xBA\\x9C\\xE7\\x90\\x89\\xE7\\x95\\x99\\xE7\\xA1\\xAB\\xE7\\xB4\\x90\\xE9\"\n\t\"\\xA1\\x9E\\xE5\\x85\\xAD\\xE6\\x88\\xAE\\xE9\\x99\\xB8\\xE5\\x80\\xAB\\xE5\\xB4\\x99\\xE6\\xB7\\xAA\\xE8\\xBC\\xAA\\xE5\\xBE\"\n\t\"\\x8B\\xE6\\x85\\x84\\xE6\\xA0\\x97\\xE9\\x9A\\x86\\xE5\\x88\\xA9\\xE5\\x90\\x8F\\xE5\\xB1\\xA5\\xE6\\x98\\x93\\xE6\\x9D\\x8E\"\n\t\"\\xE6\\xA2\\xA8\\xE6\\xB3\\xA5\\xE7\\x90\\x86\\xE7\\x97\\xA2\\xE7\\xBD\\xB9\\xE8\\xA3\\x8F\\xE8\\xA3\\xA1\\xE9\\x87\\x8C\\xE9\"\n\t\"\\x9B\\xA2\\xE5\\x8C\\xBF\\xE6\\xBA\\xBA\\xE5\\x90\\x9D\\xE7\\x87\\x90\\xE7\\x92\\x98\\xE8\\x97\\xBA\\xE9\\x9A\\xA3\\xE9\\xB1\"\n\t\"\\x97\\xE9\\xBA\\x9F\\xE6\\x9E\\x97\\xE6\\xB7\\x8B\\xE8\\x87\\xA8\\xE7\\xAB\\x8B\\xE7\\xAC\\xA0\\xE7\\xB2\\x92\\xE7\\x8B\\x80\"\n\t\"\\xE7\\x82\\x99\\xE8\\xAD\\x98\\xE4\\xBB\\x80\\xE8\\x8C\\xB6\\xE5\\x88\\xBA\\xE5\\x88\\x87\\xE5\\xBA\\xA6\\xE6\\x8B\\x93\\xE7\"\n\t\"\\xB3\\x96\\xE5\\xAE\\x85\\xE6\\xB4\\x9E\\xE6\\x9A\\xB4\\xE8\\xBC\\xBB\\xE8\\xA1\\x8C\\xE9\\x99\\x8D\\xE8\\xA6\\x8B\\xE5\\xBB\"\n\t\"\\x93\\xE5\\x85\\x80\\xE5\\x97\\x80\\xE5\\xA1\\x9A\\xE6\\x99\\xB4\\xE5\\x87\\x9E\\xE7\\x8C\\xAA\\xE7\\x9B\\x8A\\xE7\\xA4\\xBC\"\n\t\"\\xE7\\xA5\\x9E\\xE7\\xA5\\xA5\\xE7\\xA6\\x8F\\xE9\\x9D\\x96\\xE7\\xB2\\xBE\\xE7\\xBE\\xBD\\xE8\\x98\\x92\\xE8\\xAB\\xB8\\xE9\"\n\t\"\\x80\\xB8\\xE9\\x83\\xBD\\xE9\\xA3\\xAF\\xE9\\xA3\\xBC\\xE9\\xA4\\xA8\\xE9\\xB6\\xB4\\xE9\\x83\\x9E\\xE9\\x9A\\xB7\\xE4\\xBE\"\n\t\"\\xAE\\xE5\\x83\\xA7\\xE5\\x85\\x8D\\xE5\\x8B\\x89\\xE5\\x8B\\xA4\\xE5\\x8D\\x91\\xE5\\x96\\x9D\\xE5\\x98\\x86\\xE5\\x99\\xA8\"\n\t\"\\xE5\\xA1\\x80\\xE5\\xA2\\xA8\\xE5\\xB1\\xA4\\xE5\\xB1\\xAE\\xE6\\x82\\x94\\xE6\\x85\\xA8\\xE6\\x86\\x8E\\xE6\\x87\\xB2\\xE6\"\n\t\"\\x95\\x8F\\xE6\\x97\\xA2\\xE6\\x9A\\x91\\xE6\\xA2\\x85\\xE6\\xB5\\xB7\\xE6\\xB8\\x9A\\xE6\\xBC\\xA2\\xE7\\x85\\xAE\\xE7\\x88\"\n\t\"\\xAB\\xE7\\x90\\xA2\\xE7\\xA2\\x91\\xE7\\xA4\\xBE\\xE7\\xA5\\x89\\xE7\\xA5\\x88\\xE7\\xA5\\x90\\xE7\\xA5\\x96\\xE7\\xA5\\x9D\"\n\t\"\\xE7\\xA6\\x8D\\xE7\\xA6\\x8E\\xE7\\xA9\\x80\\xE7\\xAA\\x81\\xE7\\xAF\\x80\\xE7\\xB8\\x89\\xE7\\xB9\\x81\\xE7\\xBD\\xB2\\xE8\"\n\t\"\\x80\\x85\\xE8\\x87\\xAD\\xE8\\x89\\xB9\\xE8\\x91\\x97\\xE8\\xA4\\x90\\xE8\\xA6\\x96\\xE8\\xAC\\x81\\xE8\\xAC\\xB9\\xE8\\xB3\"\n\t\"\\x93\\xE8\\xB4\\x88\\xE8\\xBE\\xB6\\xE9\\x9B\\xA3\\xE9\\x9F\\xBF\\xE9\\xA0\\xBB\\xE6\\x81\\xB5\\xF0\\xA4\\x8B\\xAE\\xE8\\x88\"\n\t\"\\x98\\xE4\\xB8\\xA6\\xE5\\x86\\xB5\\xE5\\x85\\xA8\\xE4\\xBE\\x80\\xE5\\x85\\x85\\xE5\\x86\\x80\\xE5\\x8B\\x87\\xE5\\x8B\\xBA\"\n\t\"\\xE5\\x95\\x95\\xE5\\x96\\x99\\xE5\\x97\\xA2\\xE5\\xA2\\xB3\\xE5\\xA5\\x84\\xE5\\xA5\\x94\\xE5\\xA9\\xA2\\xE5\\xAC\\xA8\\xE5\"\n\t\"\\xBB\\x92\\xE5\\xBB\\x99\\xE5\\xBD\\xA9\\xE5\\xBE\\xAD\\xE6\\x83\\x98\\xE6\\x85\\x8E\\xE6\\x84\\x88\\xE6\\x85\\xA0\\xE6\\x88\"\n\t\"\\xB4\\xE6\\x8F\\x84\\xE6\\x90\\x9C\\xE6\\x91\\x92\\xE6\\x95\\x96\\xE6\\x9C\\x9B\\xE6\\x9D\\x96\\xE6\\xAD\\xB9\\xE6\\xBB\\x9B\"\n\t\"\\xE6\\xBB\\x8B\\xE7\\x80\\x9E\\xE7\\x9E\\xA7\\xE7\\x88\\xB5\\xE7\\x8A\\xAF\\xE7\\x91\\xB1\\xE7\\x94\\x86\\xE7\\x94\\xBB\\xE7\"\n\t\"\\x98\\x9D\\xE7\\x98\\x9F\\xE7\\x9B\\x9B\\xE7\\x9B\\xB4\\xE7\\x9D\\x8A\\xE7\\x9D\\x80\\xE7\\xA3\\x8C\\xE7\\xAA\\xB1\\xE7\\xB1\"\n\t\"\\xBB\\xE7\\xB5\\x9B\\xE7\\xBC\\xBE\\xE8\\x8D\\x92\\xE8\\x8F\\xAF\\xE8\\x9D\\xB9\\xE8\\xA5\\x81\\xE8\\xA6\\x86\\xE8\\xAA\\xBF\"\n\t\"\\xE8\\xAB\\x8B\\xE8\\xAB\\xAD\\xE8\\xAE\\x8A\\xE8\\xBC\\xB8\\xE9\\x81\\xB2\\xE9\\x86\\x99\\xE9\\x89\\xB6\\xE9\\x99\\xBC\\xE9\"\n\t\"\\x9F\\x9B\\xE9\\xA0\\x8B\\xE9\\xAC\\x92\\xF0\\xA2\\xA1\\x8A\\xF0\\xA2\\xA1\\x84\\xF0\\xA3\\x8F\\x95\\xE3\\xAE\\x9D\\xE4\\x80\"\n\t\"\\x98\\xE4\\x80\\xB9\\xF0\\xA5\\x89\\x89\\xF0\\xA5\\xB3\\x90\\xF0\\xA7\\xBB\\x93\\xE9\\xBD\\x83\\xE9\\xBE\\x8E\\xD7\\x99\\xD6\"\n\t\"\\xB4\\xD7\\xB2\\xD6\\xB7\\xD7\\xA9\\xD7\\x81\\xD7\\xA9\\xD7\\x82\\xD7\\xA9\\xD6\\xBC\\xD7\\x81\\xD7\\xA9\\xD6\\xBC\\xD7\\x82\"\n\t\"\\xD7\\x90\\xD6\\xB7\\xD7\\x90\\xD6\\xB8\\xD7\\x90\\xD6\\xBC\\xD7\\x91\\xD6\\xBC\\xD7\\x92\\xD6\\xBC\\xD7\\x93\\xD6\\xBC\\xD7\"\n\t\"\\x94\\xD6\\xBC\\xD7\\x95\\xD6\\xBC\\xD7\\x96\\xD6\\xBC\\xD7\\x98\\xD6\\xBC\\xD7\\x99\\xD6\\xBC\\xD7\\x9A\\xD6\\xBC\\xD7\\x9B\"\n\t\"\\xD6\\xBC\\xD7\\x9C\\xD6\\xBC\\xD7\\x9E\\xD6\\xBC\\xD7\\xA0\\xD6\\xBC\\xD7\\xA1\\xD6\\xBC\\xD7\\xA3\\xD6\\xBC\\xD7\\xA4\\xD6\"\n\t\"\\xBC\\xD7\\xA6\\xD6\\xBC\\xD7\\xA7\\xD6\\xBC\\xD7\\xA8\\xD6\\xBC\\xD7\\xAA\\xD6\\xBC\\xD7\\x95\\xD6\\xB9\\xD7\\x91\\xD6\\xBF\"\n\t\"\\xD7\\x9B\\xD6\\xBF\\xD7\\xA4\\xD6\\xBF\\xF0\\x91\\x82\\x99\\xF0\\x91\\x82\\xBA\\xF0\\x91\\x82\\x9B\\xF0\\x91\\x82\\xBA\\xF0\"\n\t\"\\x91\\x82\\xA5\\xF0\\x91\\x82\\xBA\\xF0\\x91\\x84\\xB1\\xF0\\x91\\x84\\xA7\\xF0\\x91\\x84\\xB2\\xF0\\x91\\x84\\xA7\\xF0\\x91\"\n\t\"\\x8D\\x87\\xF0\\x91\\x8C\\xBE\\xF0\\x91\\x8D\\x87\\xF0\\x91\\x8D\\x97\\xF0\\x91\\x92\\xB9\\xF0\\x91\\x92\\xBA\\xF0\\x91\\x92\"\n\t\"\\xB9\\xF0\\x91\\x92\\xB0\\xF0\\x91\\x92\\xB9\\xF0\\x91\\x92\\xBD\\xF0\\x91\\x96\\xB8\\xF0\\x91\\x96\\xAF\\xF0\\x91\\x96\\xB9\"\n\t\"\\xF0\\x91\\x96\\xAF\\xF0\\x9D\\x85\\x97\\xF0\\x9D\\x85\\xA5\\xF0\\x9D\\x85\\x98\\xF0\\x9D\\x85\\xA5\\xF0\\x9D\\x85\\x98\\xF0\"\n\t\"\\x9D\\x85\\xA5\\xF0\\x9D\\x85\\xAE\\xF0\\x9D\\x85\\x98\\xF0\\x9D\\x85\\xA5\\xF0\\x9D\\x85\\xAF\\xF0\\x9D\\x85\\x98\\xF0\\x9D\"\n\t\"\\x85\\xA5\\xF0\\x9D\\x85\\xB0\\xF0\\x9D\\x85\\x98\\xF0\\x9D\\x85\\xA5\\xF0\\x9D\\x85\\xB1\\xF0\\x9D\\x85\\x98\\xF0\\x9D\\x85\"\n\t\"\\xA5\\xF0\\x9D\\x85\\xB2\\xF0\\x9D\\x86\\xB9\\xF0\\x9D\\x85\\xA5\\xF0\\x9D\\x86\\xBA\\xF0\\x9D\\x85\\xA5\\xF0\\x9D\\x86\\xB9\"\n\t\"\\xF0\\x9D\\x85\\xA5\\xF0\\x9D\\x85\\xAE\\xF0\\x9D\\x86\\xBA\\xF0\\x9D\\x85\\xA5\\xF0\\x9D\\x85\\xAE\\xF0\\x9D\\x86\\xB9\\xF0\"\n\t\"\\x9D\\x85\\xA5\\xF0\\x9D\\x85\\xAF\\xF0\\x9D\\x86\\xBA\\xF0\\x9D\\x85\\xA5\\xF0\\x9D\\x85\\xAF\\xE4\\xB8\\xBD\\xE4\\xB8\\xB8\"\n\t\"\\xE4\\xB9\\x81\\xF0\\xA0\\x84\\xA2\\xE4\\xBD\\xA0\\xE4\\xBE\\xBB\\xE5\\x80\\x82\\xE5\\x81\\xBA\\xE5\\x82\\x99\\xE5\\x83\\x8F\"\n\t\"\\xE3\\x92\\x9E\\xF0\\xA0\\x98\\xBA\\xE5\\x85\\x94\\xE5\\x85\\xA4\\xE5\\x85\\xB7\\xF0\\xA0\\x94\\x9C\\xE3\\x92\\xB9\\xE5\\x85\"\n\t\"\\xA7\\xE5\\x86\\x8D\\xF0\\xA0\\x95\\x8B\\xE5\\x86\\x97\\xE5\\x86\\xA4\\xE4\\xBB\\x8C\\xE5\\x86\\xAC\\xF0\\xA9\\x87\\x9F\\xE5\"\n\t\"\\x87\\xB5\\xE5\\x88\\x83\\xE3\\x93\\x9F\\xE5\\x88\\xBB\\xE5\\x89\\x86\\xE5\\x89\\xB2\\xE5\\x89\\xB7\\xE3\\x94\\x95\\xE5\\x8C\"\n\t\"\\x85\\xE5\\x8C\\x86\\xE5\\x8D\\x89\\xE5\\x8D\\x9A\\xE5\\x8D\\xB3\\xE5\\x8D\\xBD\\xE5\\x8D\\xBF\\xF0\\xA0\\xA8\\xAC\\xE7\\x81\"\n\t\"\\xB0\\xE5\\x8F\\x8A\\xE5\\x8F\\x9F\\xF0\\xA0\\xAD\\xA3\\xE5\\x8F\\xAB\\xE5\\x8F\\xB1\\xE5\\x90\\x86\\xE5\\x92\\x9E\\xE5\\x90\"\n\t\"\\xB8\\xE5\\x91\\x88\\xE5\\x91\\xA8\\xE5\\x92\\xA2\\xE5\\x93\\xB6\\xE5\\x94\\x90\\xE5\\x95\\x93\\xE5\\x95\\xA3\\xE5\\x96\\x84\"\n\t\"\\xE5\\x96\\xAB\\xE5\\x96\\xB3\\xE5\\x97\\x82\\xE5\\x9C\\x96\\xE5\\x9C\\x97\\xE5\\x99\\x91\\xE5\\x99\\xB4\\xE5\\xA3\\xAE\\xE5\"\n\t\"\\x9F\\x8E\\xE5\\x9F\\xB4\\xE5\\xA0\\x8D\\xE5\\x9E\\x8B\\xE5\\xA0\\xB2\\xE5\\xA0\\xB1\\xE5\\xA2\\xAC\\xF0\\xA1\\x93\\xA4\\xE5\"\n\t\"\\xA3\\xB2\\xE5\\xA3\\xB7\\xE5\\xA4\\x86\\xE5\\xA4\\x9A\\xE5\\xA4\\xA2\\xE5\\xA5\\xA2\\xF0\\xA1\\x9A\\xA8\\xF0\\xA1\\x9B\\xAA\"\n\t\"\\xE5\\xA7\\xAC\\xE5\\xA8\\x9B\\xE5\\xA8\\xA7\\xE5\\xA7\\x98\\xE5\\xA9\\xA6\\xE3\\x9B\\xAE\\xE3\\x9B\\xBC\\xE5\\xAC\\x88\\xE5\"\n\t\"\\xAC\\xBE\\xF0\\xA1\\xA7\\x88\\xE5\\xAF\\x83\\xE5\\xAF\\x98\\xE5\\xAF\\xB3\\xF0\\xA1\\xAC\\x98\\xE5\\xAF\\xBF\\xE5\\xB0\\x86\"\n\t\"\\xE5\\xBD\\x93\\xE5\\xB0\\xA2\\xE3\\x9E\\x81\\xE5\\xB1\\xA0\\xE5\\xB3\\x80\\xE5\\xB2\\x8D\\xF0\\xA1\\xB7\\xA4\\xE5\\xB5\\x83\"\n\t\"\\xF0\\xA1\\xB7\\xA6\\xE5\\xB5\\xAE\\xE5\\xB5\\xAB\\xE5\\xB5\\xBC\\xE5\\xB7\\xA1\\xE5\\xB7\\xA2\\xE3\\xA0\\xAF\\xE5\\xB7\\xBD\"\n\t\"\\xE5\\xB8\\xA8\\xE5\\xB8\\xBD\\xE5\\xB9\\xA9\\xE3\\xA1\\xA2\\xF0\\xA2\\x86\\x83\\xE3\\xA1\\xBC\\xE5\\xBA\\xB0\\xE5\\xBA\\xB3\"\n\t\"\\xE5\\xBA\\xB6\\xF0\\xAA\\x8E\\x92\\xE5\\xBB\\xBE\\xF0\\xA2\\x8C\\xB1\\xE8\\x88\\x81\\xE5\\xBC\\xA2\\xE3\\xA3\\x87\\xF0\\xA3\"\n\t\"\\x8A\\xB8\\xF0\\xA6\\x87\\x9A\\xE5\\xBD\\xA2\\xE5\\xBD\\xAB\\xE3\\xA3\\xA3\\xE5\\xBE\\x9A\\xE5\\xBF\\x8D\\xE5\\xBF\\x97\\xE5\"\n\t\"\\xBF\\xB9\\xE6\\x82\\x81\\xE3\\xA4\\xBA\\xE3\\xA4\\x9C\\xF0\\xA2\\x9B\\x94\\xE6\\x83\\x87\\xE6\\x85\\x88\\xE6\\x85\\x8C\\xE6\"\n\t\"\\x85\\xBA\\xE6\\x86\\xB2\\xE6\\x86\\xA4\\xE6\\x86\\xAF\\xE6\\x87\\x9E\\xE6\\x88\\x90\\xE6\\x88\\x9B\\xE6\\x89\\x9D\\xE6\\x8A\"\n\t\"\\xB1\\xE6\\x8B\\x94\\xE6\\x8D\\x90\\xF0\\xA2\\xAC\\x8C\\xE6\\x8C\\xBD\\xE6\\x8B\\xBC\\xE6\\x8D\\xA8\\xE6\\x8E\\x83\\xE6\\x8F\"\n\t\"\\xA4\\xF0\\xA2\\xAF\\xB1\\xE6\\x90\\xA2\\xE6\\x8F\\x85\\xE6\\x8E\\xA9\\xE3\\xA8\\xAE\\xE6\\x91\\xA9\\xE6\\x91\\xBE\\xE6\\x92\"\n\t\"\\x9D\\xE6\\x91\\xB7\\xE3\\xA9\\xAC\\xE6\\x95\\xAC\\xF0\\xA3\\x80\\x8A\\xE6\\x97\\xA3\\xE6\\x9B\\xB8\\xE6\\x99\\x89\\xE3\\xAC\"\n\t\"\\x99\\xE3\\xAC\\x88\\xE3\\xAB\\xA4\\xE5\\x86\\x92\\xE5\\x86\\x95\\xE6\\x9C\\x80\\xE6\\x9A\\x9C\\xE8\\x82\\xAD\\xE4\\x8F\\x99\"\n\t\"\\xE6\\x9C\\xA1\\xE6\\x9D\\x9E\\xE6\\x9D\\x93\\xF0\\xA3\\x8F\\x83\\xE3\\xAD\\x89\\xE6\\x9F\\xBA\\xE6\\x9E\\x85\\xE6\\xA1\\x92\"\n\t\"\\xF0\\xA3\\x91\\xAD\\xE6\\xA2\\x8E\\xE6\\xA0\\x9F\\xE6\\xA4\\x94\\xE6\\xA5\\x82\\xE6\\xA6\\xA3\\xE6\\xA7\\xAA\\xE6\\xAA\\xA8\"\n\t\"\\xF0\\xA3\\x9A\\xA3\\xE6\\xAB\\x9B\\xE3\\xB0\\x98\\xE6\\xAC\\xA1\\xF0\\xA3\\xA2\\xA7\\xE6\\xAD\\x94\\xE3\\xB1\\x8E\\xE6\\xAD\"\n\t\"\\xB2\\xE6\\xAE\\x9F\\xE6\\xAE\\xBB\\xF0\\xA3\\xAA\\x8D\\xF0\\xA1\\xB4\\x8B\\xF0\\xA3\\xAB\\xBA\\xE6\\xB1\\x8E\\xF0\\xA3\\xB2\"\n\t\"\\xBC\\xE6\\xB2\\xBF\\xE6\\xB3\\x8D\\xE6\\xB1\\xA7\\xE6\\xB4\\x96\\xE6\\xB4\\xBE\\xE6\\xB5\\xA9\\xE6\\xB5\\xB8\\xE6\\xB6\\x85\"\n\t\"\\xF0\\xA3\\xB4\\x9E\\xE6\\xB4\\xB4\\xE6\\xB8\\xAF\\xE6\\xB9\\xAE\\xE3\\xB4\\xB3\\xE6\\xBB\\x87\\xF0\\xA3\\xBB\\x91\\xE6\\xB7\"\n\t\"\\xB9\\xE6\\xBD\\xAE\\xF0\\xA3\\xBD\\x9E\\xF0\\xA3\\xBE\\x8E\\xE6\\xBF\\x86\\xE7\\x80\\xB9\\xE7\\x80\\x9B\\xE3\\xB6\\x96\\xE7\"\n\t\"\\x81\\x8A\\xE7\\x81\\xBD\\xE7\\x81\\xB7\\xE7\\x82\\xAD\\xF0\\xA0\\x94\\xA5\\xE7\\x85\\x85\\xF0\\xA4\\x89\\xA3\\xE7\\x86\\x9C\"\n\t\"\\xF0\\xA4\\x8E\\xAB\\xE7\\x88\\xA8\\xE7\\x89\\x90\\xF0\\xA4\\x98\\x88\\xE7\\x8A\\x80\\xE7\\x8A\\x95\\xF0\\xA4\\x9C\\xB5\\xF0\"\n\t\"\\xA4\\xA0\\x94\\xE7\\x8D\\xBA\\xE7\\x8E\\x8B\\xE3\\xBA\\xAC\\xE7\\x8E\\xA5\\xE3\\xBA\\xB8\\xE7\\x91\\x87\\xE7\\x91\\x9C\\xE7\"\n\t\"\\x92\\x85\\xE7\\x93\\x8A\\xE3\\xBC\\x9B\\xE7\\x94\\xA4\\xF0\\xA4\\xB0\\xB6\\xE7\\x94\\xBE\\xF0\\xA4\\xB2\\x92\\xF0\\xA2\\x86\"\n\t\"\\x9F\\xE7\\x98\\x90\\xF0\\xA4\\xBE\\xA1\\xF0\\xA4\\xBE\\xB8\\xF0\\xA5\\x81\\x84\\xE3\\xBF\\xBC\\xE4\\x80\\x88\\xF0\\xA5\\x83\"\n\t\"\\xB3\\xF0\\xA5\\x83\\xB2\\xF0\\xA5\\x84\\x99\\xF0\\xA5\\x84\\xB3\\xE7\\x9C\\x9E\\xE7\\x9C\\x9F\\xE7\\x9E\\x8B\\xE4\\x81\\x86\"\n\t\"\\xE4\\x82\\x96\\xF0\\xA5\\x90\\x9D\\xE7\\xA1\\x8E\\xE4\\x83\\xA3\\xF0\\xA5\\x98\\xA6\\xF0\\xA5\\x9A\\x9A\\xF0\\xA5\\x9B\\x85\"\n\t\"\\xE7\\xA7\\xAB\\xE4\\x84\\xAF\\xE7\\xA9\\x8A\\xE7\\xA9\\x8F\\xF0\\xA5\\xA5\\xBC\\xF0\\xA5\\xAA\\xA7\\xE7\\xAB\\xAE\\xE4\\x88\"\n\t\"\\x82\\xF0\\xA5\\xAE\\xAB\\xE7\\xAF\\x86\\xE7\\xAF\\x89\\xE4\\x88\\xA7\\xF0\\xA5\\xB2\\x80\\xE7\\xB3\\x92\\xE4\\x8A\\xA0\\xE7\"\n\t\"\\xB3\\xA8\\xE7\\xB3\\xA3\\xE7\\xB4\\x80\\xF0\\xA5\\xBE\\x86\\xE7\\xB5\\xA3\\xE4\\x8C\\x81\\xE7\\xB7\\x87\\xE7\\xB8\\x82\\xE7\"\n\t\"\\xB9\\x85\\xE4\\x8C\\xB4\\xF0\\xA6\\x88\\xA8\\xF0\\xA6\\x89\\x87\\xE4\\x8D\\x99\\xF0\\xA6\\x8B\\x99\\xE7\\xBD\\xBA\\xF0\\xA6\"\n\t\"\\x8C\\xBE\\xE7\\xBE\\x95\\xE7\\xBF\\xBA\\xF0\\xA6\\x93\\x9A\\xF0\\xA6\\x94\\xA3\\xE8\\x81\\xA0\\xF0\\xA6\\x96\\xA8\\xE8\\x81\"\n\t\"\\xB0\\xF0\\xA3\\x8D\\x9F\\xE4\\x8F\\x95\\xE8\\x82\\xB2\\xE8\\x84\\x83\\xE4\\x90\\x8B\\xE8\\x84\\xBE\\xE5\\xAA\\xB5\\xF0\\xA6\"\n\t\"\\x9E\\xA7\\xF0\\xA6\\x9E\\xB5\\xF0\\xA3\\x8E\\x93\\xF0\\xA3\\x8E\\x9C\\xE8\\x88\\x84\\xE8\\xBE\\x9E\\xE4\\x91\\xAB\\xE8\\x8A\"\n\t\"\\x91\\xE8\\x8A\\x8B\\xE8\\x8A\\x9D\\xE5\\x8A\\xB3\\xE8\\x8A\\xB1\\xE8\\x8A\\xB3\\xE8\\x8A\\xBD\\xE8\\x8B\\xA6\\xF0\\xA6\\xAC\"\n\t\"\\xBC\\xE8\\x8C\\x9D\\xE8\\x8D\\xA3\\xE8\\x8E\\xAD\\xE8\\x8C\\xA3\\xE8\\x8E\\xBD\\xE8\\x8F\\xA7\\xE8\\x8D\\x93\\xE8\\x8F\\x8A\"\n\t\"\\xE8\\x8F\\x8C\\xE8\\x8F\\x9C\\xF0\\xA6\\xB0\\xB6\\xF0\\xA6\\xB5\\xAB\\xF0\\xA6\\xB3\\x95\\xE4\\x94\\xAB\\xE8\\x93\\xB1\\xE8\"\n\t\"\\x93\\xB3\\xE8\\x94\\x96\\xF0\\xA7\\x8F\\x8A\\xE8\\x95\\xA4\\xF0\\xA6\\xBC\\xAC\\xE4\\x95\\x9D\\xE4\\x95\\xA1\\xF0\\xA6\\xBE\"\n\t\"\\xB1\\xF0\\xA7\\x83\\x92\\xE4\\x95\\xAB\\xE8\\x99\\x90\\xE8\\x99\\xA7\\xE8\\x99\\xA9\\xE8\\x9A\\xA9\\xE8\\x9A\\x88\\xE8\\x9C\"\n\t\"\\x8E\\xE8\\x9B\\xA2\\xE8\\x9C\\xA8\\xE8\\x9D\\xAB\\xE8\\x9E\\x86\\xE4\\x97\\x97\\xE8\\x9F\\xA1\\xE8\\xA0\\x81\\xE4\\x97\\xB9\"\n\t\"\\xE8\\xA1\\xA0\\xE8\\xA1\\xA3\\xF0\\xA7\\x99\\xA7\\xE8\\xA3\\x97\\xE8\\xA3\\x9E\\xE4\\x98\\xB5\\xE8\\xA3\\xBA\\xE3\\x92\\xBB\"\n\t\"\\xF0\\xA7\\xA2\\xAE\\xF0\\xA7\\xA5\\xA6\\xE4\\x9A\\xBE\\xE4\\x9B\\x87\\xE8\\xAA\\xA0\\xE8\\xB1\\x95\\xF0\\xA7\\xB2\\xA8\\xE8\"\n\t\"\\xB2\\xAB\\xE8\\xB3\\x81\\xE8\\xB4\\x9B\\xE8\\xB5\\xB7\\xF0\\xA7\\xBC\\xAF\\xF0\\xA0\\xA0\\x84\\xE8\\xB7\\x8B\\xE8\\xB6\\xBC\"\n\t\"\\xE8\\xB7\\xB0\\xF0\\xA0\\xA3\\x9E\\xE8\\xBB\\x94\\xF0\\xA8\\x97\\x92\\xF0\\xA8\\x97\\xAD\\xE9\\x82\\x94\\xE9\\x83\\xB1\\xE9\"\n\t\"\\x84\\x91\\xF0\\xA8\\x9C\\xAE\\xE9\\x84\\x9B\\xE9\\x88\\xB8\\xE9\\x8B\\x97\\xE9\\x8B\\x98\\xE9\\x89\\xBC\\xE9\\x8F\\xB9\\xE9\"\n\t\"\\x90\\x95\\xF0\\xA8\\xAF\\xBA\\xE9\\x96\\x8B\\xE4\\xA6\\x95\\xE9\\x96\\xB7\\xF0\\xA8\\xB5\\xB7\\xE4\\xA7\\xA6\\xE9\\x9B\\x83\"\n\t\"\\xE5\\xB6\\xB2\\xE9\\x9C\\xA3\\xF0\\xA9\\x85\\x85\\xF0\\xA9\\x88\\x9A\\xE4\\xA9\\xAE\\xE4\\xA9\\xB6\\xE9\\x9F\\xA0\\xF0\\xA9\"\n\t\"\\x90\\x8A\\xE4\\xAA\\xB2\\xF0\\xA9\\x92\\x96\\xE9\\xA0\\xA9\\xF0\\xA9\\x96\\xB6\\xE9\\xA3\\xA2\\xE4\\xAC\\xB3\\xE9\\xA4\\xA9\"\n\t\"\\xE9\\xA6\\xA7\\xE9\\xA7\\x82\\xE9\\xA7\\xBE\\xE4\\xAF\\x8E\\xF0\\xA9\\xAC\\xB0\\xE9\\xB1\\x80\\xE9\\xB3\\xBD\\xE4\\xB3\\x8E\"\n\t\"\\xE4\\xB3\\xAD\\xE9\\xB5\\xA7\\xF0\\xAA\\x83\\x8E\\xE4\\xB3\\xB8\\xF0\\xAA\\x84\\x85\\xF0\\xAA\\x88\\x8E\\xF0\\xAA\\x8A\\x91\"\n\t\"\\xE9\\xBA\\xBB\\xE4\\xB5\\x96\\xE9\\xBB\\xB9\\xE9\\xBB\\xBE\\xE9\\xBC\\x85\\xE9\\xBC\\x8F\\xE9\\xBC\\x96\\xE9\\xBC\\xBB\\xF0\"\n\t\"\\xAA\\x98\\x80\\x20\\x20\\xCC\\x88\\x20\\xCC\\x84\\x32\\x33\\x20\\xCC\\x81\\xCE\\xBC\\x20\\xCC\\xA7\\x31\\x31\\xE2\\x81\\x84\"\n\t\"\\x34\\x31\\xE2\\x81\\x84\\x32\\x33\\xE2\\x81\\x84\\x34\\x49\\x4A\\x69\\x6A\\x4C\\xC2\\xB7\\x6C\\xC2\\xB7\\xCA\\xBC\\x6E\\x44\"\n\t\"\\x5A\\xCC\\x8C\\x44\\x7A\\xCC\\x8C\\x64\\x7A\\xCC\\x8C\\x4C\\x4A\\x4C\\x6A\\x6C\\x6A\\x4E\\x4A\\x4E\\x6A\\x6E\\x6A\\xC9\\xA6\"\n\t\"\\xC9\\xB9\\xC9\\xBB\\xCA\\x81\\x20\\xCC\\x86\\x20\\xCC\\x87\\x20\\xCC\\x8A\\x20\\xCC\\xA8\\x20\\xCC\\x83\\x20\\xCC\\x8B\\xC9\"\n\t\"\\xA3\\xCA\\x95\\x20\\xCD\\x85\\x20\\xCC\\x88\\xCC\\x81\\xCE\\xB2\\xCE\\xB8\\xCF\\x86\\xCF\\x80\\xCE\\xBA\\xCF\\x82\\xCE\\x98\"\n\t\"\\xCE\\xA3\\xD5\\xA5\\xD6\\x82\\xD8\\xA7\\xD9\\xB4\\xD9\\x88\\xD9\\xB4\\xDB\\x87\\xD9\\xB4\\xD9\\x8A\\xD9\\xB4\\xE0\\xB3\\x86\"\n\t\"\\xE0\\xB3\\x82\\xE0\\xB3\\x95\\xE0\\xB7\\x99\\xE0\\xB7\\x8F\\xE0\\xB7\\x8A\\xE0\\xB9\\x8D\\xE0\\xB8\\xB2\\xE0\\xBB\\x8D\\xE0\"\n\t\"\\xBA\\xB2\\xE0\\xBA\\xAB\\xE0\\xBA\\x99\\xE0\\xBA\\xAB\\xE0\\xBA\\xA1\\xE0\\xBC\\x8B\\xE0\\xBE\\xB2\\xE0\\xBD\\xB1\\xE0\\xBE\"\n\t\"\\x80\\xE0\\xBE\\xB3\\xE0\\xBD\\xB1\\xE0\\xBE\\x80\\xE1\\x83\\x9C\\xC6\\x8E\\xC8\\xA2\\xC9\\x90\\xC9\\x91\\xE1\\xB4\\x82\\xC9\"\n\t\"\\x99\\xC9\\x9B\\xC9\\x9C\\xC5\\x8B\\xC9\\x94\\xE1\\xB4\\x96\\xE1\\xB4\\x97\\xE1\\xB4\\x9D\\xC9\\xAF\\xE1\\xB4\\xA5\\xCE\\xB3\"\n\t\"\\xCE\\xB4\\xCF\\x87\\xD0\\xBD\\xC9\\x92\\xC9\\x95\\xC3\\xB0\\xC9\\x9F\\xC9\\xA1\\xC9\\xA5\\xC9\\xA8\\xC9\\xA9\\xC9\\xAA\\xE1\"\n\t\"\\xB5\\xBB\\xCA\\x9D\\xC9\\xAD\\xE1\\xB6\\x85\\xCA\\x9F\\xC9\\xB1\\xC9\\xB0\\xC9\\xB2\\xC9\\xB3\\xC9\\xB4\\xC9\\xB5\\xC9\\xB8\"\n\t\"\\xCA\\x82\\xCA\\x83\\xC6\\xAB\\xCA\\x89\\xCA\\x8A\\xE1\\xB4\\x9C\\xCA\\x8B\\xCA\\x8C\\xCA\\x90\\xCA\\x91\\x61\\xCA\\xBE\\xCE\"\n\t\"\\xA5\\xCC\\x94\\xCC\\x80\\xCE\\xB1\\xCD\\x82\\xCD\\x85\\x20\\xCC\\x93\\x20\\xCD\\x82\\x20\\xCC\\x88\\xCD\\x82\\xCE\\xB7\\xCD\"\n\t\"\\x82\\xCD\\x85\\x20\\xCC\\x93\\xCC\\x80\\x20\\xCC\\x93\\xCC\\x81\\x20\\xCC\\x93\\xCD\\x82\\x20\\xCC\\x94\\xCC\\x80\\x20\\xCC\"\n\t\"\\x94\\xCC\\x81\\x20\\xCC\\x94\\xCD\\x82\\x20\\xCC\\x88\\xCC\\x80\\xCF\\x89\\xCD\\x82\\xCD\\x85\\xE2\\x80\\x90\\x20\\xCC\\xB3\"\n\t\"\\x2E\\x2E\\x2E\\xE2\\x80\\xB2\\xE2\\x80\\xB2\\xE2\\x80\\xB2\\xE2\\x80\\xB2\\xE2\\x80\\xB2\\xE2\\x80\\xB5\\xE2\\x80\\xB5\\xE2\"\n\t\"\\x80\\xB5\\xE2\\x80\\xB5\\xE2\\x80\\xB5\\x21\\x21\\x20\\xCC\\x85\\x3F\\x3F\\x3F\\x21\\x21\\x3F\\x30\\x35\\x36\\x37\\x38\\x39\"\n\t\"\\x2B\\xE2\\x88\\x92\\x28\\x29\\x52\\x73\\x61\\x2F\\x63\\x61\\x2F\\x73\\xC2\\xB0\\x43\\x63\\x2F\\x6F\\x63\\x2F\\x75\\xC6\\x90\"\n\t\"\\xC2\\xB0\\x46\\xC4\\xA7\\x4E\\x6F\\x51\\x53\\x4D\\x54\\x45\\x4C\\x54\\x4D\\x46\\x41\\x58\\xCE\\x93\\xCE\\xA0\\xE2\\x88\\x91\"\n\t\"\\x31\\xE2\\x81\\x84\\x37\\x31\\xE2\\x81\\x84\\x39\\x31\\xE2\\x81\\x84\\x31\\x30\\x31\\xE2\\x81\\x84\\x33\\x32\\xE2\\x81\\x84\"\n\t\"\\x33\\x31\\xE2\\x81\\x84\\x35\\x32\\xE2\\x81\\x84\\x35\\x33\\xE2\\x81\\x84\\x35\\x34\\xE2\\x81\\x84\\x35\\x31\\xE2\\x81\\x84\"\n\t\"\\x36\\x35\\xE2\\x81\\x84\\x36\\x31\\xE2\\x81\\x84\\x38\\x33\\xE2\\x81\\x84\\x38\\x35\\xE2\\x81\\x84\\x38\\x37\\xE2\\x81\\x84\"\n\t\"\\x38\\x49\\x49\\x49\\x49\\x49\\x49\\x56\\x56\\x49\\x56\\x49\\x49\\x56\\x49\\x49\\x49\\x49\\x58\\x58\\x49\\x58\\x49\\x49\\x69\"\n\t\"\\x69\\x69\\x69\\x69\\x69\\x76\\x76\\x69\\x76\\x69\\x69\\x76\\x69\\x69\\x69\\x69\\x78\\x78\\x69\\x78\\x69\\x69\\x30\\xE2\\x81\"\n\t\"\\x84\\x33\\xE2\\x88\\xAB\\xE2\\x88\\xAB\\xE2\\x88\\xAB\\xE2\\x88\\xAB\\xE2\\x88\\xAB\\xE2\\x88\\xAE\\xE2\\x88\\xAE\\xE2\\x88\"\n\t\"\\xAE\\xE2\\x88\\xAE\\xE2\\x88\\xAE\\x31\\x32\\x31\\x33\\x31\\x34\\x31\\x35\\x31\\x36\\x31\\x37\\x31\\x38\\x31\\x39\\x32\\x30\"\n\t\"\\x28\\x31\\x29\\x28\\x32\\x29\\x28\\x33\\x29\\x28\\x34\\x29\\x28\\x35\\x29\\x28\\x36\\x29\\x28\\x37\\x29\\x28\\x38\\x29\\x28\"\n\t\"\\x39\\x29\\x28\\x31\\x30\\x29\\x28\\x31\\x31\\x29\\x28\\x31\\x32\\x29\\x28\\x31\\x33\\x29\\x28\\x31\\x34\\x29\\x28\\x31\\x35\"\n\t\"\\x29\\x28\\x31\\x36\\x29\\x28\\x31\\x37\\x29\\x28\\x31\\x38\\x29\\x28\\x31\\x39\\x29\\x28\\x32\\x30\\x29\\x31\\x2E\\x32\\x2E\"\n\t\"\\x33\\x2E\\x34\\x2E\\x35\\x2E\\x36\\x2E\\x37\\x2E\\x38\\x2E\\x39\\x2E\\x31\\x30\\x2E\\x31\\x31\\x2E\\x31\\x32\\x2E\\x31\\x33\"\n\t\"\\x2E\\x31\\x34\\x2E\\x31\\x35\\x2E\\x31\\x36\\x2E\\x31\\x37\\x2E\\x31\\x38\\x2E\\x31\\x39\\x2E\\x32\\x30\\x2E\\x28\\x61\\x29\"\n\t\"\\x28\\x62\\x29\\x28\\x63\\x29\\x28\\x64\\x29\\x28\\x65\\x29\\x28\\x66\\x29\\x28\\x67\\x29\\x28\\x68\\x29\\x28\\x69\\x29\\x28\"\n\t\"\\x6A\\x29\\x28\\x6B\\x29\\x28\\x6C\\x29\\x28\\x6D\\x29\\x28\\x6E\\x29\\x28\\x6F\\x29\\x28\\x70\\x29\\x28\\x71\\x29\\x28\\x72\"\n\t\"\\x29\\x28\\x73\\x29\\x28\\x74\\x29\\x28\\x75\\x29\\x28\\x76\\x29\\x28\\x77\\x29\\x28\\x78\\x29\\x28\\x79\\x29\\x28\\x7A\\x29\"\n\t\"\\x3A\\x3A\\x3D\\x3D\\x3D\\xE2\\xB5\\xA1\\xE6\\xAF\\x8D\\xE9\\xBE\\x9F\\xE4\\xB8\\x80\\xE4\\xB8\\xA8\\xE4\\xB8\\xB6\\xE4\\xB8\"\n\t\"\\xBF\\xE4\\xB9\\x99\\xE4\\xBA\\x85\\xE4\\xBA\\x8C\\xE4\\xBA\\xA0\\xE4\\xBA\\xBA\\xE5\\x84\\xBF\\xE5\\x85\\xA5\\xE5\\x85\\xAB\"\n\t\"\\xE5\\x86\\x82\\xE5\\x86\\x96\\xE5\\x86\\xAB\\xE5\\x87\\xA0\\xE5\\x88\\x80\\xE5\\x8B\\xB9\\xE5\\x8C\\x95\\xE5\\x8C\\x9A\\xE5\"\n\t\"\\x8C\\xB8\\xE5\\x8D\\x81\\xE5\\x8D\\x9C\\xE5\\x8D\\xA9\\xE5\\x8E\\x82\\xE5\\x8E\\xB6\\xE5\\x8F\\x88\\xE5\\x8F\\xA3\\xE5\\x9B\"\n\t\"\\x97\\xE5\\x9C\\x9F\\xE5\\xA3\\xAB\\xE5\\xA4\\x82\\xE5\\xA4\\x8A\\xE5\\xA4\\x95\\xE5\\xA4\\xA7\\xE5\\xAD\\x90\\xE5\\xAE\\x80\"\n\t\"\\xE5\\xAF\\xB8\\xE5\\xB0\\x8F\\xE5\\xB0\\xB8\\xE5\\xB1\\xB1\\xE5\\xB7\\x9B\\xE5\\xB7\\xA5\\xE5\\xB7\\xB1\\xE5\\xB7\\xBE\\xE5\"\n\t\"\\xB9\\xB2\\xE5\\xB9\\xBA\\xE5\\xB9\\xBF\\xE5\\xBB\\xB4\\xE5\\xBC\\x8B\\xE5\\xBC\\x93\\xE5\\xBD\\x90\\xE5\\xBD\\xA1\\xE5\\xBD\"\n\t\"\\xB3\\xE5\\xBF\\x83\\xE6\\x88\\x88\\xE6\\x88\\xB6\\xE6\\x89\\x8B\\xE6\\x94\\xAF\\xE6\\x94\\xB4\\xE6\\x96\\x87\\xE6\\x96\\x97\"\n\t\"\\xE6\\x96\\xA4\\xE6\\x96\\xB9\\xE6\\x97\\xA0\\xE6\\x97\\xA5\\xE6\\x9B\\xB0\\xE6\\x9C\\x88\\xE6\\x9C\\xA8\\xE6\\xAC\\xA0\\xE6\"\n\t\"\\xAD\\xA2\\xE6\\xAE\\xB3\\xE6\\xAF\\x8B\\xE6\\xAF\\x94\\xE6\\xAF\\x9B\\xE6\\xB0\\x8F\\xE6\\xB0\\x94\\xE6\\xB0\\xB4\\xE7\\x81\"\n\t\"\\xAB\\xE7\\x88\\xAA\\xE7\\x88\\xB6\\xE7\\x88\\xBB\\xE7\\x88\\xBF\\xE7\\x89\\x87\\xE7\\x89\\x99\\xE7\\x89\\x9B\\xE7\\x8A\\xAC\"\n\t\"\\xE7\\x8E\\x84\\xE7\\x8E\\x89\\xE7\\x93\\x9C\\xE7\\x93\\xA6\\xE7\\x94\\x98\\xE7\\x94\\x9F\\xE7\\x94\\xA8\\xE7\\x94\\xB0\\xE7\"\n\t\"\\x96\\x8B\\xE7\\x96\\x92\\xE7\\x99\\xB6\\xE7\\x99\\xBD\\xE7\\x9A\\xAE\\xE7\\x9A\\xBF\\xE7\\x9B\\xAE\\xE7\\x9F\\x9B\\xE7\\x9F\"\n\t\"\\xA2\\xE7\\x9F\\xB3\\xE7\\xA4\\xBA\\xE7\\xA6\\xB8\\xE7\\xA6\\xBE\\xE7\\xA9\\xB4\\xE7\\xAB\\xB9\\xE7\\xB1\\xB3\\xE7\\xB3\\xB8\"\n\t\"\\xE7\\xBC\\xB6\\xE7\\xBD\\x91\\xE7\\xBE\\x8A\\xE8\\x80\\x8C\\xE8\\x80\\x92\\xE8\\x80\\xB3\\xE8\\x81\\xBF\\xE8\\x82\\x89\\xE8\"\n\t\"\\x87\\xA3\\xE8\\x87\\xAA\\xE8\\x87\\xB3\\xE8\\x87\\xBC\\xE8\\x88\\x8C\\xE8\\x88\\x9B\\xE8\\x88\\x9F\\xE8\\x89\\xAE\\xE8\\x89\"\n\t\"\\xB2\\xE8\\x89\\xB8\\xE8\\x99\\x8D\\xE8\\x99\\xAB\\xE8\\xA1\\x80\\xE8\\xA5\\xBE\\xE8\\xA7\\x92\\xE8\\xA8\\x80\\xE8\\xB0\\xB7\"\n\t\"\\xE8\\xB1\\x86\\xE8\\xB1\\xB8\\xE8\\xB2\\x9D\\xE8\\xB5\\xA4\\xE8\\xB5\\xB0\\xE8\\xB6\\xB3\\xE8\\xBA\\xAB\\xE8\\xBE\\x9B\\xE8\"\n\t\"\\xBE\\xB5\\xE9\\x82\\x91\\xE9\\x85\\x89\\xE9\\x87\\x86\\xE9\\x95\\xB7\\xE9\\x96\\x80\\xE9\\x98\\x9C\\xE9\\x9A\\xB6\\xE9\\x9A\"\n\t\"\\xB9\\xE9\\x9B\\xA8\\xE9\\x9D\\x91\\xE9\\x9D\\x9E\\xE9\\x9D\\xA2\\xE9\\x9D\\xA9\\xE9\\x9F\\x8B\\xE9\\x9F\\xAD\\xE9\\x9F\\xB3\"\n\t\"\\xE9\\xA0\\x81\\xE9\\xA2\\xA8\\xE9\\xA3\\x9B\\xE9\\xA3\\x9F\\xE9\\xA6\\x96\\xE9\\xA6\\x99\\xE9\\xA6\\xAC\\xE9\\xAA\\xA8\\xE9\"\n\t\"\\xAB\\x98\\xE9\\xAB\\x9F\\xE9\\xAC\\xA5\\xE9\\xAC\\xAF\\xE9\\xAC\\xB2\\xE9\\xAC\\xBC\\xE9\\xAD\\x9A\\xE9\\xB3\\xA5\\xE9\\xB9\"\n\t\"\\xB5\\xE9\\xBA\\xA5\\xE9\\xBB\\x83\\xE9\\xBB\\x8D\\xE9\\xBB\\x91\\xE9\\xBB\\xBD\\xE9\\xBC\\x8E\\xE9\\xBC\\x93\\xE9\\xBC\\xA0\"\n\t\"\\xE9\\xBD\\x8A\\xE9\\xBD\\x92\\xE9\\xBE\\xA0\\xE3\\x80\\x92\\xE5\\x8D\\x84\\xE5\\x8D\\x85\\x20\\xE3\\x82\\x99\\x20\\xE3\\x82\"\n\t\"\\x9A\\xE3\\x82\\x88\\xE3\\x82\\x8A\\xE3\\x82\\xB3\\xE3\\x83\\x88\\xE1\\x84\\x80\\xE1\\x84\\x81\\xE1\\x86\\xAA\\xE1\\x84\\x82\"\n\t\"\\xE1\\x86\\xAC\\xE1\\x86\\xAD\\xE1\\x84\\x83\\xE1\\x84\\x84\\xE1\\x84\\x85\\xE1\\x86\\xB0\\xE1\\x86\\xB1\\xE1\\x86\\xB2\\xE1\"\n\t\"\\x86\\xB3\\xE1\\x86\\xB4\\xE1\\x86\\xB5\\xE1\\x84\\x9A\\xE1\\x84\\x86\\xE1\\x84\\x87\\xE1\\x84\\x88\\xE1\\x84\\xA1\\xE1\\x84\"\n\t\"\\x89\\xE1\\x84\\x8A\\xE1\\x84\\x8B\\xE1\\x84\\x8C\\xE1\\x84\\x8D\\xE1\\x84\\x8E\\xE1\\x84\\x8F\\xE1\\x84\\x90\\xE1\\x84\\x91\"\n\t\"\\xE1\\x84\\x92\\xE1\\x85\\xA1\\xE1\\x85\\xA2\\xE1\\x85\\xA3\\xE1\\x85\\xA4\\xE1\\x85\\xA5\\xE1\\x85\\xA6\\xE1\\x85\\xA7\\xE1\"\n\t\"\\x85\\xA8\\xE1\\x85\\xA9\\xE1\\x85\\xAA\\xE1\\x85\\xAB\\xE1\\x85\\xAC\\xE1\\x85\\xAD\\xE1\\x85\\xAE\\xE1\\x85\\xAF\\xE1\\x85\"\n\t\"\\xB0\\xE1\\x85\\xB1\\xE1\\x85\\xB2\\xE1\\x85\\xB3\\xE1\\x85\\xB4\\xE1\\x85\\xB5\\xE1\\x85\\xA0\\xE1\\x84\\x94\\xE1\\x84\\x95\"\n\t\"\\xE1\\x87\\x87\\xE1\\x87\\x88\\xE1\\x87\\x8C\\xE1\\x87\\x8E\\xE1\\x87\\x93\\xE1\\x87\\x97\\xE1\\x87\\x99\\xE1\\x84\\x9C\\xE1\"\n\t\"\\x87\\x9D\\xE1\\x87\\x9F\\xE1\\x84\\x9D\\xE1\\x84\\x9E\\xE1\\x84\\xA0\\xE1\\x84\\xA2\\xE1\\x84\\xA3\\xE1\\x84\\xA7\\xE1\\x84\"\n\t\"\\xA9\\xE1\\x84\\xAB\\xE1\\x84\\xAC\\xE1\\x84\\xAD\\xE1\\x84\\xAE\\xE1\\x84\\xAF\\xE1\\x84\\xB2\\xE1\\x84\\xB6\\xE1\\x85\\x80\"\n\t\"\\xE1\\x85\\x87\\xE1\\x85\\x8C\\xE1\\x87\\xB1\\xE1\\x87\\xB2\\xE1\\x85\\x97\\xE1\\x85\\x98\\xE1\\x85\\x99\\xE1\\x86\\x84\\xE1\"\n\t\"\\x86\\x85\\xE1\\x86\\x88\\xE1\\x86\\x91\\xE1\\x86\\x92\\xE1\\x86\\x94\\xE1\\x86\\x9E\\xE1\\x86\\xA1\\xE4\\xB8\\x89\\xE5\\x9B\"\n\t\"\\x9B\\xE4\\xB8\\x8A\\xE4\\xB8\\xAD\\xE4\\xB8\\x8B\\xE7\\x94\\xB2\\xE4\\xB8\\x99\\xE4\\xB8\\x81\\xE5\\xA4\\xA9\\xE5\\x9C\\xB0\"\n\t\"\\x28\\xE1\\x84\\x80\\x29\\x28\\xE1\\x84\\x82\\x29\\x28\\xE1\\x84\\x83\\x29\\x28\\xE1\\x84\\x85\\x29\\x28\\xE1\\x84\\x86\\x29\"\n\t\"\\x28\\xE1\\x84\\x87\\x29\\x28\\xE1\\x84\\x89\\x29\\x28\\xE1\\x84\\x8B\\x29\\x28\\xE1\\x84\\x8C\\x29\\x28\\xE1\\x84\\x8E\\x29\"\n\t\"\\x28\\xE1\\x84\\x8F\\x29\\x28\\xE1\\x84\\x90\\x29\\x28\\xE1\\x84\\x91\\x29\\x28\\xE1\\x84\\x92\\x29\\x28\\xE1\\x84\\x80\\xE1\"\n\t\"\\x85\\xA1\\x29\\x28\\xE1\\x84\\x82\\xE1\\x85\\xA1\\x29\\x28\\xE1\\x84\\x83\\xE1\\x85\\xA1\\x29\\x28\\xE1\\x84\\x85\\xE1\\x85\"\n\t\"\\xA1\\x29\\x28\\xE1\\x84\\x86\\xE1\\x85\\xA1\\x29\\x28\\xE1\\x84\\x87\\xE1\\x85\\xA1\\x29\\x28\\xE1\\x84\\x89\\xE1\\x85\\xA1\"\n\t\"\\x29\\x28\\xE1\\x84\\x8B\\xE1\\x85\\xA1\\x29\\x28\\xE1\\x84\\x8C\\xE1\\x85\\xA1\\x29\\x28\\xE1\\x84\\x8E\\xE1\\x85\\xA1\\x29\"\n\t\"\\x28\\xE1\\x84\\x8F\\xE1\\x85\\xA1\\x29\\x28\\xE1\\x84\\x90\\xE1\\x85\\xA1\\x29\\x28\\xE1\\x84\\x91\\xE1\\x85\\xA1\\x29\\x28\"\n\t\"\\xE1\\x84\\x92\\xE1\\x85\\xA1\\x29\\x28\\xE1\\x84\\x8C\\xE1\\x85\\xAE\\x29\\x28\\xE1\\x84\\x8B\\xE1\\x85\\xA9\\xE1\\x84\\x8C\"\n\t\"\\xE1\\x85\\xA5\\xE1\\x86\\xAB\\x29\\x28\\xE1\\x84\\x8B\\xE1\\x85\\xA9\\xE1\\x84\\x92\\xE1\\x85\\xAE\\x29\\x28\\xE4\\xB8\\x80\"\n\t\"\\x29\\x28\\xE4\\xBA\\x8C\\x29\\x28\\xE4\\xB8\\x89\\x29\\x28\\xE5\\x9B\\x9B\\x29\\x28\\xE4\\xBA\\x94\\x29\\x28\\xE5\\x85\\xAD\"\n\t\"\\x29\\x28\\xE4\\xB8\\x83\\x29\\x28\\xE5\\x85\\xAB\\x29\\x28\\xE4\\xB9\\x9D\\x29\\x28\\xE5\\x8D\\x81\\x29\\x28\\xE6\\x9C\\x88\"\n\t\"\\x29\\x28\\xE7\\x81\\xAB\\x29\\x28\\xE6\\xB0\\xB4\\x29\\x28\\xE6\\x9C\\xA8\\x29\\x28\\xE9\\x87\\x91\\x29\\x28\\xE5\\x9C\\x9F\"\n\t\"\\x29\\x28\\xE6\\x97\\xA5\\x29\\x28\\xE6\\xA0\\xAA\\x29\\x28\\xE6\\x9C\\x89\\x29\\x28\\xE7\\xA4\\xBE\\x29\\x28\\xE5\\x90\\x8D\"\n\t\"\\x29\\x28\\xE7\\x89\\xB9\\x29\\x28\\xE8\\xB2\\xA1\\x29\\x28\\xE7\\xA5\\x9D\\x29\\x28\\xE5\\x8A\\xB4\\x29\\x28\\xE4\\xBB\\xA3\"\n\t\"\\x29\\x28\\xE5\\x91\\xBC\\x29\\x28\\xE5\\xAD\\xA6\\x29\\x28\\xE7\\x9B\\xA3\\x29\\x28\\xE4\\xBC\\x81\\x29\\x28\\xE8\\xB3\\x87\"\n\t\"\\x29\\x28\\xE5\\x8D\\x94\\x29\\x28\\xE7\\xA5\\xAD\\x29\\x28\\xE4\\xBC\\x91\\x29\\x28\\xE8\\x87\\xAA\\x29\\x28\\xE8\\x87\\xB3\"\n\t\"\\x29\\xE5\\x95\\x8F\\xE5\\xB9\\xBC\\xE7\\xAE\\x8F\\x50\\x54\\x45\\x32\\x32\\x32\\x34\\x32\\x35\\x32\\x36\\x32\\x37\\x32\\x38\"\n\t\"\\x32\\x39\\x33\\x30\\x33\\x33\\x33\\x34\\x33\\x35\\xE1\\x84\\x8E\\xE1\\x85\\xA1\\xE1\\x86\\xB7\\xE1\\x84\\x80\\xE1\\x85\\xA9\"\n\t\"\\xE1\\x84\\x8C\\xE1\\x85\\xAE\\xE1\\x84\\x8B\\xE1\\x85\\xB4\\xE1\\x84\\x8B\\xE1\\x85\\xAE\\xE7\\xA7\\x98\\xE7\\x94\\xB7\\xE9\"\n\t\"\\x81\\xA9\\xE5\\x84\\xAA\\xE5\\x8D\\xB0\\xE6\\xB3\\xA8\\xE9\\xA0\\x85\\xE5\\x86\\x99\\xE6\\xAD\\xA3\\xE5\\xB7\\xA6\\xE5\\x8F\"\n\t\"\\xB3\\xE5\\x8C\\xBB\\xE5\\xAE\\x97\\xE5\\xA4\\x9C\\x33\\x36\\x33\\x37\\x33\\x38\\x33\\x39\\x34\\x30\\x34\\x34\\x34\\x35\\x34\"\n\t\"\\x36\\x34\\x37\\x34\\x38\\x34\\x39\\x35\\x30\\x31\\xE6\\x9C\\x88\\x32\\xE6\\x9C\\x88\\x33\\xE6\\x9C\\x88\\x34\\xE6\\x9C\\x88\"\n\t\"\\x35\\xE6\\x9C\\x88\\x36\\xE6\\x9C\\x88\\x37\\xE6\\x9C\\x88\\x38\\xE6\\x9C\\x88\\x39\\xE6\\x9C\\x88\\x31\\x30\\xE6\\x9C\\x88\"\n\t\"\\x31\\x31\\xE6\\x9C\\x88\\x31\\x32\\xE6\\x9C\\x88\\x48\\x67\\x65\\x72\\x67\\x65\\x56\\x4C\\x54\\x44\\xE3\\x82\\xA2\\xE3\\x82\"\n\t\"\\xA4\\xE3\\x82\\xA8\\xE3\\x82\\xAA\\xE3\\x83\\x8A\\xE3\\x83\\x8B\\xE3\\x83\\x8C\\xE3\\x83\\x8D\\xE3\\x83\\x8E\\xE3\\x83\\x9E\"\n\t\"\\xE3\\x83\\x9F\\xE3\\x83\\xA0\\xE3\\x83\\xA1\\xE3\\x83\\xA2\\xE3\\x83\\xA4\\xE3\\x83\\xA6\\xE3\\x83\\xA8\\xE3\\x83\\xA9\\xE3\"\n\t\"\\x83\\xAA\\xE3\\x83\\xAB\\xE3\\x83\\xAC\\xE3\\x83\\xAD\\xE3\\x82\\xA2\\xE3\\x83\\x8F\\xE3\\x82\\x9A\\xE3\\x83\\xBC\\xE3\\x83\"\n\t\"\\x88\\xE3\\x82\\xA2\\xE3\\x83\\xAB\\xE3\\x83\\x95\\xE3\\x82\\xA1\\xE3\\x82\\xA2\\xE3\\x83\\xB3\\xE3\\x83\\x98\\xE3\\x82\\x9A\"\n\t\"\\xE3\\x82\\xA2\\xE3\\x82\\xA2\\xE3\\x83\\xBC\\xE3\\x83\\xAB\\xE3\\x82\\xA4\\xE3\\x83\\x8B\\xE3\\x83\\xB3\\xE3\\x82\\xAF\\xE3\"\n\t\"\\x82\\x99\\xE3\\x82\\xA4\\xE3\\x83\\xB3\\xE3\\x83\\x81\\xE3\\x82\\xA6\\xE3\\x82\\xA9\\xE3\\x83\\xB3\\xE3\\x82\\xA8\\xE3\\x82\"\n\t\"\\xB9\\xE3\\x82\\xAF\\xE3\\x83\\xBC\\xE3\\x83\\x88\\xE3\\x82\\x99\\xE3\\x82\\xA8\\xE3\\x83\\xBC\\xE3\\x82\\xAB\\xE3\\x83\\xBC\"\n\t\"\\xE3\\x82\\xAA\\xE3\\x83\\xB3\\xE3\\x82\\xB9\\xE3\\x82\\xAA\\xE3\\x83\\xBC\\xE3\\x83\\xA0\\xE3\\x82\\xAB\\xE3\\x82\\xA4\\xE3\"\n\t\"\\x83\\xAA\\xE3\\x82\\xAB\\xE3\\x83\\xA9\\xE3\\x83\\x83\\xE3\\x83\\x88\\xE3\\x82\\xAB\\xE3\\x83\\xAD\\xE3\\x83\\xAA\\xE3\\x83\"\n\t\"\\xBC\\xE3\\x82\\xAB\\xE3\\x82\\x99\\xE3\\x83\\xAD\\xE3\\x83\\xB3\\xE3\\x82\\xAB\\xE3\\x82\\x99\\xE3\\x83\\xB3\\xE3\\x83\\x9E\"\n\t\"\\xE3\\x82\\xAD\\xE3\\x82\\x99\\xE3\\x82\\xAB\\xE3\\x82\\x99\\xE3\\x82\\xAD\\xE3\\x82\\x99\\xE3\\x83\\x8B\\xE3\\x83\\xBC\\xE3\"\n\t\"\\x82\\xAD\\xE3\\x83\\xA5\\xE3\\x83\\xAA\\xE3\\x83\\xBC\\xE3\\x82\\xAD\\xE3\\x82\\x99\\xE3\\x83\\xAB\\xE3\\x82\\xBF\\xE3\\x82\"\n\t\"\\x99\\xE3\\x83\\xBC\\xE3\\x82\\xAD\\xE3\\x83\\xAD\\xE3\\x82\\xAD\\xE3\\x83\\xAD\\xE3\\x82\\xAF\\xE3\\x82\\x99\\xE3\\x83\\xA9\"\n\t\"\\xE3\\x83\\xA0\\xE3\\x82\\xAD\\xE3\\x83\\xAD\\xE3\\x83\\xA1\\xE3\\x83\\xBC\\xE3\\x83\\x88\\xE3\\x83\\xAB\\xE3\\x82\\xAD\\xE3\"\n\t\"\\x83\\xAD\\xE3\\x83\\xAF\\xE3\\x83\\x83\\xE3\\x83\\x88\\xE3\\x82\\xAF\\xE3\\x82\\x99\\xE3\\x83\\xA9\\xE3\\x83\\xA0\\xE3\\x83\"\n\t\"\\x88\\xE3\\x83\\xB3\\xE3\\x82\\xAF\\xE3\\x83\\xAB\\xE3\\x82\\xBB\\xE3\\x82\\x99\\xE3\\x82\\xA4\\xE3\\x83\\xAD\\xE3\\x82\\xAF\"\n\t\"\\xE3\\x83\\xAD\\xE3\\x83\\xBC\\xE3\\x83\\x8D\\xE3\\x82\\xB1\\xE3\\x83\\xBC\\xE3\\x82\\xB9\\xE3\\x82\\xB3\\xE3\\x83\\xAB\\xE3\"\n\t\"\\x83\\x8A\\xE3\\x82\\xB3\\xE3\\x83\\xBC\\xE3\\x83\\x9B\\xE3\\x82\\x9A\\xE3\\x82\\xB5\\xE3\\x82\\xA4\\xE3\\x82\\xAF\\xE3\\x83\"\n\t\"\\xAB\\xE3\\x82\\xB5\\xE3\\x83\\xB3\\xE3\\x83\\x81\\xE3\\x83\\xBC\\xE3\\x83\\xA0\\xE3\\x82\\xB7\\xE3\\x83\\xAA\\xE3\\x83\\xB3\"\n\t\"\\xE3\\x82\\xAF\\xE3\\x82\\x99\\xE3\\x82\\xBB\\xE3\\x83\\xB3\\xE3\\x83\\x81\\xE3\\x82\\xBB\\xE3\\x83\\xB3\\xE3\\x83\\x88\\xE3\"\n\t\"\\x82\\xBF\\xE3\\x82\\x99\\xE3\\x83\\xBC\\xE3\\x82\\xB9\\xE3\\x83\\x86\\xE3\\x82\\x99\\xE3\\x82\\xB7\\xE3\\x83\\x88\\xE3\\x82\"\n\t\"\\x99\\xE3\\x83\\xAB\\xE3\\x83\\x8A\\xE3\\x83\\x8E\\xE3\\x83\\x8E\\xE3\\x83\\x83\\xE3\\x83\\x88\\xE3\\x83\\x8F\\xE3\\x82\\xA4\"\n\t\"\\xE3\\x83\\x84\\xE3\\x83\\x8F\\xE3\\x82\\x9A\\xE3\\x83\\xBC\\xE3\\x82\\xBB\\xE3\\x83\\xB3\\xE3\\x83\\x88\\xE3\\x83\\x8F\\xE3\"\n\t\"\\x82\\x9A\\xE3\\x83\\xBC\\xE3\\x83\\x84\\xE3\\x83\\x8F\\xE3\\x82\\x99\\xE3\\x83\\xBC\\xE3\\x83\\xAC\\xE3\\x83\\xAB\\xE3\\x83\"\n\t\"\\x92\\xE3\\x82\\x9A\\xE3\\x82\\xA2\\xE3\\x82\\xB9\\xE3\\x83\\x88\\xE3\\x83\\xAB\\xE3\\x83\\x92\\xE3\\x82\\x9A\\xE3\\x82\\xAF\"\n\t\"\\xE3\\x83\\xAB\\xE3\\x83\\x92\\xE3\\x82\\x9A\\xE3\\x82\\xB3\\xE3\\x83\\x92\\xE3\\x82\\x99\\xE3\\x83\\xAB\\xE3\\x83\\x95\\xE3\"\n\t\"\\x82\\xA1\\xE3\\x83\\xA9\\xE3\\x83\\x83\\xE3\\x83\\x88\\xE3\\x82\\x99\\xE3\\x83\\x95\\xE3\\x82\\xA3\\xE3\\x83\\xBC\\xE3\\x83\"\n\t\"\\x88\\xE3\\x83\\x95\\xE3\\x82\\x99\\xE3\\x83\\x83\\xE3\\x82\\xB7\\xE3\\x82\\xA7\\xE3\\x83\\xAB\\xE3\\x83\\x95\\xE3\\x83\\xA9\"\n\t\"\\xE3\\x83\\xB3\\xE3\\x83\\x98\\xE3\\x82\\xAF\\xE3\\x82\\xBF\\xE3\\x83\\xBC\\xE3\\x83\\xAB\\xE3\\x83\\x98\\xE3\\x82\\x9A\\xE3\"\n\t\"\\x82\\xBD\\xE3\\x83\\x98\\xE3\\x82\\x9A\\xE3\\x83\\x8B\\xE3\\x83\\x92\\xE3\\x83\\x98\\xE3\\x83\\xAB\\xE3\\x83\\x84\\xE3\\x83\"\n\t\"\\x98\\xE3\\x82\\x9A\\xE3\\x83\\xB3\\xE3\\x82\\xB9\\xE3\\x83\\x98\\xE3\\x82\\x9A\\xE3\\x83\\xBC\\xE3\\x82\\xB7\\xE3\\x82\\x99\"\n\t\"\\xE3\\x83\\x98\\xE3\\x82\\x99\\xE3\\x83\\xBC\\xE3\\x82\\xBF\\xE3\\x83\\x9B\\xE3\\x82\\x9A\\xE3\\x82\\xA4\\xE3\\x83\\xB3\\xE3\"\n\t\"\\x83\\x88\\xE3\\x83\\x9B\\xE3\\x82\\x99\\xE3\\x83\\xAB\\xE3\\x83\\x88\\xE3\\x83\\x9B\\xE3\\x83\\xB3\\xE3\\x83\\x9B\\xE3\\x82\"\n\t\"\\x9A\\xE3\\x83\\xB3\\xE3\\x83\\x88\\xE3\\x82\\x99\\xE3\\x83\\x9B\\xE3\\x83\\xBC\\xE3\\x83\\xAB\\xE3\\x83\\x9B\\xE3\\x83\\xBC\"\n\t\"\\xE3\\x83\\xB3\\xE3\\x83\\x9E\\xE3\\x82\\xA4\\xE3\\x82\\xAF\\xE3\\x83\\xAD\\xE3\\x83\\x9E\\xE3\\x82\\xA4\\xE3\\x83\\xAB\\xE3\"\n\t\"\\x83\\x9E\\xE3\\x83\\x83\\xE3\\x83\\x8F\\xE3\\x83\\x9E\\xE3\\x83\\xAB\\xE3\\x82\\xAF\\xE3\\x83\\x9E\\xE3\\x83\\xB3\\xE3\\x82\"\n\t\"\\xB7\\xE3\\x83\\xA7\\xE3\\x83\\xB3\\xE3\\x83\\x9F\\xE3\\x82\\xAF\\xE3\\x83\\xAD\\xE3\\x83\\xB3\\xE3\\x83\\x9F\\xE3\\x83\\xAA\"\n\t\"\\xE3\\x83\\x9F\\xE3\\x83\\xAA\\xE3\\x83\\x8F\\xE3\\x82\\x99\\xE3\\x83\\xBC\\xE3\\x83\\xAB\\xE3\\x83\\xA1\\xE3\\x82\\xAB\\xE3\"\n\t\"\\x82\\x99\\xE3\\x83\\xA1\\xE3\\x82\\xAB\\xE3\\x82\\x99\\xE3\\x83\\x88\\xE3\\x83\\xB3\\xE3\\x83\\xA4\\xE3\\x83\\xBC\\xE3\\x83\"\n\t\"\\x88\\xE3\\x82\\x99\\xE3\\x83\\xA4\\xE3\\x83\\xBC\\xE3\\x83\\xAB\\xE3\\x83\\xA6\\xE3\\x82\\xA2\\xE3\\x83\\xB3\\xE3\\x83\\xAA\"\n\t\"\\xE3\\x83\\x83\\xE3\\x83\\x88\\xE3\\x83\\xAB\\xE3\\x83\\xAA\\xE3\\x83\\xA9\\xE3\\x83\\xAB\\xE3\\x83\\x92\\xE3\\x82\\x9A\\xE3\"\n\t\"\\x83\\xBC\\xE3\\x83\\xAB\\xE3\\x83\\xBC\\xE3\\x83\\x95\\xE3\\x82\\x99\\xE3\\x83\\xAB\\xE3\\x83\\xAC\\xE3\\x83\\xA0\\xE3\\x83\"\n\t\"\\xAC\\xE3\\x83\\xB3\\xE3\\x83\\x88\\xE3\\x82\\xB1\\xE3\\x82\\x99\\xE3\\x83\\xB3\\x30\\xE7\\x82\\xB9\\x31\\xE7\\x82\\xB9\\x32\"\n\t\"\\xE7\\x82\\xB9\\x33\\xE7\\x82\\xB9\\x34\\xE7\\x82\\xB9\\x35\\xE7\\x82\\xB9\\x36\\xE7\\x82\\xB9\\x37\\xE7\\x82\\xB9\\x38\\xE7\"\n\t\"\\x82\\xB9\\x39\\xE7\\x82\\xB9\\x31\\x30\\xE7\\x82\\xB9\\x31\\x31\\xE7\\x82\\xB9\\x31\\x32\\xE7\\x82\\xB9\\x31\\x33\\xE7\\x82\"\n\t\"\\xB9\\x31\\x34\\xE7\\x82\\xB9\\x31\\x35\\xE7\\x82\\xB9\\x31\\x36\\xE7\\x82\\xB9\\x31\\x37\\xE7\\x82\\xB9\\x31\\x38\\xE7\\x82\"\n\t\"\\xB9\\x31\\x39\\xE7\\x82\\xB9\\x32\\x30\\xE7\\x82\\xB9\\x32\\x31\\xE7\\x82\\xB9\\x32\\x32\\xE7\\x82\\xB9\\x32\\x33\\xE7\\x82\"\n\t\"\\xB9\\x32\\x34\\xE7\\x82\\xB9\\x68\\x50\\x61\\x64\\x61\\x41\\x55\\x62\\x61\\x72\\x6F\\x56\\x70\\x63\\x64\\x6D\\x64\\x6D\\x32\"\n\t\"\\x64\\x6D\\x33\\x49\\x55\\xE5\\xB9\\xB3\\xE6\\x88\\x90\\xE6\\x98\\xAD\\xE5\\x92\\x8C\\xE5\\xA4\\xA7\\xE6\\xAD\\xA3\\xE6\\x98\"\n\t\"\\x8E\\xE6\\xB2\\xBB\\xE6\\xA0\\xAA\\xE5\\xBC\\x8F\\xE4\\xBC\\x9A\\xE7\\xA4\\xBE\\x70\\x41\\x6E\\x41\\xCE\\xBC\\x41\\x6D\\x41\"\n\t\"\\x6B\\x41\\x4B\\x42\\x4D\\x42\\x47\\x42\\x63\\x61\\x6C\\x6B\\x63\\x61\\x6C\\x70\\x46\\x6E\\x46\\xCE\\xBC\\x46\\xCE\\xBC\\x67\"\n\t\"\\x6D\\x67\\x6B\\x67\\x48\\x7A\\x6B\\x48\\x7A\\x4D\\x48\\x7A\\x47\\x48\\x7A\\x54\\x48\\x7A\\xCE\\xBC\\x6C\\x6D\\x6C\\x64\\x6C\"\n\t\"\\x6B\\x6C\\x66\\x6D\\x6E\\x6D\\xCE\\xBC\\x6D\\x6D\\x6D\\x63\\x6D\\x6B\\x6D\\x6D\\x6D\\x32\\x63\\x6D\\x32\\x6B\\x6D\\x32\\x6D\"\n\t\"\\x6D\\x33\\x63\\x6D\\x33\\x6B\\x6D\\x33\\x6D\\xE2\\x88\\x95\\x73\\x6D\\xE2\\x88\\x95\\x73\\x32\\x6B\\x50\\x61\\x4D\\x50\\x61\"\n\t\"\\x47\\x50\\x61\\x72\\x61\\x64\\x72\\x61\\x64\\xE2\\x88\\x95\\x73\\x72\\x61\\x64\\xE2\\x88\\x95\\x73\\x32\\x70\\x73\\x6E\\x73\"\n\t\"\\xCE\\xBC\\x73\\x6D\\x73\\x70\\x56\\x6E\\x56\\xCE\\xBC\\x56\\x6D\\x56\\x6B\\x56\\x4D\\x56\\x70\\x57\\x6E\\x57\\xCE\\xBC\\x57\"\n\t\"\\x6D\\x57\\x6B\\x57\\x4D\\x57\\x6B\\xCE\\xA9\\x4D\\xCE\\xA9\\x61\\x2E\\x6D\\x2E\\x42\\x71\\x63\\x63\\x43\\xE2\\x88\\x95\\x6B\"\n\t\"\\x67\\x43\\x6F\\x2E\\x64\\x42\\x47\\x79\\x68\\x61\\x48\\x50\\x69\\x6E\\x4B\\x4B\\x4B\\x4D\\x6B\\x74\\x6C\\x6E\\x6C\\x6F\\x67\"\n\t\"\\x6C\\x78\\x6D\\x62\\x6D\\x69\\x6C\\x6D\\x6F\\x6C\\x50\\x48\\x70\\x2E\\x6D\\x2E\\x50\\x50\\x4D\\x50\\x52\\x53\\x76\\x57\\x62\"\n\t\"\\x56\\xE2\\x88\\x95\\x6D\\x41\\xE2\\x88\\x95\\x6D\\x31\\xE6\\x97\\xA5\\x32\\xE6\\x97\\xA5\\x33\\xE6\\x97\\xA5\\x34\\xE6\\x97\"\n\t\"\\xA5\\x35\\xE6\\x97\\xA5\\x36\\xE6\\x97\\xA5\\x37\\xE6\\x97\\xA5\\x38\\xE6\\x97\\xA5\\x39\\xE6\\x97\\xA5\\x31\\x30\\xE6\\x97\"\n\t\"\\xA5\\x31\\x31\\xE6\\x97\\xA5\\x31\\x32\\xE6\\x97\\xA5\\x31\\x33\\xE6\\x97\\xA5\\x31\\x34\\xE6\\x97\\xA5\\x31\\x35\\xE6\\x97\"\n\t\"\\xA5\\x31\\x36\\xE6\\x97\\xA5\\x31\\x37\\xE6\\x97\\xA5\\x31\\x38\\xE6\\x97\\xA5\\x31\\x39\\xE6\\x97\\xA5\\x32\\x30\\xE6\\x97\"\n\t\"\\xA5\\x32\\x31\\xE6\\x97\\xA5\\x32\\x32\\xE6\\x97\\xA5\\x32\\x33\\xE6\\x97\\xA5\\x32\\x34\\xE6\\x97\\xA5\\x32\\x35\\xE6\\x97\"\n\t\"\\xA5\\x32\\x36\\xE6\\x97\\xA5\\x32\\x37\\xE6\\x97\\xA5\\x32\\x38\\xE6\\x97\\xA5\\x32\\x39\\xE6\\x97\\xA5\\x33\\x30\\xE6\\x97\"\n\t\"\\xA5\\x33\\x31\\xE6\\x97\\xA5\\x67\\x61\\x6C\\xD1\\x8A\\xD1\\x8C\\xEA\\x9D\\xAF\\xC4\\xA6\\xC5\\x93\\xEA\\x9C\\xA7\\xEA\\xAC\"\n\t\"\\xB7\\xC9\\xAB\\xEA\\xAD\\x92\\x66\\x66\\x66\\x69\\x66\\x6C\\x66\\x66\\x69\\x66\\x66\\x6C\\x73\\x74\\xD5\\xB4\\xD5\\xB6\\xD5\"\n\t\"\\xB4\\xD5\\xA5\\xD5\\xB4\\xD5\\xAB\\xD5\\xBE\\xD5\\xB6\\xD5\\xB4\\xD5\\xAD\\xD7\\xA2\\xD7\\x9D\\xD7\\x90\\xD7\\x9C\\xD9\\xB1\"\n\t\"\\xD9\\xBB\\xD9\\xBE\\xDA\\x80\\xD9\\xBA\\xD9\\xBF\\xD9\\xB9\\xDA\\xA4\\xDA\\xA6\\xDA\\x84\\xDA\\x83\\xDA\\x86\\xDA\\x87\\xDA\"\n\t\"\\x8D\\xDA\\x8C\\xDA\\x8E\\xDA\\x88\\xDA\\x98\\xDA\\x91\\xDA\\xA9\\xDA\\xAF\\xDA\\xB3\\xDA\\xB1\\xDA\\xBA\\xDA\\xBB\\xDA\\xBE\"\n\t\"\\xDA\\xAD\\xDB\\x86\\xDB\\x88\\xDB\\x8B\\xDB\\x85\\xDB\\x89\\xDB\\x90\\xD9\\x89\\xD9\\x8A\\xD9\\x94\\xD8\\xA7\\xD9\\x8A\\xD9\"\n\t\"\\x94\\xD9\\x88\\xD9\\x8A\\xD9\\x94\\xDB\\x87\\xD9\\x8A\\xD9\\x94\\xDB\\x86\\xD9\\x8A\\xD9\\x94\\xDB\\x88\\xD9\\x8A\\xD9\\x94\"\n\t\"\\xDB\\x90\\xD9\\x8A\\xD9\\x94\\xD9\\x89\\xDB\\x8C\\xD9\\x8A\\xD9\\x94\\xD8\\xAC\\xD9\\x8A\\xD9\\x94\\xD8\\xAD\\xD9\\x8A\\xD9\"\n\t\"\\x94\\xD9\\x85\\xD9\\x8A\\xD9\\x94\\xD9\\x8A\\xD8\\xA8\\xD8\\xAC\\xD8\\xA8\\xD8\\xAD\\xD8\\xA8\\xD8\\xAE\\xD8\\xA8\\xD9\\x85\"\n\t\"\\xD8\\xA8\\xD9\\x89\\xD8\\xA8\\xD9\\x8A\\xD8\\xAA\\xD8\\xAC\\xD8\\xAA\\xD8\\xAD\\xD8\\xAA\\xD8\\xAE\\xD8\\xAA\\xD9\\x85\\xD8\"\n\t\"\\xAA\\xD9\\x89\\xD8\\xAA\\xD9\\x8A\\xD8\\xAB\\xD8\\xAC\\xD8\\xAB\\xD9\\x85\\xD8\\xAB\\xD9\\x89\\xD8\\xAB\\xD9\\x8A\\xD8\\xAC\"\n\t\"\\xD8\\xAD\\xD8\\xAC\\xD9\\x85\\xD8\\xAD\\xD9\\x85\\xD8\\xAE\\xD8\\xAC\\xD8\\xAE\\xD8\\xAD\\xD8\\xAE\\xD9\\x85\\xD8\\xB3\\xD8\"\n\t\"\\xAC\\xD8\\xB3\\xD8\\xAD\\xD8\\xB3\\xD8\\xAE\\xD8\\xB3\\xD9\\x85\\xD8\\xB5\\xD8\\xAD\\xD8\\xB5\\xD9\\x85\\xD8\\xB6\\xD8\\xAC\"\n\t\"\\xD8\\xB6\\xD8\\xAD\\xD8\\xB6\\xD8\\xAE\\xD8\\xB6\\xD9\\x85\\xD8\\xB7\\xD8\\xAD\\xD8\\xB7\\xD9\\x85\\xD8\\xB8\\xD9\\x85\\xD8\"\n\t\"\\xB9\\xD8\\xAC\\xD8\\xB9\\xD9\\x85\\xD8\\xBA\\xD8\\xAC\\xD8\\xBA\\xD9\\x85\\xD9\\x81\\xD8\\xAC\\xD9\\x81\\xD8\\xAD\\xD9\\x81\"\n\t\"\\xD8\\xAE\\xD9\\x81\\xD9\\x85\\xD9\\x81\\xD9\\x89\\xD9\\x81\\xD9\\x8A\\xD9\\x82\\xD8\\xAD\\xD9\\x82\\xD9\\x85\\xD9\\x82\\xD9\"\n\t\"\\x89\\xD9\\x82\\xD9\\x8A\\xD9\\x83\\xD8\\xA7\\xD9\\x83\\xD8\\xAC\\xD9\\x83\\xD8\\xAD\\xD9\\x83\\xD8\\xAE\\xD9\\x83\\xD9\\x84\"\n\t\"\\xD9\\x83\\xD9\\x85\\xD9\\x83\\xD9\\x89\\xD9\\x83\\xD9\\x8A\\xD9\\x84\\xD8\\xAC\\xD9\\x84\\xD8\\xAD\\xD9\\x84\\xD8\\xAE\\xD9\"\n\t\"\\x84\\xD9\\x85\\xD9\\x84\\xD9\\x89\\xD9\\x84\\xD9\\x8A\\xD9\\x85\\xD8\\xAC\\xD9\\x85\\xD9\\x85\\xD9\\x85\\xD9\\x89\\xD9\\x86\"\n\t\"\\xD8\\xAC\\xD9\\x86\\xD8\\xAD\\xD9\\x86\\xD8\\xAE\\xD9\\x86\\xD9\\x85\\xD9\\x86\\xD9\\x89\\xD9\\x86\\xD9\\x8A\\xD9\\x87\\xD8\"\n\t\"\\xAC\\xD9\\x87\\xD9\\x85\\xD9\\x87\\xD9\\x89\\xD9\\x87\\xD9\\x8A\\xD9\\x8A\\xD8\\xAD\\xD9\\x8A\\xD8\\xAE\\xD9\\x8A\\xD9\\x89\"\n\t\"\\xD8\\xB0\\xD9\\xB0\\xD8\\xB1\\xD9\\xB0\\xD9\\x89\\xD9\\xB0\\x20\\xD9\\x8C\\xD9\\x91\\x20\\xD9\\x8D\\xD9\\x91\\x20\\xD9\\x8E\"\n\t\"\\xD9\\x91\\x20\\xD9\\x8F\\xD9\\x91\\x20\\xD9\\x90\\xD9\\x91\\x20\\xD9\\x91\\xD9\\xB0\\xD9\\x8A\\xD9\\x94\\xD8\\xB1\\xD9\\x8A\"\n\t\"\\xD9\\x94\\xD8\\xB2\\xD9\\x8A\\xD9\\x94\\xD9\\x86\\xD8\\xA8\\xD8\\xB1\\xD8\\xA8\\xD8\\xB2\\xD8\\xA8\\xD9\\x86\\xD8\\xAA\\xD8\"\n\t\"\\xB1\\xD8\\xAA\\xD8\\xB2\\xD8\\xAA\\xD9\\x86\\xD8\\xAB\\xD8\\xB1\\xD8\\xAB\\xD8\\xB2\\xD8\\xAB\\xD9\\x86\\xD9\\x85\\xD8\\xA7\"\n\t\"\\xD9\\x86\\xD8\\xB1\\xD9\\x86\\xD8\\xB2\\xD9\\x86\\xD9\\x86\\xD9\\x8A\\xD8\\xB1\\xD9\\x8A\\xD8\\xB2\\xD9\\x8A\\xD9\\x86\\xD9\"\n\t\"\\x8A\\xD9\\x94\\xD8\\xAE\\xD9\\x8A\\xD9\\x94\\xD9\\x87\\xD8\\xA8\\xD9\\x87\\xD8\\xAA\\xD9\\x87\\xD8\\xB5\\xD8\\xAE\\xD9\\x84\"\n\t\"\\xD9\\x87\\xD9\\x86\\xD9\\x87\\xD9\\x87\\xD9\\xB0\\xD9\\x8A\\xD8\\xAD\\xD8\\xAB\\xD9\\x87\\xD8\\xB3\\xD9\\x87\\xD8\\xB4\\xD9\"\n\t\"\\x85\\xD8\\xB4\\xD9\\x87\\xD9\\x80\\xD9\\x8E\\xD9\\x91\\xD9\\x80\\xD9\\x8F\\xD9\\x91\\xD9\\x80\\xD9\\x90\\xD9\\x91\\xD8\\xB7\"\n\t\"\\xD9\\x89\\xD8\\xB7\\xD9\\x8A\\xD8\\xB9\\xD9\\x89\\xD8\\xB9\\xD9\\x8A\\xD8\\xBA\\xD9\\x89\\xD8\\xBA\\xD9\\x8A\\xD8\\xB3\\xD9\"\n\t\"\\x89\\xD8\\xB3\\xD9\\x8A\\xD8\\xB4\\xD9\\x89\\xD8\\xB4\\xD9\\x8A\\xD8\\xAD\\xD9\\x89\\xD8\\xAC\\xD9\\x89\\xD8\\xAE\\xD9\\x89\"\n\t\"\\xD8\\xB5\\xD9\\x89\\xD8\\xB5\\xD9\\x8A\\xD8\\xB6\\xD9\\x89\\xD8\\xB6\\xD9\\x8A\\xD8\\xB4\\xD8\\xAC\\xD8\\xB4\\xD8\\xAD\\xD8\"\n\t\"\\xB4\\xD8\\xAE\\xD8\\xB4\\xD8\\xB1\\xD8\\xB3\\xD8\\xB1\\xD8\\xB5\\xD8\\xB1\\xD8\\xB6\\xD8\\xB1\\xD8\\xA7\\xD9\\x8B\\xD8\\xAA\"\n\t\"\\xD8\\xAC\\xD9\\x85\\xD8\\xAA\\xD8\\xAD\\xD8\\xAC\\xD8\\xAA\\xD8\\xAD\\xD9\\x85\\xD8\\xAA\\xD8\\xAE\\xD9\\x85\\xD8\\xAA\\xD9\"\n\t\"\\x85\\xD8\\xAC\\xD8\\xAA\\xD9\\x85\\xD8\\xAD\\xD8\\xAA\\xD9\\x85\\xD8\\xAE\\xD8\\xAD\\xD9\\x85\\xD9\\x8A\\xD8\\xAD\\xD9\\x85\"\n\t\"\\xD9\\x89\\xD8\\xB3\\xD8\\xAD\\xD8\\xAC\\xD8\\xB3\\xD8\\xAC\\xD8\\xAD\\xD8\\xB3\\xD8\\xAC\\xD9\\x89\\xD8\\xB3\\xD9\\x85\\xD8\"\n\t\"\\xAD\\xD8\\xB3\\xD9\\x85\\xD8\\xAC\\xD8\\xB3\\xD9\\x85\\xD9\\x85\\xD8\\xB5\\xD8\\xAD\\xD8\\xAD\\xD8\\xB5\\xD9\\x85\\xD9\\x85\"\n\t\"\\xD8\\xB4\\xD8\\xAD\\xD9\\x85\\xD8\\xB4\\xD8\\xAC\\xD9\\x8A\\xD8\\xB4\\xD9\\x85\\xD8\\xAE\\xD8\\xB4\\xD9\\x85\\xD9\\x85\\xD8\"\n\t\"\\xB6\\xD8\\xAD\\xD9\\x89\\xD8\\xB6\\xD8\\xAE\\xD9\\x85\\xD8\\xB7\\xD9\\x85\\xD8\\xAD\\xD8\\xB7\\xD9\\x85\\xD9\\x85\\xD8\\xB7\"\n\t\"\\xD9\\x85\\xD9\\x8A\\xD8\\xB9\\xD8\\xAC\\xD9\\x85\\xD8\\xB9\\xD9\\x85\\xD9\\x85\\xD8\\xB9\\xD9\\x85\\xD9\\x89\\xD8\\xBA\\xD9\"\n\t\"\\x85\\xD9\\x85\\xD8\\xBA\\xD9\\x85\\xD9\\x8A\\xD8\\xBA\\xD9\\x85\\xD9\\x89\\xD9\\x81\\xD8\\xAE\\xD9\\x85\\xD9\\x82\\xD9\\x85\"\n\t\"\\xD8\\xAD\\xD9\\x82\\xD9\\x85\\xD9\\x85\\xD9\\x84\\xD8\\xAD\\xD9\\x85\\xD9\\x84\\xD8\\xAD\\xD9\\x8A\\xD9\\x84\\xD8\\xAD\\xD9\"\n\t\"\\x89\\xD9\\x84\\xD8\\xAC\\xD8\\xAC\\xD9\\x84\\xD8\\xAE\\xD9\\x85\\xD9\\x84\\xD9\\x85\\xD8\\xAD\\xD9\\x85\\xD8\\xAD\\xD8\\xAC\"\n\t\"\\xD9\\x85\\xD8\\xAD\\xD9\\x8A\\xD9\\x85\\xD8\\xAC\\xD8\\xAD\\xD9\\x85\\xD8\\xAE\\xD9\\x85\\xD9\\x85\\xD8\\xAC\\xD8\\xAE\\xD9\"\n\t\"\\x87\\xD9\\x85\\xD8\\xAC\\xD9\\x87\\xD9\\x85\\xD9\\x85\\xD9\\x86\\xD8\\xAD\\xD9\\x85\\xD9\\x86\\xD8\\xAD\\xD9\\x89\\xD9\\x86\"\n\t\"\\xD8\\xAC\\xD9\\x85\\xD9\\x86\\xD8\\xAC\\xD9\\x89\\xD9\\x86\\xD9\\x85\\xD9\\x8A\\xD9\\x86\\xD9\\x85\\xD9\\x89\\xD9\\x8A\\xD9\"\n\t\"\\x85\\xD9\\x85\\xD8\\xA8\\xD8\\xAE\\xD9\\x8A\\xD8\\xAA\\xD8\\xAC\\xD9\\x8A\\xD8\\xAA\\xD8\\xAC\\xD9\\x89\\xD8\\xAA\\xD8\\xAE\"\n\t\"\\xD9\\x8A\\xD8\\xAA\\xD8\\xAE\\xD9\\x89\\xD8\\xAA\\xD9\\x85\\xD9\\x8A\\xD8\\xAA\\xD9\\x85\\xD9\\x89\\xD8\\xAC\\xD9\\x85\\xD9\"\n\t\"\\x8A\\xD8\\xAC\\xD8\\xAD\\xD9\\x89\\xD8\\xAC\\xD9\\x85\\xD9\\x89\\xD8\\xB3\\xD8\\xAE\\xD9\\x89\\xD8\\xB5\\xD8\\xAD\\xD9\\x8A\"\n\t\"\\xD8\\xB4\\xD8\\xAD\\xD9\\x8A\\xD8\\xB6\\xD8\\xAD\\xD9\\x8A\\xD9\\x84\\xD8\\xAC\\xD9\\x8A\\xD9\\x84\\xD9\\x85\\xD9\\x8A\\xD9\"\n\t\"\\x8A\\xD8\\xAD\\xD9\\x8A\\xD9\\x8A\\xD8\\xAC\\xD9\\x8A\\xD9\\x8A\\xD9\\x85\\xD9\\x8A\\xD9\\x85\\xD9\\x85\\xD9\\x8A\\xD9\\x82\"\n\t\"\\xD9\\x85\\xD9\\x8A\\xD9\\x86\\xD8\\xAD\\xD9\\x8A\\xD8\\xB9\\xD9\\x85\\xD9\\x8A\\xD9\\x83\\xD9\\x85\\xD9\\x8A\\xD9\\x86\\xD8\"\n\t\"\\xAC\\xD8\\xAD\\xD9\\x85\\xD8\\xAE\\xD9\\x8A\\xD9\\x84\\xD8\\xAC\\xD9\\x85\\xD9\\x83\\xD9\\x85\\xD9\\x85\\xD8\\xAC\\xD8\\xAD\"\n\t\"\\xD9\\x8A\\xD8\\xAD\\xD8\\xAC\\xD9\\x8A\\xD9\\x85\\xD8\\xAC\\xD9\\x8A\\xD9\\x81\\xD9\\x85\\xD9\\x8A\\xD8\\xA8\\xD8\\xAD\\xD9\"\n\t\"\\x8A\\xD8\\xB3\\xD8\\xAE\\xD9\\x8A\\xD9\\x86\\xD8\\xAC\\xD9\\x8A\\xD8\\xB5\\xD9\\x84\\xDB\\x92\\xD9\\x82\\xD9\\x84\\xDB\\x92\"\n\t\"\\xD8\\xA7\\xD9\\x84\\xD9\\x84\\xD9\\x87\\xD8\\xA7\\xD9\\x83\\xD8\\xA8\\xD8\\xB1\\xD9\\x85\\xD8\\xAD\\xD9\\x85\\xD8\\xAF\\xD8\"\n\t\"\\xB5\\xD9\\x84\\xD8\\xB9\\xD9\\x85\\xD8\\xB1\\xD8\\xB3\\xD9\\x88\\xD9\\x84\\xD8\\xB9\\xD9\\x84\\xD9\\x8A\\xD9\\x87\\xD9\\x88\"\n\t\"\\xD8\\xB3\\xD9\\x84\\xD9\\x85\\xD8\\xB5\\xD9\\x84\\xD9\\x89\\xD8\\xB5\\xD9\\x84\\xD9\\x89\\x20\\xD8\\xA7\\xD9\\x84\\xD9\\x84\"\n\t\"\\xD9\\x87\\x20\\xD8\\xB9\\xD9\\x84\\xD9\\x8A\\xD9\\x87\\x20\\xD9\\x88\\xD8\\xB3\\xD9\\x84\\xD9\\x85\\xD8\\xAC\\xD9\\x84\\x20\"\n\t\"\\xD8\\xAC\\xD9\\x84\\xD8\\xA7\\xD9\\x84\\xD9\\x87\\xD8\\xB1\\xDB\\x8C\\xD8\\xA7\\xD9\\x84\\x2C\\xE3\\x80\\x81\\xE3\\x80\\x82\"\n\t\"\\xE3\\x80\\x96\\xE3\\x80\\x97\\xE2\\x80\\x94\\xE2\\x80\\x93\\x5F\\x7B\\x7D\\xE3\\x80\\x94\\xE3\\x80\\x95\\xE3\\x80\\x90\\xE3\"\n\t\"\\x80\\x91\\xE3\\x80\\x8A\\xE3\\x80\\x8B\\xE3\\x80\\x8C\\xE3\\x80\\x8D\\xE3\\x80\\x8E\\xE3\\x80\\x8F\\x5B\\x5D\\x23\\x26\\x2A\"\n\t\"\\x2D\\x5C\\x24\\x25\\x40\\x20\\xD9\\x8B\\xD9\\x80\\xD9\\x8B\\xD9\\x80\\xD9\\x91\\x20\\xD9\\x92\\xD9\\x80\\xD9\\x92\\xD8\\xA1\"\n\t\"\\xD8\\xA9\\xD9\\x84\\xD8\\xA7\\xD9\\x93\\xD9\\x84\\xD8\\xA7\\xD9\\x94\\xD9\\x84\\xD8\\xA7\\xD9\\x95\\x22\\x27\\x5E\\x7C\\x7E\"\n\t\"\\xE2\\xA6\\x85\\xE2\\xA6\\x86\\xE3\\x83\\xBB\\xE3\\x82\\xA5\\xE3\\x83\\xA3\\xC2\\xA2\\xC2\\xA3\\xC2\\xAC\\xC2\\xA6\\xC2\\xA5\"\n\t\"\\xE2\\x82\\xA9\\xE2\\x94\\x82\\xE2\\x86\\x91\\xE2\\x86\\x93\\xE2\\x96\\xA0\\xE2\\x97\\x8B\\xF0\\x9D\\x85\\x98\\xF0\\x9D\\x85\"\n\t\"\\xA5\\xF0\\x9D\\x85\\xAE\\xC4\\xB1\\xC8\\xB7\\xCE\\x92\\xCE\\x94\\xCE\\x96\\xCE\\x9A\\xCE\\x9B\\xCE\\x9C\\xCE\\x9D\\xCE\\x9E\"\n\t\"\\xCE\\xA4\\xCE\\xA6\\xCE\\xA7\\xCE\\xA8\\xE2\\x88\\x87\\xCE\\xB6\\xCE\\xBB\\xCE\\xBD\\xCE\\xBE\\xCF\\x83\\xCF\\x84\\xCF\\x88\"\n\t\"\\xE2\\x88\\x82\\xCF\\x9C\\xCF\\x9D\\xD9\\xAE\\xDA\\xA1\\xD9\\xAF\\x30\\x2C\\x31\\x2C\\x32\\x2C\\x33\\x2C\\x34\\x2C\\x35\\x2C\"\n\t\"\\x36\\x2C\\x37\\x2C\\x38\\x2C\\x39\\x2C\\x28\\x41\\x29\\x28\\x42\\x29\\x28\\x43\\x29\\x28\\x44\\x29\\x28\\x45\\x29\\x28\\x46\"\n\t\"\\x29\\x28\\x47\\x29\\x28\\x48\\x29\\x28\\x49\\x29\\x28\\x4A\\x29\\x28\\x4B\\x29\\x28\\x4C\\x29\\x28\\x4D\\x29\\x28\\x4E\\x29\"\n\t\"\\x28\\x4F\\x29\\x28\\x50\\x29\\x28\\x51\\x29\\x28\\x52\\x29\\x28\\x53\\x29\\x28\\x54\\x29\\x28\\x55\\x29\\x28\\x56\\x29\\x28\"\n\t\"\\x57\\x29\\x28\\x58\\x29\\x28\\x59\\x29\\x28\\x5A\\x29\\xE3\\x80\\x94\\x53\\xE3\\x80\\x95\\x43\\x44\\x57\\x5A\\x48\\x56\\x53\"\n\t\"\\x44\\x53\\x53\\x50\\x50\\x56\\x57\\x43\\x4D\\x43\\x4D\\x44\\x44\\x4A\\xE3\\x81\\xBB\\xE3\\x81\\x8B\\xE3\\x82\\xB3\\xE3\\x82\"\n\t\"\\xB3\\xE5\\xAD\\x97\\xE5\\x8F\\x8C\\xE8\\xA7\\xA3\\xE4\\xBA\\xA4\\xE6\\x98\\xA0\\xE7\\x84\\xA1\\xE5\\x89\\x8D\\xE5\\xBE\\x8C\"\n\t\"\\xE6\\x96\\xB0\\xE5\\x88\\x9D\\xE7\\xB5\\x82\\xE8\\xB2\\xA9\\xE5\\xA3\\xB0\\xE5\\x90\\xB9\\xE6\\xBC\\x94\\xE6\\x8A\\x95\\xE6\"\n\t\"\\x8D\\x95\\xE9\\x81\\x8A\\xE6\\x8C\\x87\\xE6\\x89\\x93\\xE7\\xA6\\x81\\xE7\\xA9\\xBA\\xE5\\x90\\x88\\xE6\\xBA\\x80\\xE7\\x94\"\n\t\"\\xB3\\xE5\\x96\\xB6\\xE3\\x80\\x94\\xE6\\x9C\\xAC\\xE3\\x80\\x95\\xE3\\x80\\x94\\xE4\\xB8\\x89\\xE3\\x80\\x95\\xE3\\x80\\x94\"\n\t\"\\xE4\\xBA\\x8C\\xE3\\x80\\x95\\xE3\\x80\\x94\\xE5\\xAE\\x89\\xE3\\x80\\x95\\xE3\\x80\\x94\\xE7\\x82\\xB9\\xE3\\x80\\x95\\xE3\"\n\t\"\\x80\\x94\\xE6\\x89\\x93\\xE3\\x80\\x95\\xE3\\x80\\x94\\xE7\\x9B\\x97\\xE3\\x80\\x95\\xE3\\x80\\x94\\xE5\\x8B\\x9D\\xE3\\x80\"\n\t\"\\x95\\xE3\\x80\\x94\\xE6\\x95\\x97\\xE3\\x80\\x95\\xE5\\xBE\\x97\\xE5\\x8F\\xAF\\xC3\\x80\\xC3\\x81\\xC3\\x82\\xC3\\x83\\xC3\"\n\t\"\\x84\\xC3\\x85\\xC3\\x87\\xC3\\x88\\xC3\\x89\\xC3\\x8A\\xC3\\x8B\\xC3\\x8C\\xC3\\x8D\\xC3\\x8E\\xC3\\x8F\\xC3\\x90\\xC3\\x91\"\n\t\"\\xC3\\x92\\xC3\\x93\\xC3\\x94\\xC3\\x95\\xC3\\x96\\xC3\\x99\\xC3\\x9A\\xC3\\x9B\\xC3\\x9C\\xC3\\x9D\\xC3\\x9E\\xC5\\xB8\\xC4\"\n\t\"\\x80\\xC4\\x82\\xC4\\x84\\xC4\\x86\\xC4\\x88\\xC4\\x8A\\xC4\\x8C\\xC4\\x8E\\xC4\\x90\\xC4\\x92\\xC4\\x94\\xC4\\x96\\xC4\\x98\"\n\t\"\\xC4\\x9A\\xC4\\x9C\\xC4\\x9E\\xC4\\xA0\\xC4\\xA2\\xC4\\xA4\\xC4\\xA8\\xC4\\xAA\\xC4\\xAC\\xC4\\xAE\\xC4\\xB2\\xC4\\xB4\\xC4\"\n\t\"\\xB6\\xC4\\xB9\\xC4\\xBB\\xC4\\xBD\\xC4\\xBF\\xC5\\x81\\xC5\\x83\\xC5\\x85\\xC5\\x87\\xCA\\xBC\\x4E\\xC5\\x8A\\xC5\\x8C\\xC5\"\n\t\"\\x8E\\xC5\\x90\\xC5\\x92\\xC5\\x94\\xC5\\x96\\xC5\\x98\\xC5\\x9A\\xC5\\x9C\\xC5\\x9E\\xC5\\xA0\\xC5\\xA2\\xC5\\xA4\\xC5\\xA6\"\n\t\"\\xC5\\xA8\\xC5\\xAA\\xC5\\xAC\\xC5\\xAE\\xC5\\xB0\\xC5\\xB2\\xC5\\xB4\\xC5\\xB6\\xC5\\xB9\\xC5\\xBB\\xC5\\xBD\\xC9\\x83\\xC6\"\n\t\"\\x82\\xC6\\x84\\xC6\\x87\\xC6\\x8B\\xC6\\x91\\xC7\\xB6\\xC6\\x98\\xC8\\xBD\\xC8\\xA0\\xC6\\xA0\\xC6\\xA2\\xC6\\xA4\\xC6\\xA7\"\n\t\"\\xC6\\xAC\\xC6\\xAF\\xC6\\xB3\\xC6\\xB5\\xC6\\xB8\\xC6\\xBC\\xC7\\xB7\\xC7\\x84\\xC7\\x87\\xC7\\x8A\\xC7\\x8D\\xC7\\x8F\\xC7\"\n\t\"\\x91\\xC7\\x93\\xC7\\x95\\xC7\\x97\\xC7\\x99\\xC7\\x9B\\xC7\\x9E\\xC7\\xA0\\xC7\\xA2\\xC7\\xA4\\xC7\\xA6\\xC7\\xA8\\xC7\\xAA\"\n\t\"\\xC7\\xAC\\xC7\\xAE\\x4A\\xCC\\x8C\\xC7\\xB1\\xC7\\xB4\\xC7\\xB8\\xC7\\xBA\\xC7\\xBC\\xC7\\xBE\\xC8\\x80\\xC8\\x82\\xC8\\x84\"\n\t\"\\xC8\\x86\\xC8\\x88\\xC8\\x8A\\xC8\\x8C\\xC8\\x8E\\xC8\\x90\\xC8\\x92\\xC8\\x94\\xC8\\x96\\xC8\\x98\\xC8\\x9A\\xC8\\x9C\\xC8\"\n\t\"\\x9E\\xC8\\xA4\\xC8\\xA6\\xC8\\xA8\\xC8\\xAA\\xC8\\xAC\\xC8\\xAE\\xC8\\xB0\\xC8\\xB2\\xC8\\xBB\\xE2\\xB1\\xBE\\xE2\\xB1\\xBF\"\n\t\"\\xC9\\x81\\xC9\\x86\\xC9\\x88\\xC9\\x8A\\xC9\\x8C\\xC9\\x8E\\xE2\\xB1\\xAF\\xE2\\xB1\\xAD\\xE2\\xB1\\xB0\\xC6\\x81\\xC6\\x86\"\n\t\"\\xC6\\x89\\xC6\\x8A\\xC6\\x8F\\xEA\\x9E\\xAB\\xC6\\x93\\xEA\\x9E\\xAC\\xC6\\x94\\xEA\\x9E\\x8D\\xEA\\x9E\\xAA\\xC6\\x97\\xC6\"\n\t\"\\x96\\xE2\\xB1\\xA2\\xEA\\x9E\\xAD\\xC6\\x9C\\xE2\\xB1\\xAE\\xC6\\x9D\\xC6\\x9F\\xE2\\xB1\\xA4\\xC6\\xA6\\xC6\\xA9\\xEA\\x9E\"\n\t\"\\xB1\\xC6\\xAE\\xC9\\x84\\xC6\\xB1\\xC6\\xB2\\xC9\\x85\\xEA\\x9E\\xB0\\xCD\\xB0\\xCD\\xB2\\xCD\\xB6\\xCF\\xBD\\xCF\\xBE\\xCF\"\n\t\"\\xBF\\xCE\\x99\\xCC\\x88\\xCC\\x81\\xCE\\x86\\xCE\\x88\\xCE\\x89\\xCE\\x8A\\xCE\\xA5\\xCC\\x88\\xCC\\x81\\xCE\\xAA\\xCE\\xAB\"\n\t\"\\xCE\\x8C\\xCE\\x8E\\xCE\\x8F\\xCF\\x8F\\xCF\\x98\\xCF\\x9A\\xCF\\x9E\\xCF\\xA0\\xCF\\xA2\\xCF\\xA4\\xCF\\xA6\\xCF\\xA8\\xCF\"\n\t\"\\xAA\\xCF\\xAC\\xCF\\xAE\\xCF\\xB9\\xCD\\xBF\\xCF\\xB7\\xCF\\xBA\\xD0\\x91\\xD0\\x92\\xD0\\x94\\xD0\\x99\\xD0\\x9B\\xD0\\x9C\"\n\t\"\\xD0\\x9D\\xD0\\x9F\\xD0\\xA0\\xD0\\xA1\\xD0\\xA2\\xD0\\xA4\\xD0\\xA5\\xD0\\xA6\\xD0\\xA8\\xD0\\xA9\\xD0\\xAA\\xD0\\xAC\\xD0\"\n\t\"\\xAE\\xD0\\xAF\\xD0\\x80\\xD0\\x81\\xD0\\x82\\xD0\\x83\\xD0\\x84\\xD0\\x85\\xD0\\x87\\xD0\\x88\\xD0\\x89\\xD0\\x8A\\xD0\\x8B\"\n\t\"\\xD0\\x8C\\xD0\\x8D\\xD0\\x8E\\xD0\\x8F\\xD1\\xA0\\xD1\\xA2\\xD1\\xA4\\xD1\\xA6\\xD1\\xA8\\xD1\\xAA\\xD1\\xAC\\xD1\\xAE\\xD1\"\n\t\"\\xB0\\xD1\\xB2\\xD1\\xB6\\xD1\\xB8\\xD1\\xBA\\xD1\\xBC\\xD1\\xBE\\xD2\\x80\\xD2\\x8A\\xD2\\x8C\\xD2\\x8E\\xD2\\x90\\xD2\\x92\"\n\t\"\\xD2\\x94\\xD2\\x96\\xD2\\x98\\xD2\\x9A\\xD2\\x9C\\xD2\\x9E\\xD2\\xA0\\xD2\\xA2\\xD2\\xA4\\xD2\\xA6\\xD2\\xA8\\xD2\\xAA\\xD2\"\n\t\"\\xAC\\xD2\\xAE\\xD2\\xB0\\xD2\\xB2\\xD2\\xB4\\xD2\\xB6\\xD2\\xB8\\xD2\\xBA\\xD2\\xBC\\xD2\\xBE\\xD3\\x81\\xD3\\x83\\xD3\\x85\"\n\t\"\\xD3\\x87\\xD3\\x89\\xD3\\x8B\\xD3\\x8D\\xD3\\x80\\xD3\\x90\\xD3\\x92\\xD3\\x94\\xD3\\x96\\xD3\\x9A\\xD3\\x9C\\xD3\\x9E\\xD3\"\n\t\"\\xA0\\xD3\\xA2\\xD3\\xA4\\xD3\\xA6\\xD3\\xAA\\xD3\\xAC\\xD3\\xAE\\xD3\\xB0\\xD3\\xB2\\xD3\\xB4\\xD3\\xB6\\xD3\\xB8\\xD3\\xBA\"\n\t\"\\xD3\\xBC\\xD3\\xBE\\xD4\\x80\\xD4\\x82\\xD4\\x84\\xD4\\x86\\xD4\\x88\\xD4\\x8A\\xD4\\x8C\\xD4\\x8E\\xD4\\x90\\xD4\\x92\\xD4\"\n\t\"\\x94\\xD4\\x96\\xD4\\x98\\xD4\\x9A\\xD4\\x9C\\xD4\\x9E\\xD4\\xA0\\xD4\\xA2\\xD4\\xA4\\xD4\\xA6\\xD4\\xA8\\xD4\\xAA\\xD4\\xAC\"\n\t\"\\xD4\\xAE\\xD4\\xB1\\xD4\\xB2\\xD4\\xB3\\xD4\\xB4\\xD4\\xB5\\xD4\\xB6\\xD4\\xB7\\xD4\\xB8\\xD4\\xB9\\xD4\\xBA\\xD4\\xBB\\xD4\"\n\t\"\\xBC\\xD4\\xBD\\xD4\\xBE\\xD4\\xBF\\xD5\\x80\\xD5\\x81\\xD5\\x82\\xD5\\x83\\xD5\\x84\\xD5\\x85\\xD5\\x86\\xD5\\x87\\xD5\\x88\"\n\t\"\\xD5\\x89\\xD5\\x8A\\xD5\\x8B\\xD5\\x8C\\xD5\\x8D\\xD5\\x8E\\xD5\\x8F\\xD5\\x90\\xD5\\x91\\xD5\\x92\\xD5\\x93\\xD5\\x94\\xD5\"\n\t\"\\x95\\xD5\\x96\\xD4\\xB5\\xD5\\x92\\xEA\\x9D\\xBD\\xE2\\xB1\\xA3\\xE1\\xB8\\x80\\xE1\\xB8\\x82\\xE1\\xB8\\x84\\xE1\\xB8\\x86\"\n\t\"\\xE1\\xB8\\x88\\xE1\\xB8\\x8A\\xE1\\xB8\\x8C\\xE1\\xB8\\x8E\\xE1\\xB8\\x90\\xE1\\xB8\\x92\\xE1\\xB8\\x94\\xE1\\xB8\\x96\\xE1\"\n\t\"\\xB8\\x98\\xE1\\xB8\\x9A\\xE1\\xB8\\x9C\\xE1\\xB8\\x9E\\xE1\\xB8\\xA0\\xE1\\xB8\\xA2\\xE1\\xB8\\xA4\\xE1\\xB8\\xA6\\xE1\\xB8\"\n\t\"\\xA8\\xE1\\xB8\\xAA\\xE1\\xB8\\xAC\\xE1\\xB8\\xAE\\xE1\\xB8\\xB0\\xE1\\xB8\\xB2\\xE1\\xB8\\xB4\\xE1\\xB8\\xB6\\xE1\\xB8\\xB8\"\n\t\"\\xE1\\xB8\\xBA\\xE1\\xB8\\xBC\\xE1\\xB8\\xBE\\xE1\\xB9\\x80\\xE1\\xB9\\x82\\xE1\\xB9\\x84\\xE1\\xB9\\x86\\xE1\\xB9\\x88\\xE1\"\n\t\"\\xB9\\x8A\\xE1\\xB9\\x8C\\xE1\\xB9\\x8E\\xE1\\xB9\\x90\\xE1\\xB9\\x92\\xE1\\xB9\\x94\\xE1\\xB9\\x96\\xE1\\xB9\\x98\\xE1\\xB9\"\n\t\"\\x9A\\xE1\\xB9\\x9C\\xE1\\xB9\\x9E\\xE1\\xB9\\xA0\\xE1\\xB9\\xA2\\xE1\\xB9\\xA4\\xE1\\xB9\\xA6\\xE1\\xB9\\xA8\\xE1\\xB9\\xAA\"\n\t\"\\xE1\\xB9\\xAC\\xE1\\xB9\\xAE\\xE1\\xB9\\xB0\\xE1\\xB9\\xB2\\xE1\\xB9\\xB4\\xE1\\xB9\\xB6\\xE1\\xB9\\xB8\\xE1\\xB9\\xBA\\xE1\"\n\t\"\\xB9\\xBC\\xE1\\xB9\\xBE\\xE1\\xBA\\x80\\xE1\\xBA\\x82\\xE1\\xBA\\x84\\xE1\\xBA\\x86\\xE1\\xBA\\x88\\xE1\\xBA\\x8A\\xE1\\xBA\"\n\t\"\\x8C\\xE1\\xBA\\x8E\\xE1\\xBA\\x90\\xE1\\xBA\\x92\\xE1\\xBA\\x94\\x48\\xCC\\xB1\\x54\\xCC\\x88\\x57\\xCC\\x8A\\x59\\xCC\\x8A\"\n\t\"\\x41\\xCA\\xBE\\xE1\\xBA\\xA0\\xE1\\xBA\\xA2\\xE1\\xBA\\xA4\\xE1\\xBA\\xA6\\xE1\\xBA\\xA8\\xE1\\xBA\\xAA\\xE1\\xBA\\xAC\\xE1\"\n\t\"\\xBA\\xAE\\xE1\\xBA\\xB0\\xE1\\xBA\\xB2\\xE1\\xBA\\xB4\\xE1\\xBA\\xB6\\xE1\\xBA\\xB8\\xE1\\xBA\\xBA\\xE1\\xBA\\xBC\\xE1\\xBA\"\n\t\"\\xBE\\xE1\\xBB\\x80\\xE1\\xBB\\x82\\xE1\\xBB\\x84\\xE1\\xBB\\x86\\xE1\\xBB\\x88\\xE1\\xBB\\x8A\\xE1\\xBB\\x8C\\xE1\\xBB\\x8E\"\n\t\"\\xE1\\xBB\\x90\\xE1\\xBB\\x92\\xE1\\xBB\\x94\\xE1\\xBB\\x96\\xE1\\xBB\\x98\\xE1\\xBB\\x9A\\xE1\\xBB\\x9C\\xE1\\xBB\\x9E\\xE1\"\n\t\"\\xBB\\xA0\\xE1\\xBB\\xA2\\xE1\\xBB\\xA4\\xE1\\xBB\\xA6\\xE1\\xBB\\xA8\\xE1\\xBB\\xAA\\xE1\\xBB\\xAC\\xE1\\xBB\\xAE\\xE1\\xBB\"\n\t\"\\xB0\\xE1\\xBB\\xB2\\xE1\\xBB\\xB4\\xE1\\xBB\\xB6\\xE1\\xBB\\xB8\\xE1\\xBB\\xBA\\xE1\\xBB\\xBC\\xE1\\xBB\\xBE\\xE1\\xBC\\x88\"\n\t\"\\xE1\\xBC\\x89\\xE1\\xBC\\x8A\\xE1\\xBC\\x8B\\xE1\\xBC\\x8C\\xE1\\xBC\\x8D\\xE1\\xBC\\x8E\\xE1\\xBC\\x8F\\xE1\\xBC\\x98\\xE1\"\n\t\"\\xBC\\x99\\xE1\\xBC\\x9A\\xE1\\xBC\\x9B\\xE1\\xBC\\x9C\\xE1\\xBC\\x9D\\xE1\\xBC\\xA8\\xE1\\xBC\\xA9\\xE1\\xBC\\xAA\\xE1\\xBC\"\n\t\"\\xAB\\xE1\\xBC\\xAC\\xE1\\xBC\\xAD\\xE1\\xBC\\xAE\\xE1\\xBC\\xAF\\xE1\\xBC\\xB8\\xE1\\xBC\\xB9\\xE1\\xBC\\xBA\\xE1\\xBC\\xBB\"\n\t\"\\xE1\\xBC\\xBC\\xE1\\xBC\\xBD\\xE1\\xBC\\xBE\\xE1\\xBC\\xBF\\xE1\\xBD\\x88\\xE1\\xBD\\x89\\xE1\\xBD\\x8A\\xE1\\xBD\\x8B\\xE1\"\n\t\"\\xBD\\x8C\\xE1\\xBD\\x8D\\xCE\\xA5\\xCC\\x93\\xE1\\xBD\\x99\\xCE\\xA5\\xCC\\x93\\xCC\\x80\\xE1\\xBD\\x9B\\xCE\\xA5\\xCC\\x93\"\n\t\"\\xCC\\x81\\xE1\\xBD\\x9D\\xCE\\xA5\\xCC\\x93\\xCD\\x82\\xE1\\xBD\\x9F\\xE1\\xBD\\xA8\\xE1\\xBD\\xA9\\xE1\\xBD\\xAA\\xE1\\xBD\"\n\t\"\\xAB\\xE1\\xBD\\xAC\\xE1\\xBD\\xAD\\xE1\\xBD\\xAE\\xE1\\xBD\\xAF\\xE1\\xBE\\xBA\\xE1\\xBE\\xBB\\xE1\\xBF\\x88\\xE1\\xBF\\x89\"\n\t\"\\xE1\\xBF\\x8A\\xE1\\xBF\\x8B\\xE1\\xBF\\x9A\\xE1\\xBF\\x9B\\xE1\\xBF\\xB8\\xE1\\xBF\\xB9\\xE1\\xBF\\xAA\\xE1\\xBF\\xAB\\xE1\"\n\t\"\\xBF\\xBA\\xE1\\xBF\\xBB\\xE1\\xBC\\x88\\xCE\\x99\\xE1\\xBC\\x89\\xCE\\x99\\xE1\\xBC\\x8A\\xCE\\x99\\xE1\\xBC\\x8B\\xCE\\x99\"\n\t\"\\xE1\\xBC\\x8C\\xCE\\x99\\xE1\\xBC\\x8D\\xCE\\x99\\xE1\\xBC\\x8E\\xCE\\x99\\xE1\\xBC\\x8F\\xCE\\x99\\xE1\\xBC\\xA8\\xCE\\x99\"\n\t\"\\xE1\\xBC\\xA9\\xCE\\x99\\xE1\\xBC\\xAA\\xCE\\x99\\xE1\\xBC\\xAB\\xCE\\x99\\xE1\\xBC\\xAC\\xCE\\x99\\xE1\\xBC\\xAD\\xCE\\x99\"\n\t\"\\xE1\\xBC\\xAE\\xCE\\x99\\xE1\\xBC\\xAF\\xCE\\x99\\xE1\\xBD\\xA8\\xCE\\x99\\xE1\\xBD\\xA9\\xCE\\x99\\xE1\\xBD\\xAA\\xCE\\x99\"\n\t\"\\xE1\\xBD\\xAB\\xCE\\x99\\xE1\\xBD\\xAC\\xCE\\x99\\xE1\\xBD\\xAD\\xCE\\x99\\xE1\\xBD\\xAE\\xCE\\x99\\xE1\\xBD\\xAF\\xCE\\x99\"\n\t\"\\xE1\\xBE\\xB8\\xE1\\xBE\\xB9\\xE1\\xBE\\xBA\\xCE\\x99\\xCE\\x91\\xCE\\x99\\xCE\\x86\\xCE\\x99\\xCE\\x91\\xCD\\x82\\xCE\\x91\"\n\t\"\\xCD\\x82\\xCE\\x99\\xE1\\xBF\\x8A\\xCE\\x99\\xCE\\x97\\xCE\\x99\\xCE\\x89\\xCE\\x99\\xCE\\x97\\xCD\\x82\\xCE\\x97\\xCD\\x82\"\n\t\"\\xCE\\x99\\xE1\\xBF\\x98\\xE1\\xBF\\x99\\xCE\\x99\\xCC\\x88\\xCC\\x80\\xCE\\x99\\xCD\\x82\\xCE\\x99\\xCC\\x88\\xCD\\x82\\xE1\"\n\t\"\\xBF\\xA8\\xE1\\xBF\\xA9\\xCE\\xA5\\xCC\\x88\\xCC\\x80\\xCE\\xA1\\xCC\\x93\\xE1\\xBF\\xAC\\xCE\\xA5\\xCD\\x82\\xCE\\xA5\\xCC\"\n\t\"\\x88\\xCD\\x82\\xE1\\xBF\\xBA\\xCE\\x99\\xCE\\xA9\\xCE\\x99\\xCE\\x8F\\xCE\\x99\\xCE\\xA9\\xCD\\x82\\xCE\\xA9\\xCD\\x82\\xCE\"\n\t\"\\x99\\xE2\\x84\\xB2\\xE2\\x85\\xA0\\xE2\\x85\\xA1\\xE2\\x85\\xA2\\xE2\\x85\\xA3\\xE2\\x85\\xA4\\xE2\\x85\\xA5\\xE2\\x85\\xA6\"\n\t\"\\xE2\\x85\\xA7\\xE2\\x85\\xA8\\xE2\\x85\\xA9\\xE2\\x85\\xAA\\xE2\\x85\\xAB\\xE2\\x85\\xAC\\xE2\\x85\\xAD\\xE2\\x85\\xAE\\xE2\"\n\t\"\\x85\\xAF\\xE2\\x86\\x83\\xE2\\x92\\xB6\\xE2\\x92\\xB7\\xE2\\x92\\xB8\\xE2\\x92\\xB9\\xE2\\x92\\xBA\\xE2\\x92\\xBB\\xE2\\x92\"\n\t\"\\xBC\\xE2\\x92\\xBD\\xE2\\x92\\xBE\\xE2\\x92\\xBF\\xE2\\x93\\x80\\xE2\\x93\\x81\\xE2\\x93\\x82\\xE2\\x93\\x83\\xE2\\x93\\x84\"\n\t\"\\xE2\\x93\\x85\\xE2\\x93\\x86\\xE2\\x93\\x87\\xE2\\x93\\x88\\xE2\\x93\\x89\\xE2\\x93\\x8A\\xE2\\x93\\x8B\\xE2\\x93\\x8C\\xE2\"\n\t\"\\x93\\x8D\\xE2\\x93\\x8E\\xE2\\x93\\x8F\\xE2\\xB0\\x80\\xE2\\xB0\\x81\\xE2\\xB0\\x82\\xE2\\xB0\\x83\\xE2\\xB0\\x84\\xE2\\xB0\"\n\t\"\\x85\\xE2\\xB0\\x86\\xE2\\xB0\\x87\\xE2\\xB0\\x88\\xE2\\xB0\\x89\\xE2\\xB0\\x8A\\xE2\\xB0\\x8B\\xE2\\xB0\\x8C\\xE2\\xB0\\x8D\"\n\t\"\\xE2\\xB0\\x8E\\xE2\\xB0\\x8F\\xE2\\xB0\\x90\\xE2\\xB0\\x91\\xE2\\xB0\\x92\\xE2\\xB0\\x93\\xE2\\xB0\\x94\\xE2\\xB0\\x95\\xE2\"\n\t\"\\xB0\\x96\\xE2\\xB0\\x97\\xE2\\xB0\\x98\\xE2\\xB0\\x99\\xE2\\xB0\\x9A\\xE2\\xB0\\x9B\\xE2\\xB0\\x9C\\xE2\\xB0\\x9D\\xE2\\xB0\"\n\t\"\\x9E\\xE2\\xB0\\x9F\\xE2\\xB0\\xA0\\xE2\\xB0\\xA1\\xE2\\xB0\\xA2\\xE2\\xB0\\xA3\\xE2\\xB0\\xA4\\xE2\\xB0\\xA5\\xE2\\xB0\\xA6\"\n\t\"\\xE2\\xB0\\xA7\\xE2\\xB0\\xA8\\xE2\\xB0\\xA9\\xE2\\xB0\\xAA\\xE2\\xB0\\xAB\\xE2\\xB0\\xAC\\xE2\\xB0\\xAD\\xE2\\xB0\\xAE\\xE2\"\n\t\"\\xB1\\xA0\\xC8\\xBA\\xC8\\xBE\\xE2\\xB1\\xA7\\xE2\\xB1\\xA9\\xE2\\xB1\\xAB\\xE2\\xB1\\xB2\\xE2\\xB1\\xB5\\xE2\\xB2\\x80\\xE2\"\n\t\"\\xB2\\x82\\xE2\\xB2\\x84\\xE2\\xB2\\x86\\xE2\\xB2\\x88\\xE2\\xB2\\x8A\\xE2\\xB2\\x8C\\xE2\\xB2\\x8E\\xE2\\xB2\\x90\\xE2\\xB2\"\n\t\"\\x92\\xE2\\xB2\\x94\\xE2\\xB2\\x96\\xE2\\xB2\\x98\\xE2\\xB2\\x9A\\xE2\\xB2\\x9C\\xE2\\xB2\\x9E\\xE2\\xB2\\xA0\\xE2\\xB2\\xA2\"\n\t\"\\xE2\\xB2\\xA4\\xE2\\xB2\\xA6\\xE2\\xB2\\xA8\\xE2\\xB2\\xAA\\xE2\\xB2\\xAC\\xE2\\xB2\\xAE\\xE2\\xB2\\xB0\\xE2\\xB2\\xB2\\xE2\"\n\t\"\\xB2\\xB4\\xE2\\xB2\\xB6\\xE2\\xB2\\xB8\\xE2\\xB2\\xBA\\xE2\\xB2\\xBC\\xE2\\xB2\\xBE\\xE2\\xB3\\x80\\xE2\\xB3\\x82\\xE2\\xB3\"\n\t\"\\x84\\xE2\\xB3\\x86\\xE2\\xB3\\x88\\xE2\\xB3\\x8A\\xE2\\xB3\\x8C\\xE2\\xB3\\x8E\\xE2\\xB3\\x90\\xE2\\xB3\\x92\\xE2\\xB3\\x94\"\n\t\"\\xE2\\xB3\\x96\\xE2\\xB3\\x98\\xE2\\xB3\\x9A\\xE2\\xB3\\x9C\\xE2\\xB3\\x9E\\xE2\\xB3\\xA0\\xE2\\xB3\\xA2\\xE2\\xB3\\xAB\\xE2\"\n\t\"\\xB3\\xAD\\xE2\\xB3\\xB2\\xE1\\x82\\xA0\\xE1\\x82\\xA1\\xE1\\x82\\xA2\\xE1\\x82\\xA3\\xE1\\x82\\xA4\\xE1\\x82\\xA5\\xE1\\x82\"\n\t\"\\xA6\\xE1\\x82\\xA7\\xE1\\x82\\xA8\\xE1\\x82\\xA9\\xE1\\x82\\xAA\\xE1\\x82\\xAB\\xE1\\x82\\xAC\\xE1\\x82\\xAD\\xE1\\x82\\xAE\"\n\t\"\\xE1\\x82\\xAF\\xE1\\x82\\xB0\\xE1\\x82\\xB1\\xE1\\x82\\xB2\\xE1\\x82\\xB3\\xE1\\x82\\xB4\\xE1\\x82\\xB5\\xE1\\x82\\xB6\\xE1\"\n\t\"\\x82\\xB7\\xE1\\x82\\xB8\\xE1\\x82\\xB9\\xE1\\x82\\xBA\\xE1\\x82\\xBB\\xE1\\x82\\xBC\\xE1\\x82\\xBD\\xE1\\x82\\xBE\\xE1\\x82\"\n\t\"\\xBF\\xE1\\x83\\x80\\xE1\\x83\\x81\\xE1\\x83\\x82\\xE1\\x83\\x83\\xE1\\x83\\x84\\xE1\\x83\\x85\\xE1\\x83\\x87\\xE1\\x83\\x8D\"\n\t\"\\xEA\\x99\\x80\\xEA\\x99\\x82\\xEA\\x99\\x84\\xEA\\x99\\x86\\xEA\\x99\\x88\\xEA\\x99\\x8A\\xEA\\x99\\x8C\\xEA\\x99\\x8E\\xEA\"\n\t\"\\x99\\x90\\xEA\\x99\\x92\\xEA\\x99\\x94\\xEA\\x99\\x96\\xEA\\x99\\x98\\xEA\\x99\\x9A\\xEA\\x99\\x9C\\xEA\\x99\\x9E\\xEA\\x99\"\n\t\"\\xA0\\xEA\\x99\\xA2\\xEA\\x99\\xA4\\xEA\\x99\\xA6\\xEA\\x99\\xA8\\xEA\\x99\\xAA\\xEA\\x99\\xAC\\xEA\\x9A\\x80\\xEA\\x9A\\x82\"\n\t\"\\xEA\\x9A\\x84\\xEA\\x9A\\x86\\xEA\\x9A\\x88\\xEA\\x9A\\x8A\\xEA\\x9A\\x8C\\xEA\\x9A\\x8E\\xEA\\x9A\\x90\\xEA\\x9A\\x92\\xEA\"\n\t\"\\x9A\\x94\\xEA\\x9A\\x96\\xEA\\x9A\\x98\\xEA\\x9A\\x9A\\xEA\\x9C\\xA2\\xEA\\x9C\\xA4\\xEA\\x9C\\xA6\\xEA\\x9C\\xA8\\xEA\\x9C\"\n\t\"\\xAA\\xEA\\x9C\\xAC\\xEA\\x9C\\xAE\\xEA\\x9C\\xB2\\xEA\\x9C\\xB4\\xEA\\x9C\\xB6\\xEA\\x9C\\xB8\\xEA\\x9C\\xBA\\xEA\\x9C\\xBC\"\n\t\"\\xEA\\x9C\\xBE\\xEA\\x9D\\x80\\xEA\\x9D\\x82\\xEA\\x9D\\x84\\xEA\\x9D\\x86\\xEA\\x9D\\x88\\xEA\\x9D\\x8A\\xEA\\x9D\\x8C\\xEA\"\n\t\"\\x9D\\x8E\\xEA\\x9D\\x90\\xEA\\x9D\\x92\\xEA\\x9D\\x94\\xEA\\x9D\\x96\\xEA\\x9D\\x98\\xEA\\x9D\\x9A\\xEA\\x9D\\x9C\\xEA\\x9D\"\n\t\"\\x9E\\xEA\\x9D\\xA0\\xEA\\x9D\\xA2\\xEA\\x9D\\xA4\\xEA\\x9D\\xA6\\xEA\\x9D\\xA8\\xEA\\x9D\\xAA\\xEA\\x9D\\xAC\\xEA\\x9D\\xAE\"\n\t\"\\xEA\\x9D\\xB9\\xEA\\x9D\\xBB\\xEA\\x9D\\xBE\\xEA\\x9E\\x80\\xEA\\x9E\\x82\\xEA\\x9E\\x84\\xEA\\x9E\\x86\\xEA\\x9E\\x8B\\xEA\"\n\t\"\\x9E\\x90\\xEA\\x9E\\x92\\xEA\\x9E\\x96\\xEA\\x9E\\x98\\xEA\\x9E\\x9A\\xEA\\x9E\\x9C\\xEA\\x9E\\x9E\\xEA\\x9E\\xA0\\xEA\\x9E\"\n\t\"\\xA2\\xEA\\x9E\\xA4\\xEA\\x9E\\xA6\\xEA\\x9E\\xA8\\x46\\x46\\x46\\x49\\x46\\x4C\\x46\\x46\\x49\\x46\\x46\\x4C\\x53\\x54\\xD5\"\n\t\"\\x84\\xD5\\x86\\xD5\\x84\\xD4\\xB5\\xD5\\x84\\xD4\\xBB\\xD5\\x8E\\xD5\\x86\\xD5\\x84\\xD4\\xBD\\xEF\\xBC\\xA1\\xEF\\xBC\\xA2\"\n\t\"\\xEF\\xBC\\xA3\\xEF\\xBC\\xA4\\xEF\\xBC\\xA5\\xEF\\xBC\\xA6\\xEF\\xBC\\xA7\\xEF\\xBC\\xA8\\xEF\\xBC\\xA9\\xEF\\xBC\\xAA\\xEF\"\n\t\"\\xBC\\xAB\\xEF\\xBC\\xAC\\xEF\\xBC\\xAD\\xEF\\xBC\\xAE\\xEF\\xBC\\xAF\\xEF\\xBC\\xB0\\xEF\\xBC\\xB1\\xEF\\xBC\\xB2\\xEF\\xBC\"\n\t\"\\xB3\\xEF\\xBC\\xB4\\xEF\\xBC\\xB5\\xEF\\xBC\\xB6\\xEF\\xBC\\xB7\\xEF\\xBC\\xB8\\xEF\\xBC\\xB9\\xEF\\xBC\\xBA\\xF0\\x90\\x90\"\n\t\"\\x80\\xF0\\x90\\x90\\x81\\xF0\\x90\\x90\\x82\\xF0\\x90\\x90\\x83\\xF0\\x90\\x90\\x84\\xF0\\x90\\x90\\x85\\xF0\\x90\\x90\\x86\"\n\t\"\\xF0\\x90\\x90\\x87\\xF0\\x90\\x90\\x88\\xF0\\x90\\x90\\x89\\xF0\\x90\\x90\\x8A\\xF0\\x90\\x90\\x8B\\xF0\\x90\\x90\\x8C\\xF0\"\n\t\"\\x90\\x90\\x8D\\xF0\\x90\\x90\\x8E\\xF0\\x90\\x90\\x8F\\xF0\\x90\\x90\\x90\\xF0\\x90\\x90\\x91\\xF0\\x90\\x90\\x92\\xF0\\x90\"\n\t\"\\x90\\x93\\xF0\\x90\\x90\\x94\\xF0\\x90\\x90\\x95\\xF0\\x90\\x90\\x96\\xF0\\x90\\x90\\x97\\xF0\\x90\\x90\\x98\\xF0\\x90\\x90\"\n\t\"\\x99\\xF0\\x90\\x90\\x9A\\xF0\\x90\\x90\\x9B\\xF0\\x90\\x90\\x9C\\xF0\\x90\\x90\\x9D\\xF0\\x90\\x90\\x9E\\xF0\\x90\\x90\\x9F\"\n\t\"\\xF0\\x90\\x90\\xA0\\xF0\\x90\\x90\\xA1\\xF0\\x90\\x90\\xA2\\xF0\\x90\\x90\\xA3\\xF0\\x90\\x90\\xA4\\xF0\\x90\\x90\\xA5\\xF0\"\n\t\"\\x90\\x90\\xA6\\xF0\\x90\\x90\\xA7\\xF0\\x91\\xA2\\xA0\\xF0\\x91\\xA2\\xA1\\xF0\\x91\\xA2\\xA2\\xF0\\x91\\xA2\\xA3\\xF0\\x91\"\n\t\"\\xA2\\xA4\\xF0\\x91\\xA2\\xA5\\xF0\\x91\\xA2\\xA6\\xF0\\x91\\xA2\\xA7\\xF0\\x91\\xA2\\xA8\\xF0\\x91\\xA2\\xA9\\xF0\\x91\\xA2\"\n\t\"\\xAA\\xF0\\x91\\xA2\\xAB\\xF0\\x91\\xA2\\xAC\\xF0\\x91\\xA2\\xAD\\xF0\\x91\\xA2\\xAE\\xF0\\x91\\xA2\\xAF\\xF0\\x91\\xA2\\xB0\"\n\t\"\\xF0\\x91\\xA2\\xB1\\xF0\\x91\\xA2\\xB2\\xF0\\x91\\xA2\\xB3\\xF0\\x91\\xA2\\xB4\\xF0\\x91\\xA2\\xB5\\xF0\\x91\\xA2\\xB6\\xF0\"\n\t\"\\x91\\xA2\\xB7\\xF0\\x91\\xA2\\xB8\\xF0\\x91\\xA2\\xB9\\xF0\\x91\\xA2\\xBA\\xF0\\x91\\xA2\\xBB\\xF0\\x91\\xA2\\xBC\\xF0\\x91\"\n\t\"\\xA2\\xBD\\xF0\\x91\\xA2\\xBE\\xF0\\x91\\xA2\\xBF\\xC3\\xA0\\xC3\\xA1\\xC3\\xA2\\xC3\\xA3\\xC3\\xA4\\xC3\\xA5\\xC3\\xA7\\xC3\"\n\t\"\\xA8\\xC3\\xA9\\xC3\\xAA\\xC3\\xAB\\xC3\\xAC\\xC3\\xAD\\xC3\\xAE\\xC3\\xAF\\xC3\\xB1\\xC3\\xB2\\xC3\\xB3\\xC3\\xB4\\xC3\\xB5\"\n\t\"\\xC3\\xB6\\xC3\\xB9\\xC3\\xBA\\xC3\\xBB\\xC3\\xBC\\xC3\\xBD\\xC3\\xBE\\xC4\\x81\\xC4\\x83\\xC4\\x85\\xC4\\x87\\xC4\\x89\\xC4\"\n\t\"\\x8B\\xC4\\x8D\\xC4\\x8F\\xC4\\x91\\xC4\\x93\\xC4\\x95\\xC4\\x97\\xC4\\x99\\xC4\\x9B\\xC4\\x9D\\xC4\\x9F\\xC4\\xA1\\xC4\\xA3\"\n\t\"\\xC4\\xA5\\xC4\\xA9\\xC4\\xAB\\xC4\\xAD\\xC4\\xAF\\x69\\xCC\\x87\\xC4\\xB3\\xC4\\xB5\\xC4\\xB7\\xC4\\xBA\\xC4\\xBC\\xC4\\xBE\"\n\t\"\\xC5\\x80\\xC5\\x82\\xC5\\x84\\xC5\\x86\\xC5\\x88\\xC5\\x8D\\xC5\\x8F\\xC5\\x91\\xC5\\x95\\xC5\\x97\\xC5\\x99\\xC5\\x9B\\xC5\"\n\t\"\\x9D\\xC5\\x9F\\xC5\\xA1\\xC5\\xA3\\xC5\\xA5\\xC5\\xA7\\xC5\\xA9\\xC5\\xAB\\xC5\\xAD\\xC5\\xAF\\xC5\\xB1\\xC5\\xB3\\xC5\\xB5\"\n\t\"\\xC5\\xB7\\xC3\\xBF\\xC5\\xBA\\xC5\\xBC\\xC5\\xBE\\xC9\\x93\\xC6\\x83\\xC6\\x85\\xC6\\x88\\xC9\\x96\\xC9\\x97\\xC6\\x8C\\xC7\"\n\t\"\\x9D\\xC6\\x92\\xC9\\xA0\\xC6\\x99\\xC6\\xA1\\xC6\\xA3\\xC6\\xA5\\xCA\\x80\\xC6\\xA8\\xC6\\xAD\\xCA\\x88\\xC6\\xB0\\xC6\\xB4\"\n\t\"\\xC6\\xB6\\xC6\\xB9\\xC6\\xBD\\xC7\\x86\\xC7\\x89\\xC7\\x8C\\xC7\\x8E\\xC7\\x90\\xC7\\x92\\xC7\\x94\\xC7\\x96\\xC7\\x98\\xC7\"\n\t\"\\x9A\\xC7\\x9C\\xC7\\x9F\\xC7\\xA1\\xC7\\xA3\\xC7\\xA5\\xC7\\xA7\\xC7\\xA9\\xC7\\xAB\\xC7\\xAD\\xC7\\xAF\\xC7\\xB3\\xC7\\xB5\"\n\t\"\\xC6\\x95\\xC6\\xBF\\xC7\\xB9\\xC7\\xBB\\xC7\\xBD\\xC7\\xBF\\xC8\\x81\\xC8\\x83\\xC8\\x85\\xC8\\x87\\xC8\\x89\\xC8\\x8B\\xC8\"\n\t\"\\x8D\\xC8\\x8F\\xC8\\x91\\xC8\\x93\\xC8\\x95\\xC8\\x97\\xC8\\x99\\xC8\\x9B\\xC8\\x9D\\xC8\\x9F\\xC6\\x9E\\xC8\\xA3\\xC8\\xA5\"\n\t\"\\xC8\\xA7\\xC8\\xA9\\xC8\\xAB\\xC8\\xAD\\xC8\\xAF\\xC8\\xB1\\xC8\\xB3\\xE2\\xB1\\xA5\\xC8\\xBC\\xC6\\x9A\\xE2\\xB1\\xA6\\xC9\"\n\t\"\\x82\\xC6\\x80\\xC9\\x87\\xC9\\x89\\xC9\\x8B\\xC9\\x8D\\xC9\\x8F\\xCD\\xB1\\xCD\\xB3\\xCD\\xB7\\xCF\\xB3\\xCE\\xAC\\xCE\\xAD\"\n\t\"\\xCE\\xAE\\xCE\\xAF\\xCF\\x8C\\xCF\\x8D\\xCF\\x8E\\xCF\\x8A\\xCF\\x8B\\xCF\\x97\\xCF\\x99\\xCF\\x9B\\xCF\\x9F\\xCF\\xA1\\xCF\"\n\t\"\\xA3\\xCF\\xA5\\xCF\\xA7\\xCF\\xA9\\xCF\\xAB\\xCF\\xAD\\xCF\\xAF\\xCF\\xB8\\xCF\\xB2\\xCF\\xBB\\xCD\\xBB\\xCD\\xBC\\xCD\\xBD\"\n\t\"\\xD1\\x90\\xD1\\x91\\xD1\\x92\\xD1\\x93\\xD1\\x94\\xD1\\x95\\xD1\\x97\\xD1\\x98\\xD1\\x99\\xD1\\x9A\\xD1\\x9B\\xD1\\x9C\\xD1\"\n\t\"\\x9D\\xD1\\x9E\\xD1\\x9F\\xD0\\xB1\\xD0\\xB2\\xD0\\xB4\\xD0\\xB9\\xD0\\xBB\\xD0\\xBC\\xD0\\xBF\\xD1\\x80\\xD1\\x81\\xD1\\x82\"\n\t\"\\xD1\\x84\\xD1\\x85\\xD1\\x86\\xD1\\x88\\xD1\\x89\\xD1\\x8E\\xD1\\x8F\\xD1\\xA1\\xD1\\xA3\\xD1\\xA5\\xD1\\xA7\\xD1\\xA9\\xD1\"\n\t\"\\xAB\\xD1\\xAD\\xD1\\xAF\\xD1\\xB1\\xD1\\xB3\\xD1\\xB7\\xD1\\xB9\\xD1\\xBB\\xD1\\xBD\\xD1\\xBF\\xD2\\x81\\xD2\\x8B\\xD2\\x8D\"\n\t\"\\xD2\\x8F\\xD2\\x91\\xD2\\x93\\xD2\\x95\\xD2\\x97\\xD2\\x99\\xD2\\x9B\\xD2\\x9D\\xD2\\x9F\\xD2\\xA1\\xD2\\xA3\\xD2\\xA5\\xD2\"\n\t\"\\xA7\\xD2\\xA9\\xD2\\xAB\\xD2\\xAD\\xD2\\xAF\\xD2\\xB1\\xD2\\xB3\\xD2\\xB5\\xD2\\xB7\\xD2\\xB9\\xD2\\xBB\\xD2\\xBD\\xD2\\xBF\"\n\t\"\\xD3\\x8F\\xD3\\x82\\xD3\\x84\\xD3\\x86\\xD3\\x88\\xD3\\x8A\\xD3\\x8C\\xD3\\x8E\\xD3\\x91\\xD3\\x93\\xD3\\x95\\xD3\\x97\\xD3\"\n\t\"\\x9B\\xD3\\x9D\\xD3\\x9F\\xD3\\xA1\\xD3\\xA3\\xD3\\xA5\\xD3\\xA7\\xD3\\xAB\\xD3\\xAD\\xD3\\xAF\\xD3\\xB1\\xD3\\xB3\\xD3\\xB5\"\n\t\"\\xD3\\xB7\\xD3\\xB9\\xD3\\xBB\\xD3\\xBD\\xD3\\xBF\\xD4\\x81\\xD4\\x83\\xD4\\x85\\xD4\\x87\\xD4\\x89\\xD4\\x8B\\xD4\\x8D\\xD4\"\n\t\"\\x8F\\xD4\\x91\\xD4\\x93\\xD4\\x95\\xD4\\x97\\xD4\\x99\\xD4\\x9B\\xD4\\x9D\\xD4\\x9F\\xD4\\xA1\\xD4\\xA3\\xD4\\xA5\\xD4\\xA7\"\n\t\"\\xD4\\xA9\\xD4\\xAB\\xD4\\xAD\\xD4\\xAF\\xD5\\xA1\\xD5\\xA2\\xD5\\xA3\\xD5\\xA4\\xD5\\xA6\\xD5\\xA7\\xD5\\xA8\\xD5\\xA9\\xD5\"\n\t\"\\xAA\\xD5\\xAC\\xD5\\xAE\\xD5\\xAF\\xD5\\xB0\\xD5\\xB1\\xD5\\xB2\\xD5\\xB3\\xD5\\xB5\\xD5\\xB7\\xD5\\xB8\\xD5\\xB9\\xD5\\xBA\"\n\t\"\\xD5\\xBB\\xD5\\xBC\\xD5\\xBD\\xD5\\xBF\\xD6\\x80\\xD6\\x81\\xD6\\x83\\xD6\\x84\\xD6\\x85\\xD6\\x86\\xE2\\xB4\\x80\\xE2\\xB4\"\n\t\"\\x81\\xE2\\xB4\\x82\\xE2\\xB4\\x83\\xE2\\xB4\\x84\\xE2\\xB4\\x85\\xE2\\xB4\\x86\\xE2\\xB4\\x87\\xE2\\xB4\\x88\\xE2\\xB4\\x89\"\n\t\"\\xE2\\xB4\\x8A\\xE2\\xB4\\x8B\\xE2\\xB4\\x8C\\xE2\\xB4\\x8D\\xE2\\xB4\\x8E\\xE2\\xB4\\x8F\\xE2\\xB4\\x90\\xE2\\xB4\\x91\\xE2\"\n\t\"\\xB4\\x92\\xE2\\xB4\\x93\\xE2\\xB4\\x94\\xE2\\xB4\\x95\\xE2\\xB4\\x96\\xE2\\xB4\\x97\\xE2\\xB4\\x98\\xE2\\xB4\\x99\\xE2\\xB4\"\n\t\"\\x9A\\xE2\\xB4\\x9B\\xE2\\xB4\\x9C\\xE2\\xB4\\x9D\\xE2\\xB4\\x9E\\xE2\\xB4\\x9F\\xE2\\xB4\\xA0\\xE2\\xB4\\xA1\\xE2\\xB4\\xA2\"\n\t\"\\xE2\\xB4\\xA3\\xE2\\xB4\\xA4\\xE2\\xB4\\xA5\\xE2\\xB4\\xA7\\xE2\\xB4\\xAD\\xE1\\xB8\\x81\\xE1\\xB8\\x83\\xE1\\xB8\\x85\\xE1\"\n\t\"\\xB8\\x87\\xE1\\xB8\\x89\\xE1\\xB8\\x8B\\xE1\\xB8\\x8D\\xE1\\xB8\\x8F\\xE1\\xB8\\x91\\xE1\\xB8\\x93\\xE1\\xB8\\x95\\xE1\\xB8\"\n\t\"\\x97\\xE1\\xB8\\x99\\xE1\\xB8\\x9B\\xE1\\xB8\\x9D\\xE1\\xB8\\x9F\\xE1\\xB8\\xA1\\xE1\\xB8\\xA3\\xE1\\xB8\\xA5\\xE1\\xB8\\xA7\"\n\t\"\\xE1\\xB8\\xA9\\xE1\\xB8\\xAB\\xE1\\xB8\\xAD\\xE1\\xB8\\xAF\\xE1\\xB8\\xB1\\xE1\\xB8\\xB3\\xE1\\xB8\\xB5\\xE1\\xB8\\xB7\\xE1\"\n\t\"\\xB8\\xB9\\xE1\\xB8\\xBB\\xE1\\xB8\\xBD\\xE1\\xB8\\xBF\\xE1\\xB9\\x81\\xE1\\xB9\\x83\\xE1\\xB9\\x85\\xE1\\xB9\\x87\\xE1\\xB9\"\n\t\"\\x89\\xE1\\xB9\\x8B\\xE1\\xB9\\x8D\\xE1\\xB9\\x8F\\xE1\\xB9\\x91\\xE1\\xB9\\x93\\xE1\\xB9\\x95\\xE1\\xB9\\x97\\xE1\\xB9\\x99\"\n\t\"\\xE1\\xB9\\x9B\\xE1\\xB9\\x9D\\xE1\\xB9\\x9F\\xE1\\xB9\\xA1\\xE1\\xB9\\xA3\\xE1\\xB9\\xA5\\xE1\\xB9\\xA7\\xE1\\xB9\\xA9\\xE1\"\n\t\"\\xB9\\xAB\\xE1\\xB9\\xAD\\xE1\\xB9\\xAF\\xE1\\xB9\\xB1\\xE1\\xB9\\xB3\\xE1\\xB9\\xB5\\xE1\\xB9\\xB7\\xE1\\xB9\\xB9\\xE1\\xB9\"\n\t\"\\xBB\\xE1\\xB9\\xBD\\xE1\\xB9\\xBF\\xE1\\xBA\\x81\\xE1\\xBA\\x83\\xE1\\xBA\\x85\\xE1\\xBA\\x87\\xE1\\xBA\\x89\\xE1\\xBA\\x8B\"\n\t\"\\xE1\\xBA\\x8D\\xE1\\xBA\\x8F\\xE1\\xBA\\x91\\xE1\\xBA\\x93\\xE1\\xBA\\x95\\xC3\\x9F\\xE1\\xBA\\xA1\\xE1\\xBA\\xA3\\xE1\\xBA\"\n\t\"\\xA5\\xE1\\xBA\\xA7\\xE1\\xBA\\xA9\\xE1\\xBA\\xAB\\xE1\\xBA\\xAD\\xE1\\xBA\\xAF\\xE1\\xBA\\xB1\\xE1\\xBA\\xB3\\xE1\\xBA\\xB5\"\n\t\"\\xE1\\xBA\\xB7\\xE1\\xBA\\xB9\\xE1\\xBA\\xBB\\xE1\\xBA\\xBD\\xE1\\xBA\\xBF\\xE1\\xBB\\x81\\xE1\\xBB\\x83\\xE1\\xBB\\x85\\xE1\"\n\t\"\\xBB\\x87\\xE1\\xBB\\x89\\xE1\\xBB\\x8B\\xE1\\xBB\\x8D\\xE1\\xBB\\x8F\\xE1\\xBB\\x91\\xE1\\xBB\\x93\\xE1\\xBB\\x95\\xE1\\xBB\"\n\t\"\\x97\\xE1\\xBB\\x99\\xE1\\xBB\\x9B\\xE1\\xBB\\x9D\\xE1\\xBB\\x9F\\xE1\\xBB\\xA1\\xE1\\xBB\\xA3\\xE1\\xBB\\xA5\\xE1\\xBB\\xA7\"\n\t\"\\xE1\\xBB\\xA9\\xE1\\xBB\\xAB\\xE1\\xBB\\xAD\\xE1\\xBB\\xAF\\xE1\\xBB\\xB1\\xE1\\xBB\\xB3\\xE1\\xBB\\xB5\\xE1\\xBB\\xB7\\xE1\"\n\t\"\\xBB\\xB9\\xE1\\xBB\\xBB\\xE1\\xBB\\xBD\\xE1\\xBB\\xBF\\xE1\\xBC\\x80\\xE1\\xBC\\x81\\xE1\\xBC\\x82\\xE1\\xBC\\x83\\xE1\\xBC\"\n\t\"\\x84\\xE1\\xBC\\x85\\xE1\\xBC\\x86\\xE1\\xBC\\x87\\xE1\\xBC\\x90\\xE1\\xBC\\x91\\xE1\\xBC\\x92\\xE1\\xBC\\x93\\xE1\\xBC\\x94\"\n\t\"\\xE1\\xBC\\x95\\xE1\\xBC\\xA0\\xE1\\xBC\\xA1\\xE1\\xBC\\xA2\\xE1\\xBC\\xA3\\xE1\\xBC\\xA4\\xE1\\xBC\\xA5\\xE1\\xBC\\xA6\\xE1\"\n\t\"\\xBC\\xA7\\xE1\\xBC\\xB0\\xE1\\xBC\\xB1\\xE1\\xBC\\xB2\\xE1\\xBC\\xB3\\xE1\\xBC\\xB4\\xE1\\xBC\\xB5\\xE1\\xBC\\xB6\\xE1\\xBC\"\n\t\"\\xB7\\xE1\\xBD\\x80\\xE1\\xBD\\x81\\xE1\\xBD\\x82\\xE1\\xBD\\x83\\xE1\\xBD\\x84\\xE1\\xBD\\x85\\xE1\\xBD\\x91\\xE1\\xBD\\x93\"\n\t\"\\xE1\\xBD\\x95\\xE1\\xBD\\x97\\xE1\\xBD\\xA0\\xE1\\xBD\\xA1\\xE1\\xBD\\xA2\\xE1\\xBD\\xA3\\xE1\\xBD\\xA4\\xE1\\xBD\\xA5\\xE1\"\n\t\"\\xBD\\xA6\\xE1\\xBD\\xA7\\xE1\\xBE\\x80\\xE1\\xBE\\x81\\xE1\\xBE\\x82\\xE1\\xBE\\x83\\xE1\\xBE\\x84\\xE1\\xBE\\x85\\xE1\\xBE\"\n\t\"\\x86\\xE1\\xBE\\x87\\xE1\\xBE\\x90\\xE1\\xBE\\x91\\xE1\\xBE\\x92\\xE1\\xBE\\x93\\xE1\\xBE\\x94\\xE1\\xBE\\x95\\xE1\\xBE\\x96\"\n\t\"\\xE1\\xBE\\x97\\xE1\\xBE\\xA0\\xE1\\xBE\\xA1\\xE1\\xBE\\xA2\\xE1\\xBE\\xA3\\xE1\\xBE\\xA4\\xE1\\xBE\\xA5\\xE1\\xBE\\xA6\\xE1\"\n\t\"\\xBE\\xA7\\xE1\\xBE\\xB0\\xE1\\xBE\\xB1\\xE1\\xBD\\xB0\\xE1\\xBD\\xB1\\xE1\\xBE\\xB3\\xE1\\xBD\\xB2\\xE1\\xBD\\xB3\\xE1\\xBD\"\n\t\"\\xB4\\xE1\\xBD\\xB5\\xE1\\xBF\\x83\\xE1\\xBF\\x90\\xE1\\xBF\\x91\\xE1\\xBD\\xB6\\xE1\\xBD\\xB7\\xE1\\xBF\\xA0\\xE1\\xBF\\xA1\"\n\t\"\\xE1\\xBD\\xBA\\xE1\\xBD\\xBB\\xE1\\xBF\\xA5\\xE1\\xBD\\xB8\\xE1\\xBD\\xB9\\xE1\\xBD\\xBC\\xE1\\xBD\\xBD\\xE1\\xBF\\xB3\\xE2\"\n\t\"\\x85\\x8E\\xE2\\x85\\xB0\\xE2\\x85\\xB1\\xE2\\x85\\xB2\\xE2\\x85\\xB3\\xE2\\x85\\xB4\\xE2\\x85\\xB5\\xE2\\x85\\xB6\\xE2\\x85\"\n\t\"\\xB7\\xE2\\x85\\xB8\\xE2\\x85\\xB9\\xE2\\x85\\xBA\\xE2\\x85\\xBB\\xE2\\x85\\xBC\\xE2\\x85\\xBD\\xE2\\x85\\xBE\\xE2\\x85\\xBF\"\n\t\"\\xE2\\x86\\x84\\xE2\\x93\\x90\\xE2\\x93\\x91\\xE2\\x93\\x92\\xE2\\x93\\x93\\xE2\\x93\\x94\\xE2\\x93\\x95\\xE2\\x93\\x96\\xE2\"\n\t\"\\x93\\x97\\xE2\\x93\\x98\\xE2\\x93\\x99\\xE2\\x93\\x9A\\xE2\\x93\\x9B\\xE2\\x93\\x9C\\xE2\\x93\\x9D\\xE2\\x93\\x9E\\xE2\\x93\"\n\t\"\\x9F\\xE2\\x93\\xA0\\xE2\\x93\\xA1\\xE2\\x93\\xA2\\xE2\\x93\\xA3\\xE2\\x93\\xA4\\xE2\\x93\\xA5\\xE2\\x93\\xA6\\xE2\\x93\\xA7\"\n\t\"\\xE2\\x93\\xA8\\xE2\\x93\\xA9\\xE2\\xB0\\xB0\\xE2\\xB0\\xB1\\xE2\\xB0\\xB2\\xE2\\xB0\\xB3\\xE2\\xB0\\xB4\\xE2\\xB0\\xB5\\xE2\"\n\t\"\\xB0\\xB6\\xE2\\xB0\\xB7\\xE2\\xB0\\xB8\\xE2\\xB0\\xB9\\xE2\\xB0\\xBA\\xE2\\xB0\\xBB\\xE2\\xB0\\xBC\\xE2\\xB0\\xBD\\xE2\\xB0\"\n\t\"\\xBE\\xE2\\xB0\\xBF\\xE2\\xB1\\x80\\xE2\\xB1\\x81\\xE2\\xB1\\x82\\xE2\\xB1\\x83\\xE2\\xB1\\x84\\xE2\\xB1\\x85\\xE2\\xB1\\x86\"\n\t\"\\xE2\\xB1\\x87\\xE2\\xB1\\x88\\xE2\\xB1\\x89\\xE2\\xB1\\x8A\\xE2\\xB1\\x8B\\xE2\\xB1\\x8C\\xE2\\xB1\\x8D\\xE2\\xB1\\x8E\\xE2\"\n\t\"\\xB1\\x8F\\xE2\\xB1\\x90\\xE2\\xB1\\x91\\xE2\\xB1\\x92\\xE2\\xB1\\x93\\xE2\\xB1\\x94\\xE2\\xB1\\x95\\xE2\\xB1\\x96\\xE2\\xB1\"\n\t\"\\x97\\xE2\\xB1\\x98\\xE2\\xB1\\x99\\xE2\\xB1\\x9A\\xE2\\xB1\\x9B\\xE2\\xB1\\x9C\\xE2\\xB1\\x9D\\xE2\\xB1\\x9E\\xE2\\xB1\\xA1\"\n\t\"\\xE1\\xB5\\xBD\\xC9\\xBD\\xE2\\xB1\\xA8\\xE2\\xB1\\xAA\\xE2\\xB1\\xAC\\xE2\\xB1\\xB3\\xE2\\xB1\\xB6\\xC8\\xBF\\xC9\\x80\\xE2\"\n\t\"\\xB2\\x81\\xE2\\xB2\\x83\\xE2\\xB2\\x85\\xE2\\xB2\\x87\\xE2\\xB2\\x89\\xE2\\xB2\\x8B\\xE2\\xB2\\x8D\\xE2\\xB2\\x8F\\xE2\\xB2\"\n\t\"\\x91\\xE2\\xB2\\x93\\xE2\\xB2\\x95\\xE2\\xB2\\x97\\xE2\\xB2\\x99\\xE2\\xB2\\x9B\\xE2\\xB2\\x9D\\xE2\\xB2\\x9F\\xE2\\xB2\\xA1\"\n\t\"\\xE2\\xB2\\xA3\\xE2\\xB2\\xA5\\xE2\\xB2\\xA7\\xE2\\xB2\\xA9\\xE2\\xB2\\xAB\\xE2\\xB2\\xAD\\xE2\\xB2\\xAF\\xE2\\xB2\\xB1\\xE2\"\n\t\"\\xB2\\xB3\\xE2\\xB2\\xB5\\xE2\\xB2\\xB7\\xE2\\xB2\\xB9\\xE2\\xB2\\xBB\\xE2\\xB2\\xBD\\xE2\\xB2\\xBF\\xE2\\xB3\\x81\\xE2\\xB3\"\n\t\"\\x83\\xE2\\xB3\\x85\\xE2\\xB3\\x87\\xE2\\xB3\\x89\\xE2\\xB3\\x8B\\xE2\\xB3\\x8D\\xE2\\xB3\\x8F\\xE2\\xB3\\x91\\xE2\\xB3\\x93\"\n\t\"\\xE2\\xB3\\x95\\xE2\\xB3\\x97\\xE2\\xB3\\x99\\xE2\\xB3\\x9B\\xE2\\xB3\\x9D\\xE2\\xB3\\x9F\\xE2\\xB3\\xA1\\xE2\\xB3\\xA3\\xE2\"\n\t\"\\xB3\\xAC\\xE2\\xB3\\xAE\\xE2\\xB3\\xB3\\xEA\\x99\\x81\\xEA\\x99\\x83\\xEA\\x99\\x85\\xEA\\x99\\x87\\xEA\\x99\\x89\\xEA\\x99\"\n\t\"\\x8B\\xEA\\x99\\x8D\\xEA\\x99\\x8F\\xEA\\x99\\x91\\xEA\\x99\\x93\\xEA\\x99\\x95\\xEA\\x99\\x97\\xEA\\x99\\x99\\xEA\\x99\\x9B\"\n\t\"\\xEA\\x99\\x9D\\xEA\\x99\\x9F\\xEA\\x99\\xA1\\xEA\\x99\\xA3\\xEA\\x99\\xA5\\xEA\\x99\\xA7\\xEA\\x99\\xA9\\xEA\\x99\\xAB\\xEA\"\n\t\"\\x99\\xAD\\xEA\\x9A\\x81\\xEA\\x9A\\x83\\xEA\\x9A\\x85\\xEA\\x9A\\x87\\xEA\\x9A\\x89\\xEA\\x9A\\x8B\\xEA\\x9A\\x8D\\xEA\\x9A\"\n\t\"\\x8F\\xEA\\x9A\\x91\\xEA\\x9A\\x93\\xEA\\x9A\\x95\\xEA\\x9A\\x97\\xEA\\x9A\\x99\\xEA\\x9A\\x9B\\xEA\\x9C\\xA3\\xEA\\x9C\\xA5\"\n\t\"\\xEA\\x9C\\xA9\\xEA\\x9C\\xAB\\xEA\\x9C\\xAD\\xEA\\x9C\\xAF\\xEA\\x9C\\xB3\\xEA\\x9C\\xB5\\xEA\\x9C\\xB7\\xEA\\x9C\\xB9\\xEA\"\n\t\"\\x9C\\xBB\\xEA\\x9C\\xBD\\xEA\\x9C\\xBF\\xEA\\x9D\\x81\\xEA\\x9D\\x83\\xEA\\x9D\\x85\\xEA\\x9D\\x87\\xEA\\x9D\\x89\\xEA\\x9D\"\n\t\"\\x8B\\xEA\\x9D\\x8D\\xEA\\x9D\\x8F\\xEA\\x9D\\x91\\xEA\\x9D\\x93\\xEA\\x9D\\x95\\xEA\\x9D\\x97\\xEA\\x9D\\x99\\xEA\\x9D\\x9B\"\n\t\"\\xEA\\x9D\\x9D\\xEA\\x9D\\x9F\\xEA\\x9D\\xA1\\xEA\\x9D\\xA3\\xEA\\x9D\\xA5\\xEA\\x9D\\xA7\\xEA\\x9D\\xA9\\xEA\\x9D\\xAB\\xEA\"\n\t\"\\x9D\\xAD\\xEA\\x9D\\xBA\\xEA\\x9D\\xBC\\xE1\\xB5\\xB9\\xEA\\x9D\\xBF\\xEA\\x9E\\x81\\xEA\\x9E\\x83\\xEA\\x9E\\x85\\xEA\\x9E\"\n\t\"\\x87\\xEA\\x9E\\x8C\\xEA\\x9E\\x91\\xEA\\x9E\\x93\\xEA\\x9E\\x97\\xEA\\x9E\\x99\\xEA\\x9E\\x9B\\xEA\\x9E\\x9D\\xEA\\x9E\\x9F\"\n\t\"\\xEA\\x9E\\xA1\\xEA\\x9E\\xA3\\xEA\\x9E\\xA5\\xEA\\x9E\\xA7\\xEA\\x9E\\xA9\\xC9\\xAC\\xCA\\x9E\\xCA\\x87\\xEF\\xBD\\x81\\xEF\"\n\t\"\\xBD\\x82\\xEF\\xBD\\x83\\xEF\\xBD\\x84\\xEF\\xBD\\x85\\xEF\\xBD\\x86\\xEF\\xBD\\x87\\xEF\\xBD\\x88\\xEF\\xBD\\x89\\xEF\\xBD\"\n\t\"\\x8A\\xEF\\xBD\\x8B\\xEF\\xBD\\x8C\\xEF\\xBD\\x8D\\xEF\\xBD\\x8E\\xEF\\xBD\\x8F\\xEF\\xBD\\x90\\xEF\\xBD\\x91\\xEF\\xBD\\x92\"\n\t\"\\xEF\\xBD\\x93\\xEF\\xBD\\x94\\xEF\\xBD\\x95\\xEF\\xBD\\x96\\xEF\\xBD\\x97\\xEF\\xBD\\x98\\xEF\\xBD\\x99\\xEF\\xBD\\x9A\\xF0\"\n\t\"\\x90\\x90\\xA8\\xF0\\x90\\x90\\xA9\\xF0\\x90\\x90\\xAA\\xF0\\x90\\x90\\xAB\\xF0\\x90\\x90\\xAC\\xF0\\x90\\x90\\xAD\\xF0\\x90\"\n\t\"\\x90\\xAE\\xF0\\x90\\x90\\xAF\\xF0\\x90\\x90\\xB0\\xF0\\x90\\x90\\xB1\\xF0\\x90\\x90\\xB2\\xF0\\x90\\x90\\xB3\\xF0\\x90\\x90\"\n\t\"\\xB4\\xF0\\x90\\x90\\xB5\\xF0\\x90\\x90\\xB6\\xF0\\x90\\x90\\xB7\\xF0\\x90\\x90\\xB8\\xF0\\x90\\x90\\xB9\\xF0\\x90\\x90\\xBA\"\n\t\"\\xF0\\x90\\x90\\xBB\\xF0\\x90\\x90\\xBC\\xF0\\x90\\x90\\xBD\\xF0\\x90\\x90\\xBE\\xF0\\x90\\x90\\xBF\\xF0\\x90\\x91\\x80\\xF0\"\n\t\"\\x90\\x91\\x81\\xF0\\x90\\x91\\x82\\xF0\\x90\\x91\\x83\\xF0\\x90\\x91\\x84\\xF0\\x90\\x91\\x85\\xF0\\x90\\x91\\x86\\xF0\\x90\"\n\t\"\\x91\\x87\\xF0\\x90\\x91\\x88\\xF0\\x90\\x91\\x89\\xF0\\x90\\x91\\x8A\\xF0\\x90\\x91\\x8B\\xF0\\x90\\x91\\x8C\\xF0\\x90\\x91\"\n\t\"\\x8D\\xF0\\x90\\x91\\x8E\\xF0\\x90\\x91\\x8F\\xF0\\x91\\xA3\\x80\\xF0\\x91\\xA3\\x81\\xF0\\x91\\xA3\\x82\\xF0\\x91\\xA3\\x83\"\n\t\"\\xF0\\x91\\xA3\\x84\\xF0\\x91\\xA3\\x85\\xF0\\x91\\xA3\\x86\\xF0\\x91\\xA3\\x87\\xF0\\x91\\xA3\\x88\\xF0\\x91\\xA3\\x89\\xF0\"\n\t\"\\x91\\xA3\\x8A\\xF0\\x91\\xA3\\x8B\\xF0\\x91\\xA3\\x8C\\xF0\\x91\\xA3\\x8D\\xF0\\x91\\xA3\\x8E\\xF0\\x91\\xA3\\x8F\\xF0\\x91\"\n\t\"\\xA3\\x90\\xF0\\x91\\xA3\\x91\\xF0\\x91\\xA3\\x92\\xF0\\x91\\xA3\\x93\\xF0\\x91\\xA3\\x94\\xF0\\x91\\xA3\\x95\\xF0\\x91\\xA3\"\n\t\"\\x96\\xF0\\x91\\xA3\\x97\\xF0\\x91\\xA3\\x98\\xF0\\x91\\xA3\\x99\\xF0\\x91\\xA3\\x9A\\xF0\\x91\\xA3\\x9B\\xF0\\x91\\xA3\\x9C\"\n\t\"\\xF0\\x91\\xA3\\x9D\\xF0\\x91\\xA3\\x9E\\xF0\\x91\\xA3\\x9F\\x53\\x73\\xC7\\x85\\xC7\\x88\\xC7\\x8B\\xC7\\xB2\\xD4\\xB5\\xD6\"\n\t\"\\x82\\xE1\\xBE\\x88\\xE1\\xBE\\x89\\xE1\\xBE\\x8A\\xE1\\xBE\\x8B\\xE1\\xBE\\x8C\\xE1\\xBE\\x8D\\xE1\\xBE\\x8E\\xE1\\xBE\\x8F\"\n\t\"\\xE1\\xBE\\x98\\xE1\\xBE\\x99\\xE1\\xBE\\x9A\\xE1\\xBE\\x9B\\xE1\\xBE\\x9C\\xE1\\xBE\\x9D\\xE1\\xBE\\x9E\\xE1\\xBE\\x9F\\xE1\"\n\t\"\\xBE\\xA8\\xE1\\xBE\\xA9\\xE1\\xBE\\xAA\\xE1\\xBE\\xAB\\xE1\\xBE\\xAC\\xE1\\xBE\\xAD\\xE1\\xBE\\xAE\\xE1\\xBE\\xAF\\xE1\\xBE\"\n\t\"\\xBA\\xCD\\x85\\xE1\\xBE\\xBC\\xCE\\x86\\xCD\\x85\\xCE\\x91\\xCD\\x82\\xCD\\x85\\xE1\\xBF\\x8A\\xCD\\x85\\xE1\\xBF\\x8C\\xCE\"\n\t\"\\x89\\xCD\\x85\\xCE\\x97\\xCD\\x82\\xCD\\x85\\xE1\\xBF\\xBA\\xCD\\x85\\xE1\\xBF\\xBC\\xCE\\x8F\\xCD\\x85\\xCE\\xA9\\xCD\\x82\"\n\t\"\\xCD\\x85\\x46\\x66\\x46\\x69\\x46\\x6C\\x46\\x66\\x69\\x46\\x66\\x6C\\x53\\x74\\xD5\\x84\\xD5\\xB6\\xD5\\x84\\xD5\\xA5\\xD5\"\n\t\"\\x84\\xD5\\xAB\\xD5\\x8E\\xD5\\xB6\\xD5\\x84\\xD5\\xAD\\x73\\x73\\xE1\\xBC\\x80\\xCE\\xB9\\xE1\\xBC\\x81\\xCE\\xB9\\xE1\\xBC\"\n\t\"\\x82\\xCE\\xB9\\xE1\\xBC\\x83\\xCE\\xB9\\xE1\\xBC\\x84\\xCE\\xB9\\xE1\\xBC\\x85\\xCE\\xB9\\xE1\\xBC\\x86\\xCE\\xB9\\xE1\\xBC\"\n\t\"\\x87\\xCE\\xB9\\xE1\\xBC\\xA0\\xCE\\xB9\\xE1\\xBC\\xA1\\xCE\\xB9\\xE1\\xBC\\xA2\\xCE\\xB9\\xE1\\xBC\\xA3\\xCE\\xB9\\xE1\\xBC\"\n\t\"\\xA4\\xCE\\xB9\\xE1\\xBC\\xA5\\xCE\\xB9\\xE1\\xBC\\xA6\\xCE\\xB9\\xE1\\xBC\\xA7\\xCE\\xB9\\xE1\\xBD\\xA0\\xCE\\xB9\\xE1\\xBD\"\n\t\"\\xA1\\xCE\\xB9\\xE1\\xBD\\xA2\\xCE\\xB9\\xE1\\xBD\\xA3\\xCE\\xB9\\xE1\\xBD\\xA4\\xCE\\xB9\\xE1\\xBD\\xA5\\xCE\\xB9\\xE1\\xBD\"\n\t\"\\xA6\\xCE\\xB9\\xE1\\xBD\\xA7\\xCE\\xB9\\xE1\\xBD\\xB0\\xCE\\xB9\\xCE\\xB1\\xCE\\xB9\\xCE\\xAC\\xCE\\xB9\\xCE\\xB1\\xCD\\x82\"\n\t\"\\xCE\\xB9\\xE1\\xBD\\xB4\\xCE\\xB9\\xCE\\xB7\\xCE\\xB9\\xCE\\xAE\\xCE\\xB9\\xCE\\xB7\\xCD\\x82\\xCE\\xB9\\xE1\\xBD\\xBC\\xCE\"\n\t\"\\xB9\\xCF\\x89\\xCE\\xB9\\xCF\\x8E\\xCE\\xB9\\xCF\\x89\\xCD\\x82\\xCE\\xB9\"\n;\nconst size_t CompressedStringDataLength = 19415;"
  },
  {
    "path": "external/utf8rewind/source/unicodedatabase.h",
    "content": "/*\n\tCopyright (C) 2014-2016 Quinten Lansu\n\n\tPermission is hereby granted, free of charge, to any person\n\tobtaining a copy of this software and associated documentation\n\tfiles (the \"Software\"), to deal in the Software without\n\trestriction, including without limitation the rights to use,\n\tcopy, modify, merge, publish, distribute, sublicense, and/or\n\tsell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following\n\tconditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n*/\n\n#ifndef _UTF8REWIND_UNICODEDATABASE_H_\n#define _UTF8REWIND_UNICODEDATABASE_H_\n\n/*!\n\t\\file\n\t\\brief Unicode property database.\n\n\t\\cond INTERNAL\n*/\n\n#include \"../include/utf8rewind/utf8rewind.h\"\n\ntypedef struct {\n\tunicode_t codepoint;\n\tuint32_t length_and_offset;\n} DecompositionRecord;\n\ntypedef struct {\n\tuint64_t key;\n\tunicode_t value;\n} CompositionRecord;\n\nextern const size_t* GeneralCategoryIndexPtr;\nextern const uint32_t* GeneralCategoryDataPtr;\n\nextern const size_t* CanonicalCombiningClassIndexPtr;\nextern const uint8_t* CanonicalCombiningClassDataPtr;\n\nextern const size_t* QuickCheckCaseMappedIndexPtr;\nextern const uint8_t* QuickCheckCaseMappedDataPtr;\n\nextern const size_t* QuickCheckNFCIndexPtr;\nextern const uint8_t* QuickCheckNFCDataPtr;\n\nextern const size_t* QuickCheckNFDIndexPtr;\nextern const uint8_t* QuickCheckNFDDataPtr;\n\nextern const size_t* QuickCheckNFKCIndexPtr;\nextern const uint8_t* QuickCheckNFKCDataPtr;\n\nextern const size_t* QuickCheckNFKDIndexPtr;\nextern const uint8_t* QuickCheckNFKDDataPtr;\n\nextern const size_t UnicodeNFDRecordCount;\nextern const DecompositionRecord* UnicodeNFDRecordPtr;\n\nextern const size_t UnicodeNFKDRecordCount;\nextern const DecompositionRecord* UnicodeNFKDRecordPtr;\n\nextern const size_t UnicodeUppercaseRecordCount;\nextern const DecompositionRecord* UnicodeUppercaseRecordPtr;\n\nextern const size_t UnicodeLowercaseRecordCount;\nextern const DecompositionRecord* UnicodeLowercaseRecordPtr;\n\nextern const size_t UnicodeTitlecaseRecordCount;\nextern const DecompositionRecord* UnicodeTitlecaseRecordPtr;\n\nextern const size_t UnicodeCompositionRecordCount;\nextern const CompositionRecord* UnicodeCompositionRecordPtr;\n\nextern const uint32_t* NFDIndex1Ptr;\nextern const uint32_t* NFDIndex2Ptr;\nextern const uint32_t* NFDDataPtr;\n\nextern const uint32_t* NFKDIndex1Ptr;\nextern const uint32_t* NFKDIndex2Ptr;\nextern const uint32_t* NFKDDataPtr;\n\nextern const uint32_t* UppercaseIndex1Ptr;\nextern const uint32_t* UppercaseIndex2Ptr;\nextern const uint32_t* UppercaseDataPtr;\n\nextern const uint32_t* LowercaseIndex1Ptr;\nextern const uint32_t* LowercaseIndex2Ptr;\nextern const uint32_t* LowercaseDataPtr;\n\nextern const uint32_t* TitlecaseIndex1Ptr;\nextern const uint32_t* TitlecaseIndex2Ptr;\nextern const uint32_t* TitlecaseDataPtr;\n\nextern const uint32_t* CaseFoldingIndex1Ptr;\nextern const uint32_t* CaseFoldingIndex2Ptr;\nextern const uint32_t* CaseFoldingDataPtr;\n\nextern const char* CompressedStringData;\nextern const size_t CompressedStringDataLength;\n\nextern const char* DecompositionData;\nextern const size_t DecompositionDataLength;\n\n/*! \\endcond */\n\n#endif /* _UTF8REWIND_UNICODEDATABASE_H_ */"
  },
  {
    "path": "external/utf8rewind/source/utf8rewind.c",
    "content": "/*\n\tCopyright (C) 2014-2016 Quinten Lansu\n\n\tPermission is hereby granted, free of charge, to any person\n\tobtaining a copy of this software and associated documentation\n\tfiles (the \"Software\"), to deal in the Software without\n\trestriction, including without limitation the rights to use,\n\tcopy, modify, merge, publish, distribute, sublicense, and/or\n\tsell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following\n\tconditions:\n\n\tThe above copyright notice and this permission notice shall be\n\tincluded in all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n*/\n\n#include \"../include/utf8rewind/utf8rewind.h\"\n\n#include \"internal/base.h\"\n#include \"internal/casemapping.h\"\n#include \"internal/codepoint.h\"\n#include \"internal/composition.h\"\n#include \"internal/decomposition.h\"\n#include \"internal/database.h\"\n#include \"internal/seeking.h\"\n#include \"internal/streaming.h\"\n\n#ifndef _WIN32\n\t#include <strings.h>\n#else\n\tint strncasecmp(const char* s1, const char* s2, size_t n)\n\t{\n\t\tfor(; n != 0; --n)\n\t\t{\n\t\t\tint c1 = tolower(*((unsigned char*) s1++));\n\t\t\tint c2 = tolower(*((unsigned char*) s2++));\n\n\t\t\tif((c1 != c2) || (c1 == '\\0'))\n\t\t\t{\n\t\t\t\treturn c1 - c2;\n\t\t\t}\n\t\t}\n\n\t\treturn 0;\n\t}\n#endif\n\n\nsize_t utf8len(const char* text)\n{\n\tconst uint8_t* src;\n\tsize_t src_length;\n\tsize_t length;\n\n\t/* Validate input */\n\n\tif (text == 0 ||\n\t\ttext[0] == 0)\n\t{\n\t\treturn 0;\n\t}\n\n\tlength = 0;\n\n\t/* Determine length in codepoints */\n\n\tsrc = (const uint8_t*)text;\n\tsrc_length = strlen(text);\n\n\twhile (src_length > 0)\n\t{\n\t\tuint8_t src_offset = 1;\n\n\t\t/* Check if the current byte is part of a multi-byte sequence */\n\n\t\tuint8_t codepoint_length = codepoint_decoded_length[*src];\n\t\tif (codepoint_length > 1)\n\t\t{\n\t\t\t/* Check every byte of the sequence */\n\n\t\t\tdo\n\t\t\t{\n\t\t\t\tif (src[src_offset] < 0x80 ||  /* Not a continuation byte */\n\t\t\t\t\tsrc[src_offset] > 0xBF)    /* Start of a new sequence */\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\twhile (++src_offset < codepoint_length);\n\t\t}\n\n\t\t/* Found a codepoint */\n\n\t\tlength++;\n\n\t\t/* Move cursor */\n\n\t\tif (src_offset >= src_length)\n\t\t{\n\t\t\tbreak;\n\t\t}\n\n\t\tsrc += src_offset;\n\t\tsrc_length -= src_offset;\n\t}\n\n\treturn length;\n}\n\nsize_t utf16toutf8(const utf16_t* input, size_t inputSize, char* target, size_t targetSize, int32_t* errors)\n{\n\tconst utf16_t* src;\n\tsize_t src_size;\n\tchar* dst;\n\tsize_t dst_size;\n\tsize_t bytes_written = 0;\n\n\t/* Validate parameters */\n\n\tUTF8_VALIDATE_PARAMETERS_CHAR(utf16_t, bytes_written);\n\tUTF8_SET_ERROR(NONE);\n\n\t/* Setup cursors */\n\n\tsrc = input;\n\tsrc_size = inputSize;\n\tdst = target;\n\tdst_size = targetSize;\n\n\t/* Loop over input */\n\n\twhile (src_size > 0)\n\t{\n\t\tunicode_t codepoint;\n\t\tuint8_t encoded_size;\n\n\t\tif (src_size < sizeof(utf16_t))\n\t\t{\n\t\t\t/* Not enough data */\n\n\t\t\tgoto invaliddata;\n\t\t}\n\n\t\tcodepoint = (unicode_t)*src;\n\n\t\tif (codepoint >= SURROGATE_HIGH_START &&\n\t\t\tcodepoint <= SURROGATE_LOW_END)\n\t\t{\n\t\t\t/* Decode surrogate pair */\n\n\t\t\tif (codepoint > SURROGATE_HIGH_END)\n\t\t\t{\n\t\t\t\t/* Missing high surrogate codepoint */\n\n\t\t\t\tcodepoint = REPLACEMENT_CHARACTER;\n\n\t\t\t\tUTF8_SET_ERROR(INVALID_DATA);\n\t\t\t}\n\t\t\telse if (\n\t\t\t\tsrc_size < 2 * sizeof(utf16_t))\n\t\t\t{\n\t\t\t\t/* Not enough data */\n\n\t\t\t\tgoto invaliddata;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* Read low surrogate codepoint */\n\n\t\t\t\tif (src[1] < SURROGATE_LOW_START ||\n\t\t\t\t\tsrc[1] > SURROGATE_LOW_END)\n\t\t\t\t{\n\t\t\t\t\t/* Missing low surrogate codepoint */\n\n\t\t\t\t\tcodepoint = REPLACEMENT_CHARACTER;\n\n\t\t\t\t\tUTF8_SET_ERROR(INVALID_DATA);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t/* Decode codepoint from surrogate pair */\n\n\t\t\t\t\tcodepoint =\n\t\t\t\t\t\t(MAX_BASIC_MULTILINGUAL_PLANE + 1) +\n\t\t\t\t\t\t(src[1] - SURROGATE_LOW_START) +\n\t\t\t\t\t\t((src[0] - SURROGATE_HIGH_START) << 10);\n\n\t\t\t\t\tsrc++;\n\t\t\t\t\tsrc_size -= sizeof(utf16_t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tencoded_size = codepoint_write(codepoint, &dst, &dst_size);\n\t\tif (encoded_size == 0)\n\t\t{\n\t\t\tUTF8_SET_ERROR(NOT_ENOUGH_SPACE);\n\n\t\t\treturn bytes_written;\n\t\t}\n\n\t\tbytes_written += encoded_size;\n\n\t\tsrc++;\n\t\tsrc_size -= sizeof(utf16_t);\n\t}\n\n\treturn bytes_written;\n\ninvaliddata:\n\tif (dst != 0)\n\t{\n\t\tif (dst_size < REPLACEMENT_CHARACTER_STRING_LENGTH)\n\t\t{\n\t\t\tUTF8_SET_ERROR(NOT_ENOUGH_SPACE);\n\n\t\t\treturn bytes_written;\n\t\t}\n\n\t\t/* Write replacement codepoint to output */\n\n\t\tmemcpy(dst, REPLACEMENT_CHARACTER_STRING, REPLACEMENT_CHARACTER_STRING_LENGTH);\n\t}\n\n\tUTF8_SET_ERROR(INVALID_DATA);\n\n\treturn bytes_written + REPLACEMENT_CHARACTER_STRING_LENGTH;\n}\n\nsize_t utf32toutf8(const unicode_t* input, size_t inputSize, char* target, size_t targetSize, int32_t* errors)\n{\n\tconst unicode_t* src;\n\tsize_t src_size;\n\tchar* dst;\n\tsize_t dst_size;\n\tsize_t bytes_written = 0;\n\n\t/* Validate parameters */\n\n\tUTF8_VALIDATE_PARAMETERS_CHAR(unicode_t, bytes_written);\n\tUTF8_SET_ERROR(NONE);\n\n\t/* Setup cursors */\n\n\tsrc = input;\n\tsrc_size = inputSize;\n\tdst = target;\n\tdst_size = targetSize;\n\n\t/* Loop over input */\n\n\twhile (src_size > 0)\n\t{\n\t\tunicode_t codepoint;\n\t\tuint8_t encoded_size;\n\n\t\tif (src_size < sizeof(unicode_t))\n\t\t{\n\t\t\t/* Not enough data */\n\n\t\t\tgoto invaliddata;\n\t\t}\n\n\t\tcodepoint = *src;\n\n\t\tif (codepoint >= SURROGATE_HIGH_START &&\n\t\t\tcodepoint <= SURROGATE_LOW_END)\n\t\t{\n\t\t\t/* Decode surrogate pair */\n\n\t\t\tif (codepoint > SURROGATE_HIGH_END)\n\t\t\t{\n\t\t\t\t/* Missing high surrogate codepoint */\n\n\t\t\t\tcodepoint = REPLACEMENT_CHARACTER;\n\n\t\t\t\tUTF8_SET_ERROR(INVALID_DATA);\n\t\t\t}\n\t\t\telse if (\n\t\t\t\tsrc_size < 2 * sizeof(unicode_t))\n\t\t\t{\n\t\t\t\t/* Not enough data */\n\n\t\t\t\tgoto invaliddata;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* Read low surrogate codepoint */\n\n\t\t\t\tif (src[1] < SURROGATE_LOW_START ||\n\t\t\t\t\tsrc[1] > SURROGATE_LOW_END)\n\t\t\t\t{\n\t\t\t\t\t/* Missing low surrogate codepoint */\n\n\t\t\t\t\tcodepoint = REPLACEMENT_CHARACTER;\n\n\t\t\t\t\tUTF8_SET_ERROR(INVALID_DATA);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t/* Decode codepoint from surrogate pair */\n\n\t\t\t\t\tcodepoint =\n\t\t\t\t\t\t(MAX_BASIC_MULTILINGUAL_PLANE + 1) +\n\t\t\t\t\t\t(src[1] - SURROGATE_LOW_START) +\n\t\t\t\t\t\t((src[0] - SURROGATE_HIGH_START) << 10);\n\n\t\t\t\t\tsrc++;\n\t\t\t\t\tsrc_size -= sizeof(unicode_t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tencoded_size = codepoint_write(codepoint, &dst, &dst_size);\n\t\tif (encoded_size == 0)\n\t\t{\n\t\t\tUTF8_SET_ERROR(NOT_ENOUGH_SPACE);\n\n\t\t\treturn bytes_written;\n\t\t}\n\n\t\tbytes_written += encoded_size;\n\n\t\tsrc++;\n\t\tsrc_size -= sizeof(unicode_t);\n\t}\n\n\treturn bytes_written;\n\ninvaliddata:\n\tif (dst != 0)\n\t{\n\t\tif (dst_size < REPLACEMENT_CHARACTER_STRING_LENGTH)\n\t\t{\n\t\t\tUTF8_SET_ERROR(NOT_ENOUGH_SPACE);\n\n\t\t\treturn bytes_written;\n\t\t}\n\n\t\t/* Write replacement codepoint to output */\n\n\t\tmemcpy(dst, REPLACEMENT_CHARACTER_STRING, REPLACEMENT_CHARACTER_STRING_LENGTH);\n\t}\n\n\tUTF8_SET_ERROR(INVALID_DATA);\n\n\treturn bytes_written + REPLACEMENT_CHARACTER_STRING_LENGTH;\n}\n\nsize_t widetoutf8(const wchar_t* input, size_t inputSize, char* target, size_t targetSize, int32_t* errors)\n{\n#if UTF8_WCHAR_UTF16\n\treturn utf16toutf8((const utf16_t*)input, inputSize, target, targetSize, errors);\n#elif UTF8_WCHAR_UTF32\n\treturn utf32toutf8((const unicode_t*)input, inputSize, target, targetSize, errors);\n#else\n\treturn SIZE_MAX;\n#endif\n}\n\nsize_t utf8toutf16(const char* input, size_t inputSize, utf16_t* target, size_t targetSize, int32_t* errors)\n{\n\tconst char* src;\n\tsize_t src_size;\n\tutf16_t* dst;\n\tsize_t dst_size;\n\tsize_t bytes_written = 0;\n\n\t/* Validate parameters */\n\n\tUTF8_VALIDATE_PARAMETERS(char, utf16_t, bytes_written);\n\n\t/* Setup cursors */\n\n\tsrc = input;\n\tsrc_size = inputSize;\n\tdst = target;\n\tdst_size = targetSize;\n\n\t/* Loop over input */\n\n\twhile (src_size > 0)\n\t{\n\t\tunicode_t decoded;\n\t\tuint8_t decoded_size = codepoint_read(src, src_size, &decoded);\n\n\t\tif (decoded <= MAX_BASIC_MULTILINGUAL_PLANE)\n\t\t{\n\t\t\t/* Codepoint fits in a single UTF-16 codepoint */\n\n\t\t\tif (dst != 0)\n\t\t\t{\n\t\t\t\t/* Write to output */\n\n\t\t\t\tif (dst_size < sizeof(utf16_t))\n\t\t\t\t{\n\t\t\t\t\tUTF8_SET_ERROR(NOT_ENOUGH_SPACE);\n\n\t\t\t\t\treturn bytes_written;\n\t\t\t\t}\n\n\t\t\t\t*dst++ = (utf16_t)decoded;\n\t\t\t\tdst_size -= sizeof(utf16_t);\n\t\t\t}\n\n\t\t\tbytes_written += sizeof(utf16_t);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/* Codepoint must be encoded using a surrogate pair */\n\n\t\t\tif (dst != 0)\n\t\t\t{\n\t\t\t\t/* Write to output */\n\n\t\t\t\tif (dst_size < 2 * sizeof(utf16_t))\n\t\t\t\t{\n\t\t\t\t\tUTF8_SET_ERROR(NOT_ENOUGH_SPACE);\n\n\t\t\t\t\treturn bytes_written;\n\t\t\t\t}\n\n\t\t\t\t/* Encoded value is always beyond BMP */\n\n\t\t\t\tdecoded -= (MAX_BASIC_MULTILINGUAL_PLANE + 1);\n\t\t\t\t*dst++ = SURROGATE_HIGH_START + (utf16_t) (decoded >> 10);\n\t\t\t\t*dst++ = SURROGATE_LOW_START + (decoded & 0x03FF);\n\n\t\t\t\tdst_size -= 2 * sizeof(utf16_t);\n\t\t\t}\n\n\t\t\tbytes_written += 2 * sizeof(utf16_t);\n\t\t}\n\n\t\tsrc += decoded_size;\n\t\tsrc_size -= decoded_size;\n\t}\n\n\tUTF8_SET_ERROR(NONE);\n\n\treturn bytes_written;\n}\n\nsize_t utf8toutf32(const char* input, size_t inputSize, unicode_t* target, size_t targetSize, int32_t* errors)\n{\n\tconst char* src;\n\tsize_t src_size;\n\tunicode_t* dst;\n\tsize_t dst_size;\n\tsize_t bytes_written = 0;\n\n\t/* Validate parameters */\n\n\tUTF8_VALIDATE_PARAMETERS(char, unicode_t, bytes_written);\n\n\t/* Setup cursors */\n\n\tsrc = input;\n\tsrc_size = inputSize;\n\tdst = target;\n\tdst_size = targetSize;\n\n\t/* Loop over input */\n\n\twhile (src_size > 0)\n\t{\n\t\tunicode_t decoded;\n\t\tuint8_t decoded_length = codepoint_read(src, src_size, &decoded);\n\n\t\tif (dst != 0)\n\t\t{\n\t\t\t/* Write to output */\n\n\t\t\tif (dst_size < sizeof(unicode_t))\n\t\t\t{\n\t\t\t\tUTF8_SET_ERROR(NOT_ENOUGH_SPACE);\n\n\t\t\t\treturn bytes_written;\n\t\t\t}\n\n\t\t\t*dst++ = decoded;\n\t\t\tdst_size -= sizeof(unicode_t);\n\t\t}\n\n\t\tbytes_written += sizeof(unicode_t);\n\n\t\tsrc += decoded_length;\n\t\tsrc_size -= decoded_length;\n\t}\n\n\tUTF8_SET_ERROR(NONE);\n\n\treturn bytes_written;\n}\n\nsize_t utf8towide(const char* input, size_t inputSize, wchar_t* target, size_t targetSize, int32_t* errors)\n{\n#if UTF8_WCHAR_UTF16\n\treturn utf8toutf16(input, inputSize, (utf16_t*)target, targetSize, errors);\n#elif UTF8_WCHAR_UTF32\n\treturn utf8toutf32(input, inputSize, (unicode_t*)target, targetSize, errors);\n#else\n\treturn SIZE_MAX;\n#endif\n}\n\nconst char* utf8seek(const char* text, size_t textSize, const char* textStart, off_t offset, int direction)\n{\n\tconst char* text_end;\n\n\tif (text == 0 ||\n\t\ttextStart == 0)\n\t{\n\t\treturn text;\n\t}\n\n\ttext_end = textStart + textSize;\n\n\tswitch (direction)\n\t{\n\n\tcase SEEK_CUR:\n\t\t{\n\t\t\tif (offset == 0)\n\t\t\t{\n\t\t\t\treturn text;\n\t\t\t}\n\t\t\telse if (offset > 0)\n\t\t\t{\n\t\t\t\treturn seeking_forward(text, text_end, textSize, offset);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn seeking_rewind(textStart, text, textSize, offset);\n\t\t\t}\n\n\t\t} break;\n\n\tcase SEEK_SET:\n\t\t{\n\t\t\tif (text < textStart)\n\t\t\t{\n\t\t\t\treturn text;\n\t\t\t}\n\n\t\t\treturn seeking_forward(textStart, text_end, textSize, offset);\n\n\t\t} break;\n\n\tcase SEEK_END:\n\t\treturn seeking_rewind(textStart, text_end, textSize, -offset);\n\n\tdefault:\n\t\treturn text;\n\n\t}\n}\n\nUTF8_API size_t utf8envlocale()\n{\n\t/*\n\t\tSources for locales and code pages\n\n\t\tWindows\n\t\thttps://msdn.microsoft.com/en-US/goglobal/bb896001.aspx\n\n\t\tPOSIX\n\t\thttps://www-01.ibm.com/support/knowledgecenter/ssw_aix_61/com.ibm.aix.nlsgdrf/support_languages_locales.htm\n\t*/\n\n#if WIN32 || _WINDOWS\n\t#define UTF8_LOCALE_CHECK(_name, _ansiCodepage, _oemCodepage) \\\n\t\t(codepage == _ansiCodepage || codepage == _oemCodepage)\n\n\t// Microsoft changed the name of the codepage member in VS2015.\n\n\t#if _MSC_VER >= 1800\n\t\t#define UTF8_CODEPAGE_GET(_locale)  ((__crt_locale_data_public*)(_locale)->locinfo)->_locale_lc_codepage\n\t#else\n\t\t#define UTF8_CODEPAGE_GET(_locale)  (_locale)->locinfo->lc_codepage\n\t#endif\n\n\tunsigned int codepage;\n\t_locale_t locale = _get_current_locale();\n\n\tif (locale == 0)\n\t{\n\t\treturn UTF8_LOCALE_DEFAULT;\n\t}\n\n\tcodepage = UTF8_CODEPAGE_GET(locale);\n#else\n\t#define UTF8_LOCALE_CHECK(_name, _ansiCodepage, _oemCodepage) \\\n\t\t!strncasecmp(locale, _name, 5)\n\n\tconst char* locale = setlocale(LC_ALL, 0);\n\tif (locale == 0)\n\t{\n\t\treturn UTF8_LOCALE_DEFAULT;\n\t}\n#endif\n\n\tif (UTF8_LOCALE_CHECK(\"lt_lt\", 1257, 775))\n\t{\n\t\treturn UTF8_LOCALE_LITHUANIAN;\n\t}\n\telse if (\n\t\tUTF8_LOCALE_CHECK(\"tr_tr\", 1254, 857) ||\n\t\tUTF8_LOCALE_CHECK(\"az_az\", 1254, 857))\n\t{\n\t\treturn UTF8_LOCALE_TURKISH_AND_AZERI_LATIN;\n\t}\n\n\treturn UTF8_LOCALE_DEFAULT;\n}\n\nsize_t utf8toupper(const char* input, size_t inputSize, char* target, size_t targetSize, size_t locale, int32_t* errors)\n{\n\tCaseMappingState state;\n\n\t/* Validate parameters */\n\n\tUTF8_VALIDATE_PARAMETERS_CHAR(char, 0);\n\n\t/* Initialize case mapping */\n\n\tif (!casemapping_initialize(\n\t\t&state,\n\t\tinput, inputSize,\n\t\ttarget, targetSize,\n\t\tUppercaseIndex1Ptr, UppercaseIndex2Ptr, UppercaseDataPtr,\n\t\tQuickCheckCaseMapped_Uppercase, locale,\n\t\terrors))\n\t{\n\t\treturn state.total_bytes_needed;\n\t}\n\n\t/* Execute case mapping as long as input remains */\n\n\twhile (state.src_size > 0)\n\t{\n\t\tsize_t converted;\n\n\t\tif ((converted = casemapping_execute(&state, errors)) == 0)\n\t\t{\n\t\t\treturn state.total_bytes_needed;\n\t\t}\n\n\t\tstate.total_bytes_needed += converted;\n\t}\n\n\tUTF8_SET_ERROR(NONE);\n\n\treturn state.total_bytes_needed;\n}\n\nsize_t utf8tolower(const char* input, size_t inputSize, char* target, size_t targetSize, size_t locale, int32_t* errors)\n{\n\tCaseMappingState state;\n\n\t/* Validate parameters */\n\n\tUTF8_VALIDATE_PARAMETERS_CHAR(char, 0);\n\n\t/* Initialize case mapping */\n\n\tif (!casemapping_initialize(\n\t\t&state,\n\t\tinput, inputSize,\n\t\ttarget, targetSize,\n\t\tLowercaseIndex1Ptr, LowercaseIndex2Ptr, LowercaseDataPtr,\n\t\tQuickCheckCaseMapped_Lowercase, locale,\n\t\terrors))\n\t{\n\t\treturn state.total_bytes_needed;\n\t}\n\n\t/* Execute case mapping as long as input remains */\n\n\twhile (state.src_size > 0)\n\t{\n\t\tsize_t converted;\n\n\t\tif ((converted = casemapping_execute(&state, errors)) == 0)\n\t\t{\n\t\t\treturn state.total_bytes_needed;\n\t\t}\n\n\t\tstate.total_bytes_needed += converted;\n\t}\n\n\tUTF8_SET_ERROR(NONE);\n\n\treturn state.total_bytes_needed;\n}\n\nsize_t utf8totitle(const char* input, size_t inputSize, char* target, size_t targetSize, size_t locale, int32_t* errors)\n{\n\tCaseMappingState state;\n\n\t/* Validate parameters */\n\n\tUTF8_VALIDATE_PARAMETERS_CHAR(char, 0);\n\n\t/* Initialize case mapping */\n\n\tif (!casemapping_initialize(\n\t\t&state,\n\t\tinput, inputSize,\n\t\ttarget, targetSize,\n\t\tTitlecaseIndex1Ptr, TitlecaseIndex2Ptr, TitlecaseDataPtr,\n\t\tQuickCheckCaseMapped_Titlecase, locale,\n\t\terrors))\n\t{\n\t\treturn state.total_bytes_needed;\n\t}\n\n\t/* Execute case mapping as long as input remains */\n\n\twhile (state.src_size > 0)\n\t{\n\t\tsize_t converted;\n\n\t\tif ((converted = casemapping_execute(&state, errors)) == 0)\n\t\t{\n\t\t\treturn state.total_bytes_needed;\n\t\t}\n\n\t\t/*\n\t\t\tThe first letter of every word should be titlecase, the rest should\n\t\t\tbe converted to lowercase.\n\t\t*/\n\n\t\tif (state.last_canonical_combining_class == CCC_NOT_REORDERED)\n\t\t{\n\t\t\tif (state.property_data == TitlecaseDataPtr)\n\t\t\t{\n\t\t\t\tif ((state.last_general_category & UTF8_CATEGORY_LETTER) != 0)\n\t\t\t\t{\n\t\t\t\t\tstate.property_index1 = LowercaseIndex1Ptr;\n\t\t\t\t\tstate.property_index2 = LowercaseIndex2Ptr;\n\t\t\t\t\tstate.property_data = LowercaseDataPtr;\n\n\t\t\t\t\tstate.quickcheck_flags = QuickCheckCaseMapped_Lowercase;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (\n\t\t\t\t(state.last_general_category & UTF8_CATEGORY_LETTER) == 0)\n\t\t\t{\n\t\t\t\tstate.property_index1 = TitlecaseIndex1Ptr;\n\t\t\t\tstate.property_index2 = TitlecaseIndex2Ptr;\n\t\t\t\tstate.property_data = TitlecaseDataPtr;\n\n\t\t\t\tstate.quickcheck_flags = QuickCheckCaseMapped_Titlecase;\n\t\t\t}\n\t\t}\n\n\t\tstate.total_bytes_needed += converted;\n\t}\n\n\tUTF8_SET_ERROR(NONE);\n\n\treturn state.total_bytes_needed;\n}\n\nsize_t utf8casefold(const char* input, size_t inputSize, char* target, size_t targetSize, size_t locale, int32_t* errors)\n{\n\tCaseMappingState state;\n\n\t/* Validate parameters */\n\n\tUTF8_VALIDATE_PARAMETERS_CHAR(char, 0);\n\n\t/* Initialize case mapping */\n\n\tif (!casemapping_initialize(\n\t\t&state,\n\t\tinput, inputSize,\n\t\ttarget, targetSize,\n\t\tCaseFoldingIndex1Ptr, CaseFoldingIndex2Ptr, CaseFoldingDataPtr,\n\t\tQuickCheckCaseMapped_Casefolded, locale,\n\t\terrors))\n\t{\n\t\treturn state.total_bytes_needed;\n\t}\n\n\tif (state.locale == UTF8_LOCALE_TURKISH_AND_AZERI_LATIN)\n\t{\n\t\t/* Exceptional behavior for Turkish and Azerbaijani (Latin) locales */\n\n\t\twhile (state.src_size > 0)\n\t\t{\n\t\t\tconst char* resolved = 0;\n\t\t\tuint8_t bytes_needed = 0;\n\n\t\t\t/* Read next code point */\n\n\t\t\tif (state.last_code_point_size = codepoint_read(state.src, state.src_size, &state.last_code_point), state.last_code_point_size)\n\t\t\t{\n\t\t\t\tgoto invaliddata;\n\t\t\t}\n\n\t\t\t/* Move source cursor */\n\n\t\t\tif (state.src_size >= state.last_code_point_size)\n\t\t\t{\n\t\t\t\tstate.src += state.last_code_point_size;\n\t\t\t\tstate.src_size -= state.last_code_point_size;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstate.src_size = 0;\n\t\t\t}\n\n\t\t\t/* Resolve case folding */\n\n\t\t\tif ((PROPERTY_GET_CM(state.last_code_point) & QuickCheckCaseMapped_Casefolded) != 0)\n\t\t\t{\n\t\t\t\tif (state.last_code_point == CP_LATIN_CAPITAL_LETTER_I)\n\t\t\t\t{\n\t\t\t\t\tresolved = \"\\xC4\\xB1\";\n\t\t\t\t\tbytes_needed = 2;\n\t\t\t\t}\n\t\t\t\telse if (\n\t\t\t\t\tstate.last_code_point == CP_LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE)\n\t\t\t\t{\n\t\t\t\t\tresolved = \"i\";\n\t\t\t\t\tbytes_needed = 1;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tresolved = database_querydecomposition(state.last_code_point, state.property_index1, state.property_index2, state.property_data, &bytes_needed);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* Write to output */\n\n\t\t\tif (resolved != 0)\n\t\t\t{\n\t\t\t\t/* Write resolved string to output */\n\n\t\t\t\tif (state.dst != 0)\n\t\t\t\t{\n\t\t\t\t\tif (state.dst_size < bytes_needed)\n\t\t\t\t\t{\n\t\t\t\t\t\tgoto outofspace;\n\t\t\t\t\t}\n\n\t\t\t\t\tmemcpy(state.dst, resolved, bytes_needed);\n\n\t\t\t\t\tstate.dst += bytes_needed;\n\t\t\t\t\tstate.dst_size -= bytes_needed;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* Write code point unchanged to output */\n\n\t\t\t\tif (bytes_needed = codepoint_write(state.last_code_point, &state.dst, &state.dst_size), !bytes_needed)\n\t\t\t\t{\n\t\t\t\t\tgoto outofspace;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstate.total_bytes_needed += bytes_needed;\n\t\t}\n\t}\n\telse\n\t{\n\t\t/* Execute case mapping as long as input remains */\n\n\t\twhile (state.src_size > 0)\n\t\t{\n\t\t\tconst char* resolved = 0;\n\t\t\tuint8_t bytes_needed = 0;\n\n\t\t\t/* Read next code point */\n\n\t\t\tif (state.last_code_point_size = codepoint_read(state.src, state.src_size, &state.last_code_point), state.last_code_point_size)\n\t\t\t{\n\t\t\t\tgoto invaliddata;\n\t\t\t}\n\n\t\t\t/* Move source cursor */\n\n\t\t\tif (state.src_size >= state.last_code_point_size)\n\t\t\t{\n\t\t\t\tstate.src += state.last_code_point_size;\n\t\t\t\tstate.src_size -= state.last_code_point_size;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstate.src_size = 0;\n\t\t\t}\n\n\t\t\t/* Resolve case folding */\n\n\t\t\tif ((PROPERTY_GET_CM(state.last_code_point) & QuickCheckCaseMapped_Casefolded) != 0)\n\t\t\t{\n\t\t\t\tresolved = database_querydecomposition(state.last_code_point, state.property_index1, state.property_index2, state.property_data, &bytes_needed);\n\t\t\t}\n\n\t\t\tif (resolved != 0)\n\t\t\t{\n\t\t\t\t/* Write resolved string to output */\n\n\t\t\t\tif (state.dst != 0)\n\t\t\t\t{\n\t\t\t\t\tif (state.dst_size < bytes_needed)\n\t\t\t\t\t{\n\t\t\t\t\t\tgoto outofspace;\n\t\t\t\t\t}\n\n\t\t\t\t\tmemcpy(state.dst, resolved, bytes_needed);\n\n\t\t\t\t\tstate.dst += bytes_needed;\n\t\t\t\t\tstate.dst_size -= bytes_needed;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* Write code point unchanged to output */\n\n\t\t\t\tif (bytes_needed = codepoint_write(state.last_code_point, &state.dst, &state.dst_size), bytes_needed)\n\t\t\t\t{\n\t\t\t\t\tgoto outofspace;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstate.total_bytes_needed += bytes_needed;\n\t\t}\n\t}\n\n\tUTF8_SET_ERROR(NONE);\n\n\treturn state.total_bytes_needed;\n\ninvaliddata:\n\tUTF8_SET_ERROR(INVALID_DATA);\n\n\treturn state.total_bytes_needed;\n\noutofspace:\n\tUTF8_SET_ERROR(NOT_ENOUGH_SPACE);\n\n\treturn state.total_bytes_needed;\n}\n\nuint8_t utf8isnormalized(const char* input, size_t inputSize, size_t flags, size_t* offset)\n{\n\tconst char* src = input;\n\tsize_t src_size = inputSize;\n\tuint8_t last_canonical_class = CCC_NOT_REORDERED;\n\tsize_t found_offset = 0;\n\tuint8_t result = UTF8_NORMALIZATION_RESULT_YES;\n\tunicode_t decoded;\n\tuint8_t canonical_class;\n\tuint8_t quick_check;\n\tconst size_t* property_index;\n\tconst uint8_t* property_data;\n\n\t/* Validate input and flags */\n\n\tif (input == NULL ||\n\t\tinputSize == 0 ||\n\t\t(flags & (UTF8_NORMALIZE_DECOMPOSE | UTF8_NORMALIZE_COMPOSE)) == 0)\n\t{\n\t\tgoto end;\n\t}\n\n\t/* Get properties */\n\n\tif ((flags & UTF8_NORMALIZE_COMPOSE) != 0)\n\t{\n\t\tif ((flags & UTF8_NORMALIZE_COMPATIBILITY) != 0)\n\t\t{\n\t\t\tproperty_index = QuickCheckNFKCIndexPtr;\n\t\t\tproperty_data = QuickCheckNFKCDataPtr;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tproperty_index = QuickCheckNFCIndexPtr;\n\t\t\tproperty_data = QuickCheckNFCDataPtr;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif ((flags & UTF8_NORMALIZE_COMPATIBILITY) != 0)\n\t\t{\n\t\t\tproperty_index = QuickCheckNFKDIndexPtr;\n\t\t\tproperty_data = QuickCheckNFKDDataPtr;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tproperty_index = QuickCheckNFDIndexPtr;\n\t\t\tproperty_data = QuickCheckNFDDataPtr;\n\t\t}\n\t}\n\n\t/* Process input */\n\n\twhile (src_size > 0)\n\t{\n\t\t/* Read codepoint at cursor */\n\n\t\tuint8_t read = codepoint_read(src, src_size, &decoded);\n\t\tif (read == 0)\n\t\t{\n\t\t\tbreak;\n\t\t}\n\n\t\t/* Get canonical combining class and quick check value */\n\n\t\tcanonical_class = PROPERTY_GET_CCC(decoded);\n\t\tquick_check = PROPERTY_GET(property_index, property_data, decoded);\n\n\t\t/* Compare CCC to previous CCC */\n\n\t\tif (last_canonical_class > canonical_class &&\n\t\t\tcanonical_class > CCC_NOT_REORDERED)\n\t\t{\n\t\t\tresult = UTF8_NORMALIZATION_RESULT_NO;\n\n\t\t\tbreak;\n\t\t}\n\n\t\t/* Compare quick check value */\n\n\t\tif (quick_check == QuickCheckResult_No)\n\t\t{\n\t\t\tresult = UTF8_NORMALIZATION_RESULT_NO;\n\n\t\t\tbreak;\n\t\t}\n\t\telse if (\n\t\t\tquick_check == QuickCheckResult_Maybe)\n\t\t{\n\t\t\tresult = UTF8_NORMALIZATION_RESULT_MAYBE;\n\t\t}\n\n\t\t/* Append to offset */\n\n\t\tif (result != UTF8_NORMALIZATION_RESULT_MAYBE)\n\t\t{\n\t\t\tfound_offset += read;\n\t\t}\n\n\t\tlast_canonical_class = canonical_class;\n\n\t\tsrc += read;\n\t\tsrc_size -= read;\n\t}\n\nend:\n\tif (offset != 0)\n\t{\n\t\t*offset = found_offset;\n\t}\n\treturn result;\n}\n\nsize_t utf8normalize(const char* input, size_t inputSize, char* target, size_t targetSize, size_t flags, int32_t* errors)\n{\n\tchar* dst = target;\n\tsize_t dst_size = targetSize;\n\tStreamState stream[4];\n\tDecomposeState decompose_state;\n\tComposeState compose_state = { 0 };\n\tuint8_t compatibility = (flags & UTF8_NORMALIZE_COMPATIBILITY) != 0;\n\tStreamState* stream_output;\n\tuint8_t finished = 0;\n\tsize_t bytes_written = 0;\n\n\t/*\n\t\tDecomposition uses the following process:\n\n\t\tinput         -->  stream[0]  -->\n\t\t(decompose)   -->  stream[1]  -->\n\t\t(accumulate)  -->  stream[2]  -->\n\t\toutput\n\n\t\tThe accumulation step is necessary in order to prevent buffer overflow\n\t\tattacks.\n\n\t\tComposition adds another stream buffer:\n\n\t\tinput         --> stream[0]  -->\n\t\t(decompose)   --> stream[1]  -->\n\t\t(accumulate)  --> stream[2]  -->\n\t\t(compose)     --> stream[3]  -->\n\t\toutput\n\n\t\tAlthough four streaming buffers may seem excessive, they are necessary\n\t\tfor preventing allocations on the heap.\n\t*/\n\n\t/* Check for valid flags */\n\n\tif ((flags & (UTF8_NORMALIZE_DECOMPOSE | UTF8_NORMALIZE_COMPOSE)) == 0)\n\t{\n\t\tUTF8_SET_ERROR(INVALID_FLAG);\n\n\t\treturn bytes_written;\n\t}\n\n\t/* Validate parameters */\n\n\tUTF8_VALIDATE_PARAMETERS_CHAR(char, bytes_written);\n\n\t/* Initialize decomposition */\n\n\tmemset(stream, 0, sizeof(stream));\n\n\tif (!stream_initialize(&stream[0], input, inputSize) ||\n\t\t!decompose_initialize(&decompose_state, &stream[0], &stream[1], compatibility))\n\t{\n\t\tUTF8_SET_ERROR(INVALID_DATA);\n\n\t\treturn bytes_written;\n\t}\n\n\tstream_output = &stream[2];\n\n\tif ((flags & UTF8_NORMALIZE_COMPOSE) != 0)\n\t{\n\t\t/* Initialize composition */\n\n\t\tif (!compose_initialize(&compose_state, &stream[2], &stream[3], compatibility))\n\t\t{\n\t\t\tUTF8_SET_ERROR(INVALID_DATA);\n\n\t\t\treturn bytes_written;\n\t\t}\n\n\t\tstream_output = &stream[3];\n\t}\n\n\tdo\n\t{\n\t\tuint8_t write = 0;\n\n\t\t/* Accumulate decomposed input in next stream */\n\n\t\tif (stream[1].current > 0)\n\t\t{\n\t\t\tunicode_t* src_codepoint = stream[1].codepoint;\n\t\t\tunicode_t* dst_codepoint = stream[2].codepoint + stream[2].filled;\n\t\t\tuint8_t* src_qc = stream[1].quick_check;\n\t\t\tuint8_t* dst_qc = stream[2].quick_check + stream[2].filled;\n\t\t\tuint8_t* src_ccc = stream[1].canonical_combining_class;\n\t\t\tuint8_t* dst_ccc = stream[2].canonical_combining_class + stream[2].filled;\n\n\t\t\tif ((flags & UTF8_NORMALIZE_COMPOSE) != 0)\n\t\t\t{\n\t\t\t\tuint8_t i;\n\n\t\t\t\t/* Update stream properties to use composition values */\n\n\t\t\t\tfor (i = 0; i < stream[1].current; ++i)\n\t\t\t\t{\n\t\t\t\t\t*dst_qc++ = PROPERTY_GET(compose_state.qc_index, compose_state.qc_data, *src_codepoint);\n\t\t\t\t\t*dst_ccc++ = *src_ccc++;\n\t\t\t\t\t*dst_codepoint++ = *src_codepoint++;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* Copy directly */\n\n\t\t\t\tmemcpy(dst_codepoint, src_codepoint, stream[1].current * sizeof(unicode_t));\n\t\t\t\tmemcpy(dst_qc, src_qc, stream[1].current * sizeof(uint8_t));\n\t\t\t\tmemcpy(dst_ccc, src_ccc, stream[1].current * sizeof(uint8_t));\n\t\t\t}\n\n\t\t\tstream[2].current += stream[1].current;\n\t\t\tstream[2].filled += stream[1].current;\n\t\t}\n\n\t\t/* Decompose input sequence into next stream */\n\n\t\tfinished = !decompose_execute(&decompose_state);\n\t\tif (!finished)\n\t\t{\n\t\t\t/* Output current stream it it could overflow accumulation buffer */\n\n\t\t\twrite = (stream[1].current + stream[2].filled) >= STREAM_SAFE_MAX;\n\t\t}\n\n\t\t/* Reorder potentially unordered decomposed stream */\n\n\t\tif (!stream[1].stable)\n\t\t{\n\t\t\tstream_reorder(&stream[1]);\n\t\t}\n\n\t\t/* Write stream to output when overflowing or when accumulation buffer is empty*/\n\n\t\tif (write ||\n\t\t\tfinished)\n\t\t{\n\t\t\tuint8_t i;\n\n\t\t\t/* Compose accumulation buffer */\n\n\t\t\tif ((flags & UTF8_NORMALIZE_COMPOSE) != 0 &&\n\t\t\t\t!compose_execute(&compose_state))\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/* Write to output buffer */\n\n\t\t\tfor (i = 0; i < stream_output->current; ++i)\n\t\t\t{\n\t\t\t\tuint8_t encoded_size = codepoint_write(stream_output->codepoint[i], &dst, &dst_size);\n\t\t\t\tif (encoded_size == 0)\n\t\t\t\t{\n\t\t\t\t\tUTF8_SET_ERROR(NOT_ENOUGH_SPACE);\n\n\t\t\t\t\treturn bytes_written;\n\t\t\t\t}\n\n\t\t\t\tbytes_written += encoded_size;\n\t\t\t}\n\n\t\t\t/* Reset accumulation buffer */\n\n\t\t\tstream[2].current = 0;\n\t\t\tstream[2].filled = 0;\n\t\t}\n\t}\n\twhile (!finished);\n\n\tUTF8_SET_ERROR(NONE);\n\n\treturn bytes_written;\n}\n\nsize_t utf8iscategory(const char* input, size_t inputSize, size_t flags)\n{\n\tconst char* src = input;\n\tsize_t src_size = inputSize;\n\n\tif (input == 0 ||\n\t\tinputSize == 0)\n\t{\n\t\treturn 0;\n\t}\n\n\twhile (src_size > 0)\n\t{\n\t\tunicode_t code_point;\n\t\tuint32_t general_category;\n\t\tuint8_t canonical_combining_class;\n\t\tuint8_t offset;\n\n\t\t/* Compatibility fixes */\n\n\t\tif ((flags & UTF8_CATEGORY_COMPATIBILITY) != 0 &&\n\t\t\t*src < MAX_BASIC_LATIN)\n\t\t{\n\t\t\tif (flags == UTF8_CATEGORY_ISBLANK)\n\t\t\t{\n\t\t\t\tif (*src == 0x09)\n\t\t\t\t{\n\t\t\t\t\t/* CHARACTER TABULATION */\n\n\t\t\t\t\tsrc++;\n\t\t\t\t\tsrc_size--;\n\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telse if (\n\t\t\t\t\t*src == 0x20)\n\t\t\t\t{\n\t\t\t\t\t/* SPACE */\n\n\t\t\t\t\tsrc++;\n\t\t\t\t\tsrc_size--;\n\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (\n\t\t\t\tflags == UTF8_CATEGORY_ISSPACE)\n\t\t\t{\n\t\t\t\tif (*src < 0x09 ||\n\t\t\t\t\t*src > 0x20)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\telse if (\n\t\t\t\t\t*src <= 0x0D)\n\t\t\t\t{\n\t\t\t\t\t/* CHARACTER TABULATION ... CARRIAGE RETURN (CR) */\n\n\t\t\t\t\tsrc++;\n\t\t\t\t\tsrc_size--;\n\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telse if (\n\t\t\t\t\t*src == 0x20)\n\t\t\t\t{\n\t\t\t\t\t/* SPACE */\n\n\t\t\t\t\tsrc++;\n\t\t\t\t\tsrc_size--;\n\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (\n\t\t\t\tflags == UTF8_CATEGORY_ISXDIGIT)\n\t\t\t{\n\t\t\t\tif (*src < 0x30 ||\n\t\t\t\t\t*src > 0x66)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\telse if (\n\t\t\t\t\t*src <= 0x39)\n\t\t\t\t{\n\t\t\t\t\t/* DIGIT ZERO ... DIGIT NINE */\n\n\t\t\t\t\tsrc++;\n\t\t\t\t\tsrc_size--;\n\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telse if (\n\t\t\t\t\t*src >= 0x41 &&\n\t\t\t\t\t*src <= 0x46)\n\t\t\t\t{\n\t\t\t\t\t/* LATIN CAPITAL LETTER A ... LATIN CAPITAL LETTER F */\n\n\t\t\t\t\tsrc++;\n\t\t\t\t\tsrc_size--;\n\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telse if (\n\t\t\t\t\t*src >= 0x61)\n\t\t\t\t{\n\t\t\t\t\t/* LATIN SMALL LETTER A ... LATIN SMALL LETTER F */\n\n\t\t\t\t\tsrc++;\n\t\t\t\t\tsrc_size--;\n\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Read next code point */\n\n\t\toffset = codepoint_read(src, src_size, &code_point);\n\n\t\t/* Match General Category against flags */\n\n\t\tgeneral_category = PROPERTY_GET_GC(code_point);\n\t\tif ((general_category & flags) == 0 &&\n\t\t\t/* Check for the start of the next grapheme cluster */\n\t\t\t((flags & UTF8_CATEGORY_IGNORE_GRAPHEME_CLUSTER) != 0 || (canonical_combining_class = PROPERTY_GET_CCC(code_point)) == CCC_NOT_REORDERED))\n\t\t{\n\t\t\tbreak;\n\t\t}\n\n\t\t/* Move source cursor */\n\n\t\tif (offset > src_size)\n\t\t{\n\t\t\tbreak;\n\t\t}\n\n\t\tsrc += offset;\n\t\tsrc_size -= offset;\n\t}\n\n\treturn src - input;\n}\n"
  },
  {
    "path": "issues.md",
    "content": "# Issues\n\nNote: this is just a personal log of outstanding issues, shorter rants/ramblings, and a changelog that doesn't need me to scroll through git.\n\n\n## FEATURES TO IMPLEMENT\n\n2. Destructors for classes\n\n\n5. String operators\n\n\n6. Location information for type specifiers in definitions\n\n\n7. 'cases' member of enums to enable runtime enumeration of... the enumeration.\n\n\n8. Operator overloading for assignment and subscript/slice\n\n\n14. Multi-dimensional arrays, as opposed to our current 'array-of-arrays' approach\n\teg. index with `foo[a, b, c]` instead of `foo[a][b][c]`\n\n\n16. `[[noreturn]]` for functions, so we don't error when no value is returned (eg. when calling `abort()`)\n\n\n18. Some way of handling both types and expressions in `sizeof`/`typeid`/`typeof`. Might work if we just check for identifiers, but then\n\twhat about polymorphic types? Those won't even parse as expressions.\n\n\n-----\n\n\n## THINGS TO FIX\n\n2. There are still some instances where we explicitly 'initialise' a class equivalent to `memset(0)` -- see *THINGS TO NOTE* below.\n\n\n\n------\n\n\n## THINGS TO INVESTIGATE\n\n* ### Possibly allow struct-constructors to init transparent fields\n\n\n* ### Errors need to propagate better\n\tRight now with the newly-implemented `PrettyError` system, we can propagate a lot more information upwards, and with the new thing of throwing an\n\terror when we unwrap a `TCResult`, there's less need to be explicit when handling errors during typechecking.\n\n\tUnfortunately, for a simple failed generic function instantiation, we get a mess like this:\n\t```\n\t(supertiny.flx:159:37) Error: No such function named 'foo' (in scope 'supertiny.main().__anon_scope_0')\n\t\tlet k = foo<T: int, G: str>(10, 20)\n\t\t\t\t\t\t\t\t^\n\t(supertiny.flx:159:37) Error: No viable candidates in attempted instantiation of parametric entity 'foo'; candidates are:\n\t\tlet k = foo<T: int, G: str>(10, 20)\n\t\t\t\t\t\t\t\t^\n\t(supertiny.flx:159:37) Error: Parametric entity 'foo' does not have an argument 'G'\n\t\tlet k = foo<T: int, G: str>(10, 20)\n\t\t\t\t\t\t\t\t^\n\t(supertiny.flx:157:13) Note: 'foo' was defined here:\n\t\tfn foo<T>(a: T, b: T) -> T { return a + b }\n\t```\n\n\tWhich is counter to our goal of having readable error messages even in the face of failed template instantiations (looking at you, C++)\n\n\tPossibly we need more 'kinds' of errors, where we can have boilerplate prefixes like `Candidate not suitable: <bla bla>`, rather than cascading\n\tmultiple errors (most of them should be `info` anyway, and not errors), and also the possiblity of just posting text without the `Error`/`Warning` etc\n\tprefix. Also, we should be able to control the context-printing of each of those as well.\n\n\n\n* ### Certain cases we still allow a zeroinitialised class to exist:\n\tA. When growing a dynamic array, the new elements are zeroinitialised instead of having a value set (for non-class types, they get their default value)\n\tB. When initialising a field in a struct, if not explicitly assigned to it is left as it is -- which should be the zeroinitialiser\n\tC. When initialising a field in a class without an inline initialiser, we explicitly set it to 0.\n\n\tWe either document this properly, or change the behaviour. I don't really want to devolve into the C++ style of forcing super-explicit initialiser\n\tsyntax. However, we can enforce setting a value by forcing an inline initialiser for classes.\n\n\tFor structs, we have 2 options -- 1: screw it, just make a zeroinit class if they appear in a struct; 2: only allow initialising structs with\n\tconstructers that specify a value for any class types.\n\n\tFor the former, I'm more inclined to do that, but the latter is more 'correct', as it were. Unfortunately, that would also mean disallowing\n\t`var foo: SomeStruct` without an initialiser...\n\n\n\n* ### Some kind of construct to make a variable immutable beyond a certain point\n\tthus you could have arbitrarily complex initialisation code,\n\tthen have the compiler enforce that your variable is immutable after that point, eg:\n\n\t```\n\t\tvar k = ...\n\t\tif(some_cond1)  k = get_value()\n\t\telse            k = get_other_value()\n\n\t\tk.mutating_func()\n\n\t\tmake_immutable(k)\n\n\t\tk = ...      // will not compile\n\t```\n\n\n* ### Type inference for single-expr functions? It's a little weird to have two arrows like this:\n\t`fn foo(a: T) -> T => a * a`\n\n\tThe type inference would require some re-working though, because to generate the declaration of the function we need the return type, but to\n\tget the return type in this situation we need to typecheck the function body. Albeit it's a single expression, there might still be\n\tunresolved or unresolvable things inside the body.\n\n\tPossibly investigate whether we can do the typechecking in the generateDecl function?? But it's highly likely we separated those for a reason,\n\tso I don't think it's doable at this point.\n\n\tIt's not really a high-priority thing anyway.\n\n\n* ### wrt. optional arguments\n\tyou *must* refer to it by name to specify a value. For example:\n\n\t`fn foo(a: int, b: int = 3) => ...`\n\n\t```\n\t// valid combinations:\n\tfoo(30)\n\tfoo(a: 30)\n\tfoo(30, b: 5)\n\tfoo(a: 30, b: 1)\n\n\t// invalid combinations:\n\tfoo(a: 30, 1)\t\t<-- cannot have positional arguments after named ones\n\tfoo(30, 7)\t\t\t<-- must name the optional argument 'b'\n\n\t```\n\n\n* https://proandroiddev.com/understanding-generics-and-variance-in-kotlin-714c14564c47\n\thttps://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)\n\n\n\n* Arguments-after-varargs (see https://youtu.be/mGe5d6dPHAU?t=1379)\n\tBasically, allow passing named parameters after var-args.\n\n\n* Optimisation: use interned strings for comparison (and for use as keys in all the hashmaps we have), hopefully allowing a large-ish speedup since\n\t(according to historical profiles) `std::string`-related things are the cause of a lot of slowdowns.\n\n\n\n* Right now we design the `any` type to not handle refcounted types at all -- meaning it doesn't touch the refcount of those, and thus\n\tthe `any` can outlive the referred-to value.\n\n\tTo change this, `any` itself would need to be refcounted, but then we'd need to be able to check whether something was refcounted\n\t** AT RUNTIME **, which is a whole bucket of shit I don't want to deal with yet.\n\n\tSo for now, we are documenting that `any` does not care about reference counting, and deal with it later.\n\n\n\n* A similar issue with refcounting for casting, though i'm not entirely sure if this is a real issue or just something that i'm imagining.\n\n\tSo, when we assign something `x = y`, then it is necessary that the types of `x` and `y` are the same. Then, if the type in question is a\n\treference counted type, we do some `autoAssignRefCountedValue()`, that does separate things for lvalues and rvalues. If the right-hand side\n\tis an lvalue, then we increment its reference count; else, we perform a 'move' of the rvalue by removing it from the reference-counting stack.\n\n\tThe problem comes when we need to cast `y` to the type of `x`. If we had to do a cast, that means that we transform the (potential) rhs-lvalue into\n\tan rvalue. This means that, if the rhs was originally an lvalue, we would try to remove the output of the casting op from the refcounting stack,\n\twhich it doesn't exist in.\n\n\tSo, we will add the output of the casting op to the refcounting list, if the output type is reference counted. The issue comes with how we handle\n\tthe reference count of the *original* rhs.\n\n\tThe potential cases that I can think of where we might get some trouble involves `any`:\n\n\t```rust\n\tlet x = string(\"hello\")\n\tlet b: any = x\n\t```\n\n\tIn this case, `x` is an lvalue that gets casted to an rvalue of type `any`. In the assignment, we remove the casted rvalue from the rc-stack,\n\t(assuming we implement the fix above), then just do the store.\n\n\t```rust\n\tlet x: any = string(\"world\")\n\tlet y = x as string\n\t```\n\n\tIn this case, it's a similar thing; if we apply the mentioned fix, I don't *see* any issues...\n\n\tTODO: actually investigate this properly.\n\n-----\n\n\n\n\n\n## POLYMORPHIC PIPELINE DOCUMENTATION\n\nSo, this thing serves as the shitty documentation for how the generic pipeline works for future implementations.\n\n1. When AST nodes are typechecked at the top level, if they are polymorphic things they will refuse to be checked,\n\tand won't return a result (`ast::Block` does the same check), but instead add themselves to a list of pending,\n\tuninstantiated generic types in the `sst::StateTree`.\n\n2. When resolving a reference (function call or identifier), we check the pending generic list if we can't find any\n\tnormal things that match (or if we already have some explicit mappings). If there is a match, we call into\n\t`attemptToDisambiguateGenericReference()` with whatever information we have (eg. partial solutions)\n\n3. We call `inferTypesForGenericEntity` which is the main solver function that infers types for the type arguments\n\tthat are missing. This just acts like a black box for the most part.\n\n4. If we find that we're actually a reference to a function (ie. we act like a function pointer instead of a call) then\n\twe do a thing called `fillGenericTypeWithPlaceholders` which puts in fake 'solutions' for each type argument (aka\n\t`fir::PolyPlaceholderType`), and proceeds to return it.\n\n5. We will then allow that to typecheck. For now, only functions can have placeholder types, so we special-case that in\n\tfunction typechecking by just skipping the body typecheck when we have placeholders.\n\n6. Once we manage to solve everything -- ie. get rid of all the placeholder types, we need to re-typecheck the original definition\n\twith proper filled in types. This happens in `resolveFunctionCall`.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "libs/OpenGL/GL.flx",
    "content": "// GL.flx\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\npublic enum GL: u32\n{\n\tcase FALSE                                        = 0\n\tcase TRUE                                         = 1\n\tcase BYTE                                         = 0x1400\n\tcase UNSIGNED_BYTE                                = 0x1401\n\tcase SHORT                                        = 0x1402\n\tcase UNSIGNED_SHORT                               = 0x1403\n\tcase INT                                          = 0x1404\n\tcase UNSIGNED_INT                                 = 0x1405\n\tcase FLOAT                                        = 0x1406\n\tcase TWO_BYTES                                    = 0x1407\n\tcase THREE_BYTES                                  = 0x1408\n\tcase FOUR_BYTES                                   = 0x1409\n\tcase DOUBLE                                       = 0x140A\n\tcase POINTS                                       = 0x0000\n\tcase LINES                                        = 0x0001\n\tcase LINE_LOOP                                    = 0x0002\n\tcase LINE_STRIP                                   = 0x0003\n\tcase TRIANGLES                                    = 0x0004\n\tcase TRIANGLE_STRIP                               = 0x0005\n\tcase TRIANGLE_FAN                                 = 0x0006\n\tcase QUADS                                        = 0x0007\n\tcase QUAD_STRIP                                   = 0x0008\n\tcase POLYGON                                      = 0x0009\n\tcase VERTEX_ARRAY                                 = 0x8074\n\tcase NORMAL_ARRAY                                 = 0x8075\n\tcase COLOR_ARRAY                                  = 0x8076\n\tcase INDEX_ARRAY                                  = 0x8077\n\tcase TEXTURE_COORD_ARRAY                          = 0x8078\n\tcase EDGE_FLAG_ARRAY                              = 0x8079\n\tcase VERTEX_ARRAY_SIZE                            = 0x807A\n\tcase VERTEX_ARRAY_TYPE                            = 0x807B\n\tcase VERTEX_ARRAY_STRIDE                          = 0x807C\n\tcase NORMAL_ARRAY_TYPE                            = 0x807E\n\tcase NORMAL_ARRAY_STRIDE                          = 0x807F\n\tcase COLOR_ARRAY_SIZE                             = 0x8081\n\tcase COLOR_ARRAY_TYPE                             = 0x8082\n\tcase COLOR_ARRAY_STRIDE                           = 0x8083\n\tcase INDEX_ARRAY_TYPE                             = 0x8085\n\tcase INDEX_ARRAY_STRIDE                           = 0x8086\n\tcase TEXTURE_COORD_ARRAY_SIZE                     = 0x8088\n\tcase TEXTURE_COORD_ARRAY_TYPE                     = 0x8089\n\tcase TEXTURE_COORD_ARRAY_STRIDE                   = 0x808A\n\tcase EDGE_FLAG_ARRAY_STRIDE                       = 0x808C\n\tcase VERTEX_ARRAY_POINTER                         = 0x808E\n\tcase NORMAL_ARRAY_POINTER                         = 0x808F\n\tcase COLOR_ARRAY_POINTER                          = 0x8090\n\tcase INDEX_ARRAY_POINTER                          = 0x8091\n\tcase TEXTURE_COORD_ARRAY_POINTER                  = 0x8092\n\tcase EDGE_FLAG_ARRAY_POINTER                      = 0x8093\n\tcase V2F                                          = 0x2A20\n\tcase V3F                                          = 0x2A21\n\tcase C4UB_V2F                                     = 0x2A22\n\tcase C4UB_V3F                                     = 0x2A23\n\tcase C3F_V3F                                      = 0x2A24\n\tcase N3F_V3F                                      = 0x2A25\n\tcase C4F_N3F_V3F                                  = 0x2A26\n\tcase T2F_V3F                                      = 0x2A27\n\tcase T4F_V4F                                      = 0x2A28\n\tcase T2F_C4UB_V3F                                 = 0x2A29\n\tcase T2F_C3F_V3F                                  = 0x2A2A\n\tcase T2F_N3F_V3F                                  = 0x2A2B\n\tcase T2F_C4F_N3F_V3F                              = 0x2A2C\n\tcase T4F_C4F_N3F_V4F                              = 0x2A2D\n\tcase MATRIX_MODE                                  = 0x0BA0\n\tcase MODELVIEW                                    = 0x1700\n\tcase PROJECTION                                   = 0x1701\n\tcase TEXTURE                                      = 0x1702\n\tcase POINT_SMOOTH                                 = 0x0B10\n\tcase POINT_SIZE                                   = 0x0B11\n\tcase POINT_SIZE_GRANULARITY                       = 0x0B13\n\tcase POINT_SIZE_RANGE                             = 0x0B12\n\tcase LINE_SMOOTH                                  = 0x0B20\n\tcase LINE_STIPPLE                                 = 0x0B24\n\tcase LINE_STIPPLE_PATTERN                         = 0x0B25\n\tcase LINE_STIPPLE_REPEAT                          = 0x0B26\n\tcase LINE_WIDTH                                   = 0x0B21\n\tcase LINE_WIDTH_GRANULARITY                       = 0x0B23\n\tcase LINE_WIDTH_RANGE                             = 0x0B22\n\tcase POINT                                        = 0x1B00\n\tcase LINE                                         = 0x1B01\n\tcase FILL                                         = 0x1B02\n\tcase CW                                           = 0x0900\n\tcase CCW                                          = 0x0901\n\tcase FRONT                                        = 0x0404\n\tcase BACK                                         = 0x0405\n\tcase POLYGON_MODE                                 = 0x0B40\n\tcase POLYGON_SMOOTH                               = 0x0B41\n\tcase POLYGON_STIPPLE                              = 0x0B42\n\tcase EDGE_FLAG                                    = 0x0B43\n\tcase CULL_FACE                                    = 0x0B44\n\tcase CULL_FACE_MODE                               = 0x0B45\n\tcase FRONT_FACE                                   = 0x0B46\n\tcase POLYGON_OFFSET_FACTOR                        = 0x8038\n\tcase POLYGON_OFFSET_UNITS                         = 0x2A00\n\tcase POLYGON_OFFSET_POINT                         = 0x2A01\n\tcase POLYGON_OFFSET_LINE                          = 0x2A02\n\tcase POLYGON_OFFSET_FILL                          = 0x8037\n\tcase COMPILE                                      = 0x1300\n\tcase COMPILE_AND_EXECUTE                          = 0x1301\n\tcase LIST_BASE                                    = 0x0B32\n\tcase LIST_INDEX                                   = 0x0B33\n\tcase LIST_MODE                                    = 0x0B30\n\tcase NEVER                                        = 0x0200\n\tcase LESS                                         = 0x0201\n\tcase EQUAL                                        = 0x0202\n\tcase LEQUAL                                       = 0x0203\n\tcase GREATER                                      = 0x0204\n\tcase NOTEQUAL                                     = 0x0205\n\tcase GEQUAL                                       = 0x0206\n\tcase ALWAYS                                       = 0x0207\n\tcase DEPTH_TEST                                   = 0x0B71\n\tcase DEPTH_BITS                                   = 0x0D56\n\tcase DEPTH_CLEAR_VALUE                            = 0x0B73\n\tcase DEPTH_FUNC                                   = 0x0B74\n\tcase DEPTH_RANGE                                  = 0x0B70\n\tcase DEPTH_WRITEMASK                              = 0x0B72\n\tcase DEPTH_COMPONENT                              = 0x1902\n\tcase LIGHTING                                     = 0x0B50\n\tcase LIGHT0                                       = 0x4000\n\tcase LIGHT1                                       = 0x4001\n\tcase LIGHT2                                       = 0x4002\n\tcase LIGHT3                                       = 0x4003\n\tcase LIGHT4                                       = 0x4004\n\tcase LIGHT5                                       = 0x4005\n\tcase LIGHT6                                       = 0x4006\n\tcase LIGHT7                                       = 0x4007\n\tcase SPOT_EXPONENT                                = 0x1205\n\tcase SPOT_CUTOFF                                  = 0x1206\n\tcase CONSTANT_ATTENUATION                         = 0x1207\n\tcase LINEAR_ATTENUATION                           = 0x1208\n\tcase QUADRATIC_ATTENUATION                        = 0x1209\n\tcase AMBIENT                                      = 0x1200\n\tcase DIFFUSE                                      = 0x1201\n\tcase SPECULAR                                     = 0x1202\n\tcase SHININESS                                    = 0x1601\n\tcase EMISSION                                     = 0x1600\n\tcase POSITION                                     = 0x1203\n\tcase SPOT_DIRECTION                               = 0x1204\n\tcase AMBIENT_AND_DIFFUSE                          = 0x1602\n\tcase COLOR_INDEXES                                = 0x1603\n\tcase LIGHT_MODEL_TWO_SIDE                         = 0x0B52\n\tcase LIGHT_MODEL_LOCAL_VIEWER                     = 0x0B51\n\tcase LIGHT_MODEL_AMBIENT                          = 0x0B53\n\tcase FRONT_AND_BACK                               = 0x0408\n\tcase SHADE_MODEL                                  = 0x0B54\n\tcase FLAT                                         = 0x1D00\n\tcase SMOOTH                                       = 0x1D01\n\tcase COLOR_MATERIAL                               = 0x0B57\n\tcase COLOR_MATERIAL_FACE                          = 0x0B55\n\tcase COLOR_MATERIAL_PARAMETER                     = 0x0B56\n\tcase NORMALIZE                                    = 0x0BA1\n\tcase CLIP_PLANE0                                  = 0x3000\n\tcase CLIP_PLANE1                                  = 0x3001\n\tcase CLIP_PLANE2                                  = 0x3002\n\tcase CLIP_PLANE3                                  = 0x3003\n\tcase CLIP_PLANE4                                  = 0x3004\n\tcase CLIP_PLANE5                                  = 0x3005\n\tcase ACCUM_RED_BITS                               = 0x0D58\n\tcase ACCUM_GREEN_BITS                             = 0x0D59\n\tcase ACCUM_BLUE_BITS                              = 0x0D5A\n\tcase ACCUM_ALPHA_BITS                             = 0x0D5B\n\tcase ACCUM_CLEAR_VALUE                            = 0x0B80\n\tcase ACCUM                                        = 0x0100\n\tcase ADD                                          = 0x0104\n\tcase LOAD                                         = 0x0101\n\tcase MULT                                         = 0x0103\n\tcase RETURN                                       = 0x0102\n\tcase ALPHA_TEST                                   = 0x0BC0\n\tcase ALPHA_TEST_REF                               = 0x0BC2\n\tcase ALPHA_TEST_FUNC                              = 0x0BC1\n\tcase BLEND                                        = 0x0BE2\n\tcase BLEND_SRC                                    = 0x0BE1\n\tcase BLEND_DST                                    = 0x0BE0\n\tcase ZERO                                         = 0\n\tcase ONE                                          = 1\n\tcase SRC_COLOR                                    = 0x0300\n\tcase ONE_MINUS_SRC_COLOR                          = 0x0301\n\tcase SRC_ALPHA                                    = 0x0302\n\tcase ONE_MINUS_SRC_ALPHA                          = 0x0303\n\tcase DST_ALPHA                                    = 0x0304\n\tcase ONE_MINUS_DST_ALPHA                          = 0x0305\n\tcase DST_COLOR                                    = 0x0306\n\tcase ONE_MINUS_DST_COLOR                          = 0x0307\n\tcase SRC_ALPHA_SATURATE                           = 0x0308\n\tcase FEEDBACK                                     = 0x1C01\n\tcase RENDER                                       = 0x1C00\n\tcase SELECT                                       = 0x1C02\n\tcase TWO_D                                        = 0x0600\n\tcase THREE_D                                      = 0x0601\n\tcase THREE_D_COLOR                                = 0x0602\n\tcase THREE_D_COLOR_TEXTURE                        = 0x0603\n\tcase FOUR_D_COLOR_TEXTURE                         = 0x0604\n\tcase POINT_TOKEN                                  = 0x0701\n\tcase LINE_TOKEN                                   = 0x0702\n\tcase LINE_RESET_TOKEN                             = 0x0707\n\tcase POLYGON_TOKEN                                = 0x0703\n\tcase BITMAP_TOKEN                                 = 0x0704\n\tcase DRAW_PIXEL_TOKEN                             = 0x0705\n\tcase COPY_PIXEL_TOKEN                             = 0x0706\n\tcase PASS_THROUGH_TOKEN                           = 0x0700\n\tcase FEEDBACK_BUFFER_POINTER                      = 0x0DF0\n\tcase FEEDBACK_BUFFER_SIZE                         = 0x0DF1\n\tcase FEEDBACK_BUFFER_TYPE                         = 0x0DF2\n\tcase SELECTION_BUFFER_POINTER                     = 0x0DF3\n\tcase SELECTION_BUFFER_SIZE                        = 0x0DF4\n\tcase FOG                                          = 0x0B60\n\tcase FOG_MODE                                     = 0x0B65\n\tcase FOG_DENSITY                                  = 0x0B62\n\tcase FOG_COLOR                                    = 0x0B66\n\tcase FOG_INDEX                                    = 0x0B61\n\tcase FOG_START                                    = 0x0B63\n\tcase FOG_END                                      = 0x0B64\n\tcase LINEAR                                       = 0x2601\n\tcase EXP                                          = 0x0800\n\tcase EXP2                                         = 0x0801\n\tcase LOGIC_OP                                     = 0x0BF1\n\tcase INDEX_LOGIC_OP                               = 0x0BF1\n\tcase COLOR_LOGIC_OP                               = 0x0BF2\n\tcase LOGIC_OP_MODE                                = 0x0BF0\n\tcase CLEAR                                        = 0x1500\n\tcase SET                                          = 0x150F\n\tcase COPY                                         = 0x1503\n\tcase COPY_INVERTED                                = 0x150C\n\tcase NOOP                                         = 0x1505\n\tcase INVERT                                       = 0x150A\n\tcase AND                                          = 0x1501\n\tcase NAND                                         = 0x150E\n\tcase OR                                           = 0x1507\n\tcase NOR                                          = 0x1508\n\tcase XOR                                          = 0x1506\n\tcase EQUIV                                        = 0x1509\n\tcase AND_REVERSE                                  = 0x1502\n\tcase AND_INVERTED                                 = 0x1504\n\tcase OR_REVERSE                                   = 0x150B\n\tcase OR_INVERTED                                  = 0x150D\n\tcase STENCIL_BITS                                 = 0x0D57\n\tcase STENCIL_TEST                                 = 0x0B90\n\tcase STENCIL_CLEAR_VALUE                          = 0x0B91\n\tcase STENCIL_FUNC                                 = 0x0B92\n\tcase STENCIL_VALUE_MASK                           = 0x0B93\n\tcase STENCIL_FAIL                                 = 0x0B94\n\tcase STENCIL_PASS_DEPTH_FAIL                      = 0x0B95\n\tcase STENCIL_PASS_DEPTH_PASS                      = 0x0B96\n\tcase STENCIL_REF                                  = 0x0B97\n\tcase STENCIL_WRITEMASK                            = 0x0B98\n\tcase STENCIL_INDEX                                = 0x1901\n\tcase KEEP                                         = 0x1E00\n\tcase REPLACE                                      = 0x1E01\n\tcase INCR                                         = 0x1E02\n\tcase DECR                                         = 0x1E03\n\tcase NONE                                         = 0\n\tcase LEFT                                         = 0x0406\n\tcase RIGHT                                        = 0x0407\n\tcase FRONT_LEFT                                   = 0x0400\n\tcase FRONT_RIGHT                                  = 0x0401\n\tcase BACK_LEFT                                    = 0x0402\n\tcase BACK_RIGHT                                   = 0x0403\n\tcase AUX0                                         = 0x0409\n\tcase AUX1                                         = 0x040A\n\tcase AUX2                                         = 0x040B\n\tcase AUX3                                         = 0x040C\n\tcase COLOR_INDEX                                  = 0x1900\n\tcase RED                                          = 0x1903\n\tcase GREEN                                        = 0x1904\n\tcase BLUE                                         = 0x1905\n\tcase ALPHA                                        = 0x1906\n\tcase LUMINANCE                                    = 0x1909\n\tcase LUMINANCE_ALPHA                              = 0x190A\n\tcase ALPHA_BITS                                   = 0x0D55\n\tcase RED_BITS                                     = 0x0D52\n\tcase GREEN_BITS                                   = 0x0D53\n\tcase BLUE_BITS                                    = 0x0D54\n\tcase INDEX_BITS                                   = 0x0D51\n\tcase SUBPIXEL_BITS                                = 0x0D50\n\tcase AUX_BUFFERS                                  = 0x0C00\n\tcase READ_BUFFER                                  = 0x0C02\n\tcase DRAW_BUFFER                                  = 0x0C01\n\tcase DOUBLEBUFFER                                 = 0x0C32\n\tcase STEREO                                       = 0x0C33\n\tcase BITMAP                                       = 0x1A00\n\tcase COLOR                                        = 0x1800\n\tcase DEPTH                                        = 0x1801\n\tcase STENCIL                                      = 0x1802\n\tcase DITHER                                       = 0x0BD0\n\tcase RGB                                          = 0x1907\n\tcase RGBA                                         = 0x1908\n\tcase MAX_LIST_NESTING                             = 0x0B31\n\tcase MAX_EVAL_ORDER                               = 0x0D30\n\tcase MAX_LIGHTS                                   = 0x0D31\n\tcase MAX_CLIP_PLANES                              = 0x0D32\n\tcase MAX_TEXTURE_SIZE                             = 0x0D33\n\tcase MAX_PIXEL_MAP_TABLE                          = 0x0D34\n\tcase MAX_ATTRIB_STACK_DEPTH                       = 0x0D35\n\tcase MAX_MODELVIEW_STACK_DEPTH                    = 0x0D36\n\tcase MAX_NAME_STACK_DEPTH                         = 0x0D37\n\tcase MAX_PROJECTION_STACK_DEPTH                   = 0x0D38\n\tcase MAX_TEXTURE_STACK_DEPTH                      = 0x0D39\n\tcase MAX_VIEWPORT_DIMS                            = 0x0D3A\n\tcase MAX_CLIENT_ATTRIB_STACK_DEPTH                = 0x0D3B\n\tcase ATTRIB_STACK_DEPTH                           = 0x0BB0\n\tcase CLIENT_ATTRIB_STACK_DEPTH                    = 0x0BB1\n\tcase COLOR_CLEAR_VALUE                            = 0x0C22\n\tcase COLOR_WRITEMASK                              = 0x0C23\n\tcase CURRENT_INDEX                                = 0x0B01\n\tcase CURRENT_COLOR                                = 0x0B00\n\tcase CURRENT_NORMAL                               = 0x0B02\n\tcase CURRENT_RASTER_COLOR                         = 0x0B04\n\tcase CURRENT_RASTER_DISTANCE                      = 0x0B09\n\tcase CURRENT_RASTER_INDEX                         = 0x0B05\n\tcase CURRENT_RASTER_POSITION                      = 0x0B07\n\tcase CURRENT_RASTER_TEXTURE_COORDS                = 0x0B06\n\tcase CURRENT_RASTER_POSITION_VALID                = 0x0B08\n\tcase CURRENT_TEXTURE_COORDS                       = 0x0B03\n\tcase INDEX_CLEAR_VALUE                            = 0x0C20\n\tcase INDEX_MODE                                   = 0x0C30\n\tcase INDEX_WRITEMASK                              = 0x0C21\n\tcase MODELVIEW_MATRIX                             = 0x0BA6\n\tcase MODELVIEW_STACK_DEPTH                        = 0x0BA3\n\tcase NAME_STACK_DEPTH                             = 0x0D70\n\tcase PROJECTION_MATRIX                            = 0x0BA7\n\tcase PROJECTION_STACK_DEPTH                       = 0x0BA4\n\tcase RENDER_MODE                                  = 0x0C40\n\tcase RGBA_MODE                                    = 0x0C31\n\tcase TEXTURE_MATRIX                               = 0x0BA8\n\tcase TEXTURE_STACK_DEPTH                          = 0x0BA5\n\tcase VIEWPORT                                     = 0x0BA2\n\tcase AUTO_NORMAL                                  = 0x0D80\n\tcase MAP1_COLOR_4                                 = 0x0D90\n\tcase MAP1_INDEX                                   = 0x0D91\n\tcase MAP1_NORMAL                                  = 0x0D92\n\tcase MAP1_TEXTURE_COORD_1                         = 0x0D93\n\tcase MAP1_TEXTURE_COORD_2                         = 0x0D94\n\tcase MAP1_TEXTURE_COORD_3                         = 0x0D95\n\tcase MAP1_TEXTURE_COORD_4                         = 0x0D96\n\tcase MAP1_VERTEX_3                                = 0x0D97\n\tcase MAP1_VERTEX_4                                = 0x0D98\n\tcase MAP2_COLOR_4                                 = 0x0DB0\n\tcase MAP2_INDEX                                   = 0x0DB1\n\tcase MAP2_NORMAL                                  = 0x0DB2\n\tcase MAP2_TEXTURE_COORD_1                         = 0x0DB3\n\tcase MAP2_TEXTURE_COORD_2                         = 0x0DB4\n\tcase MAP2_TEXTURE_COORD_3                         = 0x0DB5\n\tcase MAP2_TEXTURE_COORD_4                         = 0x0DB6\n\tcase MAP2_VERTEX_3                                = 0x0DB7\n\tcase MAP2_VERTEX_4                                = 0x0DB8\n\tcase MAP1_GRID_DOMAIN                             = 0x0DD0\n\tcase MAP1_GRID_SEGMENTS                           = 0x0DD1\n\tcase MAP2_GRID_DOMAIN                             = 0x0DD2\n\tcase MAP2_GRID_SEGMENTS                           = 0x0DD3\n\tcase COEFF                                        = 0x0A00\n\tcase ORDER                                        = 0x0A01\n\tcase DOMAIN                                       = 0x0A02\n\tcase PERSPECTIVE_CORRECTION_HINT                  = 0x0C50\n\tcase POINT_SMOOTH_HINT                            = 0x0C51\n\tcase LINE_SMOOTH_HINT                             = 0x0C52\n\tcase POLYGON_SMOOTH_HINT                          = 0x0C53\n\tcase FOG_HINT                                     = 0x0C54\n\tcase DONT_CARE                                    = 0x1100\n\tcase FASTEST                                      = 0x1101\n\tcase NICEST                                       = 0x1102\n\tcase SCISSOR_BOX                                  = 0x0C10\n\tcase SCISSOR_TEST                                 = 0x0C11\n\tcase MAP_COLOR                                    = 0x0D10\n\tcase MAP_STENCIL                                  = 0x0D11\n\tcase INDEX_SHIFT                                  = 0x0D12\n\tcase INDEX_OFFSET                                 = 0x0D13\n\tcase RED_SCALE                                    = 0x0D14\n\tcase RED_BIAS                                     = 0x0D15\n\tcase GREEN_SCALE                                  = 0x0D18\n\tcase GREEN_BIAS                                   = 0x0D19\n\tcase BLUE_SCALE                                   = 0x0D1A\n\tcase BLUE_BIAS                                    = 0x0D1B\n\tcase ALPHA_SCALE                                  = 0x0D1C\n\tcase ALPHA_BIAS                                   = 0x0D1D\n\tcase DEPTH_SCALE                                  = 0x0D1E\n\tcase DEPTH_BIAS                                   = 0x0D1F\n\tcase PIXEL_MAP_S_TO_S_SIZE                        = 0x0CB1\n\tcase PIXEL_MAP_I_TO_I_SIZE                        = 0x0CB0\n\tcase PIXEL_MAP_I_TO_R_SIZE                        = 0x0CB2\n\tcase PIXEL_MAP_I_TO_G_SIZE                        = 0x0CB3\n\tcase PIXEL_MAP_I_TO_B_SIZE                        = 0x0CB4\n\tcase PIXEL_MAP_I_TO_A_SIZE                        = 0x0CB5\n\tcase PIXEL_MAP_R_TO_R_SIZE                        = 0x0CB6\n\tcase PIXEL_MAP_G_TO_G_SIZE                        = 0x0CB7\n\tcase PIXEL_MAP_B_TO_B_SIZE                        = 0x0CB8\n\tcase PIXEL_MAP_A_TO_A_SIZE                        = 0x0CB9\n\tcase PIXEL_MAP_S_TO_S                             = 0x0C71\n\tcase PIXEL_MAP_I_TO_I                             = 0x0C70\n\tcase PIXEL_MAP_I_TO_R                             = 0x0C72\n\tcase PIXEL_MAP_I_TO_G                             = 0x0C73\n\tcase PIXEL_MAP_I_TO_B                             = 0x0C74\n\tcase PIXEL_MAP_I_TO_A                             = 0x0C75\n\tcase PIXEL_MAP_R_TO_R                             = 0x0C76\n\tcase PIXEL_MAP_G_TO_G                             = 0x0C77\n\tcase PIXEL_MAP_B_TO_B                             = 0x0C78\n\tcase PIXEL_MAP_A_TO_A                             = 0x0C79\n\tcase PACK_ALIGNMENT                               = 0x0D05\n\tcase PACK_LSB_FIRST                               = 0x0D01\n\tcase PACK_ROW_LENGTH                              = 0x0D02\n\tcase PACK_SKIP_PIXELS                             = 0x0D04\n\tcase PACK_SKIP_ROWS                               = 0x0D03\n\tcase PACK_SWAP_BYTES                              = 0x0D00\n\tcase UNPACK_ALIGNMENT                             = 0x0CF5\n\tcase UNPACK_LSB_FIRST                             = 0x0CF1\n\tcase UNPACK_ROW_LENGTH                            = 0x0CF2\n\tcase UNPACK_SKIP_PIXELS                           = 0x0CF4\n\tcase UNPACK_SKIP_ROWS                             = 0x0CF3\n\tcase UNPACK_SWAP_BYTES                            = 0x0CF0\n\tcase ZOOM_X                                       = 0x0D16\n\tcase ZOOM_Y                                       = 0x0D17\n\tcase TEXTURE_ENV                                  = 0x2300\n\tcase TEXTURE_ENV_MODE                             = 0x2200\n\tcase TEXTURE_1D                                   = 0x0DE0\n\tcase TEXTURE_2D                                   = 0x0DE1\n\tcase TEXTURE_WRAP_S                               = 0x2802\n\tcase TEXTURE_WRAP_T                               = 0x2803\n\tcase TEXTURE_MAG_FILTER                           = 0x2800\n\tcase TEXTURE_MIN_FILTER                           = 0x2801\n\tcase TEXTURE_ENV_COLOR                            = 0x2201\n\tcase TEXTURE_GEN_S                                = 0x0C60\n\tcase TEXTURE_GEN_T                                = 0x0C61\n\tcase TEXTURE_GEN_R                                = 0x0C62\n\tcase TEXTURE_GEN_Q                                = 0x0C63\n\tcase TEXTURE_GEN_MODE                             = 0x2500\n\tcase TEXTURE_BORDER_COLOR                         = 0x1004\n\tcase TEXTURE_WIDTH                                = 0x1000\n\tcase TEXTURE_HEIGHT                               = 0x1001\n\tcase TEXTURE_BORDER                               = 0x1005\n\tcase TEXTURE_COMPONENTS                           = 0x1003\n\tcase TEXTURE_RED_SIZE                             = 0x805C\n\tcase TEXTURE_GREEN_SIZE                           = 0x805D\n\tcase TEXTURE_BLUE_SIZE                            = 0x805E\n\tcase TEXTURE_ALPHA_SIZE                           = 0x805F\n\tcase TEXTURE_LUMINANCE_SIZE                       = 0x8060\n\tcase TEXTURE_INTENSITY_SIZE                       = 0x8061\n\tcase NEAREST_MIPMAP_NEAREST                       = 0x2700\n\tcase NEAREST_MIPMAP_LINEAR                        = 0x2702\n\tcase LINEAR_MIPMAP_NEAREST                        = 0x2701\n\tcase LINEAR_MIPMAP_LINEAR                         = 0x2703\n\tcase OBJECT_LINEAR                                = 0x2401\n\tcase OBJECT_PLANE                                 = 0x2501\n\tcase EYE_LINEAR                                   = 0x2400\n\tcase EYE_PLANE                                    = 0x2502\n\tcase SPHERE_MAP                                   = 0x2402\n\tcase DECAL                                        = 0x2101\n\tcase MODULATE                                     = 0x2100\n\tcase NEAREST                                      = 0x2600\n\tcase REPEAT                                       = 0x2901\n\tcase CLAMP                                        = 0x2900\n\tcase S                                            = 0x2000\n\tcase T                                            = 0x2001\n\tcase R                                            = 0x2002\n\tcase Q                                            = 0x2003\n\tcase VENDOR                                       = 0x1F00\n\tcase RENDERER                                     = 0x1F01\n\tcase VERSION                                      = 0x1F02\n\tcase EXTENSIONS                                   = 0x1F03\n\tcase NO_ERROR                                     = 0\n\tcase INVALID_ENUM                                 = 0x0500\n\tcase INVALID_VALUE                                = 0x0501\n\tcase INVALID_OPERATION                            = 0x0502\n\tcase STACK_OVERFLOW                               = 0x0503\n\tcase STACK_UNDERFLOW                              = 0x0504\n\tcase OUT_OF_MEMORY                                = 0x0505\n\tcase CURRENT_BIT                                  = 0x00000001\n\tcase POINT_BIT                                    = 0x00000002\n\tcase LINE_BIT                                     = 0x00000004\n\tcase POLYGON_BIT                                  = 0x00000008\n\tcase POLYGON_STIPPLE_BIT                          = 0x00000010\n\tcase PIXEL_MODE_BIT                               = 0x00000020\n\tcase LIGHTING_BIT                                 = 0x00000040\n\tcase FOG_BIT                                      = 0x00000080\n\tcase DEPTH_BUFFER_BIT                             = 0x00000100\n\tcase ACCUM_BUFFER_BIT                             = 0x00000200\n\tcase STENCIL_BUFFER_BIT                           = 0x00000400\n\tcase VIEWPORT_BIT                                 = 0x00000800\n\tcase TRANSFORM_BIT                                = 0x00001000\n\tcase ENABLE_BIT                                   = 0x00002000\n\tcase COLOR_BUFFER_BIT                             = 0x00004000\n\tcase HINT_BIT                                     = 0x00008000\n\tcase EVAL_BIT                                     = 0x00010000\n\tcase LIST_BIT                                     = 0x00020000\n\tcase TEXTURE_BIT                                  = 0x00040000\n\tcase SCISSOR_BIT                                  = 0x00080000\n\tcase ALL_ATTRIB_BITS                              = 0x000FFFFF\n\n    // OpenGL 1.1\n\tcase PROXY_TEXTURE_1D                             = 0x8063\n\tcase PROXY_TEXTURE_2D                             = 0x8064\n\tcase TEXTURE_PRIORITY                             = 0x8066\n\tcase TEXTURE_RESIDENT                             = 0x8067\n\tcase TEXTURE_BINDING_1D                           = 0x8068\n\tcase TEXTURE_BINDING_2D                           = 0x8069\n\tcase TEXTURE_INTERNAL_FORMAT                      = 0x1003\n\tcase ALPHA4                                       = 0x803B\n\tcase ALPHA8                                       = 0x803C\n\tcase ALPHA12                                      = 0x803D\n\tcase ALPHA16                                      = 0x803E\n\tcase LUMINANCE4                                   = 0x803F\n\tcase LUMINANCE8                                   = 0x8040\n\tcase LUMINANCE12                                  = 0x8041\n\tcase LUMINANCE16                                  = 0x8042\n\tcase LUMINANCE4_ALPHA4                            = 0x8043\n\tcase LUMINANCE6_ALPHA2                            = 0x8044\n\tcase LUMINANCE8_ALPHA8                            = 0x8045\n\tcase LUMINANCE12_ALPHA4                           = 0x8046\n\tcase LUMINANCE12_ALPHA12                          = 0x8047\n\tcase LUMINANCE16_ALPHA16                          = 0x8048\n\tcase INTENSITY                                    = 0x8049\n\tcase INTENSITY4                                   = 0x804A\n\tcase INTENSITY8                                   = 0x804B\n\tcase INTENSITY12                                  = 0x804C\n\tcase INTENSITY16                                  = 0x804D\n\tcase R3_G3_B2                                     = 0x2A10\n\tcase RGB4                                         = 0x804F\n\tcase RGB5                                         = 0x8050\n\tcase RGB8                                         = 0x8051\n\tcase RGB10                                        = 0x8052\n\tcase RGB12                                        = 0x8053\n\tcase RGB16                                        = 0x8054\n\tcase RGBA2                                        = 0x8055\n\tcase RGBA4                                        = 0x8056\n\tcase RGB5_A1                                      = 0x8057\n\tcase RGBA8                                        = 0x8058\n\tcase RGB10_A2                                     = 0x8059\n\tcase RGBA12                                       = 0x805A\n\tcase RGBA16                                       = 0x805B\n\tcase CLIENT_PIXEL_STORE_BIT                       = 0x00000001\n\tcase CLIENT_VERTEX_ARRAY_BIT                      = 0x00000002\n\tcase ALL_CLIENT_ATTRIB_BITS                       = 0xFFFFFFFF\n\tcase CLIENT_ALL_ATTRIB_BITS                       = 0xFFFFFFFF\n\n\n    // OpenGL 1.2\n\tcase RESCALE_NORMAL                               = 0x803A\n\tcase CLAMP_TO_EDGE                                = 0x812F\n\tcase MAX_ELEMENTS_VERTICES                        = 0x80E8\n\tcase MAX_ELEMENTS_INDICES                         = 0x80E9\n\tcase BGR                                          = 0x80E0\n\tcase BGRA                                         = 0x80E1\n\tcase UNSIGNED_BYTE_3_3_2                          = 0x8032\n\tcase UNSIGNED_BYTE_2_3_3_REV                      = 0x8362\n\tcase UNSIGNED_SHORT_5_6_5                         = 0x8363\n\tcase UNSIGNED_SHORT_5_6_5_REV                     = 0x8364\n\tcase UNSIGNED_SHORT_4_4_4_4                       = 0x8033\n\tcase UNSIGNED_SHORT_4_4_4_4_REV                   = 0x8365\n\tcase UNSIGNED_SHORT_5_5_5_1                       = 0x8034\n\tcase UNSIGNED_SHORT_1_5_5_5_REV                   = 0x8366\n\tcase UNSIGNED_INT_8_8_8_8                         = 0x8035\n\tcase UNSIGNED_INT_8_8_8_8_REV                     = 0x8367\n\tcase UNSIGNED_INT_10_10_10_2                      = 0x8036\n\tcase UNSIGNED_INT_2_10_10_10_REV                  = 0x8368\n\tcase LIGHT_MODEL_COLOR_CONTROL                    = 0x81F8\n\tcase SINGLE_COLOR                                 = 0x81F9\n\tcase SEPARATE_SPECULAR_COLOR                      = 0x81FA\n\tcase TEXTURE_MIN_LOD                              = 0x813A\n\tcase TEXTURE_MAX_LOD                              = 0x813B\n\tcase TEXTURE_BASE_LEVEL                           = 0x813C\n\tcase TEXTURE_MAX_LEVEL                            = 0x813D\n\tcase SMOOTH_POINT_SIZE_RANGE                      = 0x0B12\n\tcase SMOOTH_POINT_SIZE_GRANULARITY                = 0x0B13\n\tcase SMOOTH_LINE_WIDTH_RANGE                      = 0x0B22\n\tcase SMOOTH_LINE_WIDTH_GRANULARITY                = 0x0B23\n\tcase ALIASED_POINT_SIZE_RANGE                     = 0x846D\n\tcase ALIASED_LINE_WIDTH_RANGE                     = 0x846E\n\tcase PACK_SKIP_IMAGES                             = 0x806B\n\tcase PACK_IMAGE_HEIGHT                            = 0x806C\n\tcase UNPACK_SKIP_IMAGES                           = 0x806D\n\tcase UNPACK_IMAGE_HEIGHT                          = 0x806E\n\tcase TEXTURE_3D                                   = 0x806F\n\tcase PROXY_TEXTURE_3D                             = 0x8070\n\tcase TEXTURE_DEPTH                                = 0x8071\n\tcase TEXTURE_WRAP_R                               = 0x8072\n\tcase MAX_3D_TEXTURE_SIZE                          = 0x8073\n\tcase TEXTURE_BINDING_3D                           = 0x806A\n\n\n    // GL_ARB_imaging\n\tcase CONSTANT_COLOR                               = 0x8001\n\tcase ONE_MINUS_NT_COLOR                           = 0x8002\n\tcase CONSTANT_ALPHA                               = 0x8003\n\tcase ONE_MINUS_NT_ALPHA                           = 0x8004\n\tcase COLOR_TABLE                                  = 0x80D0\n\tcase POST_CONVOLUTION_COLOR_TABLE                 = 0x80D1\n\tcase POST_COLOR_MATRIX_COLOR_TABLE                = 0x80D2\n\tcase PROXY_COLOR_TABLE                            = 0x80D3\n\tcase PROXY_POST_CONVOLUTION_COLOR_TABLE           = 0x80D4\n\tcase PROXY_POST_COLOR_MATRIX_COLOR_TABLE          = 0x80D5\n\tcase COLOR_TABLE_SCALE                            = 0x80D6\n\tcase COLOR_TABLE_BIAS                             = 0x80D7\n\tcase COLOR_TABLE_FORMAT                           = 0x80D8\n\tcase COLOR_TABLE_WIDTH                            = 0x80D9\n\tcase COLOR_TABLE_RED_SIZE                         = 0x80DA\n\tcase COLOR_TABLE_GREEN_SIZE                       = 0x80DB\n\tcase COLOR_TABLE_BLUE_SIZE                        = 0x80DC\n\tcase COLOR_TABLE_ALPHA_SIZE                       = 0x80DD\n\tcase COLOR_TABLE_LUMINANCE_SIZE                   = 0x80DE\n\tcase COLOR_TABLE_INTENSITY_SIZE                   = 0x80DF\n\tcase CONVOLUTION_1D                               = 0x8010\n\tcase CONVOLUTION_2D                               = 0x8011\n\tcase SEPARABLE_2D                                 = 0x8012\n\tcase CONVOLUTION_BORDER_MODE                      = 0x8013\n\tcase CONVOLUTION_FILTER_SCALE                     = 0x8014\n\tcase CONVOLUTION_FILTER_BIAS                      = 0x8015\n\tcase REDUCE                                       = 0x8016\n\tcase CONVOLUTION_FORMAT                           = 0x8017\n\tcase CONVOLUTION_WIDTH                            = 0x8018\n\tcase CONVOLUTION_HEIGHT                           = 0x8019\n\tcase MAX_CONVOLUTION_WIDTH                        = 0x801A\n\tcase MAX_CONVOLUTION_HEIGHT                       = 0x801B\n\tcase POST_CONVOLUTION_RED_SCALE                   = 0x801C\n\tcase POST_CONVOLUTION_GREEN_SCALE                 = 0x801D\n\tcase POST_CONVOLUTION_BLUE_SCALE                  = 0x801E\n\tcase POST_CONVOLUTION_ALPHA_SCALE                 = 0x801F\n\tcase POST_CONVOLUTION_RED_BIAS                    = 0x8020\n\tcase POST_CONVOLUTION_GREEN_BIAS                  = 0x8021\n\tcase POST_CONVOLUTION_BLUE_BIAS                   = 0x8022\n\tcase POST_CONVOLUTION_ALPHA_BIAS                  = 0x8023\n\tcase CONSTANT_BORDER                              = 0x8151\n\tcase REPLICATE_BORDER                             = 0x8153\n\tcase CONVOLUTION_BORDER_COLOR                     = 0x8154\n\tcase COLOR_MATRIX                                 = 0x80B1\n\tcase COLOR_MATRIX_STACK_DEPTH                     = 0x80B2\n\tcase MAX_COLOR_MATRIX_STACK_DEPTH                 = 0x80B3\n\tcase POST_COLOR_MATRIX_RED_SCALE                  = 0x80B4\n\tcase POST_COLOR_MATRIX_GREEN_SCALE                = 0x80B5\n\tcase POST_COLOR_MATRIX_BLUE_SCALE                 = 0x80B6\n\tcase POST_COLOR_MATRIX_ALPHA_SCALE                = 0x80B7\n\tcase POST_COLOR_MATRIX_RED_BIAS                   = 0x80B8\n\tcase POST_COLOR_MATRIX_GREEN_BIAS                 = 0x80B9\n\tcase POST_COLOR_MATRIX_BLUE_BIAS                  = 0x80BA\n\tcase POST_COLOR_MATRIX_ALPHA_BIAS                 = 0x80BB\n\tcase HISTOGRAM                                    = 0x8024\n\tcase PROXY_HISTOGRAM                              = 0x8025\n\tcase HISTOGRAM_WIDTH                              = 0x8026\n\tcase HISTOGRAM_FORMAT                             = 0x8027\n\tcase HISTOGRAM_RED_SIZE                           = 0x8028\n\tcase HISTOGRAM_GREEN_SIZE                         = 0x8029\n\tcase HISTOGRAM_BLUE_SIZE                          = 0x802A\n\tcase HISTOGRAM_ALPHA_SIZE                         = 0x802B\n\tcase HISTOGRAM_LUMINANCE_SIZE                     = 0x802C\n\tcase HISTOGRAM_SINK                               = 0x802D\n\tcase MINMAX                                       = 0x802E\n\tcase MINMAX_FORMAT                                = 0x802F\n\tcase MINMAX_SINK                                  = 0x8030\n\tcase TABLE_TOO_LARGE                              = 0x8031\n\tcase BLEND_EQUATION                               = 0x8009\n\tcase MIN                                          = 0x8007\n\tcase MAX                                          = 0x8008\n\tcase FUNC_ADD                                     = 0x8006\n\tcase FUNC_SUBTRACT                                = 0x800A\n\tcase FUNC_REVERSE_SUBTRACT                        = 0x800B\n\tcase BLEND_COLOR                                  = 0x8005\n\n\n\n    // OpenGL 1.3\n\tcase TEXTURE0                                     = 0x84C0\n\tcase TEXTURE1                                     = 0x84C1\n\tcase TEXTURE2                                     = 0x84C2\n\tcase TEXTURE3                                     = 0x84C3\n\tcase TEXTURE4                                     = 0x84C4\n\tcase TEXTURE5                                     = 0x84C5\n\tcase TEXTURE6                                     = 0x84C6\n\tcase TEXTURE7                                     = 0x84C7\n\tcase TEXTURE8                                     = 0x84C8\n\tcase TEXTURE9                                     = 0x84C9\n\tcase TEXTURE10                                    = 0x84CA\n\tcase TEXTURE11                                    = 0x84CB\n\tcase TEXTURE12                                    = 0x84CC\n\tcase TEXTURE13                                    = 0x84CD\n\tcase TEXTURE14                                    = 0x84CE\n\tcase TEXTURE15                                    = 0x84CF\n\tcase TEXTURE16                                    = 0x84D0\n\tcase TEXTURE17                                    = 0x84D1\n\tcase TEXTURE18                                    = 0x84D2\n\tcase TEXTURE19                                    = 0x84D3\n\tcase TEXTURE20                                    = 0x84D4\n\tcase TEXTURE21                                    = 0x84D5\n\tcase TEXTURE22                                    = 0x84D6\n\tcase TEXTURE23                                    = 0x84D7\n\tcase TEXTURE24                                    = 0x84D8\n\tcase TEXTURE25                                    = 0x84D9\n\tcase TEXTURE26                                    = 0x84DA\n\tcase TEXTURE27                                    = 0x84DB\n\tcase TEXTURE28                                    = 0x84DC\n\tcase TEXTURE29                                    = 0x84DD\n\tcase TEXTURE30                                    = 0x84DE\n\tcase TEXTURE31                                    = 0x84DF\n\tcase ACTIVE_TEXTURE                               = 0x84E0\n\tcase CLIENT_ACTIVE_TEXTURE                        = 0x84E1\n\tcase MAX_TEXTURE_UNITS                            = 0x84E2\n\tcase NORMAL_MAP                                   = 0x8511\n\tcase REFLECTION_MAP                               = 0x8512\n\tcase TEXTURE_CUBE_MAP                             = 0x8513\n\tcase TEXTURE_BINDING_CUBE_MAP                     = 0x8514\n\tcase TEXTURE_CUBE_MAP_POSITIVE_X                  = 0x8515\n\tcase TEXTURE_CUBE_MAP_NEGATIVE_X                  = 0x8516\n\tcase TEXTURE_CUBE_MAP_POSITIVE_Y                  = 0x8517\n\tcase TEXTURE_CUBE_MAP_NEGATIVE_Y                  = 0x8518\n\tcase TEXTURE_CUBE_MAP_POSITIVE_Z                  = 0x8519\n\tcase TEXTURE_CUBE_MAP_NEGATIVE_Z                  = 0x851A\n\tcase PROXY_TEXTURE_CUBE_MAP                       = 0x851B\n\tcase MAX_CUBE_MAP_TEXTURE_SIZE                    = 0x851C\n\tcase COMPRESSED_ALPHA                             = 0x84E9\n\tcase COMPRESSED_LUMINANCE                         = 0x84EA\n\tcase COMPRESSED_LUMINANCE_ALPHA                   = 0x84EB\n\tcase COMPRESSED_INTENSITY                         = 0x84EC\n\tcase COMPRESSED_RGB                               = 0x84ED\n\tcase COMPRESSED_RGBA                              = 0x84EE\n\tcase TEXTURE_COMPRESSION_HINT                     = 0x84EF\n\tcase TEXTURE_COMPRESSED_IMAGE_SIZE                = 0x86A0\n\tcase TEXTURE_COMPRESSED                           = 0x86A1\n\tcase NUM_COMPRESSED_TEXTURE_FORMATS               = 0x86A2\n\tcase COMPRESSED_TEXTURE_FORMATS                   = 0x86A3\n\tcase MULTISAMPLE                                  = 0x809D\n\tcase SAMPLE_ALPHA_TO_COVERAGE                     = 0x809E\n\tcase SAMPLE_ALPHA_TO_ONE                          = 0x809F\n\tcase SAMPLE_COVERAGE                              = 0x80A0\n\tcase SAMPLE_BUFFERS                               = 0x80A8\n\tcase SAMPLES                                      = 0x80A9\n\tcase SAMPLE_COVERAGE_VALUE                        = 0x80AA\n\tcase SAMPLE_COVERAGE_INVERT                       = 0x80AB\n\tcase MULTISAMPLE_BIT                              = 0x20000000\n\tcase TRANSPOSE_MODELVIEW_MATRIX                   = 0x84E3\n\tcase TRANSPOSE_PROJECTION_MATRIX                  = 0x84E4\n\tcase TRANSPOSE_TEXTURE_MATRIX                     = 0x84E5\n\tcase TRANSPOSE_COLOR_MATRIX                       = 0x84E6\n\tcase COMBINE                                      = 0x8570\n\tcase COMBINE_RGB                                  = 0x8571\n\tcase COMBINE_ALPHA                                = 0x8572\n\tcase SOURCE0_RGB                                  = 0x8580\n\tcase SOURCE1_RGB                                  = 0x8581\n\tcase SOURCE2_RGB                                  = 0x8582\n\tcase SOURCE0_ALPHA                                = 0x8588\n\tcase SOURCE1_ALPHA                                = 0x8589\n\tcase SOURCE2_ALPHA                                = 0x858A\n\tcase OPERAND0_RGB                                 = 0x8590\n\tcase OPERAND1_RGB                                 = 0x8591\n\tcase OPERAND2_RGB                                 = 0x8592\n\tcase OPERAND0_ALPHA                               = 0x8598\n\tcase OPERAND1_ALPHA                               = 0x8599\n\tcase OPERAND2_ALPHA                               = 0x859A\n\tcase RGB_SCALE                                    = 0x8573\n\tcase ADD_SIGNED                                   = 0x8574\n\tcase INTERPOLATE                                  = 0x8575\n\tcase SUBTRACT                                     = 0x84E7\n\tcase NT                                           = 0x8576\n\tcase PRIMARY_COLOR                                = 0x8577\n\tcase PREVIOUS                                     = 0x8578\n\tcase DOT3_RGB                                     = 0x86AE\n\tcase DOT3_RGBA                                    = 0x86AF\n\tcase CLAMP_TO_BORDER                              = 0x812D\n\n    // GL_ARB_multitexture (ARB extension 1 and OpenGL 1.2.1)\n\tcase ARB_multitexture                             = 1\n\tcase TEXTURE0_ARB                                 = 0x84C0\n\tcase TEXTURE1_ARB                                 = 0x84C1\n\tcase TEXTURE2_ARB                                 = 0x84C2\n\tcase TEXTURE3_ARB                                 = 0x84C3\n\tcase TEXTURE4_ARB                                 = 0x84C4\n\tcase TEXTURE5_ARB                                 = 0x84C5\n\tcase TEXTURE6_ARB                                 = 0x84C6\n\tcase TEXTURE7_ARB                                 = 0x84C7\n\tcase TEXTURE8_ARB                                 = 0x84C8\n\tcase TEXTURE9_ARB                                 = 0x84C9\n\tcase TEXTURE10_ARB                                = 0x84CA\n\tcase TEXTURE11_ARB                                = 0x84CB\n\tcase TEXTURE12_ARB                                = 0x84CC\n\tcase TEXTURE13_ARB                                = 0x84CD\n\tcase TEXTURE14_ARB                                = 0x84CE\n\tcase TEXTURE15_ARB                                = 0x84CF\n\tcase TEXTURE16_ARB                                = 0x84D0\n\tcase TEXTURE17_ARB                                = 0x84D1\n\tcase TEXTURE18_ARB                                = 0x84D2\n\tcase TEXTURE19_ARB                                = 0x84D3\n\tcase TEXTURE20_ARB                                = 0x84D4\n\tcase TEXTURE21_ARB                                = 0x84D5\n\tcase TEXTURE22_ARB                                = 0x84D6\n\tcase TEXTURE23_ARB                                = 0x84D7\n\tcase TEXTURE24_ARB                                = 0x84D8\n\tcase TEXTURE25_ARB                                = 0x84D9\n\tcase TEXTURE26_ARB                                = 0x84DA\n\tcase TEXTURE27_ARB                                = 0x84DB\n\tcase TEXTURE28_ARB                                = 0x84DC\n\tcase TEXTURE29_ARB                                = 0x84DD\n\tcase TEXTURE30_ARB                                = 0x84DE\n\tcase TEXTURE31_ARB                                = 0x84DF\n\tcase ACTIVE_TEXTURE_ARB                           = 0x84E0\n\tcase CLIENT_ACTIVE_TEXTURE_ARB                    = 0x84E1\n\tcase MAX_TEXTURE_UNITS_ARB                        = 0x84E2\n}\n\n\n// glu\npublic ffi fn gluPerspective(fovy: f64, aspect: f64, znear: f64, zfar: f64) -> void\n\n\n\npublic ffi fn glClearIndex(c: f32) -> void\npublic ffi fn glClearColor(red: f32, green: f32, blue: f32, alpha: f32) -> void\npublic ffi fn glClear(mask: GL) -> void\npublic ffi fn glIndexMask(mask: u32) -> void\npublic ffi fn glColorMask(red: bool, green: bool, blue: bool, alpha: bool) -> void\npublic ffi fn glAlphaFunc(f: u32, ref: f32) -> void\npublic ffi fn glBlendFunc(sfactor: u32, dfactor: u32) -> void\npublic ffi fn glLogicOp(opcode: u32) -> void\npublic ffi fn glCullFace(mode: u32) -> void\npublic ffi fn glFrontFace(mode: u32) -> void\npublic ffi fn glPointSize(size: f32) -> void\npublic ffi fn glLineWidth(width: f32) -> void\npublic ffi fn glLineStipple(factor: i32, pattern: u16) -> void\npublic ffi fn glPolygonMode(face: u32, mode: u32) -> void\npublic ffi fn glPolygonOffset(factor: f32, units: f32) -> void\npublic ffi fn glPolygonStipple(mask: &i8) -> void\npublic ffi fn glGetPolygonStipple(mask: &i8) -> void\npublic ffi fn glEdgeFlag(flag: bool) -> void\npublic ffi fn glEdgeFlagv(flag: &bool) -> void\npublic ffi fn glScissor(x: i32, y: i32, width: i32, height: i32) -> void\npublic ffi fn glClipPlane(plane: u32, equation: &f64) -> void\npublic ffi fn glGetClipPlane(plane: u32, equation: &f64) -> void\npublic ffi fn glDrawBuffer(mode: u32) -> void\npublic ffi fn glReadBuffer(mode: u32) -> void\npublic ffi fn glEnable(cap: GL) -> void\npublic ffi fn glDisable(cap: GL) -> void\npublic ffi fn glIsEnabled(cap: u32) -> bool\npublic ffi fn glEnableClientState(cap: GL) -> void\npublic ffi fn glDisableClientState(cap: GL) -> void\npublic ffi fn glGetBooleanv(pname: u32, params: &bool) -> void\npublic ffi fn glGetDoublev(pname: u32, params: &f64) -> void\npublic ffi fn glGetFloatv(pname: u32, params: &f32) -> void\npublic ffi fn glGetIntegerv(pname: u32, params: &i32) -> void\npublic ffi fn glPushAttrib(mask: u32) -> void\npublic ffi fn glPopAttrib() -> void\npublic ffi fn glPushClientAttrib(mask: u32) -> void\npublic ffi fn glPopClientAttrib() -> void\npublic ffi fn glRenderMode(mode: u32) -> i32\npublic ffi fn glGetError() -> u32\npublic ffi fn glGetString(name: u32) -> &i8\npublic ffi fn glFinish() -> void\npublic ffi fn glFlush() -> void\npublic ffi fn glHint(target: u32, mode: u32) -> void\n\n// Depth Buffer\npublic ffi fn glClearDepth(depth: f64) -> void\npublic ffi fn glDepthFunc(f: GL) -> void\npublic ffi fn glDepthMask(flag: bool) -> void\npublic ffi fn glDepthRange(near_val: f64, far_val: f64) -> void\n\n// Accumulation Buffer\npublic ffi fn glClearAccum(red: f32, green: f32, blue: f32, alpha: f32) -> void\npublic ffi fn glAccum(op: u32, value: f32) -> void\n\n// Transformation\npublic ffi fn glMatrixMode(mode: GL) -> void\npublic ffi fn glOrtho(left: f64, right: f64, bottom: f64, top: f64, near_val: f64, far_val: f64) -> void\npublic ffi fn glFrustum(left: f64, right: f64, bottom: f64, top: f64, near_val: f64, far_val: f64) -> void\npublic ffi fn glViewport(x: i32, y: i32, width: i32, height: i32) -> void\npublic ffi fn glPushMatrix() -> void\npublic ffi fn glPopMatrix() -> void\npublic ffi fn glLoadIdentity() -> void\npublic ffi fn glLoadMatrixd(m: &f64) -> void\npublic ffi fn glLoadMatrixf(m: &f32) -> void\npublic ffi fn glMultMatrixd(m: &f64) -> void\npublic ffi fn glMultMatrixf(m: &f32) -> void\npublic ffi fn glRotated(angle: f64, x: f64, y: f64, z: f64) -> void\npublic ffi fn glRotatef(angle: f32, x: f32, y: f32, z: f32) -> void\npublic ffi fn glScaled(x: f64, y: f64, z: f64) -> void\npublic ffi fn glScalef(x: f32, y: f32, z: f32) -> void\npublic ffi fn glTranslated(x: f64, y: f64, z: f64) -> void\npublic ffi fn glTranslatef(x: f32, y: f32, z: f32) -> void\n\n\n// Display Lists\npublic ffi fn glIsList(list: u32) -> bool\npublic ffi fn glDeleteLists(list: u32, range: i32) -> void\npublic ffi fn glGenLists(range: i32) -> u32\npublic ffi fn glNewList(list: u32, mode: u32) -> void\npublic ffi fn glEndList() -> void\npublic ffi fn glCallList(list: u32) -> void\npublic ffi fn glCallLists(n: i32, type: u32, lists: &void) -> void\npublic ffi fn glListBase(base: u32) -> void\n\n// Drawing Functions\npublic ffi fn glBegin(mode: GL) -> void\npublic ffi fn glEnd() -> void\npublic ffi fn glVertex2d(x: f64, y: f64) -> void\npublic ffi fn glVertex2f(x: f32, y: f32) -> void\npublic ffi fn glVertex2i(x: i32, y: i32) -> void\npublic ffi fn glVertex2s(x: i16, y: i16) -> void\npublic ffi fn glVertex3d(x: f64, y: f64, z: f64) -> void\npublic ffi fn glVertex3f(x: f32, y: f32, z: f32) -> void\npublic ffi fn glVertex3i(x: i32, y: i32, z: i32) -> void\npublic ffi fn glVertex3s(x: i16, y: i16, z: i16) -> void\npublic ffi fn glVertex4d(x: f64, y: f64, z: f64, w: f64) -> void\npublic ffi fn glVertex4f(x: f32, y: f32, z: f32, w: f32) -> void\npublic ffi fn glVertex4i(x: i32, y: i32, z: i32, w: i32) -> void\npublic ffi fn glVertex4s(x: i16, y: i16, z: i16, w: i16) -> void\npublic ffi fn glVertex2dv(v: &f64) -> void\npublic ffi fn glVertex2fv(v: &f32) -> void\npublic ffi fn glVertex2iv(v: &i32) -> void\npublic ffi fn glVertex2sv(v: &i16) -> void\npublic ffi fn glVertex3dv(v: &f64) -> void\npublic ffi fn glVertex3fv(v: &f32) -> void\npublic ffi fn glVertex3iv(v: &i32) -> void\npublic ffi fn glVertex3sv(v: &i16) -> void\npublic ffi fn glVertex4dv(v: &f64) -> void\npublic ffi fn glVertex4fv(v: &f32) -> void\npublic ffi fn glVertex4iv(v: &i32) -> void\npublic ffi fn glVertex4sv(v: &i16) -> void\npublic ffi fn glNormal3b(nx: i8, ny: i8, nz: i8) -> void\npublic ffi fn glNormal3d(nx: f64, ny: f64, nz: f64) -> void\npublic ffi fn glNormal3f(nx: f32, ny: f32, nz: f32) -> void\npublic ffi fn glNormal3i(nx: i32, ny: i32, nz: i32) -> void\npublic ffi fn glNormal3s(nx: i16, ny: i16, nz: i16) -> void\npublic ffi fn glNormal3bv(v: &i8) -> void\npublic ffi fn glNormal3dv(v: &f64) -> void\npublic ffi fn glNormal3fv(v: &f32) -> void\npublic ffi fn glNormal3iv(v: &i32) -> void\npublic ffi fn glNormal3sv(v: &i16) -> void\npublic ffi fn glIndexd(c: f64) -> void\npublic ffi fn glIndexf(c: f32) -> void\npublic ffi fn glIndexi(c: i32) -> void\npublic ffi fn glIndexs(c: i16) -> void\npublic ffi fn glIndexub(c: i8) -> void\npublic ffi fn glIndexdv(c: &f64) -> void\npublic ffi fn glIndexfv(c: &f32) -> void\npublic ffi fn glIndexiv(c: &i32) -> void\npublic ffi fn glIndexsv(c: &i16) -> void\npublic ffi fn glIndexubv(c: &i8) -> void\npublic ffi fn glColor3b(red: i8, green: i8, blue: i8) -> void\npublic ffi fn glColor3d(red: f64, green: f64, blue: f64) -> void\npublic ffi fn glColor3f(red: f32, green: f32, blue: f32) -> void\npublic ffi fn glColor3i(red: i32, green: i32, blue: i32) -> void\npublic ffi fn glColor3s(red: i16, green: i16, blue: i16) -> void\npublic ffi fn glColor3ub(red: i8, green: i8, blue: i8) -> void\npublic ffi fn glColor3ui(red: u32, green: u32, blue: u32) -> void\npublic ffi fn glColor3us(red: u16, green: u16, blue: u16) -> void\npublic ffi fn glColor4b(red: i8, green: i8, blue: i8, alpha: i8) -> void\npublic ffi fn glColor4d(red: f64, green: f64, blue: f64, alpha: f64) -> void\npublic ffi fn glColor4f(red: f32, green: f32, blue: f32, alpha: f32) -> void\npublic ffi fn glColor4i(red: i32, green: i32, blue: i32, alpha: i32) -> void\npublic ffi fn glColor4s(red: i16, green: i16, blue: i16, alpha: i16) -> void\npublic ffi fn glColor4ub(red: i8, green: i8, blue: i8, alpha: i8) -> void\npublic ffi fn glColor4ui(red: u32, green: u32, blue: u32, alpha: u32) -> void\npublic ffi fn glColor4us(red: u16, green: u16, blue: u16, alpha: u16) -> void\npublic ffi fn glColor3bv(v: &i8) -> void\npublic ffi fn glColor3dv(v: &f64) -> void\npublic ffi fn glColor3fv(v: &f32) -> void\npublic ffi fn glColor3iv(v: &i32) -> void\npublic ffi fn glColor3sv(v: &i16) -> void\npublic ffi fn glColor3ubv(v: &i8) -> void\npublic ffi fn glColor3uiv(v: &u32) -> void\npublic ffi fn glColor3usv(v: &u16) -> void\npublic ffi fn glColor4bv(v: &i8) -> void\npublic ffi fn glColor4dv(v: &f64) -> void\npublic ffi fn glColor4fv(v: &f32) -> void\npublic ffi fn glColor4iv(v: &i32) -> void\npublic ffi fn glColor4sv(v: &i16) -> void\npublic ffi fn glColor4ubv(v: &i8) -> void\npublic ffi fn glColor4uiv(v: &u32) -> void\npublic ffi fn glColor4usv(v: &u16) -> void\npublic ffi fn glTexCoord1d(s: f64) -> void\npublic ffi fn glTexCoord1f(s: f32) -> void\npublic ffi fn glTexCoord1i(s: i32) -> void\npublic ffi fn glTexCoord1s(s: i16) -> void\npublic ffi fn glTexCoord2d(s: f64, t: f64) -> void\npublic ffi fn glTexCoord2f(s: f32, t: f32) -> void\npublic ffi fn glTexCoord2i(s: i32, t: i32) -> void\npublic ffi fn glTexCoord2s(s: i16, t: i16) -> void\npublic ffi fn glTexCoord3d(s: f64, t: f64, r: f64) -> void\npublic ffi fn glTexCoord3f(s: f32, t: f32, r: f32) -> void\npublic ffi fn glTexCoord3i(s: i32, t: i32, r: i32) -> void\npublic ffi fn glTexCoord3s(s: i16, t: i16, r: i16) -> void\npublic ffi fn glTexCoord4d(s: f64, t: f64, r: f64, q: f64) -> void\npublic ffi fn glTexCoord4f(s: f32, t: f32, r: f32, q: f32) -> void\npublic ffi fn glTexCoord4i(s: i32, t: i32, r: i32, q: i32) -> void\npublic ffi fn glTexCoord4s(s: i16, t: i16, r: i16, q: i16) -> void\npublic ffi fn glTexCoord1dv(v: &f64) -> void\npublic ffi fn glTexCoord1fv(v: &f32) -> void\npublic ffi fn glTexCoord1iv(v: &i32) -> void\npublic ffi fn glTexCoord1sv(v: &i16) -> void\npublic ffi fn glTexCoord2dv(v: &f64) -> void\npublic ffi fn glTexCoord2fv(v: &f32) -> void\npublic ffi fn glTexCoord2iv(v: &i32) -> void\npublic ffi fn glTexCoord2sv(v: &i16) -> void\npublic ffi fn glTexCoord3dv(v: &f64) -> void\npublic ffi fn glTexCoord3fv(v: &f32) -> void\npublic ffi fn glTexCoord3iv(v: &i32) -> void\npublic ffi fn glTexCoord3sv(v: &i16) -> void\npublic ffi fn glTexCoord4dv(v: &f64) -> void\npublic ffi fn glTexCoord4fv(v: &f32) -> void\npublic ffi fn glTexCoord4iv(v: &i32) -> void\npublic ffi fn glTexCoord4sv(v: &i16) -> void\npublic ffi fn glRasterPos2d(x: f64, y: f64) -> void\npublic ffi fn glRasterPos2f(x: f32, y: f32) -> void\npublic ffi fn glRasterPos2i(x: i32, y: i32) -> void\npublic ffi fn glRasterPos2s(x: i16, y: i16) -> void\npublic ffi fn glRasterPos3d(x: f64, y: f64, z: f64) -> void\npublic ffi fn glRasterPos3f(x: f32, y: f32, z: f32) -> void\npublic ffi fn glRasterPos3i(x: i32, y: i32, z: i32) -> void\npublic ffi fn glRasterPos3s(x: i16, y: i16, z: i16) -> void\npublic ffi fn glRasterPos4d(x: f64, y: f64, z: f64, w: f64) -> void\npublic ffi fn glRasterPos4f(x: f32, y: f32, z: f32, w: f32) -> void\npublic ffi fn glRasterPos4i(x: i32, y: i32, z: i32, w: i32) -> void\npublic ffi fn glRasterPos4s(x: i16, y: i16, z: i16, w: i16) -> void\npublic ffi fn glRasterPos2dv(v: &f64) -> void\npublic ffi fn glRasterPos2fv(v: &f32) -> void\npublic ffi fn glRasterPos2iv(v: &i32) -> void\npublic ffi fn glRasterPos2sv(v: &i16) -> void\npublic ffi fn glRasterPos3dv(v: &f64) -> void\npublic ffi fn glRasterPos3fv(v: &f32) -> void\npublic ffi fn glRasterPos3iv(v: &i32) -> void\npublic ffi fn glRasterPos3sv(v: &i16) -> void\npublic ffi fn glRasterPos4dv(v: &f64) -> void\npublic ffi fn glRasterPos4fv(v: &f32) -> void\npublic ffi fn glRasterPos4iv(v: &i32) -> void\npublic ffi fn glRasterPos4sv(v: &i16) -> void\npublic ffi fn glRectd(x1: f64, y1: f64, x2: f64, y2: f64) -> void\npublic ffi fn glRectf(x1: f32, y1: f32, x2: f32, y2: f32) -> void\npublic ffi fn glRecti(x1: i32, y1: i32, x2: i32, y2: i32) -> void\npublic ffi fn glRects(x1: i16, y1: i16, x2: i16, y2: i16) -> void\npublic ffi fn glRectdv(v1: &f64, v2: &f64) -> void\npublic ffi fn glRectfv(v1: &f32, v2: &f32) -> void\npublic ffi fn glRectiv(v1: &i32, v2: &i32) -> void\npublic ffi fn glRectsv(v1: &i16, v2: &i16) -> void\n\n\n// Vertex Arrays\npublic ffi fn glVertexPointer(size: i32, type: GL, stride: i32, ptr: &void) -> void\npublic ffi fn glNormalPointer(type: GL, stride: i32, ptr: &void) -> void\npublic ffi fn glColorPointer(size: i32, type: GL, stride: i32, ptr: &void) -> void\npublic ffi fn glIndexPointer(type: GL, stride: i32, ptr: &void) -> void\npublic ffi fn glTexCoordPointer(size: i32, type: GL, stride: i32, ptr: &void) -> void\npublic ffi fn glEdgeFlagPointer(stride: i32, ptr: &void) -> void\npublic ffi fn glGetPointerv(pname: u32, params: &&void) -> void\npublic ffi fn glArrayElement(i: i32) -> void\npublic ffi fn glDrawArrays(mode: GL, first: i32, count: i32) -> void\npublic ffi fn glDrawElements(mode: GL, count: i32, type: GL, indices: &void) -> void\npublic ffi fn glInterleavedArrays(format: u32, stride: i32, pointer: &void) -> void\n\n// Lighting\npublic ffi fn glShadeModel(mode: u32) -> void\npublic ffi fn glLightf(light: u32, pname: u32, param: f32) -> void\npublic ffi fn glLighti(light: u32, pname: u32, param: i32) -> void\npublic ffi fn glLightfv(light: u32, pname: u32, params: &f32) -> void\npublic ffi fn glLightiv(light: u32, pname: u32, params: &i32) -> void\npublic ffi fn glGetLightfv(light: u32, pname: u32, params: &f32) -> void\npublic ffi fn glGetLightiv(light: u32, pname: u32, params: &i32) -> void\npublic ffi fn glLightModelf(pname: u32, param: f32) -> void\npublic ffi fn glLightModeli(pname: u32, param: i32) -> void\npublic ffi fn glLightModelfv(pname: u32, params: &f32) -> void\npublic ffi fn glLightModeliv(pname: u32, params: &i32) -> void\npublic ffi fn glMaterialf(face: u32, pname: u32, param: f32) -> void\npublic ffi fn glMateriali(face: u32, pname: u32, param: i32) -> void\npublic ffi fn glMaterialfv(face: u32, pname: u32, params: &f32) -> void\npublic ffi fn glMaterialiv(face: u32, pname: u32, params: &i32) -> void\npublic ffi fn glGetMaterialfv(face: u32, pname: u32, params: &f32) -> void\npublic ffi fn glGetMaterialiv(face: u32, pname: u32, params: &i32) -> void\npublic ffi fn glColorMaterial(face: u32, mode: u32) -> void\n\n\n// Raster Functions\npublic ffi fn glPixelZoom(xfactor: f32, yfactor: f32) -> void\npublic ffi fn glPixelStoref(pname: u32, param: f32) -> void\npublic ffi fn glPixelStorei(pname: u32, param: i32) -> void\npublic ffi fn glPixelTransferf(pname: u32, param: f32) -> void\npublic ffi fn glPixelTransferi(pname: u32, param: i32) -> void\npublic ffi fn glPixelMapfv(map: u32, mapsize: i32, values: &f32) -> void\npublic ffi fn glPixelMapuiv(map: u32, mapsize: i32, values: &u32) -> void\npublic ffi fn glPixelMapusv(map: u32, mapsize: i32, values: &u16) -> void\npublic ffi fn glGetPixelMapfv(map: u32, values: &f32) -> void\npublic ffi fn glGetPixelMapuiv(map: u32, values: &u32) -> void\npublic ffi fn glGetPixelMapusv(map: u32, values: &u16) -> void\npublic ffi fn glBitmap(width: i32, height: i32, xorig: f32, yorig: f32, xmove: f32,\n    ymove: f32, bitmap: &i8) -> void\npublic ffi fn glReadPixels(x: i32, y: i32, width: i32, height: i32, format: u32, type: u32, pixels: &void) -> void\npublic ffi fn glDrawPixels(width: i32, height: i32, format: u32, type: u32, pixels: &void) -> void\npublic ffi fn glCopyPixels(x: i32, y: i32, width: i32, height: i32, type: u32) -> void\n\n// Stenciling\npublic ffi fn glStencilFunc(f: u32, ref: i32, mask: u32) -> void\npublic ffi fn glStencilMask(mask: u32) -> void\npublic ffi fn glStencilOp(fail: u32, zfail: u32, zpass: u32) -> void\npublic ffi fn glClearStencil(s: i32) -> void\n\n// Texture Mapping\npublic ffi fn glTexGend(coord: u32, pname: u32, param: f64) -> void\npublic ffi fn glTexGenf(coord: u32, pname: u32, param: f32) -> void\npublic ffi fn glTexGeni(coord: u32, pname: u32, param: i32) -> void\npublic ffi fn glTexGendv(coord: u32, pname: u32, params: f64) -> void\npublic ffi fn glTexGenfv(coord: u32, pname: u32, params: f32) -> void\npublic ffi fn glTexGeniv(coord: u32, pname: u32, params: i32) -> void\npublic ffi fn glGetTexGendv(coord: u32, pname: u32, params: f64) -> void\npublic ffi fn glGetTexGenfv(coord: u32, pname: u32, params: f32) -> void\npublic ffi fn glGetTexGeniv(coord: u32, pname: u32, params: i32) -> void\npublic ffi fn glTexEnvf(target: u32, pname: u32, param: f32) -> void\npublic ffi fn glTexEnvi(target: u32, pname: u32, param: i32) -> void\npublic ffi fn glTexEnvfv(target: u32, pname: u32, params: f32) -> void\npublic ffi fn glTexEnviv(target: u32, pname: u32, params: i32) -> void\npublic ffi fn glGetTexEnvfv(target: u32, pname: u32, params: f32) -> void\npublic ffi fn glGetTexEnviv(target: u32, pname: u32, params: i32) -> void\npublic ffi fn glTexParameterf(target: u32, pname: u32, param: f32) -> void\npublic ffi fn glTexParameteri(target: u32, pname: u32, param: i32) -> void\npublic ffi fn glTexParameterfv(target: u32, pname: u32, params: f32) -> void\npublic ffi fn glTexParameteriv(target: u32, pname: u32, params: i32) -> void\npublic ffi fn glGetTexParameterfv(target: u32, pname: u32, params: f32) -> void\npublic ffi fn glGetTexParameteriv(target: u32, pname: u32, params: i32) -> void\npublic ffi fn glGetTexLevelParameterfv(target: u32, level: i32, pname: u32, params: &f32) -> void\npublic ffi fn glGetTexLevelParameteriv(target: u32, level: i32, pname: u32, params: &i32) -> void\npublic ffi fn glTexImage1D(target: u32, level: i32, internalFormat: i32, width: i32, border: i32,\n    format: u32, type: u32, pixels: &void) -> void\npublic ffi fn glTexImage2D(target: u32, level: i32, internalFormat: i32, width: i32, height: i32,\n    border: i32, format: u32, type: u32, pixels: &void) -> void\npublic ffi fn glGetTexImage(target: u32, level: i32, format: u32, type: u32, pixels: &void) -> void\n\n// OpenGL 1.1 functions\npublic ffi fn glGenTextures(n: i32, textures: &u32) -> void\npublic ffi fn glDeleteTextures(n: i32, textures: &u32) -> void\npublic ffi fn glBindTexture(target: u32, texture: u32) -> void\npublic ffi fn glPrioritizeTextures(n: i32, textures: &u32, priorities: &f32) -> void\npublic ffi fn glAreTexturesResident(n: i32, textures: &u32, residences: &bool) -> bool\npublic ffi fn glIsTexture(texture: u32) -> bool\npublic ffi fn glTexSubImage1D(target: u32, level: i32, xoffset: i32, width: i32, format: u32,\n    type: u32, pixels: &void) -> void\n\npublic ffi fn glTexSubImage2D(target: u32, level: i32, xoffset: i32, yoffset: i32, width: i32,\n    height: i32, format: u32, type: u32, pixels: &void) -> void\n\npublic ffi fn glCopyTexImage1D(target: u32, level: i32, internalformat: u32, x: i32, y: i32,\n    width: i32, border: i32) -> void\n\npublic ffi fn glCopyTexImage2D(target: u32, level: i32, internalformat: u32, x: i32, y: i32,\n    width: i32, height: i32, border: i32) -> void\n\npublic ffi fn glCopyTexSubImage1D(target: u32, level: i32, xoffset: i32, x: i32, y: i32, width: i32) -> void\npublic ffi fn glCopyTexSubImage2D(target: u32, level: i32, xoffset: i32, yoffset: i32, x: i32, y: i32,\n    width: i32, height: i32) -> void\n\n// Evaluators\npublic ffi fn glMap1d(target: u32, u1: f64, u2: f64, stride: i32, order: i32, points: &f64) -> void\npublic ffi fn glMap1f(target: u32, u1: f32, u2: f32, stride: i32, order: i32, points: &f32) -> void\npublic ffi fn glMap2d(target: u32, u1: f64, u2: f64, ustride: i32, uorder: i32,\n    v1: f64, v2: f64, vstride: i32, vorder: i32, points: &f64) -> void\npublic ffi fn glMap2f(target: u32, u1: f32, u2: f32, ustride: i32, uorder: i32,\n    v1: f32, v2: f32, vstride: i32, vorder: i32, points: &f32) -> void\npublic ffi fn glGetMapdv(target: u32, query: u32, v: &f64) -> void\npublic ffi fn glGetMapfv(target: u32, query: u32, v: &f32) -> void\npublic ffi fn glGetMapiv(target: u32, query: u32, v: &i32) -> void\npublic ffi fn glEvalCoord1d(u: f64) -> void\npublic ffi fn glEvalCoord1f(u: f32) -> void\npublic ffi fn glEvalCoord1dv(u: &f64) -> void\npublic ffi fn glEvalCoord1fv(u: &f32) -> void\npublic ffi fn glEvalCoord2d(u: f64, v: f64) -> void\npublic ffi fn glEvalCoord2f(u: f32, v: f32) -> void\npublic ffi fn glEvalCoord2dv(u: &f64) -> void\npublic ffi fn glEvalCoord2fv(u: &f32) -> void\npublic ffi fn glMapGrid1d(un: i32, u1: f64, u2: f64) -> void\npublic ffi fn glMapGrid1f(un: i32, u1: f32, u2: f32) -> void\npublic ffi fn glMapGrid2d(un: i32, u1: f64, u2: f64, vn: i32, v1: f64, v2: f64) -> void\npublic ffi fn glMapGrid2f(un: i32, u1: f32, u2: f32, vn: i32, v1: f32, v2: f32) -> void\npublic ffi fn glEvalPoint1(i: i32) -> void\npublic ffi fn glEvalPoint2(i: i32, j: i32) -> void\npublic ffi fn glEvalMesh1(mode: u32, i1: i32, i2: i32) -> void\npublic ffi fn glEvalMesh2(mode: u32, i1: i32, i2: i32, j1: i32, j2: i32) -> void\n\n// Fog\npublic ffi fn glFogf(pname: u32, param: f32) -> void\npublic ffi fn glFogi(pname: u32, param: i32) -> void\npublic ffi fn glFogfv(pname: u32, params: &f32) -> void\npublic ffi fn glFogiv(pname: u32, params: &i32) -> void\n\n// Selection and Feedback\npublic ffi fn glFeedbackBuffer(size: i32, type: u32, buffer: &f32) -> void\npublic ffi fn glPassThrough(token: f32) -> void\npublic ffi fn glSelectBuffer(size: i32, buffer: &u32) -> void\npublic ffi fn glInitNames() -> void\npublic ffi fn glLoadName(name: u32) -> void\npublic ffi fn glPushName(name: u32) -> void\npublic ffi fn glPopName() -> void\npublic ffi fn glDrawRangeElements(mode: u32, start: u32, end: u32, count: i32, type: u32, indices: &void) -> void\npublic ffi fn glTexImage3D(target: u32, level: i32, internalFormat: i32, width: i32, height: i32,\n    depth: i32, border: i32, format: u32, type: u32, pixels: &void) -> void\npublic ffi fn glTexSubImage3D(target: u32, level: i32, xoffset: i32, yoffset: i32, zoffset: i32, width: i32,\n    height: i32, depth: i32, format: u32, type: u32, pixels: &void) -> void\npublic ffi fn glCopyTexSubImage3D(target: u32, level: i32, xoffset: i32, yoffset: i32, zoffset: i32, x: i32,\n    y: i32, width: i32, height: i32) -> void\npublic ffi fn glColorTable(target: u32, internalformat: u32, width: i32, format: u32, type: u32,\n    table: &void) -> void\npublic ffi fn glColorSubTable(target: u32, start: i32, count: i32, format: u32, type: u32, data: &void) -> void\npublic ffi fn glColorTableParameteriv(target: u32, pname: u32, params: &i32) -> void\npublic ffi fn glColorTableParameterfv(target: u32, pname: u32, params: &f32) -> void\npublic ffi fn glCopyColorSubTable(target: u32, start: i32, x: i32, y: i32, width: i32) -> void\npublic ffi fn glCopyColorTable(target: u32, internalformat: u32, x: i32, y: i32, width: i32) -> void\npublic ffi fn glGetColorTable(target: u32, format: u32, type: u32, table: &void) -> void\npublic ffi fn glGetColorTableParameterfv(target: u32, pname: u32, params: &f32) -> void\npublic ffi fn glGetColorTableParameteriv(target: u32, pname: u32, params: &i32) -> void\npublic ffi fn glBlendEquation(mode: u32) -> void\npublic ffi fn glBlendColor(red: f32, green: f32, blue: f32, alpha: f32) -> void\npublic ffi fn glHistogram(target: u32, width: i32, internalformat: u32, sink: bool) -> void\npublic ffi fn glResetHistogram(target: u32) -> void\npublic ffi fn glGetHistogram(target: u32, reset: bool, format: u32, type: u32, values: &void) -> void\npublic ffi fn glGetHistogramParameterfv(target: u32, pname: u32, params: &f32) -> void\npublic ffi fn glGetHistogramParameteriv(target: u32, pname: u32, params: &i32) -> void\npublic ffi fn glMinmax(target: u32, internalformat: u32, sink: bool) -> void\npublic ffi fn glResetMinmax(target: u32) -> void\npublic ffi fn glGetMinmax(target: u32, reset: bool, format: u32, types: u32, values: &void) -> void\npublic ffi fn glGetMinmaxParameterfv(target: u32, pname: u32, params: &f32) -> void\npublic ffi fn glGetMinmaxParameteriv(target: u32, pname: u32, params: &i32) -> void\npublic ffi fn glConvolutionFilter1D(target: u32, internalformat: u32, width: i32, format: u32, type: u32,\n    image: &void) -> void\n\npublic ffi fn glConvolutionFilter2D(target: u32, internalformat: u32, width: i32, height: i32, format: u32,\n    type: u32, image: &void) -> void\n\npublic ffi fn glConvolutionParameterf(target: u32, pname: u32, params: f32) -> void\npublic ffi fn glConvolutionParameterfv(target: u32, pname: u32, params: &f32) -> void\npublic ffi fn glConvolutionParameteri(target: u32, pname: u32, params: i32) -> void\npublic ffi fn glConvolutionParameteriv(target: u32, pname: u32, params: &i32) -> void\npublic ffi fn glCopyConvolutionFilter1D(target: u32, internalformat: u32, x: i32, y: i32, width: i32) -> void\npublic ffi fn glCopyConvolutionFilter2D(target: u32, internalformat: u32, x: i32, y: i32, width: i32,\n    height: i32) -> void\n\npublic ffi fn glGetConvolutionFilter(target: u32, format: u32, type: u32, image: &void) -> void\npublic ffi fn glGetConvolutionParameterfv(target: u32, pname: u32, params: &f32) -> void\npublic ffi fn glGetConvolutionParameteriv(target: u32, pname: u32, params: &i32) -> void\n\npublic ffi fn glSeparableFilter2D(target: u32, internalformat: u32, width: i32, height: i32, format: u32,\n    type: u32, row: &void, column: &void) -> void\n\npublic ffi fn glGetSeparableFilter(target: u32, format: u32, type: u32, row: &void, column: &void, span: &void) -> void\n\npublic ffi fn glActiveTexture(texture: u32) -> void\npublic ffi fn glClientActiveTexture(texture: u32) -> void\n\npublic ffi fn glCompressedTexImage1D(target: u32, level: i32, internalformat: u32, width: i32, border: i32,\n    imageSize: i32, data: &void) -> void\n\npublic ffi fn glCompressedTexImage2D(target: u32, level: i32, internalformat: u32, width: i32, height: i32,\n    border: i32, imageSize: i32, data: &void) -> void\n\npublic ffi fn glCompressedTexImage3D(target: u32, level: i32, internalformat: u32, width: i32, height: i32,\n     voiddepth: i32, border: i32, imageSize: i32, data: &void)\n\npublic ffi fn glCompressedTexSubImage1D(target: u32, level: i32, xoffset: i32, width: i32, format: u32,\n    imageSize: i32, data: &void) -> void\n\npublic ffi fn glCompressedTexSubImage2D(target: u32, level: i32, xoffset: i32, yoffset: i32, width: i32,\n    height: i32, format: u32, imageSize: i32, data: &void) -> void\n\npublic ffi fn glCompressedTexSubImage3D(target: u32, level: i32, xoffset: i32, yoffset: i32, zoffset: i32,\n    width: i32, height: i32, depth: i32, format: u32, imageSize: i32, data: &void) -> void\n\npublic ffi fn glGetCompressedTexImage(target: u32, lod: i32, img: &void) -> void\npublic ffi fn glMultiTexCoord1d(target: u32, s: f64) -> void\npublic ffi fn glMultiTexCoord1dv(target: u32, v: &f64) -> void\npublic ffi fn glMultiTexCoord1f(target: u32, s: f32) -> void\npublic ffi fn glMultiTexCoord1fv(target: u32, v: &f32) -> void\npublic ffi fn glMultiTexCoord1i(target: u32, s: i32) -> void\npublic ffi fn glMultiTexCoord1iv(target: u32, v: &i32) -> void\npublic ffi fn glMultiTexCoord1s(target: u32, s: i16) -> void\npublic ffi fn glMultiTexCoord1sv(target: u32, v: &i16) -> void\npublic ffi fn glMultiTexCoord2d(target: u32, s: f64, t: f64) -> void\npublic ffi fn glMultiTexCoord2dv(target: u32, v: &f64) -> void\npublic ffi fn glMultiTexCoord2f(target: u32, s: f32, t: f32) -> void\npublic ffi fn glMultiTexCoord2fv(target: u32, v: &f32) -> void\npublic ffi fn glMultiTexCoord2i(target: u32, s: i32, t: i32) -> void\npublic ffi fn glMultiTexCoord2iv(target: u32, v: &i32) -> void\npublic ffi fn glMultiTexCoord2s(target: u32, s: i16, t: i16) -> void\npublic ffi fn glMultiTexCoord2sv(target: u32, v: &i16) -> void\npublic ffi fn glMultiTexCoord3d(target: u32, s: f64, t: f64, r: f64) -> void\npublic ffi fn glMultiTexCoord3dv(target: u32, v: &f64) -> void\npublic ffi fn glMultiTexCoord3f(target: u32, s: f32, t: f32, r: f32) -> void\npublic ffi fn glMultiTexCoord3fv(target: u32, v: &f32) -> void\npublic ffi fn glMultiTexCoord3i(target: u32, s: i32, t: i32, r: i32) -> void\npublic ffi fn glMultiTexCoord3iv(target: u32, v: &i32) -> void\npublic ffi fn glMultiTexCoord3s(target: u32, s: i16, t: i16, r: i16) -> void\npublic ffi fn glMultiTexCoord3sv(target: u32, v: &i16) -> void\npublic ffi fn glMultiTexCoord4d(target: u32, s: f64, t: f64, r: f64, q: f64) -> void\npublic ffi fn glMultiTexCoord4dv(target: u32, v: &f64) -> void\npublic ffi fn glMultiTexCoord4f(target: u32, s: f32, t: f32, r: f32, q: f32) -> void\npublic ffi fn glMultiTexCoord4fv(target: u32, v: &f32) -> void\npublic ffi fn glMultiTexCoord4i(target: u32, s: i32, t: i32, r: i32, q: i32) -> void\npublic ffi fn glMultiTexCoord4iv(target: u32, v: &i32) -> void\npublic ffi fn glMultiTexCoord4s(target: u32, s: i16, t: i16, r: i16, q: i16) -> void\npublic ffi fn glMultiTexCoord4sv(target: u32, v: &i16) -> void\npublic ffi fn glLoadTransposeMatrixd(m: [f64: 16]) -> void\npublic ffi fn glLoadTransposeMatrixf(m: [f32: 16]) -> void\npublic ffi fn glMultTransposeMatrixd(m: [f64: 16]) -> void\npublic ffi fn glMultTransposeMatrixf(m: [f32: 16]) -> void\npublic ffi fn glSampleCoverage(value: f32, invert: bool) -> void\npublic ffi fn glActiveTextureARB(texture: u32) -> void\npublic ffi fn glClientActiveTextureARB(texture: u32) -> void\npublic ffi fn glMultiTexCoord1dARB(target: u32, s: f64) -> void\npublic ffi fn glMultiTexCoord1dvARB(target: u32, v: &f64) -> void\npublic ffi fn glMultiTexCoord1fARB(target: u32, s: f32) -> void\npublic ffi fn glMultiTexCoord1fvARB(target: u32, v: &f32) -> void\npublic ffi fn glMultiTexCoord1iARB(target: u32, s: i32) -> void\npublic ffi fn glMultiTexCoord1ivARB(target: u32, v: &i32) -> void\npublic ffi fn glMultiTexCoord1sARB(target: u32, s: i16) -> void\npublic ffi fn glMultiTexCoord1svARB(target: u32, v: &i16) -> void\npublic ffi fn glMultiTexCoord2dARB(target: u32, s: f64, t: f64) -> void\npublic ffi fn glMultiTexCoord2dvARB(target: u32, v: &f64) -> void\npublic ffi fn glMultiTexCoord2fARB(target: u32, s: f32, t: f32) -> void\npublic ffi fn glMultiTexCoord2fvARB(target: u32, v: &f32) -> void\npublic ffi fn glMultiTexCoord2iARB(target: u32, s: i32, t: i32) -> void\npublic ffi fn glMultiTexCoord2ivARB(target: u32, v: &i32) -> void\npublic ffi fn glMultiTexCoord2sARB(target: u32, s: i16, t: i16) -> void\npublic ffi fn glMultiTexCoord2svARB(target: u32, v: &i16) -> void\npublic ffi fn glMultiTexCoord3dARB(target: u32, s: f64, t: f64, r: f64) -> void\npublic ffi fn glMultiTexCoord3dvARB(target: u32, v: &f64) -> void\npublic ffi fn glMultiTexCoord3fARB(target: u32, s: f32, t: f32, r: f32) -> void\npublic ffi fn glMultiTexCoord3fvARB(target: u32, v: &f32) -> void\npublic ffi fn glMultiTexCoord3iARB(target: u32, s: i32, t: i32, r: i32) -> void\npublic ffi fn glMultiTexCoord3ivARB(target: u32, v: &i32) -> void\npublic ffi fn glMultiTexCoord3sARB(target: u32, s: i16, t: i16, r: i16) -> void\npublic ffi fn glMultiTexCoord3svARB(target: u32, v: &i16) -> void\npublic ffi fn glMultiTexCoord4dARB(target: u32, s: f64, t: f64, r: f64, q: f64) -> void\npublic ffi fn glMultiTexCoord4dvARB(target: u32, v: &f64) -> void\npublic ffi fn glMultiTexCoord4fARB(target: u32, s: f32, t: f32, r: f32, q: f32) -> void\npublic ffi fn glMultiTexCoord4fvARB(target: u32, v: &f32) -> void\npublic ffi fn glMultiTexCoord4iARB(target: u32, s: i32, t: i32, r: i32, q: i32) -> void\npublic ffi fn glMultiTexCoord4ivARB(target: u32, v: &i32) -> void\npublic ffi fn glMultiTexCoord4sARB(target: u32, s: i16, t: i16, r: i16, q: i16) -> void\npublic ffi fn glMultiTexCoord4svARB(target: u32, v: &i16) -> void\n\n\n\n\n\n\n\n"
  },
  {
    "path": "libs/OpenGL/GLUT.flx",
    "content": "// GLUT.flx\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\npublic namespace GLUT\n{\n\tpublic let RGB: i32\t\t\t= 0\n\tpublic let RGBA: i32\t\t= 0\n\tpublic let INDEX: i32\t\t= 1\n\n\tpublic let SINGLE: i32\t\t= 0\n\tpublic let DOUBLE: i32\t\t= 2\n\tpublic let ACCUM: i32\t\t= 4\n\tpublic let ALPHA: i32\t\t= 8\n\tpublic let DEPTH: i32\t\t= 16\n\tpublic let STENCIL: i32\t\t= 32\n}\n\n\npublic ffi fn glutInit(argcp: &i32, argv: &&i8)\npublic ffi fn glutInitDisplayMode(mode: u32)\npublic ffi fn glutInitDisplayString(s: &i8)\npublic ffi fn glutInitWindowPosition(x: i32, y: i32)\npublic ffi fn glutInitWindowSize(width: i32, height: i32)\npublic ffi fn glutMainLoop()\n\npublic ffi fn glutCreateWindow(title: &i8) -> i32\npublic ffi fn glutCreateSubWindow(win: i32, x: i32, y: i32, width: i32, height: i32) -> i32\npublic ffi fn glutDestroyWindow(win: i32) -> void\npublic ffi fn glutPostRedisplay() -> void\npublic ffi fn glutPostWindowRedisplay(win: i32) -> void\npublic ffi fn glutSwapBuffers() -> void\npublic ffi fn glutGetWindow() -> i32\npublic ffi fn glutSetWindow(win: i32) -> void\npublic ffi fn glutSetWindowTitle(title: &i8) -> void\npublic ffi fn glutSetIconTitle(title: &i8) -> void\npublic ffi fn glutPositionWindow(x: i32, y: i32) -> void\npublic ffi fn glutReshapeWindow(width: i32, height: i32) -> void\npublic ffi fn glutPopWindow() -> void\npublic ffi fn glutPushWindow() -> void\npublic ffi fn glutIconifyWindow() -> void\npublic ffi fn glutShowWindow() -> void\npublic ffi fn glutHideWindow() -> void\npublic ffi fn glutFullScreen() -> void\npublic ffi fn glutSetCursor(cursor: i32) -> void\npublic ffi fn glutWarpPointer(x: i32, y: i32) -> void\n\n\npublic ffi fn glutSolidDodecahedron() -> void\n\n"
  },
  {
    "path": "libs/SDL2/Keyboard.flx",
    "content": "// Keyboard.flx\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport SDL::Keyboard\n\npublic enum Key: u32\n{\n\tcase UNKNOWN            = 0\n\n\tcase Backspace          = 0x08\n\tcase Tab                = 0x09\n\tcase Return             = 0x0D\n\tcase Escape             = 0x1B\n\n\tcase Space              = 0x20\n\tcase Exclaim            = 0x21\n\tcase DoubleQuote        = 0x21\n\tcase Hash               = 0x22\n\tcase Dollar             = 0x23\n\tcase Percent            = 0x24\n\tcase Ampersand          = 0x25\n\tcase Quote              = 0x26\n\tcase LeftParen          = 0x27\n\tcase RightParen         = 0x28\n\tcase Asterisk           = 0x29\n\tcase Plus               = 0x2A\n\tcase Comma              = 0x2B\n\tcase Minus              = 0x2C\n\tcase Period             = 0x2D\n\tcase Slash              = 0x2E\n\tcase Zero               = 0x2F\n\tcase One                = 0x30\n\tcase Two                = 0x31\n\tcase Three              = 0x32\n\tcase Four               = 0x33\n\tcase Five               = 0x34\n\tcase Six                = 0x35\n\tcase Seven              = 0x36\n\tcase Eight              = 0x37\n\tcase Nine               = 0x38\n\tcase Ten                = 0x39\n\tcase Colon              = 0x3A\n\tcase Semicolon          = 0x3B\n\tcase Less               = 0x3C\n\tcase Equals             = 0x3D\n\tcase Greater            = 0x3E\n\tcase Question           = 0x3F\n\tcase At                 = 0x40\n\n\t// Skip uppercase letters\n\tcase LeftBracket        = 0x41\n\tcase Backslash          = 0x42\n\tcase RightBracket       = 0x45\n\tcase Caret              = 0x46\n\tcase Underscore         = 0x47\n\tcase Backquote          = 0x48\n\n\tcase A\t\t\t\t\t= 0x61\n\tcase B                  = 0x62\n\tcase C                  = 0x63\n\tcase D                  = 0x64\n\tcase E                  = 0x65\n\tcase F                  = 0x66\n\tcase G                  = 0x67\n\tcase H                  = 0x68\n\tcase I                  = 0x69\n\tcase J                  = 0x6A\n\tcase K                  = 0x6B\n\tcase L                  = 0x6C\n\tcase M                  = 0x6D\n\tcase N                  = 0x6E\n\tcase O                  = 0x6F\n\tcase P                  = 0x70\n\tcase Q                  = 0x71\n\tcase R                  = 0x72\n\tcase S                  = 0x73\n\tcase T                  = 0x74\n\tcase U                  = 0x75\n\tcase V                  = 0x76\n\tcase W                  = 0x77\n\tcase X                  = 0x78\n\tcase Y                  = 0x79\n\tcase Z                  = 0x7A\n\n\t/*CAPSLOCK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CAPSLOCK),\n\n\tF1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F1),\n\tF2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F2),\n\tF3 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F3),\n\tF4 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F4),\n\tF5 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F5),\n\tF6 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F6),\n\tF7 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F7),\n\tF8 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F8),\n\tF9 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F9),\n\tF10 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F10),\n\tF11 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F11),\n\tF12 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F12),\n\n\tPRINTSCREEN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PRINTSCREEN),\n\tSCROLLLOCK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SCROLLLOCK),\n\tPAUSE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAUSE),\n\tINSERT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_INSERT),\n\tHOME = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_HOME),\n\tPAGEUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEUP),\n\tDELETE = '\\177',\n\tEND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_END),\n\tPAGEDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEDOWN),\n\tRIGHT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RIGHT),\n\tLEFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LEFT),\n\tDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DOWN),\n\tUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_UP),\n\n\tNUMLOCKCLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_NUMLOCKCLEAR),\n\tKP_DIVIDE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DIVIDE),\n\tKP_MULTIPLY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MULTIPLY),\n\tKP_MINUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MINUS),\n\tKP_PLUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PLUS),\n\tKP_ENTER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_ENTER),\n\tKP_1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_1),\n\tKP_2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_2),\n\tKP_3 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_3),\n\tKP_4 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_4),\n\tKP_5 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_5),\n\tKP_6 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_6),\n\tKP_7 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_7),\n\tKP_8 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_8),\n\tKP_9 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_9),\n\tKP_0 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_0),\n\tKP_PERIOD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PERIOD),\n\n\tAPPLICATION = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APPLICATION),\n\tPOWER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_POWER),\n\tKP_EQUALS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EQUALS),\n\tF13 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F13),\n\tF14 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F14),\n\tF15 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F15),\n\tF16 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F16),\n\tF17 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F17),\n\tF18 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F18),\n\tF19 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F19),\n\tF20 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F20),\n\tF21 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F21),\n\tF22 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F22),\n\tF23 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F23),\n\tF24 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F24),\n\tEXECUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EXECUTE),\n\tHELP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_HELP),\n\tMENU = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MENU),\n\tSELECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SELECT),\n\tSTOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_STOP),\n\tAGAIN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AGAIN),\n\tUNDO = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_UNDO),\n\tCUT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CUT),\n\tCOPY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_COPY),\n\tPASTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PASTE),\n\tFIND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_FIND),\n\tMUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MUTE),\n\tVOLUMEUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_VOLUMEUP),\n\tVOLUMEDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_VOLUMEDOWN),\n\tKP_COMMA = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_COMMA),\n\tKP_EQUALSAS400 =\n\tSDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EQUALSAS400),\n\n\tALTERASE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_ALTERASE),\n\tSYSREQ = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SYSREQ),\n\tCANCEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CANCEL),\n\tCLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CLEAR),\n\tPRIOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PRIOR),\n\tRETURN2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RETURN2),\n\tSEPARATOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SEPARATOR),\n\tOUT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_OUT),\n\tOPER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_OPER),\n\tCLEARAGAIN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CLEARAGAIN),\n\tCRSEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CRSEL),\n\tEXSEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EXSEL),\n\n\tKP_00 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_00),\n\tKP_000 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_000),\n\tTHOUSANDSSEPARATOR =\n\tSDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_THOUSANDSSEPARATOR),\n\tDECIMALSEPARATOR =\n\tSDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DECIMALSEPARATOR),\n\tCURRENCYUNIT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CURRENCYUNIT),\n\tCURRENCYSUBUNIT =\n\tSDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CURRENCYSUBUNIT),\n\tKP_LEFTPAREN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LEFTPAREN),\n\tKP_RIGHTPAREN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_RIGHTPAREN),\n\tKP_LEFTBRACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LEFTBRACE),\n\tKP_RIGHTBRACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_RIGHTBRACE),\n\tKP_TAB = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_TAB),\n\tKP_BACKSPACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_BACKSPACE),\n\tKP_A = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_A),\n\tKP_B = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_B),\n\tKP_C = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_C),\n\tKP_D = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_D),\n\tKP_E = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_E),\n\tKP_F = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_F),\n\tKP_XOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_XOR),\n\tKP_POWER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_POWER),\n\tKP_PERCENT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PERCENT),\n\tKP_LESS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LESS),\n\tKP_GREATER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_GREATER),\n\tKP_AMPERSAND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_AMPERSAND),\n\tKP_DBLAMPERSAND =\n\tSDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DBLAMPERSAND),\n\tKP_VERTICALBAR =\n\tSDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_VERTICALBAR),\n\tKP_DBLVERTICALBAR =\n\tSDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DBLVERTICALBAR),\n\tKP_COLON = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_COLON),\n\tKP_HASH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_HASH),\n\tKP_SPACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_SPACE),\n\tKP_AT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_AT),\n\tKP_EXCLAM = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EXCLAM),\n\tKP_MEMSTORE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMSTORE),\n\tKP_MEMRECALL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMRECALL),\n\tKP_MEMCLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMCLEAR),\n\tKP_MEMADD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMADD),\n\tKP_MEMSUBTRACT =\n\tSDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMSUBTRACT),\n\tKP_MEMMULTIPLY =\n\tSDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMMULTIPLY),\n\tKP_MEMDIVIDE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMDIVIDE),\n\tKP_PLUSMINUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PLUSMINUS),\n\tKP_CLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_CLEAR),\n\tKP_CLEARENTRY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_CLEARENTRY),\n\tKP_BINARY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_BINARY),\n\tKP_OCTAL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_OCTAL),\n\tKP_DECIMAL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DECIMAL),\n\tKP_HEXADECIMAL =\n\tSDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_HEXADECIMAL),\n\n\tLCTRL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LCTRL),\n\tLSHIFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LSHIFT),\n\tLALT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LALT),\n\tLGUI = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LGUI),\n\tRCTRL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RCTRL),\n\tRSHIFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RSHIFT),\n\tRALT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RALT),\n\tRGUI = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RGUI),\n\n\tMODE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MODE),\n\n\tAUDIONEXT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIONEXT),\n\tAUDIOPREV = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOPREV),\n\tAUDIOSTOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOSTOP),\n\tAUDIOPLAY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOPLAY),\n\tAUDIOMUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOMUTE),\n\tMEDIASELECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MEDIASELECT),\n\tWWW = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_WWW),\n\tMAIL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MAIL),\n\tCALCULATOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CALCULATOR),\n\tCOMPUTER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_COMPUTER),\n\tAC_SEARCH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_SEARCH),\n\tAC_HOME = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_HOME),\n\tAC_BACK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_BACK),\n\tAC_FORWARD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_FORWARD),\n\tAC_STOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_STOP),\n\tAC_REFRESH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_REFRESH),\n\tAC_BOOKMARKS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_BOOKMARKS),\n\n\tBRIGHTNESSDOWN =\n\tSDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_BRIGHTNESSDOWN),\n\tBRIGHTNESSUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_BRIGHTNESSUP),\n\tDISPLAYSWITCH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DISPLAYSWITCH),\n\tKBDILLUMTOGGLE =\n\tSDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMTOGGLE),\n\tKBDILLUMDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMDOWN),\n\tKBDILLUMUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMUP),\n\tEJECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EJECT),\n\tSLEEP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SLEEP)*/\n}\n\n\n// #define SCANCODE_MASK (1<<30)\n// #define SDL_SCANCODE_TO_KEYCODE(X)  (X | SCANCODE_MASK)\n\n// enum\n// {\n// };\n\n// /**\n//  * \\brief Enumeration of valid key mods (possibly OR'd together).\n//  */\n// typedef enum\n// {\n//     KMOD_NONE = 0x0000,\n//     KMOD_LSHIFT = 0x0001,\n//     KMOD_RSHIFT = 0x0002,\n//     KMOD_LCTRL = 0x0040,\n//     KMOD_RCTRL = 0x0080,\n//     KMOD_LALT = 0x0100,\n//     KMOD_RALT = 0x0200,\n//     KMOD_LGUI = 0x0400,\n//     KMOD_RGUI = 0x0800,\n//     KMOD_NUM = 0x1000,\n//     KMOD_CAPS = 0x2000,\n//     KMOD_MODE = 0x4000,\n//     KMOD_RESERVED = 0x8000\n// } SDL_Keymod;\n\n// #define KMOD_CTRL   (KMOD_LCTRL|KMOD_RCTRL)\n// #define KMOD_SHIFT  (KMOD_LSHIFT|KMOD_RSHIFT)\n// #define KMOD_ALT    (KMOD_LALT|KMOD_RALT)\n// #define KMOD_GUI    (KMOD_LGUI|KMOD_RGUI)\n"
  },
  {
    "path": "libs/SDL2/SDL.flx",
    "content": "// SDL.flx\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport SDL\n\nimport \"Keyboard.flx\"\n\n\npublic let INIT_TIMER: u32                      = 0x00000001\npublic let INIT_AUDIO: u32                      = 0x00000010\npublic let INIT_VIDEO: u32                      = 0x00000020\npublic let INIT_JOYSTICK: u32                   = 0x00000200\npublic let INIT_HAPTIC: u32                     = 0x00001000\npublic let INIT_GAMECONTROLLER: u32             = 0x00002000\npublic let INIT_EVENTS: u32                     = 0x00004000\npublic let INIT_NOPARACHUTE: u32                = 0x00100000\npublic let INIT_EVERYTHING: u32                 = INIT_TIMER | INIT_AUDIO | INIT_VIDEO | INIT_EVENTS |\n\t\t\t\t\t\t\t\t\t\t\t\t\tINIT_JOYSTICK | INIT_HAPTIC | INIT_GAMECONTROLLER\n\npublic let GL_RED_SIZE: i32                     = 0\npublic let GL_GREEN_SIZE: i32                   = 1\npublic let GL_BLUE_SIZE: i32                    = 2\npublic let GL_ALPHA_SIZE: i32                   = 3\npublic let GL_BUFFER_SIZE: i32                  = 4\npublic let GL_DOUBLEBUFFER: i32                 = 5\npublic let GL_DEPTH_SIZE: i32                   = 6\npublic let GL_STENCIL_SIZE: i32                 = 7\npublic let GL_ACCUM_RED_SIZE: i32               = 8\npublic let GL_ACCUM_GREEN_SIZE: i32             = 9\npublic let GL_ACCUM_BLUE_SIZE: i32              = 10\npublic let GL_ACCUM_ALPHA_SIZE: i32             = 11\npublic let GL_STEREO: i32                       = 12\npublic let GL_MULTISAMPLEBUFFERS: i32           = 13\npublic let GL_MULTISAMPLESAMPLES: i32           = 14\npublic let GL_ACCELERATED_VISUAL: i32           = 15\npublic let GL_RETAINED_BACKING: i32             = 16\npublic let GL_CONTEXT_MAJOR_VERSION: i32        = 17\npublic let GL_CONTEXT_MINOR_VERSION: i32        = 18\npublic let GL_CONTEXT_EGL: i32                  = 19\npublic let GL_CONTEXT_FLAGS: i32                = 20\npublic let GL_CONTEXT_PROFILE_MASK: i32         = 21\npublic let GL_SHARE_WITH_CURRENT_CONTEXT: i32   = 22\npublic let GL_FRAMEBUFFER_SRGB_CAPABLE: i32     = 23\npublic let GL_CONTEXT_RELEASE_BEHAVIOR: i32     = 24\n\n\npublic enum EventType: u32\n{\n\tcase FIRSTEVENT                 = 0\n\n\tcase Quit                       = 0x100\n\tcase App_Terminating            = 0x101\n\tcase App_LowMemory              = 0x102\n\tcase App_WillEnterBackground    = 0x103\n\tcase App_DidEnterBackground     = 0x104\n\tcase App_WillEnterForeground    = 0x105\n\tcase App_DidEnterForeground     = 0x106\n\n\tcase WindowEvent                = 0x200\n\tcase SysWMEvent                 = 0x201\n\n\tcase KeyDown                    = 0x300\n\tcase KeyUp                      = 0x301\n\tcase TextEditing                = 0x302\n\tcase TextInput                  = 0x303\n\tcase KeymapChanged              = 0x304\n\n\tcase Mouse_Motion               = 0x400\n\tcase Mouse_ButtonDown           = 0x401\n\tcase Mouse_ButtonUp             = 0x402\n\tcase Mouse_Wheel                = 0x403\n\n\tcase Joy_AxisMotion             = 0x600\n\tcase Joy_BallMotion             = 0x601\n\tcase Joy_HatMotion              = 0x602\n\tcase Joy_ButtonDown             = 0x603\n\tcase Joy_ButtonUp               = 0x604\n\tcase Joy_DeviceAdded            = 0x605\n\tcase Joy_DeviceRemoved          = 0x606\n\n\tcase Controller_AxisMotion      = 0x650\n\tcase Controller_ButtonDown      = 0x651\n\tcase Controller_ButtonUp        = 0x652\n\tcase Controller_DeviceAdded     = 0x653\n\tcase Controller_DeviceRemoved   = 0x654\n\tcase Controller_DeviceRemapped  = 0x655\n\n\tcase FingerDown                 = 0x700\n\tcase FingerUp                   = 0x701\n\tcase FingerMotion               = 0x702\n\n\tcase DollarGesture              = 0x800\n\tcase DollarRecord               = 0x801\n\tcase MultiGesture               = 0x802\n\n\tcase ClipboardUpdate            = 0x900\n\n\tcase DropFile                   = 0x1000\n\n\tcase Audio_DeviceAdded          = 0x1100\n\tcase Audio_DeviceRemoved        = 0x1101\n\n\tcase Render_TargetsReset        = 0x2000\n\tcase Render_DeviceReset         = 0x2001\n\n\tcase USEREVENT                  = 0x8000\n\tcase LASTEVENT                  = 0xFFFF\n}\n\npublic struct Event\n{\n\ttype: EventType\n\tlol: [i8: 52]\n}\n\nstruct KeySym\n{\n\t// SDL_Scancode scancode\n\tscancode: u32\n\tsym: Keyboard::Key\n\n\tmod: u16\n\tunused: u32\n}\n\npublic struct KeyboardEvent\n{\n\ttype: EventType\n\ttimestamp: u32\n\twindowid: u32\n\tstate: u8\n\trepeat: u8\n\tpadding: u16\n\tkeysym: KeySym\n}\n\npublic ffi fn SDL_Init(flags: u32) -> i32\npublic ffi fn SDL_CreateWindow(title: &i8, xpos: i32, ypos: i32, width: i32, height: i32, flags: u32) -> &void\n\n\npublic ffi fn SDL_GL_SetAttribute(attr: i32, value: i32)\n\npublic ffi fn SDL_PollEvent(event: &SDL::Event) -> i32\n\n// opengl stuff\n\npublic ffi fn SDL_GL_CreateContext(window: &void) -> &void\npublic ffi fn SDL_GL_SwapWindow(window: &void) -> void\n\n\n\n\n"
  },
  {
    "path": "libs/libc.flx",
    "content": "// libc.flx\n// Copyright (c) 2014 - 2015, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport libc\n\n// printing\npublic ffi fn puts(fmt: &i8) -> i32\npublic ffi fn printf(fmt: &i8, ...) -> i32\npublic ffi fn sprintf(fmt: &i8, y: &i8, ...) -> i32\npublic ffi fn snprintf(fmt: &i8, l: u64, y: &i8, ...) -> i32\n\npublic ffi fn fprintf(stream: &void, y: &i8, ...) -> i32\n\npublic ffi fn putchar(x: i32) -> i32\n\n\n// memcpy/set/move\npublic ffi fn memcpy(dest: &i8, source: &i8, length: u64) -> &i8\npublic ffi fn memmove(dest: &i8, source: &i8, length: u64) -> &i8\npublic ffi fn memset(dest: &i8, value: i32, length: u64) -> &i8\n\n// heap\n// public ffi fn malloc(size: i64) -> &i8\n// public ffi fn free(pointer: &i8)\n\n// strings\npublic ffi fn strlen(s: &i8) -> i64\npublic ffi fn strcmp(s1: &i8, s2: &i8) -> i32\npublic ffi fn strncmp(s1: &i8, s2: &i8, length: i64) -> i32\n\n// random things\npublic ffi fn usleep(usec: u32) -> i32\npublic ffi fn sleep(sec: u32) -> u32\npublic ffi fn abort()\npublic ffi fn exit(status: i32)\n\n// file stuff\npublic ffi fn fsync(fd: i32) -> i32\npublic ffi fn fflush(fd: &void) -> i32\npublic ffi fn ioctl(fd: i32, cmd: u64, ...) -> i32\n\npublic ffi fn fopen(path: &i8, mode: &i8) -> &void\npublic ffi fn fread(buf: &i8, sz: u64, cnt: u64, file: &void) -> u64\npublic ffi fn fclose(file: &void) -> i32\n\n// unistd.h\n\n\n// posix stuff, that windows likes to rename for some reason!!!!!\n#if os::name == \"windows\"\n{\n\t// unistd.h\n\tpublic ffi fn open(path: &i8, flags: i32, mode: i32) -> i32     as \"_open\"\n\tpublic ffi fn close(fd: i32) -> i32                             as \"_close\"\n\n\tpublic ffi fn read(fd: i32, buf: &i8, count: i64) -> i64        as \"_read\"\n\tpublic ffi fn write(fd: i32, buf: &i8, count: i64) -> i64       as \"_write\"\n\n\tpublic ffi fn lseek(fd: i32, ofs: i64, whence: i32) -> i64      as \"_lseek\"\n\n\t// stdio.h\n\tpublic ffi fn fdopen(fd: i32, mode: &i8) -> &void               as \"_fdopen\"\n}\nelse\n{\n\t// unistd.h\n\tpublic ffi fn open(path: &i8, flags: i32, mode: i32) -> i32\n\tpublic ffi fn close(fd: i32) -> i32\n\n\tpublic ffi fn read(fd: i32, buf: &i8, count: i64) -> i64\n\tpublic ffi fn write(fd: i32, buf: &i8, count: i64) -> i64\n\n\tpublic ffi fn lseek(fd: i32, ofs: i64, whence: i32) -> i64\n\n\t// stdio.h\n\tpublic ffi fn fdopen(fd: i32, mode: &i8) -> &void\n}\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "libs/os.flx",
    "content": "// os.flx\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport os\n"
  },
  {
    "path": "libs/std/file.flx",
    "content": "// file.flx\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport std::io\nimport libc\n\n// // rudimentary file handling\n// public struct File\n// {\n// \tfd: int\n// \tbuf: [i8]\n// }\n\n// public enum Mode\n// {\n// \tcase Read\n// \tcase Write\n// \tcase ReadWrite\n// \tcase Append\n// }\n\n// let O_RDONLY: i32   = 0x0000    // open for reading only\n// let O_WRONLY: i32   = 0x0001    // open for writing only\n// let O_RDWR: i32     = 0x0002    // open for reading and writing\n// let O_ACCMODE: i32  = 0x0003    // mask for above modes\n// let O_NONBLOCK: i32 = 0x0004    // no delay\n// let O_APPEND: i32   = 0x0008    // set append mode\n// let O_CREAT: i32    = 0x0200    // create if nonexistant\n// let O_TRUNC: i32    = 0x0400    // truncate to zero length\n// let O_EXCL: i32     = 0x0800    // error if already exists\n\n// let SEEK_SET: i32   = 0         // set file offset to offset\n// let SEEK_CUR: i32   = 1         // set file offset to current plus offset\n// let SEEK_END: i32   = 2         // set file offset to EOF plus offset\n\n// public fn open(path: str, mode: Mode) -> File\n// {\n// \tvar flags: i32\n// \tif mode == Mode::Read       => flags = O_RDONLY\n// \tif mode == Mode::Write      => flags = O_WRONLY\n// \tif mode == Mode::ReadWrite  => flags = O_RDWR\n// \tif mode == Mode::Append     => flags = O_RDWR | O_APPEND\n\n// \treturn File(fd: libc::open(path, flags, 0), buf: [ ])\n// }\n\n// public fn read(f: File) -> [i8]\n// {\n// \tif f.buf.length != 0 => return f.buf\n\n\n// \treturn [ ]\n// }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "libs/std/io.flx",
    "content": "// io.flx\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport std::io\n\npublic import file as _\npublic import print as _\n"
  },
  {
    "path": "libs/std/limits.flx",
    "content": "// limits.flx\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport std::limits\n\npublic namespace int8\n{\n\tpublic let min: i8 = -128\n\tpublic let max: i8 = +127\n}\npublic namespace int16\n{\n\tpublic let min: i16 = -32768\n\tpublic let max: i16 = +32767\n}\npublic namespace int32\n{\n\tpublic let min: i32 = -2147483648\n\tpublic let max: i32 = +2147483647\n}\npublic namespace int64\n{\n\tpublic let min: i64 = -9223372036854775808\n\tpublic let max: i64 = +9223372036854775807\n}\n\npublic namespace uint8\n{\n\tpublic let min: u8 = 0\n\tpublic let max: u8 = 255\n}\npublic namespace uint16\n{\n\tpublic let min: u16 = 0\n\tpublic let max: u16 = 65535\n}\npublic namespace uint32\n{\n\tpublic let min: u32 = 0\n\tpublic let max: u32 = 4294967295\n}\npublic namespace uint64\n{\n\tpublic let min: u64 = 0\n\tpublic let max: u64 = 18446744073709551615\n}\n\n\n\n\n\n"
  },
  {
    "path": "libs/std/map.flx",
    "content": "// map.flx\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport std\nimport libc\nimport std::opt\n\n// haphazardly taken from http://sidsen.azurewebsites.net/papers/rb-trees-talg.pdf\n\npublic class map<K, V>\n{\n\tstruct node\n\t{\n\t\tvar parent: &node\n\t\tvar left: &node\n\t\tvar right: &node\n\n\t\tvar key: K\n\t\tvar value: V\n\n\t\tvar rank: int\n\t}\n\n\tvar root: &node\n\tvar size: int\n\n\tinit()\n\t{\n\t\troot = null\n\t\tsize = 0\n\t}\n\n\n\n\n\tfn _rotateLeft(n: &node)\n\t{\n\t\tvar r = n.right\n\t\tn.right = r.left\n\n\t\tif(r.left != null)  => r.left.parent = n\n\n\t\tr.parent = n.parent\n\t\tif(n.parent == null)        => root = r\n\t\telse if(n.parent.left == n) => n.parent.left = r\n\t\telse                        => n.parent.right = r\n\n\t\tr.left = n\n\t\tn.parent = r\n\t}\n\n\tfn _rotateRight(n: &node)\n\t{\n\t\tvar l = n.left\n\t\tn.left = l.right\n\n\t\tif(l.right != null) => l.right.parent = n\n\n\t\tl.parent = n.parent\n\t\tif(n.parent == null)            => root = l\n\t\telse if(n.parent.right == n)    => n.parent.right = l\n\t\telse                            => n.parent.left = l\n\n\t\tl.right = n\n\t\tn.parent = l\n\t}\n\n\tfn _getPredecessor(node: &node) -> &node\n\t{\n\t\tif(node == null) => return null\n\t\telse if(node.left != null)\n\t\t{\n\t\t\tvar l = node.left\n\t\t\twhile(l.right != null)\n\t\t\t\t=> l = l.right\n\n\t\t\treturn l\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// keep searching upwards till we find something on our left.\n\t\t\tvar par = node.parent\n\t\t\tvar chd = node\n\n\t\t\twhile(par != null && chd == par.left)\n\t\t\t{\n\t\t\t\tchd = par\n\t\t\t\tpar = par.parent\n\t\t\t}\n\n\t\t\treturn par\n\t\t}\n\t}\n\n\tfn _getSuccessor(node: &node) -> &node\n\t{\n\t\tif(node == null) => return null\n\t\telse if(node.right != null)\n\t\t{\n\t\t\tvar r = node.right\n\t\t\twhile(r.left != null)\n\t\t\t\t=> r = r.left\n\n\t\t\treturn r\n\t\t}\n\t\telse\n\t\t{\n\t\t\tvar par = node.parent\n\t\t\tvar chd = node\n\n\t\t\twhile(par != null && chd == par.right)\n\t\t\t{\n\t\t\t\tchd = par\n\t\t\t\tpar = par.parent\n\t\t\t}\n\n\t\t\treturn par\n\t\t}\n\t}\n\n\n\n\n\n\t// returns true if we inserted a new value, false if the key already existed\n\tfn insert(key: K, val: V) -> bool\n\t{\n\t\tif(root == null)\n\t\t{\n\t\t\troot = alloc node(key: key, value: val, rank: 0)\n\t\t\tsize = 1\n\t\t\treturn true\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn _insert(key, val, root)\n\t\t}\n\t}\n\n\tfn _insert(key: K, val: V, _n: &node) -> bool\n\t{\n\t\tfn checkLeftUnbal(n: &node) -> bool\n\t\t{\n\t\t\tif(n.left == null)\n\t\t\t{\n\t\t\t\tif(n.rank == 1) => return true\n\t\t\t\telse            => return false\n\t\t\t}\n\t\t\telse if(n.rank >= n.left.rank + 2)\n\t\t\t{\n\t\t\t\treturn true\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\n\n\t\tfn checkRightUnbal(n: &node) -> bool\n\t\t{\n\t\t\tif(n.right == null)\n\t\t\t{\n\t\t\t\tif(n.rank == 1) => return true\n\t\t\t\telse            => return false\n\t\t\t}\n\t\t\telse if(n.rank >= n.right.rank + 2)\n\t\t\t{\n\t\t\t\treturn true\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\n\n\n\t\t// args are immutable.\n\t\tvar n = _n\n\n\t\tvar side = 0        // -1 for left, 1 for right\n\n\t\tif(n.key == key) => return false\n\t\telse if(key < n.key)\n\t\t{\n\t\t\tside = -1\n\t\t\tif(n.left == null)\n\t\t\t{\n\t\t\t\tn.left = alloc node(key: key, value: val, parent: n)\n\t\t\t\tif(n.left == null)\n\t\t\t\t{\n\t\t\t\t\tlibc::printf(\"node alloc failed!\\n\")\n\t\t\t\t\tlibc::abort()\n\t\t\t\t}\n\t\t\t}\n\t\t\telse                => return _insert(key, val, n.left)\n\t\t}\n\t\telse\n\t\t{\n\t\t\tside = 1\n\t\t\tif(n.right == null)\n\t\t\t{\n\t\t\t\tn.right = alloc node(key: key, value: val, parent: n)\n\t\t\t\tif(n.right == null)\n\t\t\t\t{\n\t\t\t\t\tlibc::printf(\"node alloc failed!\\n\")\n\t\t\t\t\tlibc::abort()\n\t\t\t\t}\n\t\t\t}\n\t\t\telse                => return _insert(key, val, n.right)\n\t\t}\n\n\n\n\n\t\tif(n.parent != null && n.parent.rank == 0)\n\t\t{\n\t\t\tn.parent.rank += 1\n\n\t\t\tvar par = n.parent\n\t\t\twhile(par != null && n.rank + 1 != par.rank)\n\t\t\t{\n\t\t\t\tif(side == -1)\n\t\t\t\t{\n\t\t\t\t\tif(checkRightUnbal(par))\n\t\t\t\t\t{\n\t\t\t\t\t\tif(n.left == null || n.rank >= n.left.rank + 2)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tn.rank -= 1\n\t\t\t\t\t\t\tn.right.rank += 1\n\t\t\t\t\t\t\t_rotateLeft(n)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpar.rank -= 1\n\t\t\t\t\t\t_rotateRight(par)\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif(checkLeftUnbal(par))\n\t\t\t\t\t{\n\t\t\t\t\t\tif(n.right == null || n.rank >= n.right.rank + 2)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tn.rank -= 1\n\t\t\t\t\t\t\tn.left.rank += 1\n\t\t\t\t\t\t\t_rotateRight(n)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpar.rank -= 1\n\t\t\t\t\t\t_rotateLeft(par)\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\n\n\t\t\t\tn = par\n\t\t\t\tpar = n.parent\n\n\t\t\t\tn.rank += 1\n\t\t\t}\n\t\t}\n\n\t\tsize += 1\n\t\treturn true\n\t}\n\n\n\n\tfn _rebalance(_n: &node, _p: &node, _s: &node)\n\t{\n\t\tfn nodeIs22(n: &node) -> bool\n\t\t{\n\t\t\tif(n == null || n.rank == 0)    => return false\n\t\t\tif(n.rank == 1)                 => return (n.left == null && n.right == null)\n\t\t\telse                            => return (n.left.rank == n.right.rank && n.left.rank + 2 == n.rank)\n\t\t}\n\n\t\tfn _rank(n: &node) -> int\n\t\t{\n\t\t\tif(n == null)   => return -1\n\t\t\telse            => return n.rank\n\t\t}\n\n\t\tvar n = _n\n\t\tvar parent = _p\n\t\tvar sibling = _s\n\n\t\tvar deltaRank = parent.rank - n.rank\n\t\twhile(deltaRank == 3 || parent.rank == 1 && nodeIs22(parent))\n\t\t{\n\t\t\tvar deltaRankSibling = 0\n\t\t\tif(sibling == null) => deltaRankSibling = parent.rank + 1\n\t\t\telse                => deltaRankSibling = parent.rank - sibling.rank\n\n\t\t\tif(deltaRankSibling == 2)\n\t\t\t{\n\t\t\t\tparent.rank -= 1\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlet drsL = sibling.rank - _rank(sibling.left)\n\t\t\t\tlet drsR = sibling.rank - _rank(sibling.right)\n\n\t\t\t\tif(drsL == 2 && drsR == 2)\n\t\t\t\t{\n\t\t\t\t\tparent.rank -= 1\n\t\t\t\t\tsibling.rank -= 1\n\t\t\t\t}\n\t\t\t\telse if(parent.right == sibling)\n\t\t\t\t{\n\t\t\t\t\tif(drsR == 1)\n\t\t\t\t\t{\n\t\t\t\t\t\tsibling.rank += 1\n\t\t\t\t\t\tparent.rank -= 1\n\t\t\t\t\t\tif(sibling.left == null) => parent.rank -= 1\n\n\t\t\t\t\t\t_rotateLeft(parent)\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tparent.rank -= 2\n\t\t\t\t\t\tsibling.rank -= 1\n\t\t\t\t\t\tsibling.left.rank += 2\n\n\t\t\t\t\t\t_rotateRight(sibling)\n\t\t\t\t\t\t_rotateLeft(parent)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif(drsL == 1)\n\t\t\t\t\t{\n\t\t\t\t\t\tsibling.rank += 1\n\t\t\t\t\t\tparent.rank -= 1\n\t\t\t\t\t\tif(sibling.right == null) => parent.rank -= 1\n\n\t\t\t\t\t\t_rotateRight(parent)\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tparent.rank -= 2\n\t\t\t\t\t\tsibling.rank -= 1\n\t\t\t\t\t\tsibling.right.rank += 2\n\n\t\t\t\t\t\t_rotateLeft(sibling)\n\t\t\t\t\t\t_rotateRight(parent)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(parent.parent == null) => return\n\n\t\t\tn = parent\n\t\t\tparent = parent.parent\n\t\t\tif(parent.left == n)    => sibling = parent.right\n\t\t\telse                    => sibling = parent.left\n\n\t\t\tdeltaRank = parent.rank - n.rank\n\t\t}\n\t}\n\n\n\n\t// returns true if the key was found, false if not.\n\tfn remove(key: K) -> bool\n\t{\n\t\tvar n = _search(key, root)\n\t\tif(n == null) => return false\n\n\t\t// ok, now remove the node from the thing.\n\t\tsize -= 1\n\n\t\tif(n.left == null && n.right == null && n == root)\n\t\t{\n\t\t\t// if we're the only node then just delete us and go away\n\t\t\tfree n\n\t\t\troot = null\n\t\t\treturn true\n\t\t}\n\n\n\n\t\tif(n.left != null && n.right != null)\n\t\t{\n\t\t\tlet p = _getPredecessor(n)\n\t\t\tn.key = p.key\n\t\t\tn.value = p.value\n\t\t\tn = p\n\t\t}\n\n\n\t\tvar replacement: &node = null\n\t\tif(n.left != null)  => replacement = n.left\n\t\telse                => replacement = n.right\n\n\t\tif(replacement != null)\n\t\t{\n\t\t\tvar sibling: &node = null\n\t\t\treplacement.parent = n.parent\n\n\t\t\tif(n.parent == null)\n\t\t\t{\n\t\t\t\troot = replacement\n\t\t\t\treturn true\n\t\t\t}\n\t\t\telse if(n == n.parent.left)\n\t\t\t{\n\t\t\t\tn.parent.left = replacement\n\t\t\t\tsibling = n.parent.right\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tn.parent.right = replacement\n\t\t\t\tsibling = n.parent.left\n\t\t\t}\n\n\t\t\tn.left = null\n\t\t\tn.right = null\n\t\t\tn.parent = null\n\n\t\t\t_rebalance(replacement, replacement.parent, sibling)\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlet rebalNode = n.parent\n\t\t\tvar sibling: &node = null\n\n\t\t\tif(n == n.parent.left)\n\t\t\t{\n\t\t\t\tn.parent.left = null\n\t\t\t\tsibling = rebalNode.right\n\t\t\t}\n\t\t\telse if(n == n.parent.right)\n\t\t\t{\n\t\t\t\tn.parent.right = null\n\t\t\t\tsibling = rebalNode.left\n\t\t\t}\n\n\t\t\tn.parent = null\n\t\t\tn.rank -= 1\n\n\t\t\t_rebalance(n, rebalNode, sibling)\n\t\t}\n\n\t\treturn true\n\t}\n\n\n\n\n\tfn search(key: K) -> std::opt!<V>\n\t{\n\t\tlet n = _search(key, root)\n\t\tif(n == null)   => return std::opt!<V>::none\n\t\telse            => return std::opt::some(n.value)\n\t}\n\n\tfn _search(key: K, n: &node) -> &node\n\t{\n\t\tif(n == null)       => return null\n\t\tif(n.key == key)    => return n\n\n\t\tif(key < n.key)     => return _search(key, n.left)\n\t\telse                => return _search(key, n.right)\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "libs/std/math.flx",
    "content": "// math.flx\n// Copyright (c) 2014 - 2015, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport math\n\npublic ffi fn sqrt(x: f64) -> f64\npublic ffi fn sqrtf(x: f32) -> f32\n\npublic ffi fn log(x: f64) -> f64\npublic ffi fn logf(x: f32) -> f32\n\npublic ffi fn floor(x: f64) -> f64\npublic ffi fn floorf(x: f32) -> f32\n\npublic ffi fn pow(x: f64, y: f64) -> f64\npublic ffi fn powf(x: f32, y: f32) -> f32\n\n\npublic let π: f64  = 3.14159265358979323846264338327950\npublic let pi: f64 = 3.14159265358979323846264338327950\n"
  },
  {
    "path": "libs/std/opt.flx",
    "content": "// opt.flx\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport std\n\npublic union opt<T>\n{\n\tsome: T\n\tnone\n}\n"
  },
  {
    "path": "libs/std/print.flx",
    "content": "// print.flx\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport std::io\nimport libc\n\nfn error(msg: str)\n{\n\tlibc::printf(\"invalid format string: '%s'\\n\", msg)\n\tlibc::abort()\n}\n\nfn to_string_i64(n: i64) -> string\n{\n\tvar ret = @raw alloc i8 [16]\n\tlet len = libc::sprintf(ret, \"%lld\", n)\n\n\tlet s = string(ret, len)\n\tfree ret\n\n\treturn s\n}\n\nfn to_string_u64(n: u64) -> string\n{\n\tvar ret = @raw alloc i8 [16]\n\tlet len = libc::sprintf(ret, \"%llu\", n)\n\n\tlet s = string(ret, len)\n\tfree ret\n\n\treturn s\n}\n\n\nfn to_string_f64(n: f64) -> string\n{\n\tvar ret = @raw alloc i8 [24]\n\tlet len = libc::sprintf(ret, \"%f\", n)\n\n\tlet s = string(ret, len)\n\tfree ret\n\n\treturn s\n}\n\n\n\npublic fn format(fmt: str, args: [any: ...]) -> string\n{\n\t// todo: this is quite inefficient.\n\t// should we make some kind of stringbuilder class?\n\n\tvar ret: string\n\tvar argi = 0\n\n\tvar idx = 0\n\twhile idx < fmt.length\n\t{\n\t\tlet ch = fmt[idx]\n\t\tif ch == '%'\n\t\t{\n\t\t\tif argi >= args.length\n\t\t\t{\n\t\t\t\terror(format(\"too few arguments: got only %, expected at least %\", args.length, argi + 1))\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlet arg = args[argi]\n\t\t\t\targi += 1\n\n\t\t\t\tif arg is u8            => ret.append(to_string_u64(arg as u8))\n\t\t\t\telse if arg is u16      => ret.append(to_string_u64(arg as u16))\n\t\t\t\telse if arg is u32      => ret.append(to_string_u64(arg as u32))\n\t\t\t\telse if arg is u64      => ret.append(to_string_u64(arg as u64))\n\n\t\t\t\telse if arg is i8       => ret.append(to_string_i64(arg as i8))\n\t\t\t\telse if arg is i16      => ret.append(to_string_i64(arg as i16))\n\t\t\t\telse if arg is i32      => ret.append(to_string_i64(arg as i32))\n\t\t\t\telse if arg is i64      => ret.append(to_string_i64(arg as i64))\n\n\t\t\t\telse if arg is f32      => ret.append(to_string_f64(arg as f32))\n\t\t\t\telse if arg is f64      => ret.append(to_string_f64(arg as f64))\n\n\t\t\t\telse if arg is string   => ret.append(arg as string)\n\t\t\t\telse if arg is str      => ret.append(arg as str)\n\n\t\t\t\telse                    => ret.append(\"(?)\")\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif ch == '\\\\'\n\t\t\t{\n\t\t\t\tidx += 1\n\t\t\t\tret.append(fmt[idx])\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tret.append(ch)\n\t\t\t}\n\t\t}\n\n\t\tidx += 1\n\t}\n\n\treturn ret\n}\n\n// in case you're lazy\npublic fn println()\n{\n\tlibc::puts(\"\")\n}\n\npublic fn println(fmt: str, args: [any: ...])\n{\n\tlibc::puts(format(fmt, ...args))\n}\n\npublic fn print(fmt: str, args: [any: ...])\n{\n\tlet s = format(fmt, ...args)\n\tlibc::write(1, s.ptr, s.length)\n}\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "libs/std/set.flx",
    "content": "// set.flx\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\nexport std\n\npublic class set<T>\n{\n\tstruct node\n\t{\n\t\tvar parent: &node\n\t\tvar left: &node\n\t\tvar right: &node\n\n\t\tvar data: T\n\t}\n\n\tvar root: &node\n}\n"
  },
  {
    "path": "meson.build",
    "content": "# meson.build\n\nproject('flax', version: '0.41.7-pre', default_options: [ 'warning_level=3' ])\n\nadd_languages(['c', 'cpp'])\n\n\nthe_compiler = meson.get_compiler('c')\n\n\nif the_compiler.get_id() == 'msvc'\n\tadd_project_arguments('/utf-8', language:  ['c', 'cpp'])\n\tadd_project_arguments('/std:c++latest', language: 'cpp')\n\tadd_project_arguments('/permissive-', language: 'cpp')\n\tadd_project_arguments('-D_STDC_LIMIT_MACROS', language: 'cpp')\n\tadd_project_arguments('-D_SCL_SECURE_NO_WARNINGS', language:  ['c', 'cpp'])\n\tadd_project_arguments('-D_CRT_SECURE_NO_WARNINGS', language:  ['c', 'cpp'])\n\tadd_project_arguments('-D_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING', language: 'cpp')\n\n\tadd_project_arguments('/W4', language: ['c', 'cpp'])\n\n\t# disable some useless warnings:\n\tadd_project_arguments('/wd4100', language: ['c', 'cpp'])    # unused function parameter\n\tadd_project_arguments('/wd4127', language: ['c', 'cpp'])    # if expression is constant (msvc apparently doesn't understand &&)\n\tadd_project_arguments('/wd4456', language: ['c', 'cpp'])    # local variable shadowing\n\tadd_project_arguments('/wd4457', language: ['c', 'cpp'])    # function parameter shadowing\n\tadd_project_arguments('/wd4458', language: ['c', 'cpp'])    # class member shadowing\n\n\t# enable some useful warnings (set them to fire at level 1):\n\tadd_project_arguments('/w14062', language: ['c', 'cpp'])    # enum value not handled in switch-case\n\tadd_project_arguments('/w14263', language: ['c', 'cpp'])    # member method hides base method\n\tadd_project_arguments('/w14265', language: ['c', 'cpp'])    # non-virtual destructor when class has virtual methods\n\tadd_project_arguments('/w14548', language: ['c', 'cpp'])    # first part of comma-expression has no side-effects\n\n\t# until meson fixes the PCH issue on MSVC (https://github.com/mesonbuild/meson/issues/5648)\n\t# we must force include precompile.h to get the STL types!\n\tadd_project_arguments('/FIsource/include/precompile.h', language: 'cpp')\n\n\n\tadd_project_link_arguments('/ignore:4099', language: ['c', 'cpp'])\n\tadd_project_link_arguments('/machine:X64', language:  ['c', 'cpp'])\n\n\tadd_project_link_arguments('/opt:noref', language:  ['c', 'cpp'])\n\t# add_project_link_arguments('/incremental', language:  ['c', 'cpp'])\n\n\tadd_project_link_arguments('/nodefaultlib:libcmt.lib', language:  ['c', 'cpp'])\n\tadd_project_link_arguments('/nodefaultlib:libcmtd.lib', language:  ['c', 'cpp'])\n\n\tif get_option('buildtype') == 'debug'\n\t\tlibKind = 'Debug'\n\telse\n\t\tlibKind = 'Release'\n\tendif\n\n\t# ok, so because meson is dumb, and we want to allow configuring the locations *without* editing this file\n\t# eg. in CI environments, we run an external command that's just an echo of the environment variable, and\n\t# capture the output to use. all because it's apparently \"a bad idea\" to allow people to read env vars...\n\n\tenvname_mpir    = '%MPIR_ROOT_DIR%'\n\tenvname_mpfr    = '%MPFR_ROOT_DIR%'\n\tenvname_llvm    = '%LLVM_ROOT_DIR%'\n\tenvname_libffi  = '%LIBFFI_ROOT_DIR%'\n\n\tllvm_version   = '11.0.0'\n\n\tmpir_root_dir = run_command('cmd.exe', '/C', 'echo', envname_mpir).stdout().strip()\n\tif mpir_root_dir == envname_mpir\n\t\tmpir_root_dir = 'D:/Projects/lib/mpir'\n\tendif\n\n\tmpfr_root_dir = run_command('cmd.exe', '/C', 'echo', envname_mpfr).stdout().strip()\n\tif mpfr_root_dir == envname_mpfr\n\t\tmpfr_root_dir = 'D:/Projects/lib/mpfr'\n\tendif\n\n\tllvm_root_dir = run_command('cmd.exe', '/C', 'echo', envname_llvm).stdout().strip()\n\tif llvm_root_dir == envname_llvm\n\t\tllvm_root_dir = 'D:/Projects/lib/llvm/' + llvm_version\n\tendif\n\n\tlibffi_root_dir = run_command('cmd.exe', '/C', 'echo', envname_libffi).stdout().strip()\n\tif libffi_root_dir == envname_libffi\n\t\tlibffi_root_dir = 'D:/Projects/lib/libffi'\n\tendif\n\n\tmessage('mpir_root: ' + mpir_root_dir)\n\tmessage('mpfr_root: ' + mpfr_root_dir)\n\tmessage('llvm_root: ' + llvm_root_dir)\n\tmessage('libffi_root: ' + libffi_root_dir)\n\n\tmpir_hdr_dir    = mpir_root_dir   + '/' + libKind + '/include/'\n\tmpfr_hdr_dir    = mpfr_root_dir   + '/' + libKind + '/include/'\n\tllvm_hdr_dir    = llvm_root_dir   + '/' + libKind + '/include/'\n\tlibffi_hdr_dir  = libffi_root_dir + '/' + libKind + '/include/'\n\n\tmpir_lib_dir    = mpir_root_dir   + '/' + libKind + '/lib/'\n\tmpfr_lib_dir    = mpfr_root_dir   + '/' + libKind + '/lib/'\n\tllvm_lib_dir    = llvm_root_dir   + '/' + libKind + '/lib/'\n\tlibffi_lib_dir  = libffi_root_dir + '/' + libKind + '/lib/'\n\n\tlegacy_stdio_dep = declare_dependency(dependencies: the_compiler.find_library('legacy_stdio_definitions'))\n\n\tmpir_dep = declare_dependency(version: '3.0.0', include_directories: include_directories(mpir_hdr_dir),\n\t\tdependencies: the_compiler.find_library('mpir', dirs: mpir_lib_dir))\n\n\tmpfr_dep = declare_dependency(version: '4.0.0', include_directories: include_directories(mpfr_hdr_dir),\n\t\tdependencies: the_compiler.find_library('mpfr', dirs: mpfr_lib_dir))\n\n\tlibffi_dep = declare_dependency(version: '3.2.1', include_directories: include_directories(libffi_hdr_dir),\n\t\tdependencies: the_compiler.find_library('libffi', dirs: libffi_lib_dir))\n\n\tllvm_dep = declare_dependency(version: llvm_version, include_directories: include_directories(llvm_hdr_dir),\n\t\tdependencies: [ mpfr_dep, mpir_dep,\n\t\t\tthe_compiler.find_library('LLVMAnalysis', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMAsmPrinter', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMBinaryFormat', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMBitReader', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMBitstreamReader', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMBitWriter', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMCFGuard', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMCodegen', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMCore', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMDebugInfoCodeView', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMDebugInfoDWARF', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMDebugInfoGSYM', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMDebugInfoPDB', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMDebugInfoMSF', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMDemangle', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMExecutionEngine', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMGlobalISel', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMInstCombine', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMipo', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMJITLink', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMLibDriver', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMLinker', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMMC', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMMCDisassembler', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMMCJIT', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMMCParser', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMObject', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMOrcError', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMOrcJIT', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMPasses', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMProfileData', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMRemarks', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMRuntimeDyld', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMScalarOpts', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMSelectionDAG', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMSupport', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMTablegen', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMTarget', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMTextAPI', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMTransformUtils', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMVectorize', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMX86AsmParser', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMX86CodeGen', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMX86Desc', dirs: llvm_lib_dir),\n\t\t\tthe_compiler.find_library('LLVMX86Info', dirs: llvm_lib_dir),\n\t\t]\n\t)\n\n\tall_deps = [ legacy_stdio_dep, mpir_dep, mpfr_dep, libffi_dep, llvm_dep ]\n\nelse\n\tadd_project_arguments('-std=c11', language: 'c')\n\tadd_project_arguments('-std=c++17', language: 'cpp')\n\t# add_project_arguments('-include', 'source/include/precompile.h', language: 'cpp')\n\n\tadd_project_arguments('-Wall', '-Wno-unused-parameter', '-Wno-sign-conversion', '-Wno-padded', '-Wno-conversion',\n\t\t'-Wno-shadow', '-Wno-missing-noreturn', '-Wno-unused-macros', '-Wno-switch-enum', '-Wno-deprecated', '-Wno-format-nonliteral',\n\t\t'-Wno-trigraphs', '-Wno-unused-const-variable', '-Wno-deprecated-declarations', '-Wno-unused-lambda-capture',\n\t\t'-Wno-unused-variable',\n\t\tlanguage:'cpp')\n\n\t# on unix, we use GMP instead of MPIR.\n\tmpfr_dep = dependency('mpfr', version: '>= 4.0.0')\n\tlibffi_dep = dependency('libffi', version: '>= 3.2.1')\n\tllvm_dep = dependency('llvm', static: true, version: '9.0.0', modules: [\n\t\t'core', 'engine', 'native', 'linker', 'bitwriter',\n\t\t'lto', 'vectorize', 'all-targets', 'object', 'orcjit'\n\t])\n\n\tall_deps = [ mpfr_dep, libffi_dep, llvm_dep ]\n\nendif\n\n\nsource_files = files([\n\t'source/main.cpp',\n\n\t'source/misc/mpool.cpp',\n\t'source/misc/allocator.cpp',\n\t'source/misc/identifier.cpp',\n\t'source/misc/destructors.cpp',\n\n\t'source/repl/driver.cpp',\n\t'source/repl/execute.cpp',\n\t'source/repl/history.cpp',\n\t'source/repl/commands.cpp',\n\n\t'source/frontend/pts.cpp',\n\t'source/frontend/file.cpp',\n\t'source/frontend/lexer.cpp',\n\t'source/frontend/errors.cpp',\n\t'source/frontend/import.cpp',\n\t'source/frontend/arguments.cpp',\n\t'source/frontend/collector.cpp',\n\t'source/frontend/dependencies.cpp',\n\n\t'source/platform/compiler.cpp',\n\t'source/platform/platform.cpp',\n\t'source/platform/backtrace.cpp',\n\t'source/platform/msvcfinder.cpp',\n\n\t'source/frontend/parser/misc.cpp',\n\t'source/frontend/parser/expr.cpp',\n\t'source/frontend/parser/type.cpp',\n\t'source/frontend/parser/literal.cpp',\n\t'source/frontend/parser/variable.cpp',\n\t'source/frontend/parser/function.cpp',\n\t'source/frontend/parser/toplevel.cpp',\n\t'source/frontend/parser/operators.cpp',\n\t'source/frontend/parser/controlflow.cpp',\n\n\t'source/backend/backend.cpp',\n\t'source/backend/x64AsmBackend.cpp',\n\n\t'source/backend/llvm/jit.cpp',\n\t'source/backend/llvm/linker.cpp',\n\t'source/backend/llvm/translator.cpp',\n\n\t'source/backend/interp/driver.cpp',\n\n\t'source/typecheck/misc.cpp',\n\t'source/typecheck/call.cpp',\n\t'source/typecheck/type.cpp',\n\t'source/typecheck/using.cpp',\n\t'source/typecheck/slice.cpp',\n\t'source/typecheck/defer.cpp',\n\t'source/typecheck/loops.cpp',\n\t'source/typecheck/dotop.cpp',\n\t'source/typecheck/enums.cpp',\n\t'source/typecheck/alloc.cpp',\n\t'source/typecheck/assign.cpp',\n\t'source/typecheck/ranges.cpp',\n\t'source/typecheck/sizeof.cpp',\n\t'source/typecheck/unions.cpp',\n\t'source/typecheck/traits.cpp',\n\t'source/typecheck/special.cpp',\n\t'source/typecheck/structs.cpp',\n\t'source/typecheck/classes.cpp',\n\t'source/typecheck/function.cpp',\n\t'source/typecheck/variable.cpp',\n\t'source/typecheck/literals.cpp',\n\t'source/typecheck/toplevel.cpp',\n\t'source/typecheck/subscript.cpp',\n\t'source/typecheck/operators.cpp',\n\t'source/typecheck/arithmetic.cpp',\n\t'source/typecheck/directives.cpp',\n\t'source/typecheck/destructure.cpp',\n\t'source/typecheck/controlflow.cpp',\n\t'source/typecheck/typecheckstate.cpp',\n\n\t'source/typecheck/polymorph/misc.cpp',\n\t'source/typecheck/polymorph/driver.cpp',\n\t'source/typecheck/polymorph/solver.cpp',\n\t'source/typecheck/polymorph/transforms.cpp',\n\t'source/typecheck/polymorph/instantiator.cpp',\n\n\t'source/typecheck/resolver/misc.cpp',\n\t'source/typecheck/resolver/driver.cpp',\n\t'source/typecheck/resolver/resolver.cpp',\n\n\t'source/codegen/raii.cpp',\n\t'source/codegen/misc.cpp',\n\t'source/codegen/call.cpp',\n\t'source/codegen/loops.cpp',\n\t'source/codegen/slice.cpp',\n\t'source/codegen/alloc.cpp',\n\t'source/codegen/enums.cpp',\n\t'source/codegen/dotop.cpp',\n\t'source/codegen/ranges.cpp',\n\t'source/codegen/sizeof.cpp',\n\t'source/codegen/assign.cpp',\n\t'source/codegen/unions.cpp',\n\t'source/codegen/traits.cpp',\n\t'source/codegen/structs.cpp',\n\t'source/codegen/classes.cpp',\n\t'source/codegen/logical.cpp',\n\t'source/codegen/builtin.cpp',\n\t'source/codegen/variable.cpp',\n\t'source/codegen/function.cpp',\n\t'source/codegen/toplevel.cpp',\n\t'source/codegen/literals.cpp',\n\t'source/codegen/operators.cpp',\n\t'source/codegen/subscript.cpp',\n\t'source/codegen/arithmetic.cpp',\n\t'source/codegen/directives.cpp',\n\t'source/codegen/destructure.cpp',\n\t'source/codegen/refcounting.cpp',\n\t'source/codegen/controlflow.cpp',\n\t'source/codegen/constructor.cpp',\n\t'source/codegen/autocasting.cpp',\n\t'source/codegen/codegenstate.cpp',\n\n\t'source/codegen/glue/any.cpp',\n\t'source/codegen/glue/misc.cpp',\n\t'source/codegen/glue/arrays.cpp',\n\t'source/codegen/glue/strings.cpp',\n\t'source/codegen/glue/saa_common.cpp',\n\n\t'source/fir/interp/wrappers.cpp',\n\t'source/fir/interp/compiler.cpp',\n\t'source/fir/interp/interpreter.cpp',\n\n\t'source/fir/ConstantValue.cpp',\n\t'source/fir/GlobalValue.cpp',\n\t'source/fir/Instruction.cpp',\n\t'source/fir/IRBuilder.cpp',\n\t'source/fir/Function.cpp',\n\t'source/fir/IRBlock.cpp',\n\t'source/fir/Module.cpp',\n\t'source/fir/Value.cpp',\n\t'source/fir/Name.cpp',\n\n\t'source/fir/Types/DynamicArrayType.cpp',\n\t'source/fir/Types/ArraySliceType.cpp',\n\t'source/fir/Types/PrimitiveType.cpp',\n\t'source/fir/Types/FunctionType.cpp',\n\t'source/fir/Types/RawUnionType.cpp',\n\t'source/fir/Types/PointerType.cpp',\n\t'source/fir/Types/SingleTypes.cpp',\n\t'source/fir/Types/OpaqueType.cpp',\n\t'source/fir/Types/StructType.cpp',\n\t'source/fir/Types/TypeUtils.cpp',\n\t'source/fir/Types/ArrayType.cpp',\n\t'source/fir/Types/TraitType.cpp',\n\t'source/fir/Types/ClassType.cpp',\n\t'source/fir/Types/TupleType.cpp',\n\t'source/fir/Types/UnionType.cpp',\n\t'source/fir/Types/EnumType.cpp',\n\t'source/fir/Types/Type.cpp'\n])\n\nutf8rewind_dep = declare_dependency(include_directories: include_directories('external/utf8rewind/include'),\n\tsources: [\n\t\t\t\t'external/utf8rewind/source/utf8rewind.c',\n\t\t\t\t'external/utf8rewind/source/unicodedatabase.c',\n\n\t\t\t\t'external/utf8rewind/source/internal/seeking.c',\n\t\t\t\t'external/utf8rewind/source/internal/database.c',\n\t\t\t\t'external/utf8rewind/source/internal/streaming.c',\n\t\t\t\t'external/utf8rewind/source/internal/codepoint.c',\n\t\t\t\t'external/utf8rewind/source/internal/composition.c',\n\t\t\t\t'external/utf8rewind/source/internal/casemapping.c',\n\t\t\t\t'external/utf8rewind/source/internal/decomposition.c'\n\t\t\t]\n)\n\ntinyproclib_dep = declare_dependency(include_directories: include_directories('external/tinyprocesslib'),\n\tsources: [\n\t\t\t\t'external/tinyprocesslib/process.cpp',\n\t\t\t\t'external/tinyprocesslib/process_os.cpp'\n\t\t\t]\n)\n\n\n\nexecutable('flaxc', source_files,\n\tinclude_directories: include_directories([ 'source/include', 'external' ]),\n\tdependencies: all_deps + [ tinyproclib_dep, utf8rewind_dep ],\n\t# cpp_pch: 'source/include/precompile.h'\n)\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "notes.md",
    "content": "## notes\n\n## to fix\n\n1. `public static` doesn't work, but `static public` works.\n\n2. underlining breaks for multi-line spans; just don't underline in that case.\n\n3. types don't appear before functions for some reason, for typechecking. (ie. order becomes important)\n\n4. enum values are not working correctly (seems to be right-shifted by 8?)\n\t(the values are not assigned)\n\n5. defer appears to be broken:\n```\nvar i = 0\nwhile true {\n\tdefer i += 1\n\n\t// doesn't change\n}\n```\n\n6. \"unsynchronised use of global init function!!!\" -- need to figure out a way to serialise access to the global init function\n\n7. polymorphic stuff breaks when manually instantiating\n\n8. compiler crash:\n```\nimport libc as _\n\nstruct Cat<T> {\n     fn greet() {\n        printf(\"i love manga uwu\\n\")\n    }\n}\n\n@entry fn main() {\n    let c: Cat!<Integer> = Cat()\n\n    c.greet();\n}\n```\n\n9. ambiguous call to initialiser of class\n\n10. assignment to runtime variable in #run block\n\n11. numbers basically don't cast properly at all\n\n\n\n## to refactor\n\n3. all uses of defer() need to be audited. there are instances where an exception is thrown during typechecking\n\tas a result of unwrapping a `TCResult` that contains an error; as the stack unwinds, it may encounter a\n\tdefer() object, which necessitates calling the code inside.\n\n\t- in general that is fine (most of the time, it's just `fs->pushLoc()` followed by `defer(fs->popLoc())`),\n\t\tbut in some instances it is not fine --- most notably, when we push a body context and pop it in the defer.\n\n\t- since the popping of the body context asserts that the top of the stack is the same as what we expect, we might\n\t\tend up in a situation where exception-throwing function pushes a different context and throws before popping it,\n\t\tleaving the calling frame with an inconsistent view\n\n\t- the assertion will cause the compiler to terminate when it should have just printed the error message generated\n\t\tby the exception-throwing function.\n\n4. instead of keeping a separate list of `unresolvedGenericDefns` which is pretty ugly, it should be feasible to create\n\ta sort of `sst::ParametricDefn` that simply contains a pointer to the original `ast::Parameterisable` as its only\n\tfield; then, we should be able to simplify the typechecking code substantially by moving those the polymorph\n\tinstantiation into that definition's typecheck method instead.\n\n5. setting the method's containing class via the `infer` parameter feels super fucking dirty, and ngl it has felt dirty\n\tfor the past 5 years.\n\n\n## to investigate\n\n1. we rely on a lot of places to set `enclosingScope` correctly when typechecking structs etc. there should\n\tbe a better way to do this, probably automatically or something like that. basically anything except error-prone manual setting.\n"
  },
  {
    "path": "programs/fic/main.flx",
    "content": "// main.flx\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n\n// this is supposed to be an irc client, in case i forget.\n@entry fn main()\n{\n}\n"
  },
  {
    "path": "programs/fic/run.bat",
    "content": "@echo off\n\nrobocopy libs build\\sysroot\\usr\\local\\lib\\flaxlibs /e /nfl /ndl /njh /njs /nc /ns /np\nbuild\\meson-rel\\flaxc.exe -sysroot build\\sysroot -run programs\\fic\\main.flx"
  },
  {
    "path": "roadmap.md",
    "content": "# Flax 1.0 Roadmap\n\nAs more of the core features are slowly being finished up, the 1.0 milestone is in sight. This is just a list of things that\nshould be finished before the initial implementation can be labelled \"fit-for-use\". Of course, this doesn't preclude any\nbugfixes that are necessary.\n\n\n## Features\n\n1. Traits\n2. Extensions\n3. Cleanup and modernise operator overloading\n4. Standard library\n5. Proper documentation for the entire language and all features\n6. Proper introduction to language features (eg. for a README)\n\n\n### Cleanup/modernise Operator Overloading\n\nThe operator overloading mechanism is dated pre-resolver rewrite, which means that it probably isn't as extensible as we'd\nlike it to be. For example, polymorphic operators aren't a possiblity currently, and that should be a thing that is allowed.\n\n"
  },
  {
    "path": "source/backend/backend.cpp",
    "content": "// Backend.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"backends/llvm.h\"\n#include \"backends/interp.h\"\n\nnamespace backend\n{\n\tBackend* Backend::getBackendFromOption(BackendOption opt, CompiledData& cd,\n\t\tconst std::vector<std::string>& in, const std::string& out)\n\t{\n\t\tswitch(opt)\n\t\t{\n\t\t\tcase BackendOption::LLVM:\n\t\t\t\treturn new LLVMBackend(cd, in, out);\n\n\t\t\tcase BackendOption::Interpreter:\n\t\t\t\treturn new FIRInterpBackend(cd, in, out);\n\n\t\t\tcase BackendOption::Assembly_x64:\n\t\t\t\treturn new x64Backend(cd, in, out);\n\n\t\t\tcase BackendOption::None:\n\t\t\t\treturn nullptr;\n\n\t\t\tcase BackendOption::Invalid:\n\t\t\tdefault:\n\t\t\t\t_error_and_exit(\"invalid backend\\n\");\n\t\t}\n\t}\n\n\tstd::string capabilitiesToString(BackendCaps::Capabilities caps)\n\t{\n\t\tstd::vector<std::string> list;\n\t\tif(caps & BackendCaps::EmitAssembly)\n\t\t\tlist.push_back(\"'emit assembly'\");\n\n\t\tif(caps & BackendCaps::EmitObject)\n\t\t\tlist.push_back(\"'emit object file'\");\n\n\t\tif(caps & BackendCaps::EmitProgram)\n\t\t\tlist.push_back(\"'emit compiled program'\");\n\n\t\tif(caps & BackendCaps::JIT)\n\t\t\tlist.push_back(\"'JIT'\");\n\n\n\t\tif(list.size() == 1)\n\t\t{\n\t\t\treturn list.front();\n\t\t}\n\t\telse if(list.size() == 2)\n\t\t{\n\t\t\treturn list[0] + \" and \" + list[1];\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::string ret;\n\t\t\tfor(size_t i = 0; i < list.size() - 1; i++)\n\t\t\t\tret += list[i] + \", \";\n\n\t\t\tret += \"and \" + list.back();\n\n\t\t\treturn ret;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "source/backend/interp/driver.cpp",
    "content": "// driver.cpp\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include <chrono>\n\n#include \"defs.h\"\n#include \"backend.h\"\n#include \"frontend.h\"\n#include \"platform.h\"\n\n#include \"ir/interp.h\"\n#include \"ir/module.h\"\n\n#include \"backends/interp.h\"\n\n\nnamespace backend\n{\n\ttemplate <typename T>\n\tstatic void _printTiming(T ts, const std::string& thing)\n\t{\n\t\tif(frontend::getPrintProfileStats())\n\t\t{\n\t\t\tauto dur = std::chrono::high_resolution_clock::now() - ts;\n\t\t\tauto ms = static_cast<double>(dur.count()) / 1000000.0;\n\t\t\tprintf(\"%s took %.1f ms%s\\n\", thing.c_str(), ms, ms > 3000 ? strprintf(\"  (aka %.2f s)\", ms / 1000.0).c_str() : \"\");\n\t\t}\n\t}\n\n\n\tusing namespace fir;\n\tusing namespace fir::interp;\n\n\tFIRInterpBackend::FIRInterpBackend(CompiledData& dat, const std::vector<std::string>& inputs, const std::string& output)\n\t\t: Backend(BackendCaps::JIT, dat, inputs, output)\n\t{\n\t\tplatform::compiler::performSelfDlOpen();\n\t}\n\n\tFIRInterpBackend::~FIRInterpBackend()\n\t{\n\t\tif(this->is) delete this->is;\n\t}\n\n\tstd::string FIRInterpBackend::str()\n\t{\n\t\treturn \"FIR Interpreter\";\n\t}\n\n\tvoid FIRInterpBackend::performCompilation()\n\t{\n\t\tthis->is = new InterpState(this->compiledData.module);\n\t\tthis->is->initialise(/* runGlobalInit:*/ true);\n\n\t\t// it suffices to compile just the entry function.\n\t\tthis->is->compileFunction(this->compiledData.module->getEntryFunction());\n\t}\n\n\tvoid FIRInterpBackend::optimiseProgram()\n\t{\n\t\t// nothing.\n\t}\n\n\tvoid FIRInterpBackend::writeOutput()\n\t{\n\t\tif(auto entryfn = this->compiledData.module->getEntryFunction(); entryfn)\n\t\t{\n\t\t\tauto ts = std::chrono::high_resolution_clock::now();\n\n\n\t\t\tauto f = this->is->compiledFunctions[entryfn];\n\n\t\t\t// add arguments if necessary, i guess.\n\t\t\t// just make null values.\n\t\t\tstd::vector<interp::Value> args;\n\t\t\tfor(auto a : entryfn->getArguments())\n\t\t\t\targs.push_back(this->is->makeValue(a));\n\n\t\t\tthis->is->runFunction(f, args);\n\n\t\t\t_printTiming(ts, \"interp\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(\"interp: no entry function, cannot run!\");\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/backend/llvm/jit.cpp",
    "content": "// jit.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"errors.h\"\n#include \"backends/llvm.h\"\n\n\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n\t#pragma warning(disable: 4267)\n\t#pragma warning(disable: 4244)\n#else\n\t#pragma GCC diagnostic push\n\t#pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#endif\n\n#include \"llvm/Analysis/Passes.h\"\n#include \"llvm/Transforms/Scalar.h\"\n#include \"llvm/IR/LegacyPassManager.h\"\n#include \"llvm/Transforms/Scalar/GVN.h\"\n#include \"llvm/Transforms/InstCombine/InstCombine.h\"\n\n\n#ifdef _MSC_VER\n\t#pragma warning(pop)\n#else\n\t#pragma GCC diagnostic pop\n#endif\n\n\nstatic std::string dealWithLLVMError(const llvm::Error& err)\n{\n\tstd::string str;\n\tauto out = llvm::raw_string_ostream(str);\n\n\tout << err;\n\treturn out.str();\n}\n\nnamespace backend\n{\n\tLLVMJit::LLVMJit(llvm::orc::JITTargetMachineBuilder JTMB, llvm::DataLayout DL) : ObjectLayer(ES, []() {\n\t\t\treturn std::make_unique<llvm::SectionMemoryManager>();\n\t\t}),\n        CompileLayer(ES, ObjectLayer, std::make_unique<llvm::orc::ConcurrentIRCompiler>(std::move(JTMB))),\n        OptimiseLayer(ES, CompileLayer, optimiseModule),\n        DL(std::move(DL)), Mangle(ES, this->DL),\n        Ctx(std::make_unique<llvm::LLVMContext>()),\n        dylib(ES.createJITDylib(\"<jit>\").get())\n\t{\n\t\tllvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);\n\t\tdylib.addGenerator(llvm::cantFail(\n\t\t\tllvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(DL.getGlobalPrefix())));\n\n\t\t// dunno who's bright idea it was to match symbol flags *EXACTLY* instead of something more sane\n\t\tObjectLayer.setOverrideObjectFlagsWithResponsibilityFlags(true);\n\t\tObjectLayer.setAutoClaimResponsibilityForObjectSymbols(true);\n\t}\n\n\tvoid LLVMJit::addModule(std::unique_ptr<llvm::Module> mod)\n\t{\n\t\t// store it first lest it get stolen away\n\t\tauto modIdent = mod->getModuleIdentifier();\n\n\t\t// llvm::Error::operator bool() returns true if there's an error.\n\t\tif(auto err = OptimiseLayer.add(this->dylib, llvm::orc::ThreadSafeModule(std::move(mod), Ctx)); err)\n\t\t\terror(\"llvm: failed to add module '%s': %s\", modIdent, dealWithLLVMError(err));\n\t}\n\n\tllvm::JITEvaluatedSymbol LLVMJit::findSymbol(const std::string& name)\n\t{\n\t\tif(auto ret = ES.lookup({ &this->dylib }, Mangle(name)); !ret)\n\t\t\terror(\"llvm: failed to find symbol '%s': %s\", name, dealWithLLVMError(ret.takeError()));\n\n\t\telse\n\t\t\treturn ret.get();\n\t}\n\n\n\n\tLLVMJit* LLVMJit::create()\n\t{\n\t\tauto JTMB = llvm::orc::JITTargetMachineBuilder::detectHost();\n\t\tif(!JTMB) error(\"llvm: failed to detect host\", dealWithLLVMError(JTMB.takeError()));\n\n\t\tauto DL = JTMB->getDefaultDataLayoutForTarget();\n\t\tif(!DL) error(\"llvm: failed to get data layout\", dealWithLLVMError(DL.takeError()));\n\n\t\treturn new LLVMJit(std::move(*JTMB), std::move(*DL));\n\t}\n\n\n\tllvm::Expected<llvm::orc::ThreadSafeModule> LLVMJit::optimiseModule(llvm::orc::ThreadSafeModule TSM,\n\t\tconst llvm::orc::MaterializationResponsibility& R)\n\t{\n\t\t#if 0\n\t\t // Create a function pass manager.\n\t\tauto FPM = llvm::make_unique<llvm::legacy::FunctionPassManager>(TSM.getModule());\n\n\t\t// Add some optimizations.\n\t\tFPM->add(llvm::createInstructionCombiningPass());\n\t\tFPM->add(llvm::createReassociatePass());\n\t\tFPM->add(llvm::createGVNPass());\n\t\tFPM->add(llvm::createCFGSimplificationPass());\n\t\tFPM->doInitialization();\n\n\t\t// Run the optimizations over all functions in the module being added to\n\t\t// the JIT.\n\t\tfor(auto& F : *TSM.getModule())\n\t\t\tFPM->run(F);\n\t\t#endif\n\n\t\treturn TSM;\n\t}\n\n\tllvm::JITTargetAddress LLVMJit::getSymbolAddress(const std::string& name)\n\t{\n\t\treturn this->findSymbol(name).getAddress();\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/backend/llvm/linker.cpp",
    "content": "// linker.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n\n\n#ifndef __STDC_CONSTANT_MACROS\n#define __STDC_CONSTANT_MACROS\n#endif\n\n#ifndef __STDC_LIMIT_MACROS\n#define __STDC_LIMIT_MACROS\n#endif\n\n#include <fstream>\n\n\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n\t#pragma warning(disable: 4267)\n\t#pragma warning(disable: 4244)\n#else\n\t#pragma GCC diagnostic push\n\t#pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#endif\n\n#include \"llvm/IR/Verifier.h\"\n#include \"llvm/IR/IRBuilder.h\"\n#include \"llvm/Support/Host.h\"\n#include \"llvm/Linker/Linker.h\"\n#include \"llvm/Transforms/IPO.h\"\n#include \"llvm/IR/LLVMContext.h\"\n#include \"llvm/Analysis/Passes.h\"\n#include \"llvm/Transforms/Utils.h\"\n#include \"llvm/Transforms/Scalar.h\"\n#include \"llvm/Support/raw_ostream.h\"\n#include \"llvm/Support/TargetSelect.h\"\n#include \"llvm/Support/TargetSelect.h\"\n#include \"llvm/Target/TargetMachine.h\"\n#include \"llvm/IR/LegacyPassManager.h\"\n#include \"llvm/Bitcode/BitcodeWriter.h\"\n#include \"llvm/ExecutionEngine/MCJIT.h\"\n#include \"llvm/Support/TargetRegistry.h\"\n#include \"llvm/Support/ToolOutputFile.h\"\n#include \"llvm/Support/DynamicLibrary.h\"\n#include \"llvm/Transforms/Scalar/Scalarizer.h\"\n#include \"llvm/ExecutionEngine/ExecutionEngine.h\"\n#include \"llvm/Transforms/InstCombine/InstCombine.h\"\n\n#ifdef _MSC_VER\n\t#pragma warning(pop)\n#else\n\t#pragma GCC diagnostic pop\n#endif\n\n#include <stdio.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n\n#include \"ir/type.h\"\n#include \"ir/value.h\"\n#include \"ir/module.h\"\n#include \"ir/irbuilder.h\"\n\n#include \"frontend.h\"\n#include \"backends/llvm.h\"\n\n#include \"tinyprocesslib/tinyprocess.h\"\n\n\nstatic llvm::LLVMContext globalContext;\n\ntemplate <typename T>\nstatic void _printTiming(T ts, const std::string& thing)\n{\n\tif(frontend::getPrintProfileStats())\n\t{\n\t\tauto dur = std::chrono::high_resolution_clock::now() - ts;\n\t\tauto ms = static_cast<double>(dur.count()) / 1000000.0;\n\t\tprintf(\"%s took %.1f ms%s\\n\", thing.c_str(), ms, ms > 3000 ? strprintf(\"  (aka %.2f s)\", ms / 1000.0).c_str() : \"\");\n\t}\n}\n\nnamespace backend\n{\n\tllvm::LLVMContext& LLVMBackend::getLLVMContext()\n\t{\n\t\treturn globalContext;\n\t}\n\n\tLLVMBackend::LLVMBackend(CompiledData& dat, const std::vector<std::string>& inputs, const std::string& output)\n\t\t: Backend(BackendCaps::EmitAssembly | BackendCaps::EmitObject | BackendCaps::EmitProgram | BackendCaps::JIT, dat, inputs, output)\n\t{\n\t}\n\n\tstd::string LLVMBackend::str()\n\t{\n\t\treturn \"LLVM\";\n\t}\n\n\tvoid LLVMBackend::performCompilation()\n\t{\n\t\tauto ts = std::chrono::high_resolution_clock::now();\n\n\t\tllvm::InitializeNativeTarget();\n\n\t\tauto mainModule = this->translateFIRtoLLVM(this->compiledData.module);\n\n\t\tif(this->compiledData.module->getEntryFunction())\n\t\t\tthis->entryFunction = mainModule->getFunction(this->compiledData.module->getEntryFunction()->getName().mangled());\n\n\t\tthis->linkedModule = std::unique_ptr<llvm::Module>(mainModule);\n\n\t\t// ok, move some shit into here because llvm is fucking retarded\n\t\tthis->setupTargetMachine();\n\t\tthis->linkedModule->setDataLayout(this->targetMachine->createDataLayout());\n\n\t\t_printTiming(ts, \"llvm translation\");\n\t}\n\n\n\tvoid LLVMBackend::optimiseProgram()\n\t{\n\t\tauto ts = std::chrono::high_resolution_clock::now();\n\n\t\tllvm::legacy::PassManager fpm = llvm::legacy::PassManager();\n\n\t\tfpm.add(llvm::createDeadInstEliminationPass());\n\t\tfpm.add(llvm::createDeadCodeEliminationPass());\n\n\t\tif(frontend::getOptLevel() > OptimisationLevel::Debug)\n\t\t{\n\t\t\t// mem2reg is based, because it changes inefficient load-store branches into more efficient phi-nodes (at least more efficient\n\t\t\t// in terms of optimisation potential)\n\t\t\tfpm.add(llvm::createPromoteMemoryToRegisterPass());\n\t\t\tfpm.add(llvm::createMergedLoadStoreMotionPass());\n\t\t\tfpm.add(llvm::createInstructionCombiningPass());\n\t\t\tfpm.add(llvm::createConstantPropagationPass());\n\t\t\tfpm.add(llvm::createScalarizerPass());\n\t\t}\n\n\t\tif(frontend::getOptLevel() > OptimisationLevel::None)\n\t\t{\n\t\t\tfpm.add(llvm::createReassociatePass());\n\t\t\tfpm.add(llvm::createCFGSimplificationPass());\n\n\t\t\t// hmm.\n\t\t\t// fuck it, turn everything on.\n\n\t\t\tfpm.add(llvm::createConstantHoistingPass());\n\t\t\tfpm.add(llvm::createLICMPass());\n\t\t\tfpm.add(llvm::createDelinearizationPass());\n\t\t\tfpm.add(llvm::createFlattenCFGPass());\n\t\t\tfpm.add(llvm::createScalarizerPass());\n\t\t\tfpm.add(llvm::createSinkingPass());\n\t\t\tfpm.add(llvm::createDeadStoreEliminationPass());\n\t\t\tfpm.add(llvm::createMemCpyOptPass());\n\n\t\t\tfpm.add(llvm::createSCCPPass());\n\n\t\t\tfpm.add(llvm::createTailCallEliminationPass());\n\t\t}\n\n\t\tif(frontend::getOptLevel() > OptimisationLevel::Minimal)\n\t\t{\n\t\t\tfpm.add(llvm::createAggressiveDCEPass());\n\n\t\t\t// module-level stuff\n\t\t\tfpm.add(llvm::createMergeFunctionsPass());\n\t\t\tfpm.add(llvm::createLoopSimplifyPass());\n\t\t}\n\n\t\tfpm.run(*this->linkedModule);\n\n\t\t_printTiming(ts, \"llvm opt\");\n\n\t\tif(frontend::getPrintLLVMIR())\n\t\t\tthis->linkedModule->print(llvm::outs(), 0);\n\t}\n\n\tvoid LLVMBackend::writeOutput()\n\t{\n\t\tauto ts = std::chrono::high_resolution_clock::now();\n\n\t\tif(llvm::verifyModule(*this->linkedModule, &llvm::errs()))\n\t\t{\n\t\t\tfprintf(stderr, \"\\n\\n\");\n\t\t\tthis->linkedModule->print(llvm::errs(), 0);\n\n\t\t\tBareError::make(\"llvm: module verification failed\")->postAndQuit();\n\t\t}\n\n\t\tstd::string oname;\n\t\tif(this->outputFilename.empty())\n\t\t{\n\t\t\tauto base = this->linkedModule->getModuleIdentifier();\n\n\t\t\tif(frontend::getOutputMode() == ProgOutputMode::ObjectFile)\n\t\t\t\toname = platform::compiler::getObjectFileName(base);\n\n\t\t\telse\n\t\t\t\toname = platform::compiler::getExecutableName(base);\n\t\t}\n\t\telse\n\t\t{\n\t\t\toname = this->outputFilename;\n\t\t}\n\n\n\t\tif(frontend::getOutputMode() == ProgOutputMode::RunJit)\n\t\t{\n\t\t\tstd::string modname = (\"llvm-jit-\" + this->linkedModule->getModuleIdentifier());\n\t\t\tconst char* argv = modname.c_str();\n\n\t\t\tauto entry = this->getEntryFunctionFromJIT();\n\n\t\t\t_printTiming(ts, \"llvm jit\");\n\t\t\tprintf(\"\\n\");\n\n\t\t\ticeAssert(this->jitInstance);\n\t\t\tentry(1, &argv);\n\n\t\t\tdelete this->jitInstance;\n\t\t}\n\t\telse if(frontend::getOutputMode() == ProgOutputMode::LLVMBitcode)\n\t\t{\n\t\t\tstd::error_code e;\n\t\t\tllvm::sys::fs::OpenFlags of = static_cast<llvm::sys::fs::OpenFlags>(0);\n\t\t\tllvm::raw_fd_ostream rso(oname.c_str(), e, of);\n\n\t\t\tllvm::WriteBitcodeToFile(*this->linkedModule.get(), rso);\n\t\t\trso.close();\n\n\t\t\t_printTiming(ts, \"writing bitcode file\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif(frontend::getOutputMode() != ProgOutputMode::ObjectFile && !this->compiledData.module->getEntryFunction())\n\t\t\t{\n\t\t\t\terror(\"llvm: no entry function marked, a program cannot be compiled\");\n\t\t\t}\n\n\t\t\tllvm::SmallVector<char, 0> buffer;\n\t\t\t{\n\t\t\t\tauto bufferStream = std::make_unique<llvm::raw_svector_ostream>(buffer);\n\t\t\t\tllvm::raw_pwrite_stream* rawStream = bufferStream.get();\n\n\t\t\t\t{\n\t\t\t\t\tllvm::legacy::PassManager pm = llvm::legacy::PassManager();\n\t\t\t\t\ttargetMachine->addPassesToEmitFile(pm, *rawStream, nullptr,\n\t\t\t\t\t\tllvm::CodeGenFileType::CGFT_ObjectFile);\n\n\t\t\t\t\tpm.run(*this->linkedModule);\n\t\t\t\t}\n\n\t\t\t\t// flush and kill it.\n\t\t\t\trawStream->flush();\n\t\t\t}\n\n\n\t\t\tif(frontend::getOutputMode() == ProgOutputMode::ObjectFile)\n\t\t\t{\n\t\t\t\t// now memoryBuffer should contain the .object file\n\t\t\t\tstd::ofstream objectOutput(oname, std::ios::binary | std::ios::out);\n\t\t\t\tobjectOutput.write(buffer.data(), buffer.size_in_bytes());\n\t\t\t\tobjectOutput.close();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstd::string objname = platform::compiler::getObjectFileName(this->linkedModule->getModuleIdentifier());\n\n\t\t\t\tstd::ofstream objectOutput(objname, std::ios::binary | std::ios::out);\n\t\t\t\tobjectOutput.write(buffer.data(), buffer.size_in_bytes());\n\t\t\t\tobjectOutput.close();\n\n\t\t\t\tauto cmdline = platform::compiler::getCompilerCommandLine({ objname }, oname);\n\n\t\t\t\t// debuglogln(\"link cmdline:\\n%s\", cmdline);\n\n\t\t\t\tstd::string sout;\n\t\t\t\tstd::string serr;\n\n\t\t\t\ttinyproclib::Process proc(cmdline, \"\", [&sout](const char* bytes, size_t n) {\n\t\t\t\t\tsout = std::string(bytes, n);\n\t\t\t\t}, [&serr](const char* bytes, size_t n) {\n\t\t\t\t\tserr = std::string(bytes, n);\n\t\t\t\t});\n\n\t\t\t\t// note: this waits for the process to finish.\n\t\t\t\tint status = proc.get_exit_status();\n\n\t\t\t\tif(status != 0)\n\t\t\t\t{\n\t\t\t\t\tif(!sout.empty()) fprintf(stderr, \"%s\\n\", sout.c_str());\n\t\t\t\t\tif(!serr.empty()) fprintf(stderr, \"%s\\n\", serr.c_str());\n\n\t\t\t\t\tfprintf(stderr, \"linker returned non-zero (status = %d), exiting\\n\", status);\n\t\t\t\t\tfprintf(stderr, \"cmdline was: %s\\n\", cmdline.c_str());\n\t\t\t\t\texit(status);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t_printTiming(ts, \"outputting exe/obj\");\n\t\t}\n\t}\n\n\n\n\n\n\n\n\n\n\n\tvoid LLVMBackend::setupTargetMachine()\n\t{\n\t\tllvm::InitializeNativeTarget();\n\t\tllvm::InitializeNativeTargetAsmParser();\n\t\tllvm::InitializeNativeTargetAsmPrinter();\n\n\t\tllvm::Triple targetTriple;\n\t\tif(frontend::getOutputMode() == ProgOutputMode::RunJit || frontend::getParameter(\"targetarch\").empty())\n\t\t{\n\t\t\ttargetTriple.setTriple(llvm::sys::getProcessTriple());\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttargetTriple.setTriple(frontend::getParameter(\"targetarch\"));\n\t\t}\n\n\t\tstd::string err_str;\n\t\tconst llvm::Target* theTarget = llvm::TargetRegistry::lookupTarget(\"\", targetTriple, err_str);\n\t\tif(!theTarget)\n\t\t{\n\t\t\terror(\"llvm: failed in creating target: (wanted: '%s'); llvm error: %s\\n\", targetTriple.str(), err_str);\n\t\t}\n\n\n\t\t// get the mcmodel\n\t\tllvm::CodeModel::Model codeModel;\n\n\t\tauto getMcModelOfString = [](const std::string& s) -> llvm::CodeModel::Model {\n\t\t\tif(s == \"kernel\")   return llvm::CodeModel::Kernel;\n\t\t\tif(s == \"small\")    return llvm::CodeModel::Small;\n\t\t\tif(s == \"medium\")   return llvm::CodeModel::Medium;\n\t\t\tif(s == \"large\")    return llvm::CodeModel::Large;\n\t\t\telse                error(\"llvm: invalid mcmodel '%s' (valid options: kernel, small, medium, or large)\", s);\n\t\t};\n\n\t\tauto getDefaultCodeModelForTarget = [](const llvm::Triple& triple) -> llvm::CodeModel::Model {\n\t\t\tif(triple.isArch64Bit() && !triple.isOSDarwin() && !triple.isAndroid() && !(triple.isAArch64() && triple.isOSLinux()))\n\t\t\t{\n\t\t\t\treturn llvm::CodeModel::Large;\n\t\t\t}\n\t\t\telse if(triple.isOSDarwin() && (frontend::getOutputMode() == ProgOutputMode::RunJit))\n\t\t\t{\n\t\t\t\t// apparently, when we JIT on osx we need mcmodel=large\n\t\t\t\t// but when we are compiling, we need mcmodel=small!!\n\t\t\t\t// WTF? nobody on the internet seems to know, but this was determined experimentally.\n\t\t\t\t// if we use mcmodel=small when JIT-ing, we crash when running...\n\t\t\t\treturn llvm::CodeModel::Large;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn llvm::CodeModel::Small;\n\t\t\t}\n\t\t};\n\n\t\tif(auto mcm = frontend::getParameter(\"mcmodel\"); !mcm.empty())\n\t\t\tcodeModel = getMcModelOfString(mcm);\n\n\t\telse\n\t\t\tcodeModel = getDefaultCodeModelForTarget(targetTriple);\n\n\n\t\tllvm::TargetOptions targetOptions;\n\t\tllvm::Reloc::Model relocModel = llvm::Reloc::Model::Static;\n\n\t\t// todo: use dynamic no pic for dylibs?? idk\n\t\tif(frontend::getIsPositionIndependent())\n\t\t\trelocModel = llvm::Reloc::Model::PIC_;\n\n\t\tthis->targetMachine = theTarget->createTargetMachine(targetTriple.getTriple(), \"\", \"\",\n\t\t\ttargetOptions, relocModel, codeModel, llvm::CodeGenOpt::Default);\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tEntryPoint_t LLVMBackend::getEntryFunctionFromJIT()\n\t{\n\t\tusing namespace llvm::sys;\n\n\t\tplatform::compiler::addLibrarySearchPaths();\n\n\t\t// default libraries come with the correct prefix/extension for the platform already, but user ones do not.\n\t\tauto tolink = zfu::map(frontend::getLibrariesToLink(), [](auto lib) -> auto {\n\t\t\treturn platform::compiler::getSharedLibraryName(lib);\n\t\t}) + platform::compiler::getDefaultSharedLibraries();\n\n\t\tfor(auto lib : tolink)\n\t\t{\n\t\t\tstd::string err;\n\t\t\tauto dl = DynamicLibrary::getPermanentLibrary(lib.c_str(), &err);\n\t\t\tif(!dl.isValid())\n\t\t\t\terror(\"llvm: failed to load library '%s', dlopen failed with error:\\n%s\", lib, err);\n\t\t}\n\n\t\tfor(auto fw : frontend::getFrameworksToLink())\n\t\t{\n\t\t\tauto name = strprintf(\"%s.framework/%s\", fw, fw);\n\n\t\t\tstd::string err;\n\t\t\tauto dl = DynamicLibrary::getPermanentLibrary(name.c_str(), &err);\n\t\t\tif(!dl.isValid())\n\t\t\t\terror(\"llvm: failed to load framework '%s', dlopen failed with error:\\n%s\", fw, err);\n\t\t}\n\n\n\t\tEntryPoint_t ret = 0;\n\t\ticeAssert(this->entryFunction);\n\t\t{\n\t\t\tauto name = this->entryFunction->getName().str();\n\n\t\t\tthis->jitInstance = LLVMJit::create();\n\t\t\tthis->jitInstance->addModule(std::move(this->linkedModule));\n\n\t\t\tauto entryaddr = this->jitInstance->getSymbolAddress(name);\n\t\t\tret = reinterpret_cast<EntryPoint_t>(entryaddr);\n\n\t\t\ticeAssert(ret && \"failed to resolve entry function address\");\n\t\t}\n\n\t\tplatform::compiler::restoreLibrarySearchPaths();\n\t\treturn ret;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/backend/llvm/translator.cpp",
    "content": "// Translator.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n\n#ifndef __STDC_CONSTANT_MACROS\n#define __STDC_CONSTANT_MACROS\n#endif\n\n#ifndef __STDC_LIMIT_MACROS\n#define __STDC_LIMIT_MACROS\n#endif\n\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n#else\n\t#pragma GCC diagnostic push\n\t#pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#endif\n\n#include \"llvm/IR/Verifier.h\"\n#include \"llvm/IR/IRBuilder.h\"\n#include \"llvm/IR/LLVMContext.h\"\n\n#ifdef _MSC_VER\n\t#pragma warning(pop)\n#else\n\t#pragma GCC diagnostic pop\n#endif\n\n#include \"gluecode.h\"\n#include \"ir/module.h\"\n#include \"ir/constant.h\"\n\n#include \"backends/llvm.h\"\n\n#include <set>\n\n\n#define SLICE_DATA_INDEX            0\n#define SLICE_LENGTH_INDEX          1\n\n#define SAA_DATA_INDEX              0\n#define SAA_LENGTH_INDEX            1\n#define SAA_CAPACITY_INDEX          2\n#define SAA_REFCOUNTPTR_INDEX       3\n\n#define ANY_TYPEID_INDEX            0\n#define ANY_REFCOUNTPTR_INDEX       1\n#define ANY_DATA_ARRAY_INDEX        2\n\nnamespace backend\n{\n\tstatic util::hash_map<fir::Name, llvm::StructType*> createdTypes;\n\tstatic std::map<fir::ConstantValue*, llvm::Constant*> cachedConstants;\n\n\n\tinline std::string llvmTyToString(llvm::Type* t)\n\t{\n\t\tstd::string str;\n\t\tllvm::raw_string_ostream rso(str);\n\t\tt->print(rso);\n\n\t\treturn str;\n\t}\n\n\tinline std::string llvmToString(llvm::Value* t)\n\t{\n\t\tstd::string str;\n\t\tllvm::raw_string_ostream rso(str);\n\t\tt->print(rso);\n\n\t\treturn str;\n\t}\n\n\tstatic llvm::Type* getNativeWordTy()\n\t{\n\t\tauto& gc = LLVMBackend::getLLVMContext();\n\t\treturn llvm::IntegerType::getIntNTy(gc, static_cast<unsigned int>(fir::getNativeWordSizeInBits()));\n\t}\n\n\tstatic llvm::Type* typeToLlvm(fir::Type* type, llvm::Module* mod)\n\t{\n\t\tauto& gc = LLVMBackend::getLLVMContext();\n\t\tif(type->isPrimitiveType())\n\t\t{\n\t\t\tfir::PrimitiveType* pt = type->toPrimitiveType();\n\n\t\t\t// signed/unsigned is lost.\n\t\t\tif(pt->isIntegerType())\n\t\t\t{\n\t\t\t\treturn llvm::IntegerType::getIntNTy(gc, static_cast<unsigned int>(pt->getIntegerBitWidth()));\n\t\t\t}\n\t\t\telse if(pt->isFloatingPointType())\n\t\t\t{\n\t\t\t\tif(pt->getFloatingPointBitWidth() == 32)\n\t\t\t\t\treturn llvm::Type::getFloatTy(gc);\n\n\t\t\t\telse if(pt->getFloatingPointBitWidth() == 64)\n\t\t\t\t\treturn llvm::Type::getDoubleTy(gc);\n\n\t\t\t\telse if(pt->getFloatingPointBitWidth() == 80)\n\t\t\t\t\treturn llvm::Type::getX86_FP80Ty(gc);\n\n\t\t\t\telse if(pt->getFloatingPointBitWidth() == 128)\n\t\t\t\t\treturn llvm::Type::getFP128Ty(gc);\n\n\t\t\t\terror(\"llvm: what\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\terror(\"llvm: what\");\n\t\t\t}\n\t\t}\n\t\telse if(type->isStructType())\n\t\t{\n\t\t\tfir::StructType* st = type->toStructType();\n\n\t\t\tif(createdTypes.find(st->getTypeName()) != createdTypes.end())\n\t\t\t\treturn createdTypes[st->getTypeName()];\n\n\t\t\t// to allow recursion, declare the type first.\n\t\t\tcreatedTypes[st->getTypeName()] = llvm::StructType::create(gc, st->getTypeName().mangled());\n\n\t\t\tstd::vector<llvm::Type*> lmems;\n\t\t\tfor(auto a : st->getElements())\n\t\t\t\tlmems.push_back(typeToLlvm(a, mod));\n\n\t\t\tcreatedTypes[st->getTypeName()]->setBody(lmems, st->isPackedStruct());\n\t\t\treturn createdTypes[st->getTypeName()];\n\t\t}\n\t\telse if(type->isClassType())\n\t\t{\n\t\t\tfir::ClassType* ct = type->toClassType();\n\n\t\t\tif(createdTypes.find(ct->getTypeName()) != createdTypes.end())\n\t\t\t\treturn createdTypes[ct->getTypeName()];\n\n\t\t\t// to allow recursion, declare the type first.\n\t\t\tcreatedTypes[ct->getTypeName()] = llvm::StructType::create(gc, ct->getTypeName().mangled());\n\n\t\t\tstd::vector<llvm::Type*> lmems = zfu::map(ct->getAllElementsIncludingBase(), [&mod](auto t) -> auto {\n\t\t\t\treturn typeToLlvm(t, mod);\n\t\t\t});\n\n\t\t\t// insert the vtable at the front.\n\t\t\tif(ct->getVirtualMethodCount() > 0)\n\t\t\t\tlmems.insert(lmems.begin(), llvm::Type::getInt8PtrTy(gc));\n\n\t\t\tcreatedTypes[ct->getTypeName()]->setBody(lmems);\n\t\t\treturn createdTypes[ct->getTypeName()];\n\t\t}\n\t\telse if(type->isTupleType())\n\t\t{\n\t\t\tfir::TupleType* tt = type->toTupleType();\n\n\t\t\tstd::vector<llvm::Type*> lmems;\n\t\t\tfor(auto a : tt->getElements())\n\t\t\t\tlmems.push_back(typeToLlvm(a, mod));\n\n\t\t\treturn llvm::StructType::get(gc, lmems);\n\t\t}\n\t\telse if(type->isFunctionType())\n\t\t{\n\t\t\tfir::FunctionType* ft = type->toFunctionType();\n\t\t\tstd::vector<llvm::Type*> largs;\n\t\t\tfor(auto a : ft->getArgumentTypes())\n\t\t\t\tlargs.push_back(typeToLlvm(a, mod));\n\n\t\t\t//! note(workaround): THIS IS A HACK.\n\t\t\t// we *ALWAYS* return a pointer to function, because llvm is stupid.\n\t\t\t// when we create an llvm::Function using this type, we always dereference the pointer type.\n\t\t\t// however, everywhere else (eg. function variables, parameters, etc.) we need pointers, because\n\t\t\t// llvm doesn't let FunctionType be a raw type (of a variable or param), but i'll let fir be less stupid,\n\t\t\t// so it transparently works without fir having to need pointers.\n\t\t\treturn llvm::FunctionType::get(typeToLlvm(ft->getReturnType(), mod), largs, ft->isCStyleVarArg())->getPointerTo();\n\t\t}\n\t\telse if(type->isArrayType())\n\t\t{\n\t\t\tfir::ArrayType* at = type->toArrayType();\n\t\t\treturn llvm::ArrayType::get(typeToLlvm(at->getElementType(), mod), at->getArraySize());\n\t\t}\n\t\telse if(type->isPointerType() || type->isNullType())\n\t\t{\n\t\t\tif(type == fir::Type::getVoidPtr() || type->isNullType())\n\t\t\t\treturn llvm::Type::getInt8PtrTy(gc);\n\n\t\t\telse\n\t\t\t\treturn typeToLlvm(type->getPointerElementType(), mod)->getPointerTo();\n\t\t}\n\t\telse if(type->isVoidType())\n\t\t{\n\t\t\treturn llvm::Type::getVoidTy(gc);\n\t\t}\n\t\telse if(type->isDynamicArrayType())\n\t\t{\n\t\t\tfir::DynamicArrayType* llat = type->toDynamicArrayType();\n\t\t\tstd::vector<llvm::Type*> mems(4);\n\n\t\t\tmems[SAA_DATA_INDEX]        = typeToLlvm(llat->getElementType()->getPointerTo(), mod);\n\t\t\tmems[SAA_LENGTH_INDEX]      = getNativeWordTy();\n\t\t\tmems[SAA_CAPACITY_INDEX]    = getNativeWordTy();\n\t\t\tmems[SAA_REFCOUNTPTR_INDEX] = getNativeWordTy()->getPointerTo();\n\n\t\t\treturn llvm::StructType::get(gc, mems, false);\n\t\t}\n\t\telse if(type->isStringType())\n\t\t{\n\t\t\tllvm::Type* i8ptrtype = llvm::Type::getInt8PtrTy(gc);\n\n\t\t\tauto id = fir::Name::obfuscate(\"string\", fir::NameKind::Type);\n\t\t\tif(createdTypes.find(id) != createdTypes.end())\n\t\t\t\treturn createdTypes[id];\n\n\n\t\t\tstd::vector<llvm::Type*> mems(4);\n\n\t\t\tmems[SAA_DATA_INDEX]        = i8ptrtype;\n\t\t\tmems[SAA_LENGTH_INDEX]      = getNativeWordTy();\n\t\t\tmems[SAA_CAPACITY_INDEX]    = getNativeWordTy();\n\t\t\tmems[SAA_REFCOUNTPTR_INDEX] = getNativeWordTy()->getPointerTo();\n\n\t\t\tauto str = llvm::StructType::create(gc, id.mangled());\n\t\t\tstr->setBody(mems);\n\n\t\t\treturn createdTypes[id] = str;\n\t\t}\n\t\telse if(type->isArraySliceType())\n\t\t{\n\t\t\tfir::ArraySliceType* slct = type->toArraySliceType();\n\t\t\tstd::vector<llvm::Type*> mems(2);\n\n\t\t\tmems[SLICE_DATA_INDEX]          = typeToLlvm(slct->getElementType()->getPointerTo(), mod);\n\t\t\tmems[SLICE_LENGTH_INDEX]        = getNativeWordTy();\n\n\t\t\treturn llvm::StructType::get(gc, mems, false);\n\t\t}\n\t\telse if(type->isBoolType())\n\t\t{\n\t\t\treturn llvm::Type::getInt1Ty(gc);\n\t\t}\n\t\telse if(type->isRangeType())\n\t\t{\n\t\t\tauto id = fir::Name::obfuscate(\"range\", fir::NameKind::Type);\n\t\t\tif(createdTypes.find(id) != createdTypes.end())\n\t\t\t\treturn createdTypes[id];\n\n\t\t\tauto str = llvm::StructType::create(gc, id.mangled());\n\t\t\tstr->setBody({ getNativeWordTy(), getNativeWordTy(), getNativeWordTy() });\n\n\t\t\treturn createdTypes[id] = str;\n\t\t}\n\t\telse if(type->isEnumType())\n\t\t{\n\t\t\tstd::vector<llvm::Type*> mems;\n\t\t\tmems.push_back(getNativeWordTy());\n\t\t\tmems.push_back(typeToLlvm(type->toEnumType()->getCaseType(), mod));\n\n\t\t\treturn llvm::StructType::get(gc, mems, false);\n\t\t}\n\t\telse if(type->isAnyType())\n\t\t{\n\t\t\tllvm::Type* arrtype = llvm::ArrayType::get(llvm::Type::getInt8Ty(gc), BUILTIN_ANY_DATA_BYTECOUNT);\n\n\t\t\tauto id = fir::Name::obfuscate(\"any\", fir::NameKind::Type);\n\t\t\tif(createdTypes.find(id) != createdTypes.end())\n\t\t\t\treturn createdTypes[id];\n\n\t\t\tauto str = llvm::StructType::create(gc, id.mangled());\n\n\t\t\t// typeid (+ highest-bit-mask), refcount, data.\n\t\t\tstr->setBody({ getNativeWordTy(), getNativeWordTy()->getPointerTo(), arrtype });\n\n\t\t\treturn createdTypes[id] = str;\n\t\t}\n\t\telse if(type->isUnionType())\n\t\t{\n\t\t\tauto ut = type->toUnionType();\n\n\t\t\tif(createdTypes.find(ut->getTypeName()) != createdTypes.end())\n\t\t\t\treturn createdTypes[ut->getTypeName()];\n\n\t\t\tauto dl = llvm::DataLayout(mod);\n\n\t\t\tsize_t maxSz = 0;\n\t\t\tfor(auto v : ut->getVariants())\n\t\t\t{\n\t\t\t\tif(!v.second->getInteriorType()->isVoidType())\n\t\t\t\t\tmaxSz = std::max(maxSz, static_cast<size_t>(dl.getTypeAllocSize(typeToLlvm(v.second->getInteriorType(), mod))));\n\t\t\t}\n\n\t\t\tif(maxSz > 0)\n\t\t\t{\n\t\t\t\tcreatedTypes[ut->getTypeName()] = llvm::StructType::create(gc, {\n\t\t\t\t\tgetNativeWordTy(), llvm::ArrayType::get(llvm::Type::getInt8Ty(gc), maxSz)\n\t\t\t\t}, ut->getTypeName().mangled());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcreatedTypes[ut->getTypeName()] = llvm::StructType::create(gc, { getNativeWordTy() }, ut->getTypeName().mangled());\n\t\t\t}\n\n\t\t\treturn createdTypes[ut->getTypeName()];\n\t\t}\n\t\telse if(type->isRawUnionType())\n\t\t{\n\t\t\tauto ut = type->toRawUnionType();\n\n\t\t\tif(createdTypes.find(ut->getTypeName()) != createdTypes.end())\n\t\t\t\treturn createdTypes[ut->getTypeName()];\n\n\t\t\tauto dl = llvm::DataLayout(mod);\n\n\t\t\tsize_t maxSz = 0;\n\t\t\tfor(auto v : ut->getVariants())\n\t\t\t\tmaxSz = std::max(maxSz, static_cast<size_t>(dl.getTypeAllocSize(typeToLlvm(v.second, mod))));\n\n\t\t\ticeAssert(maxSz > 0);\n\t\t\tcreatedTypes[ut->getTypeName()] = llvm::StructType::create(gc, {\n\t\t\t\tllvm::IntegerType::getIntNTy(gc, static_cast<unsigned int>(maxSz * CHAR_BIT))\n\t\t\t}, ut->getTypeName().mangled());\n\n\t\t\treturn createdTypes[ut->getTypeName()];\n\t\t}\n\t\telse if(type->isPolyPlaceholderType())\n\t\t{\n\t\t\terror(\"llvm: unfulfilled polymorphic placeholder type '%s'\", type);\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(\"llvm: unimplememented type '%s' for LLVM backend\", type);\n\t\t}\n\t}\n\n\n\tstatic llvm::Function* translateFunctionDecl(fir::Function* ffn, util::hash_map<size_t, llvm::Value*>& valueMap, llvm::Module* mod)\n\t{\n\t\tif(auto it = valueMap.find(ffn->id); it != valueMap.end())\n\t\t\treturn llvm::cast<llvm::Function>(it->second);\n\n\t\tllvm::GlobalValue::LinkageTypes link;\n\t\tswitch(ffn->linkageType)\n\t\t{\n\t\t\tcase fir::LinkageType::External:\n\t\t\t\tlink = llvm::GlobalValue::LinkageTypes::ExternalLinkage;\n\t\t\t\tbreak;\n\n\t\t\tcase fir::LinkageType::Internal:\n\t\t\t\tlink = llvm::GlobalValue::LinkageTypes::InternalLinkage;\n\t\t\t\tbreak;\n\n\t\t\tcase fir::LinkageType::ExternalWeak:\n\t\t\t\tlink = llvm::GlobalValue::LinkageTypes::ExternalWeakLinkage;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\terror(\"llvm: enotsup\");\n\t\t}\n\n\n\t\tllvm::FunctionType* ftype = llvm::cast<llvm::FunctionType>(typeToLlvm(ffn->getType(), mod)->getPointerElementType());\n\t\tllvm::Function* func = llvm::Function::Create(ftype, link, ffn->getName().mangled(), mod);\n\n\t\tif(ffn->isAlwaysInlined())\n\t\t\tfunc->addFnAttr(llvm::Attribute::AttrKind::AlwaysInline);\n\n\t\tvalueMap[ffn->id] = func;\n\n\t\tsize_t i = 0;\n\t\tfor(auto it = func->arg_begin(); it != func->arg_end(); it++, i++)\n\t\t\tvalueMap[ffn->getArguments()[i]->id] = it;\n\n\n\t\tfor(auto b : ffn->getBlockList())\n\t\t{\n\t\t\tllvm::BasicBlock* bb = llvm::BasicBlock::Create(LLVMBackend::getLLVMContext(), b->getName().mangled(), func);\n\t\t\tvalueMap[b->id] = bb;\n\t\t}\n\n\t\treturn func;\n\t}\n\n\tstatic llvm::Constant* constToLlvm(fir::ConstantValue* fc, util::hash_map<size_t, llvm::Value*>& valueMap, llvm::Module* mod)\n\t{\n\t\ticeAssert(fc);\n\t\tauto ret = cachedConstants[fc];\n\t\tif(ret) return ret;\n\n\t\tif(auto ci = dcast(fir::ConstantInt, fc))\n\t\t{\n\t\t\tllvm::Type* it = typeToLlvm(fc->getType(), mod);\n\t\t\tif(ci->getType()->toPrimitiveType()->isSigned())\n\t\t\t{\n\t\t\t\treturn cachedConstants[fc] = llvm::ConstantInt::getSigned(it, ci->getSignedValue());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn cachedConstants[fc] = llvm::ConstantInt::get(it, ci->getUnsignedValue());\n\t\t\t}\n\t\t}\n\t\telse if(auto cf = dcast(fir::ConstantFP, fc))\n\t\t{\n\t\t\tllvm::Type* it = typeToLlvm(fc->getType(), mod);\n\t\t\treturn cachedConstants[fc] = llvm::ConstantFP::get(it, cf->getValue());\n\t\t}\n\t\telse if(dcast(fir::ConstantNumber, fc))\n\t\t{\n\t\t\terror(\"cannot\");\n\t\t}\n\t\telse if(auto cc = dcast(fir::ConstantBool, fc))\n\t\t{\n\t\t\tllvm::Type* ct = typeToLlvm(fc->getType(), mod);\n\t\t\treturn cachedConstants[fc] = llvm::ConstantInt::get(ct, cc->getValue());\n\t\t}\n\t\telse if(auto cbc = dcast(fir::ConstantBitcast, fc))\n\t\t{\n\t\t\tllvm::Type* t = typeToLlvm(cbc->getType(), mod);\n\t\t\treturn cachedConstants[fc] = llvm::ConstantExpr::getBitCast(constToLlvm(cbc->getValue(), valueMap, mod), t);\n\t\t}\n\t\telse if(auto ca = dcast(fir::ConstantArray, fc))\n\t\t{\n\t\t\tauto arrt = llvm::cast<llvm::ArrayType>(typeToLlvm(ca->getType(), mod));\n\n\t\t\tstd::vector<llvm::Constant*> vals;\n\t\t\tvals.reserve(ca->getValues().size());\n\n\t\t\tfor(auto con : ca->getValues())\n\t\t\t{\n\t\t\t\tauto c = constToLlvm(con, valueMap, mod);\n\t\t\t\tif(c->getType() != arrt->getArrayElementType())\n\t\t\t\t{\n\t\t\t\t\terror(\"llvm: expected type '%s' in const array (%d), found '%s'\",\n\t\t\t\t\t\tllvmTyToString(arrt->getArrayElementType()), ca->id, llvmToString(c));\n\t\t\t\t\t// c = llvm::ConstantExpr::getBitCast(c, arrt->getArrayElementType());\n\t\t\t\t}\n\n\t\t\t\tvals.push_back(c);\n\t\t\t}\n\n\t\t\treturn cachedConstants[fc] = llvm::ConstantArray::get(arrt, vals);\n\t\t}\n\t\telse if(auto ct = dcast(fir::ConstantTuple, fc))\n\t\t{\n\t\t\tstd::vector<llvm::Constant*> vals;\n\t\t\tvals.reserve(ct->getValues().size());\n\n\t\t\tfor(auto v : ct->getValues())\n\t\t\t\tvals.push_back(constToLlvm(v, valueMap, mod));\n\n\t\t\treturn cachedConstants[fc] = llvm::ConstantStruct::getAnon(LLVMBackend::getLLVMContext(), vals);\n\t\t}\n\t\telse if(auto cec = dcast(fir::ConstantEnumCase, fc))\n\t\t{\n\t\t\tauto ty = typeToLlvm(cec->getType(), mod);\n\t\t\ticeAssert(ty->isStructTy());\n\n\t\t\treturn cachedConstants[fc] = llvm::ConstantStruct::get(llvm::cast<llvm::StructType>(ty),\n\t\t\t\tconstToLlvm(cec->getIndex(), valueMap, mod), constToLlvm(cec->getValue(), valueMap, mod));\n\t\t}\n\t\telse if(dcast(fir::ConstantCharSlice, fc) || dcast(fir::ConstantDynamicString, fc))\n\t\t{\n\t\t\tbool wasDynStr = false;\n\n\t\t\tstd::string str;\n\t\t\tif(auto ccs = dcast(fir::ConstantCharSlice, fc))\n\t\t\t\tstr = ccs->getValue();\n\n\t\t\telse if(auto cds = dcast(fir::ConstantDynamicString, fc))\n\t\t\t\twasDynStr = true, str = cds->getValue();\n\n\n\t\t\tllvm::Constant* cstr = llvm::ConstantDataArray::getString(LLVMBackend::getLLVMContext(), str, true);\n\t\t\tllvm::GlobalVariable* gv = new llvm::GlobalVariable(*mod, cstr->getType(), true,\n\t\t\t\tllvm::GlobalValue::LinkageTypes::InternalLinkage, cstr, \"_FV_STR_\" + std::to_string(fc->id));\n\n\t\t\tauto zconst = llvm::ConstantInt::get(getNativeWordTy(), 0);\n\t\t\tstd::vector<llvm::Constant*> indices = { zconst, zconst };\n\t\t\tllvm::Constant* gepd = llvm::ConstantExpr::getGetElementPtr(gv->getType()->getPointerElementType(), gv, indices);\n\n\t\t\tauto len = llvm::ConstantInt::get(getNativeWordTy(), str.size());\n\n\t\t\ticeAssert(gepd->getType() == llvm::Type::getInt8PtrTy(LLVMBackend::getLLVMContext()));\n\t\t\ticeAssert(len->getType() == getNativeWordTy());\n\n\t\t\tfir::Type* ty = fir::Type::getCharSlice(false);\n\t\t\tstd::vector<llvm::Constant*> mems = { gepd, len };\n\t\t\tif(wasDynStr)\n\t\t\t{\n\t\t\t\tty = fir::Type::getString();\n\n\t\t\t\t// add -1 for the capacity and 0 for the refcountptr.\n\t\t\t\tmems.push_back(llvm::ConstantInt::get(getNativeWordTy(), static_cast<uint64_t>(-1)));\n\t\t\t\tmems.push_back(zconst);\n\t\t\t}\n\n\t\t\tauto ret = llvm::ConstantStruct::get(llvm::cast<llvm::StructType>(typeToLlvm(ty, mod)), mems);\n\n\t\t\tcachedConstants[fc] = ret;\n\t\t\treturn ret;\n\t\t}\n\t\telse if(auto cas = dcast(fir::ConstantArraySlice, fc))\n\t\t{\n\t\t\tstd::vector<llvm::Constant*> mems = { constToLlvm(cas->getData(), valueMap, mod), constToLlvm(cas->getLength(), valueMap, mod) };\n\n\t\t\tauto ret = llvm::ConstantStruct::get(llvm::cast<llvm::StructType>(typeToLlvm(cas->getType(), mod)), mems);\n\t\t\treturn cachedConstants[fc] = ret;\n\t\t}\n\t\telse if(auto cda = dcast(fir::ConstantDynamicArray, fc))\n\t\t{\n\t\t\tif(cda->getArray())\n\t\t\t{\n\t\t\t\tllvm::Constant* constArray = constToLlvm(cda->getArray(), valueMap, mod);\n\t\t\t\ticeAssert(constArray);\n\n\t\t\t\t// don't make it immutable. this probably puts the global variable in the .data segment, instead of the\n\t\t\t\t// .rodata/.rdata segment.\n\n\t\t\t\t// this allows us to modify it, eg.\n\t\t\t\t// var foo = [ 1, 2, 3 ]\n\t\t\t\t// foo[0] = 4\n\n\t\t\t\t// of course, since capacity == -1, the moment we try to like append or something,\n\t\t\t\t// we get back new heap memory\n\n\t\t\t\tllvm::GlobalVariable* tmpglob = new llvm::GlobalVariable(*mod, constArray->getType(), false,\n\t\t\t\t\tllvm::GlobalValue::LinkageTypes::InternalLinkage, constArray, \"_FV_ARR_\" + std::to_string(cda->id));\n\n\t\t\t\tauto zconst = llvm::ConstantInt::get(getNativeWordTy(), 0);\n\t\t\t\tstd::vector<llvm::Constant*> indices = { zconst, zconst };\n\t\t\t\tllvm::Constant* gepd = llvm::ConstantExpr::getGetElementPtr(tmpglob->getType()->getPointerElementType(), tmpglob, indices);\n\n\t\t\t\tauto flen = fir::ConstantInt::getNative(cda->getArray()->getType()->toArrayType()->getArraySize());\n\t\t\t\tauto fcap = fir::ConstantInt::getNative(-1);\n\t\t\t\tstd::vector<llvm::Constant*> mems = { gepd, constToLlvm(flen, valueMap, mod), constToLlvm(fcap, valueMap, mod), zconst };\n\n\t\t\t\tauto ret = llvm::ConstantStruct::get(llvm::cast<llvm::StructType>(typeToLlvm(cda->getType(), mod)), mems);\n\t\t\t\treturn cachedConstants[fc] = ret;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstd::vector<llvm::Constant*> mems = { constToLlvm(cda->getData(), valueMap, mod), constToLlvm(cda->getLength(), valueMap, mod),\n\t\t\t\t\tconstToLlvm(cda->getCapacity(), valueMap, mod), llvm::ConstantInt::get(getNativeWordTy(), 0) };\n\n\t\t\t\tauto ret = llvm::ConstantStruct::get(llvm::cast<llvm::StructType>(typeToLlvm(cda->getType(), mod)), mems);\n\t\t\t\treturn cachedConstants[fc] = ret;\n\t\t\t}\n\t\t}\n\t\telse if(auto fn = dcast(fir::Function, fc))\n\t\t{\n\t\t\treturn translateFunctionDecl(fn, valueMap, mod);\n\t\t}\n\t\telse if(dcast(fir::ConstantStruct, fc))\n\t\t{\n\t\t\t_error_and_exit(\"notsup const struct\\n\");\n\t\t}\n\t\telse if(auto it = valueMap.find(fc->id); it != valueMap.end() && llvm::isa<llvm::Constant>(it->second))\n\t\t{\n\t\t\treturn llvm::cast<llvm::Constant>(it->second);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn cachedConstants[fc] = llvm::Constant::getNullValue(typeToLlvm(fc->getType(), mod));\n\t\t}\n\t}\n\n\n\n\n\n\n\tllvm::Module* LLVMBackend::translateFIRtoLLVM(fir::Module* firmod)\n\t{\n\t\tauto& gc = LLVMBackend::getLLVMContext();\n\n\t\tllvm::Module* module = new llvm::Module(firmod->getModuleName(), LLVMBackend::getLLVMContext());\n\t\tllvm::IRBuilder<> builder(gc);\n\n\n\t\tcreatedTypes.clear();\n\t\tcachedConstants.clear();\n\n\t\tutil::hash_map<size_t, llvm::Value*>& valueMap = *(new util::hash_map<size_t, llvm::Value*>());\n\n\n\n\t\tauto decay = [&builder](fir::Value* fv, llvm::Value* lv) -> llvm::Value* {\n\t\t\tif(fv->islvalue())\n\t\t\t\treturn builder.CreateLoad(lv);\n\n\t\t\telse\n\t\t\t\treturn lv;\n\t\t};\n\n\n\t\tauto getValue = [&valueMap, &module, &firmod](fir::Value* fv) -> llvm::Value*\n\t\t{\n\t\t\tif(fir::GlobalVariable* gv = dcast(fir::GlobalVariable, fv))\n\t\t\t{\n\t\t\t\tllvm::Value* lgv = valueMap[gv->id];\n\t\t\t\tif(!lgv)\n\t\t\t\t\terror(\"llvm: failed to find var %d in mod %s\\n\", gv->id, firmod->getModuleName());\n\n\t\t\t\ticeAssert(lgv);\n\t\t\t\treturn lgv;\n\t\t\t}\n\t\t\t// we must do this because function now derives from constantvalue\n\t\t\telse if(dcast(fir::Function, fv))\n\t\t\t{\n\t\t\t\tllvm::Value* ret = valueMap[fv->id];\n\t\t\t\tif(!ret) error(\"llvm: !ret fn (id = %d)\", fv->id);\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t\telse if(fir::ConstantValue* cv = dcast(fir::ConstantValue, fv))\n\t\t\t{\n\t\t\t\treturn constToLlvm(cv, valueMap, module);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tllvm::Value* ret = valueMap[fv->id];\n\t\t\t\tif(!ret) error(\"llvm: !ret (id = %d)\", fv->id);\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t};\n\n\t\tauto getUndecayedOperand = [&getValue](fir::Instruction* inst, size_t op) -> llvm::Value* {\n\n\t\t\ticeAssert(inst->operands.size() > op);\n\t\t\tfir::Value* fv = inst->operands[op];\n\n\t\t\treturn getValue(fv);\n\t\t};\n\n\n\t\tauto getOperand = [&getValue, &decay](fir::Instruction* inst, size_t op) -> llvm::Value* {\n\n\t\t\ticeAssert(inst->operands.size() > op);\n\t\t\tfir::Value* fv = inst->operands[op];\n\n\t\t\treturn decay(fv, getValue(fv));\n\t\t};\n\n\n\t\tauto addValueToMap = [&valueMap](llvm::Value* v, fir::Value* fv) {\n\n\t\t\ticeAssert(v);\n\n\t\t\t// fprintf(stderr, \"add id %d\\n\", fv->id);\n\n\t\t\tif(valueMap.find(fv->id) != valueMap.end())\n\t\t\t\terror(\"llvm: already have value with id %d\", fv->id);\n\n\t\t\tvalueMap[fv->id] = v;\n\t\t\t// printf(\"adding value %d\\n\", fv->id);\n\n\t\t\tif(!v->getType()->isVoidTy())\n\t\t\t\tv->setName(fv->getName().mangled());\n\t\t};\n\n\n\t\tstatic size_t strn = 0;\n\t\tfor(auto string : firmod->_getGlobalStrings())\n\t\t{\n\t\t\tstd::string id = \"_FV_STR\" + std::to_string(strn);\n\n\t\t\tllvm::Constant* cstr = llvm::ConstantDataArray::getString(gc, string.first, true);\n\t\t\tllvm::Constant* gv = new llvm::GlobalVariable(*module, cstr->getType(), true,\n\t\t\t\tllvm::GlobalValue::LinkageTypes::InternalLinkage, cstr, id);\n\n\t\t\tauto zconst = llvm::ConstantInt::get(getNativeWordTy(), 0);\n\n\t\t\tstd::vector<llvm::Constant*> ix { zconst, zconst };\n\t\t\tgv = llvm::ConstantExpr::getInBoundsGetElementPtr(gv->getType()->getPointerElementType(), gv, ix);\n\n\n\t\t\tvalueMap[string.second->id] = gv;\n\t\t\tstrn++;\n\t\t}\n\n\t\tfor(auto global : firmod->_getGlobals())\n\t\t{\n\t\t\tllvm::Constant* initval = 0;\n\t\t\tllvm::Type* ty = typeToLlvm(global.second->getType(), module);\n\n\t\t\tif(global.second->getInitialValue() != 0)\n\t\t\t\tinitval = constToLlvm(global.second->getInitialValue(), valueMap, module);\n\n\t\t\telse\n\t\t\t\tinitval = llvm::Constant::getNullValue(ty);\n\n\t\t\tllvm::GlobalVariable* gv = new llvm::GlobalVariable(*module, ty, false, global.second->linkageType == fir::LinkageType::External ? llvm::GlobalValue::LinkageTypes::ExternalLinkage : llvm::GlobalValue::LinkageTypes::InternalLinkage, initval,\n\t\t\t\tglobal.first.mangled());\n\n\t\t\tvalueMap[global.second->id] = gv;\n\t\t}\n\n\t\tfor(auto type : firmod->_getNamedTypes())\n\t\t{\n\t\t\t// should just automatically create it.\n\t\t\ttypeToLlvm(type.second, module);\n\t\t}\n\n\t\tfor(auto intr : firmod->_getIntrinsicFunctions())\n\t\t{\n\t\t\tllvm::Value* fn = 0;\n\n\t\t\t//* in LLVM 7, the intrinsics changed to no longer specify the alignment\n\t\t\t//* so, the arugments are: [ ptr, ptr, size, is_volatile ]\n\t\t\tif(intr.first.str() == \"memcpy\")\n\t\t\t{\n\t\t\t\tllvm::FunctionType* ft = llvm::FunctionType::get(llvm::Type::getVoidTy(gc), { llvm::Type::getInt8PtrTy(gc),\n\t\t\t\t\tllvm::Type::getInt8PtrTy(gc), getNativeWordTy(), llvm::Type::getInt1Ty(gc) }, false);\n\t\t\t\tfn = module->getOrInsertFunction(strprintf(\"llvm.memcpy.p0i8.p0i8.i%d\", fir::getNativeWordSizeInBits()), ft).getCallee();\n\t\t\t}\n\t\t\telse if(intr.first.str() == \"memmove\")\n\t\t\t{\n\t\t\t\tllvm::FunctionType* ft = llvm::FunctionType::get(llvm::Type::getVoidTy(gc), { llvm::Type::getInt8PtrTy(gc),\n\t\t\t\t\tllvm::Type::getInt8PtrTy(gc), getNativeWordTy(), llvm::Type::getInt1Ty(gc) }, false);\n\t\t\t\tfn = module->getOrInsertFunction(strprintf(\"llvm.memmove.p0i8.p0i8.i%d\", fir::getNativeWordSizeInBits()), ft).getCallee();\n\t\t\t}\n\t\t\telse if(intr.first.str() == \"memset\")\n\t\t\t{\n\t\t\t\tllvm::FunctionType* ft = llvm::FunctionType::get(llvm::Type::getVoidTy(gc), { llvm::Type::getInt8PtrTy(gc),\n\t\t\t\t\tllvm::Type::getInt8Ty(gc), getNativeWordTy(), llvm::Type::getInt1Ty(gc) }, false);\n\t\t\t\tfn = module->getOrInsertFunction(strprintf(\"llvm.memset.p0i8.i%d\", fir::getNativeWordSizeInBits()), ft).getCallee();\n\t\t\t}\n\t\t\telse if(intr.first.str() == \"memcmp\")\n\t\t\t{\n\t\t\t\t// in line with the rest, take 4 arguments. (this is our own \"intrinsic\")\n\n\t\t\t\tllvm::FunctionType* ft = llvm::FunctionType::get(llvm::Type::getInt32Ty(gc), { llvm::Type::getInt8PtrTy(gc),\n\t\t\t\t\tllvm::Type::getInt8PtrTy(gc), getNativeWordTy(), llvm::Type::getInt1Ty(gc) }, false);\n\n\t\t\t\tfn = llvm::Function::Create(ft, llvm::GlobalValue::LinkageTypes::InternalLinkage, \"fir.intrinsic.memcmp\", module);\n\t\t\t\tllvm::Function* func = llvm::cast<llvm::Function>(fn);\n\t\t\t\ticeAssert(func);\n\n\t\t\t\t// ok... now make the function, right here.\n\t\t\t\t{\n\t\t\t\t\tfunc->addFnAttr(llvm::Attribute::AttrKind::AlwaysInline);\n\t\t\t\t\tllvm::BasicBlock* entry = llvm::BasicBlock::Create(gc, \"entry\", func);\n\n\t\t\t\t\tbuilder.SetInsertPoint(entry);\n\n\t\t\t\t\t/*\n\t\t\t\t\t\tbasically:\n\n\t\t\t\t\t\tint counter = 0;\n\t\t\t\t\t\twhile(counter < size)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ti8 c1 = s1[counter];\n\t\t\t\t\t\t\ti8 c2 = s2[counter];\n\n\t\t\t\t\t\t\tif(c1 != c2)\n\t\t\t\t\t\t\t\treturn c1 - c2;\n\n\t\t\t\t\t\t\tcounter++;\n\t\t\t\t\t\t}\n\t\t\t\t\t*/\n\n\t\t\t\t\tllvm::Value* res = builder.CreateAlloca(llvm::Type::getInt32Ty(gc));\n\t\t\t\t\tllvm::Value* ptr1 = 0;\n\t\t\t\t\tllvm::Value* ptr2 = 0;\n\t\t\t\t\tllvm::Value* cmplen = 0;\n\t\t\t\t\t{\n\t\t\t\t\t\t// llvm is stupid.\n\t\t\t\t\t\tauto it = func->arg_begin();\n\t\t\t\t\t\tptr1 = it;\n\t\t\t\t\t\tit++;\n\n\t\t\t\t\t\tptr2 = it;\n\t\t\t\t\t\tit++;\n\n\t\t\t\t\t\tcmplen = it;\n\t\t\t\t\t}\n\n\t\t\t\t\tauto zeroconst = llvm::ConstantInt::get(gc, llvm::APInt(64, 0, true));\n\t\t\t\t\tauto zeroconst8 = llvm::ConstantInt::get(gc, llvm::APInt(8, 0, true));\n\n\t\t\t\t\tllvm::Value* ctr = builder.CreateAlloca(getNativeWordTy());\n\t\t\t\t\tbuilder.CreateStore(zeroconst, ctr);\n\n\t\t\t\t\tllvm::BasicBlock* loopcond = llvm::BasicBlock::Create(gc, \"loopcond\", func);\n\t\t\t\t\tllvm::BasicBlock* loopbody = llvm::BasicBlock::Create(gc, \"loopbody\", func);\n\t\t\t\t\tllvm::BasicBlock* merge = llvm::BasicBlock::Create(gc, \"merge\", func);\n\n\n\t\t\t\t\t// explicit branch to loopcond\n\t\t\t\t\tbuilder.CreateBr(loopcond);\n\n\t\t\t\t\tbuilder.SetInsertPoint(loopcond);\n\t\t\t\t\t{\n\t\t\t\t\t\t// bounds check\n\t\t\t\t\t\tllvm::Value* cond = builder.CreateICmpSLT(builder.CreateLoad(ctr), cmplen);\n\t\t\t\t\t\tbuilder.CreateCondBr(cond, loopbody, merge);\n\t\t\t\t\t}\n\n\t\t\t\t\tbuilder.SetInsertPoint(loopbody);\n\t\t\t\t\t{\n\t\t\t\t\t\tllvm::Value* ctrval = builder.CreateLoad(ctr);\n\n\t\t\t\t\t\tllvm::Value* ch1 = builder.CreateLoad(builder.CreateInBoundsGEP(ptr1, ctrval));\n\t\t\t\t\t\tllvm::Value* ch2 = builder.CreateLoad(builder.CreateInBoundsGEP(ptr2, ctrval));\n\n\t\t\t\t\t\tllvm::Value* diff = builder.CreateSub(ch1, ch2);\n\t\t\t\t\t\tbuilder.CreateStore(builder.CreateIntCast(diff, llvm::Type::getInt32Ty(gc), false), res);\n\n\t\t\t\t\t\tbuilder.CreateStore(builder.CreateAdd(ctrval, llvm::ConstantInt::get(gc, llvm::APInt(64, 1, true))), ctr);\n\n\t\t\t\t\t\tbuilder.CreateCondBr(builder.CreateICmpEQ(diff, zeroconst8), loopcond, merge);\n\t\t\t\t\t}\n\n\t\t\t\t\tbuilder.SetInsertPoint(merge);\n\t\t\t\t\t{\n\t\t\t\t\t\tbuilder.CreateRet(builder.CreateLoad(res));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(intr.first.name == \"roundup_pow2\")\n\t\t\t{\n\t\t\t\tllvm::FunctionType* ft = llvm::FunctionType::get(getNativeWordTy(), { getNativeWordTy() }, false);\n\t\t\t\tfn = llvm::Function::Create(ft, llvm::GlobalValue::LinkageTypes::InternalLinkage, \"fir.intrinsic.roundup_pow2\", module);\n\n\t\t\t\tllvm::Function* func = llvm::cast<llvm::Function>(fn);\n\t\t\t\ticeAssert(func);\n\n\n\t\t\t\t// ok... now make the function, right here.\n\t\t\t\t{\n\t\t\t\t\tfunc->addFnAttr(llvm::Attribute::AttrKind::AlwaysInline);\n\t\t\t\t\tllvm::BasicBlock* entry = llvm::BasicBlock::Create(gc, \"entry\", func);\n\n\t\t\t\t\tbuilder.SetInsertPoint(entry);\n\n\t\t\t\t\t/*\n\t\t\t\t\t\tbasically:\n\n\t\t\t\t\t\tint num = arg;\n\t\t\t\t\t\tint ret = 1;\n\n\t\t\t\t\t\twhile(num > 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tnum >>= 1\n\t\t\t\t\t\t\tret <<= 1;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn ret;\n\t\t\t\t\t*/\n\n\t\t\t\t\tllvm::Value* num = builder.CreateAlloca(getNativeWordTy());\n\t\t\t\t\tllvm::Value* retval = builder.CreateAlloca(getNativeWordTy());\n\n\t\t\t\t\tauto oneconst = llvm::ConstantInt::get(gc, llvm::APInt(64, 1, true));\n\t\t\t\t\tauto zeroconst = llvm::ConstantInt::get(gc, llvm::APInt(64, 0, true));\n\n\t\t\t\t\tbuilder.CreateStore(oneconst, retval);\n\t\t\t\t\tbuilder.CreateStore(func->arg_begin(), num);\n\n\n\t\t\t\t\tllvm::BasicBlock* loopcond = llvm::BasicBlock::Create(gc, \"loopcond\", func);\n\t\t\t\t\tllvm::BasicBlock* loopbody = llvm::BasicBlock::Create(gc, \"loopbody\", func);\n\t\t\t\t\tllvm::BasicBlock* merge = llvm::BasicBlock::Create(gc, \"merge\", func);\n\n\n\t\t\t\t\t// explicit branch to loopcond\n\t\t\t\t\tbuilder.CreateBr(loopcond);\n\n\t\t\t\t\tbuilder.SetInsertPoint(loopcond);\n\t\t\t\t\t{\n\t\t\t\t\t\t// bounds check\n\t\t\t\t\t\tllvm::Value* cond = builder.CreateICmpSGT(builder.CreateLoad(num), zeroconst);\n\t\t\t\t\t\tbuilder.CreateCondBr(cond, loopbody, merge);\n\t\t\t\t\t}\n\n\t\t\t\t\tbuilder.SetInsertPoint(loopbody);\n\t\t\t\t\t{\n\t\t\t\t\t\tllvm::Value* shifted = builder.CreateLShr(builder.CreateLoad(num), 1);\n\t\t\t\t\t\tbuilder.CreateStore(shifted, num);\n\n\t\t\t\t\t\tbuilder.CreateStore(builder.CreateShl(builder.CreateLoad(retval), 1), retval);\n\n\t\t\t\t\t\tbuilder.CreateBr(loopcond);\n\t\t\t\t\t}\n\n\t\t\t\t\tbuilder.SetInsertPoint(merge);\n\t\t\t\t\t{\n\t\t\t\t\t\tbuilder.CreateRet(builder.CreateLoad(retval));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\terror(\"llvm: unknown intrinsic '%s'\", intr.first.str());\n\t\t\t}\n\n\t\t\tvalueMap[intr.second->id] = fn;\n\t\t}\n\n\t\t// fprintf(stderr, \"translating module %s\\n\", this->moduleName.c_str());\n\t\tfor(auto f : firmod->_getFunctions())\n\t\t{\n\t\t\ttranslateFunctionDecl(f.second, valueMap, module);\n\t\t}\n\n\n\t\t#define DO_DUMP 0\n\n\t\t#if DO_DUMP\n\t\t#define DUMP_INSTR(fmt, ...)\t\t(fprintf(stderr, fmt, ##__VA_ARGS__))\n\t\t#else\n\t\t#define DUMP_INSTR(...)\n\t\t#endif\n\n\n\t\tfor(auto fp : firmod->_getFunctions())\n\t\t{\n\t\t\tfir::Function* ffn = fp.second;\n\n\t\t\t// if(isGenericInAnyWay(ffn->getType()))\n\t\t\t\t// continue;\n\n\t\t\tllvm::Function* func = module->getFunction(fp.second->getName().mangled());\n\t\t\ticeAssert(func);\n\n\n\t\t\tDUMP_INSTR(\"%s%s\", ffn->getBlockList().size() == 0 ? \"declare \" : \"\", ffn->getName().c_str());\n\n\t\t\tif(ffn->getBlockList().size() > 0)\n\t\t\t{\n\t\t\t\t// print args\n\t\t\t\tDUMP_INSTR(\" :: (\");\n\n\t\t\t\tsize_t i = 0;\n\t\t\t\tfor(auto arg : ffn->getArguments())\n\t\t\t\t{\n\t\t\t\t\tDUMP_INSTR(\"%%%d :: %s\", arg->id, arg->getType()->str().c_str());\n\t\t\t\t\ti++;\n\n\t\t\t\t\t(void) arg;\n\n\t\t\t\t\tif(i != ffn->getArgumentCount())\n\t\t\t\t\t{\n\t\t\t\t\t\tDUMP_INSTR(\",\");\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tDUMP_INSTR(\")\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tDUMP_INSTR(\" :: %s\\n\", ffn->getType()->str().c_str());\n\t\t\t}\n\n\t\t\tfor(auto block : ffn->getBlockList())\n\t\t\t{\n\t\t\t\tllvm::BasicBlock* bb = llvm::cast<llvm::BasicBlock>(valueMap[block->id]);\n\t\t\t\tbuilder.SetInsertPoint(bb);\n\n\t\t\t\tDUMP_INSTR(\"\\n    %s\", (\"(%\" + std::to_string(block->id) + \") \" + block->getName() + \":\\n\").c_str());\n\n\t\t\t\tfor(auto inst : block->getInstructions())\n\t\t\t\t{\n\t\t\t\t\tDUMP_INSTR(\"        %s\\n\", inst->str().c_str());\n\n\t\t\t\t\t// good god.\n\t\t\t\t\tswitch(inst->opKind)\n\t\t\t\t\t{\n\t\t\t\t\t\tcase fir::OpKind::Signed_Add:\n\t\t\t\t\t\tcase fir::OpKind::Unsigned_Add:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateAdd(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Signed_Sub:\n\t\t\t\t\t\tcase fir::OpKind::Unsigned_Sub:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateSub(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Signed_Mul:\n\t\t\t\t\t\tcase fir::OpKind::Unsigned_Mul:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateMul(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Signed_Div:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateSDiv(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Signed_Mod:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateSRem(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Signed_Neg:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 1);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateNeg(a);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Unsigned_Div:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateUDiv(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Unsigned_Mod:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateURem(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Floating_Add:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFAdd(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Floating_Sub:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFSub(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Floating_Mul:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFMul(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Floating_Div:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFDiv(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Floating_Mod:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFRem(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Floating_Neg:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 1);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFNeg(a);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Floating_Truncate:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tfir::Type* ft = inst->operands[1]->getType();\n\n\t\t\t\t\t\t\tllvm::Type* t = typeToLlvm(ft, module);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFPTrunc(a, t);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Floating_Extend:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tfir::Type* ft = inst->operands[1]->getType();\n\n\t\t\t\t\t\t\tllvm::Type* t = typeToLlvm(ft, module);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFPExt(a, t);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Integer_ZeroExt:\n\t\t\t\t\t\tcase fir::OpKind::Integer_Truncate:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tfir::Type* ft = inst->operands[1]->getType();\n\n\t\t\t\t\t\t\tllvm::Type* t = typeToLlvm(ft, module);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateZExtOrTrunc(a, t);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\n\n\t\t\t\t\t\tcase fir::OpKind::ICompare_Equal:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateICmpEQ(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::ICompare_NotEqual:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateICmpNE(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::ICompare_Greater:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = 0;\n\t\t\t\t\t\t\tif(inst->operands[0]->getType()->isSignedIntType() || inst->operands[1]->getType()->isSignedIntType())\n\t\t\t\t\t\t\t\tret = builder.CreateICmpSGT(a, b);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tret = builder.CreateICmpUGT(a, b);\n\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::ICompare_Less:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = 0;\n\t\t\t\t\t\t\tif(inst->operands[0]->getType()->isSignedIntType() || inst->operands[1]->getType()->isSignedIntType())\n\t\t\t\t\t\t\t\tret = builder.CreateICmpSLT(a, b);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tret = builder.CreateICmpULT(a, b);\n\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\tcase fir::OpKind::ICompare_GreaterEqual:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = 0;\n\t\t\t\t\t\t\tif(inst->operands[0]->getType()->isSignedIntType() || inst->operands[1]->getType()->isSignedIntType())\n\t\t\t\t\t\t\t\tret = builder.CreateICmpSGE(a, b);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tret = builder.CreateICmpUGE(a, b);\n\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::ICompare_LessEqual:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = 0;\n\t\t\t\t\t\t\tif(inst->operands[0]->getType()->isSignedIntType() || inst->operands[1]->getType()->isSignedIntType())\n\t\t\t\t\t\t\t\tret = builder.CreateICmpSLE(a, b);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tret = builder.CreateICmpULE(a, b);\n\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::FCompare_Equal_ORD:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFCmpOEQ(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::FCompare_Equal_UNORD:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFCmpUEQ(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::FCompare_NotEqual_ORD:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFCmpONE(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::FCompare_NotEqual_UNORD:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFCmpUNE(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::FCompare_Greater_ORD:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFCmpOGT(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::FCompare_Greater_UNORD:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFCmpUGT(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::FCompare_Less_ORD:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFCmpOLT(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::FCompare_Less_UNORD:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFCmpULT(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::FCompare_GreaterEqual_ORD:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFCmpOGE(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::FCompare_GreaterEqual_UNORD:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFCmpUGE(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::FCompare_LessEqual_ORD:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFCmpOLE(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::FCompare_LessEqual_UNORD:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateFCmpULE(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\tcase fir::OpKind::ICompare_Multi:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tbool sgn = inst->operands[0]->getType()->isSignedIntType() || inst->operands[1]->getType()->isSignedIntType();\n\n\t\t\t\t\t\t\tllvm::Value* r1 = 0;\n\t\t\t\t\t\t\tif(sgn)\tr1 = builder.CreateICmpSGE(a, b);\n\t\t\t\t\t\t\telse\tr1 = builder.CreateICmpUGE(a, b);\n\n\t\t\t\t\t\t\tllvm::Value* r2 = 0;\n\t\t\t\t\t\t\tif(sgn)\tr2 = builder.CreateICmpSLE(a, b);\n\t\t\t\t\t\t\telse\tr2 = builder.CreateICmpULE(a, b);\n\n\t\t\t\t\t\t\tr1 = builder.CreateIntCast(r1, getNativeWordTy(), false);\n\t\t\t\t\t\t\tr2 = builder.CreateIntCast(r2, getNativeWordTy(), false);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateSub(r1, r2);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\tcase fir::OpKind::FCompare_Multi:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* r1 = builder.CreateFCmpOGE(a, b);\n\t\t\t\t\t\t\tllvm::Value* r2 = builder.CreateFCmpOLE(a, b);\n\n\t\t\t\t\t\t\tr1 = builder.CreateIntCast(r1, getNativeWordTy(), false);\n\t\t\t\t\t\t\tr2 = builder.CreateIntCast(r2, getNativeWordTy(), false);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateSub(r1, r2);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t\t\t\t\t\tcase fir::OpKind::Bitwise_Not:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 1);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateNot(a);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Bitwise_Xor:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateXor(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Bitwise_Arithmetic_Shr:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateAShr(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Bitwise_Logical_Shr:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateLShr(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Bitwise_Shl:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateShl(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Bitwise_And:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateAnd(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Bitwise_Or:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateOr(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Value_WritePtr:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tif(a->getType() != b->getType()->getPointerElementType())\n\t\t\t\t\t\t\t\terror(\"llvm: cannot store '%s' into '%s'\", inst->operands[0]->getType(), inst->operands[1]->getType());\n\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateStore(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Value_ReadPtr:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 1);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateLoad(a);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Value_CreatePHI:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 1);\n\t\t\t\t\t\t\tllvm::Type* t = typeToLlvm(inst->operands[0]->getType(), module);\n\n\t\t\t\t\t\t\tauto phi = dcast(fir::PHINode, inst->realOutput);\n\t\t\t\t\t\t\ticeAssert(phi);\n\n\t\t\t\t\t\t\tllvm::PHINode* ret = builder.CreatePHI(t, static_cast<unsigned int>(phi->getValues().size()));\n\n\t\t\t\t\t\t\tfor(auto v : phi->getValues())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tret->addIncoming(decay(v.second, getValue(v.second)),\n\t\t\t\t\t\t\t\t\tllvm::cast<llvm::BasicBlock>(decay(v.first, getValue(v.first)))\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Value_CallFunction:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() >= 1);\n\t\t\t\t\t\t\tfir::Function* fn = dcast(fir::Function, inst->operands[0]);\n\t\t\t\t\t\t\ticeAssert(fn);\n\n\t\t\t\t\t\t\tllvm::Function* a = llvm::cast<llvm::Function>(getUndecayedOperand(inst, 0));\n\n\t\t\t\t\t\t\tstd::vector<llvm::Value*> args;\n\n\t\t\t\t\t\t\tstd::vector<fir::Value*> fargs = inst->operands;\n\n\t\t\t\t\t\t\tfor(size_t i = 1; i < fargs.size(); ++i)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\targs.push_back(decay(fargs[i], getValue(fargs[i])));\n\t\t\t\t\t\t\t\t// args.back()->dump();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// a->dump();\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateCall(a, args);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Value_CallFunctionPointer:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() >= 1);\n\t\t\t\t\t\t\tllvm::Value* fn = getOperand(inst, 0);\n\n\t\t\t\t\t\t\tstd::vector<llvm::Value*> args;\n\n\t\t\t\t\t\t\tstd::vector<fir::Value*> fargs = inst->operands;\n\n\t\t\t\t\t\t\tfor(size_t i = 1; i < fargs.size(); ++i)\n\t\t\t\t\t\t\t\targs.push_back(decay(fargs[i], getValue(fargs[i])));\n\n\t\t\t\t\t\t\tllvm::Type* lft = typeToLlvm(inst->operands.front()->getType(), module);\n\n\t\t\t\t\t\t\ticeAssert(lft->isPointerTy());\n\t\t\t\t\t\t\ticeAssert(lft->getPointerElementType()->isFunctionTy());\n\n\t\t\t\t\t\t\tllvm::FunctionType* ft = llvm::cast<llvm::FunctionType>(lft->getPointerElementType());\n\t\t\t\t\t\t\ticeAssert(ft);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateCall(ft, fn, args);\n\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Value_CallVirtualMethod:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// args are: 0. classtype, 1. index, 2. functiontype, 3...N args\n\t\t\t\t\t\t\tauto clsty = inst->operands[0]->getType()->toClassType();\n\t\t\t\t\t\t\ticeAssert(clsty);\n\t\t\t\t\t\t\ticeAssert(clsty->getVirtualMethodCount() > 0);\n\n\t\t\t\t\t\t\tstd::vector<llvm::Value*> args;\n\t\t\t\t\t\t\tfor(size_t i = 3; i < inst->operands.size(); i++)\n\t\t\t\t\t\t\t\targs.push_back(decay(inst->operands[i], getValue(inst->operands[i])));\n\n\t\t\t\t\t\t\tllvm::Value* vtable = builder.CreateLoad(builder.CreateStructGEP(typeToLlvm(clsty, module), args[0], 0));\n\n\t\t\t\t\t\t\tvtable = builder.CreateBitOrPointerCast(vtable,\n\t\t\t\t\t\t\t\tllvm::ArrayType::get(llvm::FunctionType::get(llvm::Type::getVoidTy(gc), false)->getPointerTo(),\n\t\t\t\t\t\t\t\tclsty->getVirtualMethodCount())->getPointerTo());\n\n\t\t\t\t\t\t\tauto fptr = builder.CreateConstInBoundsGEP2_32(vtable->getType()->getPointerElementType(), vtable,\n\t\t\t\t\t\t\t\t0, static_cast<unsigned int>(dcast(fir::ConstantInt, inst->operands[1])->getUnsignedValue()));\n\n\t\t\t\t\t\t\tauto ffty = inst->operands[2]->getType()->toFunctionType();\n\n\t\t\t\t\t\t\tfptr = builder.CreateBitOrPointerCast(builder.CreateLoad(fptr), typeToLlvm(ffty, module));\n\n\t\t\t\t\t\t\tllvm::FunctionType* ft = llvm::cast<llvm::FunctionType>(typeToLlvm(ffty, module)->getPointerElementType());\n\t\t\t\t\t\t\ticeAssert(ft);\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateCall(ft, fptr, args);\n\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Value_Return:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tllvm::Value* ret = 0;\n\t\t\t\t\t\t\tif(inst->operands.size() == 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tret = builder.CreateRetVoid();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 1);\n\t\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\n\t\t\t\t\t\t\t\tret = builder.CreateRet(a);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Branch_UnCond:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 1);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateBr(llvm::cast<llvm::BasicBlock>(a));\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Branch_Cond:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 3);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\t\t\t\t\t\t\tllvm::Value* c = getOperand(inst, 2);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateCondBr(a, llvm::cast<llvm::BasicBlock>(b), llvm::cast<llvm::BasicBlock>(c));\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\n\n\t\t\t\t\t\tcase fir::OpKind::Cast_Bitcast:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tfir::Type* ft = inst->operands[1]->getType();\n\t\t\t\t\t\t\tllvm::Type* t = typeToLlvm(ft, module);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateBitCast(a, t);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Cast_IntSize:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\n\t\t\t\t\t\t\tfir::Type* ft = inst->operands[1]->getType();\n\t\t\t\t\t\t\tllvm::Type* t = typeToLlvm(ft, module);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateIntCast(a, t, ft->isSignedIntType());\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Cast_Signedness:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\n\t\t\t\t\t\t\t// no-op\n\t\t\t\t\t\t\taddValueToMap(a, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Cast_FloatToInt:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tfir::Type* ft = inst->operands[1]->getType();\n\t\t\t\t\t\t\tllvm::Type* t = typeToLlvm(ft, module);\n\n\t\t\t\t\t\t\tllvm::Value* ret = 0;\n\t\t\t\t\t\t\tif(ft->isSignedIntType())\n\t\t\t\t\t\t\t\tret = builder.CreateFPToSI(a, t);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tret = builder.CreateFPToUI(a, t);\n\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Cast_IntToFloat:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tfir::Type* ft = inst->operands[1]->getType();\n\t\t\t\t\t\t\tllvm::Type* t = typeToLlvm(ft, module);\n\n\t\t\t\t\t\t\tllvm::Value* ret = 0;\n\t\t\t\t\t\t\tif(inst->operands[0]->getType()->isSignedIntType())\n\t\t\t\t\t\t\t\tret = builder.CreateSIToFP(a, t);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tret = builder.CreateUIToFP(a, t);\n\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Cast_PointerType:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tfir::Type* ft = inst->operands[1]->getType();\n\t\t\t\t\t\t\tllvm::Type* t = typeToLlvm(ft, module);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreatePointerCast(a, t);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Cast_PointerToInt:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tfir::Type* ft = inst->operands[1]->getType();\n\t\t\t\t\t\t\tllvm::Type* t = typeToLlvm(ft, module);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreatePtrToInt(a, t);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Cast_IntToPointer:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tfir::Type* ft = inst->operands[1]->getType();\n\t\t\t\t\t\t\tllvm::Type* t = typeToLlvm(ft, module);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateIntToPtr(a, t);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Cast_IntSignedness:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// is no op.\n\t\t\t\t\t\t\t// since llvm does not differentiate signed and unsigned.\n\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* ret = getOperand(inst, 0);\n\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\n\n\n\t\t\t\t\t\tcase fir::OpKind::Value_GetPointer:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// equivalent to GEP(ptr*, index)\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\ticeAssert(!inst->operands[0]->getType()->isClassType() && !inst->operands[0]->getType()->isStructType());\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateGEP(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Value_GetGEP2:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// equivalent to GEP(ptr*, index)\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 3);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\n\t\t\t\t\t\t\ticeAssert(!inst->operands[0]->getType()->isClassType() && !inst->operands[0]->getType()->isStructType());\n\n\t\t\t\t\t\t\tstd::vector<llvm::Value*> indices = { getOperand(inst, 1), getOperand(inst, 2) };\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateGEP(a, indices);\n\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\n\t\t\t\t\t\tcase fir::OpKind::Misc_Sizeof:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 1);\n\n\t\t\t\t\t\t\tllvm::Type* t = getOperand(inst, 0)->getType();\n\t\t\t\t\t\t\ticeAssert(t);\n\n\t\t\t\t\t\t\tllvm::Value* gep = builder.CreateConstGEP1_64(llvm::ConstantPointerNull::get(t->getPointerTo()), 1);\n\t\t\t\t\t\t\tgep = builder.CreatePtrToInt(gep, getNativeWordTy());\n\n\t\t\t\t\t\t\taddValueToMap(gep, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\n\n\n\n\n\n\n\n\t\t\t\t\t\tcase fir::OpKind::Logical_Not:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 1);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateICmpEQ(a, llvm::Constant::getNullValue(a->getType()));\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\n\t\t\t\t\t\tcase fir::OpKind::Value_InsertValue:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() >= 3);\n\n\t\t\t\t\t\t\tllvm::Value* str = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* elm = getOperand(inst, 1);\n\n\t\t\t\t\t\t\tstd::vector<unsigned int> inds;\n\t\t\t\t\t\t\tfor(size_t i = 2; i < inst->operands.size(); i++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfir::ConstantInt* ci = dcast(fir::ConstantInt, inst->operands[i]);\n\t\t\t\t\t\t\t\ticeAssert(ci);\n\n\t\t\t\t\t\t\t\tinds.push_back(static_cast<unsigned int>(ci->getUnsignedValue()));\n\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\ticeAssert(str->getType()->isStructTy() || str->getType()->isArrayTy());\n\t\t\t\t\t\t\tif(str->getType()->isStructTy())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ticeAssert(elm->getType() == llvm::cast<llvm::StructType>(str->getType())->getElementType(inds[0]));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if(str->getType()->isArrayTy())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ticeAssert(elm->getType() == llvm::cast<llvm::ArrayType>(str->getType())->getElementType());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ticeAssert(0);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateInsertValue(str, elm, inds);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Value_ExtractValue:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() >= 2);\n\n\t\t\t\t\t\t\tllvm::Value* str = getOperand(inst, 0);\n\n\t\t\t\t\t\t\tstd::vector<unsigned int> inds;\n\t\t\t\t\t\t\tfor(size_t i = 1; i < inst->operands.size(); i++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfir::ConstantInt* ci = dcast(fir::ConstantInt, inst->operands[i]);\n\t\t\t\t\t\t\t\ticeAssert(ci);\n\n\t\t\t\t\t\t\t\tinds.push_back(static_cast<unsigned int>(ci->getUnsignedValue()));\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\ticeAssert(str->getType()->isStructTy() || str->getType()->isArrayTy());\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateExtractValue(str, inds);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t\t\t\t\t\tcase fir::OpKind::SAA_GetData:\n\t\t\t\t\t\tcase fir::OpKind::SAA_GetLength:\n\t\t\t\t\t\tcase fir::OpKind::SAA_GetCapacity:\n\t\t\t\t\t\tcase fir::OpKind::SAA_GetRefCountPtr:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 1);\n\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\ticeAssert(a->getType()->isStructTy());\n\n\t\t\t\t\t\t\tint ind = 0;\n\t\t\t\t\t\t\tif(inst->opKind == fir::OpKind::SAA_GetData)\n\t\t\t\t\t\t\t\tind = SAA_DATA_INDEX;\n\n\t\t\t\t\t\t\telse if(inst->opKind == fir::OpKind::SAA_GetLength)\n\t\t\t\t\t\t\t\tind = SAA_LENGTH_INDEX;\n\n\t\t\t\t\t\t\telse if(inst->opKind == fir::OpKind::SAA_GetCapacity)\n\t\t\t\t\t\t\t\tind = SAA_CAPACITY_INDEX;\n\n\t\t\t\t\t\t\telse if(inst->opKind == fir::OpKind::SAA_GetRefCountPtr)\n\t\t\t\t\t\t\t\tind = SAA_REFCOUNTPTR_INDEX;\n\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ticeAssert(0 && \"invalid\");\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateExtractValue(a, ind);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::SAA_SetData:\n\t\t\t\t\t\tcase fir::OpKind::SAA_SetLength:\n\t\t\t\t\t\tcase fir::OpKind::SAA_SetCapacity:\n\t\t\t\t\t\tcase fir::OpKind::SAA_SetRefCountPtr:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\ticeAssert(a->getType()->isStructTy());\n\n\t\t\t\t\t\t\tint ind = 0;\n\t\t\t\t\t\t\tif(inst->opKind == fir::OpKind::SAA_SetData)\n\t\t\t\t\t\t\t\tind = SAA_DATA_INDEX;\n\n\t\t\t\t\t\t\telse if(inst->opKind == fir::OpKind::SAA_SetLength)\n\t\t\t\t\t\t\t\tind = SAA_LENGTH_INDEX;\n\n\t\t\t\t\t\t\telse if(inst->opKind == fir::OpKind::SAA_SetCapacity)\n\t\t\t\t\t\t\t\tind = SAA_CAPACITY_INDEX;\n\n\t\t\t\t\t\t\telse if(inst->opKind == fir::OpKind::SAA_SetRefCountPtr)\n\t\t\t\t\t\t\t\tind = SAA_REFCOUNTPTR_INDEX;\n\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ticeAssert(0 && \"invalid\");\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateInsertValue(a, b, ind);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\n\n\n\n\n\n\n\t\t\t\t\t\tcase fir::OpKind::ArraySlice_GetData:\n\t\t\t\t\t\tcase fir::OpKind::ArraySlice_GetLength:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 1);\n\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\ticeAssert(a->getType()->isStructTy());\n\n\t\t\t\t\t\t\tint ind = 0;\n\t\t\t\t\t\t\tif(inst->opKind == fir::OpKind::ArraySlice_GetData)         ind = SLICE_DATA_INDEX;\n\t\t\t\t\t\t\telse if(inst->opKind == fir::OpKind::ArraySlice_GetLength)  ind = SLICE_LENGTH_INDEX;\n\t\t\t\t\t\t\telse                                                        iceAssert(0 && \"invalid\");\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateExtractValue(a, ind);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\n\t\t\t\t\t\tcase fir::OpKind::ArraySlice_SetData:\n\t\t\t\t\t\tcase fir::OpKind::ArraySlice_SetLength:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\ticeAssert(a->getType()->isStructTy());\n\n\t\t\t\t\t\t\tint ind = 0;\n\t\t\t\t\t\t\tif(inst->opKind == fir::OpKind::ArraySlice_SetData)         ind = SLICE_DATA_INDEX;\n\t\t\t\t\t\t\telse if(inst->opKind == fir::OpKind::ArraySlice_SetLength)  ind = SLICE_LENGTH_INDEX;\n\t\t\t\t\t\t\telse                                                        iceAssert(0 && \"invalid\");\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateInsertValue(a, b, ind);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\n\n\n\n\n\n\n\t\t\t\t\t\tcase fir::OpKind::Any_GetData:\n\t\t\t\t\t\tcase fir::OpKind::Any_GetTypeID:\n\t\t\t\t\t\tcase fir::OpKind::Any_GetRefCountPtr:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 1);\n\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\ticeAssert(a->getType()->isStructTy());\n\n\t\t\t\t\t\t\tint ind = 0;\n\t\t\t\t\t\t\tif(inst->opKind == fir::OpKind::Any_GetTypeID)\n\t\t\t\t\t\t\t\tind = ANY_TYPEID_INDEX;\n\n\t\t\t\t\t\t\telse if(inst->opKind == fir::OpKind::Any_GetRefCountPtr)\n\t\t\t\t\t\t\t\tind = ANY_REFCOUNTPTR_INDEX;\n\n\t\t\t\t\t\t\telse if(inst->opKind == fir::OpKind::Any_GetData)\n\t\t\t\t\t\t\t\tind = ANY_DATA_ARRAY_INDEX;\n\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ticeAssert(0 && \"invalid\");\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateExtractValue(a, ind);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Any_SetData:\n\t\t\t\t\t\tcase fir::OpKind::Any_SetTypeID:\n\t\t\t\t\t\tcase fir::OpKind::Any_SetRefCountPtr:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\ticeAssert(a->getType()->isStructTy());\n\n\t\t\t\t\t\t\tint ind = 0;\n\t\t\t\t\t\t\tif(inst->opKind == fir::OpKind::Any_SetTypeID)\n\t\t\t\t\t\t\t\tind = ANY_TYPEID_INDEX;\n\n\t\t\t\t\t\t\telse if(inst->opKind == fir::OpKind::Any_SetRefCountPtr)\n\t\t\t\t\t\t\t\tind = ANY_REFCOUNTPTR_INDEX;\n\n\t\t\t\t\t\t\telse if(inst->opKind == fir::OpKind::Any_SetData)\n\t\t\t\t\t\t\t\tind = ANY_DATA_ARRAY_INDEX;\n\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ticeAssert(0 && \"invalid\");\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateInsertValue(a, b, ind);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\n\t\t\t\t\t\tcase fir::OpKind::Range_GetLower:\n\t\t\t\t\t\tcase fir::OpKind::Range_GetUpper:\n\t\t\t\t\t\tcase fir::OpKind::Range_GetStep:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tunsigned int pos = 0;\n\t\t\t\t\t\t\tif(inst->opKind == fir::OpKind::Range_GetUpper)\n\t\t\t\t\t\t\t\tpos = 1;\n\n\t\t\t\t\t\t\telse if(inst->opKind == fir::OpKind::Range_GetStep)\n\t\t\t\t\t\t\t\tpos = 2;\n\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\ticeAssert(a->getType()->isStructTy());\n\n\t\t\t\t\t\t\tllvm::Value* val = builder.CreateExtractValue(a, { pos });\n\t\t\t\t\t\t\taddValueToMap(val, inst->realOutput);\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\tcase fir::OpKind::Range_SetLower:\n\t\t\t\t\t\tcase fir::OpKind::Range_SetUpper:\n\t\t\t\t\t\tcase fir::OpKind::Range_SetStep:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tunsigned int pos = 0;\n\t\t\t\t\t\t\tif(inst->opKind == fir::OpKind::Range_SetUpper)\n\t\t\t\t\t\t\t\tpos = 1;\n\n\t\t\t\t\t\t\telse if(inst->opKind == fir::OpKind::Range_SetStep)\n\t\t\t\t\t\t\t\tpos = 2;\n\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\ticeAssert(a->getType()->isStructTy());\n\t\t\t\t\t\t\ticeAssert(b->getType()->isIntegerTy());\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateInsertValue(a, b, { pos });\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\n\t\t\t\t\t\tcase fir::OpKind::Enum_GetIndex:\n\t\t\t\t\t\tcase fir::OpKind::Enum_GetValue:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tunsigned int pos = 0;\n\t\t\t\t\t\t\tif(inst->opKind == fir::OpKind::Enum_GetValue)\n\t\t\t\t\t\t\t\tpos = 1;\n\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\ticeAssert(a->getType()->isStructTy());\n\n\t\t\t\t\t\t\tllvm::Value* val = builder.CreateExtractValue(a, { pos });\n\t\t\t\t\t\t\taddValueToMap(val, inst->realOutput);\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\tcase fir::OpKind::Enum_SetIndex:\n\t\t\t\t\t\tcase fir::OpKind::Enum_SetValue:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tunsigned int pos = 0;\n\t\t\t\t\t\t\tif(inst->opKind == fir::OpKind::Enum_SetValue)\n\t\t\t\t\t\t\t\tpos = 1;\n\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getOperand(inst, 1);\n\n\t\t\t\t\t\t\ticeAssert(a->getType()->isStructTy());\n\t\t\t\t\t\t\tif(pos == 0)\ticeAssert(b->getType()->isIntegerTy());\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateInsertValue(a, b, { pos });\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Value_Select:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tllvm::Value* cond = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* one = getOperand(inst, 1);\n\t\t\t\t\t\t\tllvm::Value* two = getOperand(inst, 2);\n\n\t\t\t\t\t\t\ticeAssert(cond->getType()->isIntegerTy() && cond->getType()->getIntegerBitWidth() == 1);\n\t\t\t\t\t\t\ticeAssert(one->getType() == two->getType());\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateSelect(cond, one, two);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\n\t\t\t\t\t\tcase fir::OpKind::Value_StackAlloc:\n\t\t\t\t\t\tcase fir::OpKind::Value_CreateLVal:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 1);\n\t\t\t\t\t\t\tfir::Type* ft = inst->operands[0]->getType();\n\t\t\t\t\t\t\tllvm::Type* t = typeToLlvm(ft, module);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateAlloca(t);\n\t\t\t\t\t\t\tbuilder.CreateStore(llvm::Constant::getNullValue(t), ret);\n\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Value_Store:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* b = getUndecayedOperand(inst, 1);\n\n\t\t\t\t\t\t\tif(a->getType() != b->getType()->getPointerElementType())\n\t\t\t\t\t\t\t\terror(\"llvm: cannot store '%s' into '%s'\", inst->operands[0]->getType(), inst->operands[1]->getType());\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateStore(a, b);\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Value_AddressOf:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 1);\n\t\t\t\t\t\t\tllvm::Value* a = getUndecayedOperand(inst, 0);\n\n\t\t\t\t\t\t\taddValueToMap(a, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Value_Dereference:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 1);\n\t\t\t\t\t\t\tllvm::Value* a = getOperand(inst, 0);\n\n\t\t\t\t\t\t\taddValueToMap(a, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::RawUnion_GEP:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* a = getUndecayedOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Type* target = typeToLlvm(inst->operands[1]->getType(), module);\n\n\t\t\t\t\t\t\ticeAssert(a->getType()->isPointerTy() && a->getType()->getPointerElementType()->isStructTy());\n\t\t\t\t\t\t\tauto ptr = builder.CreateConstGEP2_32(a->getType()->getPointerElementType(), a, 0, 0);\n\t\t\t\t\t\t\tptr = builder.CreatePointerCast(ptr, target->getPointerTo());\n\n\t\t\t\t\t\t\taddValueToMap(ptr, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\n\t\t\t\t\t\tcase fir::OpKind::Value_GetPointerToStructMember:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// equivalent to llvm's GEP(ptr*, ptrIndex, memberIndex)\n\t\t\t\t\t\t\terror(\"llvm: enotsup\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Value_GetStructMember:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// equivalent to GEP(ptr*, 0, memberIndex)\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\tllvm::Value* ptr = getUndecayedOperand(inst, 0);\n\n\t\t\t\t\t\t\tfir::ConstantInt* ci = dcast(fir::ConstantInt, inst->operands[1]);\n\t\t\t\t\t\t\ticeAssert(ci);\n\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateStructGEP(ptr->getType()->getPointerElementType(),\n\t\t\t\t\t\t\t\tptr, static_cast<unsigned int>(ci->getUnsignedValue()));\n\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\tcase fir::OpKind::Union_GetVariantID:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// fairly straightforward.\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 1);\n\t\t\t\t\t\t\ticeAssert(inst->operands[0]->getType()->isUnionType());\n\n\t\t\t\t\t\t\tllvm::Value* uv = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateExtractValue(uv, { 0 });\n\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Union_SetVariantID:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\ticeAssert(inst->operands[0]->getType()->isUnionType());\n\n\t\t\t\t\t\t\tllvm::Value* uv = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreateInsertValue(uv, getOperand(inst, 1), { 0 });\n\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\tcase fir::OpKind::Union_GetValue:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 2);\n\t\t\t\t\t\t\ticeAssert(inst->operands[0]->getType()->isUnionType());\n\n\t\t\t\t\t\t\tauto ut = inst->operands[0]->getType()->toUnionType();\n\t\t\t\t\t\t\tauto vid = dcast(fir::ConstantInt, inst->operands[1])->getSignedValue();\n\n\t\t\t\t\t\t\ticeAssert(static_cast<size_t>(vid) < ut->getVariantCount());\n\t\t\t\t\t\t\tauto vt = ut->getVariant(vid)->getInteriorType();\n\n\t\t\t\t\t\t\tauto lut = typeToLlvm(ut, module);\n\t\t\t\t\t\t\tauto lvt = typeToLlvm(vt, module);\n\n\t\t\t\t\t\t\tllvm::Value* unionVal = getOperand(inst, 0);\n\t\t\t\t\t\t\tllvm::Value* arrp = builder.CreateAlloca(lut->getStructElementType(1));\n\t\t\t\t\t\t\tbuilder.CreateStore(builder.CreateExtractValue(unionVal, { 1 }), arrp);\n\n\t\t\t\t\t\t\t// cast to the appropriate type.\n\t\t\t\t\t\t\tllvm::Value* ret = builder.CreatePointerCast(arrp, lvt->getPointerTo());\n\t\t\t\t\t\t\tret = builder.CreateLoad(ret);\n\n\t\t\t\t\t\t\taddValueToMap(ret, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\tcase fir::OpKind::Union_SetValue:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ticeAssert(inst->operands.size() == 3);\n\t\t\t\t\t\t\ticeAssert(inst->operands[0]->getType()->isUnionType());\n\n\t\t\t\t\t\t\tauto luv = getOperand(inst, 0);\n\t\t\t\t\t\t\tauto lut = luv->getType();\n\n\t\t\t\t\t\t\tauto val = getOperand(inst, 2);\n\n\t\t\t\t\t\t\t// this is not really efficient, but without a significant\n\t\t\t\t\t\t\t// re-architecting of how we handle structs and pointers and shit\n\t\t\t\t\t\t\t// (to let us use GEP for everything), this will have to do.\n\n\t\t\t\t\t\t\tllvm::Value* arrp = builder.CreateAlloca(lut->getStructElementType(1));\n\n\t\t\t\t\t\t\t// cast to the correct pointer type\n\t\t\t\t\t\t\tauto valp = builder.CreateBitCast(arrp, val->getType()->getPointerTo());\n\t\t\t\t\t\t\tbuilder.CreateStore(val, valp);\n\n\t\t\t\t\t\t\t// cast it back, then load it.\n\t\t\t\t\t\t\tarrp = builder.CreateBitCast(valp, arrp->getType());\n\t\t\t\t\t\t\tauto arr = builder.CreateLoad(arrp);\n\n\t\t\t\t\t\t\t// insert it back into the union.\n\t\t\t\t\t\t\tluv = builder.CreateInsertValue(luv, arr, { 1 });\n\n\t\t\t\t\t\t\t// then insert the id.\n\t\t\t\t\t\t\tluv = builder.CreateInsertValue(luv, getOperand(inst, 1), { 0 });\n\n\t\t\t\t\t\t\taddValueToMap(luv, inst->realOutput);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\n\n\n\n\n\n\t\t\t\t\t\tcase fir::OpKind::Unreachable:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbuilder.CreateUnreachable();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase fir::OpKind::Invalid:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// note we don't use \"default\" to catch\n\t\t\t\t\t\t\t// new opkinds that we forget to add.\n\t\t\t\t\t\t\ticeAssert(\"invalid opcode\" && 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn module;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/backend/x64AsmBackend.cpp",
    "content": "// x64AsmBackend.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"backend.h\"\n\nnamespace backend\n{\n\tx64Backend::x64Backend(CompiledData& dat, const std::vector<std::string>& inputs, const std::string& output)\n\t\t: Backend(0, dat, inputs, output)\n\t{\n\t}\n\n\tvoid x64Backend::performCompilation()\n\t{\n\t\t_error_and_exit(\"enotsup\\n\");\n\t}\n\n\tvoid x64Backend::optimiseProgram()\n\t{\n\t\t_error_and_exit(\"enotsup\\n\");\n\t}\n\n\tvoid x64Backend::writeOutput()\n\t{\n\t\t_error_and_exit(\"enotsup\\n\");\n\t}\n\n\tstd::string x64Backend::str()\n\t{\n\t\treturn \"x64 Assembly\";\n\t}\n}\n"
  },
  {
    "path": "source/codegen/alloc.cpp",
    "content": "// alloc.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"codegen.h\"\n#include \"platform.h\"\n#include \"gluecode.h\"\n\nstatic fir::Function* getCheckNegativeLengthFunction(cgn::CodegenState* cs)\n{\n\tauto fname = fir::Name::obfuscate(\"alloc_checkneg\");\n\tfir::Function* checkf = cs->module->getFunction(fname);\n\n\tif(!checkf)\n\t{\n\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\tfir::FunctionType::get({ fir::Type::getNativeWord(), fir::Type::getCharSlice(false) }, fir::Type::getVoid()),\n\t\t\tfir::LinkageType::Internal);\n\n\t\tfunc->setAlwaysInline();\n\n\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\tcs->irb.setCurrentBlock(entry);\n\n\t\tfir::Value* s1 = func->getArguments()[0];\n\t\tfir::Value* s2 = func->getArguments()[1];\n\n\t\tfir::IRBlock* failb = cs->irb.addNewBlockInFunction(\"fail\", func);\n\t\tfir::IRBlock* merge = cs->irb.addNewBlockInFunction(\"merge\", func);\n\n\t\t// make the thing\n\t\tauto isNeg = cs->irb.ICmpLT(s1, fir::ConstantInt::getNative(0));\n\t\tcs->irb.CondBranch(isNeg, failb, merge);\n\n\n\t\tcs->irb.setCurrentBlock(failb);\n\t\t{\n\t\t\tcgn::glue::printRuntimeError(cs, s2, \"tried to allocate a negative ('%ld') amount of memory\\n\", { s1 });\n\t\t}\n\n\t\tcs->irb.setCurrentBlock(merge);\n\t\tcs->irb.ReturnVoid();\n\n\t\tcs->irb.setCurrentBlock(restore);\n\t\tcheckf = func;\n\t}\n\n\ticeAssert(checkf);\n\treturn checkf;\n}\n\n\nstatic fir::Value* performAllocation(cgn::CodegenState* cs, sst::AllocOp* alloc, fir::Type* type, std::vector<sst::Expr*> counts, bool isRaw)\n{\n\tauto callSetFunction = [cs](fir::Type* type, sst::AllocOp* alloc, fir::Value* ptr, fir::Value* count) -> void {\n\n\t\tauto callUserCode = [cs, alloc](fir::Value* elmp, fir::Value* idxp) {\n\t\t\ticeAssert(alloc->initBlockIdx);\n\t\t\ticeAssert(alloc->initBlockVar);\n\n\t\t\t// ok, then. create the variables:\n\t\t\tcs->addVariableUsingStorage(alloc->initBlockIdx, idxp);\n\t\t\tcs->addVariableUsingStorage(alloc->initBlockVar, elmp);\n\n\t\t\talloc->initBlock->codegen(cs);\n\t\t};\n\n\n\n\n\t\tauto arrp = ptr;\n\t\tauto ctrp = cs->irb.CreateLValue(fir::Type::getNativeWord());\n\n\t\tauto actuallyStore = [cs, type, alloc](fir::Value* ptr) -> void {\n\n\t\t\tif(type->isClassType())\n\t\t\t{\n\t\t\t\tauto constr = dcast(sst::FunctionDefn, alloc->constructor);\n\t\t\t\ticeAssert(constr);\n\n\t\t\t\t//! here, the arguments are called once per element.\n\t\t\t\tauto value = cs->constructClassWithArguments(type->toClassType(), constr, alloc->arguments);\n\t\t\t\tcs->autoAssignRefCountedValue(cs->irb.Dereference(ptr), value, true);\n\t\t\t}\n\t\t\telse if(type->isStructType())\n\t\t\t{\n\t\t\t\tauto value = cs->getConstructedStructValue(type->toStructType(), alloc->arguments);\n\t\t\t\tcs->autoAssignRefCountedValue(cs->irb.Dereference(ptr), value, true);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto value = cs->getDefaultValue(type);\n\t\t\t\tcs->autoAssignRefCountedValue(cs->irb.Dereference(ptr), value, true);\n\t\t\t}\n\t\t};\n\n\n\t\tif(alloc->counts.empty())\n\t\t{\n\t\t\tactuallyStore(arrp);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcs->createWhileLoop([cs, ctrp, count](auto pass, auto fail) {\n\t\t\t\tauto cond = cs->irb.ICmpLT(ctrp, count);\n\t\t\t\tcs->irb.CondBranch(cond, pass, fail);\n\t\t\t},\n\t\t\t[cs, callUserCode, actuallyStore, alloc, ctrp, arrp]() {\n\n\t\t\t\tauto ptr = cs->irb.GetPointer(arrp, ctrp);\n\n\t\t\t\tactuallyStore(ptr);\n\n\t\t\t\tif(alloc->initBlock)\n\t\t\t\t\tcallUserCode(cs->irb.Dereference(ptr), ctrp);\n\n\t\t\t\tcs->irb.Store(cs->irb.Add(ctrp, fir::ConstantInt::getNative(1)), ctrp);\n\t\t\t});\n\t\t}\n\t};\n\n\n\n\tif(counts.empty() || isRaw)\n\t{\n\t\tfir::Value* cnt = (counts.empty() ? fir::ConstantInt::getNative(1)\n\t\t\t: cs->oneWayAutocast(counts[0]->codegen(cs, fir::Type::getNativeWord()).value, fir::Type::getNativeWord()));\n\n\t\t//* if we don't have a count, then we just return a T* -- no arrays, nothing.\n\n\t\tauto sz = cs->irb.Multiply(cs->irb.Sizeof(type), cnt);\n\t\tauto mem = cs->irb.Call(cgn::glue::misc::getMallocWrapperFunction(cs), sz, fir::ConstantCharSlice::get(alloc->loc.shortString()));\n\t\tmem = cs->irb.PointerTypeCast(mem, type->getMutablePointerTo());\n\n\t\tcallSetFunction(type, alloc, mem, cnt);\n\n\t\t// check if we were supposed to be immutable\n\t\tif(!alloc->isMutable)\n\t\t\tmem = cs->irb.PointerTypeCast(mem, mem->getType()->getImmutablePointerVersion());\n\n\t\treturn mem;\n\t}\n\telse\n\t{\n\t\tauto ecount = counts[0];\n\n\t\tauto count = cs->oneWayAutocast(ecount->codegen(cs, fir::Type::getNativeWord()).value, fir::Type::getNativeWord());\n\t\tif(!count || !count->getType()->isIntegerType())\n\t\t\terror(ecount, \"expected integer type for length, found '%s' instead\", (count ? count->getType()->str() : \"null\"));\n\n\t\t// make sure the length isn't negative\n\t\tauto checkf = getCheckNegativeLengthFunction(cs);\n\t\ticeAssert(checkf);\n\t\tcs->irb.Call(checkf, count, fir::ConstantCharSlice::get(ecount->loc.toString()));\n\n\t\tauto arr = cs->irb.CreateValue(fir::DynamicArrayType::get(type));\n\t\tauto expandfn = cgn::glue::saa_common::generateReserveAtLeastFunction(cs, arr->getType());\n\t\ticeAssert(expandfn);\n\n\t\tarr = cs->irb.Call(expandfn, arr, count);\n\t\tarr = cs->irb.SetSAALength(arr, count);\n\n\t\tcallSetFunction(type, alloc, cs->irb.GetSAAData(arr), count);\n\t\tcs->addRefCountedValue(arr);\n\n\t\treturn arr;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\nCGResult sst::AllocOp::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tif(this->counts.size() > 1)\n\t\terror(this, \"multi-dimensional arrays are not supported yet.\");\n\n\treturn CGResult(performAllocation(cs, this, this->elmType, this->counts, this->attrs.has(attr::RAW)));\n}\n\n\n\nCGResult sst::DeallocOp::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\n\tauto freef = cs->getOrDeclareLibCFunction(FREE_MEMORY_FUNC);\n\ticeAssert(freef);\n\n\tauto value = this->expr->codegen(cs).value;\n\tauto ty = value->getType();\n\n\ticeAssert(ty->isPointerType());\n\n\tfir::Value* ptr = cs->irb.PointerTypeCast(value, fir::Type::getMutInt8Ptr());\n\n\tcs->irb.Call(freef, ptr);\n\treturn CGResult(0);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/arithmetic.cpp",
    "content": "// arithmetic.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"codegen.h\"\n#include \"gluecode.h\"\n#include \"typecheck.h\"\n\nnamespace sst\n{\n\tCGResult BinaryOp::_codegen(cgn::CodegenState* cs, fir::Type* inferred)\n\t{\n\t\ticeAssert(!Operator::isAssignment(this->op));\n\n\t\tif(this->op == Operator::TypeCast)\n\t\t{\n\t\t\tauto target = this->right->codegen(cs).value->getType();\n\t\t\tauto value = this->left->codegen(cs).value;\n\t\t\tauto vt = value->getType();\n\n\t\t\tif(vt->isConstantNumberType() && (target->isFloatingPointType() || target->isIntegerType()))\n\t\t\t{\n\t\t\t\tauto cn = dcast(fir::ConstantNumber, value);\n\t\t\t\tif(!cn) error(this->left, \"what\");\n\n\t\t\t\treturn CGResult(cs->unwrapConstantNumber(cn, target));\n\t\t\t}\n\t\t\telse if(vt->isEnumType())\n\t\t\t{\n\t\t\t\tauto res = cs->irb.AppropriateCast(cs->irb.GetEnumCaseValue(value), target);\n\n\t\t\t\tif(!res)\n\t\t\t\t{\n\t\t\t\t\terror(this, \"case type of '%s' is '%s', cannot cast to type '%s'\", vt, vt->toEnumType()->getCaseType(), target);\n\t\t\t\t}\n\n\t\t\t\treturn CGResult(res);\n\t\t\t}\n\t\t\telse if(vt->isAnyType())\n\t\t\t{\n\t\t\t\tauto fn = cgn::glue::any::generateGetValueFromAnyFunction(cs, target);\n\t\t\t\ticeAssert(fn);\n\n\t\t\t\treturn CGResult(cs->irb.Call(fn, value));\n\t\t\t}\n\t\t\telse if(vt->isUnionType() && target->isUnionVariantType())\n\t\t\t{\n\t\t\t\tif(auto parent = target->toUnionVariantType()->getParentUnion(); parent != vt)\n\t\t\t\t{\n\t\t\t\t\terror(this, \"unwrapping union of type '%s' to variant ('%s') of unrelated union '%s'\",\n\t\t\t\t\t\tvt, target->toUnionVariantType()->getName(), parent);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfir::IRBlock* invalid = cs->irb.addNewBlockInFunction(\"invalid\", cs->irb.getCurrentFunction());\n\t\t\t\t\tfir::IRBlock* merge = cs->irb.addNewBlockInFunction(\"merge\", cs->irb.getCurrentFunction());\n\n\t\t\t\t\tauto targetId = fir::ConstantInt::getNative(target->toUnionVariantType()->getVariantId());\n\t\t\t\t\tauto variantId = cs->irb.GetUnionVariantID(value);\n\n\t\t\t\t\tauto valid = cs->irb.ICmpEQ(targetId, variantId);\n\t\t\t\t\tcs->irb.CondBranch(valid, merge, invalid);\n\n\t\t\t\t\tcs->irb.setCurrentBlock(invalid);\n\t\t\t\t\t{\n\t\t\t\t\t\t// TODO: actually say what the variant was -- requires creating a runtime array of the names of the variants,\n\t\t\t\t\t\t// TODO: probably. might be easier once we have type info at runtime!\n\t\t\t\t\t\tcgn::glue::printRuntimeError(cs, fir::ConstantCharSlice::get(cs->loc().toString()),\n\t\t\t\t\t\t\t\"invalid unwrap of value of union '%s' into variant '%s'\", {\n\t\t\t\t\t\t\t\tcs->module->createGlobalString(vt->str()),\n\t\t\t\t\t\t\t\tcs->module->createGlobalString(target->toUnionVariantType()->getName())\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tcs->irb.setCurrentBlock(merge);\n\t\t\t\t\treturn CGResult(cs->irb.GetUnionVariantData(value, target->toUnionVariantType()->getVariantId()));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto res = cs->irb.AppropriateCast(value, target);\n\n\t\t\t\tif(!res)\n\t\t\t\t{\n\t\t\t\t\terror(this, \"no appropriate cast from type '%s' to '%s'\",\n\t\t\t\t\t\tvt, target);\n\t\t\t\t}\n\n\t\t\t\treturn CGResult(res);\n\t\t\t}\n\t\t}\n\t\telse if(this->op == Operator::TypeIs)\n\t\t{\n\t\t\tauto value = this->left->codegen(cs).value;\n\t\t\tauto target = this->right->codegen(cs).value->getType();\n\n\t\t\tif(value->getType()->isAnyType())\n\t\t\t{\n\t\t\t\t// get the type out.\n\t\t\t\tauto res = cs->irb.BitwiseAND(cs->irb.GetAnyTypeID(value),\n\t\t\t\t\tcs->irb.BitwiseNOT(fir::ConstantInt::getUNative(BUILTIN_ANY_FLAG_MASK)));\n\n\t\t\t\treturn CGResult(res = cs->irb.ICmpEQ(res, fir::ConstantInt::getUNative(target->getID())));\n\t\t\t}\n\t\t\telse if(value->getType()->isUnionType() && target->isUnionVariantType())\n\t\t\t{\n\t\t\t\t// it's slightly more complicated.\n\t\t\t\tauto vid1 = cs->irb.GetUnionVariantID(value);\n\t\t\t\tauto vid2 = fir::ConstantInt::getNative(target->toUnionVariantType()->getVariantId());\n\n\t\t\t\treturn CGResult(cs->irb.ICmpEQ(vid1, vid2));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto res = fir::ConstantInt::getUNative(value->getType()->getID());\n\t\t\t\treturn CGResult(cs->irb.ICmpEQ(res, fir::ConstantInt::getUNative(target->getID())));\n\t\t\t}\n\t\t}\n\n\n\t\tif(this->op == Operator::LogicalAnd || this->op == Operator::LogicalOr)\n\t\t\treturn cs->performLogicalBinaryOperation(this);\n\n\n\t\t// TODO: figure out a better way\n\t\tauto _lr = this->left->codegen(cs/*, inferred*/);\n\t\tauto _rr = this->right->codegen(cs/*, inferred*/);\n\n\t\tauto [ l, r ] = std::make_tuple(_lr.value, _rr.value);\n\t\t// auto [ lt, rt ] = std::make_tuple(l.value->getType(), r.value->getType());\n\n\n\t\tif(this->overloadedOpFunction)\n\t\t{\n\t\t\t// fantastic, just call this piece of shit.\n\t\t\tauto func = dcast(fir::Function, this->overloadedOpFunction->codegen(cs, 0).value);\n\t\t\ticeAssert(func);\n\t\t\ticeAssert(func->getArgumentCount() == 2);\n\n\t\t\tfir::Value* lv = cs->oneWayAutocast(l, func->getArguments()[0]->getType());\n\t\t\tfir::Value* rv = cs->oneWayAutocast(r, func->getArguments()[0]->getType());\n\n\t\t\tif(lv->getType() != func->getArguments()[0]->getType())\n\t\t\t{\n\t\t\t\tSpanError::make(SimpleError::make(this->left->loc,\n\t\t\t\t\t\"mismatched types for left side of overloaded binary operator '%s'; expected '%s', found '%s' instead\",\n\t\t\t\t\tthis->op, func->getArguments()[0]->getType(), lv->getType())\n\t\t\t\t)->append(SimpleError::make(MsgType::Note, this->overloadedOpFunction->loc, \"operator was overloaded here:\"))\n\t\t\t\t->postAndQuit();\n\t\t\t}\n\t\t\telse if(rv->getType() != func->getArguments()[1]->getType())\n\t\t\t{\n\t\t\t\tSpanError::make(SimpleError::make(this->right->loc,\n\t\t\t\t\t\"mismatched types for right side of overloaded binary operator '%s'; expected '%s', found '%s' instead\",\n\t\t\t\t\tthis->op, func->getArguments()[1]->getType(), rv->getType())\n\t\t\t\t)->append(SimpleError::make(MsgType::Note, this->overloadedOpFunction->loc, \"operator was overloaded here:\"))\n\t\t\t\t->postAndQuit();\n\t\t\t}\n\n\t\t\t// ok, call that guy.\n\t\t\treturn CGResult(cs->irb.Call(func, lv, rv));\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn cs->performBinaryOperation(this->loc, { this->left->loc, l }, { this->right->loc, r }, this->op);\n\t\t}\n\t}\n\n\n\n\n\n\n\tCGResult UnaryOp::_codegen(cgn::CodegenState* cs, fir::Type* inferred)\n\t{\n\t\tauto val = this->expr->codegen(cs, inferred).value;\n\t\tauto ty = val->getType();\n\n\n\t\tif(this->overloadedOpFunction)\n\t\t{\n\t\t\t// fantastic, just call this piece of shit.\n\t\t\tauto func = dcast(fir::Function, this->overloadedOpFunction->codegen(cs, 0).value);\n\t\t\ticeAssert(func);\n\t\t\ticeAssert(func->getArgumentCount() == 1);\n\n\t\t\tval = cs->oneWayAutocast(val, func->getArguments()[0]->getType());\n\n\t\t\tif(val->getType() != func->getArguments()[0]->getType())\n\t\t\t{\n\t\t\t\tSpanError::make(SimpleError::make(this->expr->loc, \"mismatched types for overloaded unary operator '%s'; \"\n\t\t\t\t\t\"expected '%s', found '%s' instead\", this->op, func->getArguments()[0]->getType(), val->getType()))\n\t\t\t\t\t->append(SimpleError::make(MsgType::Note, this->overloadedOpFunction->loc, \"operator was overloaded here:\"))\n\t\t\t\t\t->postAndQuit();\n\t\t\t}\n\n\t\t\t// ok, call that guy.\n\t\t\treturn CGResult(cs->irb.Call(func, val));\n\t\t}\n\n\n\t\tif(this->op == Operator::LogicalNot)\n\t\t{\n\t\t\ticeAssert(ty->isBoolType());\n\t\t\tif(auto c = dcast(fir::ConstantInt, val))\n\t\t\t{\n\t\t\t\tbool b = c->getSignedValue();\n\t\t\t\treturn CGResult(fir::ConstantBool::get(!b));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn CGResult(cs->irb.LogicalNot(val));\n\t\t\t}\n\t\t}\n\t\telse if(this->op == Operator::UnaryPlus)\n\t\t{\n\t\t\treturn CGResult(val);\n\t\t}\n\t\telse if(this->op == Operator::UnaryMinus)\n\t\t{\n\t\t\tif(auto ci = dcast(fir::ConstantInt, val))\n\t\t\t{\n\t\t\t\ticeAssert(ci->getType()->isSignedIntType());\n\t\t\t\treturn CGResult(fir::ConstantInt::get(ci->getType(), -1 * ci->getSignedValue()));\n\t\t\t}\n\t\t\telse if(auto cf = dcast(fir::ConstantFP, val))\n\t\t\t{\n\t\t\t\treturn CGResult(fir::ConstantFP::get(cf->getType(), -1 * cf->getValue()));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn CGResult(cs->irb.Negate(val));\n\t\t\t}\n\t\t}\n\t\telse if(this->op == Operator::PointerDeref)\n\t\t{\n\t\t\ticeAssert(ty->isPointerType());\n\t\t\treturn CGResult(cs->irb.Dereference(val));\n\t\t}\n\t\telse if(this->op == Operator::AddressOf)\n\t\t{\n\t\t\tif(!val->islvalue())\n\t\t\t\terror(this, \"cannot take address of a non-lvalue\");\n\n\t\t\telse if(val->getType()->isFunctionType())\n\t\t\t\terror(this, \"cannot take the address of a function; use it as a value type\");\n\n\t\t\treturn CGResult(cs->irb.AddressOf(val, false));\n\t\t}\n\t\telse if(this->op == Operator::BitwiseNot)\n\t\t{\n\t\t\ticeAssert(ty->isIntegerType() && !ty->isSignedIntType());\n\t\t\tif(auto ci = dcast(fir::ConstantInt, val))\n\t\t\t{\n\t\t\t\treturn CGResult(fir::ConstantInt::get(ci->getType(), ~(ci->getUnsignedValue())));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn CGResult(cs->irb.BitwiseNOT(val));\n\t\t\t}\n\t\t}\n\n\t\terror(this, \"not a unary op\");\n\t}\n}\n\n\n\nnamespace cgn\n{\n\tCGResult CodegenState::performBinaryOperation(const Location& loc, std::pair<Location, fir::Value*> lhs,\n\t\tstd::pair<Location, fir::Value*> rhs, std::string op)\n\t{\n\t\tauto unsupportedError = [loc, op](const Location& al, fir::Type* a, const Location& bl, fir::Type* b) {\n\n\t\t\tSpanError::make(SimpleError::make(loc, \"unsupported operator '%s' between types '%s' and '%s'\", op, a, b))\n\t\t\t\t->add(util::ESpan(al, strprintf(\"type '%s'\", a)))\n\t\t\t\t->add(util::ESpan(bl, strprintf(\"type '%s'\", b)))\n\t\t\t\t->postAndQuit();\n\t\t};\n\n\t\tauto l = lhs.second;\n\t\tauto r = rhs.second;\n\n\t\tauto lt = l->getType();\n\t\tauto rt = r->getType();\n\n\t\tauto lv = l;\n\t\tauto rv = r;\n\n\t\tif(Operator::isComparison(op))\n\t\t{\n\t\t\tauto [ lr, rr ] = this->autoCastValueTypes(l, r);\n\t\t\tif(!lr || !rr)\n\t\t\t\tunsupportedError(lhs.first, lt, rhs.first, rt);\n\n\t\t\ticeAssert(lr && rr);\n\n\t\t\tauto [ lt, rt ] = std::make_pair(lr->getType(), rr->getType());\n\n\t\t\t// do comparison\n\t\t\tif((lt->isIntegerType() && rt->isIntegerType()) || (lt->isPointerType() && rt->isPointerType()))\n\t\t\t{\n\t\t\t\t// we should cast these to be similar-ish.\n\n\t\t\t\tif(op == Operator::CompareEQ)   return CGResult(this->irb.ICmpEQ(lr, rr));\n\t\t\t\tif(op == Operator::CompareNEQ)  return CGResult(this->irb.ICmpNEQ(lr, rr));\n\t\t\t\tif(op == Operator::CompareLT)   return CGResult(this->irb.ICmpLT(lr, rr));\n\t\t\t\tif(op == Operator::CompareLEQ)  return CGResult(this->irb.ICmpLEQ(lr, rr));\n\t\t\t\tif(op == Operator::CompareGT)   return CGResult(this->irb.ICmpGT(lr, rr));\n\t\t\t\tif(op == Operator::CompareGEQ)  return CGResult(this->irb.ICmpGEQ(lr, rr));\n\n\t\t\t\terror(\"no\");\n\t\t\t}\n\t\t\telse if(lt->isFloatingPointType() && rt->isFloatingPointType())\n\t\t\t{\n\t\t\t\tif(op == Operator::CompareEQ)   return CGResult(this->irb.FCmpEQ_ORD(lr, rr));\n\t\t\t\tif(op == Operator::CompareNEQ)  return CGResult(this->irb.FCmpNEQ_ORD(lr, rr));\n\t\t\t\tif(op == Operator::CompareLT)   return CGResult(this->irb.FCmpLT_ORD(lr, rr));\n\t\t\t\tif(op == Operator::CompareLEQ)  return CGResult(this->irb.FCmpLEQ_ORD(lr, rr));\n\t\t\t\tif(op == Operator::CompareGT)   return CGResult(this->irb.FCmpGT_ORD(lr, rr));\n\t\t\t\tif(op == Operator::CompareGEQ)  return CGResult(this->irb.FCmpGEQ_ORD(lr, rr));\n\n\t\t\t\terror(\"no\");\n\t\t\t}\n\t\t\telse if((lt->isPrimitiveType() && rt->isConstantNumberType()) || (lt->isConstantNumberType() && rt->isPrimitiveType()))\n\t\t\t{\n\t\t\t\tif(lr->getType()->isFloatingPointType())\n\t\t\t\t{\n\t\t\t\t\tif(op == Operator::CompareEQ)   return CGResult(this->irb.FCmpEQ_ORD(lr, rr));\n\t\t\t\t\tif(op == Operator::CompareNEQ)  return CGResult(this->irb.FCmpNEQ_ORD(lr, rr));\n\t\t\t\t\tif(op == Operator::CompareLT)   return CGResult(this->irb.FCmpLT_ORD(lr, rr));\n\t\t\t\t\tif(op == Operator::CompareLEQ)  return CGResult(this->irb.FCmpLEQ_ORD(lr, rr));\n\t\t\t\t\tif(op == Operator::CompareGT)   return CGResult(this->irb.FCmpGT_ORD(lr, rr));\n\t\t\t\t\tif(op == Operator::CompareGEQ)  return CGResult(this->irb.FCmpGEQ_ORD(lr, rr));\n\n\t\t\t\t\terror(\"no\");\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif(op == Operator::CompareEQ)   return CGResult(this->irb.ICmpEQ(lr, rr));\n\t\t\t\t\tif(op == Operator::CompareNEQ)  return CGResult(this->irb.ICmpNEQ(lr, rr));\n\t\t\t\t\tif(op == Operator::CompareLT)   return CGResult(this->irb.ICmpLT(lr, rr));\n\t\t\t\t\tif(op == Operator::CompareLEQ)  return CGResult(this->irb.ICmpLEQ(lr, rr));\n\t\t\t\t\tif(op == Operator::CompareGT)   return CGResult(this->irb.ICmpGT(lr, rr));\n\t\t\t\t\tif(op == Operator::CompareGEQ)  return CGResult(this->irb.ICmpGEQ(lr, rr));\n\n\t\t\t\t\terror(\"no\");\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(lt->isStringType() && rt->isStringType())\n\t\t\t{\n\t\t\t\tauto cmpfn = cgn::glue::string::getCompareFunction(this);\n\t\t\t\tfir::Value* res = this->irb.Call(cmpfn, lv, rv);\n\n\t\t\t\tfir::Value* zero = fir::ConstantInt::getNative(0);\n\n\t\t\t\tif(op == Operator::CompareEQ)   return CGResult(this->irb.ICmpEQ(res, zero));\n\t\t\t\tif(op == Operator::CompareNEQ)  return CGResult(this->irb.ICmpNEQ(res, zero));\n\t\t\t\tif(op == Operator::CompareLT)   return CGResult(this->irb.ICmpLT(res, zero));\n\t\t\t\tif(op == Operator::CompareLEQ)  return CGResult(this->irb.ICmpLEQ(res, zero));\n\t\t\t\tif(op == Operator::CompareGT)   return CGResult(this->irb.ICmpGT(res, zero));\n\t\t\t\tif(op == Operator::CompareGEQ)  return CGResult(this->irb.ICmpGEQ(res, zero));\n\n\t\t\t\terror(\"no\");\n\t\t\t}\n\t\t\telse if(lt->isEnumType() && lt == rt)\n\t\t\t{\n\t\t\t\tauto li = this->irb.GetEnumCaseIndex(lv);\n\t\t\t\tauto ri = this->irb.GetEnumCaseIndex(rv);\n\n\t\t\t\tif(op == Operator::CompareEQ)   return CGResult(this->irb.ICmpEQ(li, ri));\n\t\t\t\tif(op == Operator::CompareNEQ)  return CGResult(this->irb.ICmpNEQ(li, ri));\n\t\t\t\tif(op == Operator::CompareLT)   return CGResult(this->irb.ICmpLT(li, ri));\n\t\t\t\tif(op == Operator::CompareLEQ)  return CGResult(this->irb.ICmpLEQ(li, ri));\n\t\t\t\tif(op == Operator::CompareGT)   return CGResult(this->irb.ICmpGT(li, ri));\n\t\t\t\tif(op == Operator::CompareGEQ)  return CGResult(this->irb.ICmpGEQ(li, ri));\n\n\t\t\t\terror(\"no\");\n\t\t\t}\n\t\t\telse if((lt->isDynamicArrayType() || lt->isArraySliceType()) && lt == rt)\n\t\t\t{\n\t\t\t\t//! use opf when we have operator overloads\n\t\t\t\tauto cmpfn = cgn::glue::array::getCompareFunction(this, lt, 0);\n\t\t\t\tfir::Value* res = this->irb.Call(cmpfn, lv, rv);\n\n\t\t\t\tfir::Value* zero = fir::ConstantInt::getNative(0);\n\n\t\t\t\tif(op == Operator::CompareEQ)   return CGResult(this->irb.ICmpEQ(res, zero));\n\t\t\t\tif(op == Operator::CompareNEQ)  return CGResult(this->irb.ICmpNEQ(res, zero));\n\t\t\t\tif(op == Operator::CompareLT)   return CGResult(this->irb.ICmpLT(res, zero));\n\t\t\t\tif(op == Operator::CompareLEQ)  return CGResult(this->irb.ICmpLEQ(res, zero));\n\t\t\t\tif(op == Operator::CompareGT)   return CGResult(this->irb.ICmpGT(res, zero));\n\t\t\t\tif(op == Operator::CompareGEQ)  return CGResult(this->irb.ICmpGEQ(res, zero));\n\n\t\t\t\terror(\"no\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\terror(\"unsupported comparison between types '%s' and '%s'\", lt, rt);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif((lt->isPrimitiveType() || lt->isConstantNumberType()) && (rt->isPrimitiveType() || rt->isConstantNumberType()))\n\t\t\t{\n\t\t\t\tauto [ lr, rr ] = this->autoCastValueTypes(l, r);\n\n\t\t\t\treturn CGResult(this->irb.BinaryOp(op, lr, rr));\n\t\t\t}\n\t\t\telse if((lt->isPointerType() && (rt->isIntegerType() || rt->isConstantNumberType()))\n\t\t\t\t|| ((lt->isIntegerType() || lt->isConstantNumberType()) && rt->isPointerType()))\n\t\t\t{\n\t\t\t\tauto ofsv = (lt->isPointerType() ? rv : lv);\n\t\t\t\tauto ofs = this->oneWayAutocast(ofsv, fir::Type::getNativeWord());\n\n\t\t\t\ticeAssert(ofs->getType()->isIntegerType());\n\n\t\t\t\tauto ptr = (lt->isPointerType() ? lv : rv);\n\t\t\t\tptr = this->irb.GetPointer(ptr, ofs);\n\n\t\t\t\treturn CGResult(ptr);\n\t\t\t}\n\t\t\telse if(lt->isStringType() && rt->isStringType())\n\t\t\t{\n\t\t\t\tif(op != Operator::Plus)\n\t\t\t\t\tunsupportedError(lhs.first, lt, rhs.first, rt);\n\n\t\t\t\t#if 0\n\t\t\t\t// ok.\n\t\t\t\t// if we're both string literals, then fuck it, do it compile-time\n\t\t\t\tif(dcast(fir::ConstantCharSlice, lv) && dcast(fir::ConstantCharSlice, rv))\n\t\t\t\t{\n\t\t\t\t\tstd::string cls = dcast(fir::ConstantCharSlice, lv)->getValue();\n\t\t\t\t\tstd::string crs = dcast(fir::ConstantCharSlice, rv)->getValue();\n\n\t\t\t\t\tinfo(loc, \"const strings\");\n\t\t\t\t\treturn CGResult(fir::ConstantCharSlice::get(cls + crs));\n\t\t\t\t}\n\t\t\t\t#endif\n\n\n\t\t\t\tauto appfn = cgn::glue::string::getConstructFromTwoFunction(this);\n\t\t\t\tauto res = this->irb.Call(appfn, this->irb.CreateSliceFromSAA(lv, false), this->irb.CreateSliceFromSAA(rv, false));\n\t\t\t\tthis->addRefCountedValue(res);\n\n\t\t\t\treturn CGResult(res);\n\t\t\t}\n\t\t\telse if((lt->isStringType() && rt->isCharSliceType()) || (lt->isCharSliceType() && rt->isStringType()))\n\t\t\t{\n\t\t\t\tif(op != Operator::Plus)\n\t\t\t\t\tunsupportedError(lhs.first, lt, rhs.first, rt);\n\n\t\t\t\t// make life easier\n\t\t\t\tif(lt->isCharSliceType())\n\t\t\t\t{\n\t\t\t\t\tstd::swap(lt, rt);\n\t\t\t\t\tstd::swap(lv, rv);\n\t\t\t\t}\n\n\t\t\t\tauto appfn = cgn::glue::string::getConstructFromTwoFunction(this);\n\t\t\t\tauto res = this->irb.Call(appfn, this->irb.CreateSliceFromSAA(lv, false), rv);\n\t\t\t\tthis->addRefCountedValue(res);\n\n\t\t\t\treturn CGResult(res);\n\t\t\t}\n\t\t\telse if((lt->isStringType() && rt->isCharType()) || (lt->isCharType() && rt->isStringType()))\n\t\t\t{\n\t\t\t\tif(op != Operator::Plus)\n\t\t\t\t\tunsupportedError(lhs.first, lt, rhs.first, rt);\n\n\t\t\t\t// make life easier\n\t\t\t\tif(lt->isCharType())\n\t\t\t\t{\n\t\t\t\t\tstd::swap(lt, rt);\n\t\t\t\t\tstd::swap(lv, rv);\n\t\t\t\t}\n\n\n\t\t\t\t#if 0\n\t\t\t\tif(dcast(fir::ConstantCharSlice, lv) && dcast(fir::ConstantChar, rv))\n\t\t\t\t{\n\t\t\t\t\tstd::string cls = dcast(fir::ConstantCharSlice, lv)->getValue();\n\t\t\t\t\tchar crs = dcast(fir::ConstantChar, rv)->getValue();\n\n\t\t\t\t\tinfo(loc, \"const strings\");\n\t\t\t\t\treturn CGResult(fir::ConstantCharSlice::get(cls + crs));\n\t\t\t\t}\n\t\t\t\t#endif\n\n\n\t\t\t\tauto appfn = cgn::glue::string::getConstructWithCharFunction(this);\n\t\t\t\tauto res = this->irb.Call(appfn, this->irb.CreateSliceFromSAA(lv, true), rv);\n\t\t\t\tthis->addRefCountedValue(res);\n\n\t\t\t\treturn CGResult(res);\n\t\t\t}\n\t\t\telse if(lt->isDynamicArrayType() && rt->isDynamicArrayType() && lt->getArrayElementType() == rt->getArrayElementType())\n\t\t\t{\n\t\t\t\t// check what we're doing\n\t\t\t\tif(op != Operator::Plus)\n\t\t\t\t\tunsupportedError(lhs.first, lt, rhs.first, rt);\n\n\t\t\t\t// ok, do the append\n\t\t\t\tauto maketwof = cgn::glue::array::getConstructFromTwoFunction(this, lt->toDynamicArrayType());\n\n\t\t\t\tfir::Value* res = this->irb.Call(maketwof, this->irb.CreateSliceFromSAA(lv, false),\n\t\t\t\t\tthis->irb.CreateSliceFromSAA(rv, false));\n\n\t\t\t\tthis->addRefCountedValue(res);\n\n\t\t\t\treturn CGResult(res);\n\n\t\t\t\t// error(loc, \"i'm gonna stop you right here\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tunsupportedError(lhs.first, lt, rhs.first, rt);\n\t\t\t\tdoTheExit();\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/assign.cpp",
    "content": "// assign.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"codegen.h\"\n#include \"gluecode.h\"\n\nsst::AssignOp::AssignOp(const Location& l) : Expr(l, fir::Type::getVoid()) { this->readableName = \"assignment statement\"; }\nsst::TupleAssignOp::TupleAssignOp(const Location& l) : Expr(l, fir::Type::getVoid()) { this->readableName = \"destructuring assignment statement\"; }\n\n\nCGResult sst::AssignOp::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tauto lr = this->left->codegen(cs).value;\n\tauto lt = lr->getType();\n\n\tif(!lr->islvalue())\n\t{\n\t\tSpanError::make(SimpleError::make(this->loc, \"cannot assign to non-lvalue (most likely a temporary) expression\"))\n\t\t\t->add(util::ESpan(this->left->loc, \"here\"))\n\t\t\t->postAndQuit();\n\t}\n\telse if(lr->isConst())\n\t{\n\t\tSpanError::make(SimpleError::make(this->loc, \"cannot assign to immutable expression\"))\n\t\t\t->add(util::ESpan(this->left->loc, \"here\"))\n\t\t\t->postAndQuit();\n\t}\n\n\n\t// okay, i guess\n\tauto rr = this->right->codegen(cs, lt).value;\n\tauto rt = rr->getType();\n\n\tif(this->op != Operator::Assign)\n\t{\n\t\t// ok it's a compound assignment\n\t\t// auto [ newl, newr ] = cs->autoCastValueTypes(lr, rr);\n\t\tauto nonass = Operator::getNonAssignmentVersion(this->op);\n\n\t\t// some things -- if we're doing +=, and the types are supported, then just call the actual\n\t\t// append function, instead of doing the + first then assigning it.\n\n\t\tif(nonass == Operator::Plus)\n\t\t{\n\t\t\tif(lt->isDynamicArrayType() && lt == rt)\n\t\t\t{\n\t\t\t\t// right then.\n\t\t\t\tif(!lr->islvalue())\n\t\t\t\t\terror(this, \"cannot append to an r-value array\");\n\n\t\t\t\tauto appendf = cgn::glue::array::getAppendFunction(cs, lt->toDynamicArrayType());\n\n\t\t\t\t//? are there any ramifications for these actions for ref-counted things?\n\t\t\t\tauto res = cs->irb.Call(appendf, lr, cs->irb.CreateSliceFromSAA(rr, false));\n\n\t\t\t\tcs->irb.Store(res, lr);\n\t\t\t\treturn CGResult(0);\n\t\t\t}\n\t\t\telse if(lt->isDynamicArrayType() && lt->getArrayElementType() == rt)\n\t\t\t{\n\t\t\t\t// right then.\n\t\t\t\tif(!lr->islvalue())\n\t\t\t\t\terror(this, \"cannot append to an r-value array\");\n\n\t\t\t\tauto appendf = cgn::glue::array::getElementAppendFunction(cs, lt->toDynamicArrayType());\n\n\t\t\t\t//? are there any ramifications for these actions for ref-counted things?\n\t\t\t\tauto res = cs->irb.Call(appendf, lr, rr);\n\n\t\t\t\tcs->irb.Store(res, lr);\n\t\t\t\treturn CGResult(0);\n\t\t\t}\n\t\t\telse if(lt->isStringType() && lt == rt)\n\t\t\t{\n\t\t\t\t// right then.\n\t\t\t\tif(!lr->islvalue())\n\t\t\t\t\terror(this, \"cannot append to an r-value array\");\n\n\t\t\t\tauto appendf = cgn::glue::string::getAppendFunction(cs);\n\n\t\t\t\t//? are there any ramifications for these actions for ref-counted things?\n\t\t\t\tauto res = cs->irb.Call(appendf, lr, cs->irb.CreateSliceFromSAA(rr, true));\n\n\t\t\t\tcs->irb.Store(res, lr);\n\t\t\t\treturn CGResult(0);\n\t\t\t}\n\t\t\telse if(lt->isStringType() && rt->isCharType())\n\t\t\t{\n\t\t\t\t// right then.\n\t\t\t\tif(!lr->islvalue())\n\t\t\t\t\terror(this, \"cannot append to an r-value string\");\n\n\t\t\t\tauto appendf = cgn::glue::string::getCharAppendFunction(cs);\n\n\t\t\t\t//? are there any ramifications for these actions for ref-counted things?\n\t\t\t\tauto res = cs->irb.Call(appendf, lr, rr);\n\n\t\t\t\tcs->irb.Store(res, lr);\n\t\t\t\treturn CGResult(0);\n\t\t\t}\n\t\t}\n\n\n\t\t// do the op first\n\t\tauto res = cs->performBinaryOperation(this->loc, { this->left->loc, lr }, { this->right->loc, rr }, nonass);\n\n\t\t// assign the res to the thing\n\t\trr = res.value;\n\t}\n\n\trr = cs->oneWayAutocast(rr, lt);\n\n\tif(rr == 0)\n\t\terror(this, \"invalid assignment from value of type '%s' to expected type '%s'\", rt, lt);\n\n\t// ok then\n\tif(lt != rr->getType())\n\t\terror(this, \"what? left = %s, right = %s\", lt, rr->getType());\n\n\tcs->autoAssignRefCountedValue(lr, rr, /* isInitial: */ false);\n\treturn CGResult(0);\n}\n\n\n\n\n\nCGResult sst::TupleAssignOp::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tauto tuple = this->right->codegen(cs).value;\n\tif(!tuple->getType()->isTupleType())\n\t\terror(this->right, \"expected tuple type in assignment to tuple on left-hand-side; found type '%s' instead\", tuple->getType());\n\n\tauto tty = tuple->getType()->toTupleType();\n\n\tstd::vector<CGResult> results;\n\n\tsize_t idx = 0;\n\tfor(auto v : this->lefts)\n\t{\n\t\tauto res = v->codegen(cs, tty->getElementN(idx));\n\t\tif(!res->islvalue())\n\t\t\terror(v, \"cannot assign to non-lvalue expression in tuple assignment\");\n\n\t\tif(res->isConst())\n\t\t\terror(v, \"cannot assign to constant in tuple assignment\");\n\n\t\tresults.push_back(res);\n\t\tidx++;\n\t}\n\n\tfor(size_t i = 0; i < idx; i++)\n\t{\n\t\tauto lr = results[i];\n\t\tauto val = cs->irb.ExtractValue(tuple, { i });\n\n\t\tauto rr = cs->oneWayAutocast(val, lr.value->getType());\n\t\tif(!rr || rr->getType() != lr.value->getType())\n\t\t{\n\t\t\terror(this->right, \"mismatched types in assignment to tuple element %d; assigning type '%s' to '%s'\",\n\t\t\t\tval->getType(), lr.value->getType());\n\t\t}\n\n\t\tcs->autoAssignRefCountedValue(lr.value, rr, /* isInitial: */ false);\n\t}\n\n\treturn CGResult(0);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/autocasting.cpp",
    "content": "// autocasting.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"errors.h\"\n#include \"codegen.h\"\n#include \"gluecode.h\"\n#include \"typecheck.h\"\n\nnamespace cgn\n{\n\tfir::ConstantValue* CodegenState::unwrapConstantNumber(fir::ConstantValue* cv)\n\t{\n\t\ticeAssert(cv->getType()->isConstantNumberType());\n\t\tauto cn = dcast(fir::ConstantNumber, cv);\n\t\ticeAssert(cn);\n\n\t\tauto ty = cv->getType()->toConstantNumberType();\n\t\ticeAssert(ty);\n\n\t\tif(ty->isFloating())\n\t\t{\n\t\t\tif(ty->getMinBits() <= fir::Type::getFloat64()->getBitWidth())\n\t\t\t\treturn fir::ConstantFP::getFloat64(cn->getDouble());\n\n\t\t\telse\n\t\t\t\terror(\"float overflow\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif(ty->getMinBits() < fir::Type::getNativeWord()->getBitWidth() - 1)\n\t\t\t\treturn fir::ConstantInt::getNative(cn->getInt64());\n\n\t\t\telse if(!ty->isSigned() && ty->getMinBits() <= fir::Type::getNativeUWord()->getBitWidth())\n\t\t\t\treturn fir::ConstantInt::getUNative(cn->getUint64());\n\n\t\t\telse\n\t\t\t\terror(\"int overflow\");\n\t\t}\n\t}\n\n\n\tstatic fir::ConstantValue* _unwrapConstantNumber(CodegenState* cs, fir::ConstantNumber* num, fir::Type* target, bool isAutocast)\n\t{\n\t\tif(!(target->isIntegerType() || target->isFloatingPointType()))\n\t\t\terror(cs->loc(), \"unable to cast number literal to inferred type '%s'\", target);\n\n\t\tauto ty = num->getType()->toConstantNumberType();\n\n\t\tbool signConvert = false;\n\t\tif(ty->isFloating() && target->isIntegerType())\n\t\t{\n\t\t\tif(isAutocast) return 0;\n\t\t\twarn(cs->loc(), \"casting floating-point literal to integer type '%s' will cause a truncation\", target);\n\t\t}\n\t\telse if(target->isIntegerType() && !target->isSignedIntType() && ty->isSigned())\n\t\t{\n\t\t\tif(isAutocast) return 0;\n\t\t\twarn(cs->loc(), \"casting negative literal to an unsigned integer type '%s'\", target);\n\t\t\tsignConvert = true;\n\t\t}\n\n\n\t\tif(target->toPrimitiveType()->getBitWidth() < ty->getMinBits())\n\t\t{\n\t\t\t// TODO: actually do what we say.\n\t\t\twarn(cs->loc(), \"casting literal to type '%s' will cause an overflow; value will be truncated bitwise to fit\",\n\t\t\t\ttarget);\n\t\t}\n\n\t\tif(signConvert)\n\t\t{\n\t\t\t// eg. ((size_t) -1) gives SIZET_MAX, basically.\n\t\t\t// so what we do, is we get the max of the target type,\n\t\t\t// then subtract (num - 1)\n\n\t\t\tif(target == fir::Type::getUint8())\n\t\t\t\treturn fir::ConstantInt::get(target, num->getUint8());\n\n\t\t\telse if(target == fir::Type::getUint16())\n\t\t\t\treturn fir::ConstantInt::get(target, num->getUint16());\n\n\t\t\telse if(target == fir::Type::getUint32())\n\t\t\t\treturn fir::ConstantInt::get(target, num->getUint32());\n\n\t\t\telse if(target == fir::Type::getUint64())\n\t\t\t\treturn fir::ConstantInt::get(target, num->getUint64());\n\n\t\t\telse\n\t\t\t\terror(\"what %s\", target);\n\t\t}\n\n\t\tif(target == fir::Type::getFloat32())\t\treturn fir::ConstantFP::getFloat32(num->getFloat());\n\t\telse if(target == fir::Type::getFloat64())\treturn fir::ConstantFP::getFloat64(num->getDouble());\n\t\telse if(target == fir::Type::getInt8())\t\treturn fir::ConstantInt::get(target, num->getInt8());\n\t\telse if(target == fir::Type::getInt16())\treturn fir::ConstantInt::get(target, num->getInt16());\n\t\telse if(target == fir::Type::getInt32())\treturn fir::ConstantInt::get(target, num->getInt32());\n\t\telse if(target == fir::Type::getInt64())\treturn fir::ConstantInt::get(target, num->getInt64());\n\t\telse if(target == fir::Type::getUint8())\treturn fir::ConstantInt::get(target, num->getUint8());\n\t\telse if(target == fir::Type::getUint16())\treturn fir::ConstantInt::get(target, num->getUint16());\n\t\telse if(target == fir::Type::getUint32())\treturn fir::ConstantInt::get(target, num->getUint32());\n\t\telse if(target == fir::Type::getUint64())\treturn fir::ConstantInt::get(target, num->getUint64());\n\n\t\telse if(target == fir::Type::getNativeWord())   return fir::ConstantInt::get(target, num->getInt64());\n\t\telse if(target == fir::Type::getNativeUWord())  return fir::ConstantInt::get(target, num->getUint64());\n\t\telse\t\t\t\t\t\t\t\t\t\t    error(\"unsupported type '%s'\", target);\n\t}\n\n\n\n\tfir::ConstantValue* CodegenState::unwrapConstantNumber(fir::ConstantNumber* cv, fir::Type* target)\n\t{\n\t\tif(target)  return _unwrapConstantNumber(this, cv, target, false);\n\t\telse        return this->unwrapConstantNumber(cv);\n\t}\n\n\n\n\n\n\n\n\t// TODO: maybe merge/refactor this and the two-way autocast into one function,\n\t// there's a bunch of duplication here\n\tfir::Value* CodegenState::oneWayAutocast(fir::Value* from, fir::Type* target)\n\t{\n\t\tif(!from) return 0;\n\n\t\tauto fromType = from->getType();\n\t\tif(fromType == target) return from;\n\n\t\tfir::Value* result = 0;\n\n\t\tif(fromType->isNullType() && target->isPointerType())\n\t\t{\n\t\t\tresult = this->irb.PointerTypeCast(from, target);\n\t\t}\n\t\telse if(fromType->isIntegerType() && target->isIntegerType() && fromType->isSignedIntType() == target->isSignedIntType()\n\t\t\t&& target->getBitWidth() >= fromType->getBitWidth())\n\t\t{\n\t\t\tresult = this->irb.IntSizeCast(from, target);\n\t\t}\n\t\telse if(fromType->isPointerType() && target->isBoolType())\n\t\t{\n\t\t\t//* support implicit casting for null checks\n\t\t\tresult = this->irb.ICmpNEQ(from, fir::ConstantValue::getZeroValue(fromType));\n\t\t}\n\t\telse if(fromType->isFloatingPointType() && target->isFloatingPointType() && target->getBitWidth() >= fromType->getBitWidth())\n\t\t{\n\t\t\tresult = this->irb.FExtend(from, target);\n\t\t}\n\t\telse if(fromType->isCharSliceType() && target == fir::Type::getInt8Ptr())\n\t\t{\n\t\t\tresult = this->irb.GetArraySliceData(from);\n\t\t}\n\t\telse if(fromType->isStringType() && target == fir::Type::getInt8Ptr())\n\t\t{\n\t\t\tresult = this->irb.PointerTypeCast(this->irb.GetSAAData(from), fir::Type::getInt8Ptr());\n\t\t}\n\t\telse if(fromType->isStringType() && target->isCharSliceType())\n\t\t{\n\t\t\tauto ret = this->irb.CreateValue(target);\n\t\t\tret = this->irb.SetArraySliceData(ret, this->irb.GetSAAData(from));\n\t\t\tret = this->irb.SetArraySliceLength(ret, this->irb.GetSAALength(from));\n\n\t\t\tresult = ret;\n\t\t}\n\t\telse if(fromType->isDynamicArrayType() && target->isArraySliceType() && target->getArrayElementType() == fromType->getArrayElementType())\n\t\t{\n\t\t\t// ok, then\n\t\t\tauto ret = this->irb.CreateValue(fir::ArraySliceType::get(fromType->getArrayElementType(), target->toArraySliceType()->isMutable()));\n\t\t\tret = this->irb.SetArraySliceData(ret, this->irb.GetSAAData(from));\n\t\t\tret = this->irb.SetArraySliceLength(ret, this->irb.GetSAALength(from));\n\n\t\t\tresult = ret;\n\t\t}\n\t\telse if(fromType->isPointerType() && target->isPointerType() && fromType->getPointerElementType()->isClassType()\n\t\t\t&& fromType->getPointerElementType()->toClassType()->hasParent(target->getPointerElementType()))\n\t\t{\n\t\t\tauto ret = this->irb.PointerTypeCast(from, target);\n\t\t\tresult = ret;\n\t\t}\n\t\telse if(fromType->isPointerType() && target->isPointerType() && fromType->getPointerElementType() == target->getPointerElementType()\n\t\t\t&& fromType->isMutablePointer() && target->isImmutablePointer())\n\t\t{\n\t\t\tauto ret = this->irb.PointerTypeCast(from, target);\n\t\t\tresult = ret;\n\t\t}\n\t\telse if(fromType->isArraySliceType() && target->isVariadicArrayType() && (fromType->getArrayElementType() == target->getArrayElementType()))\n\t\t{\n\t\t\t//* note: we can cheat, since at the llvm level there's no mutability distinction.\n\t\t\tauto ret = this->irb.Bitcast(from, target);\n\t\t\tresult = ret;\n\t\t}\n\t\telse if(fromType->isArraySliceType() && target->isArraySliceType() && (fromType->getArrayElementType() == target->getArrayElementType())\n\t\t\t&& fromType->toArraySliceType()->isMutable() && !target->toArraySliceType()->isMutable())\n\t\t{\n\t\t\t//* note: same cheat here.\n\t\t\tauto ret = this->irb.Bitcast(from, target);\n\t\t\tresult = ret;\n\t\t}\n\t\telse if(fromType->isTupleType() && target->isTupleType() && fromType->toTupleType()->getElementCount() == target->toTupleType()->getElementCount())\n\t\t{\n\t\t\t// auto ftt = fromType->toTupleType();\n\t\t\tauto ttt = target->toTupleType();\n\n\t\t\tauto tuple = this->irb.CreateValue(target);\n\n\t\t\tbool failed = false;\n\t\t\tfor(size_t i = 0; i < ttt->getElementCount(); i++)\n\t\t\t{\n\t\t\t\tauto res = this->oneWayAutocast(this->irb.ExtractValue(from, { i }), ttt->getElementN(i));\n\t\t\t\tif(res == 0)\n\t\t\t\t{\n\t\t\t\t\tfailed = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\ttuple = this->irb.InsertValue(tuple, { i }, res);\n\t\t\t}\n\n\t\t\tif(!failed)\n\t\t\t\tresult = tuple;\n\t\t}\n\t\telse if(target->isAnyType())\n\t\t{\n\t\t\t// great.\n\t\t\tauto fn = glue::any::generateCreateAnyWithValueFunction(this, from->getType());\n\t\t\ticeAssert(fn);\n\n\t\t\tresult = this->irb.Call(fn, from);\n\t\t}\n\n\n\t\tif(!result)\n\t\t{\n\t\t\terror(this->loc(), \"unsupported autocast of '%s' -> '%s'\", fromType, target);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif(fir::isRefCountedType(result->getType()))\n\t\t\t\tthis->addRefCountedValue(result);\n\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tstd::pair<fir::Value*, fir::Value*> CodegenState::autoCastValueTypes(fir::Value* lhs, fir::Value* rhs)\n\t{\n\t\tauto lt = lhs->getType();\n\t\tauto rt = rhs->getType();\n\t\tif(lt == rt)\n\t\t{\n\t\t\t// if(lt->isConstantNumberType())\n\t\t\t// {\n\t\t\t// \t// well. do the sensible default, i guess.\n\t\t\t// \ticeAssert(rt->isConstantNumberType());\n\n\t\t\t// \tauto cnt = fir::unifyConstantTypes(lt->toConstantNumberType(), rt->toConstantNumberType());\n\t\t\t// \tif(cnt->isFloating())\n\t\t\t// \t\treturn { this->irb.AppropriateCast(lhs, cnt), this->irb.AppropriateCast(rhs, cnt) };\n\t\t\t// }\n\n\t\t\treturn { lhs, rhs };\n\t\t}\n\n\t\t// prefer to cast the void pointer to the other one, not the other way around.\n\t\tif(lt->isNullType() && rt->isPointerType())\n\t\t\treturn std::make_pair(this->irb.PointerTypeCast(lhs, rt), rhs);\n\n\t\telse if(lt->isPointerType() && rt->isNullType())\n\t\t\treturn std::make_pair(lhs, this->irb.PointerTypeCast(rhs, lt));\n\n\n\t\t/* if(lt->isConstantNumberType() && !rt->isConstantNumberType())\n\t\t{\n\t\t\tauto cn = dcast(fir::ConstantNumber, lhs);\n\t\t\ticeAssert(cn);\n\n\t\t\tauto res = _unwrapConstantNumber(this, cn, rt, true);\n\t\t\tif(!res)\treturn { lhs, rhs };\n\t\t\telse\t\treturn { CGResult(res), rhs };\n\t\t}\n\t\telse if(!lt->isConstantNumberType() && rt->isConstantNumberType())\n\t\t{\n\t\t\tauto [ l, r ] = this->autoCastValueTypes(rhs, lhs);\n\t\t\treturn { r, l };\n\t\t}\n\t\telse  */if(lt->isIntegerType() && rt->isIntegerType() && lt->isSignedIntType() == rt->isSignedIntType())\n\t\t{\n\t\t\t// ok, neither are constants\n\t\t\t// do the normal thing\n\n\t\t\tif(lt->getBitWidth() > rt->getBitWidth())\n\t\t\t{\n\t\t\t\t// cast rt to lt\n\t\t\t\treturn { lhs, this->irb.IntSizeCast(rhs, lt) };\n\t\t\t}\n\t\t\telse if(lt->getBitWidth() < rt->getBitWidth())\n\t\t\t{\n\t\t\t\treturn { this->irb.IntSizeCast(lhs, rt), rhs };\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn { lhs, rhs };\n\t\t\t}\n\t\t}\n\t\telse if(lt->isFloatingPointType() && rt->isFloatingPointType())\n\t\t{\n\t\t\t// ok, neither are constants\n\t\t\t// do the normal thing\n\n\t\t\tif(lt->getBitWidth() > rt->getBitWidth())\n\t\t\t{\n\t\t\t\t// cast rt to lt\n\t\t\t\treturn { lhs, this->irb.FExtend(rhs, lt) };\n\t\t\t}\n\t\t\telse if(lt->getBitWidth() < rt->getBitWidth())\n\t\t\t{\n\t\t\t\treturn { this->irb.FExtend(lhs, rt), rhs };\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn { lhs, rhs };\n\t\t\t}\n\t\t}\n\n\t\t// TODO: do we really want this?\n\t\telse if((lt->isFloatingPointType() && rt->isIntegerType()) || (rt->isFloatingPointType() && lt->isIntegerType()))\n\t\t{\n\t\t\tif(lt->isFloatingPointType())   return { lhs, this->irb.IntToFloatCast(rhs, lt) };\n\t\t\telse                            return { this->irb.IntToFloatCast(lhs, rt), rhs };\n\t\t}\n\n\t\t// nope...\n\t\twarn(this->loc(), \"unsupported autocast of '%s' -> '%s'\", lt, rt);\n\t\treturn { 0, 0 };\n\t}\n}\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/builtin.cpp",
    "content": "// builtin.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"errors.h\"\n#include \"codegen.h\"\n#include \"gluecode.h\"\n#include \"typecheck.h\"\n\n// stupid c++, u don't do it with 'using'\nnamespace names = strs::names;\n\n\nstatic fir::Value* checkNullPointerOrReturnZero(cgn::CodegenState* cs, fir::Value* ptr)\n{\n\ticeAssert(ptr->getType() == fir::Type::getNativeWordPtr());\n\n\tauto isnull = cs->irb.ICmpEQ(ptr, fir::ConstantValue::getZeroValue(fir::Type::getNativeWordPtr()));\n\n\tauto prevb = cs->irb.getCurrentBlock();\n\tauto deref = cs->irb.addNewBlockAfter(\"deref\", prevb);\n\tauto merge = cs->irb.addNewBlockAfter(\"merge\", deref);\n\n\tcs->irb.CondBranch(isnull, merge, deref);\n\n\tcs->irb.setCurrentBlock(deref);\n\tauto rc = cs->irb.ReadPtr(ptr);\n\tcs->irb.UnCondBranch(merge);\n\n\tcs->irb.setCurrentBlock(merge);\n\tauto phi = cs->irb.CreatePHINode(fir::Type::getNativeWord());\n\tphi->addIncoming(fir::ConstantInt::getNative(0), prevb);\n\tphi->addIncoming(rc, deref);\n\n\treturn phi;\n}\n\n\n\nCGResult sst::BuiltinDotOp::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tauto res = this->lhs->codegen(cs);\n\tauto ty = res.value->getType();\n\n\tif(this->isFunctionCall)\n\t{\n\t\tstd::vector<fir::Value*> arguments = zfu::map(this->args, [cs](sst::Expr* e) -> fir::Value* { return e->codegen(cs).value; });\n\t\tif(this->name == names::saa::FN_CLONE)\n\t\t{\n\t\t\ticeAssert(arguments.empty());\n\t\t\tauto clonef = cgn::glue::saa_common::generateCloneFunction(cs, ty);\n\n\t\t\tauto ret = cs->irb.Call(clonef, cs->irb.CreateSliceFromSAA(res.value, false), fir::ConstantInt::getNative(0));\n\n\t\t\ticeAssert(fir::isRefCountedType(ret->getType()));\n\t\t\tcs->addRefCountedValue(ret);\n\n\t\t\treturn CGResult(ret);\n\t\t}\n\t\telse if(this->name == names::array::FN_POP)\n\t\t{\n\t\t\ticeAssert(!ty->isStringType());\n\n\t\t\tif(!res->islvalue())\n\t\t\t\terror(this->lhs, \"cannot call 'pop()' on an rvalue\");\n\n\t\t\telse if(res->isConst())\n\t\t\t\terror(this->lhs, \"cannot call 'pop()' (which mutates) on a constant value\");\n\n\t\t\telse if(ty->isArrayType())\n\t\t\t\terror(this->lhs, \"cannot call 'pop()' on an array type ('%s')\", ty);\n\n\t\t\tauto popf = cgn::glue::array::getPopElementFromBackFunction(cs, ty);\n\t\t\tauto tupl = cs->irb.Call(popf, res.value, fir::ConstantCharSlice::get(this->loc.toString()));\n\n\t\t\t// tupl[0] is the new array\n\t\t\t// tupl[1] is the last element\n\n\t\t\tauto newarr = cs->irb.ExtractValue(tupl, { 0 });\n\t\t\tauto retelm = cs->irb.ExtractValue(tupl, { 1 });\n\n\t\t\tcs->irb.Store(newarr, res.value);\n\t\t\treturn CGResult(retelm);\n\t\t}\n\t\telse if(this->name == names::saa::FN_APPEND)\n\t\t{\n\t\t\ticeAssert(arguments.size() == 1);\n\n\t\t\tif(!res->islvalue())\n\t\t\t\terror(this->lhs, \"cannot call 'append' on an rvalue\");\n\n\t\t\tauto arg = arguments[0];\n\t\t\tfir::Function* appendf = cgn::glue::saa_common::generateAppropriateAppendFunction(cs, ty, arg->getType());\n\t\t\ticeAssert(appendf);\n\n\t\t\tif(arg->getType()->isDynamicArrayType() && arg->getType() == ty)\n\t\t\t\targ = cs->irb.CreateSliceFromSAA(arg, true);\n\n\t\t\telse if(arg->getType()->isStringType() && arg->getType() == ty)\n\t\t\t\targ = cs->irb.CreateSliceFromSAA(arg, true);\n\n\t\t\tauto ret = cs->irb.Call(appendf, res.value, arg);\n\n\t\t\tcs->irb.Store(ret, res.value);\n\n\t\t\treturn CGResult(res);\n\t\t}\n\t}\n\telse\n\t{\n\t\tif(ty->isStringType() || ty->isDynamicArrayType())\n\t\t{\n\t\t\tif(this->name == names::saa::FIELD_POINTER)\n\t\t\t\treturn CGResult(cs->irb.GetSAAData(res.value));\n\n\t\t\telse if(this->name == names::saa::FIELD_LENGTH)\n\t\t\t\treturn CGResult(cs->irb.GetSAALength(res.value));\n\n\t\t\telse if(this->name == names::saa::FIELD_CAPACITY)\n\t\t\t\treturn CGResult(cs->irb.GetSAACapacity(res.value));\n\n\t\t\telse if(this->name == names::saa::FIELD_REFCOUNT)\n\t\t\t{\n\t\t\t\treturn CGResult(checkNullPointerOrReturnZero(cs, cs->irb.GetSAARefCountPointer(res.value)));\n\t\t\t}\n\t\t\telse if(ty->isStringType() && this->name == names::string::FIELD_COUNT)\n\t\t\t{\n\t\t\t\tauto fn = cgn::glue::string::getUnicodeLengthFunction(cs);\n\t\t\t\ticeAssert(fn);\n\n\t\t\t\tauto ret = cs->irb.Call(fn, cs->irb.GetSAAData(res.value));\n\t\t\t\treturn CGResult(ret);\n\t\t\t}\n\t\t}\n\t\telse if(ty->isArraySliceType())\n\t\t{\n\t\t\tif(this->name == names::saa::FIELD_LENGTH)\n\t\t\t\treturn CGResult(cs->irb.GetArraySliceLength(res.value));\n\n\t\t\telse if(this->name == names::saa::FIELD_POINTER)\n\t\t\t\treturn CGResult(cs->irb.GetArraySliceData(res.value));\n\t\t}\n\t\telse if(ty->isArrayType())\n\t\t{\n\t\t\tif(this->name == names::saa::FIELD_LENGTH)\n\t\t\t{\n\t\t\t\treturn CGResult(fir::ConstantInt::getNative(ty->toArrayType()->getArraySize()));\n\t\t\t}\n\t\t\telse if(this->name == names::saa::FIELD_POINTER)\n\t\t\t{\n\t\t\t\t// TODO: LVALUE HOLE\n\t\t\t\tif(res.value->islvalue())\n\t\t\t\t{\n\t\t\t\t\tauto ret = cs->irb.ConstGEP2(cs->irb.AddressOf(res.value, /* mut: */ false), 0, 0);\n\t\t\t\t\treturn CGResult(ret);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\terror(\"NOT SUP\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if(ty->isRangeType())\n\t\t{\n\t\t\tif(this->name == names::range::FIELD_BEGIN)\n\t\t\t\treturn CGResult(cs->irb.GetRangeLower(res.value));\n\n\t\t\telse if(this->name == names::range::FIELD_END)\n\t\t\t\treturn CGResult(cs->irb.GetRangeUpper(res.value));\n\n\t\t\telse if(this->name == names::range::FIELD_STEP)\n\t\t\t\treturn CGResult(cs->irb.GetRangeStep(res.value));\n\n\t\t}\n\t\telse if(ty->isAnyType())\n\t\t{\n\t\t\tif(this->name == names::any::FIELD_TYPEID)\n\t\t\t\treturn CGResult(cs->irb.GetAnyTypeID(res.value));\n\n\t\t\telse if(this->name == names::any::FIELD_REFCOUNT)\n\t\t\t\treturn CGResult(checkNullPointerOrReturnZero(cs, cs->irb.GetAnyRefCountPointer(res.value)));\n\t\t}\n\t\telse if(ty->isEnumType())\n\t\t{\n\t\t\tif(this->name == names::enumeration::FIELD_INDEX)\n\t\t\t{\n\t\t\t\treturn CGResult(cs->irb.GetEnumCaseIndex(res.value));\n\t\t\t}\n\t\t\telse if(this->name == names::enumeration::FIELD_VALUE)\n\t\t\t{\n\t\t\t\treturn CGResult(cs->irb.GetEnumCaseValue(res.value));\n\t\t\t}\n\t\t\telse if(this->name == names::enumeration::FIELD_NAME)\n\t\t\t{\n\t\t\t\tauto namearr = ty->toEnumType()->getNameArray();\n\t\t\t\ticeAssert(namearr->islvalue());\n\n\t\t\t\tauto namearrptr = cs->irb.AddressOf(namearr, /* mut: */ false);\n\t\t\t\ticeAssert(namearrptr->getType()->isPointerType() && namearrptr->getType()->getPointerElementType()->isArrayType());\n\n\t\t\t\tauto idx = cs->irb.GetEnumCaseIndex(res.value);\n\t\t\t\tauto n = cs->irb.GEP2(namearrptr, fir::ConstantInt::getNative(0), idx);\n\n\t\t\t\treturn CGResult(cs->irb.ReadPtr(n));\n\t\t\t}\n\t\t}\n\t}\n\n\n\terror(this, \"no property or builtin method '%s' on type '%s'\", this->name, ty);\n}\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/call.cpp",
    "content": "// call.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include <set>\n\n#include \"sst.h\"\n#include \"memorypool.h\"\n#include \"codegen.h\"\n#include \"gluecode.h\"\n\nutil::hash_map<std::string, size_t> cgn::CodegenState::getNameIndexMap(sst::FunctionDefn* fd)\n{\n\tutil::hash_map<std::string, size_t> idxmap;\n\n\tfor(size_t i = 0; i < fd->params.size(); i++)\n\t\tidxmap[fd->params[i].name] = i;\n\n\treturn idxmap;\n}\n\n\n\n\n\n\nstatic std::vector<fir::Value*> _codegenAndArrangeFunctionCallArguments(cgn::CodegenState* cs, fir::FunctionType* ft,\n\tconst std::vector<FnCallArgument>& arguments, const util::hash_map<std::string, size_t>& idxmap,\n\tconst util::hash_map<size_t, sst::Expr*>& defaultArgumentValues)\n{\n\tbool fvararg = ft->isVariadicFunc();\n\tsize_t numNormalArgs = ft->getArgumentCount() + (fvararg ? -1 : 0);\n\n\tutil::hash_map<size_t, sst::Expr*> argExprs;\n\tutil::hash_map<sst::Expr*, size_t> revArgExprs;\n\n\t// this thing below operates similarly to the list solver in typecheck/polymorph/solver.cpp\n\tsize_t last_arg = std::min(numNormalArgs, arguments.size());\n\n\tsize_t positionalCounter = 0;\n\tsize_t varArgStart = numNormalArgs;\n\tfor(size_t i = 0; i < last_arg; i++)\n\t{\n\t\tconst auto& arg = arguments[i];\n\n\t\tif(!arg.name.empty())\n\t\t{\n\t\t\tauto it = idxmap.find(arg.name);\n\t\t\ticeAssert(it != idxmap.end());\n\n\t\t\targExprs[it->second] = arg.value;\n\t\t\trevArgExprs[arg.value] = it->second;\n\n\t\t\tif(defaultArgumentValues.find(it->second) == defaultArgumentValues.end())\n\t\t\t\tpositionalCounter++;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// so, `positionalCounter` counts the paramters on the declaration-side. thus, once we encounter a default value,\n\t\t\t// it must mean that the rest of the parameters will be optional as well.\n\t\t\t//* ie. we've passed all the positional arguments already, leaving the optional ones, which means every argument from\n\t\t\t//* here onwards (including this one) must be named. since this is *not* named, we just skip straight to the varargs if\n\t\t\t//* it was present.\n\t\t\tif(fvararg && defaultArgumentValues.find(positionalCounter) != defaultArgumentValues.end())\n\t\t\t{\n\t\t\t\tvarArgStart = i;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\targExprs[positionalCounter] = arg.value;\n\t\t\trevArgExprs[arg.value] = positionalCounter;\n\n\t\t\tpositionalCounter++;\n\t\t}\n\t}\n\n\tfor(size_t i = 0; i < numNormalArgs; i++)\n\t{\n\t\tif(argExprs.find(i) == argExprs.end())\n\t\t{\n\t\t\tauto it = defaultArgumentValues.find(i);\n\t\t\tif(it == defaultArgumentValues.end())\n\t\t\t\terror(cs->loc(), \"missing value for argument %d\", i);\n\n\t\t\targExprs[i] = it->second;\n\t\t\trevArgExprs[it->second] = i;\n\t\t}\n\t}\n\n\tauto doCastIfNecessary = [cs](const Location& loc, fir::Value* val, fir::Type* infer) -> fir::Value* {\n\n\t\tif(val->getType()->isConstantNumberType())\n\t\t{\n\t\t\tauto cv = dcast(fir::ConstantValue, val);\n\t\t\ticeAssert(cv);\n\n\t\t\tval = cs->unwrapConstantNumber(cv);\n\t\t}\n\n\t\tif(!infer)\n\t\t\treturn val;\n\n\t\tif(val->getType() != infer)\n\t\t{\n\t\t\tval = cs->oneWayAutocast(val, infer);\n\n\t\t\tif(val->getType() != infer)\n\t\t\t{\n\t\t\t\tauto errs = SpanError::make(SimpleError::make(loc, \"mismatched type in function call; parameter has type '%s', \"\n\t\t\t\t\t\"but given argument has type '%s'\", infer, val->getType()));\n\n\t\t\t\terrs->postAndQuit();\n\t\t\t}\n\t\t}\n\n\t\treturn val;\n\t};\n\n\n\n\n\n\tstd::vector<fir::Value*> values(argExprs.size());\n\t{\n\t\tfor(size_t i = 0; i < argExprs.size(); i++)\n\t\t{\n\t\t\t// this extra complexity is to ensure we codegen arguments from left-to-right!\n\t\t\tauto arg = argExprs[i];\n\t\t\tauto k = revArgExprs[arg];\n\n\t\t\tauto infer = ft->getArgumentN(k);\n\t\t\tauto val = arg->codegen(cs, infer).value;\n\n\t\t\t//! RAII: COPY CONSTRUCTOR CALL\n\t\t\t//? the copy constructor is called when passed as an argument to a function call\n\t\t\t//* copyRAIIValue will just return 'val' if it is not a class type, so we don't check it here!\n\t\t\tval = cs->copyRAIIValue(val);\n\n\n\t\t\t//* arguments are added to the refcounting list in the function,\n\t\t\t//* so we need to \"pre-increment\" the refcount here, so it does not\n\t\t\t//* get freed when the function returns.\n\t\t\tif(fir::isRefCountedType(val->getType()))\n\t\t\t\tcs->incrementRefCount(val);\n\n\t\t\tif(val->getType()->isConstantNumberType())\n\t\t\t{\n\t\t\t\tauto cv = dcast(fir::ConstantValue, val);\n\t\t\t\ticeAssert(cv);\n\n\t\t\t\tval = cs->unwrapConstantNumber(cv);\n\t\t\t}\n\n\t\t\tval = doCastIfNecessary(arg->loc, val, infer);\n\t\t\tvalues[k] = val;\n\t\t}\n\t}\n\n\n\t// check the variadic arguments. note that IRBuilder will handle actually wrapping the values up into a slice\n\t// and/or creating an empty slice and/or forwarding an existing slice. we just need to supply the values.\n\tfor(size_t i = varArgStart; i < arguments.size(); i++)\n\t{\n\t\tauto arg = arguments[i].value;\n\t\tfir::Type* infer = 0;\n\n\t\tif(fvararg)\n\t\t{\n\t\t\tauto vararrty = ft->getArgumentN(ft->getArgumentCount() - 1);\n\n\t\t\t// if forwarding perfectly, then infer as the slice type, instead of the element type.\n\t\t\tif(i == arguments.size() - 1 && arg->type->isVariadicArrayType())\n\t\t\t{\n\t\t\t\t// perfect forwarding.\n\t\t\t\tinfer = vararrty;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ticeAssert(vararrty->isVariadicArrayType());\n\t\t\t\tinfer = vararrty->getArrayElementType();\n\t\t\t}\n\t\t}\n\n\t\tauto val = arg->codegen(cs, infer).value;\n\t\tif(fir::isRefCountedType(val->getType()))\n\t\t\tcs->incrementRefCount(val);\n\n\t\tval = doCastIfNecessary(arg->loc, val, infer);\n\n\n\t\tif(ft->isCStyleVarArg())\n\t\t{\n\t\t\t// auto-convert strings and char slices into char* when passing to va_args\n\t\t\tif(val->getType()->isStringType())\n\t\t\t\tval = cs->irb.GetSAAData(val);\n\n\t\t\telse if(val->getType()->isCharSliceType())\n\t\t\t\tval = cs->irb.GetArraySliceData(val);\n\n\t\t\t// also, see if we need to promote the type!\n\t\t\t// anything < int gets promoted to int; float -> double\n\t\t\telse if(val->getType() == fir::Type::getFloat32())\n\t\t\t\tval = cs->irb.FExtend(val, fir::Type::getFloat64());\n\n\t\t\t// don't need to worry about signedness for this; if you're smaller than int32,\n\t\t\t// int32 can represent you even if you're unsigned\n\t\t\telse if(val->getType()->isIntegerType() && val->getType()->toPrimitiveType()->getIntegerBitWidth() < 32)\n\t\t\t\tval = cs->irb.IntSizeCast(val, val->getType()->isSignedIntType() ? fir::Type::getInt32() : fir::Type::getUint32());\n\n\t\t\telse if(val->getType()->isBoolType())\n\t\t\t\tval = cs->irb.IntZeroExt(val, fir::Type::getInt32());\n\t\t}\n\n\t\tvalues.push_back(val);\n\t}\n\n\treturn values;\n}\n\n\nstd::vector<fir::Value*> cgn::CodegenState::codegenAndArrangeFunctionCallArguments(sst::Defn* target, fir::FunctionType* ft,\n\tconst std::vector<FnCallArgument>& arguments)\n{\n\tutil::hash_map<std::string, size_t> idxmap;\n\tutil::hash_map<size_t, sst::Expr*> defaultArgs;\n\n\tif(auto fd = dcast(sst::FunctionDefn, target))\n\t{\n\t\tidxmap = this->getNameIndexMap(fd);\n\n\t\tzfu::foreachIdx(fd->params, [&defaultArgs](const FnParam& arg, size_t idx) {\n\t\t\tif(arg.defaultVal)\n\t\t\t\tdefaultArgs[idx] = arg.defaultVal;\n\t\t});\n\t}\n\n\treturn _codegenAndArrangeFunctionCallArguments(this, ft, arguments, idxmap, defaultArgs);\n}\n\nCGResult sst::FunctionCall::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tif(!this->target)\n\t\terror(this, \"failed to find target for function call to '%s'\", this->name);\n\n\t// check this target\n\tfir::Value* vf = 0;\n\tfir::FunctionType* ft = 0;\n\n\n\tif(dcast(VarDefn, this->target))\n\t{\n\t\t// ok, we're calling a variable.\n\t\t// the below stuff ain't gonna work without some intervention\n\n\t\tCGResult defn;\n\t\tCGResult r = cs->valueMap[this->target];\n\n\t\tif(r.value)\n\t\t{\n\t\t\tdefn = r;\n\t\t}\n\t\telse if(cs->isInMethodBody())\n\t\t{\n\t\t\tdefn = cs->getStructFieldImplicitly(this->name);\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(this, \"no such '%s'\", this->name);\n\t\t}\n\n\t\ticeAssert(defn.value);\n\t\tvf = defn.value;\n\t}\n\telse if(auto fd = dcast(FunctionDefn, this->target); fd && fd->isVirtual)\n\t{\n\t\t// ok then.\n\t\tauto ret = cs->callVirtualMethod(this);\n\t\tcs->addRAIIOrRCValueIfNecessary(ret);\n\n\t\treturn CGResult(ret);\n\t}\n\telse\n\t{\n\t\tvf = this->target->codegen(cs).value;\n\t}\n\n\n\tif(vf->getType()->isFunctionType())\n\t{\n\t\tft = vf->getType()->toFunctionType();\n\t}\n\telse\n\t{\n\t\t// we should have disallowed this already in the typechecker.\n\t\t// TODO: is the usecase then to just cast to a function type?\n\t\t// eg. let entry = (0x400000) as (fn()->int) or something\n\t\ticeAssert(false && \"somehow you got a pointer-to-function?!\");\n\n\t\t// auto vt = vf->getType();\n\t\t// iceAssert(vt->isPointerType() && vt->getPointerElementType()->isFunctionType());\n\n\t\t// ft = vt->getPointerElementType()->toFunctionType();\n\n\t\t// warn(this, \"prefer using functions to function pointers\");\n\t}\n\n\ticeAssert(ft);\n\n\t//! SELF HANDLING (INSERTION) (CODEGEN)\n\tif(auto fd = dcast(FunctionDefn, this->target); fd && fd->parentTypeForMethod && cs->isInMethodBody() && this->isImplicitMethodCall)\n\t{\n\t\tauto fake = util::pool<RawValueExpr>(this->loc, fd->parentTypeForMethod->getPointerTo());\n\t\tfake->rawValue = CGResult(cs->irb.AddressOf(cs->getMethodSelf(), true));\n\n\t\tthis->arguments.insert(this->arguments.begin(), FnCallArgument(this->loc, \"this\", fake, 0));\n\t}\n\n\tsize_t numArgs = ft->getArgumentCount();\n\tif(ft->isCStyleVarArg() && this->arguments.size() < numArgs)\n\t{\n\t\terror(this, \"need at least %d arguments to call variadic function '%s', only have %d\",\n\t\t\tnumArgs, this->name, this->arguments.size());\n\t}\n\n\n\tauto args = cs->codegenAndArrangeFunctionCallArguments(this->target, ft, this->arguments);\n\n\tfir::Value* ret = 0;\n\n\tif(fir::Function* func = dcast(fir::Function, vf))\n\t{\n\t\tret = cs->irb.Call(func, args);\n\t}\n\telse if(vf->getType()->isFunctionType())\n\t{\n\t\tret = cs->irb.CallToFunctionPointer(vf, ft, args);\n\t}\n\telse\n\t{\n\t\ticeAssert(vf->getType()->getPointerElementType()->isFunctionType());\n\t\tauto fptr = cs->irb.ReadPtr(vf);\n\n\t\tret = cs->irb.CallToFunctionPointer(fptr, ft, args);\n\t}\n\n\t// do the refcounting if we need to\n\tcs->addRAIIOrRCValueIfNecessary(ret);\n\treturn CGResult(ret);\n}\n\n\n\nstatic CGResult callBuiltinTypeConstructor(cgn::CodegenState* cs, fir::Type* type, const std::vector<sst::Expr*>& args)\n{\n\t// for non-strings it's trivial\n\tif(args.empty())\n\t{\n\t\treturn CGResult(cs->getDefaultValue(type));\n\t}\n\telse if(!type->isStringType())\n\t{\n\t\ticeAssert(args.size() == 1);\n\t\tauto ret = cs->oneWayAutocast(args[0]->codegen(cs, type).value, type);\n\n\t\tif(type != ret->getType())\n\t\t\terror(args[0], \"mismatched type in builtin type initialiser; expected '%s', found '%s'\", type, ret->getType());\n\n\t\treturn CGResult(ret);\n\t}\n\telse\n\t{\n\t\tauto cloneTheSlice = [cs](fir::Value* slc) -> CGResult {\n\n\t\t\ticeAssert(slc->getType()->isCharSliceType());\n\n\t\t\tauto clonef = cgn::glue::string::getCloneFunction(cs);\n\t\t\ticeAssert(clonef);\n\n\t\t\tauto ret = cs->irb.Call(clonef, slc, fir::ConstantInt::getNative(0));\n\t\t\tcs->addRefCountedValue(ret);\n\n\t\t\treturn CGResult(ret);\n\t\t};\n\n\t\tif(args.size() == 1)\n\t\t{\n\t\t\ticeAssert(args[0]->type->isCharSliceType());\n\t\t\treturn cloneTheSlice(args[0]->codegen(cs, fir::Type::getCharSlice(false)).value);\n\t\t}\n\t\telse\n\t\t{\n\t\t\ticeAssert(args.size() == 2);\n\t\t\ticeAssert(args[0]->type == fir::Type::getInt8Ptr() || args[0]->type == fir::Type::getMutInt8Ptr());\n\t\t\ticeAssert(args[1]->type->isIntegerType());\n\n\t\t\tauto ptr = args[0]->codegen(cs).value;\n\t\t\tauto len = cs->oneWayAutocast(args[1]->codegen(cs, fir::Type::getNativeWord()).value, fir::Type::getNativeWord());\n\n\t\t\tauto slc = cs->irb.CreateValue(fir::Type::getCharSlice(false));\n\t\t\tslc = cs->irb.SetArraySliceData(slc, (ptr->getType()->isMutablePointer()\n\t\t\t\t? cs->irb.PointerTypeCast(ptr, fir::Type::getInt8Ptr()) : ptr));\n\n\t\t\tslc = cs->irb.SetArraySliceLength(slc, len);\n\n\t\t\treturn cloneTheSlice(slc);\n\t\t}\n\t}\n}\n\n\n\n\nCGResult sst::ExprCall::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tif(auto te = dcast(sst::TypeExpr, this->callee))\n\t\treturn callBuiltinTypeConstructor(cs, te->type, this->arguments);\n\n\ticeAssert(this->callee);\n\n\tfir::Value* fn = this->callee->codegen(cs).value;\n\ticeAssert(fn->getType()->isFunctionType());\n\n\tauto ft = fn->getType()->toFunctionType();\n\n\tif(ft->getArgumentCount() != this->arguments.size())\n\t{\n\t\tif((!ft->isVariadicFunc() && !ft->isCStyleVarArg()) || this->arguments.size() < ft->getArgumentCount())\n\t\t{\n\t\t\terror(this, \"mismatched number of arguments; expected %d, but %d were given\",\n\t\t\t\tft->getArgumentCount(), this->arguments.size());\n\t\t}\n\t}\n\n\tstd::vector<FnCallArgument> fcas = zfu::map(this->arguments, [](sst::Expr* arg) -> FnCallArgument {\n\t\treturn FnCallArgument(arg->loc, \"\", arg, /* orig: */ nullptr);\n\t});\n\n\tstd::vector<fir::Value*> args = cs->codegenAndArrangeFunctionCallArguments(/* targetDefn: */ nullptr, ft, fcas);\n\n\tauto ret = cs->irb.CallToFunctionPointer(fn, ft, args);\n\n\tcs->addRAIIOrRCValueIfNecessary(ret);\n\treturn CGResult(ret);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/classes.cpp",
    "content": "// classes.h\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"errors.h\"\n#include \"codegen.h\"\n#include \"typecheck.h\"\n#include \"memorypool.h\"\n\nCGResult sst::ClassDefn::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\ticeAssert(this->type && this->type->isClassType());\n\n\tstd::vector<fir::Function*> meths;\n\tstd::vector<fir::Function*> inits;\n\n\n\tauto clsty = this->type->toClassType();\n\n\t//* this looks stupid, but in 'setbaseclass' we update the virtual methods of the current class.\n\t//* since when we previously set the base class there were no virtual methods (we were still typechecking),\n\t//* we need to do it again.\n\tif(this->baseClass)\n\t{\n\t\tthis->baseClass->codegen(cs);\n\t\tclsty->setBaseClass(clsty->getBaseClass());\n\t}\n\n\n\tfor(auto method : this->methods)\n\t{\n\t\tauto res = method->codegen(cs);\n\n\t\tauto f = dcast(fir::Function, res.value);\n\t\tmeths.push_back(f);\n\n\t\tif(method->isVirtual)\n\t\t\tclsty->addVirtualMethod(f);\n\n\t\tif(method->id.name == \"init\")   inits.push_back(f);\n\t\tif(method->id.name == \"deinit\") clsty->setDestructor(f);\n\t\tif(method->id.name == \"copy\")   clsty->setCopyConstructor(f);\n\t\tif(method->id.name == \"move\")   clsty->setMoveConstructor(f);\n\t}\n\n\tclsty->setMethods(meths);\n\tclsty->setInitialiserFunctions(inits);\n\n\n\tfor(auto sm : this->staticFields)\n\t\tsm->codegen(cs);\n\n\tfor(auto sm : this->staticMethods)\n\t\tsm->codegen(cs);\n\n\tfor(auto nt : this->nestedTypes)\n\t\tnt->codegen(cs);\n\n\n\tauto restore = cs->irb.getCurrentBlock();\n\n\n\n\t// make the inline initialiser\n\t{\n\t\tfir::Function* func = cs->module->getOrCreateFunction(fir::Name::obfuscate(clsty->encodedStr(), \"_inline_init\"),\n\t\t\tfir::FunctionType::get({ this->type->getMutablePointerTo() }, fir::Type::getVoid()),\n\t\t\tfir::LinkageType::Internal);\n\n\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\tcs->irb.setCurrentBlock(entry);\n\n\t\tauto self = cs->irb.Dereference(func->getArguments()[0], \"this\");\n\n\t\t// make sure we call the base init first.\n\t\tif(clsty->getBaseClass())\n\t\t{\n\t\t\tauto bii = clsty->getBaseClass()->getInlineInitialiser();\n\t\t\ticeAssert(bii);\n\n\t\t\tcs->irb.Call(bii, cs->irb.PointerTypeCast(cs->irb.AddressOf(self, true), clsty->getBaseClass()->getMutablePointerTo()));\n\t\t}\n\n\t\t// set our vtable\n\t\tif(clsty->getVirtualMethodCount() > 0)\n\t\t{\n\t\t\tauto vtable = cs->irb.PointerTypeCast(cs->irb.AddressOf(cs->module->getOrCreateVirtualTableForClass(clsty), false),\n\t\t\t\tfir::Type::getInt8Ptr());\n\t\t\tcs->irb.SetVtable(self, vtable);\n\t\t}\n\n\t\tfor(auto fd : this->fields)\n\t\t{\n\t\t\tif(fd->init)\n\t\t\t{\n\t\t\t\tauto res = fd->init->codegen(cs, fd->type).value;\n\t\t\t\tauto elmptr = cs->irb.GetStructMember(self, fd->id.name);\n\n\t\t\t\tcs->autoAssignRefCountedValue(elmptr, res, true);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto elmptr = cs->irb.GetStructMember(self, fd->id.name);\n\t\t\t\tcs->autoAssignRefCountedValue(elmptr, cs->getDefaultValue(fd->type), true);\n\t\t\t}\n\t\t}\n\n\t\tcs->irb.ReturnVoid();\n\t\tclsty->setInlineInitialiser(func);\n\t}\n\n\t// this is the inline destructor\n\t{\n\t\tfir::Function* func = cs->module->getOrCreateFunction(fir::Name::obfuscate(clsty->encodedStr(), \"_inline_deinit\"),\n\t\t\tfir::FunctionType::get({ this->type->getMutablePointerTo() }, fir::Type::getVoid()),\n\t\t\tfir::LinkageType::Internal);\n\n\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\tcs->irb.setCurrentBlock(entry);\n\n\t\tauto selfptr = func->getArguments()[0];\n\t\tauto self = cs->irb.Dereference(selfptr, \"this\");\n\n\t\tfor(auto f : this->fields)\n\t\t{\n\t\t\tif(f->type->isClassType())\n\t\t\t{\n\t\t\t\tauto fld = cs->irb.GetStructMember(self, f->id.name);\n\t\t\t\tcs->callDestructor(fld);\n\t\t\t}\n\t\t}\n\n\t\t// ok, now that we have destroyed our own fields, call the base class destructor, followed by the base class inline destructor!\n\t\tif(auto base = clsty->getBaseClass(); base)\n\t\t{\n\t\t\tauto baseptr = cs->irb.PointerTypeCast(selfptr, base->getMutablePointerTo());\n\n\t\t\tif(auto des = base->getDestructor(); des)\n\t\t\t\tcs->irb.Call(des, baseptr);\n\n\t\t\tcs->irb.Call(base->getInlineDestructor(), baseptr);\n\t\t}\n\n\t\tcs->irb.ReturnVoid();\n\t\tclsty->setInlineDestructor(func);\n\t}\n\n\tcs->irb.setCurrentBlock(restore);\n\n\n\treturn CGResult(0);\n}\n\n\n\n\nfir::Value* cgn::CodegenState::callVirtualMethod(sst::FunctionCall* call)\n{\n\tauto fd = dcast(sst::FunctionDefn, call->target);\n\ticeAssert(fd);\n\n\tauto cls = fd->parentTypeForMethod->toClassType();\n\ticeAssert(cls);\n\n\n\tif(call->isImplicitMethodCall)\n\t{\n\t\ticeAssert(this->isInMethodBody() && fd->parentTypeForMethod);\n\n\t\tauto fake = util::pool<sst::RawValueExpr>(call->loc, fd->parentTypeForMethod->getPointerTo());\n\t\tfake->rawValue = CGResult(this->irb.AddressOf(this->getMethodSelf(), /* mutable: */ true));\n\n\t\t//! SELF HANDLING (INSERTION) (CODEGEN)\n\t\tcall->arguments.insert(call->arguments.begin(), FnCallArgument(call->loc, \"this\", fake, 0));\n\t}\n\n\ticeAssert(fd->type->isFunctionType());\n\n\tauto ft = fd->type->toFunctionType();\n\tauto args = this->codegenAndArrangeFunctionCallArguments(fd, ft, call->arguments);\n\n\tauto idx = cls->getVirtualMethodIndex(call->name, ft);\n\treturn this->irb.CallVirtualMethod(cls, ft, idx, args);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/codegenstate.cpp",
    "content": "// codegenstate.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"errors.h\"\n#include \"codegen.h\"\n#include \"platform.h\"\n#include \"gluecode.h\"\n#include \"typecheck.h\"\n\nnamespace cgn\n{\n\tvoid CodegenState::enterMethodBody(fir::Function* method, fir::Value* self)\n\t{\n\t\tthis->methodSelfStack.push_back(self);\n\n\t\tauto ty = self->getType();\n\t\ticeAssert(ty->isClassType() || ty->isStructType());\n\n\t\tthis->methodList[method] = ty;\n\t}\n\n\tvoid CodegenState::leaveMethodBody()\n\t{\n\t\ticeAssert(this->methodSelfStack.size() > 0);\n\t\tthis->methodSelfStack.pop_back();\n\t}\n\n\tbool CodegenState::isInMethodBody()\n\t{\n\t\treturn this->methodSelfStack.size() > 0 && this->functionStack.size() > 0\n\t\t\t&& this->methodList.find(this->functionStack.back()) != this->methodList.end();\n\t}\n\n\tfir::Value* CodegenState::getMethodSelf()\n\t{\n\t\ticeAssert(this->methodSelfStack.size() > 0);\n\t\treturn this->methodSelfStack.back();\n\t}\n\n\n\tvoid CodegenState::enterSubscriptWithLength(fir::Value* len)\n\t{\n\t\ticeAssert(len->getType()->isIntegerType());\n\t\tthis->subscriptArrayLengthStack.push_back(len);\n\t}\n\n\tfir::Value* CodegenState::getCurrentSubscriptArrayLength()\n\t{\n\t\ticeAssert(this->subscriptArrayLengthStack.size() > 0);\n\t\treturn this->subscriptArrayLengthStack.back();\n\t}\n\n\tvoid CodegenState::leaveSubscript()\n\t{\n\t\ticeAssert(this->subscriptArrayLengthStack.size() > 0);\n\t\tthis->subscriptArrayLengthStack.pop_back();\n\t}\n\n\n\n\n\n\tvoid CodegenState::enterFunction(fir::Function* fn)\n\t{\n\t\tthis->functionStack.push_back(fn);\n\t}\n\n\tvoid CodegenState::leaveFunction()\n\t{\n\t\tif(this->functionStack.empty())\n\t\t\terror(this->loc(), \"not a in function\");\n\n\t\tthis->functionStack.pop_back();\n\t}\n\n\tfir::Function* CodegenState::getCurrentFunction()\n\t{\n\t\tif(this->functionStack.empty())\n\t\t\terror(this->loc(), \"not a in function\");\n\n\t\treturn this->functionStack.back();\n\t}\n\n\n\n\tControlFlowPoint CodegenState::getCurrentCFPoint()\n\t{\n\t\treturn this->breakingPointStack.back();\n\t}\n\n\tvoid CodegenState::enterBreakableBody(const ControlFlowPoint& cfp)\n\t{\n\t\t// only the block needs to exist.\n\t\ticeAssert(cfp.block);\n\t\tthis->breakingPointStack.push_back(cfp);\n\t}\n\n\tControlFlowPoint CodegenState::leaveBreakableBody()\n\t{\n\t\ticeAssert(this->breakingPointStack.size() > 0);\n\n\t\tauto ret = this->breakingPointStack.back();\n\t\tthis->breakingPointStack.pop_back();\n\n\t\treturn ret;\n\t}\n\n\n\tBlockPoint CodegenState::getCurrentBlockPoint()\n\t{\n\t\treturn this->blockPointStack.back();\n\t}\n\n\tvoid CodegenState::enterBlock(const BlockPoint& bp)\n\t{\n\t\ticeAssert(bp.block);\n\t\tthis->blockPointStack.push_back(bp);\n\t}\n\n\tvoid CodegenState::leaveBlock()\n\t{\n\t\ticeAssert(this->blockPointStack.size() > 0);\n\t\tthis->blockPointStack.pop_back();\n\t}\n\n\n\n\tvoid CodegenState::pushLoc(const Location& l)\n\t{\n\t\tthis->locationStack.push_back(l);\n\t}\n\n\tvoid CodegenState::pushLoc(sst::Stmt* stmt)\n\t{\n\t\tthis->pushLoc(stmt->loc);\n\t}\n\n\tvoid CodegenState::popLoc()\n\t{\n\t\ticeAssert(this->locationStack.size() > 0);\n\t\tthis->locationStack.pop_back();\n\t}\n\n\tLocation CodegenState::loc()\n\t{\n\t\ticeAssert(this->locationStack.size() > 0);\n\t\treturn this->locationStack.back();\n\t}\n\n\n\tvoid CodegenState::createWhileLoop(const std::function<void (fir::IRBlock*, fir::IRBlock*)>& docheck, const std::function<void ()>& dobody)\n\t{\n\t\tfir::IRBlock* check = this->irb.addNewBlockInFunction(\"check\", this->irb.getCurrentFunction());\n\t\tfir::IRBlock* body = this->irb.addNewBlockInFunction(\"body\", this->irb.getCurrentFunction());\n\t\tfir::IRBlock* merge = this->irb.addNewBlockInFunction(\"merge\", this->irb.getCurrentFunction());\n\n\t\tthis->irb.UnCondBranch(check);\n\t\tthis->irb.setCurrentBlock(check);\n\n\t\t//* we expect this to do its own branching.\n\t\tdocheck(body, merge);\n\n\t\tthis->irb.setCurrentBlock(body);\n\t\tdobody();\n\n\t\t//* but not the body.\n\t\tthis->irb.UnCondBranch(check);\n\n\t\t//* back to regularly scheduled programming\n\t\tthis->irb.setCurrentBlock(merge);\n\t}\n\n\n\n\tfir::Value* CodegenState::getDefaultValue(fir::Type* type)\n\t{\n\t\tfir::Value* ret = 0;\n\t\tif(type->isStringType())\n\t\t{\n\t\t\tfir::Value* arr = this->irb.CreateValue(type);\n\n\t\t\tarr = this->irb.SetSAAData(arr, this->irb.PointerTypeCast(this->irb.GetArraySliceData(fir::ConstantCharSlice::get(\"\")),\n\t\t\t\tfir::Type::getMutInt8Ptr()));\n\t\t\tarr = this->irb.SetSAALength(arr, fir::ConstantInt::getNative(0));\n\t\t\tarr = this->irb.SetSAACapacity(arr, fir::ConstantInt::getNative(0));\n\t\t\tarr = this->irb.SetSAARefCountPointer(arr, fir::ConstantValue::getZeroValue(fir::Type::getNativeWord()->getPointerTo()));\n\n\t\t\tret = arr;\n\t\t}\n\t\telse if(type->isDynamicArrayType())\n\t\t{\n\t\t\tfir::Value* arr = this->irb.CreateValue(type);\n\n\t\t\tarr = this->irb.SetSAAData(arr, fir::ConstantValue::getZeroValue(type->getArrayElementType()->getMutablePointerTo()));\n\t\t\tarr = this->irb.SetSAALength(arr, fir::ConstantInt::getNative(0));\n\t\t\tarr = this->irb.SetSAACapacity(arr, fir::ConstantInt::getNative(0));\n\t\t\tarr = this->irb.SetSAARefCountPointer(arr, fir::ConstantValue::getZeroValue(fir::Type::getNativeWord()->getPointerTo()));\n\n\t\t\tret = arr;\n\t\t}\n\t\telse if(type->isArraySliceType())\n\t\t{\n\t\t\tfir::Value* arr = this->irb.CreateValue(type);\n\t\t\tarr = this->irb.SetArraySliceData(arr, fir::ConstantValue::getZeroValue(type->getArrayElementType()->getPointerTo()));\n\t\t\tarr = this->irb.SetArraySliceLength(arr, fir::ConstantInt::getNative(0));\n\n\t\t\tret = arr;\n\t\t}\n\t\telse if(type->isClassType())\n\t\t{\n\t\t\t// TODO\n\t\t\t//! use constructClassWithArguments!!!\n\n\t\t\tauto clsdef = dcast(sst::ClassDefn, this->typeDefnMap[type]);\n\t\t\ticeAssert(clsdef);\n\n\t\t\tclsdef->codegen(this);\n\n\t\t\t// first need to check if we have any initialisers with 0 parameters.\n\t\t\tauto cls = type->toClassType();\n\n\t\t\tsst::FunctionDefn* ifn = 0;\n\t\t\tfor(auto init : clsdef->initialisers)\n\t\t\t{\n\t\t\t\t//* note: count == 1 because of 'self'\n\t\t\t\tif(init->arguments.size() == 1)\n\t\t\t\t{\n\t\t\t\t\tifn = init;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(ifn == 0)\n\t\t\t{\n\t\t\t\tSimpleError::make(this->loc(), \"class '%s' cannot be automatically initialised as it does not have a constructor taking 0 arguments\",\n\t\t\t\t\tcls->getTypeName())->append(SimpleError::make(MsgType::Note, clsdef->loc, \"class '%s' was defined here:\", clsdef->id.name))\n\t\t\t\t\t->postAndQuit();\n\t\t\t}\n\n\t\t\tret = this->constructClassWithArguments(cls, ifn, { });\n\t\t}\n\t\telse\n\t\t{\n\t\t\tret = fir::ConstantValue::getZeroValue(type);\n\t\t}\n\n\t\tif(fir::isRefCountedType(type))\n\t\t\tthis->addRefCountedValue(ret);\n\n\t\tret->setKind(fir::Value::Kind::prvalue);\n\t\treturn ret;\n\t}\n\n\tvoid CodegenState::pushIRDebugIndentation()\n\t{\n\t\tthis->_debugIRIndent++;\n\t}\n\n\tvoid CodegenState::printIRDebugMessage(const std::string& msg, const std::vector<fir::Value*>& vals)\n\t{\n\t\tfir::Value* tmpstr = this->module->createGlobalString(std::string(this->_debugIRIndent * 4, ' ') + msg + \"\\n\");\n\t\tthis->irb.Call(this->getOrDeclareLibCFunction(\"printf\"), tmpstr + vals);\n\t}\n\n\tvoid CodegenState::popIRDebugIndentation()\n\t{\n\t\tthis->_debugIRIndent--;\n\t}\n\n\n\n\n\n\tfir::Function* CodegenState::getOrDeclareLibCFunction(std::string name)\n\t{\n\t\tif(name == ALLOCATE_MEMORY_FUNC)\n\t\t{\n\t\t\treturn this->module->getOrCreateFunction(fir::Name::of(ALLOCATE_MEMORY_FUNC),\n\t\t\t\tfir::FunctionType::get({ fir::Type::getNativeWord() }, fir::Type::getMutInt8Ptr()), fir::LinkageType::External);\n\t\t}\n\t\telse if(name == FREE_MEMORY_FUNC)\n\t\t{\n\t\t\treturn this->module->getOrCreateFunction(fir::Name::of(FREE_MEMORY_FUNC),\n\t\t\t\tfir::FunctionType::get({ fir::Type::getMutInt8Ptr() }, fir::Type::getVoid()), fir::LinkageType::External);\n\t\t}\n\t\telse if(name == REALLOCATE_MEMORY_FUNC)\n\t\t{\n\t\t\treturn this->module->getOrCreateFunction(fir::Name::of(REALLOCATE_MEMORY_FUNC),\n\t\t\t\tfir::FunctionType::get({ fir::Type::getMutInt8Ptr(), fir::Type::getNativeWord() }, fir::Type::getMutInt8Ptr()),\n\t\t\t\t\tfir::LinkageType::External);\n\t\t}\n\t\telse if(name == CRT_FDOPEN)\n\t\t{\n\t\t\treturn this->module->getOrCreateFunction(fir::Name::of(CRT_FDOPEN),\n\t\t\t\tfir::FunctionType::get({ fir::Type::getInt32(), fir::Type::getInt8Ptr() }, fir::Type::getVoidPtr()), fir::LinkageType::External);\n\t\t}\n\t\telse if(name == \"printf\")\n\t\t{\n\t\t\treturn this->module->getOrCreateFunction(fir::Name::of(\"printf\"),\n\t\t\t\tfir::FunctionType::getCVariadicFunc({ fir::Type::getInt8Ptr() }, fir::Type::getInt32()), fir::LinkageType::External);\n\t\t}\n\t\telse if(name == \"abort\")\n\t\t{\n\t\t\treturn this->module->getOrCreateFunction(fir::Name::of(\"abort\"),\n\t\t\t\tfir::FunctionType::get({ }, fir::Type::getVoid()), fir::LinkageType::External);\n\t\t}\n\t\telse if(name == \"exit\")\n\t\t{\n\t\t\treturn this->module->getOrCreateFunction(fir::Name::of(\"exit\"),\n\t\t\t\tfir::FunctionType::get({ fir::Type::getInt32() }, fir::Type::getVoid()), fir::LinkageType::External);\n\t\t}\n\t\telse if(name == \"strlen\")\n\t\t{\n\t\t\treturn this->module->getOrCreateFunction(fir::Name::of(\"strlen\"),\n\t\t\t\tfir::FunctionType::get({ fir::Type::getInt8Ptr() }, fir::Type::getNativeWord()), fir::LinkageType::External);\n\t\t}\n\t\telse if(name == \"fprintf\")\n\t\t{\n\t\t\treturn this->module->getOrCreateFunction(fir::Name::of(\"fprintf\"),\n\t\t\t\tfir::FunctionType::getCVariadicFunc({ fir::Type::getVoidPtr(), fir::Type::getInt8Ptr() }, fir::Type::getInt32()), fir::LinkageType::External);\n\t\t}\n\t\telse if(name == \"fflush\")\n\t\t{\n\t\t\treturn this->module->getOrCreateFunction(fir::Name::of(\"fflush\"),\n\t\t\t\tfir::FunctionType::get({ fir::Type::getVoidPtr() }, fir::Type::getInt32()), fir::LinkageType::External);\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(\"enotsup: %s\", name);\n\t\t}\n\t}\n\n\n\n\n\tbool CodegenState::isWithinGlobalInitFunction()\n\t{\n\t\treturn this->isInsideGlobalInitFunc;\n\t}\n\n\tfir::IRBlock* CodegenState::enterGlobalInitFunction(fir::GlobalValue* val)\n\t{\n\t\tif(this->isInsideGlobalInitFunc)\n\t\t\terror(this->loc(), \"unsynchronised use of global init function!!! (entering when already inside)\");\n\n\t\tauto ret = this->irb.getCurrentBlock();\n\n\t\t{\n\t\t\tfir::Function* func = this->module->getOrCreateFunction(\n\t\t\t\tfir::Name::obfuscate(zpr::sprint(\"%s_piece_%d\", strs::names::GLOBAL_INIT_FUNCTION, this->globalInitPieces.size())),\n\t\t\t\tfir::FunctionType::get({ }, fir::Type::getVoid()), fir::LinkageType::Internal);\n\n\t\t\tauto b = this->irb.addNewBlockInFunction(\"b\", func);\n\t\t\tthis->irb.setCurrentBlock(b);\n\n\t\t\tthis->globalInitPieces.push_back(std::make_pair(val, func));\n\t\t}\n\n\t\tthis->isInsideGlobalInitFunc = true;\n\t\treturn ret;\n\t}\n\n\tvoid CodegenState::leaveGlobalInitFunction(fir::IRBlock* restore)\n\t{\n\t\tif(!this->isInsideGlobalInitFunc)\n\t\t\terror(this->loc(), \"unsynchronised use of global init function!!! (leaving when not inside)\");\n\n\t\t// terminate the current function.\n\t\tthis->irb.ReturnVoid();\n\n\t\tthis->irb.setCurrentBlock(restore);\n\t\tthis->isInsideGlobalInitFunc = false;\n\t}\n\n\tvoid CodegenState::finishGlobalInitFunction()\n\t{\n\t\tif(this->finalisedGlobalInitFunction != 0)\n\t\t{\n\t\t\t// clear all the blocks from it.\n\t\t\tfor(auto b : this->finalisedGlobalInitFunction->getBlockList())\n\t\t\t\tdelete b;\n\n\t\t\tthis->finalisedGlobalInitFunction->getBlockList().clear();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthis->finalisedGlobalInitFunction = this->module->getOrCreateFunction(\n\t\t\t\tfir::Name::obfuscate(strs::names::GLOBAL_INIT_FUNCTION),\n\t\t\t\tfir::FunctionType::get({ }, fir::Type::getVoid()), fir::LinkageType::Internal);\n\t\t}\n\n\t\tauto restore = this->irb.getCurrentBlock();\n\n\t\t// ok, now we can do some stuff.\n\t\t// what we wanna do is just call all the \"piece\" global init functions that we made with enter/leave.\n\t\t// but, this function has no blocks (either cos it's new, or we deleted them all). so, make one.\n\t\tauto blk = this->irb.addNewBlockInFunction(\"entry\", this->finalisedGlobalInitFunction);\n\t\tthis->irb.setCurrentBlock(blk);\n\n\t\tfor(auto piece : this->globalInitPieces)\n\t\t\tthis->irb.Call(piece.second);\n\n\t\t// ok now return\n\t\tthis->irb.ReturnVoid();\n\t\tthis->irb.setCurrentBlock(restore);\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/constructor.cpp",
    "content": "// constructor.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"codegen.h\"\n#include \"memorypool.h\"\n\nfir::Value* cgn::CodegenState::getConstructedStructValue(fir::StructType* str, const std::vector<FnCallArgument>& args)\n{\n\tfir::Value* value = this->irb.CreateValue(str);\n\n\t// set the arguments.\n\tif(args.size() > 0)\n\t{\n\t\tbool names = !args[0].name.empty();\n\n\t\t// i just keeps track of the index in case we're not using names.\n\t\tsize_t i = 0;\n\t\tfor(const auto& arg : args)\n\t\t{\n\t\t\tif(names)\n\t\t\t{\n\t\t\t\ticeAssert(str->hasElementWithName(arg.name));\n\t\t\t\tauto elmty = str->getElement(arg.name);\n\n\t\t\t\tvalue = this->irb.InsertValueByName(value, arg.name, arg.value->codegen(this, elmty).value);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ticeAssert(str->getElementCount() > i);\n\t\t\t\tauto elmty = str->getElementN(i);\n\n\t\t\t\tvalue = this->irb.InsertValue(value, { i }, arg.value->codegen(this, elmty).value);\n\t\t\t}\n\n\t\t\ti++;\n\t\t}\n\t}\n\n\tif(fir::isRefCountedType(str))\n\t\tthis->addRefCountedValue(value);\n\n\treturn value;\n}\n\n\n\nfir::Value* cgn::CodegenState::constructClassWithArguments(fir::ClassType* cls, sst::FunctionDefn* constr, const std::vector<FnCallArgument>& args)\n{\n\tif(auto c = this->typeDefnMap[cls])\n\t\tc->codegen(this);\n\n\tauto initfn = cls->getInlineInitialiser();\n\ticeAssert(initfn);\n\n\tauto constrfn = dcast(fir::Function, constr->codegen(this, cls).value);\n\ticeAssert(constrfn);\n\n\t// this is dirty, very fucking dirty!!!\n\tstd::vector<fir::Value*> vargs;\n\t{\n\t\tauto copy = args;\n\t\tauto fake = util::pool<sst::RawValueExpr>(this->loc(), cls->getMutablePointerTo());\n\t\tfake->rawValue = CGResult(fir::ConstantValue::getZeroValue(cls->getMutablePointerTo()));\n\n\t\t//? what we are doing here is inserting a fake argument to placate `codegenAndArrangeFunctionCallArguments`, so that\n\t\t//? it does not error. this just allows us to get *THE REST* of the values in the correct order and generated appropriately,\n\t\t//? so that we can use their values and get their types below.\n\n\t\tcopy.insert(copy.begin(), FnCallArgument(this->loc(), \"this\", fake, 0));\n\t\tvargs = this->codegenAndArrangeFunctionCallArguments(constr, constrfn->getType(), copy);\n\n\t\t// for sanity, assert that it did not change. We should not have to cast anything, and \"this\" is always the first\n\t\t// argument in a constructor anyway!\n\t\ticeAssert(vargs[0] == fake->rawValue.value);\n\n\t\t// after we are done with that shennanigans, erase the first thing, which is the 'this', which doesn't really\n\t\t// exist here!\n\t\tvargs.erase(vargs.begin());\n\t}\n\n\n\t// make a wrapper...\n\tauto fname = fir::Name::obfuscate(\"init_wrapper\", constr->id.str());\n\tfir::Function* wrapper_func = this->module->getFunction(fname);\n\n\tif(!wrapper_func)\n\t{\n\t\tauto restore = this->irb.getCurrentBlock();\n\n\t\tauto arglist = zfu::map(vargs, [](fir::Value* v) -> auto {\n\t\t\treturn v->getType();\n\t\t});\n\n\t\twrapper_func = this->module->getOrCreateFunction(fname, fir::FunctionType::get(arglist, cls), fir::LinkageType::Internal);\n\n\t\tfir::IRBlock* entry = this->irb.addNewBlockInFunction(\"entry\", wrapper_func);\n\t\tthis->irb.setCurrentBlock(entry);\n\n\t\t// make the self:\n\t\tauto selfptr = this->irb.StackAlloc(cls, \"self\");\n\n\t\tstd::vector<fir::Value*> argvals = zfu::map(wrapper_func->getArguments(), [](auto a) -> fir::Value* {\n\t\t\treturn a;\n\t\t});\n\n\t\targvals.insert(argvals.begin(), selfptr);\n\n\t\tthis->irb.Call(initfn, selfptr);\n\n\t\tthis->irb.Call(constrfn, argvals);\n\t\tthis->irb.Return(this->irb.ReadPtr(selfptr));\n\n\t\tthis->irb.setCurrentBlock(restore);\n\t}\n\n\tif(vargs.size() != wrapper_func->getArgumentCount())\n\t{\n\t\tSimpleError::make(this->loc(), \"mismatched number of arguments in constructor call to class '%s'; expected %d, found %d instead\",\n\t\t\tcls, constrfn->getArgumentCount(), vargs.size())\n\t\t\t->append(SimpleError::make(MsgType::Note, constr->loc, \"constructor was defined here:\"))\n\t\t\t->postAndQuit();\n\t}\n\n\tauto ret = this->irb.Call(wrapper_func, vargs);\n\tthis->addRAIIValue(ret);\n\n\treturn ret;\n}\n\n\n\nCGResult sst::StructConstructorCall::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tthis->target->codegen(cs);\n\n\tif(!this->target)\n\t\terror(this, \"failed to find target type of constructor call\");\n\n\t//* note: we don't need an explicit thing telling us whether we should use names or not\n\t//* if the first argument has no name, then we're not using names; if it has a name, then we are\n\t//* and ofc expect consistency, but we should have already typechecked that previously.\n\n\tStructDefn* str = dcast(StructDefn, this->target);\n\tif(!str) error(this, \"non-struct type '%s' not supported in constructor call\", this->target->id.name);\n\n\t// great. now we just make the thing.\n\tfir::Value* value = cs->getConstructedStructValue(str->type->toStructType(), this->arguments);\n\n\treturn CGResult(value);\n}\n\n\n\n\n\n\nCGResult sst::ClassConstructorCall::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tthis->classty->codegen(cs);\n\n\tauto cls = this->classty->type->toClassType();\n\tauto ret = cs->constructClassWithArguments(cls, this->target, this->arguments);\n\n\tif(fir::isRefCountedType(cls))\n\t\tcs->addRefCountedValue(ret);\n\n\treturn CGResult(ret);\n}\n\n\n\nCGResult sst::BaseClassConstructorCall::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tthis->classty->codegen(cs);\n\n\tauto cls = this->classty->type;\n\tauto self = cs->getMethodSelf();\n\n\ticeAssert(self->getType()->isClassType());\n\n\tauto selfty = self->getType()->toClassType();\n\ticeAssert(selfty->getBaseClass());\n\n\tauto basety = selfty->getBaseClass();\n\n\t// just do it manually here: since we already have a self pointer, we can call the base class constructor function\n\t// directly. plus, we are not calling the inline initialiser also.\n\t{\n\t\tauto constrfn = dcast(fir::Function, this->target->codegen(cs, cls).value);\n\t\ticeAssert(constrfn);\n\n\t\tauto copy = this->arguments;\n\t\tauto selfptr = util::pool<RawValueExpr>(this->loc, selfty->getMutablePointerTo());\n\t\tselfptr->rawValue = CGResult(cs->irb.PointerTypeCast(cs->irb.AddressOf(cs->getMethodSelf(), /* mutable: */ true),\n\t\t\tbasety->getMutablePointerTo()));\n\n\t\tcopy.insert(copy.begin(), FnCallArgument(this->loc, \"this\", selfptr, 0));\n\n\t\tstd::vector<fir::Value*> vargs = cs->codegenAndArrangeFunctionCallArguments(this->target, constrfn->getType(), copy);\n\n\t\tcs->irb.Call(constrfn, vargs);\n\t}\n\n\treturn CGResult(0);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/controlflow.cpp",
    "content": "// controlflow.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"codegen.h\"\n#include \"gluecode.h\"\n\n// just a tmp thing\nstatic bool operator == (const sst::IfStmt::Case& a, const sst::IfStmt::Case& b)\n{\n\treturn (a.body == b.body && a.cond == b.cond && a.inits == b.inits);\n}\n\nCGResult sst::IfStmt::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tfir::IRBlock* mergeblk = 0;\n\tauto trueblk = cs->irb.addNewBlockAfter(\"trueCase-\" + this->loc.shortString(), cs->irb.getCurrentBlock());\n\n\tif(!this->elideMergeBlock)\n\t\tmergeblk = cs->irb.addNewBlockAfter(\"mergeCase-\" + this->loc.shortString(), trueblk);\n\n\telse\n\t\ticeAssert(this->elseCase);\n\n\tfir::IRBlock* elseblk = 0;\n\tif(this->elseCase)\telseblk = cs->irb.addNewBlockAfter(\"elseCase-\" + this->elseCase->loc.shortString(), trueblk);\n\telse\t\t\t\telseblk = mergeblk;\n\n\t// first we gotta do all the inits of all the cases first.\n\t// we're already in our own scope, so it shouldn't matter.\n\n\tfor(auto c : this->cases)\n\t\tfor(auto i : c.inits)\n\t\t\ti->codegen(cs);\n\n\t// at the current place, first do the cond.\n\ticeAssert(this->cases.size() > 0);\n\tfir::Value* firstCond = cs->oneWayAutocast(this->cases.front().cond->codegen(cs, fir::Type::getBool()).value, fir::Type::getBool());\n\ticeAssert(firstCond);\n\n\tif(!firstCond->getType()->isBoolType())\n\t\terror(this->cases.front().cond, \"non-boolean type '%s' cannot be used as a conditional\", firstCond->getType());\n\n\n\t// do a comparison\n\t// don't be stupid and cmp bool == true\n\tfir::Value* cmpRes = firstCond;\n\n\tauto restore = cs->irb.getCurrentBlock();\n\n\t//! ACHTUNG !\n\t//* we are not finished here; we will come back and insert an appropriate branch later.\n\n\n\t// now, then.\n\tcs->irb.setCurrentBlock(trueblk);\n\t{\n\t\tauto c = this->cases.front();\n\t\tc.body->codegen(cs);\n\n\t\tif(cs->irb.getCurrentBlock() != nullptr && !cs->irb.getCurrentBlock()->isTerminated())\n\t\t\tcs->irb.UnCondBranch(mergeblk);\n\t}\n\n\t// ok -- we don't really need to do it recursively, do we?\n\tauto remaining = std::vector<Case>(this->cases.begin() + 1, this->cases.end());\n\tif(remaining.size() > 0)\n\t{\n\t\t// this block serves the purpose of initialising the conditions and stuff\n\t\tauto falseblk = cs->irb.addNewBlockAfter(\"falseCase-\" + remaining[0].body->loc.shortString(), trueblk);\n\t\t{\n\t\t\t//* the patching -- if we have 'else-if' cases.\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tcs->irb.CondBranch(cmpRes, trueblk, falseblk);\n\t\t}\n\n\t\tcs->irb.setCurrentBlock(falseblk);\n\n\t\tfor(auto elif : remaining)\n\t\t{\n\t\t\tauto cond = cs->oneWayAutocast(elif.cond->codegen(cs, fir::Type::getBool()).value, fir::Type::getBool());\n\t\t\ticeAssert(cond);\n\n\t\t\tif(!cond->getType()->isBoolType())\n\t\t\t\terror(elif.cond, \"non-boolean type '%s' cannot be used as a conditional\", cond->getType());\n\n\t\t\t// ok\n\t\t\tauto trueblk = cs->irb.addNewBlockAfter(\"trueCase-\" + elif.body->loc.shortString(), cs->irb.getCurrentBlock());\n\t\t\tfir::IRBlock* falseblkr = 0;\n\t\t\tif(elif == remaining.back())    falseblkr = elseblk;\n\t\t\telse                            falseblkr = cs->irb.addNewBlockAfter(\"falseCase-\" + elif.body->loc.shortString(), cs->irb.getCurrentBlock());\n\n\t\t\tfir::Value* cmpr = cond;\n\n\t\t\tcs->irb.CondBranch(cmpr, trueblk, falseblkr);\n\n\n\t\t\tcs->irb.setCurrentBlock(trueblk);\n\t\t\t{\n\t\t\t\telif.body->codegen(cs);\n\n\t\t\t\tif(!cs->irb.getCurrentBlock()->isTerminated())\n\t\t\t\t\tcs->irb.UnCondBranch(mergeblk);\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(falseblkr);\n\t\t\t{\n\t\t\t\t// TODO: why tf is this commented out??\n\n\t\t\t\t// ok, do the next thing.\n\t\t\t\t// if we're the last block, then gtfo and branch to merge\n\t\t\t\t// if()\n\t\t\t\t// {\n\t\t\t\t// \tif(!cs->irb.getCurrentBlock()->isTerminated())\n\t\t\t\t// \t\tcs->irb.UnCondBranch(elseblk);\n\n\t\t\t\t// \tbreak;\n\t\t\t\t// }\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\t//* the patching -- if we have no 'else-if' cases.\n\t\tcs->irb.setCurrentBlock(restore);\n\t\tcs->irb.CondBranch(cmpRes, trueblk, elseblk);\n\t}\n\n\n\tcs->irb.setCurrentBlock(elseblk);\n\t{\n\t\tif(this->elseCase)\n\t\t\tthis->elseCase->codegen(cs);\n\n\t\tif(elseblk != mergeblk && !cs->irb.getCurrentBlock()->isTerminated())\n\t\t\tcs->irb.UnCondBranch(mergeblk);\n\t}\n\n\tif(mergeblk) cs->irb.setCurrentBlock(mergeblk);\n\n\t// if we were supposed to elide the merge block, it means we have no more stuff after us.\n\t// tell our parent block this -- so that it can skip any extraneous codegen, eg:\n\t// fn x() { if true { return } else { return } return }\n\t// the last 'return' will cause a problem in IR generation if we don't skip it.\n\n\treturn CGResult(0, this->elideMergeBlock ? CGResult::VK::EarlyOut : CGResult::VK::Normal);\n}\n\nstd::vector<sst::Block*> sst::IfStmt::getBlocks()\n{\n\tstd::vector<sst::Block*> ret;\n\tfor(auto c : this->cases)\n\t\tret.push_back(c.body);\n\n\tif(this->elseCase)\n\t\tret.push_back(this->elseCase);\n\n\treturn ret;\n}\n\n\n\n\n\n\n\n\n\n\n\nstatic void doBlockEndThings(cgn::CodegenState* cs, const cgn::ControlFlowPoint& cfp, const cgn::BlockPoint& bp)\n{\n\t#if DEBUG_ARRAY_REFCOUNTING | DEBUG_STRING_REFCOUNTING\n\t{\n\t\tcs->printIRDebugMessage(\"\\n! CTRLFLOW: at: \" + cfp.block->loc.shortString() + \"\\n{\", { });\n\t\tcs->pushIRDebugIndentation();\n\t}\n\t#endif\n\n\t// then do the defers\n\tfor(auto stmt : cfp.block->deferred)\n\t\tstmt->_codegen(cs);\n\n\tfor(auto c : bp.raiiValues)\n\t\tcs->callDestructor(c);\n\n\tfor(auto v : bp.refCountedValues)\n\t\tcs->decrementRefCount(v);\n\n\t#if DEBUG_ARRAY_REFCOUNTING | DEBUG_STRING_REFCOUNTING\n\t{\n\t\tcs->popIRDebugIndentation();\n\t\tcs->printIRDebugMessage(\"}\", { });\n\t}\n\t#endif\n}\n\nCGResult sst::BreakStmt::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tauto bp = cs->getCurrentCFPoint().breakPoint;\n\ticeAssert(bp);\n\n\t// do the necessary\n\tdoBlockEndThings(cs, cs->getCurrentCFPoint(), cs->getCurrentBlockPoint());\n\tcs->irb.UnCondBranch(bp);\n\n\treturn CGResult(0, CGResult::VK::EarlyOut);\n}\n\nCGResult sst::ContinueStmt::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tauto cp = cs->getCurrentCFPoint().continuePoint;\n\ticeAssert(cp);\n\n\t// do the necessary\n\tdoBlockEndThings(cs, cs->getCurrentCFPoint(), cs->getCurrentBlockPoint());\n\tcs->irb.UnCondBranch(cp);\n\n\treturn CGResult(0, CGResult::VK::EarlyOut);\n}\n\n\n\nCGResult sst::ReturnStmt::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\t// check if we have a value, and whether it's refcounted\n\t// if so, inflate its refcount so it doesn't get deallocated and can survive\n\n\tif(this->value)\n\t{\n\t\tauto v = this->value->codegen(cs, this->expectedType).value;\n\t\tif(fir::isRefCountedType(v->getType()))\n\t\t\tcs->incrementRefCount(v);\n\n\t\tif(v->getType() != this->expectedType)\n\t\t\tv = cs->oneWayAutocast(v, this->expectedType);\n\n\t\t//! RAII: COPY CONSTRUCTOR CALL\n\t\t//? the copy constructor is called when a function returns an object by value\n\t\tif(v->getType()->isClassType())\n\t\t\tv = cs->copyRAIIValue(v);\n\n\t\tdoBlockEndThings(cs, cs->getCurrentCFPoint(), cs->getCurrentBlockPoint());\n\n\t\tcs->irb.Return(v);\n\t}\n\telse\n\t{\n\t\tdoBlockEndThings(cs, cs->getCurrentCFPoint(), cs->getCurrentBlockPoint());\n\n\t\ticeAssert(this->expectedType->isVoidType());\n\t\tcs->irb.ReturnVoid();\n\t}\n\n\treturn CGResult(0, CGResult::VK::EarlyOut);\n}\n\n\n\n\n\n\nCGResult sst::Block::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tcs->enterBlock(this);\n\tdefer(cs->leaveBlock());\n\n\tif(this->preBodyCode)\n\t\tthis->preBodyCode();\n\n\tbool broke = false;\n\tfor(auto stmt : this->statements)\n\t{\n\t\tauto res = stmt->codegen(cs);\n\t\tif(res.kind == CGResult::VK::EarlyOut)\n\t\t{\n\t\t\tbroke = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif(this->postBodyCode)\n\t\tthis->postBodyCode();\n\n\t// the reason we check for !broke here before doing the block cleanup is because BreakStmt\n\t// and ContinueStmt will do it too.\n\tif(!broke)\n\t{\n\t\t#if DEBUG_ARRAY_REFCOUNTING | DEBUG_STRING_REFCOUNTING\n\t\t{\n\t\t\tcs->printIRDebugMessage(\"\\n! BLOCKEND: at: \" + this->closingBrace.shortString() + \"\\n{\", { });\n\t\t\tcs->pushIRDebugIndentation();\n\t\t}\n\t\t#endif\n\n\t\t//* this duplicates stuff from doBlockEndThings!!\n\t\tfor(auto it = this->deferred.rbegin(); it != this->deferred.rend(); it++)\n\t\t\t(*it)->_codegen(cs);\n\n\t\tfor(auto c : cs->getCurrentBlockPoint().raiiValues)\n\t\t\tcs->callDestructor(c);\n\n\t\tfor(auto v : cs->getRefCountedValues())\n\t\t\tcs->decrementRefCount(v);\n\n\t\t#if DEBUG_ARRAY_REFCOUNTING | DEBUG_STRING_REFCOUNTING\n\t\t{\n\t\t\tcs->popIRDebugIndentation();\n\t\t\tcs->printIRDebugMessage(\"}\", { });\n\t\t}\n\t\t#endif\n\t}\n\n\treturn CGResult(0);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/destructure.cpp",
    "content": "// destructure.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"codegen.h\"\n#include \"gluecode.h\"\n#include \"memorypool.h\"\n\n\nCGResult sst::DecompDefn::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tcs->generateDecompositionBindings(this->bindings, this->init->codegen(cs), true);\n\n\treturn CGResult(0);\n}\n\n\n\n\nstatic void handleDefn(cgn::CodegenState* cs, sst::VarDefn* defn, CGResult res)\n{\n\t// do a quick check for refcounting.\n\t//* note: due to the way vardefn codegen works, if we're assigning from an rvalue and the type is refcounted,\n\t//* we simply remove the rhs from the refcounting stack instead of changing refcounts around.\n\t//* so, since everything that we generate from destructuring is an rvalue, we always need to remove it.\n\n\t//* thus in order to remove it, we must first insert it.\n\n\t//* also, since the vardefn adds itself to the counting stack, when it dies we will get decremented.\n\t//* however, this cannot be allowed to happen, because we want a copy and not a move.\n\tif(fir::isRefCountedType(res->getType()))\n\t{\n\t\tcs->addRefCountedValue(res.value);\n\t\tcs->incrementRefCount(res.value);\n\t}\n\n\tif(defn)\n\t{\n\t\tauto v = util::pool<sst::RawValueExpr>(defn->loc, res.value->getType());\n\t\tv->rawValue = res;\n\n\t\tdefn->init = v;\n\t\tdefn->codegen(cs);\n\t}\n}\n\nstatic void checkTuple(cgn::CodegenState* cs, const DecompMapping& bind, CGResult rhs)\n{\n\ticeAssert(!bind.array);\n\n\tauto rt = rhs.value->getType();\n\ticeAssert(rt->isTupleType());\n\n\tauto tty = rt->toTupleType();\n\ticeAssert(bind.inner.size() == tty->getElementCount());\n\n\tfor(size_t i = 0; i < tty->getElementCount(); i++)\n\t{\n\t\tCGResult v;\n\n\t\tif(rhs->islvalue())\n\t\t{\n\t\t\tauto gep = cs->irb.StructGEP(rhs.value, i);\n\t\t\tv = CGResult(gep);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tv = CGResult(cs->irb.ExtractValue(rhs.value, { i }));\n\t\t}\n\n\t\tcs->generateDecompositionBindings(bind.inner[i], v, true);\n\t}\n}\n\nstatic void checkArray(cgn::CodegenState* cs, const DecompMapping& bind, CGResult rhs)\n{\n\ticeAssert(bind.array);\n\n\tauto rt = rhs.value->getType();\n\tbool shouldSliceBeMutable = sst::getMutabilityOfSliceOfType(rt);\n\n\tif(!rt->isArrayType() && !rt->isDynamicArrayType() && !rt->isArraySliceType() && !rt->isStringType())\n\t\terror(bind.loc, \"expected array type in destructuring declaration; found type '%s' instead\", rt);\n\n\tif(rt->isStringType())\n\t{\n\t\t// do a bounds check.\n\t\tauto numbinds = fir::ConstantInt::getNative(bind.inner.size());\n\t\t{\n\t\t\tauto checkf = cgn::glue::string::getBoundsCheckFunction(cs, true);\n\t\t\tif(checkf)\n\t\t\t{\n\t\t\t\tauto strloc = fir::ConstantCharSlice::get(bind.loc.toString());\n\t\t\t\tcs->irb.Call(checkf, cs->irb.GetSAALength(rhs.value), numbinds, strloc);\n\t\t\t}\n\t\t}\n\n\t\t//* note: special-case this, because 1. we want to return chars\n\t\tauto strdat = cs->irb.PointerTypeCast(cs->irb.GetSAAData(rhs.value), fir::Type::getMutInt8Ptr());\n\t\t{\n\t\t\tsize_t idx = 0;\n\t\t\tfor(auto& b : bind.inner)\n\t\t\t{\n\t\t\t\tauto v = CGResult(cs->irb.ReadPtr(cs->irb.GetPointer(strdat, fir::ConstantInt::getNative(idx))));\n\t\t\t\tcs->generateDecompositionBindings(b, v, false);\n\n\t\t\t\tidx++;\n\t\t\t}\n\t\t}\n\n\t\tif(!bind.restName.empty())\n\t\t{\n\t\t\tif(bind.restRef)\n\t\t\t{\n\t\t\t\t// make a slice of char.\n\t\t\t\tauto remaining = cs->irb.Subtract(cs->irb.GetSAALength(rhs.value), numbinds);\n\n\t\t\t\tauto slice = cs->irb.CreateValue(fir::Type::getCharSlice(shouldSliceBeMutable));\n\t\t\t\tslice = cs->irb.SetArraySliceData(slice, cs->irb.GetPointer(strdat, numbinds));\n\t\t\t\tslice = cs->irb.SetArraySliceLength(slice, remaining);\n\n\t\t\t\thandleDefn(cs, bind.restDefn, CGResult(slice));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// make string.\n\t\t\t\t// auto remaining = cs->irb.Subtract(cs->irb.GetSAALength(rhs.value), numbinds);\n\n\t\t\t\tauto clonef = cgn::glue::string::getCloneFunction(cs);\n\t\t\t\ticeAssert(clonef);\n\n\t\t\t\tauto string = cs->irb.Call(clonef, rhs.value, numbinds);\n\n\t\t\t\thandleDefn(cs, bind.restDefn, CGResult(string));\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tauto array = rhs.value;\n\t\tfir::Value* arrlen = 0;\n\n\t\tauto numbinds = fir::ConstantInt::getNative(bind.inner.size());\n\t\t{\n\t\t\tif(rt->isArrayType())               arrlen = fir::ConstantInt::getNative(rt->toArrayType()->getArraySize());\n\t\t\telse if(rt->isArraySliceType())     arrlen = cs->irb.GetArraySliceLength(array);\n\t\t\telse if(rt->isDynamicArrayType())   arrlen = cs->irb.GetSAALength(array);\n\t\t\telse                                iceAssert(0);\n\n\t\t\t//* note: 'true' means we're performing a decomposition, so print a more appropriate error message on bounds failure.\n\t\t\tauto checkf = cgn::glue::array::getBoundsCheckFunction(cs, true);\n\t\t\tif(checkf)\n\t\t\t{\n\t\t\t\tauto strloc = fir::ConstantCharSlice::get(bind.loc.toString());\n\t\t\t\tcs->irb.Call(checkf, arrlen, numbinds, strloc);\n\t\t\t}\n\t\t}\n\n\t\t// # if 0\n\t\tif(!rhs->islvalue() && rt->isArrayType())\n\t\t{\n\t\t\t//* because of the way LLVM is designed, and hence by extension how we are designed,\n\t\t\t//* fixed-sized arrays are kinda dumb. If we don't have a pointer to the array (for whatever reason???),\n\t\t\t//* then we can't do a GEP access, and hence can't get a pointer to use for the 'rest' binding. So,\n\t\t\t//* we error on that case but allow binding the rest.\n\n\t\t\t//* theoretically if the compiler is well designed we should never hit this case, but who knows?\n\n\t\t\tsize_t idx = 0;\n\t\t\tfor(auto& b : bind.inner)\n\t\t\t{\n\t\t\t\tauto v = CGResult(cs->irb.ExtractValue(array, { idx }));\n\t\t\t\tcs->generateDecompositionBindings(b, v, false);\n\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\twarn(bind.loc, \"destructure of array without pointer (shouldn't happen!)\");\n\t\t\tif(!bind.restName.empty())\n\t\t\t\terror(bind.loc, \"could not get pointer to array (of type '%s') to create binding for '...'\", rt);\n\t\t}\n\t\telse\n\t\t// #endif\n\n\t\t{\n\t\t\tfir::Value* data = 0;\n\n\t\t\tif(rt->isArrayType())               data = cs->irb.ConstGEP2(rhs.value, 0, 0);\n\t\t\telse if(rt->isArraySliceType())     data = cs->irb.GetArraySliceData(array);\n\t\t\telse if(rt->isDynamicArrayType())   data = cs->irb.GetSAAData(array);\n\t\t\telse                                iceAssert(0);\n\n\n\t\t\tsize_t idx = 0;\n\t\t\tfor(auto& b : bind.inner)\n\t\t\t{\n\t\t\t\tauto ptr = cs->irb.GetPointer(data, fir::ConstantInt::getNative(idx));\n\n\t\t\t\tauto v = CGResult(cs->irb.Dereference(ptr));\n\t\t\t\tcs->generateDecompositionBindings(b, v, true);\n\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tif(!bind.restName.empty())\n\t\t\t{\n\t\t\t\tif(bind.restRef)\n\t\t\t\t{\n\t\t\t\t\tauto sty = fir::ArraySliceType::get(rt->getArrayElementType(), shouldSliceBeMutable);\n\n\t\t\t\t\tauto remaining = cs->irb.Subtract(arrlen, numbinds);\n\n\t\t\t\t\tauto slice = cs->irb.CreateValue(sty);\n\t\t\t\t\tslice = cs->irb.SetArraySliceData(slice, cs->irb.GetPointer(data, numbinds));\n\t\t\t\t\tslice = cs->irb.SetArraySliceLength(slice, remaining);\n\n\t\t\t\t\thandleDefn(cs, bind.restDefn, CGResult(slice));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// always return a dynamic array here.\n\t\t\t\t\t//* note: in order to make our lives somewhat easier, for fixed arrays, we create a fake slice pointing to its data, then we\n\t\t\t\t\t//* call clone on that instead.\n\n\t\t\t\t\tfir::Value* clonee = 0;\n\t\t\t\t\tif(rt->isArrayType())\n\t\t\t\t\t{\n\t\t\t\t\t\tclonee = cs->irb.CreateValue(fir::ArraySliceType::get(rt->getArrayElementType(), shouldSliceBeMutable));\n\t\t\t\t\t\tclonee = cs->irb.SetArraySliceData(clonee, data);\n\t\t\t\t\t\tclonee = cs->irb.SetArraySliceLength(clonee, fir::ConstantInt::getNative(rt->toArrayType()->getArraySize()));\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tclonee = array;\n\t\t\t\t\t}\n\n\t\t\t\t\tauto clonef = cgn::glue::array::getCloneFunction(cs, clonee->getType());\n\t\t\t\t\ticeAssert(clonef);\n\n\t\t\t\t\tauto ret = cs->irb.Call(clonef, clonee, numbinds);\n\n\t\t\t\t\thandleDefn(cs, bind.restDefn, CGResult(ret));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid cgn::CodegenState::generateDecompositionBindings(const DecompMapping& bind, CGResult rhs, bool allowref)\n{\n\tauto rt = rhs.value->getType();\n\n\tif(!bind.name.empty())\n\t{\n\t\tif(bind.ref && !allowref)\n\t\t\terror(bind.loc, \"cannot bind to value of type '%s' by reference\", rt);\n\n\t\tif(bind.ref)\n\t\t{\n\t\t\trhs.value = this->irb.AddressOf(rhs.value, false);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// rhs.value = this->irb.Dereference(rhs.value);\n\t\t}\n\n\t\thandleDefn(this, bind.createdDefn, rhs);\n\t}\n\telse if(bind.array)\n\t{\n\t\tcheckArray(this, bind, rhs);\n\t}\n\telse\n\t{\n\t\tcheckTuple(this, bind, rhs);\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/directives.cpp",
    "content": "// directives.cpp\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include <memory>\n\n#include \"sst.h\"\n#include \"codegen.h\"\n#include \"platform.h\"\n\n#include \"ir/interp.h\"\n\n#include \"memorypool.h\"\n\nfir::ConstantValue* magicallyRunExpressionAtCompileTime(cgn::CodegenState* cs, sst::Stmt* stmt, fir::Type* infer,\n\tconst fir::Name& fname, fir::interp::InterpState* is = 0)\n{\n\t// what we do is to make a new function in IR, set the insertpoint to that,\n\t// then run codegen on the expression (so it generates inside), restore the insertpoint,\n\t// then run the interpreter on that function (after compiling it), then get the interp::Value\n\t// result, make a constantvalue with it\n\n\n\tauto restore = cs->irb.getCurrentBlock();\n\n\tbool isExpr = false;\n\tfir::Type* retty = 0;\n\tif(auto ex = dcast(sst::Expr, stmt); ex)    isExpr = true, retty = ex->type;\n\telse                                        retty = fir::Type::getVoid();\n\n\tauto fn = cs->module->getOrCreateFunction(fname, fir::FunctionType::get({ }, retty), fir::LinkageType::Internal);\n\n\ticeAssert(fn);\n\ticeAssert(stmt);\n\n\t// make the function:\n\t{\n\t\tauto entry = cs->irb.addNewBlockInFunction(\"entry\", fn);\n\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t// we need a block, even though we don't codegen -- this is to handle raii/refcounting things.\n\t\t// stack allocate, so we can get rid of it later. (automatically)\n\t\tauto fakeBlk = sst::Block(Location());\n\t\tcs->enterBlock(&fakeBlk);\n\n\t\tfir::Value* ret = 0;\n\n\t\tif(isExpr)  ret = stmt->codegen(cs, infer).value;\n\t\telse        stmt->codegen(cs, infer);\n\n\t\tif(!ret || ret->getType()->isVoidType())\n\t\t\tcs->irb.ReturnVoid();\n\n\t\telse\n\t\t\tcs->irb.Return(ret);\n\n\n\t\tcs->leaveBlock();\n\n\t\tif(restore) cs->irb.setCurrentBlock(restore);\n\t}\n\n\t// finalise the global init function if necessary:\n\tcs->finishGlobalInitFunction();\n\n\t// run the function:\n\tfir::ConstantValue* ret = 0;\n\t{\n\t\t// this unique_ptr handles destructing the temporary interpState when we're done.\n\t\tusing unique_ptr_alias = std::unique_ptr<fir::interp::InterpState, std::function<void (fir::interp::InterpState*)>>;\n\t\tauto ptr = unique_ptr_alias();\n\t\tif(!is)\n\t\t{\n\t\t\tis = new fir::interp::InterpState(cs->module);\n\t\t\tis->initialise(/* runGlobalInit: */ true);\n\t\t\tptr = unique_ptr_alias(is, [](fir::interp::InterpState* is) {\n\t\t\t\tis->finalise();\n\t\t\t\tdelete is;\n\t\t\t});\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// new strategy: run the initialisers anyway.\n\t\t\tis->initialise(/* runGlobalInit: */ true);\n\n\t\t\t// caller code will finalise.\n\t\t}\n\n\t\tauto result = is->runFunction(is->compileFunction(fn), { });\n\n\t\tif(!retty->isVoidType())\n\t\t\tret = is->unwrapInterpValueIntoConstant(result);\n\t}\n\n\t// please get rid of the runner function\n\tcs->module->removeFunction(fn);\n\tdelete fn;\n\n\n\treturn ret;\n}\n\n\n\n\n\n\n\nstatic size_t runDirectiveId = 0;\nCGResult sst::RunDirective::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tsst::Stmt* toExec = 0;\n\tif(this->insideExpr)    toExec = this->insideExpr;\n\telse                    toExec = this->block;\n\n\tauto ret = magicallyRunExpressionAtCompileTime(cs, toExec, infer, fir::Name::obfuscate(\"run_directive\", runDirectiveId++));\n\n\treturn CGResult(ret);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/dotop.cpp",
    "content": "// dotops.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"errors.h\"\n#include \"codegen.h\"\n#include \"typecheck.h\"\n#include \"memorypool.h\"\n\n\nstatic bool isAutoDereferencable(fir::Type* t)\n{\n\treturn (t->isStructType() || t->isClassType() || t->isRawUnionType());\n}\n\nstatic CGResult getAppropriateValuePointer(cgn::CodegenState* cs, sst::Expr* user, sst::Expr* lhs, fir::Type** baseType)\n{\n\tauto res = lhs->codegen(cs);\n\tauto restype = res.value->getType();\n\n\tfir::Value* retv = 0;\n\n\tif(isAutoDereferencable(restype))\n\t{\n\t\tauto t = res.value->getType();\n\t\ticeAssert(isAutoDereferencable(t));\n\n\t\tretv = res.value;\n\t\t*baseType = restype;\n\t}\n\telse if(restype->isTupleType())\n\t{\n\t\tretv = res.value;\n\t\t*baseType = restype;\n\t}\n\telse if(restype->isPointerType() && isAutoDereferencable(restype->getPointerElementType()))\n\t{\n\t\ticeAssert(isAutoDereferencable(res.value->getType()->getPointerElementType()));\n\n\t\tretv = cs->irb.Dereference(res.value);\n\t\t*baseType = restype->getPointerElementType();\n\t}\n\telse\n\t{\n\t\terror(user, \"invalid type '%s' for instance dot op\", restype);\n\t}\n\n\treturn CGResult(retv);\n}\n\n\n\n\nCGResult sst::MethodDotOp::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\n\tif(auto fc = dcast(sst::FunctionCall, this->call))\n\t{\n\t\t// basically what we need to do is just get the pointer\n\t\tfir::Type* sty = 0;\n\t\tauto res = getAppropriateValuePointer(cs, this, this->lhs, &sty);\n\n\t\tif(!res->islvalue())\n\t\t{\n\t\t\tauto tmplval = cs->irb.CreateLValue(this->lhs->type);\n\t\t\tcs->irb.Store(res.value, tmplval);\n\n\t\t\tres.value = tmplval;\n\t\t\tres->makeConst();\n\t\t}\n\n\t\t// then we insert it as the first argument\n\t\tauto rv = util::pool<sst::RawValueExpr>(this->loc, res.value->getType()->getMutablePointerTo());\n\t\trv->rawValue = CGResult(cs->irb.AddressOf(res.value, true));\n\n\t\t//! SELF HANDLING (INSERTION) (CODEGEN)\n\t\tfc->arguments.insert(fc->arguments.begin(), FnCallArgument(this->loc, \"this\", rv, 0));\n\t\treturn fc->codegen(cs);\n\t}\n\telse if(auto ec = dcast(sst::ExprCall, this->call))\n\t{\n\t\treturn ec->codegen(cs);\n\t}\n\telse\n\t{\n\t\terror(this->call, \"what?\");\n\t}\n}\n\n\n\n\nCGResult sst::FieldDotOp::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tif(this->isMethodRef)\n\t\terror(\"method ref not supported\");\n\n\tfir::Type* sty = 0;\n\tauto res = getAppropriateValuePointer(cs, this, this->lhs, &sty);\n\n\t// TODO: clean up the code dupe here\n\tif(this->isTransparentField)\n\t{\n\t\ticeAssert(this->lhs->type->isRawUnionType() || this->lhs->type->isStructType());\n\t\tif(this->lhs->type->isRawUnionType())\n\t\t{\n\t\t\tfir::Value* field = 0;\n\t\t\tif(res->islvalue())\n\t\t\t{\n\t\t\t\tfield = cs->irb.GetRawUnionFieldByType(res.value, this->type);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto addr = cs->irb.ImmutStackAlloc(this->lhs->type, res.value);\n\t\t\t\tfield = cs->irb.GetRawUnionFieldByType(addr, this->type);\n\t\t\t}\n\n\t\t\treturn CGResult(field);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif(res->islvalue())\n\t\t\t{\n\t\t\t\t// ok, at this point it's just a normal, instance field.\n\t\t\t\treturn CGResult(cs->irb.StructGEP(res.value, this->indexOfTransparentField));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// use extractvalue.\n\t\t\t\treturn CGResult(cs->irb.ExtractValue(res.value, { this->indexOfTransparentField }));\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tif(this->lhs->type->isRawUnionType())\n\t\t{\n\t\t\tfir::Value* field = 0;\n\t\t\tif(res->islvalue())\n\t\t\t{\n\t\t\t\tfield = cs->irb.GetRawUnionField(res.value, this->rhsIdent);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto addr = cs->irb.ImmutStackAlloc(this->lhs->type, res.value);\n\t\t\t\tfield = cs->irb.GetRawUnionField(addr, this->rhsIdent);\n\t\t\t}\n\n\t\t\treturn CGResult(field);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif(res->islvalue())\n\t\t\t{\n\t\t\t\t// ok, at this point it's just a normal, instance field.\n\t\t\t\treturn CGResult(cs->irb.GetStructMember(res.value, this->rhsIdent));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// use extractvalue.\n\t\t\t\treturn CGResult(cs->irb.ExtractValueByName(res.value, this->rhsIdent));\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\nCGResult sst::TupleDotOp::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tfir::Type* _sty = 0;\n\tauto res = getAppropriateValuePointer(cs, this, this->lhs, &_sty);\n\n\tfir::TupleType* tty = _sty->toTupleType();\n\ticeAssert(tty);\n\n\t// make sure something didn't somehow manage to fuck up -- we should've checked this in the typechecker.\n\ticeAssert(this->index < tty->getElementCount());\n\n\t// ok, if we have a pointer, then return an lvalue\n\t// if not, return an rvalue\n\tif(res->islvalue())\n\t{\n\t\treturn CGResult(cs->irb.StructGEP(res.value, this->index));\n\t}\n\telse\n\t{\n\t\treturn CGResult(cs->irb.ExtractValue(res.value, { this->index }));\n\t}\n}\n\n\n\nCGResult cgn::CodegenState::getStructFieldImplicitly(std::string name)\n{\n\tfir::Value* self = this->getMethodSelf();\n\tauto ty = self->getType();\n\n\tauto dothing = [this, name, self](auto sty) -> auto {\n\n\t\tif(sty->hasElementWithName(name))\n\t\t{\n\t\t\t// ok -- return directly from here.\n\t\t\tfir::Value* ptr = this->irb.GetStructMember(self, name);\n\t\t\treturn CGResult(ptr);\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(this->loc(), \"type '%s' has no field named '%s'\", sty->getTypeName().str(), name);\n\t\t}\n\t};\n\n\tif(ty->isStructType())\n\t\treturn dothing(ty->toStructType());\n\n\telse if(ty->isClassType())\n\t\treturn dothing(ty->toClassType());\n\n\telse\n\t\terror(this->loc(), \"invalid self type '%s' for field named '%s'\", ty, name);\n}\n"
  },
  {
    "path": "source/codegen/enums.cpp",
    "content": "// enums.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"codegen.h\"\n\nCGResult sst::EnumDefn::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\ticeAssert(this->memberType);\n\n\t// make the runtime array\n\tauto values = std::vector<fir::ConstantValue*>(this->cases.size());\n\tauto names = std::vector<fir::ConstantValue*>(this->cases.size());\n\n\t// ok.\n\tfor(auto [ n, c ] : this->cases)\n\t{\n\t\t// do the case...? should we codegen this shit separately or what\n\t\tauto val = c->codegen(cs).value;\n\t\ticeAssert(val);\n\n\t\t// ok, then.\n\t\tauto cv = dcast(fir::ConstantValue, val);\n\t\ticeAssert(cv);\n\n\t\t// values[c->index] = fir::ConstantStruct(cv);\n\t\tnames[c->index] = fir::ConstantCharSlice::get(n);\n\t}\n\n\n\tauto et = this->type->toEnumType();\n\n\t// this is for the actual case\n\t{\n\t\t// auto array = fir::ConstantArray::get(fir::ArrayType::get(this->type, values.size()), values);\n\t\t// et->setCaseArray(cs->module->createGlobalVariable(Identifier(\"_FV_ENUM_ARR_\" + this->id.str(), IdKind::Name),\n\t\t// \tarray->getType(), array, true, fir::LinkageType::Internal));\n\t}\n\n\t// this is for the names... I guess?\n\t{\n\t\tauto array = fir::ConstantArray::get(fir::ArrayType::get(fir::Type::getCharSlice(false), names.size()), names);\n\t\tet->setNameArray(cs->module->createGlobalVariable(fir::Name::obfuscate(\"_FV_ENUM_NAME_ARR_\", this->id.str()),\n\t\t\tarray->getType(), array, true, fir::LinkageType::Internal));\n\t}\n\n\n\treturn CGResult(0);\n}\n\n\nCGResult sst::EnumCaseDefn::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tauto base = this->parentEnum->memberType;\n\n\tfir::Value* v = 0;\n\tif(this->val)\n\t{\n\t\tv = this->val->codegen(cs, base).value;\n\t\ticeAssert(v);\n\n\t\tif(dcast(fir::ConstantValue, v) == 0)\n\t\t\terror(this, \"enumeration case value ('%s' of type '%s') must be constant\", this->id.name, v->getType());\n\t}\n\telse\n\t{\n\t\tv = fir::ConstantInt::getNative(this->index);\n\t}\n\n\tthis->value = dcast(fir::ConstantValue, v);\n\n\t{\n\t\tauto ty = this->parentEnum->type;\n\t\tauto ret = fir::ConstantEnumCase::get(ty->toEnumType(), fir::ConstantInt::getNative(this->index), this->value);\n\n\t\tcs->valueMap[this] = CGResult(ret);\n\t}\n\n\treturn cs->valueMap[this];\n}\n\n\nCGResult sst::EnumDotOp::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\terror(\"unsupported\");\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/function.cpp",
    "content": "// function.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"defs.h\"\n#include \"sst.h\"\n#include \"codegen.h\"\n#include \"memorypool.h\"\n\n#include \"ir/irbuilder.h\"\n\nCGResult sst::FunctionDefn::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tif(this->type->containsPlaceholders())\n\t\treturn CGResult(0);\n\n\tstd::vector<fir::Type*> ptypes;\n\n\tfor(const auto& p : this->params)\n\t\tptypes.push_back(p.type);\n\n\tauto ft = fir::FunctionType::get(ptypes, this->returnType);\n\n\tauto ident = this->id;\n\tif(this->attrs.hasAny(attr::FN_ENTRYPOINT, attr::NO_MANGLE))\n\t\tident = Identifier(this->id.name, IdKind::Name);\n\n\tauto fn = cs->module->getOrCreateFunction(ident.convertToName(), ft,\n\t\tthis->visibility == VisibilityLevel::Private ? fir::LinkageType::Internal : fir::LinkageType::External);\n\n\t// manually set the names, I guess\n\t{\n\t\tfor(size_t i = 0; i < this->params.size(); i++)\n\t\t\tfn->getArguments()[i]->setName(this->params[i].name);\n\t}\n\n\n\t// special case for functions, to enable recursive calling:\n\t// set our cached result *before* we generate our body, in case we contain either\n\t// a: a call to ourselves, or\n\t// b: a call to someone that call us eventually\n\tthis->cachedResult = CGResult(fn);\n\n\tauto restore = cs->irb.getCurrentBlock();\n\tdefer(cs->irb.setCurrentBlock(restore));\n\n\tcs->enterFunction(fn);\n\tdefer(cs->leaveFunction());\n\n\tauto block = cs->irb.addNewBlockInFunction(this->id.name + \"_entry\", fn);\n\tcs->irb.setCurrentBlock(block);\n\n\tif(this->parentTypeForMethod)\n\t\tcs->enterMethodBody(fn, cs->irb.Dereference(fn->getArguments()[0]));\n\n\n\t// special thing here:\n\t// push a breakable block (ControlFlowPoint) so that a manual 'return' can know how to\n\t// do refcounting and deferred things.\n\n\tcs->enterBreakableBody(cgn::ControlFlowPoint(this->body, 0, 0));\n\t{\n\t\tthis->body->preBodyCode = [cs, this]() {\n\t\t\tfor(auto arg : this->arguments)\n\t\t\t\targ->codegen(cs);\n\t\t};\n\n\t\tthis->body->codegen(cs);\n\t}\n\tcs->leaveBreakableBody();\n\n\t// note that we *trust* in the typechecker\n\t// that all paths return the correct type.\n\n\n\tif(this->needReturnVoid)\n\t\tcs->irb.ReturnVoid();\n\n\tif(this->parentTypeForMethod)\n\t\tcs->leaveMethodBody();\n\n\tif(this->attrs.has(attr::FN_ENTRYPOINT))\n\t{\n\t\tif(cs->entryFunction.first != 0)\n\t\t{\n\t\t\tSimpleError::make(this->loc, \"redefinition of entry function with '@entry'\")\n\t\t\t\t->append(SimpleError::make(MsgType::Note, cs->entryFunction.second, \"previous entry function marked here:\"))\n\t\t\t\t->postAndQuit();\n\t\t}\n\n\t\tcs->entryFunction = { fn, this->loc };\n\t}\n\n\tcs->valueMap[this] = CGResult(fn);\n\treturn CGResult(fn);\n}\n\n\nCGResult sst::ForeignFuncDefn::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tfir::FunctionType* ft = 0;\n\tstd::vector<fir::Type*> ptypes;\n\tfor(const auto& p : this->params)\n\t\tptypes.push_back(p.type);\n\n\tif(this->isVarArg)\n\t\tft = fir::FunctionType::getCVariadicFunc(ptypes, this->returnType);\n\n\telse\n\t\tft = fir::FunctionType::get(ptypes, this->returnType);\n\n\tauto realId = Identifier(this->realName, IdKind::Name);\n\n\tauto ef = cs->module->getFunction(realId.convertToName());\n\tif(ef && ef->getType() != ft)\n\t{\n\t\terror(this, \"foreign function '%s' already defined elsewhere (with signature %s); overloading not possible\",\n\t\t\tthis->id.str(), ef->getType());\n\t}\n\n\tauto fn = cs->module->getOrCreateFunction(realId.convertToName(), ft, fir::LinkageType::External);\n\n\tif(this->isIntrinsic)\n\t\tfn->setIsIntrinsic();\n\n\tcs->valueMap[this] = CGResult(fn);\n\treturn CGResult(fn);\n}\n\n\n\n\nCGResult sst::ArgumentDefn::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tauto fn = cs->getCurrentFunction();\n\n\tauto arg = cs->irb.CreateLValue(this->type, this->id.name);\n\tcs->irb.Store(fn->getArgumentWithName(this->id.name), arg);\n\targ->makeConst();\n\n\tcs->addRAIIOrRCValueIfNecessary(arg);\n\n\t// ok...\n\tcs->valueMap[this] = CGResult(arg);\n\treturn CGResult(arg);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/glue/any.cpp",
    "content": "// any.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n\n#include \"codegen.h\"\n#include \"platform.h\"\n#include \"gluecode.h\"\n\nnamespace cgn {\nnamespace glue {\nnamespace any\n{\n\tstatic void _doRefCount(CodegenState* cs, fir::Function* func, bool decrement)\n\t{\n\t\tauto any = func->getArguments()[0];\n\t\tauto rcp = cs->irb.GetAnyRefCountPointer(any, \"rcp\");\n\n\t\tfir::IRBlock* merge = cs->irb.addNewBlockInFunction(\"merge\", func);\n\t\tfir::IRBlock* dorc = cs->irb.addNewBlockInFunction(\"dorc\", func);\n\n\t\tcs->irb.CondBranch(cs->irb.ICmpEQ(rcp, fir::ConstantValue::getZeroValue(fir::Type::getNativeWordPtr())),\n\t\t\tmerge, dorc);\n\n\t\tcs->irb.setCurrentBlock(dorc);\n\t\t{\n\t\t\tauto oldrc = cs->irb.ReadPtr(rcp, \"oldrc\");\n\t\t\tauto newrc = cs->irb.Add(oldrc, fir::ConstantInt::getNative(decrement ? -1 : 1));\n\n\t\t\tcs->irb.SetAnyRefCount(any, newrc);\n\n\t\t\t#if DEBUG_ANY_REFCOUNTING\n\t\t\t{\n\t\t\t\tstd::string x = decrement ? \"(decr)\" : \"(incr)\";\n\n\t\t\t\tcs->printIRDebugMessage(\"*    ANY: \" + x + \" - new rc of: (rcptr: %p) = %d\",\n\t\t\t\t\t{ cs->irb.GetAnyRefCountPointer(any), cs->irb.GetAnyRefCount(any) });\n\t\t\t}\n\t\t\t#endif\n\n\t\t\tif(decrement)\n\t\t\t{\n\t\t\t\tfir::IRBlock* dofree = cs->irb.addNewBlockInFunction(\"dofree\", func);\n\n\t\t\t\tauto cond = cs->irb.ICmpEQ(newrc, fir::ConstantInt::getNative(0));\n\n\t\t\t\t// this thing checks for the MSB of the typeid; if it's set, means we used heap memory and so we need to free.\n\t\t\t\tcond = cs->irb.BitwiseAND(cond,\n\t\t\t\t\tcs->irb.ICmpGT(cs->irb.BitwiseAND(cs->irb.GetAnyTypeID(any), fir::ConstantInt::getUNative(BUILTIN_ANY_FLAG_MASK)),\n\t\t\t\t\tfir::ConstantInt::getUNative(0)));\n\n\t\t\t\tcs->irb.CondBranch(cond, dofree, merge);\n\n\t\t\t\tcs->irb.setCurrentBlock(dofree);\n\t\t\t\t{\n\t\t\t\t\tauto freefn = cs->getOrDeclareLibCFunction(FREE_MEMORY_FUNC);\n\t\t\t\t\ticeAssert(freefn);\n\n\t\t\t\t\t//* because llvm is a little restrictive wrt. how we can fiddle with types and memory, in\n\t\t\t\t\t//* order to cast the data buffer (which is an array) to a i64*, we first get the array,\n\t\t\t\t\t//* then make a stack alloc, store the array value, use the alloc as an address and cast it\n\t\t\t\t\t//* to i64*, then dereference that to get the actual pointer to the heap memory.\n\n\t\t\t\t\t// 1. this gets us a memory location we can use.\n\t\t\t\t\tauto _buf = cs->irb.GetAnyData(any, \"buf\");\n\t\t\t\t\tauto buf = cs->irb.StackAlloc(_buf->getType());\n\t\t\t\t\tcs->irb.WritePtr(_buf, buf);\n\n\t\t\t\t\t// 2. 'buf' is a pointer to the array itself -- we cast it to i64*, so the dereference\n\t\t\t\t\t//    gives us the first 8 bytes of the data buffer.\n\t\t\t\t\tbuf = cs->irb.PointerTypeCast(buf, fir::Type::getNativeWordPtr());\n\n\t\t\t\t\t// 3. this is the dereference.\n\t\t\t\t\tauto ptr = cs->irb.ReadPtr(buf);\n\n\t\t\t\t\t// 4. the first 8 bytes are actually a pointer to the heap memory.\n\t\t\t\t\tptr = cs->irb.IntToPointerCast(ptr, fir::Type::getMutInt8Ptr());\n\n\t\t\t\t\tcs->irb.Call(freefn, ptr);\n\t\t\t\t\tcs->irb.Call(freefn, cs->irb.PointerTypeCast(cs->irb.GetAnyRefCountPointer(any), fir::Type::getMutInt8Ptr()));\n\n\t\t\t\t\t#if DEBUG_ANY_ALLOCATION\n\t\t\t\t\t{\n\t\t\t\t\t\tcs->printIRDebugMessage(\"*    ANY: free(): (ptr: %p / rcp: %p)\", {\n\t\t\t\t\t\t\tptr, cs->irb.GetAnyRefCountPointer(any) });\n\t\t\t\t\t}\n\t\t\t\t\t#endif\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcs->irb.UnCondBranch(merge);\n\t\t}\n\n\t\tcs->irb.setCurrentBlock(merge);\n\t\t{\n\t\t\tcs->irb.ReturnVoid();\n\t\t}\n\t}\n\n\n\n\n\tfir::Function* getRefCountIncrementFunction(CodegenState* cs)\n\t{\n\t\tauto fname = misc::getIncrRefcount_FName(fir::Type::getAny());\n\t\tfir::Function* retfn = cs->module->getFunction(fname);\n\n\t\tif(!retfn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ fir::Type::getAny() }, fir::Type::getVoid()), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\t_doRefCount(cs, func, false);\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tretfn = func;\n\t\t}\n\n\t\ticeAssert(retfn);\n\t\treturn retfn;\n\t}\n\n\tfir::Function* getRefCountDecrementFunction(CodegenState* cs)\n\t{\n\t\tauto fname = misc::getDecrRefcount_FName(fir::Type::getAny());\n\t\tfir::Function* retfn = cs->module->getFunction(fname);\n\n\t\tif(!retfn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ fir::Type::getAny() }, fir::Type::getVoid()), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\t_doRefCount(cs, func, true);\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tretfn = func;\n\t\t}\n\n\t\ticeAssert(retfn);\n\t\treturn retfn;\n\t}\n\n\n\n\tfir::Function* generateCreateAnyWithValueFunction(CodegenState* cs, fir::Type* type)\n\t{\n\t\tauto fname = misc::getCreateAnyOf_FName(type);\n\t\tfir::Function* retfn = cs->module->getFunction(fname);\n\n\t\tif(!retfn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ type }, fir::Type::getAny()), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\n\t\t\tauto any = cs->irb.CreateValue(fir::Type::getAny());\n\t\t\tauto dataarrty = fir::ArrayType::get(fir::Type::getInt8(), BUILTIN_ANY_DATA_BYTECOUNT);\n\n\t\t\t// make the refcount pointer.\n\t\t\tauto rcp = cs->irb.PointerTypeCast(cs->irb.Call(cs->getOrDeclareLibCFunction(ALLOCATE_MEMORY_FUNC),\n\t\t\t\tfir::ConstantInt::getNative(REFCOUNT_SIZE)), fir::Type::getNativeWordPtr());\n\n\t\t\tany = cs->irb.SetAnyRefCountPointer(any, rcp);\n\t\t\tcs->irb.SetAnyRefCount(any, fir::ConstantInt::getNative(1));\n\n\t\t\tsize_t tid = type->getID();\n\t\t\tif(auto typesz = fir::getSizeOfType(type); typesz > BUILTIN_ANY_DATA_BYTECOUNT)\n\t\t\t{\n\t\t\t\ttid |= BUILTIN_ANY_FLAG_MASK;\n\n\t\t\t\tauto ptr = cs->irb.PointerTypeCast(cs->irb.Call(cs->getOrDeclareLibCFunction(ALLOCATE_MEMORY_FUNC),\n\t\t\t\t\tfir::ConstantInt::getNative(typesz)), type->getMutablePointerTo());\n\n\t\t\t\t#if DEBUG_ANY_ALLOCATION\n\t\t\t\t{\n\t\t\t\t\tcs->printIRDebugMessage(\"*    ANY: alloc(): (id: %lu, ptr: %p / rcp: %p)\", {\n\t\t\t\t\t\tfir::ConstantInt::getUNative(tid), ptr, rcp });\n\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\tcs->irb.WritePtr(func->getArguments()[0], ptr);\n\t\t\t\tptr = cs->irb.PointerToIntCast(ptr, fir::Type::getNativeWord());\n\n\t\t\t\t// now, we make a fake data, and then store it.\n\t\t\t\tauto arrptr = cs->irb.StackAlloc(dataarrty);\n\t\t\t\tauto fakeptr = cs->irb.PointerTypeCast(arrptr, fir::Type::getNativeWordPtr()->getMutablePointerVersion());\n\t\t\t\tcs->irb.WritePtr(ptr, fakeptr);\n\n\t\t\t\tauto arr = cs->irb.ReadPtr(arrptr);\n\t\t\t\tany = cs->irb.SetAnyData(any, arr);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto arrptr = cs->irb.StackAlloc(dataarrty);\n\t\t\t\tauto fakeptr = cs->irb.PointerTypeCast(arrptr, type->getMutablePointerTo());\n\t\t\t\tcs->irb.WritePtr(func->getArguments()[0], fakeptr);\n\n\t\t\t\tauto arr = cs->irb.ReadPtr(arrptr);\n\t\t\t\tany = cs->irb.SetAnyData(any, arr);\n\n\n\t\t\t}\n\n\t\t\tany = cs->irb.SetAnyTypeID(any, fir::ConstantInt::getUNative(tid));\n\n\t\t\tcs->irb.Return(any);\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tretfn = func;\n\t\t}\n\n\t\ticeAssert(retfn);\n\t\treturn retfn;\n\t}\n\n\tfir::Function* generateGetValueFromAnyFunction(CodegenState* cs, fir::Type* type)\n\t{\n\t\tauto fname = misc::getGetValueFromAny_FName(type);\n\t\tfir::Function* retfn = cs->module->getFunction(fname);\n\n\t\tif(!retfn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ fir::Type::getAny() }, type), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\tauto any = func->getArguments()[0];\n\n\t\t\tauto dataarrty = fir::ArrayType::get(fir::Type::getInt8(), BUILTIN_ANY_DATA_BYTECOUNT);\n\t\t\tauto tid = cs->irb.BitwiseAND(cs->irb.GetAnyTypeID(any), fir::ConstantInt::getUNative(~BUILTIN_ANY_FLAG_MASK));\n\n\t\t\tfir::IRBlock* invalid = cs->irb.addNewBlockInFunction(\"invalid\", cs->irb.getCurrentFunction());\n\t\t\tfir::IRBlock* merge = cs->irb.addNewBlockInFunction(\"merge\", cs->irb.getCurrentFunction());\n\n\t\t\tauto valid = cs->irb.ICmpEQ(tid, fir::ConstantInt::getUNative(type->getID()));\n\t\t\tcs->irb.CondBranch(valid, merge, invalid);\n\n\t\t\tcs->irb.setCurrentBlock(invalid);\n\t\t\t{\n\t\t\t\tprintRuntimeError(cs, fir::ConstantCharSlice::get(cs->loc().toString()),\n\t\t\t\t\t\"invalid unwrap of 'any' with type id '%ld' into type '%s' (with id '%ld')\",\n\t\t\t\t\t{ tid, cs->module->createGlobalString(type->str()), fir::ConstantInt::getUNative(type->getID()) }\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(merge);\n\t\t\t{\n\t\t\t\tif(fir::getSizeOfType(type) > BUILTIN_ANY_DATA_BYTECOUNT)\n\t\t\t\t{\n\t\t\t\t\t// same as above, but in reverse.\n\t\t\t\t\tauto arrptr = cs->irb.StackAlloc(dataarrty);\n\t\t\t\t\tcs->irb.WritePtr(cs->irb.GetAnyData(any), arrptr);\n\n\t\t\t\t\t// cast the array* into a type**, so when we dereference it, we get the first 8 bytes interpreted as a type*.\n\t\t\t\t\t// we then just load and return that.\n\t\t\t\t\tauto fakeptr = cs->irb.PointerTypeCast(arrptr, type->getMutablePointerTo()->getMutablePointerTo());\n\t\t\t\t\tauto typeptr = cs->irb.ReadPtr(fakeptr);\n\n\t\t\t\t\tcs->irb.Return(cs->irb.ReadPtr(typeptr));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tauto arrptr = cs->irb.StackAlloc(dataarrty);\n\t\t\t\t\tcs->irb.WritePtr(cs->irb.GetAnyData(any), arrptr);\n\n\t\t\t\t\t// same as above but we skip a load.\n\t\t\t\t\tauto fakeptr = cs->irb.PointerTypeCast(arrptr, type->getMutablePointerTo());\n\t\t\t\t\tauto ret = cs->irb.ReadPtr(fakeptr);\n\n\t\t\t\t\tcs->irb.Return(ret);\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tretfn = func;\n\t\t}\n\n\t\ticeAssert(retfn);\n\t\treturn retfn;\n\t}\n}\n}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/glue/arrays.cpp",
    "content": "// arrays.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"codegen.h\"\n#include \"platform.h\"\n#include \"gluecode.h\"\n\n\nnamespace cgn {\nnamespace glue {\nnamespace array\n{\n\tfir::Function* getBoundsCheckFunction(CodegenState* cs, bool isPerformingDecomposition)\n\t{\n\t\treturn saa_common::generateBoundsCheckFunction(cs, /* isString: */false, isPerformingDecomposition);\n\t}\n\n\tfir::Function* getCloneFunction(CodegenState* cs, fir::Type* arrtype)\n\t{\n\t\treturn saa_common::generateCloneFunction(cs, arrtype);\n\t}\n\n\tfir::Function* getReserveExtraFunction(CodegenState* cs, fir::DynamicArrayType* arrtype)\n\t{\n\t\treturn saa_common::generateReserveExtraFunction(cs, arrtype);\n\t}\n\n\tfir::Function* getReserveAtLeastFunction(CodegenState* cs, fir::DynamicArrayType* arrtype)\n\t{\n\t\treturn saa_common::generateReserveAtLeastFunction(cs, arrtype);\n\t}\n\n\tfir::Function* getAppendFunction(CodegenState* cs, fir::DynamicArrayType* arrtype)\n\t{\n\t\treturn saa_common::generateAppendFunction(cs, arrtype);\n\t}\n\n\tfir::Function* getElementAppendFunction(CodegenState* cs, fir::DynamicArrayType* arrtype)\n\t{\n\t\treturn saa_common::generateElementAppendFunction(cs, arrtype);\n\t}\n\n\n\n\n\n\tfir::Function* getCallClassConstructorOnElementsFunction(CodegenState* cs, fir::ClassType* cls, sst::FunctionDefn* constr,\n\t\tconst std::vector<FnCallArgument>& args)\n\t{\n\t\ticeAssert(cls);\n\n\t\tauto fname = misc::getCallClassConstructor_FName(cls);\n\t\tfir::Function* fn = cs->module->getFunction(fname);\n\n\t\tif(!fn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ cls->getPointerTo(), fir::Type::getNativeWord() }, fir::Type::getVoid()), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\t// ok: the real difference with the one below is that we need to call the constructor function on every element.\n\n\t\t\tfir::Value* arrdata = func->getArguments()[0];\n\t\t\tfir::Value* len = func->getArguments()[1];\n\n\n\t\t\tfir::IRBlock* check = cs->irb.addNewBlockInFunction(\"check\", func);\n\t\t\tfir::IRBlock* body = cs->irb.addNewBlockInFunction(\"body\", func);\n\t\t\tfir::IRBlock* merge = cs->irb.addNewBlockInFunction(\"merge\", func);\n\n\t\t\tauto ctrptr = cs->irb.StackAlloc(fir::Type::getNativeWord());\n\n\t\t\t// already set to 0 internally\n\n\t\t\tcs->irb.UnCondBranch(check);\n\t\t\tcs->irb.setCurrentBlock(check);\n\t\t\t{\n\t\t\t\tauto cond = cs->irb.ICmpLT(cs->irb.ReadPtr(ctrptr), len);\n\t\t\t\tcs->irb.CondBranch(cond, body, merge);\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(body);\n\t\t\t{\n\t\t\t\tauto ctr = cs->irb.ReadPtr(ctrptr);\n\t\t\t\tauto ptr = cs->irb.GetPointer(arrdata, ctr);\n\n\t\t\t\tauto val = cs->constructClassWithArguments(cls, constr, args);\n\n\t\t\t\t// TODO: this is a bit dubious??\n\t\t\t\tcs->irb.WritePtr(val, ptr);\n\n\t\t\t\tcs->irb.WritePtr(cs->irb.Add(ctr, fir::ConstantInt::getNative(1)), ctrptr);\n\n\t\t\t\tcs->irb.UnCondBranch(check);\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(merge);\n\t\t\tcs->irb.ReturnVoid();\n\n\n\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tfn = func;\n\t\t}\n\n\t\treturn fn;\n\t}\n\n\n\tfir::Function* getSetElementsToValueFunction(CodegenState* cs, fir::Type* elmType)\n\t{\n\t\ticeAssert(elmType);\n\n\t\tauto fname = misc::getSetElements_FName(elmType);\n\t\tfir::Function* fn = cs->module->getFunction(fname);\n\n\t\tif(!fn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ elmType->getMutablePointerTo(), fir::Type::getNativeWord(), elmType }, fir::Type::getVoid()),\n\t\t\t\tfir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\tfir::Value* arrdata = func->getArguments()[0];\n\t\t\tfir::Value* len = func->getArguments()[1];\n\t\t\tfir::Value* value = func->getArguments()[2];\n\n\t\t\ticeAssert(value);\n\t\t\tfir::IRBlock* check = cs->irb.addNewBlockInFunction(\"check\", func);\n\t\t\tfir::IRBlock* body = cs->irb.addNewBlockInFunction(\"body\", func);\n\t\t\tfir::IRBlock* merge = cs->irb.addNewBlockInFunction(\"merge\", func);\n\n\t\t\tauto ctrptr = cs->irb.StackAlloc(fir::Type::getNativeWord());\n\n\t\t\tcs->irb.UnCondBranch(check);\n\t\t\tcs->irb.setCurrentBlock(check);\n\t\t\t{\n\t\t\t\tauto cond = cs->irb.ICmpLT(cs->irb.ReadPtr(ctrptr), len);\n\t\t\t\tcs->irb.CondBranch(cond, body, merge);\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(body);\n\t\t\t{\n\t\t\t\tauto ctr = cs->irb.ReadPtr(ctrptr);\n\t\t\t\tauto ptr = cs->irb.GetPointer(arrdata, ctr);\n\n\t\t\t\tcs->autoAssignRefCountedValue(ptr, value, true);\n\n\t\t\t\tcs->irb.WritePtr(cs->irb.Add(ctr, fir::ConstantInt::getNative(1)), ctrptr);\n\n\t\t\t\tcs->irb.UnCondBranch(check);\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(merge);\n\t\t\tcs->irb.ReturnVoid();\n\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tfn = func;\n\t\t}\n\n\t\treturn fn;\n\t}\n\n\n\tfir::Function* getSetElementsToDefaultValueFunction(CodegenState* cs, fir::Type* elmType)\n\t{\n\t\ticeAssert(elmType);\n\n\t\tauto fname = misc::getSetElementsDefault_FName(elmType);\n\t\tfir::Function* fn = cs->module->getFunction(fname);\n\n\t\tif(!fn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ elmType->getMutablePointerTo(), fir::Type::getNativeWord() }, fir::Type::getVoid()), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\tfir::Value* value = 0;\n\n\t\t\tif(elmType->isClassType())\n\t\t\t\tvalue = cs->irb.CreateValue(elmType);\n\n\t\t\telse\n\t\t\t\tvalue = cs->getDefaultValue(elmType);\n\n\t\t\ticeAssert(value);\n\n\t\t\tauto setfn = getSetElementsToValueFunction(cs, elmType);\n\t\t\ticeAssert(setfn);\n\n\t\t\tcs->irb.Call(setfn, func->getArguments()[0], func->getArguments()[1], value);\n\n\t\t\tcs->irb.ReturnVoid();\n\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tfn = func;\n\t\t}\n\n\t\treturn fn;\n\t}\n\n\n\n\n\n\n\n\n\tstatic void _compareFunctionUsingBuiltinCompare(CodegenState* cs, fir::Type* arrtype, fir::Function* func,\n\t\tfir::Value* arg1, fir::Value* arg2)\n\t{\n\t\t// ok, ez.\n\t\tfir::Value* zeroval = fir::ConstantInt::getNative(0);\n\t\tfir::Value* oneval = fir::ConstantInt::getNative(1);\n\n\t\tfir::IRBlock* cond = cs->irb.addNewBlockInFunction(\"cond\", func);\n\t\tfir::IRBlock* body = cs->irb.addNewBlockInFunction(\"body\", func);\n\t\tfir::IRBlock* incr = cs->irb.addNewBlockInFunction(\"incr\", func);\n\t\tfir::IRBlock* merge = cs->irb.addNewBlockInFunction(\"merge\", func);\n\n\t\tfir::Value* ptr1 = 0; fir::Value* ptr2 = 0;\n\n\t\tif(arrtype->isDynamicArrayType())\n\t\t{\n\t\t\tptr1 = cs->irb.GetSAAData(arg1);\n\t\t\tptr2 = cs->irb.GetSAAData(arg2);\n\t\t}\n\t\telse if(arrtype->isArraySliceType())\n\t\t{\n\t\t\tptr1 = cs->irb.GetArraySliceData(arg1);\n\t\t\tptr2 = cs->irb.GetArraySliceData(arg2);\n\t\t}\n\t\telse if(arrtype->isArrayType())\n\t\t{\n\t\t\tptr1 = cs->irb.ConstGEP2(arg1, 0, 0);\n\t\t\tptr2 = cs->irb.ConstGEP2(arg2, 0, 0);\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(\"invalid type '%s'\", arrtype);\n\t\t}\n\n\t\tfir::Value* len1 = 0; fir::Value* len2 = 0;\n\n\t\tif(arrtype->isDynamicArrayType())\n\t\t{\n\t\t\tlen1 = cs->irb.GetSAALength(arg1);\n\t\t\tlen2 = cs->irb.GetSAALength(arg2);\n\t\t}\n\t\telse if(arrtype->isArraySliceType())\n\t\t{\n\t\t\tlen1 = cs->irb.GetArraySliceLength(arg1);\n\t\t\tlen2 = cs->irb.GetArraySliceLength(arg2);\n\t\t}\n\t\telse if(arrtype->isArrayType())\n\t\t{\n\t\t\tlen1 = fir::ConstantInt::getNative(arrtype->toArrayType()->getArraySize());\n\t\t\tlen2 = fir::ConstantInt::getNative(arrtype->toArrayType()->getArraySize());\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(\"invalid type '%s'\", arrtype);\n\t\t}\n\n\t\t// we compare to this to break\n\t\tfir::Value* counter = cs->irb.StackAlloc(fir::Type::getNativeWord());\n\t\tcs->irb.WritePtr(zeroval, counter);\n\n\t\tfir::Value* res = cs->irb.StackAlloc(fir::Type::getNativeWord());\n\t\tcs->irb.WritePtr(zeroval, res);\n\n\n\t\tcs->irb.UnCondBranch(cond);\n\t\tcs->irb.setCurrentBlock(cond);\n\t\t{\n\t\t\tfir::IRBlock* retlt = cs->irb.addNewBlockInFunction(\"retlt\", func);\n\t\t\tfir::IRBlock* reteq = cs->irb.addNewBlockInFunction(\"reteq\", func);\n\t\t\tfir::IRBlock* retgt = cs->irb.addNewBlockInFunction(\"retgt\", func);\n\n\t\t\tfir::IRBlock* tmp1 = cs->irb.addNewBlockInFunction(\"tmp1\", func);\n\t\t\tfir::IRBlock* tmp2 = cs->irb.addNewBlockInFunction(\"tmp2\", func);\n\n\t\t\t// if we got here, the arrays were equal *up to this point*\n\t\t\t// if ptr1 exceeds or ptr2 exceeds, return len1 - len2\n\n\t\t\tfir::Value* t1 = cs->irb.ICmpEQ(cs->irb.ReadPtr(counter), len1);\n\t\t\tfir::Value* t2 = cs->irb.ICmpEQ(cs->irb.ReadPtr(counter), len2);\n\n\t\t\t// if t1 is over, goto tmp1, if not goto t2\n\t\t\tcs->irb.CondBranch(t1, tmp1, tmp2);\n\t\t\tcs->irb.setCurrentBlock(tmp1);\n\t\t\t{\n\t\t\t\t// t1 is over\n\t\t\t\t// check if t2 is over\n\t\t\t\t// if so, return 0 (b == a)\n\t\t\t\t// if not, return -1 (b > a)\n\n\t\t\t\tcs->irb.CondBranch(t2, reteq, retlt);\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(tmp2);\n\t\t\t{\n\t\t\t\t// t1 is not over\n\t\t\t\t// check if t2 is over\n\t\t\t\t// if so, return 1 (a > b)\n\t\t\t\t// if not, goto body\n\n\t\t\t\tcs->irb.CondBranch(t2, retgt, body);\n\t\t\t}\n\n\n\t\t\tcs->irb.setCurrentBlock(retlt);\n\t\t\tcs->irb.Return(fir::ConstantInt::getNative(-1));\n\n\t\t\tcs->irb.setCurrentBlock(reteq);\n\t\t\tcs->irb.Return(fir::ConstantInt::getNative(0));\n\n\t\t\tcs->irb.setCurrentBlock(retgt);\n\t\t\tcs->irb.Return(fir::ConstantInt::getNative(+1));\n\t\t}\n\n\n\t\tcs->irb.setCurrentBlock(body);\n\t\t{\n\t\t\tfir::Value* v1 = cs->irb.ReadPtr(cs->irb.GetPointer(ptr1, cs->irb.ReadPtr(counter)));\n\t\t\tfir::Value* v2 = cs->irb.ReadPtr(cs->irb.GetPointer(ptr2, cs->irb.ReadPtr(counter)));\n\n\t\t\tfir::Value* c = cs->performBinaryOperation(cs->loc(), { cs->loc(), v1 }, { cs->loc(), v2 }, \"==\").value;\n\n\t\t\t// c is a bool, because it's very generic in nature\n\t\t\t// so we just take !c and convert to i64 to get our result.\n\t\t\t// if c == true, then lhs == rhs, and so we should have 0.\n\n\t\t\tc = cs->irb.LogicalNot(c);\n\t\t\tc = cs->irb.IntSizeCast(c, fir::Type::getNativeWord());\n\n\t\t\tcs->irb.WritePtr(c, res);\n\n\t\t\t// compare to 0.\n\t\t\tfir::Value* cmpres = cs->irb.ICmpEQ(cs->irb.ReadPtr(res), zeroval);\n\n\t\t\t// if equal, go to incr, if not return directly\n\t\t\tcs->irb.CondBranch(cmpres, incr, merge);\n\t\t}\n\n\n\t\tcs->irb.setCurrentBlock(incr);\n\t\t{\n\t\t\tcs->irb.WritePtr(cs->irb.Add(cs->irb.ReadPtr(counter), oneval), counter);\n\t\t\tcs->irb.UnCondBranch(cond);\n\t\t}\n\n\n\n\t\tcs->irb.setCurrentBlock(merge);\n\t\t{\n\t\t\t// load and return\n\t\t\tcs->irb.Return(cs->irb.ReadPtr(res));\n\t\t}\n\t}\n\n\n\tstatic void _compareFunctionUsingOperatorFunction(CodegenState* cs, fir::Type* arrtype, fir::Function* curfunc,\n\t\tfir::Value* arg1, fir::Value* arg2, fir::Function* opf)\n\t{\n\t\terror(\"notsup\");\n\t}\n\n\n\n\tfir::Function* getCompareFunction(CodegenState* cs, fir::Type* arrtype, fir::Function* opf)\n\t{\n\t\ticeAssert(arrtype);\n\n\t\tauto fname = misc::getCompare_FName(arrtype);\n\t\tfir::Function* cmpf = cs->module->getFunction(fname);\n\n\t\tif(!cmpf)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ arrtype, arrtype }, fir::Type::getNativeWord()), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\tfir::Value* s1 = func->getArguments()[0];\n\t\t\tfir::Value* s2 = func->getArguments()[1];\n\n\t\t\t{\n\t\t\t\t// check our situation.\n\t\t\t\tif(opf == 0)\n\t\t\t\t{\n\t\t\t\t\t_compareFunctionUsingBuiltinCompare(cs, arrtype, func, s1, s2);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_compareFunctionUsingOperatorFunction(cs, arrtype, func, s1, s2, opf);\n\t\t\t\t}\n\n\t\t\t\t// functions above do their own return\n\t\t\t}\n\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tcmpf = func;\n\t\t}\n\n\t\ticeAssert(cmpf);\n\t\treturn cmpf;\n\t}\n\n\n\n\n\n\n\n\n\tstatic fir::Function* makeRecursiveRefCountingFunction(CodegenState* cs, fir::DynamicArrayType* arrtype, bool incr)\n\t{\n\t\tauto fname = misc::getRecursiveRefcount_FName(arrtype, incr);\n\t\tfir::Function* retf = cs->module->getFunction(fname);\n\n\t\tif(!retf)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ arrtype }, fir::Type::getVoid()), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\tfir::Value* arr = func->getArguments()[0];\n\n\t\t\tauto ptr = cs->irb.GetSAAData(arr);\n\t\t\tauto len = cs->irb.GetSAALength(arr);\n\t\t\tauto cap = cs->irb.GetSAACapacity(arr);\n\n\n\t\t\t{\n\t\t\t\tauto elmtype = arrtype->getElementType();\n\n\t\t\t\t// here we check whether we actually have a refcount pointer. If we don't, then we're a literal, and there's no need to change\n\t\t\t\t// the refcount anyway.\n\t\t\t\tauto prevblk = cs->irb.getCurrentBlock();\n\t\t\t\tauto dorc = cs->irb.addNewBlockInFunction(\"dorc\", cs->irb.getCurrentFunction());\n\t\t\t\tauto dontrc = cs->irb.addNewBlockInFunction(\"dontrcliteral\", cs->irb.getCurrentFunction());\n\t\t\t\t{\n\t\t\t\t\tauto rcp = cs->irb.GetSAARefCountPointer(arr);\n\t\t\t\t\tauto cond = cs->irb.ICmpNEQ(cs->irb.PointerToIntCast(rcp, fir::Type::getNativeWord()), fir::ConstantInt::getNative(0));\n\n\t\t\t\t\tcs->irb.CondBranch(cond, dorc, dontrc);\n\t\t\t\t}\n\n\t\t\t\tfir::Value* therefc = 0;\n\t\t\t\tcs->irb.setCurrentBlock(dorc);\n\t\t\t\t{\n\t\t\t\t\ttherefc = cs->irb.GetSAARefCount(arr);\n\n\t\t\t\t\tfir::Value* newrc = 0;\n\t\t\t\t\tif(incr)    newrc = cs->irb.Add(therefc, fir::ConstantInt::getNative(1));\n\t\t\t\t\telse        newrc = cs->irb.Subtract(therefc, fir::ConstantInt::getNative(1));\n\n\t\t\t\t\t// update it.\n\t\t\t\t\ttherefc = newrc;\n\t\t\t\t\tcs->irb.SetSAARefCount(arr, newrc);\n\t\t\t\t\tcs->irb.UnCondBranch(dontrc);\n\t\t\t\t}\n\n\t\t\t\tcs->irb.setCurrentBlock(dontrc);\n\n\t\t\t\t#if DEBUG_ARRAY_REFCOUNTING\n\t\t\t\t{\n\t\t\t\t\tstd::string x = incr ? \"(incr)\" : \"(decr)\";\n\n\t\t\t\t\tcs->printIRDebugMessage(\"* ARRAY:  \" + x + \" - new rc of: (ptr: %p, len: %ld, cap: %ld) = %d\",\n\t\t\t\t\t\t{ cs->irb.GetSAAData(arr), cs->irb.GetSAALength(arr), cs->irb.GetSAACapacity(arr), cs->irb.GetSAARefCount(arr) });\n\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\t// ok. if we're incrementing, then we're done -- but if we're decrementing, we may need to free the memory.\n\t\t\t\tif(!incr)\n\t\t\t\t{\n\t\t\t\t\tfir::IRBlock* dealloc = cs->irb.addNewBlockInFunction(\"dealloc\", func);\n\t\t\t\t\tfir::IRBlock* merge = cs->irb.addNewBlockInFunction(\"merge\", func);\n\n\t\t\t\t\tauto zv = fir::ConstantInt::getNative(0);\n\n\t\t\t\t\t//! NOTE: what we want to happen here is for us to free the memory, but only if refcnt == 0 && capacity >= 0\n\t\t\t\t\t//* so our condition is (REFCOUNT == 0) & (CAP >= 0)\n\n\t\t\t\t\tauto refc = cs->irb.CreatePHINode(fir::Type::getNativeWord());\n\t\t\t\t\trefc->addIncoming(therefc, dorc);\n\t\t\t\t\trefc->addIncoming(fir::ConstantInt::getNative(-1), prevblk);\n\n\t\t\t\t\tauto dofree = cs->irb.BitwiseAND(cs->irb.ICmpEQ(refc, zv), cs->irb.ICmpGEQ(cap, zv));\n\n\n\t\t\t\t\tcs->irb.CondBranch(dofree, dealloc, merge);\n\n\t\t\t\t\tcs->irb.setCurrentBlock(dealloc);\n\t\t\t\t\t{\n\t\t\t\t\t\tauto memptr = cs->irb.PointerTypeCast(ptr, fir::Type::getMutInt8Ptr());\n\n\t\t\t\t\t\tauto freefn = cs->getOrDeclareLibCFunction(FREE_MEMORY_FUNC);\n\t\t\t\t\t\ticeAssert(freefn);\n\n\t\t\t\t\t\t// only when we free, do we loop through our array and decrement its refcount.\n\t\t\t\t\t\tif(fir::isRefCountedType(elmtype))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tauto ctrp = cs->irb.StackAlloc(fir::Type::getNativeWord());\n\t\t\t\t\t\t\tcs->irb.WritePtr(zv, ctrp);\n\n\t\t\t\t\t\t\tcs->createWhileLoop([cs, ctrp, len](auto pass, auto fail) {\n\t\t\t\t\t\t\t\tauto cond = cs->irb.ICmpLT(cs->irb.ReadPtr(ctrp), len);\n\t\t\t\t\t\t\t\tcs->irb.CondBranch(cond, pass, fail);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t[cs, ctrp, ptr]() {\n\n\t\t\t\t\t\t\t\tauto ctr = cs->irb.ReadPtr(ctrp);\n\t\t\t\t\t\t\t\tauto p = cs->irb.GetPointer(ptr, ctr);\n\n\t\t\t\t\t\t\t\tcs->decrementRefCount(cs->irb.ReadPtr(p));\n\n\t\t\t\t\t\t\t\tcs->irb.WritePtr(cs->irb.Add(ctr, fir::ConstantInt::getNative(1)), ctrp);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcs->irb.Call(freefn, memptr);\n\t\t\t\t\t\tcs->irb.Call(freefn, cs->irb.PointerTypeCast(cs->irb.GetSAARefCountPointer(arr), fir::Type::getMutInt8Ptr()));\n\n\t\t\t\t\t\t#if DEBUG_ARRAY_ALLOCATION\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcs->printIRDebugMessage(\"* ARRAY:  free(): (ptr: %p / rcp: %p)\", {\n\t\t\t\t\t\t\t\tmemptr, cs->irb.GetSAARefCountPointer(arr) });\n\t\t\t\t\t\t}\n\t\t\t\t\t\t#endif\n\n\n\t\t\t\t\t\tcs->irb.UnCondBranch(merge);\n\t\t\t\t\t}\n\n\t\t\t\t\tcs->irb.setCurrentBlock(merge);\n\t\t\t\t}\n\t\t\t}\n\n\n\n\t\t\tcs->irb.ReturnVoid();\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tretf = func;\n\t\t}\n\n\t\ticeAssert(retf);\n\t\treturn retf;\n\t}\n\n\n\n\n\n\n\tstatic fir::Function* _getDoRefCountFunctionForDynamicArray(CodegenState* cs, fir::DynamicArrayType* arrtype, bool increment)\n\t{\n\t\tauto fname = (increment ? misc::getLoopIncrRefcount_FName(arrtype) : misc::getLoopDecrRefcount_FName(arrtype));\n\t\tfir::Function* cmpf = cs->module->getFunction(fname);\n\n\t\tif(!cmpf)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ arrtype }, arrtype), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\tfir::Value* arr = func->getArguments()[0];\n\t\t\tauto fn = makeRecursiveRefCountingFunction(cs, arr->getType()->toDynamicArrayType(), increment);\n\t\t\ticeAssert(fn);\n\n\t\t\tcs->irb.Call(fn, arr);\n\n\t\t\tcs->irb.Return(arr);\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tcmpf = func;\n\t\t}\n\n\t\ticeAssert(cmpf);\n\t\treturn cmpf;\n\t}\n\n\tstatic fir::Function* _getDoRefCountFunctionForArray(CodegenState* cs, fir::ArrayType* arrtype, bool incr)\n\t{\n\t\terror(\"NO!\");\n\t}\n\n\n\tfir::Function* getIncrementArrayRefCountFunction(CodegenState* cs, fir::Type* arrtype)\n\t{\n\t\tif(arrtype->isDynamicArrayType())\treturn _getDoRefCountFunctionForDynamicArray(cs, arrtype->toDynamicArrayType(), true);\n\t\telse\t\t\t\t\t\t\t\treturn _getDoRefCountFunctionForArray(cs, arrtype->toArrayType(), true);\n\t}\n\n\tfir::Function* getDecrementArrayRefCountFunction(CodegenState* cs, fir::Type* arrtype)\n\t{\n\t\tif(arrtype->isDynamicArrayType())\treturn _getDoRefCountFunctionForDynamicArray(cs, arrtype->toDynamicArrayType(), false);\n\t\telse\t\t\t\t\t\t\t\treturn _getDoRefCountFunctionForArray(cs, arrtype->toArrayType(), false);\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\tfir::Function* getConstructFromTwoFunction(CodegenState* cs, fir::DynamicArrayType* arrtype)\n\t{\n\t\treturn saa_common::generateConstructFromTwoFunction(cs, arrtype);\n\t}\n\n\n\tfir::Function* getPopElementFromBackFunction(CodegenState* cs, fir::Type* arrtype)\n\t{\n\t\ticeAssert(arrtype);\n\t\ticeAssert(arrtype->isDynamicArrayType() || arrtype->isArraySliceType());\n\n\t\tauto fname = misc::getPopBack_FName(arrtype);\n\t\tfir::Function* fn = cs->module->getFunction(fname);\n\n\t\tif(!fn)\n\t\t{\n\t\t\tbool isslice = arrtype->isArraySliceType();\n\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\t\t\tauto retTy = fir::TupleType::get({ arrtype, arrtype->getArrayElementType() });\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ arrtype, fir::Type::getCharSlice(false) }, retTy), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\n\t\t\tfir::Value* arr = func->getArguments()[0];\n\t\t\tfir::Value* loc = func->getArguments()[1];\n\n\t\t\tfir::Value* origlen = (isslice ? cs->irb.GetArraySliceLength(arr) : cs->irb.GetSAALength(arr));\n\n\t\t\tfir::IRBlock* fail = cs->irb.addNewBlockInFunction(\"fail\", func);\n\t\t\tfir::IRBlock* merge = cs->irb.addNewBlockInFunction(\"merge\", func);\n\n\t\t\tauto cond = cs->irb.ICmpLT(origlen, fir::ConstantInt::getNative(1));\n\n\t\t\tcs->irb.CondBranch(cond, fail, merge);\n\t\t\tcs->irb.setCurrentBlock(fail);\n\t\t\t{\n\t\t\t\tprintRuntimeError(cs, loc, \"calling pop() on an empty array\\n\", { });\n\t\t\t}\n\n\n\t\t\tcs->irb.setCurrentBlock(merge);\n\t\t\t{\n\t\t\t\tauto newlen = cs->irb.Subtract(origlen, fir::ConstantInt::getNative(1));\n\t\t\t\tfir::Value* ret = 0;\n\n\t\t\t\t// first, load the last value\n\t\t\t\tif(isslice)\n\t\t\t\t{\n\t\t\t\t\tauto ptr = cs->irb.GetArraySliceData(arr);\n\t\t\t\t\tauto val = cs->irb.ReadPtr(cs->irb.GetPointer(ptr, newlen));\n\n\t\t\t\t\tauto newarr = cs->irb.SetArraySliceLength(arr, newlen);\n\t\t\t\t\tret = cs->irb.CreateValue(retTy);\n\t\t\t\t\tret = cs->irb.InsertValue(ret, { 0 }, newarr);\n\t\t\t\t\tret = cs->irb.InsertValue(ret, { 1 }, val);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tauto ptr = cs->irb.GetSAAData(arr);\n\t\t\t\t\tauto val = cs->irb.ReadPtr(cs->irb.GetPointer(ptr, newlen));\n\n\t\t\t\t\tauto newarr = cs->irb.SetSAALength(arr, newlen);\n\t\t\t\t\tret = cs->irb.CreateValue(retTy);\n\t\t\t\t\tret = cs->irb.InsertValue(ret, { 0 }, newarr);\n\t\t\t\t\tret = cs->irb.InsertValue(ret, { 1 }, val);\n\t\t\t\t}\n\n\t\t\t\ticeAssert(ret);\n\t\t\t\tcs->irb.Return(ret);\n\t\t\t}\n\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tfn = func;\n\t\t}\n\n\t\treturn fn;\n\t}\n\n\n\n\n}\n}\n}\n\n"
  },
  {
    "path": "source/codegen/glue/misc.cpp",
    "content": "// misc.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"codegen.h\"\n#include \"platform.h\"\n#include \"gluecode.h\"\n#include \"frontend.h\"\n\nnamespace cgn {\nnamespace glue {\n\nvoid printRuntimeError(cgn::CodegenState* cs, fir::Value* pos, const std::string& message, const std::vector<fir::Value*>& args)\n{\n\t//! on windows, apparently fprintf doesn't like to work.\n\t//! so we just use normal printf.\n\n\tif(!frontend::getIsNoRuntimeErrorStrings())\n\t{\n\t\ticeAssert(pos->getType()->isCharSliceType());\n\n\t\tfir::Value* fmtstr = cs->module->createGlobalString((\"\\nRuntime error at %s:\\n\" + message + \"\\n\").c_str());\n\t\tfir::Value* posstr = cs->irb.GetArraySliceData(pos);\n\n\t\tstd::vector<fir::Value*> as = { fmtstr, posstr };\n\t\tas.insert(as.end(), args.begin(), args.end());\n\n\t\tcs->irb.Call(cs->getOrDeclareLibCFunction(\"printf\"), as);\n\t}\n\n\tcs->irb.Call(cs->getOrDeclareLibCFunction(\"abort\"));\n\tcs->irb.Unreachable();\n\n}\n\nnamespace misc\n{\n\tfir::Function* getMallocWrapperFunction(CodegenState* cs)\n\t{\n\t\tauto fname = getMallocWrapper_FName();\n\t\tfir::Function* fn = cs->module->getFunction(fname);\n\n\t\tif(!fn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ fir::Type::getNativeWord(), fir::Type::getCharSlice(false) }, fir::Type::getMutInt8Ptr()),\n\t\t\t\tfir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tauto sz = func->getArguments()[0];\n\t\t\tauto locstr = func->getArguments()[1];\n\n\t\t\tauto entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\t// do the alloc.\n\t\t\tauto mallocf = cs->getOrDeclareLibCFunction(ALLOCATE_MEMORY_FUNC);\n\t\t\ticeAssert(mallocf);\n\n\t\t\tauto mem = cs->irb.Call(mallocf, sz);\n\t\t\tauto cond = cs->irb.ICmpEQ(mem, fir::ConstantValue::getZeroValue(fir::Type::getInt8Ptr()));\n\n\t\t\tauto alloc_succ = cs->irb.addNewBlockAfter(\"success\", cs->irb.getCurrentBlock());\n\t\t\tauto alloc_fail = cs->irb.addNewBlockAfter(\"failure\", cs->irb.getCurrentBlock());\n\n\t\t\tcs->irb.CondBranch(cond, alloc_fail, alloc_succ);\n\t\t\tcs->irb.setCurrentBlock(alloc_succ);\n\t\t\t{\n\t\t\t\tcs->irb.Return(mem);\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(alloc_fail);\n\t\t\t{\n\t\t\t\tprintRuntimeError(cs, locstr, \"allocation failed (returned null) (tried to allocate %d bytes)\", { sz });\n\n\t\t\t\t// it emits an unreachable for us.\n\t\t\t}\n\n\t\t\tfn = func;\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t}\n\n\t\ticeAssert(fn);\n\t\treturn fn;\n\t}\n\n\tfir::Function* getRangeSanityCheckFunction(CodegenState* cs)\n\t{\n\t\tif(frontend::getIsNoRuntimeChecks())\n\t\t\treturn 0;\n\n\t\tauto fname = getRangeSanityCheck_FName();\n\t\tfir::Function* fn = cs->module->getFunction(fname);\n\n\t\tif(!fn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ fir::Type::getRange(), fir::Type::getCharSlice(false) }, fir::Type::getVoid()), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\t/*\n\t\t\t\tValid scenarios:\n\n\t\t\t\t1. start <= end, step > 0\n\t\t\t\t2. start >= end, step < 0\n\t\t\t*/\n\t\t\tauto entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\tauto check = cs->irb.addNewBlockAfter(\"check\", cs->irb.getCurrentBlock());\n\n\t\t\tauto checkstepneg = cs->irb.addNewBlockAfter(\"checkstepneg\", cs->irb.getCurrentBlock());\n\t\t\tauto checksteppos = cs->irb.addNewBlockAfter(\"checksteppos\", cs->irb.getCurrentBlock());\n\n\t\t\tauto stepnotneg = cs->irb.addNewBlockAfter(\"fail_stepnotneg\", cs->irb.getCurrentBlock());\n\t\t\tauto stepnotpos = cs->irb.addNewBlockAfter(\"fail_stepnotpos\", cs->irb.getCurrentBlock());\n\t\t\tauto stepzero = cs->irb.addNewBlockAfter(\"fail_stepzero\", cs->irb.getCurrentBlock());\n\n\t\t\tauto merge = cs->irb.addNewBlockAfter(\"merge\", cs->irb.getCurrentBlock());\n\n\n\t\t\tauto lower = cs->irb.GetRangeLower(func->getArguments()[0]);\n\t\t\tauto upper = cs->irb.GetRangeUpper(func->getArguments()[0]);\n\t\t\tauto step = cs->irb.GetRangeStep(func->getArguments()[0]);\n\n\t\t\tauto zero = fir::ConstantInt::getNative(0);\n\t\t\t// first of all check if step is zero.\n\t\t\t{\n\t\t\t\tauto cond = cs->irb.ICmpEQ(step, zero);\n\t\t\t\tcs->irb.CondBranch(cond, stepzero, check);\n\t\t\t}\n\n\n\t\t\t// first, check if start <= end.\n\t\t\tcs->irb.setCurrentBlock(check);\n\t\t\t{\n\t\t\t\tauto cond = cs->irb.ICmpLEQ(lower, upper);\n\n\t\t\t\t// if start < end, check step > 0. else check step < 0.\n\t\t\t\tcs->irb.CondBranch(cond, checksteppos, checkstepneg);\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(checksteppos);\n\t\t\t{\n\t\t\t\tauto cond = cs->irb.ICmpGT(step, zero);\n\t\t\t\tcs->irb.CondBranch(cond, merge, stepnotpos);\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(checkstepneg);\n\t\t\t{\n\t\t\t\tauto cond = cs->irb.ICmpLT(step, zero);\n\t\t\t\tcs->irb.CondBranch(cond, merge, stepnotneg);\n\t\t\t}\n\n\n\t\t\t// ok, now the failure messages.\n\t\t\t{\n\t\t\t\tcs->irb.setCurrentBlock(stepzero);\n\t\t\t\t{\n\t\t\t\t\tprintRuntimeError(cs, func->getArguments()[1], \"range step had value of zero\\n\", { });\n\t\t\t\t}\n\n\t\t\t\tcs->irb.setCurrentBlock(stepnotpos);\n\t\t\t\t{\n\t\t\t\t\tprintRuntimeError(cs, func->getArguments()[1], \"range had negative step value ('%ld'); invalid when start < end\\n\", { step });\n\t\t\t\t}\n\n\t\t\t\tcs->irb.setCurrentBlock(stepnotneg);\n\t\t\t\t{\n\t\t\t\t\tprintRuntimeError(cs, func->getArguments()[1], \"range had positive step value ('%ld'); invalid when start > end\\n\", { step });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(merge);\n\t\t\tcs->irb.ReturnVoid();\n\n\t\t\tfn = func;\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t}\n\n\t\ticeAssert(fn);\n\t\treturn fn;\n\t}\n\n\n\n\tusing Idt = fir::Name;\n\tIdt getOI(const std::string& name, fir::Type* t = 0)\n\t{\n\t\tif(t) return fir::Name::obfuscate(name, t->encodedStr());\n\t\telse  return fir::Name::obfuscate(name);\n\t}\n\n\tIdt getCompare_FName(fir::Type* t)              { return getOI(\"compare\", t); }\n\tIdt getSetElements_FName(fir::Type* t)          { return getOI(\"setelements\", t); }\n\tIdt getCallClassConstructor_FName(fir::Type* t) { return getOI(\"callclassinit\", t); }\n\tIdt getSetElementsDefault_FName(fir::Type* t)   { return getOI(\"setelementsdefault\", t); }\n\n\tIdt getClone_FName(fir::Type* t)         { return getOI(\"clone\", t); }\n\tIdt getAppend_FName(fir::Type* t)        { return getOI(\"append\", t); }\n\tIdt getPopBack_FName(fir::Type* t)       { return getOI(\"popback\", t); }\n\tIdt getMakeFromOne_FName(fir::Type* t)   { return getOI(\"makefromone\", t); }\n\tIdt getMakeFromTwo_FName(fir::Type* t)   { return getOI(\"makefromtwo\", t); }\n\tIdt getReserveExtra_FName(fir::Type* t)  { return getOI(\"reserveextra\", t); }\n\tIdt getAppendElement_FName(fir::Type* t) { return getOI(\"appendelement\", t); }\n\tIdt getReserveEnough_FName(fir::Type* t) { return getOI(\"reservesufficient\", t); }\n\tIdt getRecursiveRefcount_FName(fir::Type* t, bool incr)\n\t{\n\t\treturn getOI(strprintf(\"rrc_%s\", incr ? \"incr\" : \"decr\"), t);\n\t}\n\n\tIdt getIncrRefcount_FName(fir::Type* t)         { return getOI(\"incr_rc\", t); }\n\tIdt getDecrRefcount_FName(fir::Type* t)         { return getOI(\"decr_rc\", t); }\n\tIdt getLoopIncrRefcount_FName(fir::Type* t)     { return getOI(\"loop_incr_rc\", t); }\n\tIdt getLoopDecrRefcount_FName(fir::Type* t)     { return getOI(\"loop_decr_rc\", t); }\n\n\tIdt getCreateAnyOf_FName(fir::Type* t)          { return getOI(\"create_any_of\", t); }\n\tIdt getGetValueFromAny_FName(fir::Type* t)      { return getOI(\"get_value_from_any\", t); }\n\n\tIdt getUtf8Length_FName()           { return getOI(\"utf8_length\"); }\n\tIdt getRangeSanityCheck_FName()     { return getOI(\"range_sanity\"); }\n\tIdt getMallocWrapper_FName()        { return getOI(\"malloc_wrapper\"); }\n\tIdt getBoundsCheck_FName()          { return getOI(\"boundscheck\"); }\n\tIdt getDecompBoundsCheck_FName()    { return getOI(\"boundscheck_decomp\"); }\n\n}\n}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/glue/saa_common.cpp",
    "content": "// saa_common.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n\n#include \"codegen.h\"\n#include \"platform.h\"\n#include \"gluecode.h\"\n#include \"frontend.h\"\n\n// namespace cgn::glue::saa_common\nnamespace cgn {\nnamespace glue {\nnamespace saa_common\n{\n\tstatic inline bool isSAA(fir::Type* t) { return t->isStringType() || t->isDynamicArrayType(); }\n\tstatic inline fir::Type* getSAAElm(fir::Type* t) { iceAssert(isSAA(t)); return (t->isStringType() ? fir::Type::getInt8() : t->getArrayElementType()); }\n\tstatic inline fir::Type* getSAASlice(fir::Type* t, bool mut = true) { iceAssert(isSAA(t)); return fir::ArraySliceType::get(getSAAElm(t), mut); }\n\tstatic inline fir::ConstantInt* getCI(int64_t i) { return fir::ConstantInt::getNative(i); }\n\n\tstatic fir::Value* castRawBufToElmPtr(CodegenState* cs, fir::Type* saa, fir::Value* buf)\n\t{\n\t\tauto ptrty = getSAAElm(saa)->getMutablePointerTo();\n\n\t\tif(buf->getType()->isPointerType())\n\t\t\treturn cs->irb.PointerTypeCast(buf, ptrty);\n\n\t\telse\n\t\t\treturn cs->irb.IntToPointerCast(buf, ptrty);\n\t}\n\n\tstatic fir::Function* generateIncrementArrayRefCountInLoopFunction(CodegenState* cs, fir::Type* elm)\n\t{\n\t\ticeAssert(fir::isRefCountedType(elm));\n\n\t\tauto fname = misc::getLoopIncrRefcount_FName(elm);\n\t\tfir::Function* retfn = cs->module->getFunction(fname);\n\n\t\tif(!retfn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ elm->getPointerTo(), fir::Type::getNativeWord() }, fir::Type::getVoid()), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\tfir::IRBlock* cond = cs->irb.addNewBlockInFunction(\"loopCond\", func);\n\t\t\tfir::IRBlock* body = cs->irb.addNewBlockInFunction(\"loopBody\", func);\n\t\t\tfir::IRBlock* merge = cs->irb.addNewBlockInFunction(\"merge\", func);\n\n\t\t\tfir::Value* ctrPtr = cs->irb.StackAlloc(fir::Type::getNativeWord());\n\n\n\t\t\tfir::Value* s2ptr = func->getArguments()[0];\n\t\t\tfir::Value* s2len = func->getArguments()[1];\n\n\t\t\tcs->irb.UnCondBranch(cond);\n\t\t\tcs->irb.setCurrentBlock(cond);\n\t\t\t{\n\t\t\t\t// check the condition\n\t\t\t\tfir::Value* ctr = cs->irb.ReadPtr(ctrPtr);\n\t\t\t\tfir::Value* res = cs->irb.ICmpLT(ctr, s2len);\n\n\t\t\t\tcs->irb.CondBranch(res, body, merge);\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(body);\n\t\t\t{\n\t\t\t\t// increment refcount\n\t\t\t\tfir::Value* val = cs->irb.ReadPtr(cs->irb.GetPointer(s2ptr, cs->irb.ReadPtr(ctrPtr)));\n\n\t\t\t\tcs->incrementRefCount(val);\n\n\t\t\t\t// increment counter\n\t\t\t\tcs->irb.WritePtr(cs->irb.Add(fir::ConstantInt::getNative(1), cs->irb.ReadPtr(ctrPtr)), ctrPtr);\n\t\t\t\tcs->irb.UnCondBranch(cond);\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(merge);\n\t\t\tcs->irb.ReturnVoid();\n\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tretfn = func;\n\t\t}\n\n\t\ticeAssert(retfn);\n\t\treturn retfn;\n\t}\n\n\tfir::Value* makeNewRefCountPointer(CodegenState* cs, fir::Value* rc)\n\t{\n\t\ticeAssert(rc->getType()->isIntegerType() && \"not integer type\");\n\n\t\tauto rcp = cs->irb.Call(cs->getOrDeclareLibCFunction(ALLOCATE_MEMORY_FUNC), getCI(REFCOUNT_SIZE));\n\t\trcp = cs->irb.PointerTypeCast(rcp, fir::Type::getNativeWordPtr()->getMutablePointerVersion());\n\n\t\tcs->irb.WritePtr(rc, rcp);\n\t\treturn cs->irb.PointerTypeCast(rcp, fir::Type::getNativeWordPtr());\n\t}\n\n\tfir::Value* initSAAWithRefCount(CodegenState* cs, fir::Value* saa, fir::Value* rc)\n\t{\n\t\ticeAssert(isSAA(saa->getType()) && \"not saa type\");\n\t\ticeAssert(rc->getType()->isIntegerType() && \"not integer type\");\n\n\t\tauto rcp = makeNewRefCountPointer(cs, rc);\n\t\treturn cs->irb.SetSAARefCountPointer(saa, rcp);\n\t}\n\n\n\n\n\n\n\n\t/*\n\t\t* NOTE *\n\n\t\tsince we're changing strings and dynamic arrays to behave much the same way, why not just collapse the runtime gluecode as much\n\t\tas possible.\n\n\t\twe're going with the { ptr, len, cap, rcp } structure for both types, and so we can do a lot of things commonly. one thing is that\n\t\twe still want null terminators on strings, so that's just a couple of if-checks sprinkled around -- nothing too obnoxious.\n\t */\n\n\n\tstatic void _callCloneFunctionInLoop(CodegenState* cs, fir::Function* curfunc, fir::Function* fn,\n\t\tfir::Value* ptr, fir::Value* len, fir::Value* newptr, fir::Value* startIndex)\n\t{\n\t\tfir::IRBlock* loopcond = cs->irb.addNewBlockInFunction(\"loopcond\", curfunc);\n\t\tfir::IRBlock* loopbody = cs->irb.addNewBlockInFunction(\"loopbody\", curfunc);\n\t\tfir::IRBlock* merge = cs->irb.addNewBlockInFunction(\"merge\", curfunc);\n\n\t\tfir::Value* counter = cs->irb.StackAlloc(fir::Type::getNativeWord());\n\t\tcs->irb.WritePtr(startIndex, counter);\n\n\t\tcs->irb.UnCondBranch(loopcond);\n\t\tcs->irb.setCurrentBlock(loopcond);\n\t\t{\n\t\t\tfir::Value* res = cs->irb.ICmpEQ(cs->irb.ReadPtr(counter), len);\n\t\t\tcs->irb.CondBranch(res, merge, loopbody);\n\t\t}\n\n\t\tcs->irb.setCurrentBlock(loopbody);\n\t\t{\n\t\t\t// make clone\n\t\t\tfir::Value* origElm = cs->irb.GetPointer(ptr, cs->irb.ReadPtr(counter));\n\t\t\tfir::Value* clone = 0;\n\n\t\t\t//* note: the '0' argument specifies the offset to clone from -- since want the whole thing, the offset is 0.\n\t\t\tauto elm = cs->irb.ReadPtr(origElm);\n\n\t\t\tclone = cs->irb.Call(fn, isSAA(elm->getType()) ? cs->irb.CreateSliceFromSAA(elm, false) : elm, fir::ConstantInt::getNative(0));\n\n\t\t\t// store clone\n\t\t\tfir::Value* newElm = cs->irb.GetPointer(newptr, cs->irb.ReadPtr(counter));\n\t\t\tcs->irb.WritePtr(clone, newElm);\n\n\t\t\t// increment counter\n\t\t\tcs->irb.WritePtr(cs->irb.Add(cs->irb.ReadPtr(counter), fir::ConstantInt::getNative(1)), counter);\n\t\t\tcs->irb.UnCondBranch(loopcond);\n\t\t}\n\n\t\tcs->irb.setCurrentBlock(merge);\n\t}\n\n\tstatic void _handleCallingAppropriateCloneFunction(CodegenState* cs, fir::Function* func, fir::Type* elmType, fir::Value* oldptr,\n\t\tfir::Value* newptr, fir::Value* oldlen, fir::Value* bytecount, fir::Value* startIndex)\n\t{\n\t\tif(elmType->isPrimitiveType() || elmType->isCharType() || elmType->isEnumType())\n\t\t{\n\t\t\tfir::Function* memcpyf = cs->module->getIntrinsicFunction(\"memmove\");\n\n\t\t\tcs->irb.Call(memcpyf, { newptr, cs->irb.PointerTypeCast(cs->irb.GetPointer(oldptr,\n\t\t\t\tstartIndex), fir::Type::getMutInt8Ptr()), bytecount, fir::ConstantBool::get(false) });\n\n\t\t\t#if DEBUG_ARRAY_ALLOCATION | DEBUG_STRING_ALLOCATION\n\t\t\t{\n\t\t\t\tcs->printIRDebugMessage(\"* SAACOM: clone(): (oldptr: %p, oldlen: %d), (newptr: %p, bytecount: %d, index: %d)\", {\n\t\t\t\t\toldptr, oldlen, newptr, bytecount, startIndex });\n\t\t\t}\n\t\t\t#endif\n\n\t\t}\n\t\telse if(elmType->isDynamicArrayType())\n\t\t{\n\t\t\t// yo dawg i heard you like arrays...\n\t\t\tfir::Function* clonef = generateCloneFunction(cs, elmType);\n\t\t\ticeAssert(clonef);\n\n\t\t\t// loop\n\t\t\tfir::Value* cloneptr = cs->irb.PointerTypeCast(newptr, elmType->getMutablePointerTo());\n\t\t\t_callCloneFunctionInLoop(cs, func, clonef, oldptr, oldlen, cloneptr, startIndex);\n\t\t}\n\t\telse if(elmType->isArraySliceType())\n\t\t{\n\t\t\t// yo dawg i heard you like arrays...\n\t\t\tfir::Function* clonef = generateCloneFunction(cs, elmType);\n\t\t\ticeAssert(clonef);\n\n\t\t\t// loop\n\t\t\tfir::Value* cloneptr = cs->irb.PointerTypeCast(newptr, elmType->getMutablePointerTo());\n\t\t\t_callCloneFunctionInLoop(cs, func, clonef, oldptr, oldlen, cloneptr, startIndex);\n\t\t}\n\t\telse if(elmType->isStringType())\n\t\t{\n\t\t\tfir::Function* clonef = glue::string::getCloneFunction(cs);\n\t\t\ticeAssert(clonef);\n\n\t\t\t// loop\n\t\t\tfir::Value* cloneptr = cs->irb.PointerTypeCast(newptr, elmType->getMutablePointerTo());\n\t\t\t_callCloneFunctionInLoop(cs, func, clonef, oldptr, oldlen, cloneptr, startIndex);\n\t\t}\n\t\telse if(elmType->isStructType() || elmType->isClassType() || elmType->isTupleType() || elmType->isArrayType())\n\t\t{\n\t\t\t// todo: call copy constructors and stuff\n\n\t\t\tfir::Function* memcpyf = cs->module->getIntrinsicFunction(\"memmove\");\n\n\t\t\tcs->irb.Call(memcpyf, { newptr, cs->irb.PointerTypeCast(cs->irb.GetPointer(oldptr,\n\t\t\t\tstartIndex), fir::Type::getMutInt8Ptr()), bytecount, fir::ConstantBool::get(false) });\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(\"unsupported element type '%s' for array clone\", elmType);\n\t\t}\n\t}\n\n\n\n\n\n\n\tfir::Function* generateCloneFunction(CodegenState* cs, fir::Type* _saa)\n\t{\n\t\tauto fname = misc::getClone_FName(_saa);\n\n\t\ticeAssert(isSAA(_saa) || _saa->isArraySliceType());\n\t\tauto slicetype = (isSAA(_saa) ? getSAASlice(_saa, false) : fir::ArraySliceType::get(_saa->getArrayElementType(), false));\n\n\t\ticeAssert(slicetype->isArraySliceType());\n\t\tbool isArray = !_saa->isStringType();\n\n\t\tfir::Type* outtype = (isSAA(_saa) ? _saa : fir::DynamicArrayType::get(slicetype->getArrayElementType()));\n\n\t\tfir::Function* retfn = cs->module->getFunction(fname);\n\n\t\tif(!retfn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ slicetype, fir::Type::getNativeWord() }, outtype), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\tauto s1 = func->getArguments()[0];\n\t\t\tauto cloneofs = func->getArguments()[1];\n\n\t\t\tauto lhsbuf = cs->irb.GetArraySliceData(s1, \"lhsbuf\");\n\n\t\t\tfir::IRBlock* isnull = cs->irb.addNewBlockInFunction(\"isnull\", func);\n\t\t\tfir::IRBlock* notnull = cs->irb.addNewBlockInFunction(\"notnull\", func);\n\n\t\t\t// if it's null we just fuck off now.\n\t\t\tcs->irb.CondBranch(cs->irb.ICmpEQ(lhsbuf, fir::ConstantValue::getZeroValue(slicetype->getArrayElementType()->getPointerTo())),\n\t\t\t\tisnull, notnull);\n\n\t\t\tcs->irb.setCurrentBlock(notnull);\n\t\t\t{\n\t\t\t\tauto lhslen = cs->irb.Subtract(cs->irb.GetArraySliceLength(s1, \"l1\"), cloneofs, \"lhslen\");\n\t\t\t\tauto newcap = cs->irb.Call(cs->module->getIntrinsicFunction(\"roundup_pow2\"), lhslen, \"newcap\");\n\n\t\t\t\tauto lhsbytecount = cs->irb.Multiply(lhslen, cs->irb.Sizeof(slicetype->getArrayElementType()), \"lhsbytecount\");\n\t\t\t\tauto newbytecount = cs->irb.Multiply(newcap, cs->irb.Sizeof(slicetype->getArrayElementType()), \"newbytecount\");\n\n\t\t\t\tfir::Value* newbuf = cs->irb.Call(cgn::glue::misc::getMallocWrapperFunction(cs),\n\t\t\t\t\t!isArray ? cs->irb.Add(newbytecount, getCI(1)) : newbytecount, fir::ConstantCharSlice::get(\"(no location)\"), \"buf\");\n\t\t\t\t{\n\t\t\t\t\t// fir::Function* memcpyf = cs->module->getIntrinsicFunction(\"memmove\");\n\t\t\t\t\t// cs->irb.Call(memcpyf, { buf, castRawBufToElmPtr(cs, saa, lhsbuf), lhsbytecount,\n\t\t\t\t\t// \tfir::ConstantInt::getInt32(0), fir::ConstantBool::get(false) });\n\n\t\t\t\t\t_handleCallingAppropriateCloneFunction(cs, func, slicetype->getArrayElementType(), lhsbuf,\n\t\t\t\t\t\tnewbuf, lhslen, lhsbytecount, cloneofs);\n\n\t\t\t\t\t// null terminator\n\t\t\t\t\tif(!isArray)\n\t\t\t\t\t\tcs->irb.WritePtr(fir::ConstantInt::getInt8(0), cs->irb.GetPointer(newbuf, lhsbytecount));\n\t\t\t\t}\n\n\n\t\t\t\t{\n\t\t\t\t\tauto ret = cs->irb.CreateValue(outtype);\n\t\t\t\t\tret = cs->irb.SetSAAData(ret, castRawBufToElmPtr(cs, outtype, newbuf));\n\t\t\t\t\tret = cs->irb.SetSAALength(ret, lhslen);                    //? vv for the null terminator\n\t\t\t\t\tret = cs->irb.SetSAACapacity(ret, !isArray ? cs->irb.Subtract(newcap, getCI(1)) : newcap);\n\t\t\t\t\tret = initSAAWithRefCount(cs, ret, getCI(1));\n\n\t\t\t\t\tcs->irb.Return(ret);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(isnull);\n\t\t\t{\n\t\t\t\tauto ret = cs->irb.CreateValue(outtype);\n\t\t\t\tret = cs->irb.SetSAAData(ret, castRawBufToElmPtr(cs, outtype, getCI(0)));\n\t\t\t\tret = cs->irb.SetSAALength(ret, getCI(0));\n\t\t\t\tret = cs->irb.SetSAACapacity(ret, getCI(0));\n\t\t\t\tret = initSAAWithRefCount(cs, ret, getCI(1));\n\n\t\t\t\tcs->irb.Return(ret);\n\t\t\t}\n\n\t\t\tretfn = func;\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t}\n\n\t\ticeAssert(retfn);\n\t\treturn retfn;\n\t}\n\n\n\tfir::Function* generateAppropriateAppendFunction(CodegenState* cs, fir::Type* saa, fir::Type* appendee)\n\t{\n\t\ticeAssert(isSAA(saa));\n\t\tif(appendee == getSAAElm(saa))\n\t\t\treturn generateElementAppendFunction(cs, saa);\n\n\t\telse if(zfu::match(appendee, getSAASlice(saa), getSAASlice(saa, false), saa))\n\t\t\treturn generateAppendFunction(cs, saa);\n\n\t\telse\n\t\t\terror(cs->loc(), \"cannot append '%s' to '%s'\", appendee, saa);\n\t}\n\n\n\tfir::Function* generateAppendFunction(CodegenState* cs, fir::Type* saa)\n\t{\n\t\tauto fname = misc::getAppend_FName(saa);\n\n\t\ticeAssert(isSAA(saa));\n\t\tfir::Function* retfn = cs->module->getFunction(fname);\n\n\t\tif(!retfn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ saa, getSAASlice(saa, false) }, saa), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\tfir::Value* lhs = func->getArguments()[0];\n\t\t\tfir::Value* rhs = func->getArguments()[1];\n\n\t\t\tauto lhslen = cs->irb.GetSAALength(lhs, \"lhslen\");\n\n\t\t\tauto rhsbuf = cs->irb.GetArraySliceData(rhs, \"rhsbuf\");\n\t\t\tauto rhslen = cs->irb.GetArraySliceLength(rhs, \"rhslen\");\n\t\t\tauto rhsbytecount = cs->irb.Multiply(rhslen, cs->irb.Sizeof(rhs->getType()->getArrayElementType()), \"rhsbytecount\");\n\n\t\t\t// this handles the null case as well.\n\t\t\tlhs = cs->irb.Call(generateReserveAtLeastFunction(cs, saa), lhs, cs->irb.Add(lhslen, rhslen));\n\t\t\tauto lhsbuf = cs->irb.GetSAAData(lhs, \"lhsbuf\");\n\n\t\t\t// do a copy over the rhs.\n\t\t\t{\n\t\t\t\tfir::Function* memcpyf = cs->module->getIntrinsicFunction(\"memmove\");\n\t\t\t\tcs->irb.Call(memcpyf, {\n\t\t\t\t\tcs->irb.PointerTypeCast(cs->irb.GetPointer(lhsbuf, lhslen), fir::Type::getMutInt8Ptr()),\n\t\t\t\t\tcs->irb.PointerTypeCast(rhsbuf, fir::Type::getMutInt8Ptr()), rhsbytecount,\n\t\t\t\t\tfir::ConstantBool::get(false)\n\t\t\t\t});\n\n\t\t\t\t// null terminator\n\t\t\t\tif(saa->isStringType())\n\t\t\t\t{\n\t\t\t\t\tcs->irb.WritePtr(fir::ConstantInt::getInt8(0), cs->irb.PointerTypeCast(cs->irb.GetPointer(lhsbuf, cs->irb.Add(lhslen, rhslen)),\n\t\t\t\t\t\tfir::Type::getMutInt8Ptr()));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlhs = cs->irb.SetSAALength(lhs, cs->irb.Add(lhslen, rhslen));\n\n\t\t\t// handle refcounting\n\t\t\tif(fir::isRefCountedType(getSAAElm(saa)))\n\t\t\t{\n\t\t\t\tauto incrfn = generateIncrementArrayRefCountInLoopFunction(cs, getSAAElm(saa));\n\t\t\t\ticeAssert(incrfn);\n\n\t\t\t\tcs->irb.Call(incrfn, rhsbuf, rhslen);\n\t\t\t}\n\n\t\t\tcs->irb.Return(lhs);\n\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tretfn = func;\n\t\t}\n\n\t\ticeAssert(retfn);\n\t\treturn retfn;\n\t}\n\n\n\tfir::Function* generateElementAppendFunction(CodegenState* cs, fir::Type* saa)\n\t{\n\t\tauto fname = misc::getAppendElement_FName(saa);\n\n\t\ticeAssert(isSAA(saa));\n\t\tfir::Function* retfn = cs->module->getFunction(fname);\n\n\t\tif(!retfn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ saa, getSAAElm(saa) }, saa), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\tfir::Value* lhs = func->getArguments()[0];\n\t\t\tfir::Value* rhs = func->getArguments()[1];\n\n\t\t\tauto rhsp = cs->irb.ImmutStackAlloc(getSAAElm(saa), rhs, \"rhsptr\");\n\n\t\t\tauto rhsslice = cs->irb.CreateValue(getSAASlice(saa), \"rhsslice\");\n\t\t\trhsslice = cs->irb.SetArraySliceData(rhsslice, cs->irb.PointerTypeCast(rhsp, rhsp->getType()->getMutablePointerVersion()));\n\t\t\trhsslice = cs->irb.SetArraySliceLength(rhsslice, getCI(1));\n\n\t\t\tauto appf = generateAppendFunction(cs, saa);\n\t\t\ticeAssert(appf);\n\n\t\t\tauto ret = cs->irb.Call(appf, lhs, rhsslice);\n\t\t\tcs->irb.Return(ret);\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tretfn = func;\n\t\t}\n\n\t\ticeAssert(retfn);\n\t\treturn retfn;\n\t}\n\n\n\n\n\tfir::Function* generateConstructFromTwoFunction(CodegenState* cs, fir::Type* saa)\n\t{\n\t\tauto fname = misc::getMakeFromTwo_FName(saa);\n\n\t\ticeAssert(isSAA(saa));\n\t\tfir::Function* retfn = cs->module->getFunction(fname);\n\n\t\tif(!retfn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ getSAASlice(saa, false), getSAASlice(saa, false) }, saa), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\tfir::Value* lhs = func->getArguments()[0];\n\t\t\tfir::Value* rhs = func->getArguments()[1];\n\n\t\t\tauto lhslen = cs->irb.GetArraySliceLength(lhs, \"lhslen\");\n\t\t\tauto rhslen = cs->irb.GetArraySliceLength(rhs, \"rhslen\");\n\n\t\t\tauto lhsbuf = cs->irb.GetArraySliceData(lhs, \"lhsbuf\");\n\t\t\tauto rhsbuf = cs->irb.GetArraySliceData(rhs, \"rhsbuf\");\n\n\t\t\t// step 1 -- make a null of the SAA\n\t\t\tauto ret = cs->irb.CreateValue(saa);\n\t\t\tret = cs->irb.SetSAAData(ret, castRawBufToElmPtr(cs, saa, getCI(0)));\n\t\t\tret = cs->irb.SetSAALength(ret, getCI(0));\n\t\t\tret = cs->irb.SetSAACapacity(ret, getCI(0));  //? vv  we count on the 'reserveAtLeast' function to init our refcount\n\t\t\tret = cs->irb.SetSAARefCountPointer(ret, fir::ConstantValue::getZeroValue(fir::Type::getNativeWordPtr()));\n\n\n\t\t\tret = cs->irb.Call(generateReserveAtLeastFunction(cs, saa), ret, cs->irb.Add(cs->irb.Add(lhslen, rhslen),\n\t\t\t\tsaa->isStringType() ? getCI(1) : getCI(0)));\n\n\n\t\t\t#if DEBUG_ARRAY_ALLOCATION | DEBUG_STRING_ALLOCATION\n\t\t\t{\n\t\t\t\tcs->printIRDebugMessage(\"* SAACOM: construct2(): (ptr: %p, len: %d) + (ptr: %p, len: %d) = %p\", {\n\t\t\t\t\tlhsbuf, lhslen, rhsbuf, rhslen, cs->irb.GetSAAData(ret) });\n\t\t\t}\n\t\t\t#endif\n\n\n\t\t\tauto buf = cs->irb.GetSAAData(ret, \"buf\");\n\t\t\t{\n\t\t\t\tfir::Function* memcpyf = cs->module->getIntrinsicFunction(\"memmove\");\n\n\t\t\t\tauto rawbuf = cs->irb.PointerTypeCast(buf, fir::Type::getMutInt8Ptr(), \"rawbuf\");\n\t\t\t\tauto rawlhsbuf = cs->irb.PointerTypeCast(lhsbuf, fir::Type::getMutInt8Ptr(), \"rawlhsbuf\");\n\t\t\t\tauto rawrhsbuf = cs->irb.PointerTypeCast(rhsbuf, fir::Type::getMutInt8Ptr(), \"rawrhsbuf\");\n\n\t\t\t\tauto lhsbytecount = cs->irb.Multiply(lhslen, cs->irb.Sizeof(getSAAElm(saa)), \"lhsbytecount\");\n\t\t\t\tauto rhsbytecount = cs->irb.Multiply(rhslen, cs->irb.Sizeof(getSAAElm(saa)), \"rhsbytecount\");\n\n\t\t\t\tcs->irb.Call(memcpyf, { rawbuf, rawlhsbuf,\n\t\t\t\t\tlhsbytecount, fir::ConstantBool::get(false)\n\t\t\t\t});\n\n\t\t\t\tcs->irb.Call(memcpyf, { cs->irb.GetPointer(rawbuf, lhsbytecount), rawrhsbuf,\n\t\t\t\t\trhsbytecount, fir::ConstantBool::get(false)\n\t\t\t\t});\n\n\t\t\t\t// if it's a string, again, null terminator.\n\t\t\t\tif(saa->isStringType())\n\t\t\t\t{\n\t\t\t\t\tcs->irb.WritePtr(fir::ConstantInt::getInt8(0), cs->irb.GetPointer(rawbuf, cs->irb.Add(lhsbytecount, rhsbytecount)));\n\t\t\t\t}\n\t\t\t\telse if(fir::isRefCountedType(getSAAElm(saa)))\n\t\t\t\t{\n\t\t\t\t\tauto incrfn = generateIncrementArrayRefCountInLoopFunction(cs, getSAAElm(saa));\n\t\t\t\t\ticeAssert(incrfn);\n\n\t\t\t\t\tcs->irb.Call(incrfn, lhsbuf, lhslen);\n\t\t\t\t\tcs->irb.Call(incrfn, rhsbuf, rhslen);\n\t\t\t\t}\n\n\t\t\t\tret = cs->irb.SetSAALength(ret, cs->irb.Add(lhslen, rhslen));\n\t\t\t\tcs->irb.Return(ret);\n\t\t\t}\n\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tretfn = func;\n\t\t}\n\n\t\ticeAssert(retfn);\n\t\treturn retfn;\n\t}\n\n\n\n\tfir::Function* generateConstructWithElementFunction(CodegenState* cs, fir::Type* saa)\n\t{\n\t\tauto fname = misc::getMakeFromOne_FName(saa);\n\n\t\ticeAssert(isSAA(saa));\n\t\tfir::Function* retfn = cs->module->getFunction(fname);\n\n\t\tif(!retfn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ getSAASlice(saa), getSAAElm(saa) }, saa), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\tfir::Value* lhs = func->getArguments()[0];\n\t\t\tfir::Value* rhs = func->getArguments()[1];\n\n\t\t\tauto rhsslice = cs->irb.CreateValue(getSAASlice(saa, /* mut: */ false), \"rhsslice\");\n\t\t\trhsslice = cs->irb.SetArraySliceData(rhsslice, cs->irb.ImmutStackAlloc(getSAAElm(saa), rhs, \"rhsptr\"));\n\t\t\trhsslice = cs->irb.SetArraySliceLength(rhsslice, getCI(1));\n\n\t\t\tauto appf = generateConstructFromTwoFunction(cs, saa);\n\t\t\ticeAssert(appf);\n\n\t\t\tauto ret = cs->irb.Call(appf, lhs, rhsslice);\n\t\t\tcs->irb.Return(ret);\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tretfn = func;\n\t\t}\n\n\t\ticeAssert(retfn);\n\t\treturn retfn;\n\t}\n\n\n\n\n\n\n\n\n\t// TODO: this shit is bloody unmaintainable\n\tfir::Function* generateReserveAtLeastFunction(CodegenState* cs, fir::Type* saa)\n\t{\n\t\tauto fname = misc::getReserveEnough_FName(saa);\n\n\t\ticeAssert(isSAA(saa));\n\t\tfir::Function* retfn = cs->module->getFunction(fname);\n\n\t\tif(!retfn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ saa, fir::Type::getNativeWord() }, saa), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\n\t\t\tauto s1 = func->getArguments()[0];\n\t\t\tauto minsz = func->getArguments()[1];\n\n\t\t\tauto oldlen = cs->irb.GetSAALength(s1, \"oldlen\");\n\t\t\tauto oldcap = cs->irb.GetSAACapacity(s1, \"oldcap\");\n\n\t\t\tfir::IRBlock* nullrc = cs->irb.addNewBlockInFunction(\"nullrc\", func);\n\t\t\tfir::IRBlock* notnullrc = cs->irb.addNewBlockInFunction(\"notnullrc\", func);\n\t\t\tfir::IRBlock* mergerc = cs->irb.addNewBlockInFunction(\"mergerc\", func);\n\n\t\t\tauto oldrcp = cs->irb.GetSAARefCountPointer(s1, \"oldrcp\");\n\t\t\tcs->irb.CondBranch(cs->irb.ICmpEQ(oldrcp, cs->irb.IntToPointerCast(getCI(0), fir::Type::getNativeWordPtr())), nullrc, notnullrc);\n\n\n\t\t\t//? these phi nodes are for the refcount pointer of the thing we will eventually return.\n\t\t\tfir::Value* nullphi = 0;\n\t\t\tfir::Value* notnullphi = 0;\n\n\t\t\tcs->irb.setCurrentBlock(nullrc);\n\t\t\t{\n\t\t\t\tnullphi = makeNewRefCountPointer(cs, getCI(1));\n\t\t\t\tcs->irb.UnCondBranch(mergerc);\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(notnullrc);\n\t\t\t{\n\t\t\t\tnotnullphi = cs->irb.GetSAARefCountPointer(s1, \"oldref\");\n\t\t\t\tcs->irb.UnCondBranch(mergerc);\n\t\t\t}\n\n\n\t\t\tcs->irb.setCurrentBlock(mergerc);\n\t\t\t{\n\t\t\t\tauto rcptr = cs->irb.CreatePHINode(fir::Type::getNativeWordPtr());\n\t\t\t\trcptr->addIncoming(nullphi, nullrc);\n\t\t\t\trcptr->addIncoming(notnullphi, notnullrc);\n\n\t\t\t\tfir::IRBlock* returnUntouched = cs->irb.addNewBlockInFunction(\"noExpansion\", func);\n\t\t\t\tfir::IRBlock* doExpansion = cs->irb.addNewBlockInFunction(\"expand\", func);\n\n\t\t\t\tcs->irb.CondBranch(cs->irb.ICmpLEQ(minsz, oldcap), returnUntouched, doExpansion);\n\n\n\t\t\t\tcs->irb.setCurrentBlock(doExpansion);\n\t\t\t\t{\n\t\t\t\t\tauto newlen = cs->irb.Divide(cs->irb.Multiply(minsz, getCI(3)), getCI(2), \"mul1.5\");\n\n\t\t\t\t\t// call realloc. handles the null case as well, which is nice.\n\t\t\t\t\tconst auto oldbuf = cs->irb.PointerTypeCast(cs->irb.GetSAAData(s1), fir::Type::getMutInt8Ptr(), \"oldbuf\");\n\n\t\t\t\t\tauto newbytecount = cs->irb.Multiply(newlen, cs->irb.Sizeof(getSAAElm(saa)), \"newbytecount\");\n\n\t\t\t\t\tif(saa->isStringType())\n\t\t\t\t\t\tnewbytecount = cs->irb.Add(newbytecount, getCI(1));\n\n\t\t\t\t\t// if the capacity was negative, then the buffer points to constant memory that did not come from the heap!!\n\t\t\t\t\t// so, we cannot call realloc with oldbuf, and call it with NULL instead. also for strings, capacity of 0 is empty\n\t\t\t\t\t// so we do the same dealio.\n\t\t\t\t\tauto isfake = cs->irb.ICmpLEQ(oldcap, getCI(0));\n\t\t\t\t\tauto origbuf = cs->irb.Select(isfake, fir::ConstantValue::getZeroValue(fir::Type::getMutInt8Ptr()), oldbuf);\n\n\t\t\t\t\tauto _newbuf = cs->irb.Call(cs->getOrDeclareLibCFunction(REALLOCATE_MEMORY_FUNC), origbuf, newbytecount, \"newbuf\");\n\t\t\t\t\tauto newbuf = castRawBufToElmPtr(cs, saa, _newbuf);\n\n\n\t\t\t\t\t// again with the NULL thingy: now we need to (possibly) copy the data from the old buffer to the new buffer\n\t\t\t\t\t// bopian need some branching here.\n\t\t\t\t\t{\n\t\t\t\t\t\tauto needcopy = cs->irb.addNewBlockInFunction(\"copyold\", func);\n\t\t\t\t\t\tauto nocopy = cs->irb.addNewBlockInFunction(\"nocopyold\", func);\n\n\t\t\t\t\t\tcs->irb.CondBranch(isfake, needcopy, nocopy);\n\t\t\t\t\t\tcs->irb.setCurrentBlock(needcopy);\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcs->irb.Call(cs->module->getIntrinsicFunction(\"memmove\"), _newbuf, oldbuf, cs->irb.Multiply(oldlen,\n\t\t\t\t\t\t\t\tcs->irb.Sizeof(getSAAElm(saa))), /* isVolatile: */ fir::ConstantBool::get(false));\n\t\t\t\t\t\t\tcs->irb.UnCondBranch(nocopy);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcs->irb.setCurrentBlock(nocopy);\n\t\t\t\t\t}\n\n\t\t\t\t\t// null terminator\n\t\t\t\t\tif(saa->isStringType())\n\t\t\t\t\t\tcs->irb.WritePtr(fir::ConstantInt::getInt8(0), cs->irb.GetPointer(newbuf, cs->irb.Subtract(newbytecount, getCI(1))));\n\n\n\t\t\t\t\tauto ret = cs->irb.CreateValue(saa);\n\t\t\t\t\tret = cs->irb.SetSAAData(ret, newbuf);\n\t\t\t\t\tret = cs->irb.SetSAALength(ret, oldlen);\n\t\t\t\t\tret = cs->irb.SetSAACapacity(ret, newlen);\n\t\t\t\t\tret = cs->irb.SetSAARefCountPointer(ret, rcptr);\n\n\t\t\t\t\t#if DEBUG_ARRAY_ALLOCATION | DEBUG_STRING_ALLOCATION\n\t\t\t\t\t{\n\t\t\t\t\t\tcs->printIRDebugMessage(\"* SAACOM: realloc(): (ptr: %p, cap: %d / rcp: %p)\", {\n\t\t\t\t\t\t\tnewbuf, newlen, cs->irb.GetSAARefCountPointer(ret) });\n\t\t\t\t\t}\n\t\t\t\t\t#endif\n\n\t\t\t\t\tcs->irb.Return(ret);\n\t\t\t\t}\n\n\t\t\t\tcs->irb.setCurrentBlock(returnUntouched);\n\t\t\t\t{\n\t\t\t\t\t// as the name implies, do nothing.\n\t\t\t\t\tcs->irb.Return(s1);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tretfn = func;\n\t\t}\n\n\t\ticeAssert(retfn);\n\t\treturn retfn;\n\t}\n\n\n\tfir::Function* generateReserveExtraFunction(CodegenState* cs, fir::Type* saa)\n\t{\n\t\t// we can just do this in terms of reserveAtLeast.\n\n\t\tauto fname = misc::getReserveExtra_FName(saa);\n\n\t\ticeAssert(isSAA(saa));\n\t\tfir::Function* retfn = cs->module->getFunction(fname);\n\n\t\tif(!retfn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ saa, fir::Type::getNativeWord() }, saa), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\tauto s1 = func->getArguments()[0];\n\t\t\tauto extrasz = func->getArguments()[1];\n\n\t\t\tauto minsz = cs->irb.Add(cs->irb.GetSAACapacity(s1), extrasz);\n\t\t\tauto ret = cs->irb.Call(generateReserveAtLeastFunction(cs, saa), s1, minsz);\n\n\t\t\tcs->irb.Return(ret);\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tretfn = func;\n\t\t}\n\n\t\ticeAssert(retfn);\n\t\treturn retfn;\n\t}\n\n\n\n\tfir::Function* generateBoundsCheckFunction(CodegenState* cs, bool isString, bool isDecomp)\n\t{\n\t\tif(frontend::getIsNoRuntimeChecks())\n\t\t\treturn 0;\n\n\t\tauto fname = (isDecomp ? misc::getDecompBoundsCheck_FName() : misc::getBoundsCheck_FName());\n\t\tfir::Function* retfn = cs->module->getFunction(fname);\n\n\t\tif(!retfn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ fir::Type::getNativeWord(), fir::Type::getNativeWord(), fir::Type::getCharSlice(false) },\n\t\t\t\t\tfir::Type::getVoid()), fir::LinkageType::Internal);\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tfir::IRBlock* failb = cs->irb.addNewBlockInFunction(\"fail\", func);\n\t\t\tfir::IRBlock* checkneg = cs->irb.addNewBlockInFunction(\"checkneg\", func);\n\t\t\tfir::IRBlock* merge = cs->irb.addNewBlockInFunction(\"merge\", func);\n\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\tfir::Value* max = func->getArguments()[0];\n\t\t\tfir::Value* ind = func->getArguments()[1];\n\t\t\tfir::Value* res = 0;\n\n\t\t\t// if we're decomposing, it's length vs length, so compare strictly greater.\n\t\t\tif(isDecomp)    res = cs->irb.ICmpGT(ind, max);\n\t\t\telse            res = cs->irb.ICmpGEQ(ind, max);\n\n\n\t\t\tcs->irb.CondBranch(res, failb, checkneg);\n\t\t\tcs->irb.setCurrentBlock(failb);\n\t\t\t{\n\t\t\t\tif(isDecomp)\n\t\t\t\t{\n\t\t\t\t\tprintRuntimeError(cs, func->getArguments()[2], \"index '%ld' out of bounds for \"\n\t\t\t\t\t\t+ std::string(isString ? \"string\" : \"array\") + \" of length %ld\\n\", { ind, max });\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tprintRuntimeError(cs, func->getArguments()[2], \"binding of '%ld' \"\n\t\t\t\t\t\t+ std::string(isString ? \"chars\" : \"elements\") + \" out of bounds for string of length %ld\\n\", { ind, max });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(checkneg);\n\t\t\t{\n\t\t\t\tfir::Value* res = cs->irb.ICmpLT(ind, fir::ConstantInt::getNative(0));\n\t\t\t\tcs->irb.CondBranch(res, failb, merge);\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(merge);\n\t\t\t{\n\t\t\t\tcs->irb.ReturnVoid();\n\t\t\t}\n\n\t\t\tretfn = func;\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t}\n\n\t\ticeAssert(retfn);\n\t\treturn retfn;\n\t}\n\n}\n}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/glue/strings.cpp",
    "content": "// strings.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"codegen.h\"\n#include \"platform.h\"\n#include \"gluecode.h\"\n\n// generate runtime glue code\n\nnamespace cgn {\nnamespace glue {\nnamespace string\n{\n\tfir::Function* getCloneFunction(CodegenState* cs)\n\t{\n\t\treturn saa_common::generateCloneFunction(cs, fir::Type::getString());\n\t}\n\n\tfir::Function* getAppendFunction(CodegenState* cs)\n\t{\n\t\treturn saa_common::generateAppendFunction(cs, fir::Type::getString());\n\t}\n\n\tfir::Function* getCharAppendFunction(CodegenState* cs)\n\t{\n\t\treturn saa_common::generateElementAppendFunction(cs, fir::Type::getString());\n\t}\n\n\tfir::Function* getConstructFromTwoFunction(CodegenState* cs)\n\t{\n\t\treturn saa_common::generateConstructFromTwoFunction(cs, fir::Type::getString());\n\t}\n\n\tfir::Function* getConstructWithCharFunction(CodegenState* cs)\n\t{\n\t\treturn saa_common::generateConstructWithElementFunction(cs, fir::Type::getString());\n\t}\n\n\tfir::Function* getBoundsCheckFunction(CodegenState* cs, bool isDecomp)\n\t{\n\t\treturn saa_common::generateBoundsCheckFunction(cs, /* isString: */ true, isDecomp);\n\t}\n\n\tfir::Function* getCompareFunction(CodegenState* cs)\n\t{\n\t\tauto fname = misc::getCompare_FName(fir::Type::getString());\n\t\tfir::Function* cmpf = cs->module->getFunction(fname);\n\n\t\tif(!cmpf)\n\t\t{\n\t\t\t// great.\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ fir::Type::getString(), fir::Type::getString() },\n\t\t\t\tfir::Type::getNativeWord()), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\tfir::Value* s1 = func->getArguments()[0];\n\t\t\tfir::Value* s2 = func->getArguments()[1];\n\n\t\t\t/*\n\t\t\t\tint strcmp(const char* s1, const char* s2)\n\t\t\t\t{\n\t\t\t\t\twhile(*s1 && (*s1 == *s2))\n\t\t\t\t\t\ts1++, s2++;\n\n\t\t\t\t\treturn *(const unsigned char*) s1 - *(const unsigned char*) s2;\n\t\t\t\t}\n\t\t\t*/\n\n\t\t\t{\n\t\t\t\tfir::Value* str1p = cs->irb.StackAlloc(fir::Type::getMutInt8Ptr());\n\t\t\t\tcs->irb.WritePtr(cs->irb.GetSAAData(s1, \"s1\"), str1p);\n\n\t\t\t\tfir::Value* str2p = cs->irb.StackAlloc(fir::Type::getMutInt8Ptr());\n\t\t\t\tcs->irb.WritePtr(cs->irb.GetSAAData(s2, \"s2\"), str2p);\n\n\n\t\t\t\tfir::IRBlock* loopcond = cs->irb.addNewBlockInFunction(\"cond1\", func);\n\t\t\t\tfir::IRBlock* loopincr = cs->irb.addNewBlockInFunction(\"loopincr\", func);\n\t\t\t\tfir::IRBlock* merge = cs->irb.addNewBlockInFunction(\"merge\", func);\n\n\t\t\t\tcs->irb.UnCondBranch(loopcond);\n\t\t\t\tcs->irb.setCurrentBlock(loopcond);\n\t\t\t\t{\n\t\t\t\t\tfir::IRBlock* cond2 = cs->irb.addNewBlockInFunction(\"cond2\", func);\n\n\t\t\t\t\tfir::Value* str1 = cs->irb.ReadPtr(str1p);\n\t\t\t\t\tfir::Value* str2 = cs->irb.ReadPtr(str2p);\n\n\t\t\t\t\t// make sure ptr1 is not null\n\t\t\t\t\tfir::Value* cnd = cs->irb.ICmpNEQ(cs->irb.ReadPtr(str1), fir::ConstantInt::getInt8(0));\n\t\t\t\t\tcs->irb.CondBranch(cnd, cond2, merge);\n\n\t\t\t\t\tcs->irb.setCurrentBlock(cond2);\n\t\t\t\t\t{\n\t\t\t\t\t\t// check that they are equal\n\t\t\t\t\t\tfir::Value* iseq = cs->irb.ICmpEQ(cs->irb.ReadPtr(str1), cs->irb.ReadPtr(str2));\n\t\t\t\t\t\tcs->irb.CondBranch(iseq, loopincr, merge);\n\t\t\t\t\t}\n\n\n\t\t\t\t\tcs->irb.setCurrentBlock(loopincr);\n\t\t\t\t\t{\n\t\t\t\t\t\t// increment str1 and str2\n\t\t\t\t\t\tfir::Value* v1 = cs->irb.GetPointer(str1, fir::ConstantInt::getNative(1));\n\t\t\t\t\t\tfir::Value* v2 = cs->irb.GetPointer(str2, fir::ConstantInt::getNative(1));\n\n\t\t\t\t\t\tcs->irb.WritePtr(v1, str1p);\n\t\t\t\t\t\tcs->irb.WritePtr(v2, str2p);\n\n\t\t\t\t\t\tcs->irb.UnCondBranch(loopcond);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcs->irb.setCurrentBlock(merge);\n\t\t\t\tfir::Value* ret = cs->irb.Subtract(cs->irb.ReadPtr(cs->irb.ReadPtr(str1p)),\n\t\t\t\t\tcs->irb.ReadPtr(cs->irb.ReadPtr(str2p)));\n\n\t\t\t\tret = cs->irb.IntSizeCast(ret, func->getReturnType());\n\n\t\t\t\tcs->irb.Return(ret);\n\t\t\t}\n\n\t\t\tcmpf = func;\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t}\n\n\t\ticeAssert(cmpf);\n\t\treturn cmpf;\n\t}\n\n\n\tstatic void _doRefCount(CodegenState* cs, fir::Function* func, bool decrement)\n\t{\n\t\tauto str = func->getArguments()[0];\n\t\tauto rcp = cs->irb.GetSAARefCountPointer(str, \"rcp\");\n\n\t\tfir::IRBlock* merge = cs->irb.addNewBlockInFunction(\"merge\", func);\n\t\tfir::IRBlock* dorc = cs->irb.addNewBlockInFunction(\"dorc\", func);\n\n\t\tcs->irb.CondBranch(cs->irb.ICmpEQ(rcp, fir::ConstantValue::getZeroValue(fir::Type::getNativeWordPtr())),\n\t\t\tmerge, dorc);\n\n\t\tcs->irb.setCurrentBlock(dorc);\n\t\t{\n\t\t\tauto oldrc = cs->irb.ReadPtr(rcp, \"oldrc\");\n\t\t\tauto newrc = cs->irb.Add(oldrc, fir::ConstantInt::getNative(decrement ? -1 : 1));\n\n\t\t\tcs->irb.SetSAARefCount(str, newrc);\n\n\t\t\t#if DEBUG_STRING_REFCOUNTING\n\t\t\t{\n\t\t\t\tstd::string x = decrement ? \"(decr)\" : \"(incr)\";\n\n\t\t\t\tcs->printIRDebugMessage(\"* STRING: \" + x + \" - new rc of: (ptr: %p, len: %ld, cap: %ld) = %d\",\n\t\t\t\t\t{ cs->irb.GetSAAData(str), cs->irb.GetSAALength(str), cs->irb.GetSAACapacity(str), cs->irb.GetSAARefCount(str) });\n\t\t\t}\n\t\t\t#endif\n\n\t\t\tif(decrement)\n\t\t\t{\n\t\t\t\tfir::IRBlock* dofree = cs->irb.addNewBlockInFunction(\"dofree\", func);\n\t\t\t\tcs->irb.CondBranch(cs->irb.ICmpEQ(newrc, fir::ConstantInt::getNative(0)),\n\t\t\t\t\tdofree, merge);\n\n\t\t\t\tcs->irb.setCurrentBlock(dofree);\n\t\t\t\t{\n\t\t\t\t\tauto freefn = cs->getOrDeclareLibCFunction(FREE_MEMORY_FUNC);\n\t\t\t\t\ticeAssert(freefn);\n\n\t\t\t\t\tauto buf = cs->irb.GetSAAData(str, \"buf\");\n\t\t\t\t\tbuf = cs->irb.PointerTypeCast(buf, fir::Type::getMutInt8Ptr());\n\n\t\t\t\t\tcs->irb.Call(freefn, buf);\n\t\t\t\t\tcs->irb.Call(freefn, cs->irb.PointerTypeCast(cs->irb.GetSAARefCountPointer(str), fir::Type::getMutInt8Ptr()));\n\n\t\t\t\t\t#if DEBUG_STRING_ALLOCATION\n\t\t\t\t\t{\n\t\t\t\t\t\tcs->printIRDebugMessage(\"* STRING: free(): (ptr: %p / rcp: %p)\", {\n\t\t\t\t\t\t\tbuf, cs->irb.GetSAARefCountPointer(str) });\n\t\t\t\t\t}\n\t\t\t\t\t#endif\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcs->irb.UnCondBranch(merge);\n\t\t}\n\n\t\tcs->irb.setCurrentBlock(merge);\n\t\t{\n\t\t\tcs->irb.ReturnVoid();\n\t\t}\n\t}\n\n\n\n\n\tfir::Function* getRefCountIncrementFunction(CodegenState* cs)\n\t{\n\t\tauto fname = misc::getIncrRefcount_FName(fir::Type::getString());\n\t\tfir::Function* retfn = cs->module->getFunction(fname);\n\n\t\tif(!retfn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ fir::Type::getString() }, fir::Type::getVoid()), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\t_doRefCount(cs, func, false);\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tretfn = func;\n\t\t}\n\n\t\ticeAssert(retfn);\n\t\treturn retfn;\n\t}\n\n\tfir::Function* getRefCountDecrementFunction(CodegenState* cs)\n\t{\n\t\tauto fname = misc::getDecrRefcount_FName(fir::Type::getString());\n\t\tfir::Function* retfn = cs->module->getFunction(fname);\n\n\t\tif(!retfn)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ fir::Type::getString() }, fir::Type::getVoid()), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\t_doRefCount(cs, func, true);\n\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t\tretfn = func;\n\t\t}\n\n\t\ticeAssert(retfn);\n\t\treturn retfn;\n\t}\n\n\n\n\n\n\tfir::Function* getUnicodeLengthFunction(CodegenState* cs)\n\t{\n\t\tauto fname = misc::getUtf8Length_FName();\n\t\tfir::Function* lenf = cs->module->getFunction(fname);\n\n\t\tif(!lenf)\n\t\t{\n\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fname,\n\t\t\t\tfir::FunctionType::get({ fir::Type::getInt8Ptr() }, fir::Type::getNativeWord()), fir::LinkageType::Internal);\n\n\t\t\tfunc->setAlwaysInline();\n\n\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\tfir::Value* _ptr = func->getArguments()[0];\n\t\t\ticeAssert(_ptr);\n\n\t\t\tfir::Value* ptrp = cs->irb.StackAlloc(fir::Type::getInt8Ptr());\n\t\t\tcs->irb.WritePtr(_ptr, ptrp);\n\n\t\t\t/*\n\n\t\t\t\tpublic fn Utf8Length(_text: i8*) -> i64\n\t\t\t\t{\n\t\t\t\t\tvar len = 0\n\t\t\t\t\tvar text = _text\n\n\n\t\t\t\t\twhile *text != 0\n\t\t\t\t\t{\n\t\t\t\t\t\tif (*text & 0xC0) != 0x80\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlen += 1\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttext = text + 1\n\t\t\t\t\t}\n\n\t\t\t\t\treturn len\n\t\t\t\t}\n\t\t\t*/\n\t\t\tauto i0 = fir::ConstantInt::getNative(0);\n\t\t\tauto i1 = fir::ConstantInt::getNative(1);\n\t\t\tauto c0 = fir::ConstantInt::getInt8(0);\n\n\t\t\tfir::Value* lenp = cs->irb.StackAlloc(fir::Type::getNativeWord());\n\t\t\tcs->irb.WritePtr(i0, lenp);\n\n\n\t\t\tfir::IRBlock* cond = cs->irb.addNewBlockInFunction(\"cond\", func);\n\t\t\tfir::IRBlock* body = cs->irb.addNewBlockInFunction(\"body\", func);\n\t\t\tfir::IRBlock* merge = cs->irb.addNewBlockInFunction(\"merge\", func);\n\n\n\t\t\tfir::Value* isnull = cs->irb.ICmpEQ(fir::ConstantValue::getZeroValue(fir::Type::getInt8Ptr()), _ptr);\n\t\t\tcs->irb.CondBranch(isnull, merge, cond);\n\n\t\t\tcs->irb.setCurrentBlock(cond);\n\t\t\t{\n\t\t\t\tauto ch = cs->irb.ReadPtr(cs->irb.ReadPtr(ptrp));\n\t\t\t\tauto isnotzero = cs->irb.ICmpNEQ(ch, c0);\n\n\t\t\t\tcs->irb.CondBranch(isnotzero, body, merge);\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(body);\n\t\t\t{\n\t\t\t\t// if statement\n\t\t\t\tauto ch = cs->irb.ReadPtr(cs->irb.ReadPtr(ptrp));\n\n\t\t\t\tauto mask = cs->irb.BitwiseAND(ch, cs->irb.IntSizeCast(fir::ConstantInt::getUint8(0xC0), fir::Type::getInt8()));\n\t\t\t\tauto isch = cs->irb.ICmpNEQ(mask, cs->irb.IntSizeCast(fir::ConstantInt::getUint8(0x80), fir::Type::getInt8()));\n\n\t\t\t\tfir::IRBlock* incr = cs->irb.addNewBlockInFunction(\"incr\", func);\n\t\t\t\tfir::IRBlock* skip = cs->irb.addNewBlockInFunction(\"skip\", func);\n\n\t\t\t\tcs->irb.CondBranch(isch, incr, skip);\n\t\t\t\tcs->irb.setCurrentBlock(incr);\n\t\t\t\t{\n\t\t\t\t\tcs->irb.WritePtr(cs->irb.Add(cs->irb.ReadPtr(lenp), i1), lenp);\n\n\t\t\t\t\tcs->irb.UnCondBranch(skip);\n\t\t\t\t}\n\n\t\t\t\tcs->irb.setCurrentBlock(skip);\n\t\t\t\t{\n\t\t\t\t\tauto newptr = cs->irb.GetPointer(cs->irb.ReadPtr(ptrp), i1);\n\t\t\t\t\tcs->irb.WritePtr(newptr, ptrp);\n\n\t\t\t\t\tcs->irb.UnCondBranch(cond);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcs->irb.setCurrentBlock(merge);\n\t\t\t{\n\t\t\t\tauto len = cs->irb.ReadPtr(lenp);\n\t\t\t\tcs->irb.Return(len);\n\t\t\t}\n\n\n\t\t\tlenf = func;\n\t\t\tcs->irb.setCurrentBlock(restore);\n\t\t}\n\n\t\ticeAssert(lenf);\n\t\treturn lenf;\n\t}\n}\n}\n}\n\n"
  },
  {
    "path": "source/codegen/literals.cpp",
    "content": "// literals.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"codegen.h\"\n\nCGResult sst::LiteralNumber::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\n\tif(this->type->isConstantNumberType())\n\t{\n\t\tif(infer && !infer->isPrimitiveType())\n\t\t\tinfer = 0;\n\n\t\treturn CGResult(cs->unwrapConstantNumber(fir::ConstantNumber::get(this->type->toConstantNumberType(), this->num), infer));\n\t}\n\telse\n\t{\n\t\tif(this->type->isFloatingPointType())\n\t\t\treturn CGResult(fir::ConstantFP::get(this->type, this->num.toDouble()));\n\n\t\telse\n\t\t\treturn CGResult(fir::ConstantInt::get(this->type, this->type->isSignedIntType() ? this->num.toLLong() : this->num.toULLong()));\n\t}\n}\n\nCGResult sst::LiteralArray::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tif(this->type->isArrayType())\n\t{\n\t\tauto elmty = this->type->toArrayType()->getElementType();\n\t\tif(fir::isRefCountedType(elmty))\n\t\t\terror(this, \"cannot have refcounted type in array literal\");\n\n\t\tstd::vector<fir::ConstantValue*> vals;\n\t\tfor(auto v : this->values)\n\t\t{\n\t\t\tauto cv = dcast(fir::ConstantValue, v->codegen(cs, elmty).value);\n\t\t\tif(!cv)\n\t\t\t\terror(v, \"constant value required in fixed array literal\");\n\n\t\t\tif(cv->getType() != elmty)\n\t\t\t\terror(v, \"mismatched type for array literal; expected element type '%s', found '%s'\", elmty, cv->getType());\n\n\t\t\tvals.push_back(cv);\n\t\t}\n\n\t\t// ok\n\t\treturn CGResult(fir::ConstantArray::get(this->type, vals));\n\t}\n\telse if(this->type->isDynamicArrayType() || this->type->isArraySliceType())\n\t{\n\t\t// ok, this can basically be anything.\n\t\t// no restrictions.\n\n\t\tfir::Value* returnValue = 0;\n\t\tauto elmty = this->type->getArrayElementType();\n\n\t\tif(this->values.empty())\n\t\t{\n\t\t\t// if our element type is void, and there is no infer... die.\n\t\t\tif(!infer || (elmty->isVoidType() && infer == 0) || (infer && infer->getArrayElementType()->isVoidType()))\n\t\t\t\terror(this, \"failed to infer type for empty array literal\");\n\n\t\t\tauto z = fir::ConstantInt::getNative(0);\n\t\t\tif(infer->isDynamicArrayType())\n\t\t\t{\n\t\t\t\t// ok.\n\t\t\t\telmty = infer->getArrayElementType();\n\t\t\t\treturnValue = fir::ConstantDynamicArray::get(fir::DynamicArrayType::get(elmty),\n\t\t\t\t\tfir::ConstantValue::getZeroValue(elmty->getPointerTo()), z, z);\n\t\t\t}\n\t\t\telse if(infer->isArraySliceType())\n\t\t\t{\n\t\t\t\telmty = infer->getArrayElementType();\n\n\t\t\t\t//* note: it's clearly a null pointer, so it must be immutable.\n\t\t\t\treturnValue = fir::ConstantArraySlice::get(fir::ArraySliceType::get(elmty, false),\n\t\t\t\t\tfir::ConstantValue::getZeroValue(elmty->getPointerTo()), z);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\terror(this, \"incorrectly inferred type '%s' for empty array literal\", infer);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// make a function specifically to initialise this thing\n\t\t\tstatic size_t _id = 0;\n\n\t\t\tauto theId = _id++;\n\n\t\t\tauto _aty = fir::ArrayType::get(elmty, this->values.size());\n\t\t\tauto array = cs->module->createGlobalVariable(fir::Name::obfuscate(\"_FV_DAR_\", theId),\n\t\t\t\t_aty, fir::ConstantArray::getZeroValue(_aty), false, fir::LinkageType::Internal);\n\n\t\t\t{\n\t\t\t\tauto restore = cs->irb.getCurrentBlock();\n\n\t\t\t\tfir::Function* func = cs->module->getOrCreateFunction(fir::Name::obfuscate(\"init_array\", theId),\n\t\t\t\t\tfir::FunctionType::get({ }, fir::Type::getVoid()), fir::LinkageType::Internal);\n\n\t\t\t\tfir::IRBlock* entry = cs->irb.addNewBlockInFunction(\"entry\", func);\n\t\t\t\tcs->irb.setCurrentBlock(entry);\n\n\t\t\t\tauto arrptr = cs->irb.AddressOf(array, true);\n\n\t\t\t\tstd::vector<fir::Value*> vals;\n\t\t\t\tfor(auto v : this->values)\n\t\t\t\t{\n\t\t\t\t\tauto vl = v->codegen(cs, elmty).value;\n\t\t\t\t\tif(vl->getType() != elmty)\n\t\t\t\t\t\tvl = cs->oneWayAutocast(vl, elmty);\n\n\t\t\t\t\tif(vl->getType() != elmty)\n\t\t\t\t\t{\n\t\t\t\t\t\terror(v, \"mismatched type for array literal; expected element type '%s', found '%s'\",\n\t\t\t\t\t\t\telmty, vl->getType());\n\t\t\t\t\t}\n\n\t\t\t\t\t// ok, it works\n\t\t\t\t\tvals.push_back(vl);\n\t\t\t\t}\n\n\t\t\t\t// ok -- basically unroll the loop, except there's no loop -- so we're just...\n\t\t\t\t// doing a thing.\n\t\t\t\tfor(size_t i = 0; i < vals.size(); i++)\n\t\t\t\t{\n\t\t\t\t\t// offset by 1\n\t\t\t\t\tfir::Value* ptr = cs->irb.ConstGEP2(arrptr, 0, i);\n\t\t\t\t\tcs->irb.WritePtr(vals[i], ptr);\n\t\t\t\t}\n\n\t\t\t\tcs->irb.ReturnVoid();\n\t\t\t\tcs->irb.setCurrentBlock(restore);\n\n\t\t\t\t// ok, call the function\n\t\t\t\tcs->irb.Call(func);\n\t\t\t}\n\n\t\t\t// return it\n\t\t\tif(this->type->isDynamicArrayType())\n\t\t\t{\n\t\t\t\tauto arrptr = cs->irb.AddressOf(array, true);\n\n\t\t\t\tauto aa = cs->irb.CreateValue(this->type->toDynamicArrayType());\n\n\t\t\t\taa = cs->irb.SetSAAData(aa, cs->irb.ConstGEP2(arrptr, 0, 0));\n\t\t\t\taa = cs->irb.SetSAALength(aa, fir::ConstantInt::getNative(this->values.size()));\n\t\t\t\taa = cs->irb.SetSAACapacity(aa, fir::ConstantInt::getNative(-1));\n\t\t\t\taa = cs->irb.SetSAARefCountPointer(aa, fir::ConstantValue::getZeroValue(fir::Type::getNativeWordPtr()));\n\n\t\t\t\treturnValue = aa;\n\t\t\t}\n\t\t\telse if(this->type->isArraySliceType())\n\t\t\t{\n\t\t\t\tauto arrptr = cs->irb.AddressOf(array, true);\n\n\t\t\t\tauto aa = cs->irb.CreateValue(this->type->toArraySliceType());\n\n\t\t\t\taa = cs->irb.SetArraySliceData(aa, cs->irb.PointerTypeCast(cs->irb.ConstGEP2(arrptr, 0, 0), elmty->getPointerTo()));\n\t\t\t\taa = cs->irb.SetArraySliceLength(aa, fir::ConstantInt::getNative(this->values.size()));\n\n\t\t\t\treturnValue = aa;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\terror(this, \"what???\");\n\t\t\t}\n\t\t}\n\n\t\ticeAssert(returnValue);\n\t\tcs->addRAIIOrRCValueIfNecessary(returnValue);\n\n\t\treturn CGResult(returnValue);\n\t}\n\telse\n\t{\n\t\terror(this, \"what?\");\n\t}\n}\n\nCGResult sst::LiteralTuple::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\ticeAssert(this->type->isTupleType());\n\n\tbool allConst = true;\n\tstd::vector<fir::Value*> vals;\n\n\tfor(size_t i = 0; i < this->values.size(); i++)\n\t{\n\t\tauto ty = this->type->toTupleType()->getElementN(i);\n\t\tauto vr = this->values[i]->codegen(cs, ty).value;\n\n\t\tif(vr->getType() != ty)\n\t\t\tvr = cs->oneWayAutocast(vr, ty);\n\n\t\tif(vr->getType() != ty)\n\t\t{\n\t\t\terror(this->values[i], \"mismatched types in tuple element %d; expected type '%s', found type '%s'\",\n\t\t\t\ti, ty, vr->getType());\n\t\t}\n\n\t\tallConst &= (dcast(fir::ConstantValue, vr) != nullptr);\n\t\tvals.push_back(vr);\n\t}\n\n\tif(allConst)\n\t{\n\t\tstd::vector<fir::ConstantValue*> consts = zfu::map(vals, [](auto e) -> auto { return dcast(fir::ConstantValue, e); });\n\t\treturn CGResult(fir::ConstantTuple::get(consts));\n\t}\n\telse\n\t{\n\t\tauto tup = cs->irb.CreateValue(this->type);\n\t\tfor(size_t i = 0; i < vals.size(); i++)\n\t\t\ttup = cs->irb.InsertValue(tup, { i }, vals[i]);\n\n\t\treturn CGResult(tup);\n\t}\n}\n\n\n\n\n\nCGResult sst::LiteralNull::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tfir::Value* val = 0;\n\tif(infer)   val = fir::ConstantValue::getZeroValue(infer);\n\telse        val = fir::ConstantValue::getNull();\n\n\treturn CGResult(val);\n}\n\nCGResult sst::LiteralBool::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\treturn CGResult(fir::ConstantBool::get(this->value));\n}\n\nCGResult sst::LiteralChar::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\treturn CGResult(fir::ConstantInt::getInt8(static_cast<int8_t>(this->value)));\n}\n\nCGResult sst::LiteralString::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\t// allow automatic coercion of string literals into i8*\n\tif(this->isCString || infer == fir::Type::getInt8Ptr())\n\t{\n\t\t// good old i8*\n\t\tfir::Value* stringVal = cs->module->createGlobalString(this->str);\n\t\treturn CGResult(stringVal);\n\t}\n\telse\n\t{\n\t\tauto str = cs->module->createGlobalString(this->str);\n\t\tauto slc = fir::ConstantArraySlice::get(fir::Type::getCharSlice(false), str, fir::ConstantInt::getNative(this->str.length()));\n\n\t\treturn CGResult(slc);\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/logical.cpp",
    "content": "// logical.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"errors.h\"\n#include \"codegen.h\"\n#include \"typecheck.h\"\n\nnamespace cgn\n{\n\tstatic CGResult doLogicalOr(CodegenState* cs, sst::BinaryOp* b)\n\t{\n\t\t// use a phi thing.\n\t\tauto cb = cs->irb.getCurrentBlock();\n\n\n\t\tauto pass = cs->irb.addNewBlockAfter(\"shortcircuit-or-\" + b->loc.shortString(), cb);\n\t\tauto check = cs->irb.addNewBlockAfter(\"secondcond-or-\" + b->loc.shortString(), pass);\n\t\tauto merge = cs->irb.addNewBlockAfter(\"merge-or-\" + b->loc.shortString(), check);\n\n\t\t// ok.\n\t\t// always generate the first thing.\n\n\t\tfir::Value* left = b->left->codegen(cs, fir::Type::getBool()).value;\n\t\tif(!left->getType()->isBoolType())\n\t\t\terror(b->left, \"non-boolean type '%s' cannot be used as a conditional\", left->getType());\n\n\t\t// ok, compare first.\n\t\tfir::Value* cmpres = cs->irb.ICmpEQ(left, fir::ConstantBool::get(true));\n\t\tcs->irb.CondBranch(cmpres, pass, check);\n\n\t\tcs->irb.setCurrentBlock(pass);\n\t\t{\n\t\t\tcs->irb.UnCondBranch(merge);\n\t\t}\n\n\t\tcs->irb.setCurrentBlock(check);\n\t\t{\n\t\t\t// ok, check the second\n\t\t\tfir::Value* right = b->right->codegen(cs, fir::Type::getBool()).value;\n\t\t\tif(!right->getType()->isBoolType())\n\t\t\t\terror(b->right, \"non-boolean type '%s' cannot be used as a conditional\", right->getType());\n\n\t\t\tfir::Value* cmpres = cs->irb.ICmpEQ(right, fir::ConstantBool::get(true));\n\t\t\tcs->irb.CondBranch(cmpres, pass, merge);\n\t\t}\n\n\t\tauto fromBlk = cs->irb.getCurrentBlock();\n\n\t\tcs->irb.setCurrentBlock(merge);\n\n\t\tauto phi = cs->irb.CreatePHINode(fir::Type::getBool());\n\t\tphi->addIncoming(fir::ConstantBool::get(true), pass);\n\t\tphi->addIncoming(fir::ConstantBool::get(false), fromBlk);\n\n\t\treturn CGResult(phi);\n\t}\n\n\n\tstatic CGResult doLogicalAnd(CodegenState* cs, sst::BinaryOp* b)\n\t{\n\t\t// use a phi thing.\n\t\tauto cb = cs->irb.getCurrentBlock();\n\n\t\tauto fail = cs->irb.addNewBlockAfter(\"shortcircuit-and-\" + b->loc.shortString(), cb);\n\t\tauto check = cs->irb.addNewBlockAfter(\"secondcond-and-\" + b->loc.shortString(), fail);\n\t\tauto merge = cs->irb.addNewBlockAfter(\"merge-and-\" + b->loc.shortString(), check);\n\n\t\t// ok.\n\t\t// always generate the first thing.\n\n\t\tfir::Value* left = b->left->codegen(cs, fir::Type::getBool()).value;\n\t\tif(!left->getType()->isBoolType())\n\t\t\terror(b->left, \"non-boolean type '%s' cannot be used as a conditional\", left->getType());\n\n\t\t// ok, compare first.\n\t\tfir::Value* cmpres = cs->irb.ICmpEQ(left, fir::ConstantBool::get(true));\n\t\tcs->irb.CondBranch(cmpres, check, fail);\n\n\t\tcs->irb.setCurrentBlock(fail);\n\t\t{\n\t\t\t// break straight to merge\n\t\t\tcs->irb.UnCondBranch(merge);\n\t\t}\n\n\t\tcs->irb.setCurrentBlock(check);\n\t\t{\n\t\t\t// ok, check the second\n\t\t\tfir::Value* right = b->right->codegen(cs, fir::Type::getBool()).value;\n\t\t\tif(!right->getType()->isBoolType())\n\t\t\t\terror(b->right, \"non-boolean type '%s' cannot be used as a conditional\", right->getType());\n\n\t\t\tfir::Value* cmpres = cs->irb.ICmpEQ(right, fir::ConstantBool::get(true));\n\t\t\tcs->irb.CondBranch(cmpres, merge, fail);\n\t\t}\n\n\t\tauto fromBlk = cs->irb.getCurrentBlock();\n\n\t\tcs->irb.setCurrentBlock(merge);\n\n\t\tauto phi = cs->irb.CreatePHINode(fir::Type::getBool());\n\t\tphi->addIncoming(fir::ConstantBool::get(true), fromBlk);\n\t\tphi->addIncoming(fir::ConstantBool::get(false), fail);\n\n\t\treturn CGResult(phi);\n\t}\n\n\n\n\n\n\n\tCGResult CodegenState::performLogicalBinaryOperation(sst::BinaryOp* bo)\n\t{\n\t\tif(bo->op == \"&&\")  return doLogicalAnd(this, bo);\n\t\telse                return doLogicalOr(this, bo);\n\t}\n\n}\n\n\n"
  },
  {
    "path": "source/codegen/loops.cpp",
    "content": "// loops.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"codegen.h\"\n#include \"memorypool.h\"\n\nCGResult sst::WhileLoop::_codegen(cgn::CodegenState* cs, fir::Type* inferred)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tif(this->isDoVariant && !this->cond)\n\t{\n\t\tthis->body->codegen(cs);\n\t\treturn CGResult(0);\n\t}\n\n\n\n\tauto loop = cs->irb.addNewBlockAfter(\"loop-\" + this->loc.shortString(), cs->irb.getCurrentBlock());\n\tfir::IRBlock* merge = 0;\n\n\tif(!this->elideMergeBlock)\n\t\tmerge = cs->irb.addNewBlockAfter(\"merge-\" + this->loc.shortString(), cs->irb.getCurrentBlock());\n\n\telse if(!this->isDoVariant)\n\t\terror(this, \"internal error: cannot elide merge block with non-do while loop\");\n\n\n\n\tauto getcond = [](cgn::CodegenState* cs, Expr* c) -> fir::Value* {\n\n\t\tauto cv = cs->oneWayAutocast(c->codegen(cs, fir::Type::getBool()).value, fir::Type::getBool());\n\t\tif(cv->getType() != fir::Type::getBool())\n\t\t\terror(c, \"non-boolean expression with type '%s' cannot be used as a conditional\", cv->getType());\n\n\t\t// ok\n\t\treturn cv;\n\t};\n\n\n\n\tif(this->isDoVariant)\n\t{\n\t\tcs->irb.UnCondBranch(loop);\n\t\tcs->irb.setCurrentBlock(loop);\n\n\t\tcs->enterBreakableBody(cgn::ControlFlowPoint(this->body, merge, loop));\n\t\t{\n\t\t\tthis->body->codegen(cs);\n\t\t}\n\t\tcs->leaveBreakableBody();\n\n\t\t// if merge == NULL, that means we're suppose to elide the merge block.\n\t\t// so, don't insert any more instructions.\n\t\tif(merge)\n\t\t{\n\t\t\ticeAssert(!cs->irb.getCurrentBlock()->isTerminated());\n\t\t\tif(this->cond)\n\t\t\t{\n\t\t\t\ticeAssert(this->cond);\n\t\t\t\tauto condv = getcond(cs, this->cond);\n\t\t\t\tcs->irb.CondBranch(condv, loop, merge);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcs->irb.UnCondBranch(merge);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\ticeAssert(cs->irb.getCurrentBlock()->isTerminated());\n\t\t}\n\t}\n\telse\n\t{\n\t\tauto check = cs->irb.addNewBlockAfter(\"check\", cs->irb.getCurrentBlock());\n\t\tcs->irb.UnCondBranch(check);\n\t\tcs->irb.setCurrentBlock(check);\n\n\t\t// ok\n\t\ticeAssert(this->cond);\n\t\ticeAssert(merge);\n\t\tauto condv = getcond(cs, this->cond);\n\t\tcs->irb.CondBranch(condv, loop, merge);\n\n\t\tcs->irb.setCurrentBlock(loop);\n\n\t\tcs->enterBreakableBody(cgn::ControlFlowPoint(this->body, merge, check));\n\t\t{\n\t\t\tthis->body->codegen(cs);\n\t\t}\n\t\tcs->leaveBreakableBody();\n\n\t\t// ok, do a jump back to the top\n\t\tcs->irb.UnCondBranch(check);\n\t}\n\n\tcs->irb.setCurrentBlock(merge);\n\n\treturn CGResult(0);\n}\n\nstd::vector<sst::Block*> sst::WhileLoop::getBlocks()\n{\n\treturn { this->body };\n}\n\n\n\n\n\n\n\n\n\nCGResult sst::ForeachLoop::_codegen(cgn::CodegenState* cs, fir::Type* inferred)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\t//? this will change when we get iterators.\n\t//* but, for now, the basic model is the same for all types -- we get a pointer, we have a starting index, and we have a count.\n\t//* for ranges, we also have an increment, but for the rest it will be 1.\n\n\t/*\n\t\tinit (current):\n\t\t\tint start = $start\n\t\t\tint end = $end\n\t\t\tint step = $step\n\n\t\tcheck:\n\t\t\tif start < end goto loop else goto merge\n\n\t\tloop:\n\t\t\t.. do things ..\n\n\t\t\tstart += step\n\t\t\tgoto check\n\n\t\tmerge:\n\t\t\t.. continue ..\n\t*/\n\n\t// auto prevblock = cs->irb.getCurrentBlock();\n\n\tauto check = cs->irb.addNewBlockAfter(\"check\", cs->irb.getCurrentBlock());\n\tauto loop = cs->irb.addNewBlockAfter(\"loop\", cs->irb.getCurrentBlock());\n\tauto merge = cs->irb.addNewBlockAfter(\"merge\", cs->irb.getCurrentBlock());\n\n\tfir::Value* end = 0;\n\tfir::Value* step = 0;\n\n\tfir::Value* idxptr = cs->irb.StackAlloc(fir::Type::getNativeWord());\n\tfir::Value* iterptr = cs->irb.StackAlloc(fir::Type::getNativeWord());\n\n\tauto [ array, vk ] = this->array->codegen(cs);\n\t(void) vk;\n\n\tif(array->getType()->isRangeType())\n\t{\n\t\tcs->irb.WritePtr(cs->irb.GetRangeLower(array), idxptr);\n\t\tend = cs->irb.GetRangeUpper(array);\n\t\tstep = cs->irb.GetRangeStep(array);\n\n\t\t//* overly verbose explanation:\n\t\t/*\n\t\t\tHere's the deal: most of the time we're dealing with arrays, so we just make this a little bit easier in that case.\n\t\t\twe compare start < end as the condition, meaning that 'end' is really a length.\n\n\t\t\tfor ranges however, (since we normalise the half-open range to an open range), we actually want to reach the ending value.\n\t\t\tso, we just add 1 to end. this is independent of the step size.\n\t\t*/\n\n\t\t//! note: again for negative ranges, we should be subtracting 1 instead.\n\n\t\tend = cs->irb.Add(end, cs->irb.Select(cs->irb.ICmpGEQ(step, fir::ConstantInt::getNative(0)),\n\t\t\tfir::ConstantInt::getNative(1), fir::ConstantInt::getNative(-1)));\n\t}\n\telse\n\t{\n\t\tcs->irb.WritePtr(fir::ConstantInt::getNative(0), idxptr);\n\t\tstep = fir::ConstantInt::getNative(1);\n\n\t\tif(array->getType()->isDynamicArrayType())\n\t\t{\n\t\t\tend = cs->irb.GetSAALength(array);\n\t\t}\n\t\telse if(array->getType()->isArraySliceType())\n\t\t{\n\t\t\tend = cs->irb.GetArraySliceLength(array);\n\t\t}\n\t\telse if(array->getType()->isStringType())\n\t\t{\n\t\t\tend = cs->irb.GetSAALength(array);\n\t\t}\n\t\telse if(array->getType()->isArrayType())\n\t\t{\n\t\t\tend = fir::ConstantInt::getNative(array->getType()->toArrayType()->getArraySize());\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(this->array, \"unsupported type '%s' in foreach loop\", array->getType());\n\t\t}\n\t}\n\n\tcs->irb.UnCondBranch(check);\n\tcs->irb.setCurrentBlock(check);\n\n\t//! here's some special shit where we handle ranges with start > end\n\tfir::Value* cond = 0;\n\tif(array->getType()->isRangeType())\n\t{\n\t\tcond = cs->irb.Select(cs->irb.ICmpGT(step, fir::ConstantInt::getNative(0)),\n\t\t\tcs->irb.ICmpLT(cs->irb.ReadPtr(idxptr), end),\t\t// i < end for step > 0\n\t\t\tcs->irb.ICmpGT(cs->irb.ReadPtr(idxptr), end));\t\t// i > end for step < 0\n\t}\n\telse\n\t{\n\t\tcond = cs->irb.ICmpLT(cs->irb.ReadPtr(idxptr), end);\n\t}\n\n\ticeAssert(cond);\n\tcs->irb.CondBranch(cond, loop, merge);\n\n\tcs->irb.setCurrentBlock(loop);\n\t{\n\t\tfir::Value* theptr = 0;\n\t\tif(array->getType()->isRangeType())\n\t\t\ttheptr = idxptr;\n\n\t\telse if(array->getType()->isDynamicArrayType())\n\t\t\ttheptr = cs->irb.GetPointer(cs->irb.GetSAAData(array), cs->irb.ReadPtr(idxptr));\n\n\t\telse if(array->getType()->isArraySliceType())\n\t\t\ttheptr = cs->irb.GetPointer(cs->irb.GetArraySliceData(array), cs->irb.ReadPtr(idxptr));\n\n\t\telse if(array->getType()->isStringType())\n\t\t\ttheptr = cs->irb.PointerTypeCast(cs->irb.GetPointer(cs->irb.GetSAAData(array), cs->irb.ReadPtr(idxptr)), fir::Type::getInt8Ptr());\n\n\t\telse if(array->getType()->isArrayType())\n\t\t{\n\t\t\tfir::Value* arrptr = 0;\n\t\t\tif(array->islvalue())\n\t\t\t{\n\t\t\t\tarrptr = cs->irb.AddressOf(array, false);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tarrptr = cs->irb.CreateLValue(array->getType());\n\t\t\t\tcs->irb.Store(array, arrptr);\n\t\t\t\tarrptr->makeConst();\n\t\t\t}\n\n\t\t\ttheptr = cs->irb.GetPointer(cs->irb.ConstGEP2(arrptr, 0, 0), cs->irb.ReadPtr(idxptr));\n\t\t}\n\t\telse\n\t\t{\n\t\t\ticeAssert(0);\n\t\t}\n\n\n\t\t// make the block\n\t\tcs->enterBreakableBody(cgn::ControlFlowPoint(this->body, merge, check));\n\t\t{\n\t\t\t// msvc: structured bindings cannot be captured\n\t\t\t// what the FUCK???\n\t\t\tauto _array = array;\n\t\t\tthis->body->preBodyCode = [cs, theptr, _array, iterptr, this]() {\n\n\t\t\t\t// TODO: is this correct???\n\t\t\t\tauto res = CGResult(cs->irb.Dereference(theptr));\n\t\t\t\tcs->generateDecompositionBindings(this->mappings, res, !(_array->getType()->isRangeType() || _array->getType()->isStringType()));\n\n\t\t\t\tif(this->indexVar)\n\t\t\t\t{\n\t\t\t\t\tauto idx = util::pool<RawValueExpr>(this->indexVar->loc, fir::Type::getNativeWord());\n\t\t\t\t\tidx->rawValue = CGResult(cs->irb.ReadPtr(iterptr));\n\n\t\t\t\t\tthis->indexVar->init = idx;\n\t\t\t\t\tthis->indexVar->codegen(cs);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis->body->codegen(cs);\n\t\t}\n\t\tcs->leaveBreakableBody();\n\n\n\t\t// increment the index\n\t\tcs->irb.WritePtr(cs->irb.Add(cs->irb.ReadPtr(idxptr), step), idxptr);\n\t\tcs->irb.WritePtr(cs->irb.Add(cs->irb.ReadPtr(iterptr), fir::ConstantInt::getNative(1)), iterptr);\n\n\t\tcs->irb.UnCondBranch(check);\n\t}\n\n\tcs->irb.setCurrentBlock(merge);\n\n\treturn CGResult(0);\n}\n\nstd::vector<sst::Block*> sst::ForeachLoop::getBlocks()\n{\n\treturn { this->body };\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/misc.cpp",
    "content": "// misc.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"codegen.h\"\n\nCGResult sst::TypeExpr::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\treturn CGResult(fir::ConstantValue::getZeroValue(this->type));\n}\n\nCGResult sst::ScopeExpr::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\terror(this, \"failed to resolve scope '%s'\", this->scope.string());\n}\n\nCGResult sst::BareTypeDefn::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\t// there's nothing to do here...\n\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\treturn CGResult(0);\n}\n\nCGResult sst::Stmt::codegen(cgn::CodegenState* cs, fir::Type* inferred)\n{\n\treturn this->_codegen(cs, inferred);\n}\n\nCGResult sst::Defn::codegen(cgn::CodegenState* cs, fir::Type* inferred)\n{\n\tif(this->didCodegen && cs->id == this->cachedCSId)\n\t\treturn this->cachedResult;\n\n\tthis->didCodegen = true;\n\tthis->cachedCSId = cs->id;\n\treturn (this->cachedResult = this->_codegen(cs, inferred));\n}\n\n// TODO: move this impl somewhere else?\nsst::FunctionDefn* cgn::CodegenState::findMatchingMethodInType(sst::TypeDefn* td, sst::FunctionDecl* fn)\n{\n\tif(auto str = dcast(sst::StructDefn, td); str)\n\t{\n\t\t// TODO: when (if) we figure out what's going on in typecheck/traits.cpp:129, possibly change this to match.\n\t\tauto it = std::find_if(str->methods.begin(), str->methods.end(), [fn](sst::FunctionDefn* method) -> bool {\n\n\t\t\t//* i think this check should work, `areMethodsVirtuallyCompatible` basically checks the parameters but takes\n\t\t\t//* co/contravariance into account and doesn't match the first (self) parameter.\n\t\t\treturn (fn->id.name == method->id.name && fir::areMethodsVirtuallyCompatible(\n\t\t\t\tfn->type->toFunctionType(), method->type->toFunctionType(), /* checking trait: */ true)\n\t\t\t);\n\t\t});\n\n\t\tif(it != str->methods.end())\n\t\t\treturn *it;\n\t}\n\n\treturn 0;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/operators.cpp",
    "content": "// operators.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"codegen.h\"\n\nnamespace cgn\n{\n\tusing OperatorFn = CodegenState::OperatorFn;\n\tstd::pair<OperatorFn, fir::Function*> CodegenState::getOperatorFunctionForTypes(fir::Type* a, fir::Type* b, std::string op)\n\t{\n\t\tstd::function<bool (fir::Type*)> isBuiltinType = [&](fir::Type* t) -> bool {\n\t\t\tif(t->isPrimitiveType())\t\treturn true;\n\t\t\telse if(t->isBoolType())\t\treturn true;\n\t\t\telse if(t->isCharType())\t\treturn true;\n\t\t\telse if(t->isStringType())\t\treturn true;\n\t\t\telse if(t->isNullType())\t\treturn true;\n\t\t\telse if(t->isVoidType())\t\treturn true;\n\t\t\telse if(t->isPointerType())\t\treturn true;\n\t\t\telse if(t->isArrayType() || t->isDynamicArrayType() || t->isArraySliceType())\n\t\t\t{\n\t\t\t\treturn isBuiltinType(t->getArrayElementType());\n\t\t\t}\n\t\t\telse if(t->isTupleType())\n\t\t\t{\n\t\t\t\t// uhm...\n\t\t\t\tbool res = false;\n\t\t\t\tfor(auto e : t->toTupleType()->getElements())\n\t\t\t\t\tres &= isBuiltinType(e);\n\n\t\t\t\treturn res;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t};\n\n\t\t// check what the thing is\n\t\tif(isBuiltinType(a) && isBuiltinType(b))\n\t\t{\n\t\t\treturn { OperatorFn::Builtin, 0 };\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(this->loc(), \"unsupported operator function '%s' on types '%s' and '%s'\", op, a, b);\n\t\t}\n\t}\n}\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/raii.cpp",
    "content": "// raii.cpp\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"codegen.h\"\n#include \"string_consts.h\"\n\nnamespace cgn\n{\n\tvoid CodegenState::addRAIIValue(fir::Value* val)\n\t{\n\t\t// TODO: we need global destructors eventually.\n\t\tif(this->isWithinGlobalInitFunction())\n\t\t\treturn;\n\n\t\tif(!this->isRAIIType(val->getType()))\n\t\t\terror(\"val is not a class type! '%s'\", val->getType());\n\n\t\tauto list = &this->blockPointStack.back().raiiValues;\n\t\tif(auto it = std::find(list->begin(), list->end(), val); it == list->end())\n\t\t{\n\t\t\tlist->push_back(val);\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(\"adding duplicate raii value (ptr = %p, type = '%s')\", reinterpret_cast<void*>(val), val->getType());\n\t\t}\n\t}\n\n\tvoid CodegenState::removeRAIIValue(fir::Value* val)\n\t{\n\t\t// TODO: we need global destructors eventually.\n\t\tif(this->isWithinGlobalInitFunction())\n\t\t\treturn;\n\n\t\tif(!this->isRAIIType(val->getType()))\n\t\t\terror(\"val is not a class type! '%s'\", val->getType());\n\n\t\tauto list = &this->blockPointStack.back().raiiValues;\n\t\tif(auto it = std::find(list->begin(), list->end(), val); it != list->end())\n\t\t{\n\t\t\tlist->erase(it);\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(\"removing non-existent raii value (ptr = %p, type = '%s')\", reinterpret_cast<void*>(val), val->getType());\n\t\t}\n\t}\n\n\tstd::vector<fir::Value*> CodegenState::getRAIIValues()\n\t{\n\t\treturn this->blockPointStack.back().raiiValues;\n\t}\n\n\tvoid CodegenState::addRAIIOrRCValueIfNecessary(fir::Value* val, fir::Type* ty)\n\t{\n\t\tif(!ty)\n\t\t\tty = val->getType();\n\n\t\tif(fir::isRefCountedType(ty))\n\t\t\tthis->addRefCountedValue(val);\n\n\t\tif(this->isRAIIType(ty))\n\t\t\tthis->addRAIIValue(val);\n\t}\n\n\tstatic fir::Value* getAddressOfOrMakeTemporaryLValue(CodegenState* cs, fir::Value* val, bool mut)\n\t{\n\t\tif(val->islvalue())\n\t\t{\n\t\t\treturn cs->irb.AddressOf(val, mut);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto tmp = cs->irb.CreateLValue(val->getType());\n\t\t\tcs->irb.Store(val, tmp);\n\n\t\t\treturn cs->irb.AddressOf(tmp, mut);\n\t\t}\n\t}\n\n\n\tstatic fir::Function* getImplementationForRAIITrait(CodegenState* cs, const std::string& name, fir::Type* ty)\n\t{\n\t\tif(auto it = cs->compilerSupportDefinitions.find(name); it != cs->compilerSupportDefinitions.end())\n\t\t{\n\t\t\tauto trt = dcast(sst::TraitDefn, it->second);\n\t\t\tif(!trt) error(\"invalid use of @compiler_support[\\\"%s\\\"] on non-trait definition!\", name);\n\n\t\t\ticeAssert(trt->methods.size() == 1);\n\n\t\t\tauto str = dcast(sst::StructDefn, cs->typeDefnMap[ty]);\n\t\t\ticeAssert(str);\n\n\t\t\tauto target = cs->findMatchingMethodInType(str, trt->methods[0]);\n\t\t\tif(target)\n\t\t\t{\n\t\t\t\t// the inferred type should be the receiver type\n\t\t\t\tauto ret = target->codegen(cs, ty);\n\t\t\t\treturn dcast(fir::Function, ret.value);\n\t\t\t}\n\t\t}\n\n\t\treturn 0;\n\t}\n\n\n\n\n\tvoid CodegenState::callDestructor(fir::Value* val)\n\t{\n\t\tif(!this->typeHasDestructor(val->getType()))\n\t\t\treturn;\n\n\t\tfir::Value* selfptr = getAddressOfOrMakeTemporaryLValue(this, val, /* mutable: */ true);\n\n\n\t\tif(val->getType()->isClassType())\n\t\t{\n\t\t\tauto cls = val->getType()->toClassType();\n\n\t\t\t// call the user-defined one first, if any:\n\t\t\tif(auto des = cls->getDestructor(); des)\n\t\t\t\tthis->irb.Call(des, selfptr);\n\n\t\t\t// call the auto one. this will handle calling base class destructors for us!\n\t\t\tthis->irb.Call(cls->getInlineDestructor(), selfptr);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto destructor = getImplementationForRAIITrait(this, strs::names::support::RAII_TRAIT_DROP, val->getType());\n\n\t\t\t// well if you didn't implement it then the typechecker would have already complained about you so...\n\t\t\ticeAssert(destructor);\n\t\t\tthis->irb.Call(destructor, selfptr);\n\t\t}\n\t}\n\n\n\n\n\tstatic void doMemberWiseStuffIfNecessary(CodegenState* cs, fir::ClassType* clsty, fir::Value* from, fir::Value* target, bool move)\n\t{\n\t\t// check if there are even any class types inside. if not, do the simple thing!\n\t\tbool needSpecial = false;\n\n\t\tfor(auto m : clsty->getElements())\n\t\t{\n\t\t\tif(m->isClassType())\n\t\t\t{\n\t\t\t\tneedSpecial = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif(needSpecial)\n\t\t{\n\t\t\tauto selfptr = getAddressOfOrMakeTemporaryLValue(cs, target, true);\n\t\t\tauto otherptr = getAddressOfOrMakeTemporaryLValue(cs, from, true);\n\n\t\t\t// assign `lhs = rhs`\n\n\t\t\tfor(const auto& name : clsty->getNameList())\n\t\t\t{\n\t\t\t\tauto lhs = cs->irb.GetStructMember(cs->irb.Dereference(selfptr), name);\n\t\t\t\tauto rhs = cs->irb.GetStructMember(cs->irb.Dereference(otherptr), name);\n\n\t\t\t\tif(move)    cs->moveRAIIValue(rhs, lhs);\n\t\t\t\telse        cs->copyRAIIValue(rhs, lhs);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcs->irb.Store(from, target);\n\t\t}\n\t}\n\n\n\n\n\n\n\tfir::Value* CodegenState::copyRAIIValue(fir::Value* value)\n\t{\n\t\tif(!typeHasCopyConstructor(value->getType()))\n\t\t\treturn value;\n\n\t\t// this will zero-initialise!\n\t\tauto ret = this->irb.CreateLValue(value->getType());\n\n\t\tthis->copyRAIIValue(value, ret, /* enableMoving: */ false);\n\t\treturn ret;\n\t}\n\n\n\n\tvoid CodegenState::copyRAIIValue(fir::Value* from, fir::Value* target, bool enableMoving)\n\t{\n\t\ticeAssert(from->getType() == target->getType());\n\n\t\tif(!typeHasCopyConstructor(from->getType()))\n\t\t{\n\t\t\tthis->irb.Store(from, target);\n\t\t\treturn;\n\t\t}\n\n\t\tif(!from->islvalue() && enableMoving)\n\t\t{\n\t\t\tthis->moveRAIIValue(from, target);\n\t\t\treturn;\n\t\t}\n\n\t\t// there's probably a better way to structure this, but i can't be bothered right now\n\t\t// or ever. it's just 2 lines of code dupe anyway. so sue me.\n\n\t\tif(from->getType()->isClassType())\n\t\t{\n\t\t\tauto clsty = from->getType()->toClassType();\n\n\t\t\t// if there is a copy-constructor, then we will call the copy constructor.\n\t\t\tif(auto copycon = clsty->getCopyConstructor(); copycon)\n\t\t\t{\n\t\t\t\t// note: we make otherptr immutable, because copy() isn't supposed to pass the thing mutably!\n\t\t\t\tauto selfptr = getAddressOfOrMakeTemporaryLValue(this, target, true);\n\t\t\t\tauto otherptr = getAddressOfOrMakeTemporaryLValue(this, from, false);\n\n\t\t\t\tthis->irb.Call(copycon, selfptr, otherptr);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tdoMemberWiseStuffIfNecessary(this, clsty, from, target, /* move: */ false);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// note: we make otherptr immutable, because copy() isn't supposed to pass the thing mutably!\n\t\t\tauto selfptr = getAddressOfOrMakeTemporaryLValue(this, target, true);\n\t\t\tauto otherptr = getAddressOfOrMakeTemporaryLValue(this, from, false);\n\n\t\t\t// well we got here, so we know at least the type has a copy constructor somewhere.\n\t\t\tauto copycon = getImplementationForRAIITrait(this, strs::names::support::RAII_TRAIT_COPY, from->getType());\n\n\t\t\t// again, typechecking would have complained prior to this\n\t\t\ticeAssert(copycon);\n\t\t\tthis->irb.Call(copycon, selfptr, otherptr);\n\t\t}\n\t}\n\n\n\n\n\tvoid CodegenState::moveRAIIValue(fir::Value* from, fir::Value* target)\n\t{\n\t\ticeAssert(from->getType() == target->getType());\n\n\t\tif(!typeHasMoveConstructor(from->getType()) || from->islvalue())\n\t\t{\n\t\t\t// you can't move from lvalues!\n\t\t\tthis->copyRAIIValue(from, target);\n\t\t\treturn;\n\t\t}\n\n\t\tif(from->getType()->isClassType())\n\t\t{\n\t\t\tauto clsty = from->getType()->toClassType();\n\n\t\t\t// if there is a copy-constructor, then we will call the copy constructor.\n\t\t\tif(auto movecon = clsty->getMoveConstructor(); movecon)\n\t\t\t{\n\t\t\t\t// note: here both are mutable.\n\t\t\t\tauto selfptr = getAddressOfOrMakeTemporaryLValue(this, target, true);\n\t\t\t\tauto otherptr = getAddressOfOrMakeTemporaryLValue(this, from, true);\n\n\t\t\t\tthis->irb.Call(movecon, selfptr, otherptr);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tdoMemberWiseStuffIfNecessary(this, clsty, from, target, /* move: */ true);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// note: here both are mutable.\n\t\t\tauto selfptr = getAddressOfOrMakeTemporaryLValue(this, target, true);\n\t\t\tauto otherptr = getAddressOfOrMakeTemporaryLValue(this, from, true);\n\n\t\t\t// well we got here, so we know at least the type has a copy constructor somewhere.\n\t\t\tauto movecon = getImplementationForRAIITrait(this, strs::names::support::RAII_TRAIT_MOVE, from->getType());\n\n\t\t\t// again, typechecking would have complained prior to this\n\t\t\ticeAssert(movecon);\n\t\t\tthis->irb.Call(movecon, selfptr, otherptr);\n\t\t}\n\n\t\tthis->removeRAIIValue(from);\n\t}\n\n\n\t// TODO: memoise this for each type; the typeHas-blalba ones also!\n\tstatic bool findRAIITraitImpl(CodegenState* cs, fir::Type* ty, const std::string& name)\n\t{\n\t\tif(ty->isClassType())\n\t\t\treturn true;\n\n\t\tif(!ty->isStructType())\n\t\t\treturn false;\n\n\t\tauto str = ty->toStructType();\n\t\tauto def = dcast(sst::StructDefn, cs->typeDefnMap[str]);\n\t\ticeAssert(def);\n\n\t\treturn zfu::matchAny(def->traits, [name](sst::TraitDefn* trt) -> bool {\n\t\t\t// if we do not have such an attribute, then ::get returns an empty UA,\n\t\t\t// with an empty string as a name.\n\t\t\treturn trt->attrs.get(strs::attrs::COMPILER_SUPPORT).name == strs::attrs::COMPILER_SUPPORT;\n\t\t});\n\t}\n\n\n\tbool CodegenState::typeHasDestructor(fir::Type* ty)\n\t{\n\t\treturn findRAIITraitImpl(this, ty, strs::names::support::RAII_TRAIT_DROP);\n\t}\n\n\tbool CodegenState::typeHasCopyConstructor(fir::Type* ty)\n\t{\n\t\treturn findRAIITraitImpl(this, ty, strs::names::support::RAII_TRAIT_COPY);\n\t}\n\n\tbool CodegenState::typeHasMoveConstructor(fir::Type* ty)\n\t{\n\t\treturn findRAIITraitImpl(this, ty, strs::names::support::RAII_TRAIT_MOVE);\n\t}\n\n\tbool CodegenState::isRAIIType(fir::Type* ty)\n\t{\n\t\treturn this->typeHasDestructor(ty) || this->typeHasCopyConstructor(ty) || this->typeHasMoveConstructor(ty);\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/ranges.cpp",
    "content": "// ranges.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"codegen.h\"\n#include \"gluecode.h\"\n\nCGResult sst::RangeExpr::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tauto start = cs->oneWayAutocast(this->start->codegen(cs, fir::Type::getNativeWord()).value, fir::Type::getNativeWord());\n\ticeAssert(start);\n\tif(!start->getType()->isIntegerType())\n\t\terror(this->start, \"expected integer type in range expression (start), found '%s' instead\", start->getType());\n\n\tauto end = cs->oneWayAutocast(this->end->codegen(cs, fir::Type::getNativeWord()).value, fir::Type::getNativeWord());\n\ticeAssert(end);\n\tif(!end->getType()->isIntegerType())\n\t\terror(this->end, \"expected integer type in range expression (end), found '%s' instead\", end->getType());\n\n\t// if we're half-open, then we need to subtract 1 from the end value.\n\t// TODO: do we need to check for start > end for half open?\n\t// it's well documented that we always subtract 1 for half open, but it might be immediately obvious.\n\tif(this->halfOpen) end = cs->irb.Subtract(end, fir::ConstantInt::getNative(1));\n\n\n\t// if start > end, the automatic step should be -1. else, it should be 1 as normal.\n\tfir::Value* step = (this->step ?\n\t\tcs->oneWayAutocast(this->step->codegen(cs, fir::Type::getNativeWord()).value, fir::Type::getNativeWord()) :\n\t\tcs->irb.Select(cs->irb.ICmpLEQ(start, end), fir::ConstantInt::getNative(1), fir::ConstantInt::getNative(-1))\n\t);\n\n\ticeAssert(step);\n\tif(!step->getType()->isIntegerType())\n\t\terror(this->step, \"expected integer type in range expression (step), found '%s' instead\", step->getType());\n\n\tauto ret = cs->irb.CreateValue(fir::RangeType::get());\n\tret = cs->irb.SetRangeLower(ret, start);\n\tret = cs->irb.SetRangeUpper(ret, end);\n\tret = cs->irb.SetRangeStep(ret, step);\n\n\t// now that we have all the values, it's time to sanity check these things.\n\tauto checkf = cgn::glue::misc::getRangeSanityCheckFunction(cs);\n\tif(checkf) cs->irb.Call(checkf, ret, fir::ConstantCharSlice::get(this->loc.toString()));\n\n\n\treturn CGResult(ret);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/refcounting.cpp",
    "content": "// refcounting.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"codegen.h\"\n#include \"gluecode.h\"\n\nnamespace cgn\n{\n\tvoid CodegenState::addRefCountedValue(fir::Value* val)\n\t{\n\t\tif(this->isWithinGlobalInitFunction())\n\t\t\treturn;\n\n\t\tauto list = &this->blockPointStack.back().refCountedValues;\n\n\t\tif(auto it = std::find(list->begin(), list->end(), val); it == list->end())\n\t\t{\n\t\t\tlist->push_back(val);\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(this->loc(), \"adding duplicate refcounted value (ptr = %p, type = '%s')\",\n\t\t\t\treinterpret_cast<void*>(val), val->getType());\n\t\t}\n\t}\n\n\tvoid CodegenState::removeRefCountedValue(fir::Value* val)\n\t{\n\t\tif(this->isWithinGlobalInitFunction())\n\t\t\treturn;\n\n\t\tauto list = &this->blockPointStack.back().refCountedValues;\n\n\t\tif(auto it = std::find(list->begin(), list->end(), val); it != list->end())\n\t\t{\n\t\t\tlist->erase(it);\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(this->loc(), \"removing non-existent refcounted value (ptr = %p, type = '%s')\",\n\t\t\t\treinterpret_cast<void*>(val), val->getType());\n\t\t}\n\t}\n\n\tstd::vector<fir::Value*> CodegenState::getRefCountedValues()\n\t{\n\t\treturn this->blockPointStack.back().refCountedValues;\n\t}\n\n\n\tvoid CodegenState::autoAssignRefCountedValue(fir::Value* lhs, fir::Value* rhs, bool isinit)\n\t{\n\t\ticeAssert(lhs && rhs);\n\n\t\tif(!lhs->islvalue())\n\t\t\terror(this->loc(), \"assignment (move) to non-lvalue and non-pointer (type '%s')\", lhs->getType());\n\n\t\tif(fir::isRefCountedType(rhs->getType()))\n\t\t{\n\t\t\tif(!isinit)\n\t\t\t\tthis->decrementRefCount(lhs);\n\n\t\t\tif(rhs->canmove())\n\t\t\t{\n\t\t\t\tthis->removeRefCountedValue(rhs);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthis->incrementRefCount(rhs);\n\t\t\t}\n\t\t}\n\n\t\t// copy will do the right thing in all cases (handle non-RAII, and call move if possible)\n\t\tthis->copyRAIIValue(rhs, lhs);\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tstatic bool isStructuredAggregate(fir::Type* t)\n\t{\n\t\treturn t->isStructType() || t->isClassType() || t->isTupleType();\n\t}\n\n\n\ttemplate <typename T>\n\tvoid doRefCountOfAggregateType(CodegenState* cs, T* type, fir::Value* value, bool incr)\n\t{\n\t\tsize_t i = 0;\n\t\tfor(auto m : type->getElements())\n\t\t{\n\t\t\tif(fir::isRefCountedType(m))\n\t\t\t{\n\t\t\t\tfir::Value* mem = cs->irb.ExtractValue(value, { i });\n\n\t\t\t\tif(incr)\tcs->incrementRefCount(mem);\n\t\t\t\telse\t\tcs->decrementRefCount(mem);\n\t\t\t}\n\t\t\telse if(isStructuredAggregate(m))\n\t\t\t{\n\t\t\t\tfir::Value* mem = cs->irb.ExtractValue(value, { i });\n\n\t\t\t\tif(m->isStructType())\t\tdoRefCountOfAggregateType(cs, m->toStructType(), mem, incr);\n\t\t\t\telse if(m->isClassType())\tdoRefCountOfAggregateType(cs, m->toClassType(), mem, incr);\n\t\t\t\telse if(m->isTupleType())\tdoRefCountOfAggregateType(cs, m->toTupleType(), mem, incr);\n\t\t\t}\n\n\t\t\ti++;\n\t\t}\n\t}\n\n\tstatic void _doRefCount(CodegenState* cs, fir::Value* val, bool incr)\n\t{\n\t\tauto type = val->getType();\n\n\t\tif(type->isStringType())\n\t\t{\n\t\t\tfir::Function* rf = 0;\n\t\t\tif(incr) rf = glue::string::getRefCountIncrementFunction(cs);\n\t\t\telse rf = glue::string::getRefCountDecrementFunction(cs);\n\n\t\t\tcs->irb.Call(rf, val);\n\t\t}\n\t\telse if(isStructuredAggregate(type))\n\t\t{\n\t\t\tauto ty = type;\n\n\t\t\tif(ty->isStructType())\t\tdoRefCountOfAggregateType(cs, ty->toStructType(), val, incr);\n\t\t\telse if(ty->isClassType())\tdoRefCountOfAggregateType(cs, ty->toClassType(), val, incr);\n\t\t\telse if(ty->isTupleType())\tdoRefCountOfAggregateType(cs, ty->toTupleType(), val, incr);\n\t\t}\n\t\telse if(type->isDynamicArrayType())\n\t\t{\n\t\t\tfir::Function* rf = 0;\n\t\t\tif(incr) rf = glue::array::getIncrementArrayRefCountFunction(cs, type->toDynamicArrayType());\n\t\t\telse rf = glue::array::getDecrementArrayRefCountFunction(cs, type->toDynamicArrayType());\n\n\t\t\ticeAssert(rf);\n\t\t\tcs->irb.Call(rf, val);\n\t\t}\n\t\telse if(type->isArrayType())\n\t\t{\n\t\t\terror(\"no array\");\n\t\t}\n\t\telse if(type->isAnyType())\n\t\t{\n\t\t\tfir::Function* rf = 0;\n\t\t\tif(incr) rf = glue::any::getRefCountIncrementFunction(cs);\n\t\t\telse rf = glue::any::getRefCountDecrementFunction(cs);\n\n\t\t\tcs->irb.Call(rf, val);\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(\"no: '%s'\", type);\n\t\t}\n\t}\n\n\tvoid CodegenState::incrementRefCount(fir::Value* val)\n\t{\n\t\ticeAssert(fir::isRefCountedType(val->getType()));\n\t\t_doRefCount(this, val, true);\n\t}\n\n\tvoid CodegenState::decrementRefCount(fir::Value* val)\n\t{\n\t\ticeAssert(fir::isRefCountedType(val->getType()));\n\t\t_doRefCount(this, val, false);\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/sizeof.cpp",
    "content": "// sizeof.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"codegen.h\"\n\nCGResult sst::SizeofOp::_codegen(cgn::CodegenState* cs, fir::Type* inferred)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tauto sz = fir::ConstantInt::getNative(fir::getSizeOfType(this->typeToSize));\n\treturn CGResult(sz);\n}\n\n\nCGResult sst::TypeidOp::_codegen(cgn::CodegenState* cs, fir::Type* inferred)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tauto sz = fir::ConstantInt::getUNative(this->typeToId->getID());\n\treturn CGResult(sz);\n}\n"
  },
  {
    "path": "source/codegen/slice.cpp",
    "content": "// slice.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"codegen.h\"\n#include \"platform.h\"\n#include \"gluecode.h\"\n#include \"memorypool.h\"\n\nstatic void checkSliceOperation(cgn::CodegenState* cs, sst::Expr* user, fir::Value* maxlen, fir::Value* beginIndex, fir::Value* endIndex,\n\tsst::Expr* bexpr, sst::Expr* eexpr)\n{\n\tLocation apos = (bexpr ? bexpr->loc : user->loc);\n\tLocation bpos = (eexpr ? eexpr->loc : user->loc);\n\n\ticeAssert(beginIndex);\n\ticeAssert(endIndex);\n\n\tif(!beginIndex->getType()->isIntegerType())\n\t\terror(bexpr, \"expected integer type for array slice; got '%s'\", beginIndex->getType());\n\n\tif(!endIndex->getType()->isIntegerType())\n\t\terror(eexpr, \"expected integer type for array slice; got '%s'\", endIndex->getType());\n\n\n\t// do a check\n\tauto neg_begin = cs->irb.addNewBlockInFunction(\"neg_begin\", cs->irb.getCurrentFunction());\n\tauto neg_end = cs->irb.addNewBlockInFunction(\"neg_end\", cs->irb.getCurrentFunction());\n\tauto neg_len = cs->irb.addNewBlockInFunction(\"neg_len\", cs->irb.getCurrentFunction());\n\tauto check1 = cs->irb.addNewBlockInFunction(\"check1\", cs->irb.getCurrentFunction());\n\tauto check2 = cs->irb.addNewBlockInFunction(\"check2\", cs->irb.getCurrentFunction());\n\tauto merge = cs->irb.addNewBlockInFunction(\"merge\", cs->irb.getCurrentFunction());\n\n\t{\n\t\tfir::Value* neg = cs->irb.ICmpLT(beginIndex, fir::ConstantInt::getNative(0));\n\t\tcs->irb.CondBranch(neg, neg_begin, check1);\n\t}\n\n\tcs->irb.setCurrentBlock(check1);\n\t{\n\t\tfir::Value* neg = cs->irb.ICmpLT(endIndex, fir::ConstantInt::getNative(0));\n\t\tcs->irb.CondBranch(neg, neg_end, check2);\n\t}\n\n\tcs->irb.setCurrentBlock(check2);\n\t{\n\t\tfir::Value* neg = cs->irb.ICmpLT(endIndex, beginIndex);\n\t\tcs->irb.CondBranch(neg, neg_len, merge);\n\t}\n\n\n\tcs->irb.setCurrentBlock(neg_begin);\n\tcgn::glue::printRuntimeError(cs, fir::ConstantCharSlice::get(apos.toString()),\n\t\t\"slice start index '%ld' is < 0\\n\", { beginIndex });\n\n\tcs->irb.setCurrentBlock(neg_end);\n\tcgn::glue::printRuntimeError(cs, fir::ConstantCharSlice::get(bpos.toString()),\n\t\t\"slice end index '%ld' is < 0\\n\", { endIndex });\n\n\tcs->irb.setCurrentBlock(neg_len);\n\tcgn::glue::printRuntimeError(cs, fir::ConstantCharSlice::get(bpos.toString()),\n\t\t\"slice end index '%ld' is < start index '%ld'\\n\", { endIndex, beginIndex });\n\n\n\tcs->irb.setCurrentBlock(merge);\n\n\t// bounds check.\n\t{\n\t\t// endindex is non-inclusive -- if we're doing a decomposition check then it compares length instead\n\t\t// of indices here.\n\t\tfir::Function* checkf = cgn::glue::array::getBoundsCheckFunction(cs, /* isPerformingDecomposition: */ true);\n\t\tif(checkf)\n\t\t\tcs->irb.Call(checkf, maxlen, endIndex, fir::ConstantCharSlice::get(apos.toString()));\n\t}\n}\n\n\n\n\nstatic CGResult performSliceOperation(cgn::CodegenState* cs, sst::SliceOp* user, bool check, fir::Type* elmType, fir::Value* data,\n\tfir::Value* maxlen, fir::Value* beginIndex, fir::Value* endIndex, sst::Expr* bexpr, sst::Expr* eexpr)\n{\n\tif(check)\n\t\tcheckSliceOperation(cs, user, maxlen, beginIndex, endIndex, bexpr, eexpr);\n\n\t// ok, make the slice\n\tfir::Type* slct = user->type;\n\ticeAssert(slct->isArraySliceType());\n\n\tfir::Value* slice = cs->irb.CreateValue(slct, \"slice\");\n\n\t// FINALLY.\n\t// increment ptr\n\tfir::Value* newptr = cs->irb.GetPointer(data, beginIndex, \"newptr\");\n\tfir::Value* newlen = cs->irb.Subtract(endIndex, beginIndex, \"newlen\");\n\n\tslice = cs->irb.SetArraySliceData(slice, newptr);\n\tslice = cs->irb.SetArraySliceLength(slice, newlen);\n\n\t// slices are rvalues\n\treturn CGResult(slice);\n}\n\n\n\n\n\nCGResult sst::SliceOp::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tauto ty = this->expr->type;\n\tauto res = this->expr->codegen(cs);\n\n\tauto lhs = res.value;\n\n\ticeAssert(ty == lhs->getType());\n\n\tfir::Value* length = 0;\n\tif(ty->isDynamicArrayType())\tlength = cs->irb.GetSAALength(lhs, \"orig_len\");\n\telse if(ty->isArraySliceType())\tlength = cs->irb.GetArraySliceLength(lhs, \"orig_len\");\n\telse if(ty->isStringType())\t\tlength = cs->irb.GetSAALength(lhs, \"orig_len\");\n\telse if(ty->isArrayType())\t\tlength = fir::ConstantInt::getNative(ty->toArrayType()->getArraySize());\n\telse if(ty->isPointerType())    length = fir::ConstantInt::getNative(0);\n\telse\t\t\t\t\t\t\terror(this, \"unsupported type '%s'\", ty);\n\n\tfir::Value* beginIdx = 0;\n\tfir::Value* endIdx = 0;\n\n\ticeAssert(length);\n\t{\n\t\t// add the dollar value.\n\t\tcs->enterSubscriptWithLength(length);\n\t\tdefer(cs->leaveSubscript());\n\n\t\tif(ty->isPointerType() && !this->end)\n\t\t\terror(this, \"slicing operation on pointers requires an ending index\");\n\n\t\tif(this->begin)\tbeginIdx = this->begin->codegen(cs).value;\n\t\telse\t\t\tbeginIdx = fir::ConstantInt::getNative(0);\n\n\t\tif(this->end)\tendIdx = this->end->codegen(cs).value;\n\t\telse\t\t\tendIdx = length;\n\n\t\tbeginIdx = cs->oneWayAutocast(beginIdx, fir::Type::getNativeWord());\n\t\tendIdx = cs->oneWayAutocast(endIdx, fir::Type::getNativeWord());\n\t}\n\n\tbeginIdx->setName(\"begin\");\n\tendIdx->setName(\"end\");\n\n\t/*\n\t\tas a reminder:\n\n\t\tperformSliceOperation(  cgn::CodegenState* cs,\n\t\t\t\t\t\t\t\tsst::Expr* user,\n\t\t\t\t\t\t\t\tbool check,\n\t\t\t\t\t\t\t\tfir::Type* elmType,\n\t\t\t\t\t\t\t\tfir::Value* data,\n\t\t\t\t\t\t\t\tfir::Value* maxlen,\n\t\t\t\t\t\t\t\tfir::Value* beginIndex,\n\t\t\t\t\t\t\t\tfir::Value* endIndex,\n\t\t\t\t\t\t\t\tsst::Expr* bexpr,\n\t\t\t\t\t\t\t\tsst::Expr* eexpr)\n\t */\n\n\t//* note: mutability determination is done at the typechecking phase.\n\tif(ty->isPointerType())\n\t{\n\t\treturn performSliceOperation(cs, this, false, ty->getPointerElementType(), lhs,\n\t\t\tlength, beginIdx, endIdx, this->begin, this->end);\n\t}\n\telse if(ty->isDynamicArrayType())\n\t{\n\t\treturn performSliceOperation(cs, this, true, ty->getArrayElementType(), cs->irb.GetSAAData(lhs),\n\t\t\tlength, beginIdx, endIdx, this->begin, this->end);\n\t}\n\telse if(ty->isArrayType())\n\t{\n\t\t// TODO: LVALUE HOLE\n\t\tfir::Value* lhsptr = 0;\n\n\t\tif(!lhsptr) lhsptr = cs->irb.ImmutStackAlloc(lhs->getType(), lhs);\n\t\ticeAssert(lhsptr);\n\n\t\tfir::Value* data = cs->irb.ConstGEP2(lhsptr, 0, 0);\n\n\t\treturn performSliceOperation(cs, this, true, ty->getArrayElementType(), data,\n\t\t\tlength, beginIdx, endIdx, this->begin, this->end);\n\t}\n\telse if(ty->isArraySliceType())\n\t{\n\t\treturn performSliceOperation(cs, this, true, ty->getArrayElementType(), cs->irb.GetArraySliceData(lhs),\n\t\t\tlength, beginIdx, endIdx, this->begin, this->end);\n\t}\n\telse if(ty->isStringType())\n\t{\n\t\treturn performSliceOperation(cs, this, true, fir::Type::getInt8(), cs->irb.GetSAAData(lhs),\n\t\t\tlength, beginIdx, endIdx, this->begin, this->end);\n\t}\n\telse\n\t{\n\t\terror(this, \"cannot slice unsupported type '%s'\", ty);\n\t}\n}\n\n\n\n\n\n\n\nCGResult sst::SplatExpr::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\t// right. what we want to do is to see the kind of shit that we have.\n\tauto ty = this->inside->type;\n\n\tif(ty->isArraySliceType())\n\t{\n\t\tif(ty->isVariadicArrayType())\n\t\t{\n\t\t\tauto ret = this->inside->codegen(cs, infer);\n\t\t\ticeAssert(ret->getType()->isVariadicArrayType());\n\n\t\t\treturn ret;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto ret = this->inside->codegen(cs, infer);\n\t\t\ticeAssert(ret->getType()->isArraySliceType());\n\n\t\t\treturn CGResult(cs->irb.Bitcast(ret.value, fir::ArraySliceType::getVariadic(ret->getType()->getArrayElementType())));\n\t\t}\n\t}\n\telse if(ty->isDynamicArrayType() || ty->isArrayType())\n\t{\n\t\t// just do a slice on it.\n\t\tauto target = fir::ArraySliceType::getVariadic(ty->getArrayElementType());\n\t\tauto slice = util::pool<SliceOp>(this->loc, target);\n\n\t\tslice->expr = this->inside;\n\t\tslice->begin = 0;\n\t\tslice->end = 0;\n\n\t\tauto ret = slice->codegen(cs, infer);\n\t\treturn CGResult(cs->irb.Bitcast(ret.value, target));\n\t}\n\telse\n\t{\n\t\terror(this, \"unexpected type '%s' in splat expression\", ty);\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/structs.cpp",
    "content": "// structs.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"errors.h\"\n#include \"codegen.h\"\n#include \"typecheck.h\"\n\nCGResult sst::StructDefn::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\ticeAssert(this->type && this->type->isStructType());\n\n\tfor(auto method : this->methods)\n\t\tmethod->codegen(cs);\n\n\treturn CGResult(0);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/subscript.cpp",
    "content": "// subscript.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"codegen.h\"\n#include \"gluecode.h\"\n\nCGResult sst::SubscriptOp::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\t// check what's the left\n\tauto lr = this->expr->codegen(cs);\n\tauto lt = lr.value->getType();\n\n\n\tfir::Value* datapointer = 0;\n\tfir::Value* maxlength = 0;\n\n\tif(lt->isStringType() || lt->isDynamicArrayType())\n\t{\n\t\tdatapointer = cs->irb.GetSAAData(lr.value);\n\t\tmaxlength = cs->irb.GetSAALength(lr.value);\n\t}\n\telse if(lt->isArraySliceType())\n\t{\n\t\tdatapointer = cs->irb.GetArraySliceData(lr.value);\n\t\tmaxlength = cs->irb.GetArraySliceLength(lr.value);\n\t}\n\telse if(lt->isArrayType())\n\t{\n\t\t// TODO: LVALUE HOLE\n\t\tif(lr->islvalue())\n\t\t{\n\t\t\tdatapointer = cs->irb.ConstGEP2(cs->irb.AddressOf(lr.value, true), 0, 0);\n\t\t\tmaxlength = fir::ConstantInt::getNative(lt->toArrayType()->getArraySize());\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(\"NOT SUP\");\n\t\t}\n\t}\n\telse if(lt->isPointerType())\n\t{\n\t\tdatapointer = lr.value;\n\t\tmaxlength = 0;\n\t}\n\telse\n\t{\n\t\ticeAssert(0 && \"how?\");\n\t}\n\n\n\t// first gen the inside\n\tfir::Value* index = this->inside->codegen(cs).value;\n\t{\n\t\tif(index->getType()->isConstantNumberType())\n\t\t{\n\t\t\tauto cv = dcast(fir::ConstantValue, index);\n\t\t\ticeAssert(cv);\n\n\t\t\tindex = cs->unwrapConstantNumber(cv);\n\t\t}\n\n\t\t// of course these will have to be changed eventually\n\t\ticeAssert(index->getType()->isIntegerType());\n\t}\n\n\tif(maxlength)\n\t{\n\t\tfir::Function* checkf = cgn::glue::saa_common::generateBoundsCheckFunction(cs, /* isString: */ lt->isStringType(), /* isDecomp: */false);\n\t\tif(checkf)\n\t\t\tcs->irb.Call(checkf, maxlength, index, fir::ConstantCharSlice::get(this->loc.shortString()));\n\t}\n\n\t// ok, do it\n\tfir::Value* ptr = cs->irb.GetPointer(datapointer, index);\n\treturn CGResult(cs->irb.Dereference(ptr));\n}\n\n\n\nCGResult sst::SubscriptDollarOp::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\treturn CGResult(cs->getCurrentSubscriptArrayLength());\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/toplevel.cpp",
    "content": "// toplevel.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"errors.h\"\n#include \"codegen.h\"\n#include \"typecheck.h\"\n\n#include \"ir/type.h\"\n#include \"ir/module.h\"\n#include \"ir/interp.h\"\n#include \"ir/irbuilder.h\"\n\n#include \"memorypool.h\"\n\nnamespace cgn\n{\n\tstatic size_t csid = 0;\n\tCodegenState::CodegenState(const fir::IRBuilder& i) : irb(i)\n\t{\n\t\tthis->id = csid++;\n\t}\n\n\tfir::Module* codegen(sst::DefinitionTree* dtr)\n\t{\n\t\tauto mod = new fir::Module(dtr->base->name);\n\t\tauto builder = fir::IRBuilder(mod);\n\n\t\tauto cs = new CodegenState(builder);\n\t\tcs->module = mod;\n\n\t\tcs->typeDefnMap = dtr->typeDefnMap;\n\t\tcs->compilerSupportDefinitions = dtr->compilerSupportDefinitions;\n\n\t\t{\n\t\t\tcs->pushLoc(dtr->topLevel);\n\t\t\tdefer(cs->popLoc());\n\n\t\t\tdtr->topLevel->codegen(cs);\n\t\t\tcs->finishGlobalInitFunction();\n\t\t}\n\n\t\tmod->setEntryFunction(cs->entryFunction.first);\n\n\t\tdelete cs;\n\t\treturn mod;\n\t}\n}\n\n\n\n\nCGResult sst::NamespaceDefn::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tfor(auto stmt : this->statements)\n\t\tstmt->codegen(cs);\n\n\treturn CGResult(0);\n}\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/traits.cpp",
    "content": "// traits.cpp\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"errors.h\"\n#include \"codegen.h\"\n#include \"typecheck.h\"\n\nCGResult sst::TraitDefn::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\treturn CGResult(0);\n}\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/unions.cpp",
    "content": "// unions.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"codegen.h\"\n\nCGResult sst::UnionDefn::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\t// there's actually nothing to do.\n\t// nothing at all.\n\n\treturn CGResult(0);\n}\n\nCGResult sst::UnionVariantDefn::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\treturn CGResult(0);\n}\n\nCGResult sst::RawUnionDefn::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\t// again, does nothing.\n\treturn CGResult(0);\n}\n\nCGResult sst::UnionVariantConstructor::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tauto ut = this->parentUnion->type->toUnionType();\n\ticeAssert(ut);\n\n\tauto vt = ut->getVariant(this->variantId)->getInteriorType();\n\ticeAssert(vt);\n\n\tauto uv = cs->irb.CreateValue(ut);\n\n\tif(this->args.size() > 0)\n\t{\n\t\tfir::Value* data = 0;\n\t\tif(this->args.size() == 1)\n\t\t{\n\t\t\tdata = this->args[0].value->codegen(cs, vt).value;\n\t\t\tdata = cs->oneWayAutocast(data, vt);\n\t\t\ticeAssert(data);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto tupt = fir::TupleType::get(zfu::map(this->args, [](const FnCallArgument& fca) -> fir::Type* {\n\t\t\t\treturn fca.value->type;\n\t\t\t}));\n\n\t\t\tauto tup = cs->irb.CreateValue(tupt);\n\n\t\t\tsize_t i = 0;\n\t\t\tfor(const auto& arg : this->args)\n\t\t\t{\n\t\t\t\tauto v = arg.value->codegen(cs, tupt->getElementN(i)).value;\n\t\t\t\ttup = cs->irb.InsertValue(tup, { i }, v);\n\n\t\t\t\ti++;\n\t\t\t}\n\n\t\t\ttup = cs->oneWayAutocast(tup, vt);\n\t\t\ticeAssert(tup);\n\n\t\t\tdata = tup;\n\t\t}\n\n\t\tuv = cs->irb.SetUnionVariantData(uv, this->variantId, data);\n\t}\n\n\tuv = cs->irb.SetUnionVariantID(uv, this->variantId);\n\treturn CGResult(uv);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/codegen/variable.cpp",
    "content": "// variable.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"codegen.h\"\n\n\nCGResult sst::VarDefn::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tauto checkStore = [this, cs](fir::Value* val) -> fir::Value* {\n\t\ticeAssert(val);\n\n\t\tfir::Value* nv = val;\n\t\tif(nv->getType() != this->type)\n\t\t\tnv = cs->oneWayAutocast(nv, this->type);\n\n\t\tif(nv->getType() != this->type)\n\t\t{\n\t\t\ticeAssert(this->init);\n\n\t\t\tSpanError::make(SimpleError::make(this->loc, \"cannot initialise variable of type '%s' with a value of type '%s'\", this->type, nv->getType()))\n\t\t\t\t->add(util::ESpan(this->init->loc, strprintf(\"type '%s'\", nv->getType())))\n\t\t\t\t->postAndQuit();\n\t\t}\n\n\t\treturn nv;\n\t};\n\n\tif(auto it = cs->typeDefnMap.find(this->type); it != cs->typeDefnMap.end())\n\t\tit->second->codegen(cs);\n\n\tif(this->global)\n\t{\n\t\t//* note: we declare it as not-immutable here to make it easier to set things,\n\t\t//* but otherwise we make it immutable again below after init.\n\t\tauto glob = cs->module->createGlobalVariable(this->id.convertToName(), this->type, false,\n\t\t\tthis->visibility == VisibilityLevel::Public ? fir::LinkageType::External : fir::LinkageType::Internal);\n\n\t\tauto rest = cs->enterGlobalInitFunction(glob);\n\n\n\t\tfir::Value* res = 0;\n\n\t\tif(this->init)  res = this->init->codegen(cs, this->type).value;\n\t\telse            res = cs->getDefaultValue(this->type);\n\n\n\t\tif(auto cv = dcast(fir::ConstantValue, res); cv && cv->getType() == this->type)\n\t\t{\n\t\t\tglob->setInitialValue(cv);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tres = checkStore(res);\n\t\t\tcs->autoAssignRefCountedValue(glob, res, true);\n\t\t}\n\n\t\t// go and fix the thing.\n\t\tif(this->immutable)\n\t\t\tglob->makeConst();\n\n\t\tcs->leaveGlobalInitFunction(rest);\n\n\t\tcs->valueMap[this] = CGResult(glob);\n\t\treturn CGResult(glob);\n\t}\n\telse\n\t{\n\t\tfir::Value* val = 0;\n\n\t\tif(this->init)\n\t\t{\n\t\t\tval = this->init->codegen(cs, this->type).value;\n\t\t\tval = cs->oneWayAutocast(val, this->type);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tval = cs->getDefaultValue(this->type);\n\t\t\tval = checkStore(val);\n\t\t}\n\n\t\tauto alloc = cs->irb.CreateLValue(this->type, this->id.name);\n\t\tcs->autoAssignRefCountedValue(alloc, val, /* isInitial: */ true);\n\n\t\tif(this->immutable)\n\t\t\talloc->makeConst();\n\n\t\tcs->addVariableUsingStorage(this, alloc);\n\n\t\treturn CGResult(alloc);\n\t}\n}\n\nvoid cgn::CodegenState::addVariableUsingStorage(sst::VarDefn* var, fir::Value* alloc)\n{\n\ticeAssert(alloc);\n\tthis->valueMap[var] = CGResult(alloc);\n\n\tthis->addRAIIOrRCValueIfNecessary(alloc, /* type override: */ var->type);\n}\n\n\n\n\n\n\n\n\n\n\nCGResult sst::VarRef::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\tfir::Value* value = 0;\n\t{\n\t\tauto it = cs->valueMap.find(this->def);\n\n\t\tif(it != cs->valueMap.end())\n\t\t{\n\t\t\tvalue = it->second.value;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif(this->isImplicitField)\n\t\t\t{\n\t\t\t\ticeAssert(cs->isInMethodBody());\n\t\t\t\treturn cs->getStructFieldImplicitly(this->name);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthis->def->codegen(cs);\n\n\t\t\t\tit = cs->valueMap.find(this->def);\n\t\t\t\tif(it == cs->valueMap.end())\n\t\t\t\t{\n\t\t\t\t\tSimpleError::make(this->loc, \"failed to codegen variable definition for '%s'\", this->name)\n\t\t\t\t\t\t->append(SimpleError::make(MsgType::Note, this->def->loc, \"offending definition is here:\"))\n\t\t\t\t\t\t->postAndQuit();\n\t\t\t\t}\n\n\t\t\t\tvalue = it->second.value;\n\t\t\t}\n\t\t}\n\t}\n\n\t// make sure types match... should we bother?\n\tif(value->getType() != this->type)\n\t\terror(this, \"type mismatch; typechecking found type '%s', codegen gave type '%s'\", this->type, value->getType());\n\n\treturn CGResult(value);\n}\n\n\n\n\n\nCGResult sst::SelfVarRef::_codegen(cgn::CodegenState* cs, fir::Type* infer)\n{\n\tcs->pushLoc(this);\n\tdefer(cs->popLoc());\n\n\ticeAssert(cs->isInMethodBody());\n\treturn CGResult(cs->getMethodSelf());\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/ConstantValue.cpp",
    "content": "// ConstantValue.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include <math.h>\n#include <float.h>\n#include <inttypes.h>\n\n#include <functional>\n\n#include \"ir/value.h\"\n#include \"ir/constant.h\"\n\nnamespace fir\n{\n\tConstantValue::ConstantValue(Type* t) : Value(t)\n\t{\n\t\tthis->kind = Kind::prvalue;\n\t}\n\n\tConstantValue* ConstantValue::getZeroValue(Type* type)\n\t{\n\t\ticeAssert(!type->isVoidType() && \"cannot make void constant\");\n\n\t\treturn new ConstantValue(type);\n\t}\n\n\tConstantValue* ConstantValue::getNull()\n\t{\n\t\tauto ret = new ConstantValue(fir::Type::getNull());\n\t\treturn ret;\n\t}\n\n\tstd::string ConstantValue::str()\n\t{\n\t\treturn \"<unknown>\";\n\t}\n\n\n\tConstantBool* ConstantBool::get(bool val)\n\t{\n\t\treturn new ConstantBool(val);\n\t}\n\n\tConstantBool::ConstantBool(bool v) : ConstantValue(fir::Type::getBool()), value(v)\n\t{\n\t}\n\n\tbool ConstantBool::getValue()\n\t{\n\t\treturn this->value;\n\t}\n\n\tstd::string ConstantBool::str()\n\t{\n\t\treturn this->value ? \"true\" : \"false\";\n\t}\n\n\n\n\n\n\n\tConstantBitcast* ConstantBitcast::get(ConstantValue* v, Type* t)\n\t{\n\t\treturn new ConstantBitcast(v, t);\n\t}\n\n\tConstantBitcast::ConstantBitcast(ConstantValue* v, Type* t) : ConstantValue(t), value(v)\n\t{\n\t}\n\n\tstd::string ConstantBitcast::str()\n\t{\n\t\treturn this->value->str();\n\t}\n\n\n\n\n\tConstantNumber* ConstantNumber::get(ConstantNumberType* cnt, const mpfr::mpreal& n)\n\t{\n\t\treturn new ConstantNumber(cnt, n);\n\t}\n\n\tConstantNumber::ConstantNumber(ConstantNumberType* cnt, const mpfr::mpreal& n) : ConstantValue(cnt)\n\t{\n\t\tthis->number = n;\n\t}\n\n\tstd::string ConstantNumber::str()\n\t{\n\t\t// 6 decimal places, like default printf.\n\t\treturn this->number.toString(\"%.6R\");\n\t}\n\n\n\n\t// todo: unique these values.\n\tConstantInt* ConstantInt::get(Type* intType, uint64_t val)\n\t{\n\t\ticeAssert(intType->isIntegerType() && \"not integer type\");\n\t\treturn new ConstantInt(intType, val);\n\t}\n\n\tConstantInt::ConstantInt(Type* type, int64_t val) : ConstantValue(type)\n\t{\n\t\tthis->value = val;\n\t}\n\n\tConstantInt::ConstantInt(Type* type, uint64_t val) : ConstantValue(type)\n\t{\n\t\tthis->value = val;\n\t}\n\n\tint64_t ConstantInt::getSignedValue()\n\t{\n\t\treturn static_cast<int64_t>(this->value);\n\t}\n\n\tuint64_t ConstantInt::getUnsignedValue()\n\t{\n\t\treturn this->value;\n\t}\n\n\tConstantInt* ConstantInt::getInt8(int8_t value)\n\t{\n\t\treturn ConstantInt::get(Type::getInt8(), value);\n\t}\n\n\tConstantInt* ConstantInt::getInt16(int16_t value)\n\t{\n\t\treturn ConstantInt::get(Type::getInt16(), value);\n\t}\n\n\tConstantInt* ConstantInt::getInt32(int32_t value)\n\t{\n\t\treturn ConstantInt::get(Type::getInt32(), value);\n\t}\n\n\tConstantInt* ConstantInt::getInt64(int64_t value)\n\t{\n\t\treturn ConstantInt::get(Type::getInt64(), value);\n\t}\n\n\tConstantInt* ConstantInt::getUint8(uint8_t value)\n\t{\n\t\treturn ConstantInt::get(Type::getUint8(), value);\n\t}\n\n\tConstantInt* ConstantInt::getUint16(uint16_t value)\n\t{\n\t\treturn ConstantInt::get(Type::getUint16(), value);\n\t}\n\n\tConstantInt* ConstantInt::getUint32(uint32_t value)\n\t{\n\t\treturn ConstantInt::get(Type::getUint32(), value);\n\t}\n\n\tConstantInt* ConstantInt::getUint64(uint64_t value)\n\t{\n\t\treturn ConstantInt::get(Type::getUint64(), value);\n\t}\n\n\tConstantInt* ConstantInt::getNative(int64_t value)\n\t{\n\t\treturn ConstantInt::get(Type::getNativeWord(), value);\n\t}\n\n\tConstantInt* ConstantInt::getUNative(uint64_t value)\n\t{\n\t\treturn ConstantInt::get(Type::getNativeUWord(), value);\n\t}\n\n\tstd::string ConstantInt::str()\n\t{\n\t\tchar buf[64] = {0};\n\t\tif(this->getType() == Type::getInt8())          snprintf(buf, 63, \"%\" PRIi8,  static_cast<int8_t>(this->value));\n\t\telse if(this->getType() == Type::getInt16())    snprintf(buf, 63, \"%\" PRIi16, static_cast<int16_t>(this->value));\n\t\telse if(this->getType() == Type::getInt32())    snprintf(buf, 63, \"%\" PRIi32, static_cast<int32_t>(this->value));\n\t\telse if(this->getType() == Type::getInt64())    snprintf(buf, 63, \"%\" PRIi64, static_cast<int64_t>(this->value));\n\t\telse if(this->getType() == Type::getUint8())    snprintf(buf, 63, \"%\" PRIu8,  static_cast<uint8_t>(this->value));\n\t\telse if(this->getType() == Type::getUint16())   snprintf(buf, 63, \"%\" PRIu16, static_cast<uint16_t>(this->value));\n\t\telse if(this->getType() == Type::getUint32())   snprintf(buf, 63, \"%\" PRIu32, static_cast<uint32_t>(this->value));\n\t\telse if(this->getType() == Type::getUint64())   snprintf(buf, 63, \"%\" PRIu64, static_cast<uint64_t>(this->value));\n\t\telse                                            snprintf(buf, 63, \"<unknown int>\");\n\n\t\treturn std::string(buf);\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tConstantFP* ConstantFP::get(Type* type, float val)\n\t{\n\t\ticeAssert(type->isFloatingPointType() && \"not floating point type\");\n\t\treturn new ConstantFP(type, val);\n\t}\n\n\tConstantFP* ConstantFP::get(Type* type, double val)\n\t{\n\t\ticeAssert(type->isFloatingPointType() && \"not floating point type\");\n\t\treturn new ConstantFP(type, val);\n\t}\n\n\tConstantFP::ConstantFP(Type* type, float val) : fir::ConstantValue(type)\n\t{\n\t\tthis->value = static_cast<double>(val);\n\t}\n\n\tConstantFP::ConstantFP(Type* type, double val) : fir::ConstantValue(type)\n\t{\n\t\tthis->value = val;\n\t}\n\n\tdouble ConstantFP::getValue()\n\t{\n\t\treturn this->value;\n\t}\n\n\tConstantFP* ConstantFP::getFloat32(float value)\n\t{\n\t\treturn ConstantFP::get(Type::getFloat32(), value);\n\t}\n\n\tConstantFP* ConstantFP::getFloat64(double value)\n\t{\n\t\treturn ConstantFP::get(Type::getFloat64(), value);\n\t}\n\n\tstd::string ConstantFP::str()\n\t{\n\t\tchar buf[64] = {0};\n\t\tif(this->getType() == Type::getFloat32())       snprintf(buf, 63, \"%.6f\", static_cast<float>(this->value));\n\t\telse if(this->getType() == Type::getFloat64())  snprintf(buf, 63, \"%.6f\", static_cast<double>(this->value));\n\t\telse                                            snprintf(buf, 63, \"<unknown float>\");\n\n\t\treturn std::string(buf);\n\t}\n\n\n\n\n\n\n\n\tConstantStruct* ConstantStruct::get(StructType* st, const std::vector<ConstantValue*>& members)\n\t{\n\t\treturn new ConstantStruct(st, members);\n\t}\n\n\tConstantStruct::ConstantStruct(StructType* st, const std::vector<ConstantValue*>& members) : ConstantValue(st)\n\t{\n\t\tif(st->getElementCount() != members.size())\n\t\t\terror(\"mismatched structs: expected %d fields, got %d\", st->getElementCount(), members.size());\n\n\t\tfor(size_t i = 0; i < st->getElementCount(); i++)\n\t\t{\n\t\t\tif(st->getElementN(i) != members[i]->getType())\n\t\t\t{\n\t\t\t\terror(\"mismatched types in field %d: expected '%s', got '%s'\", i, st->getElementN(i), members[i]->getType());\n\t\t\t}\n\t\t}\n\n\t\t// ok\n\t\tthis->members = members;\n\t}\n\n\tstd::string ConstantStruct::str()\n\t{\n\t\tauto sty = this->getType()->toStructType();\n\t\tutil::hash_map<size_t, std::string> names;\n\t\tfor(const auto& p : sty->getIndexMap())\n\t\t\tnames[p.second] = p.first;\n\n\t\tstd::string ret = this->getType()->str() + \" {\\n\";\n\n\t\tfor(size_t i = 0; i < sty->getElementCount(); i++)\n\t\t{\n\t\t\tauto v = this->members[i]->str();\n\t\t\tauto t = sty->getElementN(i);\n\t\t\tauto n = names[i];\n\n\t\t\tret += zpr::sprint(\"  %s: %s = %s\\n\", n, t, v);\n\t\t}\n\n\t\treturn ret + \"}\";\n\t}\n\n\n\n\n\n\n\tConstantCharSlice* ConstantCharSlice::get(const std::string& s)\n\t{\n\t\treturn new ConstantCharSlice(s);\n\t}\n\n\tConstantCharSlice::ConstantCharSlice(const std::string& s) : ConstantValue(fir::Type::getCharSlice(false))\n\t{\n\t\tthis->value = s;\n\t}\n\n\tstd::string ConstantCharSlice::getValue()\n\t{\n\t\treturn this->value;\n\t}\n\n\tstd::string ConstantCharSlice::str()\n\t{\n\t\treturn zpr::sprint(\"\\\"%s\\\"\", this->value);\n\t}\n\n\n\n\n\n\tConstantTuple* ConstantTuple::get(const std::vector<ConstantValue*>& mems)\n\t{\n\t\treturn new ConstantTuple(mems);\n\t}\n\n\tstd::vector<ConstantValue*> ConstantTuple::getValues()\n\t{\n\t\treturn this->values;\n\t}\n\n\tstatic std::vector<Type*> mapTypes(const std::vector<ConstantValue*>& vs)\n\t{\n\t\tstd::vector<Type*> ret;\n\t\tret.reserve(vs.size());\n\n\t\tfor(auto v : vs)\n\t\t\tret.push_back(v->getType());\n\n\t\treturn ret;\n\t}\n\n\t// well this is stupid.\n\tConstantTuple::ConstantTuple(const std::vector<ConstantValue*>& mems) : fir::ConstantValue(fir::TupleType::get(mapTypes(mems)))\n\t{\n\t\tthis->values = mems;\n\t}\n\n\tstd::string ConstantTuple::str()\n\t{\n\t\treturn \"(\" + zfu::join(zfu::map(this->values, [](auto x) -> auto { return x->str(); }), \", \") + \")\";\n\t}\n\n\n\n\n\n\n\n\n\n\n\tConstantEnumCase* ConstantEnumCase::get(EnumType* et, ConstantInt* index, ConstantValue* value)\n\t{\n\t\treturn new ConstantEnumCase(et, index, value);\n\t}\n\n\tConstantInt* ConstantEnumCase::getIndex()\n\t{\n\t\treturn this->index;\n\t}\n\n\tConstantValue* ConstantEnumCase::getValue()\n\t{\n\t\treturn this->value;\n\t}\n\n\t// well this is stupid.\n\tConstantEnumCase::ConstantEnumCase(EnumType* et, ConstantInt* index, ConstantValue* value) : fir::ConstantValue(et)\n\t{\n\t\tthis->index = index;\n\t\tthis->value = value;\n\t}\n\n\tstd::string ConstantEnumCase::str()\n\t{\n\t\t// TODO: why the fuck did i design enums this way?!\n\t\treturn this->value->str();\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tConstantArray* ConstantArray::get(Type* type, const std::vector<ConstantValue*>& vals)\n\t{\n\t\treturn new ConstantArray(type, vals);\n\t}\n\n\tConstantArray::ConstantArray(Type* type, const std::vector<ConstantValue*>& vals) : fir::ConstantValue(type)\n\t{\n\t\tthis->values = vals;\n\t}\n\n\tstd::string ConstantArray::str()\n\t{\n\t\treturn \"[ \" + zfu::join(zfu::map(this->values, [](auto x) -> auto { return x->str(); }), \", \") + \" ]\";\n\t}\n\n\n\n\n\n\tConstantDynamicArray* ConstantDynamicArray::get(DynamicArrayType* t, ConstantValue* d, ConstantValue* l, ConstantValue* c)\n\t{\n\t\tauto cda = new ConstantDynamicArray(t);\n\t\tcda->data = d;\n\t\tcda->length = l;\n\t\tcda->capacity = c;\n\n\t\treturn cda;\n\t}\n\n\tConstantDynamicArray* ConstantDynamicArray::get(ConstantArray* arr)\n\t{\n\t\tauto cda = new ConstantDynamicArray(DynamicArrayType::get(arr->getType()->toArrayType()->getElementType()));\n\t\tcda->arr = arr;\n\n\t\treturn cda;\n\t}\n\n\n\tConstantDynamicArray::ConstantDynamicArray(DynamicArrayType* t) : ConstantValue(t)\n\t{\n\t}\n\n\tstd::string ConstantDynamicArray::str()\n\t{\n\t\treturn \"<dyn array>\";\n\t}\n\n\n\n\tConstantDynamicString* ConstantDynamicString::get(const std::string& s)\n\t{\n\t\treturn new ConstantDynamicString(s);\n\t}\n\n\tConstantDynamicString::ConstantDynamicString(const std::string& s) : ConstantValue(fir::Type::getString())\n\t{\n\t\tthis->value = s;\n\t}\n\n\tstd::string ConstantDynamicString::getValue()\n\t{\n\t\treturn this->value;\n\t}\n\n\tstd::string ConstantDynamicString::str()\n\t{\n\t\treturn zpr::sprint(\"\\\"%s\\\"\", this->value);\n\t}\n\n\n\n\n\n\n\tConstantArraySlice* ConstantArraySlice::get(ArraySliceType* t, ConstantValue* d, ConstantValue* l)\n\t{\n\t\tauto cda = new ConstantArraySlice(t);\n\t\tcda->data = d;\n\t\tcda->length = l;\n\n\t\treturn cda;\n\t}\n\n\tConstantArraySlice::ConstantArraySlice(ArraySliceType* t) : ConstantValue(t)\n\t{\n\t}\n\n\tstd::string ConstantArraySlice::str()\n\t{\n\t\treturn \"<slice>\";\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/Function.cpp",
    "content": "// Function.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ir/module.h\"\n#include \"ir/function.h\"\n\n#include <algorithm>\n\nnamespace fir\n{\n\t// argument stuff\n\tArgument::Argument(Function* fn, Type* type) : Value(type)\n\t{\n\t\tthis->parentFunction = fn;\n\t\tthis->realValue = new Value(type);\n\t}\n\n\tArgument::~Argument()\n\t{\n\t\tdelete this->realValue;\n\t}\n\n\tValue* Argument::getActualValue()\n\t{\n\t\tif(this->realValue) return this->realValue;\n\t\terror(\"calling getActualValue() when not in function! (no real value)\");\n\t}\n\n\tFunction* Argument::getParentFunction()\n\t{\n\t\ticeAssert(this->parentFunction);\n\t\treturn this->parentFunction;\n\t}\n\n\tvoid Argument::setValue(Value* v)\n\t{\n\t\ticeAssert(v);\n\t\tthis->realValue = v;\n\t}\n\n\tvoid Argument::clearValue()\n\t{\n\t\tthis->realValue = 0;\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t// function stuff\n\tFunction::Function(const Name& name, FunctionType* fnType, Module* module, LinkageType linkage)\n\t\t: GlobalValue(module, fnType, linkage)\n\t{\n\t\tthis->ident = name;\n\t\tthis->valueType = fnType;\n\n\t\tfor(auto t : fnType->getArgumentTypes())\n\t\t\tthis->fnArguments.push_back(new Argument(this, t));\n\t}\n\n\tType* Function::getReturnType()\n\t{\n\t\treturn this->getType()->getReturnType();\n\t}\n\n\tsize_t Function::getArgumentCount()\n\t{\n\t\treturn this->fnArguments.size();\n\t}\n\n\tconst std::vector<Argument*>& Function::getArguments()\n\t{\n\t\treturn this->fnArguments;\n\t}\n\n\tArgument* Function::getArgumentWithName(std::string name)\n\t{\n\t\tfor(auto a : this->fnArguments)\n\t\t{\n\t\t\tif(a->getName().name == name)\n\t\t\t\treturn a;\n\t\t}\n\n\t\terror(\"no argument named '%s' in function '%s'\", name, this->getName().name);\n\t}\n\n\tbool Function::isCStyleVarArg()\n\t{\n\t\treturn this->getType()->isCStyleVarArg();\n\t}\n\n\tbool Function::isVariadic()\n\t{\n\t\treturn this->getType()->isVariadicFunc();\n\t}\n\n\n\tstd::vector<IRBlock*>& Function::getBlockList()\n\t{\n\t\treturn this->blocks;\n\t}\n\n\tvoid Function::deleteBody()\n\t{\n\t\tthis->blocks.clear();\n\t}\n\n\tbool Function::isIntrinsicFunction()\n\t{\n\t\treturn this->fnIsIntrinsicFunction;\n\t}\n\n\tvoid Function::setIsIntrinsic()\n\t{\n\t\tthis->fnIsIntrinsicFunction = true;\n\t}\n\n\tvoid Function::addStackAllocation(Type* ty)\n\t{\n\t\tthis->stackAllocs.push_back(ty);\n\t}\n\n\tconst std::vector<Type*>& Function::getStackAllocations()\n\t{\n\t\treturn this->stackAllocs;\n\t}\n\n\n\tvoid Function::cullUnusedValues()\n\t{\n\t}\n\n\n\n\n\n\n\n\tbool Function::wasDeclaredWithBodyElsewhere()\n\t{\n\t\treturn this->hadBodyElsewhere;\n\t}\n\n\tvoid Function::setHadBodyElsewhere()\n\t{\n\t\tthis->hadBodyElsewhere = true;\n\t}\n\n\n\n\n\tbool Function::isAlwaysInlined()\n\t{\n\t\treturn this->alwaysInlined;\n\t}\n\n\tvoid Function::setAlwaysInline()\n\t{\n\t\tthis->alwaysInlined = true;\n\t}\n\n\n\n\n\n\n\n\n\n\tFunction* Function::create(const Name& name, fir::FunctionType* fnType, fir::Module* module, fir::LinkageType linkage)\n\t{\n\t\treturn new Function(name, fnType, module, linkage);\n\t}\n\n\n\n\n\t// overridden stuff\n\tFunctionType* Function::getType()\n\t{\n\t\tFunctionType* ft = dcast(FunctionType, this->valueType);\n\t\ticeAssert(ft && \"function is impostor (not valid function type)\");\n\n\t\treturn ft;\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/GlobalValue.cpp",
    "content": "// GlobalValue.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n\n#include \"ir/value.h\"\n#include \"ir/module.h\"\n#include \"ir/constant.h\"\n\nnamespace fir\n{\n\tGlobalValue::GlobalValue(Module* m, Type* type, LinkageType linkage, bool mut) : ConstantValue(type)\n\t{\n\t\tthis->linkageType = linkage;\n\t\tthis->parentModule = m;\n\n\t\t//* not a typo; only variables deserve to be 'lvalue', global values (eg. functions)\n\t\t//* should just be rvalues.\n\t\tif(mut) this->kind = Kind::lvalue;\n\t\telse    this->kind = Kind::prvalue;\n\t}\n\n\tstd::string GlobalValue::str()\n\t{\n\t\treturn \"<global>\";\n\t}\n\n\n\n\tGlobalVariable::GlobalVariable(const Name& name, Module* module, Type* type, bool immutable, LinkageType lt, ConstantValue* initValue)\n\t\t: GlobalValue(module, type, lt, !immutable)\n\t{\n\t\tthis->ident = name;\n\t\tthis->initValue = initValue;\n\n\t\tthis->kind = Kind::lvalue;\n\t\tthis->isconst = immutable;\n\t}\n\n\tvoid GlobalVariable::setInitialValue(ConstantValue* constVal)\n\t{\n\t\tif(constVal && constVal->getType() != this->getType())\n\t\t\terror(\"storing value of '%s' in global var of type '%s'\", constVal->getType(), this->getType());\n\n\t\tthis->initValue = constVal;\n\t}\n\n\tConstantValue* GlobalVariable::getInitialValue()\n\t{\n\t\treturn this->initValue;\n\t}\n\n\tstd::string GlobalVariable::str()\n\t{\n\t\treturn this->initValue->str();\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/IRBlock.cpp",
    "content": "// IRBlock.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ir/function.h\"\n#include \"ir/block.h\"\n\nnamespace fir\n{\n\tIRBlock::IRBlock() : Value(Type::getVoid())\n\t{\n\t\tthis->parentFunction = 0;\n\t}\n\n\tIRBlock::IRBlock(Function* fn) : Value(Type::getVoid())\n\t{\n\t\tthis->parentFunction = fn;\n\t}\n\n\tvoid IRBlock::setFunction(Function* fn)\n\t{\n\t\tthis->parentFunction = fn;\n\t}\n\n\tFunction* IRBlock::getParentFunction()\n\t{\n\t\treturn this->parentFunction;\n\t}\n\n\tvoid IRBlock::eraseFromParentFunction()\n\t{\n\t\ticeAssert(this->parentFunction && \"no function\");\n\t\tstd::vector<IRBlock*>& blist = this->parentFunction->getBlockList();\n\n\t\tfor(auto it = blist.begin(); it != blist.end(); it++)\n\t\t{\n\t\t\tif(*it == this)\n\t\t\t{\n\t\t\t\tblist.erase(it);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\ticeAssert(0 && \"not in function\");\n\t}\n\n\tstd::vector<Instruction*>& IRBlock::getInstructions()\n\t{\n\t\treturn this->instructions;\n\t}\n\n\tbool IRBlock::isTerminated()\n\t{\n\t\tif(this->instructions.size() == 0)\n\t\t\treturn false;\n\n\t\tauto last = this->instructions.back();\n\t\treturn last->opKind == OpKind::Branch_Cond\n\t\t\t\t|| last->opKind == OpKind::Branch_UnCond\n\t\t\t\t|| last->opKind == OpKind::Value_Return;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/IRBuilder.cpp",
    "content": "// IRBuilder.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include <cmath>\n\n#include \"ast.h\"\n#include \"gluecode.h\"\n\n#include \"ir/block.h\"\n#include \"ir/irbuilder.h\"\n#include \"ir/instruction.h\"\n\n#include \"memorypool.h\"\n\n\nstatic bool isSAAType(fir::Type* t)\n{\n\treturn t->isStringType() || t->isDynamicArrayType();\n}\n\nstatic fir::Type* getSAAElmType(fir::Type* t)\n{\n\ticeAssert(isSAAType(t));\n\n\tif(t->isStringType())   return fir::Type::getInt8();\n\telse                    return t->getArrayElementType();\n}\n\n\nnamespace fir\n{\n\tIRBuilder::IRBuilder(Module* mod)\n\t{\n\t\tthis->module = mod;\n\t\tthis->currentBlock = 0;\n\t\tthis->previousBlock = 0;\n\t\tthis->currentFunction = 0;\n\t}\n\n\tvoid IRBuilder::setCurrentBlock(IRBlock* block)\n\t{\n\t\tthis->previousBlock = this->currentBlock;\n\t\tthis->currentBlock = block;\n\n\t\tif(this->currentBlock != 0)\n\t\t{\n\t\t\tif(this->currentBlock->parentFunction != 0)\n\t\t\t\tthis->currentFunction = this->currentBlock->parentFunction;\n\t\t\telse\n\t\t\t\tthis->currentFunction = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthis->currentFunction = 0;\n\t\t}\n\t}\n\n\tvoid IRBuilder::restorePreviousBlock()\n\t{\n\t\tthis->currentBlock = this->previousBlock;\n\t}\n\n\tFunction* IRBuilder::getCurrentFunction()\n\t{\n\t\treturn this->currentFunction;\n\t}\n\n\tIRBlock* IRBuilder::getCurrentBlock()\n\t{\n\t\treturn this->currentBlock;\n\t}\n\n\tstatic util::MemoryPool<Instruction, 1 << 16> instr_pool;\n\n\tstatic Instruction* make_instr(OpKind kind, bool sideEffects, Type* out, const std::vector<Value*>& vals,\n\t\tValue::Kind k = Value::Kind::prvalue)\n\t{\n\t\treturn instr_pool.construct(kind, sideEffects, out, vals, k);\n\t}\n\n\tValue* IRBuilder::addInstruction(Instruction* instr, const std::string& vname)\n\t{\n\t\ticeAssert(this->currentBlock && \"no current block\");\n\n\t\t// add instruction to the end of the block\n\t\tthis->currentBlock->instructions.push_back(instr);\n\t\tValue* v = instr->realOutput;\n\n\t\t// v->addUser(this->currentBlock);\n\t\tv->setName(vname);\n\t\treturn v;\n\t}\n\n\tstatic Instruction* getBinaryOpInstruction(const std::string& ao, Value* vlhs, Value* vrhs)\n\t{\n\t\tOpKind op = OpKind::Invalid;\n\n\t\tType* lhs = vlhs->getType();\n\t\tType* rhs = vrhs->getType();\n\n\t\tbool useFloating = (lhs->isFloatingPointType() || rhs->isFloatingPointType());\n\t\tbool useSigned = ((lhs->isIntegerType() && lhs->toPrimitiveType()->isSigned())\n\t\t\t|| (rhs->isIntegerType() && rhs->toPrimitiveType()->isSigned()));\n\n\n\t\tPrimitiveType* lpt = lhs->toPrimitiveType();\n\t\tPrimitiveType* rpt = rhs->toPrimitiveType();\n\n\t\ticeAssert(lpt && rpt && \"not primitive types\");\n\n\t\tType* out = 0;\n\t\tif(ao == \"+\")\n\t\t{\n\t\t\top = useFloating ? OpKind::Floating_Add : useSigned ? OpKind::Signed_Add : OpKind::Unsigned_Add;\n\n\t\t\t// use the larger type.\n\t\t\tif(useFloating)\n\t\t\t{\n\t\t\t\tif(lpt->getFloatingPointBitWidth() > rpt->getFloatingPointBitWidth())\n\t\t\t\t\tout = lpt;\n\n\t\t\t\telse\n\t\t\t\t\tout = rpt;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// following c/c++ conventions, signed types are converted to unsigned types in mixed ops.\n\t\t\t\tif(lpt->getIntegerBitWidth() > rpt->getIntegerBitWidth())\n\t\t\t\t{\n\t\t\t\t\tif(lpt->isSigned() && rpt->isSigned())  out = lpt;\n\t\t\t\t\telse                                    out = (lpt->isSigned() ? rpt : lpt);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif(lpt->isSigned() && rpt->isSigned())  out = rpt;\n\t\t\t\t\telse                                    out = (lpt->isSigned() ? rpt : lpt);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if(ao == \"-\")\n\t\t{\n\t\t\top = useFloating ? OpKind::Floating_Sub : useSigned ? OpKind::Signed_Sub : OpKind::Unsigned_Sub;\n\n\t\t\t// use the larger type.\n\t\t\tif(useFloating)\n\t\t\t{\n\t\t\t\tif(lpt->getFloatingPointBitWidth() > rpt->getFloatingPointBitWidth())\n\t\t\t\t\tout = lpt;\n\n\t\t\t\telse\n\t\t\t\t\tout = rpt;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// following c/c++ conventions, signed types are converted to unsigned types in mixed ops.\n\t\t\t\tif(lpt->getIntegerBitWidth() > rpt->getIntegerBitWidth())\n\t\t\t\t{\n\t\t\t\t\tif(lpt->isSigned() && rpt->isSigned())  out = lpt;\n\t\t\t\t\telse                                    out = (lpt->isSigned() ? rpt : lpt);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif(lpt->isSigned() && rpt->isSigned())  out = rpt;\n\t\t\t\t\telse                                    out = (lpt->isSigned() ? rpt : lpt);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if(ao == \"*\")\n\t\t{\n\t\t\top = useFloating ? OpKind::Floating_Mul : useSigned ? OpKind::Signed_Mul : OpKind::Unsigned_Mul;\n\n\t\t\t// use the larger type.\n\t\t\tif(useFloating)\n\t\t\t{\n\t\t\t\tif(lpt->getFloatingPointBitWidth() > rpt->getFloatingPointBitWidth())\n\t\t\t\t\tout = lpt;\n\n\t\t\t\telse\n\t\t\t\t\tout = rpt;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// following c/c++ conventions, signed types are converted to unsigned types in mixed ops.\n\t\t\t\tif(lpt->getIntegerBitWidth() > rpt->getIntegerBitWidth())\n\t\t\t\t{\n\t\t\t\t\tif(lpt->isSigned() && rpt->isSigned())  out = lpt;\n\t\t\t\t\telse                                    out = (lpt->isSigned() ? rpt : lpt);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif(lpt->isSigned() && rpt->isSigned())  out = rpt;\n\t\t\t\t\telse                                    out = (lpt->isSigned() ? rpt : lpt);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if(ao == \"/\")\n\t\t{\n\t\t\top = useFloating ? OpKind::Floating_Div : useSigned ? OpKind::Signed_Div : OpKind::Unsigned_Div;\n\n\t\t\t// use the larger type.\n\t\t\tif(useFloating)\n\t\t\t{\n\t\t\t\tif(lpt->getFloatingPointBitWidth() > rpt->getFloatingPointBitWidth())\n\t\t\t\t\tout = lpt;\n\n\t\t\t\telse\n\t\t\t\t\tout = rpt;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// following c/c++ conventions, signed types are converted to unsigned types in mixed ops.\n\t\t\t\tif(lpt->getIntegerBitWidth() > rpt->getIntegerBitWidth())\n\t\t\t\t{\n\t\t\t\t\tif(lpt->isSigned() && rpt->isSigned())  out = lpt;\n\t\t\t\t\telse                                    out = (lpt->isSigned() ? rpt : lpt);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif(lpt->isSigned() && rpt->isSigned())  out = rpt;\n\t\t\t\t\telse                                    out = (lpt->isSigned() ? rpt : lpt);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if(ao == \"%\")\n\t\t{\n\t\t\top = useFloating ? OpKind::Floating_Mod : useSigned ? OpKind::Signed_Mod : OpKind::Unsigned_Mod;\n\n\t\t\t// use the larger type.\n\t\t\tif(useFloating)\n\t\t\t{\n\t\t\t\tif(lpt->getFloatingPointBitWidth() > rpt->getFloatingPointBitWidth())\n\t\t\t\t\tout = lpt;\n\n\t\t\t\telse\n\t\t\t\t\tout = rpt;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// following c/c++ conventions, signed types are converted to unsigned types in mixed ops.\n\t\t\t\tif(lpt->getIntegerBitWidth() > rpt->getIntegerBitWidth())\n\t\t\t\t{\n\t\t\t\t\tif(lpt->isSigned() && rpt->isSigned())  out = lpt;\n\t\t\t\t\telse                                    out = (lpt->isSigned() ? rpt : lpt);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif(lpt->isSigned() && rpt->isSigned())  out = rpt;\n\t\t\t\t\telse                                    out = (lpt->isSigned() ? rpt : lpt);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if(ao == \"<<\")\n\t\t{\n\t\t\tif(useFloating) iceAssert(\"shift operation can only be done with ints\");\n\n\t\t\top = OpKind::Bitwise_Shl;\n\t\t\tout = lhs;\n\t\t}\n\t\telse if(ao == \">>\")\n\t\t{\n\t\t\tif(useFloating) iceAssert(\"shift operation can only be done with ints\");\n\n\t\t\top = useSigned ? OpKind::Bitwise_Arithmetic_Shr : OpKind::Bitwise_Logical_Shr;\n\t\t\tout = lhs;\n\t\t}\n\t\telse if(ao == \"&\")\n\t\t{\n\t\t\tif(useFloating) iceAssert(\"bitwise ops only defined for int types (cast if needed)\");\n\n\t\t\top = OpKind::Bitwise_And;\n\t\t\tout = lhs;\n\t\t}\n\t\telse if(ao == \"|\")\n\t\t{\n\t\t\tif(useFloating) iceAssert(\"bitwise ops only defined for int types (cast if needed)\");\n\n\t\t\top = OpKind::Bitwise_Or;\n\t\t\tout = lhs;\n\t\t}\n\t\telse if(ao == \"^\")\n\t\t{\n\t\t\tif(useFloating) iceAssert(\"bitwise ops only defined for int types (cast if needed)\");\n\n\t\t\top = OpKind::Bitwise_Xor;\n\t\t\tout = lhs;\n\t\t}\n\t\telse if(ao == \"~\")\n\t\t{\n\t\t\tif(useFloating) iceAssert(\"bitwise ops only defined for int types (cast if needed)\");\n\n\t\t\top = OpKind::Bitwise_Not;\n\t\t\tout = lhs;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn make_instr(op, false, out, { vlhs, vrhs });\n\t}\n\n\tValue* IRBuilder::BinaryOp(const std::string& ao, Value* a, Value* b, const std::string& vname)\n\t{\n\t\tInstruction* instr = getBinaryOpInstruction(ao, a, b);\n\t\tif(instr == 0) return 0;\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tValue* IRBuilder::Negate(Value* a, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType()->toPrimitiveType() && \"cannot negate non-primitive type\");\n\t\ticeAssert((a->getType()->isFloatingPointType() || a->getType()->toPrimitiveType()->isSigned()) && \"cannot negate unsigned type\");\n\n\t\tInstruction* instr = make_instr(a->getType()->isFloatingPointType() ? OpKind::Floating_Neg : OpKind::Signed_Neg,\n\t\t\tfalse, a->getType(), { a });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::Add(Value* a, Value* b, const std::string& vname)\n\t{\n\t\tif(a->getType() != b->getType())\n\t\t\terror(\"irbuilder: creating add instruction with non-equal types ('%s' vs '%s')\", a->getType(), b->getType());\n\n\t\tOpKind ok = OpKind::Invalid;\n\t\tif(a->getType()->isSignedIntType()) ok = OpKind::Signed_Add;\n\t\telse if(a->getType()->isIntegerType()) ok = OpKind::Unsigned_Add;\n\t\telse ok = OpKind::Floating_Add;\n\n\n\t\tInstruction* instr = make_instr(ok, false, a->getType(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::Subtract(Value* a, Value* b, const std::string& vname)\n\t{\n\t\tif(a->getType() != b->getType())\n\t\t\terror(\"irbuilder: creating sub instruction with non-equal types ('%s' vs '%s')\", a->getType(), b->getType());\n\n\t\tOpKind ok = OpKind::Invalid;\n\t\tif(a->getType()->isSignedIntType()) ok = OpKind::Signed_Sub;\n\t\telse if(a->getType()->isIntegerType()) ok = OpKind::Unsigned_Sub;\n\t\telse ok = OpKind::Floating_Sub;\n\n\t\tInstruction* instr = make_instr(ok, false, a->getType(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::Multiply(Value* a, Value* b, const std::string& vname)\n\t{\n\t\tif(a->getType() != b->getType())\n\t\t\terror(\"irbuilder: creating mul instruction with non-equal types ('%s' vs '%s')\", a->getType(), b->getType());\n\n\t\tOpKind ok = OpKind::Invalid;\n\t\tif(a->getType()->isSignedIntType()) ok = OpKind::Signed_Mul;\n\t\telse if(a->getType()->isIntegerType()) ok = OpKind::Unsigned_Mul;\n\t\telse ok = OpKind::Floating_Mul;\n\n\t\tInstruction* instr = make_instr(ok, false, a->getType(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::Divide(Value* a, Value* b, const std::string& vname)\n\t{\n\t\tif(a->getType() != b->getType())\n\t\t\terror(\"irbuilder: creating div instruction with non-equal types ('%s' vs '%s')\", a->getType(), b->getType());\n\n\n\t\tOpKind ok = OpKind::Invalid;\n\t\tif(a->getType()->isSignedIntType()) ok = OpKind::Signed_Div;\n\t\telse if(a->getType()->isIntegerType()) ok = OpKind::Unsigned_Div;\n\t\telse ok = OpKind::Floating_Div;\n\n\t\tInstruction* instr = make_instr(ok, false, a->getType(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::Modulo(Value* a, Value* b, const std::string& vname)\n\t{\n\t\tif(a->getType() != b->getType())\n\t\t\terror(\"irbuilder: creating mod instruction with non-equal types ('%s' vs '%s')\", a->getType(), b->getType());\n\n\t\tOpKind ok = OpKind::Invalid;\n\t\tif(a->getType()->isSignedIntType()) ok = OpKind::Signed_Mod;\n\t\telse if(a->getType()->isIntegerType()) ok = OpKind::Unsigned_Mod;\n\t\telse ok = OpKind::Floating_Mod;\n\n\t\tInstruction* instr = make_instr(ok, false, a->getType(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::FTruncate(Value* v, Type* targetType, const std::string& vname)\n\t{\n\t\ticeAssert(v->getType()->isFloatingPointType() && targetType->isFloatingPointType() && \"not floating point type\");\n\t\tInstruction* instr = make_instr(OpKind::Floating_Truncate, false, targetType,\n\t\t\tzfu::vectorOf<Value*>(v, ConstantValue::getZeroValue(targetType))\n\t\t);\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::FExtend(Value* v, Type* targetType, const std::string& vname)\n\t{\n\t\ticeAssert(v->getType()->isFloatingPointType() && targetType->isFloatingPointType() && \"not floating point type\");\n\t\tInstruction* instr = make_instr(OpKind::Floating_Extend, false, targetType,\n\t\t\t{ v, ConstantValue::getZeroValue(targetType) });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\n\n\n\tValue* IRBuilder::ICmpEQ(Value* a, Value* b, const std::string& vname)\n\t{\n\t\t//* note: allows comparing mutable and immutable pointers.\n\t\tif(a->getType() != b->getType() && !(a->getType()->isPointerType() && b->getType()->isPointerType()\n\t\t\t&& a->getType()->getPointerElementType() == b->getType()->getPointerElementType()))\n\t\t{\n\t\t\terror(\"irbuilder: creating icmp eq instruction with non-equal types\");\n\t\t}\n\n\t\tInstruction* instr = make_instr(OpKind::ICompare_Equal, false, Type::getBool(),\n\t\t\t{ a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::ICmpNEQ(Value* a, Value* b, const std::string& vname)\n\t{\n\t\t//* note: allows comparing mutable and immutable pointers.\n\t\tif(a->getType() != b->getType() && !(a->getType()->isPointerType() && b->getType()->isPointerType()\n\t\t\t&& a->getType()->getPointerElementType() == b->getType()->getPointerElementType()))\n\t\t{\n\t\t\terror(\"irbuilder: creating icmp neq instruction with non-equal types\");\n\t\t}\n\n\t\tInstruction* instr = make_instr(OpKind::ICompare_NotEqual, false, Type::getBool(),\n\t\t\t{ a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::ICmpGT(Value* a, Value* b, const std::string& vname)\n\t{\n\t\t//* note: allows comparing mutable and immutable pointers.\n\t\tif(a->getType() != b->getType() && !(a->getType()->isPointerType() && b->getType()->isPointerType()\n\t\t\t&& a->getType()->getPointerElementType() == b->getType()->getPointerElementType()))\n\t\t{\n\t\t\terror(\"irbuilder: creating icmp gt instruction with non-equal types\");\n\t\t}\n\n\t\tInstruction* instr = make_instr(OpKind::ICompare_Greater, false, Type::getBool(),\n\t\t\t{ a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::ICmpLT(Value* a, Value* b, const std::string& vname)\n\t{\n\t\t//* note: allows comparing mutable and immutable pointers.\n\t\tif(a->getType() != b->getType() && !(a->getType()->isPointerType() && b->getType()->isPointerType()\n\t\t\t&& a->getType()->getPointerElementType() == b->getType()->getPointerElementType()))\n\t\t{\n\t\t\terror(\"irbuilder: creating icmp lt instruction with non-equal types\");\n\t\t}\n\n\t\tInstruction* instr = make_instr(OpKind::ICompare_Less, false, Type::getBool(),\n\t\t\t{ a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::ICmpGEQ(Value* a, Value* b, const std::string& vname)\n\t{\n\t\t//* note: allows comparing mutable and immutable pointers.\n\t\tif(a->getType() != b->getType() && !(a->getType()->isPointerType() && b->getType()->isPointerType()\n\t\t\t&& a->getType()->getPointerElementType() == b->getType()->getPointerElementType()))\n\t\t{\n\t\t\terror(\"irbuilder: creating icmp geq instruction with non-equal types\");\n\t\t}\n\n\t\tInstruction* instr = make_instr(OpKind::ICompare_GreaterEqual, false, Type::getBool(),\n\t\t\t{ a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::ICmpLEQ(Value* a, Value* b, const std::string& vname)\n\t{\n\t\t//* note: allows comparing mutable and immutable pointers.\n\t\tif(a->getType() != b->getType() && !(a->getType()->isPointerType() && b->getType()->isPointerType()\n\t\t\t&& a->getType()->getPointerElementType() == b->getType()->getPointerElementType()))\n\t\t{\n\t\t\terror(\"irbuilder: creating icmp leq instruction with non-equal types\");\n\t\t}\n\n\t\tInstruction* instr = make_instr(OpKind::ICompare_LessEqual, false, Type::getBool(),\n\t\t\t{ a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\n\n\n\tValue* IRBuilder::FCmpEQ_ORD(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating cmp eq_ord instruction with non-equal types\");\n\t\ticeAssert(a->getType()->isFloatingPointType() && \"creating fcmp instruction with non floating-point types\");\n\t\tInstruction* instr = make_instr(OpKind::FCompare_Equal_ORD, false, Type::getBool(),\n\t\t\t{ a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::FCmpEQ_UNORD(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating cmp eq_uord instruction with non-equal types\");\n\t\ticeAssert(a->getType()->isFloatingPointType() && \"creating fcmp instruction with non floating-point types\");\n\t\tInstruction* instr = make_instr(OpKind::FCompare_Equal_UNORD, false, Type::getBool(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::FCmpNEQ_ORD(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating cmp neq_ord instruction with non-equal types\");\n\t\ticeAssert(a->getType()->isFloatingPointType() && \"creating fcmp instruction with non floating-point types\");\n\t\tInstruction* instr = make_instr(OpKind::FCompare_NotEqual_ORD, false, Type::getBool(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::FCmpNEQ_UNORD(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating cmp neq_uord instruction with non-equal types\");\n\t\ticeAssert(a->getType()->isFloatingPointType() && \"creating fcmp instruction with non floating-point types\");\n\t\tInstruction* instr = make_instr(OpKind::FCompare_NotEqual_UNORD, false, Type::getBool(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::FCmpGT_ORD(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating cmp gt instruction with non-equal types\");\n\t\ticeAssert(a->getType()->isFloatingPointType() && \"creating fcmp instruction with non floating-point types\");\n\t\tInstruction* instr = make_instr(OpKind::FCompare_Greater_ORD, false, Type::getBool(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::FCmpGT_UNORD(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating cmp gt instruction with non-equal types\");\n\t\ticeAssert(a->getType()->isFloatingPointType() && \"creating fcmp instruction with non floating-point types\");\n\t\tInstruction* instr = make_instr(OpKind::FCompare_Greater_UNORD, false, Type::getBool(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::FCmpLT_ORD(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating cmp lt instruction with non-equal types\");\n\t\ticeAssert(a->getType()->isFloatingPointType() && \"creating fcmp instruction with non floating-point types\");\n\t\tInstruction* instr = make_instr(OpKind::FCompare_Less_ORD, false, Type::getBool(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::FCmpLT_UNORD(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating cmp lt instruction with non-equal types\");\n\t\ticeAssert(a->getType()->isFloatingPointType() && \"creating fcmp instruction with non floating-point types\");\n\t\tInstruction* instr = make_instr(OpKind::FCompare_Less_UNORD, false, Type::getBool(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::FCmpGEQ_ORD(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating cmp geq instruction with non-equal types\");\n\t\ticeAssert(a->getType()->isFloatingPointType() && \"creating fcmp instruction with non floating-point types\");\n\t\tInstruction* instr = make_instr(OpKind::FCompare_GreaterEqual_ORD, false, Type::getBool(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::FCmpGEQ_UNORD(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating cmp geq instruction with non-equal types\");\n\t\ticeAssert(a->getType()->isFloatingPointType() && \"creating fcmp instruction with non floating-point types\");\n\t\tInstruction* instr = make_instr(OpKind::FCompare_GreaterEqual_UNORD, false, Type::getBool(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::FCmpLEQ_ORD(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating cmp leq instruction with non-equal types\");\n\t\ticeAssert(a->getType()->isFloatingPointType() && \"creating fcmp instruction with non floating-point types\");\n\t\tInstruction* instr = make_instr(OpKind::FCompare_LessEqual_ORD, false, Type::getBool(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::FCmpLEQ_UNORD(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating cmp leq instruction with non-equal types\");\n\t\ticeAssert(a->getType()->isFloatingPointType() && \"creating fcmp instruction with non floating-point types\");\n\t\tInstruction* instr = make_instr(OpKind::FCompare_LessEqual_UNORD, false, Type::getBool(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\t// returns -1 for a < b, 0 for a == b, 1 for a > b\n\tValue* IRBuilder::ICmpMulti(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating icmp multi instruction with non-equal types\");\n\t\t// iceAssert(a->getType()->isIntegerType() && \"creating icmp multi instruction with non-integer type\");\n\t\tInstruction* instr = make_instr(OpKind::ICompare_Multi, false, Type::getNativeWord(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::FCmpMulti(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating cmp leq instruction with non-equal types\");\n\t\ticeAssert(a->getType()->isFloatingPointType() && \"creating fcmp instruction with non floating-point types\");\n\t\tInstruction* instr = make_instr(OpKind::FCompare_Multi, false, Type::getNativeWord(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\n\n\n\n\n\n\n\n\tValue* IRBuilder::BitwiseXOR(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating bitwise xor instruction with non-equal types\");\n\t\tInstruction* instr = make_instr(OpKind::Bitwise_Xor, false, a->getType(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::BitwiseLogicalSHR(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating bitwise lshl instruction with non-equal types\");\n\t\tInstruction* instr = make_instr(OpKind::Bitwise_Logical_Shr, false, a->getType(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::BitwiseArithmeticSHR(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating bitwise ashl instruction with non-equal types\");\n\t\tInstruction* instr = make_instr(OpKind::Bitwise_Arithmetic_Shr, false, a->getType(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::BitwiseSHL(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating bitwise shr instruction with non-equal types\");\n\t\tInstruction* instr = make_instr(OpKind::Bitwise_Shl, false, a->getType(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::BitwiseAND(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating bitwise and instruction with non-equal types\");\n\t\tInstruction* instr = make_instr(OpKind::Bitwise_And, false, a->getType(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::BitwiseOR(Value* a, Value* b, const std::string& vname)\n\t{\n\t\ticeAssert(a->getType() == b->getType() && \"creating bitwise or instruction with non-equal types\");\n\t\tInstruction* instr = make_instr(OpKind::Bitwise_Or, false, a->getType(), { a, b });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::BitwiseNOT(Value* a, const std::string& vname)\n\t{\n\t\tInstruction* instr = make_instr(OpKind::Bitwise_Not, false, a->getType(), { a });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::Bitcast(Value* v, Type* targetType, const std::string& vname)\n\t{\n\t\tInstruction* instr = make_instr(OpKind::Cast_Bitcast, false, targetType,\n\t\t\t{ v, ConstantValue::getZeroValue(targetType) });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::IntSizeCast(Value* v, Type* targetType, const std::string& vname)\n\t{\n\t\ticeAssert((v->getType()->isIntegerType() || v->getType()->isBoolType()) && \"value is not integer type\");\n\t\ticeAssert((targetType->isIntegerType() || targetType->isBoolType()) && \"target is not integer type\");\n\n\t\t// make constant result for constant operand\n\t\tif(ConstantInt* ci = dcast(ConstantInt, v))\n\t\t{\n\t\t\treturn ConstantInt::get(targetType, ci->getSignedValue());\n\t\t}\n\n\t\tInstruction* instr = make_instr(OpKind::Cast_IntSize, false, targetType,\n\t\t\t{ v, ConstantValue::getZeroValue(targetType) });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::IntSignednessCast(Value* v, Type* targetType, const std::string& vname)\n\t{\n\t\ticeAssert(v->getType()->isIntegerType() && \"value is not integer type\");\n\t\ticeAssert(targetType->isIntegerType() && \"target is not integer type\");\n\n\t\t// make constant result for constant operand\n\t\tif(ConstantInt* ci = dcast(ConstantInt, v))\n\t\t{\n\t\t\tif(ci->getType()->isSignedIntType())\n\t\t\t\treturn ConstantInt::get(targetType, ci->getSignedValue());\n\n\t\t\telse\n\t\t\t\treturn ConstantInt::get(targetType, ci->getUnsignedValue());\n\t\t}\n\n\t\tInstruction* instr = make_instr(OpKind::Cast_IntSignedness, false, targetType,\n\t\t\t{ v, ConstantValue::getZeroValue(targetType) });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::FloatToIntCast(Value* v, Type* targetType, const std::string& vname)\n\t{\n\t\ticeAssert(v->getType()->isFloatingPointType() && \"value is not floating point type\");\n\t\ticeAssert(targetType->isIntegerType() && \"target is not integer type\");\n\n\t\t// make constant result for constant operand\n\t\tif(ConstantFP* cfp = dcast(ConstantFP, v))\n\t\t{\n\t\t\tdouble _ = 0;\n\n\t\t\tif(std::modf(cfp->getValue(), &_) != 0.0)\n\t\t\t\twarn(\"truncating constant '%f' in constant cast to type '%s'\", cfp->getValue(), targetType);\n\n\t\t\treturn ConstantInt::get(targetType, static_cast<size_t>(cfp->getValue()));\n\t\t}\n\n\t\tInstruction* instr = make_instr(OpKind::Cast_FloatToInt, false, targetType,\n\t\t\t{ v, ConstantValue::getZeroValue(targetType) });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::IntToFloatCast(Value* v, Type* targetType, const std::string& vname)\n\t{\n\t\ticeAssert(v->getType()->isIntegerType() && \"value is not integer type\");\n\t\ticeAssert(targetType->isFloatingPointType() && \"target is not floating point type\");\n\n\t\t// make constant result for constant operand\n\t\tif(ConstantInt* ci = dcast(ConstantInt, v))\n\t\t{\n\t\t\tConstantFP* ret = 0;\n\t\t\tbool sgn = ci->getType()->isSignedIntType();\n\t\t\tif(targetType == Type::getFloat32())\n\t\t\t{\n\t\t\t\tif(sgn)\tret = ConstantFP::getFloat32(static_cast<float>(ci->getSignedValue()));\n\t\t\t\telse\tret = ConstantFP::getFloat32(static_cast<float>(ci->getUnsignedValue()));\n\t\t\t}\n\t\t\telse if(targetType == Type::getFloat64())\n\t\t\t{\n\t\t\t\tif(sgn)\tret = ConstantFP::getFloat64(static_cast<double>(ci->getSignedValue()));\n\t\t\t\telse\tret = ConstantFP::getFloat64(static_cast<double>(ci->getUnsignedValue()));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\terror(\"irbuilder: unknown floating point type '%s'\", targetType);\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\tInstruction* instr = make_instr(OpKind::Cast_IntToFloat, false, targetType,\n\t\t\t{ v, ConstantValue::getZeroValue(targetType) });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::PointerTypeCast(Value* v, Type* targetType, const std::string& vname)\n\t{\n\t\ticeAssert((v->getType()->isPointerType() || v->getType()->isNullType()) && \"value is not pointer type\");\n\t\ticeAssert((targetType->isPointerType() || targetType->isNullType()) && \"target is not pointer type\");\n\n\t\tInstruction* instr = make_instr(OpKind::Cast_PointerType, false, targetType,\n\t\t\t{ v, ConstantValue::getZeroValue(targetType) });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::PointerToIntCast(Value* v, Type* targetType, const std::string& vname)\n\t{\n\t\ticeAssert(v->getType()->isPointerType() && \"value is not pointer type\");\n\t\ticeAssert(targetType->isIntegerType() && \"target is not integer type\");\n\n\t\tInstruction* instr = make_instr(OpKind::Cast_PointerToInt, false, targetType,\n\t\t\t{ v, ConstantValue::getZeroValue(targetType) });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::IntToPointerCast(Value* v, Type* targetType, const std::string& vname)\n\t{\n\t\ticeAssert(v->getType()->isIntegerType() && \"value is not integer type\");\n\t\ticeAssert(targetType->isPointerType() && \"target is not pointer type\");\n\n\t\tInstruction* instr = make_instr(OpKind::Cast_IntToPointer, false, targetType,\n\t\t\t{ v, ConstantValue::getZeroValue(targetType) });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\tValue* IRBuilder::IntTruncate(Value* v, Type* targetType, const std::string& vname)\n\t{\n\t\ticeAssert(v->getType()->isIntegerType() && \"value is not integer type\");\n\t\ticeAssert(targetType->isIntegerType() && \"target is not integer type\");\n\n\t\tInstruction* instr = make_instr(OpKind::Integer_Truncate, false, targetType,\n\t\t\t{ v, ConstantValue::getZeroValue(targetType) });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::IntZeroExt(Value* v, Type* targetType, const std::string& vname)\n\t{\n\t\ticeAssert((v->getType()->isIntegerType() || v->getType()->isBoolType()) && \"value is not integer type\");\n\t\ticeAssert(targetType->isIntegerType() && \"target is not integer type\");\n\n\t\tInstruction* instr = make_instr(OpKind::Integer_ZeroExt, false, targetType,\n\t\t\t{ v, ConstantValue::getZeroValue(targetType) });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\n\n\n\tValue* IRBuilder::AppropriateCast(Value* v, Type* r, const std::string& vname)\n\t{\n\t\tauto l = v->getType();\n\n\t\tif(l->isIntegerType() && r->isIntegerType())\n\t\t\treturn this->IntSizeCast(v, r, vname);\n\n\t\telse if(l->isFloatingPointType() && r->isFloatingPointType())\n\t\t\treturn (l->getBitWidth() > r->getBitWidth() ? this->FTruncate(v, r, vname) : this->FExtend(v, r, vname));\n\n\t\telse if(l->isIntegerType() && r->isFloatingPointType())\n\t\t\treturn this->IntToFloatCast(v, r, vname);\n\n\t\telse if(l->isFloatingPointType() && r->isIntegerType())\n\t\t\treturn this->FloatToIntCast(v, r, vname);\n\n\t\telse if(l->isIntegerType() && r->isPointerType())\n\t\t\treturn this->IntToPointerCast(v, r, vname);\n\n\t\telse if(l->isPointerType() && r->isIntegerType())\n\t\t\treturn this->PointerToIntCast(v, r, vname);\n\n\t\telse if(l->isPointerType() && r->isPointerType())\n\t\t\treturn this->PointerTypeCast(v, r, vname);\n\n\t\t// nope.\n\t\treturn 0;\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\tValue* IRBuilder::Call(Function* fn, const std::string& vname)\n\t{\n\t\treturn this->Call(fn, { }, vname);\n\t}\n\n\tValue* IRBuilder::Call(Function* fn, Value* p1, const std::string& vname)\n\t{\n\t\treturn this->Call(fn, { p1 }, vname);\n\t}\n\n\tValue* IRBuilder::Call(Function* fn, Value* p1, Value* p2, const std::string& vname)\n\t{\n\t\treturn this->Call(fn, { p1, p2 }, vname);\n\t}\n\n\tValue* IRBuilder::Call(Function* fn, Value* p1, Value* p2, Value* p3, const std::string& vname)\n\t{\n\t\treturn this->Call(fn, { p1, p2, p3 }, vname);\n\t}\n\n\tValue* IRBuilder::Call(Function* fn, Value* p1, Value* p2, Value* p3, Value* p4, const std::string& vname)\n\t{\n\t\treturn this->Call(fn, { p1, p2, p3, p4 }, vname);\n\t}\n\n\n\tValue* IRBuilder::Call(Function* fn, const std::vector<Value*>& args, const std::string& vname)\n\t{\n\t\tif(args.size() != fn->getArgumentCount() && !fn->isVariadic() && !fn->isCStyleVarArg())\n\t\t{\n\t\t\terror(\"irbuilder: calling function '%s' with the wrong number of arguments (needs %d, have %d)\", fn->getName().str(),\n\t\t\t\tfn->getArgumentCount(), args.size());\n\t\t}\n\n\t\tauto autocastStuff = [this](Value* arg, Type* target) -> Value* {\n\n\t\t\tauto isSlice = [](Type* ty) -> bool {\n\t\t\t\treturn ty->isArraySliceType();\n\t\t\t};\n\n\t\t\tauto isVariadicSlice = [&isSlice](Type* ty) -> bool {\n\t\t\t\treturn isSlice(ty) && ty->toArraySliceType()->isVariadicType();\n\t\t\t};\n\n\t\t\tauto getSliceElm = [](Type* ty) -> Type* {\n\t\t\t\treturn ty->getArrayElementType();\n\t\t\t};\n\n\t\t\tauto isSliceMut = [&isSlice](Type* ty) -> bool {\n\t\t\t\treturn isSlice(ty) && ty->toArraySliceType()->isMutable();\n\t\t\t};\n\n\t\t\tauto at = arg->getType();\n\t\t\tif((isSlice(at) && isSlice(target) && (isVariadicSlice(at) != isVariadicSlice(target)))\n\t\t\t\t|| (isSlice(at) && isSlice(target)\n\t\t\t\t\t&& getSliceElm(at) == getSliceElm(target)\n\t\t\t\t\t&& isSliceMut(at) && !isSliceMut(target)\n\t\t\t\t))\n\t\t\t{\n\t\t\t\t// silently cast, because they're the same thing\n\t\t\t\t// the distinction is solely for the type system's benefit\n\t\t\t\treturn this->Bitcast(arg, target);\n\t\t\t}\n\t\t\telse if(at->isPointerType() && target->isPointerType() && at->getPointerElementType() == target->getPointerElementType() &&\n\t\t\t\tat->isMutablePointer() && target->isImmutablePointer())\n\t\t\t{\n\t\t\t\t// this is ok. at the llvm level the cast should reduce to a no-op.\n\t\t\t\treturn this->PointerTypeCast(arg, target);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn arg;\n\t\t\t}\n\t\t};\n\n\t\tstd::vector<Value*> out;\n\t\tout.reserve(args.size());\n\n\t\tbool forwarded = false;\n\t\tstd::vector<Value*> variadicArgs;\n\n\t\tauto numArgs = fn->getArgumentCount();\n\t\tfor(size_t i = 0; i < args.size(); i++)\n\t\t{\n\t\t\tauto at = args[i]->getType();\n\n\t\t\tif(i < (fn->isVariadic() ? numArgs - 1 : numArgs))\n\t\t\t{\n\t\t\t\tauto target = fn->getArguments()[i]->getType();\n\t\t\t\tout.push_back(autocastStuff(args[i], target));\n\n\t\t\t\tif(out[i]->getType() != target)\n\t\t\t\t{\n\t\t\t\t\terror(\"irbuilder: mismatch in argument type (arg. %d) in function '%s' (need '%s', have '%s')\", i, fn->getName().str(),\n\t\t\t\t\t\tfn->getArguments()[i]->getType(), out[i]->getType());\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(fn->isVariadic())\n\t\t\t{\n\t\t\t\ticeAssert(fn->getArguments().back()->getType()->isVariadicArrayType());\n\t\t\t\tauto elm = fn->getArguments().back()->getType()->getArrayElementType();\n\n\t\t\t\tif(at->isArraySliceType() && at->getArrayElementType() == elm)\n\t\t\t\t{\n\t\t\t\t\tforwarded = true;\n\t\t\t\t\tout.push_back(args[i]);\n\t\t\t\t}\n\t\t\t\telse if(args[i]->getType() != elm)\n\t\t\t\t{\n\t\t\t\t\terror(\"irbuilder: mismatch in argument type (in variadic portion) (arg. %d) in function '%s' (need '%s', have '%s')\",\n\t\t\t\t\t\ti, fn->getName().str(), elm, args[i]->getType());\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// handle it later, lol.\n\t\t\t\t\tvariadicArgs.push_back(autocastStuff(args[i], elm));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(fn->isCStyleVarArg())\n\t\t\t{\n\t\t\t\t// auto-convert strings and char slices into char* when passing to va_args\n\t\t\t\tif(at->isStringType())\n\t\t\t\t\tout.push_back(this->GetSAAData(args[i]));\n\n\t\t\t\telse if(at->isCharSliceType())\n\t\t\t\t\tout.push_back(this->GetArraySliceData(args[i]));\n\n\t\t\t\telse\n\t\t\t\t\tout.push_back(args[i]);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// shouldn't happen -- we should've errored out earlier.\n\t\t\t\ticeAssert(0);\n\t\t\t}\n\t\t}\n\n\t\tif(variadicArgs.size() > 0 && !forwarded)\n\t\t{\n\t\t\ticeAssert(fn->isVariadic());\n\t\t\ticeAssert(fn->getArguments().back()->getType()->isVariadicArrayType());\n\t\t\tauto elm = fn->getArguments().back()->getType()->getArrayElementType();\n\n\t\t\t//? so the strat here is to stack-allocate an array, so we get a pointer to the array,\n\t\t\t//? with which we can use GEP instructions to store things inside.\n\n\t\t\tauto arrty = ArrayType::get(elm, variadicArgs.size());\n\t\t\tauto arrptr = this->StackAlloc(arrty);\n\n\t\t\tfor(size_t i = 0; i < variadicArgs.size(); i++)\n\t\t\t\tthis->WritePtr(variadicArgs[i], this->ConstGEP2(arrptr, 0, i));\n\n\t\t\t// then we make a slice out of it\n\t\t\tauto slcty = ArraySliceType::getVariadic(elm);\n\t\t\tauto slc = this->CreateValue(slcty);\n\n\t\t\t// ugh, fix mutability cast.\n\t\t\tslc = this->SetArraySliceData(slc, this->PointerTypeCast(this->ConstGEP2(arrptr, 0, 0), elm->getPointerTo()));\n\t\t\tslc = this->SetArraySliceLength(slc, ConstantInt::getNative(variadicArgs.size()));\n\n\t\t\t// ok, this is the last argument.\n\t\t\tout.push_back(slc);\n\t\t}\n\t\telse if(fn->isVariadic() && variadicArgs.empty() && !forwarded)\n\t\t{\n\t\t\t// ok, insert the empty slice here.\n\t\t\tauto elm = fn->getArguments().back()->getType()->getArrayElementType();\n\t\t\tout.push_back(ConstantArraySlice::get(ArraySliceType::getVariadic(elm),\n\t\t\t\tConstantValue::getZeroValue(elm->getPointerTo()), ConstantInt::getNative(0)));\n\t\t}\n\n\t\tout.insert(out.begin(), fn);\n\n\t\tInstruction* instr = make_instr(OpKind::Value_CallFunction, true, fn->getType()->getReturnType(), out);\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::Call(Function* fn, const std::initializer_list<Value*>& args, const std::string& vname)\n\t{\n\t\treturn this->Call(fn, std::vector<Value*>(args.begin(), args.end()), vname);\n\t}\n\n\n\n\n\n\tValue* IRBuilder::CallToFunctionPointer(Value* fn, FunctionType* ft, const std::vector<Value*>& args, const std::string& vname)\n\t{\n\t\t//* note: we're using our operator overload here for T + VEC<T>\n\t\tauto out = fn + args;\n\n\t\tInstruction* instr = make_instr(OpKind::Value_CallFunctionPointer, true, ft->getReturnType(), out);\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\tValue* IRBuilder::CallVirtualMethod(ClassType* cls, FunctionType* ft, size_t index, const std::vector<Value*>& args, const std::string& vname)\n\t{\n\t\t// args[0] must be the self, for obvious reasons.\n\t\tauto ty = args[0]->getType();\n\t\ticeAssert(ty->isPointerType() && ty->getPointerElementType()->isClassType());\n\n\t\tauto self = ty->getPointerElementType()->toClassType();\n\t\ticeAssert(self && self == cls);\n\n\t\tInstruction* instr = make_instr(OpKind::Value_CallVirtualMethod, true, ft->getReturnType(),\n\t\t\tzfu::vectorOf<Value*>(\n\t\t\t\tConstantValue::getZeroValue(cls),\n\t\t\t\tConstantInt::getNative(index),\n\t\t\t\tConstantValue::getZeroValue(ft)\n\t\t\t) + args\n\t\t);\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tValue* IRBuilder::Return(Value* v)\n\t{\n\t\tInstruction* instr = make_instr(OpKind::Value_Return, true, Type::getVoid(), { v });\n\t\treturn this->addInstruction(instr, \"\");\n\t}\n\n\tValue* IRBuilder::ReturnVoid()\n\t{\n\t\tInstruction* instr = make_instr(OpKind::Value_Return, true, Type::getVoid(), { });\n\t\treturn this->addInstruction(instr, \"\");\n\t}\n\n\n\tValue* IRBuilder::LogicalNot(Value* v, const std::string& vname)\n\t{\n\t\tInstruction* instr = make_instr(OpKind::Logical_Not, false, Type::getBool(), { v });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\tPHINode* IRBuilder::CreatePHINode(Type* type, const std::string& vname)\n\t{\n\t\tInstruction* instr = make_instr(OpKind::Value_CreatePHI, false, type->getPointerTo(),\n\t\t\t{ ConstantValue::getZeroValue(type) });\n\n\t\t// we need to 'lift' (hoist) the allocation up to make it the first in the block\n\t\t// this is an llvm requirement.\n\n\t\t// MEMORY LEAK\n\t\tinstr->realOutput = new PHINode(type);\n\t\tValue* ret = instr->realOutput;\n\n\t\tret->setName(vname);\n\n\t\t// insert at the front (back = no guarantees)\n\t\tthis->currentBlock->instructions.insert(this->currentBlock->instructions.begin(), instr);\n\t\treturn dcast(PHINode, instr->realOutput);\n\t}\n\n\tValue* IRBuilder::StackAlloc(Type* type, const std::string& vname)\n\t{\n\t\tInstruction* instr = make_instr(OpKind::Value_StackAlloc, false, type->getMutablePointerTo(),\n\t\t\t{ ConstantValue::getZeroValue(type) });\n\n\t\t// we need to 'lift' (hoist) the allocation up to the entry block of the function\n\t\t// this prevents allocation inside loops eating stack memory forever\n\n\t\tValue* ret = instr->realOutput;\n\t\tret->setName(vname);\n\n\t\t// get the parent function\n\t\tauto parent = this->currentBlock->getParentFunction();\n\t\ticeAssert(parent);\n\n\t\tparent->addStackAllocation(type);\n\n\n\t\t// get the entry block\n\t\tauto entry = parent->getBlockList().front();\n\t\ticeAssert(entry);\n\n\t\t// insert at the front (back = no guarantees)\n\t\tentry->instructions.insert(entry->instructions.begin(), instr);\n\n\t\treturn ret;\n\t}\n\n\tValue* IRBuilder::ImmutStackAlloc(Type* type, Value* v, const std::string& vname)\n\t{\n\t\tValue* ret = this->StackAlloc(type, vname);\n\t\tthis->WritePtr(v, ret);\n\n\t\t// now make it immutable.\n\t\tret->setType(type->getPointerTo());\n\t\treturn ret;\n\t}\n\n\n\tValue* IRBuilder::CreateSliceFromSAA(Value* saa, bool mut, const std::string& vname)\n\t{\n\t\tif(!isSAAType(saa->getType()))\n\t\t\terror(\"irbuilder: expected string or dynamic array type, found '%s' instead\", saa->getType());\n\n\t\tauto slc = this->CreateValue(saa->getType()->isStringType() ? Type::getCharSlice(mut)\n\t\t\t: ArraySliceType::get(saa->getType()->getArrayElementType(), mut));\n\n\t\tauto slcelmty = slc->getType()->getArrayElementType();\n\n\t\tslc = this->SetArraySliceData(slc, this->PointerTypeCast(this->GetSAAData(saa), mut ? slcelmty->getMutablePointerTo()\n\t\t\t: slcelmty->getPointerTo()));\n\n\t\tslc = this->SetArraySliceLength(slc, this->GetSAALength(saa));\n\t\tslc->setName(vname);\n\n\t\treturn slc;\n\t}\n\n\n\tvoid IRBuilder::CondBranch(Value* condition, IRBlock* trueB, IRBlock* falseB)\n\t{\n\t\tInstruction* instr = make_instr(OpKind::Branch_Cond, true, Type::getVoid(),\n\t\t\t{ condition, trueB, falseB });\n\t\tthis->addInstruction(instr, \"\");\n\t}\n\n\tvoid IRBuilder::UnCondBranch(IRBlock* target)\n\t{\n\t\tInstruction* instr = make_instr(OpKind::Branch_UnCond, true, Type::getVoid(),\n\t\t\t{ target });\n\t\tthis->addInstruction(instr, \"\");\n\t}\n\n\n\tValue* IRBuilder::GetRawUnionFieldByType(Value* lval, Type* type, const std::string& vname)\n\t{\n\t\tif(!lval->islvalue())\n\t\t\terror(\"irbuilder: cannot do raw union ops on non-lvalue\");\n\n\t\tif(!lval->getType()->isRawUnionType())\n\t\t\terror(\"irbuilder: '%s' is not a raw union type!\", lval->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::RawUnion_GEP, false, type, { lval, ConstantValue::getZeroValue(type) });\n\n\t\tauto ret = this->addInstruction(instr, \"\");\n\t\tret->setKind(lval->kind);\n\t\tret->setName(vname);\n\n\t\treturn ret;\n\t}\n\n\tValue* IRBuilder::GetRawUnionField(Value* lval, const std::string& field, const std::string& vname)\n\t{\n\t\tif(!lval->islvalue())\n\t\t\terror(\"irbuilder: cannot do raw union ops on non-lvalue\");\n\n\t\tif(!lval->getType()->isRawUnionType())\n\t\t\terror(\"irbuilder: '%s' is not a raw union type!\", lval->getType());\n\n\t\tauto rut = lval->getType()->toRawUnionType();\n\t\tif(!rut->hasVariant(field))\n\t\t\terror(\"irbuilder: union '%s' does not have a field '%s'\", rut->getTypeName(), field);\n\n\t\tauto ty = rut->getVariant(field);\n\t\treturn this->GetRawUnionFieldByType(lval, ty, vname);\n\t}\n\n\n\n\ttemplate <typename T>\n\tstatic Instruction* doGEPOnCompoundType(T* type, Value* structPtr, size_t memberIndex)\n\t{\n\t\tif(!structPtr->islvalue())\n\t\t\terror(\"irbuilder: cannot do GEP on non-lvalue\");\n\n\t\ticeAssert(type->getElementCount() > memberIndex && \"struct does not have so many members\");\n\n\t\tInstruction* instr = make_instr(OpKind::Value_GetStructMember, false, type->getElementN(memberIndex),\n\t\t\t{ structPtr, ConstantInt::getUNative(memberIndex) }, Value::Kind::lvalue);\n\n\t\treturn instr;\n\t}\n\n\n\n\n\tValue* IRBuilder::StructGEP(Value* structPtr, size_t memberIndex, const std::string& vname)\n\t{\n\t\tif(!structPtr->islvalue())\n\t\t\terror(\"irbuilder: cannot do GEP on non-lvalue\");\n\n\t\tif(structPtr->getType()->isStructType())\n\t\t{\n\t\t\tauto st = structPtr->getType()->toStructType();\n\t\t\treturn this->addInstruction(doGEPOnCompoundType(st,\tstructPtr, memberIndex), vname);\n\t\t}\n\t\telse if(structPtr->getType()->isTupleType())\n\t\t{\n\t\t\tauto tt = structPtr->getType()->toTupleType();\n\t\t\treturn this->addInstruction(doGEPOnCompoundType(tt, structPtr, memberIndex), vname);\n\t\t}\n\t\telse if(structPtr->getType()->isClassType())\n\t\t{\n\t\t\terror(\"irbuilder: classes do not support element access by index\");\n\n\t\t\t// auto ct = structPtr->getType()->toClassType();\n\t\t\t// // to compensate for the vtable, we add one to the index if there is a vtable!\n\t\t\t// if(ct->getVirtualMethodCount() > 0)\n\t\t\t// \tmemberIndex += 1;\n\n\t\t\t// return this->addInstruction(doGEPOnCompoundType(ct,\n\t\t\t// \tstructPtr, memberIndex), vname);\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(\"irbuilder: type '%s' is not a valid type to GEP into\", structPtr->getType());\n\t\t}\n\t}\n\n\tValue* IRBuilder::GetStructMember(Value* ptr, const std::string& memberName)\n\t{\n\t\tif(!ptr->islvalue())\n\t\t\terror(\"irbuilder: cannot do GEP on non-lvalue\");\n\n\t\tif(ptr->getType()->isStructType())\n\t\t{\n\t\t\tauto st = ptr->getType()->toStructType();\n\t\t\tauto memt = st->getElement(memberName);\n\n\t\t\ticeAssert(st->hasElementWithName(memberName) && \"no element with such name\");\n\n\t\t\tInstruction* instr = make_instr(OpKind::Value_GetStructMember, false, memt,\n\t\t\t\t{ ptr, ConstantInt::getUNative(st->getElementIndex(memberName)) }, Value::Kind::lvalue);\n\n\t\t\treturn this->addInstruction(instr, memberName);\n\t\t}\n\t\telse if(ptr->getType()->isClassType())\n\t\t{\n\t\t\tauto ct = ptr->getType()->toClassType();\n\n\t\t\ticeAssert(ct->hasElementWithName(memberName) && \"no element with such name\");\n\t\t\tauto memt = ct->getElement(memberName);\n\n\t\t\t//! VTABLE HANDLING\n\t\t\tsize_t vTableOfs = 0;\n\t\t\tif(ct->getVirtualMethodCount() > 0)\n\t\t\t\tvTableOfs = 1;\n\n\t\t\tInstruction* instr = make_instr(OpKind::Value_GetStructMember, false, memt,\n\t\t\t\t{ ptr, ConstantInt::getUNative(ct->getAbsoluteElementIndex(memberName) + vTableOfs) }, Value::Kind::lvalue);\n\n\t\t\treturn this->addInstruction(instr, memberName);\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(\"irbuilder: type '%s' is not a valid type to GEP into\", ptr->getType());\n\t\t}\n\t}\n\n\n\n\tvoid IRBuilder::SetVtable(Value* ptr, Value* table)\n\t{\n\t\tif(!ptr->islvalue())\n\t\t\terror(\"irbuilder: cannot do set vtable on non-lvalue\");\n\n\t\tauto ty = ptr->getType();\n\t\tif(!ty->isClassType()) error(\"irbuilder: '%s' is not a class type\", ty);\n\t\tif(table->getType() != Type::getInt8Ptr()) error(\"irbuilder: expected i8* for vtable, got '%s'\", table->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::Value_GetStructMember, false, Type::getInt8Ptr(), { ptr, ConstantInt::getUNative(0) }, Value::Kind::lvalue);\n\n\t\tauto gep = this->addInstruction(instr, \"__vtable\");\n\t\tthis->Store(table, gep);\n\t}\n\n\n\n\n\t// equivalent to GEP(ptr*, ptrIndex, elmIndex)\n\tValue* IRBuilder::ConstGEP2(Value* ptr, size_t ptrIndex, size_t elmIndex, const std::string& vname)\n\t{\n\t\tif(!ptr->getType()->isPointerType())\n\t\t\terror(\"irbuilder: ptr is not a pointer type (got '%s')\", ptr->getType());\n\n\t\tauto ptri = ConstantInt::getUNative(ptrIndex);\n\t\tauto elmi = ConstantInt::getUNative(elmIndex);\n\n\t\treturn this->GEP2(ptr, ptri, elmi, vname);\n\t}\n\n\t// equivalent to GEP(ptr*, ptrIndex, elmIndex)\n\tValue* IRBuilder::GEP2(Value* ptr, Value* ptrIndex, Value* elmIndex, const std::string& vname)\n\t{\n\t\tif(!ptr->getType()->isPointerType())\n\t\t\terror(\"irbuilder: ptr is not a pointer type (got '%s')\", ptr->getType());\n\n\t\telse if(ptr->getType()->getPointerElementType()->isClassType() || ptr->getType()->getPointerElementType()->isStructType())\n\t\t\terror(\"irbuilder: use the other function for struct types\");\n\n\t\ticeAssert(ptrIndex->getType()->isIntegerType() && \"ptrIndex is not integer type\");\n\t\ticeAssert(elmIndex->getType()->isIntegerType() && \"elmIndex is not integer type\");\n\n\t\tType* retType = ptr->getType()->getPointerElementType();\n\t\tif(retType->isArrayType())\n\t\t\tretType = retType->toArrayType()->getElementType()->getPointerTo();\n\n\t\tif(ptr->getType()->isMutablePointer())\n\t\t\tretType = retType->getMutablePointerVersion();\n\n\t\tInstruction* instr = make_instr(OpKind::Value_GetGEP2, false, retType, { ptr, ptrIndex, elmIndex });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\t// equivalent to GEP(ptr*, index)\n\tValue* IRBuilder::GetPointer(Value* ptr, Value* ptrIndex, const std::string& vname)\n\t{\n\t\tif(!ptr->getType()->isPointerType())\n\t\t\terror(\"irbuilder: ptr is not a pointer type (got '%s')\", ptr->getType());\n\n\t\tif(!ptrIndex->getType()->isIntegerType())\n\t\t\terror(\"irbuilder: ptrIndex is not an integer type (got '%s')\", ptrIndex->getType());\n\n\t\tif(ptr->getType()->getPointerElementType()->isClassType() || ptr->getType()->getPointerElementType()->isStructType())\n\t\t\terror(\"irbuilder: use the other function for struct types\");\n\n\t\tInstruction* instr = make_instr(OpKind::Value_GetPointer, false, ptr->getType(), { ptr, ptrIndex });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\tValue* IRBuilder::Select(Value* cond, Value* one, Value* two, const std::string& vname)\n\t{\n\t\tif(!cond->getType()->isBoolType())\n\t\t\terror(\"irbuilder: cond is not a boolean type (got '%s')\", cond->getType());\n\n\t\tif(one->getType() != two->getType())\n\t\t\terror(\"irbuilder: non-identical types for operands (got '%s' and '%s')\", one->getType(), two->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::Value_Select, false, one->getType(), { cond, one, two });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\n\tValue* IRBuilder::Sizeof(Type* t, const std::string& vname)\n\t{\n\t\tInstruction* instr = make_instr(OpKind::Misc_Sizeof, false, Type::getNativeWord(),\n\t\t\t{ ConstantValue::getZeroValue(t) });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::CreateValue(Type* t, const std::string& vname)\n\t{\n\t\tauto ret = ConstantValue::getZeroValue(t);\n\t\tret->setName(vname);\n\n\t\treturn ret;\n\t}\n\n\n\n\n\n\n\n\n\tstatic Instruction* _insertValue(Value* val, size_t idx, Type* et, Value* elm)\n\t{\n\t\tType* t = val->getType();\n\t\tif(!t->isStructType() && !t->isClassType() && !t->isTupleType() && !t->isArrayType())\n\t\t\terror(\"irbuilder: val is not an aggregate type (have '%s')\", t);\n\n\t\tif(elm->getType() != et)\n\t\t{\n\t\t\terror(\"irbuilder: mismatched types for value and element -- trying to insert '%s' into '%s'\",\n\t\t\t\telm->getType(), et);\n\t\t}\n\n\t\tint ofs = 0;\n\t\t//! VTABLE HANDLING\n\t\tif(t->isClassType() && t->toClassType()->getVirtualMethodCount() > 0)\n\t\t\tofs = 1;\n\n\t\tstd::vector<Value*> args = { val, elm, ConstantInt::getNative(idx + ofs) };\n\n\t\t// note: no sideeffects, since we return a new aggregate\n\t\treturn make_instr(OpKind::Value_InsertValue, false, t, args);\n\t}\n\n\tstatic Instruction* _extractValue(Value* val, size_t idx, Type* et)\n\t{\n\t\tType* t = val->getType();\n\t\tif(!t->isStructType() && !t->isClassType() && !t->isTupleType() && !t->isArrayType())\n\t\t\terror(\"irbuilder: val is not an aggregate type (have '%s')\", t);\n\n\t\tint ofs = 0;\n\t\t//! VTABLE HANDLING\n\t\tif(t->isClassType() && t->toClassType()->getVirtualMethodCount() > 0)\n\t\t\tofs = 1;\n\n\t\tstd::vector<Value*> args = { val, ConstantInt::getNative(idx + ofs) };\n\n\t\t// note: no sideeffects, since we return a new aggregate\n\t\treturn make_instr(OpKind::Value_ExtractValue, false, et, args);\n\t}\n\n\n\n\n\n\n\tValue* IRBuilder::InsertValue(Value* val, const std::vector<size_t>& inds, Value* elm, const std::string& vname)\n\t{\n\t\tType* t = val->getType();\n\t\tif(t->isClassType())\n\t\t\terror(\"irbuilder: classes do not support element access by index\");\n\n\t\tif(!t->isStructType() && !t->isTupleType() && !t->isArrayType())\n\t\t\terror(\"irbuilder: val is not a supported aggregate type (have '%s')\", t);\n\n\t\tif(inds.size() != 1)\n\t\t\terror(\"irbuilder: must have exactly one index!\");\n\n\n\t\tType* et = 0;\n\t\tif(t->isStructType())       et = t->toStructType()->getElementN(inds[0]);\n\t\telse if(t->isTupleType())   et = t->toTupleType()->getElementN(inds[0]);\n\t\telse if(t->isArrayType())   et = t->toArrayType()->getElementType();\n\n\t\ticeAssert(et);\n\t\treturn this->addInstruction(_insertValue(val, inds[0], et, elm), vname);\n\t}\n\n\tValue* IRBuilder::ExtractValue(Value* val, const std::vector<size_t>& inds, const std::string& vname)\n\t{\n\t\tType* t = val->getType();\n\t\tif(!t->isStructType() && !t->isClassType() && !t->isTupleType() && !t->isArrayType())\n\t\t\terror(\"irbuilder: val is not an aggregate type (have '%s')\", t);\n\n\t\tif(inds.size() != 1)\n\t\t\terror(\"irbuilder: must have exactly one index!\");\n\n\t\tif(t->isClassType())\n\t\t\terror(\"irbuilder: classes do not support element access by index\");\n\n\t\tType* et = 0;\n\t\tif(t->isStructType())       et = t->toStructType()->getElementN(inds[0]);\n\t\telse if(t->isTupleType())   et = t->toTupleType()->getElementN(inds[0]);\n\t\telse if(t->isArrayType())   et = t->toArrayType()->getElementType();\n\n\t\ticeAssert(et);\n\t\treturn this->addInstruction(_extractValue(val, inds[0], et), vname);\n\t}\n\n\n\tValue* IRBuilder::InsertValueByName(Value* val, const std::string& n, Value* elm, const std::string& vname)\n\t{\n\t\tType* t = val->getType();\n\t\tif(!t->isStructType() && !t->isClassType())\n\t\t\terror(\"irbuilder: val is not an aggregate type with named members (class or struct) (have '%s')\", t);\n\n\t\tsize_t ind = 0;\n\t\tType* et = 0;\n\t\tif(t->isStructType())       ind = t->toStructType()->getElementIndex(n), et = t->toStructType()->getElement(n);\n\t\telse if(t->isClassType())   ind = t->toClassType()->getAbsoluteElementIndex(n), et = t->toClassType()->getElement(n);\n\t\telse                        iceAssert(0);\n\n\t\treturn this->addInstruction(_insertValue(val, ind, et, elm), vname);\n\t}\n\n\tValue* IRBuilder::ExtractValueByName(Value* val, const std::string& n, const std::string& vname)\n\t{\n\t\tType* t = val->getType();\n\t\tif(!t->isStructType() && !t->isClassType())\n\t\t\terror(\"irbuilder: val is not an aggregate type with named members (class or struct) (have '%s')\", t);\n\n\t\tsize_t ind = 0;\n\t\tType* et = 0;\n\t\tif(t->isStructType())       ind = t->toStructType()->getElementIndex(n), et = t->toStructType()->getElement(n);\n\t\telse if(t->isClassType())   ind = t->toClassType()->getAbsoluteElementIndex(n), et = t->toClassType()->getElement(n);\n\t\telse                        iceAssert(0);\n\n\t\treturn this->addInstruction(_extractValue(val, ind, et), vname);\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\tValue* IRBuilder::GetSAAData(Value* arr, const std::string& vname)\n\t{\n\t\tif(!isSAAType(arr->getType()))\n\t\t\terror(\"irbuilder: thing is not an SAA type (got '%s')\", arr->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::SAA_GetData, false, getSAAElmType(arr->getType())->getMutablePointerTo(), { arr });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::SetSAAData(Value* arr, Value* val, const std::string& vname)\n\t{\n\t\tif(!isSAAType(arr->getType()))\n\t\t\terror(\"irbuilder: thing is not an SAA type (got '%s')\", arr->getType());\n\n\t\tauto t = getSAAElmType(arr->getType());\n\t\tif(val->getType() != t->getMutablePointerTo())\n\t\t{\n\t\t\terror(\"irbuilder: val is not a pointer to elm type (need '%s', have '%s')\",\n\t\t\t\tt->getMutablePointerTo(), val->getType());\n\t\t}\n\n\t\tInstruction* instr = make_instr(OpKind::SAA_SetData, true, arr->getType(), { arr, val });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\n\tValue* IRBuilder::GetSAALength(Value* arr, const std::string& vname)\n\t{\n\t\tif(!isSAAType(arr->getType()))\n\t\t\terror(\"irbuilder: thing is not an SAA type (got '%s')\", arr->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::SAA_GetLength, false, Type::getNativeWord(), { arr });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::SetSAALength(Value* arr, Value* val, const std::string& vname)\n\t{\n\t\tif(!isSAAType(arr->getType()))\n\t\t\terror(\"irbuilder: thing is not an SAA type (got '%s')\", arr->getType());\n\n\t\tif(val->getType() != Type::getNativeWord())\n\t\t\terror(\"irbuilder: val is not an int64\");\n\n\t\tInstruction* instr = make_instr(OpKind::SAA_SetLength, true, arr->getType(), { arr, val });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\n\tValue* IRBuilder::GetSAACapacity(Value* arr, const std::string& vname)\n\t{\n\t\tif(!isSAAType(arr->getType()))\n\t\t\terror(\"irbuilder: thing is not an SAA type (got '%s')\", arr->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::SAA_GetCapacity, false, Type::getNativeWord(), { arr });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::SetSAACapacity(Value* arr, Value* val, const std::string& vname)\n\t{\n\t\tif(!isSAAType(arr->getType()))\n\t\t\terror(\"irbuilder: thing is not an SAA type (got '%s')\", arr->getType());\n\n\t\tif(val->getType() != Type::getNativeWord())\n\t\t\terror(\"irbuilder: val is not an int64\");\n\n\t\tInstruction* instr = make_instr(OpKind::SAA_SetCapacity, true, arr->getType(), { arr, val });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\n\tValue* IRBuilder::GetSAARefCountPointer(Value* arr, const std::string& vname)\n\t{\n\t\tif(!isSAAType(arr->getType()))\n\t\t\terror(\"irbuilder: thing is not an SAA type (got '%s')\", arr->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::SAA_GetRefCountPtr, false, Type::getNativeWordPtr(), { arr });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::SetSAARefCountPointer(Value* arr, Value* val, const std::string& vname)\n\t{\n\t\tif(!isSAAType(arr->getType()))\n\t\t\terror(\"irbuilder: thing is not an SAA type (got '%s')\", arr->getType());\n\n\t\tif(val->getType() != Type::getNativeWord()->getPointerTo())\n\t\t\terror(\"irbuilder: val is not an int64 pointer\");\n\n\t\tInstruction* instr = make_instr(OpKind::SAA_SetRefCountPtr, true, arr->getType(), { arr, val });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\n\tValue* IRBuilder::GetSAARefCount(Value* arr, const std::string& vname)\n\t{\n\t\treturn this->ReadPtr(this->GetSAARefCountPointer(arr), vname);\n\t}\n\n\tvoid IRBuilder::SetSAARefCount(Value* arr, Value* val)\n\t{\n\t\tif(val->getType() != Type::getNativeWord())\n\t\t\terror(\"irbuilder: val is not an int64\");\n\n\t\tthis->WritePtr(val, this->PointerTypeCast(this->GetSAARefCountPointer(arr), Type::getNativeWordPtr()->getMutablePointerVersion()));\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tValue* IRBuilder::GetArraySliceData(Value* slc, const std::string& vname)\n\t{\n\t\tif(!slc->getType()->isArraySliceType())\n\t\t\terror(\"irbuilder: slc is not an array slice type (got '%s')\", slc->getType());\n\n\t\tauto st = slc->getType()->toArraySliceType();\n\t\tauto et = st->getElementType();\n\n\t\tInstruction* instr = make_instr(OpKind::ArraySlice_GetData, false, st->isMutable() ? et->getMutablePointerTo() : et->getPointerTo(), { slc });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::SetArraySliceData(Value* slc, Value* val, const std::string& vname)\n\t{\n\t\tif(!slc->getType()->isArraySliceType())\n\t\t\terror(\"irbuilder: slc is not an array slice type (got '%s')\", slc->getType());\n\n\t\tauto st = slc->getType()->toArraySliceType();\n\t\tauto et = st->getElementType();\n\t\tauto pt = (st->isMutable() ? et->getMutablePointerTo() : et->getPointerTo());\n\n\t\tif(val->getType() != pt)\n\t\t{\n\t\t\tif(pt->getPointerElementType() != val->getType()->getPointerElementType() || (pt->isMutablePointer() && val->getType()->isImmutablePointer()))\n\t\t\t\terror(\"irbuilder: val is not a pointer to elm type (need '%s', have '%s')\", pt, val->getType());\n\t\t}\n\n\t\tInstruction* instr = make_instr(OpKind::ArraySlice_SetData, true, slc->getType(), { slc, val });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\tValue* IRBuilder::GetArraySliceLength(Value* slc, const std::string& vname)\n\t{\n\t\tif(!slc->getType()->isArraySliceType())\n\t\t\terror(\"irbuilder: slc is not an array slice type (got '%s')\", slc->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::ArraySlice_GetLength, false, Type::getNativeWord(), { slc });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::SetArraySliceLength(Value* slc, Value* val, const std::string& vname)\n\t{\n\t\tif(!slc->getType()->isArraySliceType())\n\t\t\terror(\"irbuilder: slc is not an array slice type (got '%s')\", slc->getType());\n\n\t\tif(val->getType() != Type::getNativeWord())\n\t\t\terror(\"irbuilder: val is not an int64\");\n\n\t\tInstruction* instr = make_instr(OpKind::ArraySlice_SetLength, true, slc->getType(), { slc, val });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\n\n\n\n\n\n\tValue* IRBuilder::GetAnyTypeID(Value* any, const std::string& vname)\n\t{\n\t\tif(!any->getType()->isAnyType())\n\t\t\terror(\"irbuilder: not any type (got '%s')\", any->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::Any_GetTypeID, false, Type::getNativeUWord(), { any });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::SetAnyTypeID(Value* any, Value* val, const std::string& vname)\n\t{\n\t\tif(!any->getType()->isAnyType())\n\t\t\terror(\"irbuilder: not any type (got '%s')\", any->getType());\n\n\t\telse if(val->getType() != Type::getNativeUWord())\n\t\t\terror(\"irbuilder: val is not a uint64\");\n\n\t\tInstruction* instr = make_instr(OpKind::Any_SetTypeID, true, Type::getAny(), { any, val });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\tValue* IRBuilder::GetAnyData(Value* any, const std::string& vname)\n\t{\n\t\tif(!any->getType()->isAnyType())\n\t\t\terror(\"irbuilder: not any type (got '%s')\", any->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::Any_GetData, false, ArrayType::get(Type::getInt8(),\n\t\t\tBUILTIN_ANY_DATA_BYTECOUNT), { any });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::SetAnyData(Value* any, Value* val, const std::string& vname)\n\t{\n\t\tif(!any->getType()->isAnyType())\n\t\t\terror(\"irbuilder: not any type (got '%s')\", any->getType());\n\n\t\telse if(val->getType() != ArrayType::get(Type::getInt8(), BUILTIN_ANY_DATA_BYTECOUNT))\n\t\t\terror(\"irbuilder: val is not array type (got '%s')\", val->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::Any_SetData, true, Type::getAny(), { any, val });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\tValue* IRBuilder::GetAnyRefCountPointer(Value* arr, const std::string& vname)\n\t{\n\t\tif(!arr->getType()->isAnyType())\n\t\t\terror(\"irbuilder: arr is not an any type (got '%s')\", arr->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::Any_GetRefCountPtr, false, Type::getNativeWordPtr(), { arr });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::SetAnyRefCountPointer(Value* arr, Value* val, const std::string& vname)\n\t{\n\t\tif(!arr->getType()->isAnyType())\n\t\t\terror(\"irbuilder: arr is not an any type (got '%s')\", arr->getType());\n\n\t\tif(val->getType() != Type::getNativeWord()->getPointerTo())\n\t\t\terror(\"irbuilder: val is not an int64 pointer\");\n\n\t\tInstruction* instr = make_instr(OpKind::Any_SetRefCountPtr, true, arr->getType(), { arr, val });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\n\tValue* IRBuilder::GetAnyRefCount(Value* arr, const std::string& vname)\n\t{\n\t\treturn this->ReadPtr(this->GetAnyRefCountPointer(arr), vname);\n\t}\n\n\tvoid IRBuilder::SetAnyRefCount(Value* arr, Value* val)\n\t{\n\t\tif(val->getType() != Type::getNativeWord())\n\t\t\terror(\"irbuilder: val is not an int64\");\n\n\t\tthis->WritePtr(val, this->PointerTypeCast(this->GetAnyRefCountPointer(arr),\n\t\t\tType::getNativeWordPtr()->getMutablePointerVersion()));\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tValue* IRBuilder::GetRangeLower(Value* range, const std::string& vname)\n\t{\n\t\tif(!range->getType()->isRangeType())\n\t\t\terror(\"irbuilder: range is not a range type (have '%s')\", range->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::Range_GetLower, false, Type::getNativeWord(), { range });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::SetRangeLower(Value* range, Value* val, const std::string& vname)\n\t{\n\t\tif(!range->getType()->isRangeType())\n\t\t\terror(\"irbuilder: range is not a range type (got '%s')\", range->getType());\n\n\t\tif(!val->getType()->isIntegerType())\n\t\t\terror(\"irbuilder: val is not an integer type (got '%s')\", val->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::Range_SetLower, true, Type::getRange(), { range, val });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::GetRangeUpper(Value* range, const std::string& vname)\n\t{\n\t\tif(!range->getType()->isRangeType())\n\t\t\terror(\"irbuilder: range is not a range type (have '%s')\", range->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::Range_GetUpper, false, Type::getNativeWord(), { range });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::SetRangeUpper(Value* range, Value* val, const std::string& vname)\n\t{\n\t\tif(!range->getType()->isRangeType())\n\t\t\terror(\"irbuilder: range is not a range type (got '%s')\", range->getType());\n\n\t\tif(!val->getType()->isIntegerType())\n\t\t\terror(\"irbuilder: val is not an integer type (got '%s')\", val->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::Range_SetUpper, true, Type::getRange(), { range, val });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::GetRangeStep(Value* range, const std::string& vname)\n\t{\n\t\tif(!range->getType()->isRangeType())\n\t\t\terror(\"irbuilder: range is not a range type (have '%s')\", range->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::Range_GetStep, false, Type::getNativeWord(), { range });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::SetRangeStep(Value* range, Value* val, const std::string& vname)\n\t{\n\t\tif(!range->getType()->isRangeType())\n\t\t\terror(\"irbuilder: range is not a range type (got '%s')\", range->getType());\n\n\t\tif(!val->getType()->isIntegerType())\n\t\t\terror(\"irbuilder: val is not an integer type (got '%s')\", val->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::Range_SetStep, true, Type::getRange(), { range, val });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\n\n\tValue* IRBuilder::GetEnumCaseIndex(Value* ecs, const std::string& vname)\n\t{\n\t\tif(!ecs->getType()->isEnumType())\n\t\t\terror(\"irbuilder: enum is not an enum type (got '%s')\", ecs->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::Enum_GetIndex, true, Type::getNativeWord(), { ecs });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::SetEnumCaseIndex(Value* ecs, Value* idx, const std::string& vname)\n\t{\n\t\tif(!ecs->getType()->isEnumType())\n\t\t\terror(\"irbuilder: enum is not an enum type (got '%s')\", ecs->getType());\n\n\t\tif(!idx->getType()->isIntegerType())\n\t\t\terror(\"irbuilder: index is not an integer type (got '%s')\", idx->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::Enum_SetIndex, true, ecs->getType(), { ecs, idx });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::GetEnumCaseValue(Value* ecs, const std::string& vname)\n\t{\n\t\tif(!ecs->getType()->isEnumType())\n\t\t\terror(\"irbuilder: enum is not an enum type (got '%s')\", ecs->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::Enum_GetValue, true, ecs->getType()->toEnumType()->getCaseType(), { ecs });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::SetEnumCaseValue(Value* ecs, Value* val, const std::string& vname)\n\t{\n\t\tif(!ecs->getType()->isEnumType())\n\t\t\terror(\"irbuilder: enum is not an enum type (got '%s')\", ecs->getType());\n\n\t\tif(ecs->getType()->toEnumType()->getCaseType() != val->getType())\n\t\t{\n\t\t\terror(\"irbuilder: value type mismatch (enum case type is '%s', value type is '%s'\",\n\t\t\t\tecs->getType()->toEnumType()->getCaseType(), val->getType());\n\t\t}\n\n\t\tInstruction* instr = make_instr(OpKind::Enum_SetValue, true, ecs->getType(), { ecs, val });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\n\n\n\n\n\tValue* IRBuilder::ReadPtr(Value* ptr, const std::string& vname)\n\t{\n\t\tif(!ptr->getType()->isPointerType())\n\t\t\terror(\"irbuilder: ptr is not pointer type (got '%s')\", ptr->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::Value_ReadPtr, false, ptr->getType()->getPointerElementType(), { ptr });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tvoid IRBuilder::WritePtr(Value* v, Value* ptr)\n\t{\n\t\tif(!ptr->getType()->isPointerType())\n\t\t\terror(\"irbuilder: ptr is not pointer type (got '%s')\", ptr->getType());\n\n\t\tif(ptr->getType()->isImmutablePointer())\n\t\t\terror(\"irbuilder: cannot store value to immutable pointer type '%s'\", ptr->getType());\n\n\t\tauto vt = v->getType();\n\t\tauto pt = ptr->getType();\n\n\t\tif(vt != pt->getPointerElementType())\n\t\t{\n\t\t\t//* here, we know that the storage pointer is mutable. there's a special edge-case we need to catch:\n\t\t\t//* if we're storing a value of type &T to a & &mut T, or a &mut T to a & &T.\n\t\t\t//* in those cases, the mutability of the base type doesn't matter at all. At the LLVM level, we don't even make a distinction,\n\t\t\t//* so we can safely pass this onto the translation layer without worrying about it.\n\n\t\t\t// if((vt->isPointerType() && pt->isPointerType() && vt->getPointerElementType() == pt->getPointerElementType()) == false)\n\t\t\terror(\"irbuilder: ptr is not a pointer to type of value (base types '%s' -> '%s' differ)\", vt, pt->getPointerElementType());\n\t\t}\n\n\n\t\tInstruction* instr = make_instr(OpKind::Value_WritePtr, true, Type::getVoid(), { v, ptr });\n\t\tthis->addInstruction(instr, \"\");\n\t}\n\n\n\tstatic std::pair<Instruction*, IRBlock*> getInstrThatMakesLValue(IRBuilder* irb, Type* type, const std::string& vname)\n\t{\n\t\tInstruction* instr = make_instr(OpKind::Value_CreateLVal, true, type, { ConstantValue::getZeroValue(type) }, Value::Kind::lvalue);\n\n\t\tValue* ret = instr->realOutput;\n\t\tret->setName(vname);\n\n\t\t// get the parent function\n\t\tauto parent = irb->getCurrentBlock()->getParentFunction();\n\t\ticeAssert(parent);\n\n\t\tparent->addStackAllocation(type);\n\n\t\t// get the entry block\n\t\tauto entry = parent->getBlockList().front();\n\t\ticeAssert(entry);\n\n\t\treturn { instr, entry };\n\t}\n\n\n\tValue* IRBuilder::CreateLValue(Type* type, const std::string& vname)\n\t{\n\t\tauto [ instr, entry ] = getInstrThatMakesLValue(this, type, vname);\n\n\t\t// needs to be hoisted also\n\t\tentry->instructions.insert(entry->instructions.begin(), instr);\n\n\t\treturn instr->realOutput;\n\t}\n\n\tvoid IRBuilder::Store(Value* val, Value* lval)\n\t{\n\t\tif(lval->isConst())\n\t\t\terror(\"irbuilder: cannot store to constant lvalue\");\n\n\t\telse if(!lval->islvalue())\n\t\t\terror(\"irbuilder: cannot store to non-lvalue\");\n\n\t\telse if(val->getType() != lval->getType())\n\t\t\terror(\"irbuilder: cannot store value of type '%s' to lvalue of type '%s'\", val->getType(), lval->getType());\n\n\t\t// ok...\n\t\tInstruction* instr = make_instr(OpKind::Value_Store, true, Type::getVoid(), { val, lval });\n\t\tthis->addInstruction(instr, \"\");\n\t}\n\n\tValue* IRBuilder::Dereference(Value* val, const std::string& vname)\n\t{\n\t\tif(!val->getType()->isPointerType())\n\t\t\terror(\"irbuilder: cannot dereference non-pointer type '%s'\", val->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::Value_Dereference, true, val->getType()->getPointerElementType(),\n\t\t\t{ val }, Value::Kind::lvalue);\n\n\t\tif(val->getType()->isImmutablePointer())\n\t\t\tinstr->realOutput->makeConst();\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::AddressOf(Value* lval, bool mut, const std::string& vname)\n\t{\n\t\tif(!lval->islvalue())\n\t\t\terror(\"irbuilder: cannot take the address of a non-lvalue\");\n\n\t\t// ok...\n\t\tInstruction* instr = make_instr(OpKind::Value_AddressOf, true,\n\t\t\tmut ? lval->getType()->getMutablePointerTo() : lval->getType()->getPointerTo(), { lval });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\n\tValue* IRBuilder::SetUnionVariantData(Value* unn, size_t id, Value* data, const std::string& vname)\n\t{\n\t\tif(!unn->getType()->isUnionType())\n\t\t\terror(\"irbuilder: '%s' is not a union type\", unn->getType());\n\n\t\tauto ut = unn->getType()->toUnionType();\n\t\tif(data->getType() != ut->getVariant(id)->getInteriorType())\n\t\t\terror(\"irbuilder: cannot store data '%s' into union variant '%s'\", data->getType(), ut->getVariant(id)->getInteriorType());\n\n\t\tInstruction* instr = make_instr(OpKind::Union_SetValue, true, unn->getType(),\n\t\t\t{ unn, ConstantInt::getNative(id), data });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::GetUnionVariantData(Value* unn, size_t id, const std::string& vname)\n\t{\n\t\tif(!unn->getType()->isUnionType())\n\t\t\terror(\"irbuilder: '%s' is not a union type\", unn->getType());\n\n\t\tauto ut = unn->getType()->toUnionType();\n\n\t\tInstruction* instr = make_instr(OpKind::Union_GetValue, true, ut->getVariant(id)->getInteriorType(),\n\t\t\t{ unn, ConstantInt::getNative(id) });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::GetUnionVariantID(Value* unn, const std::string& vname)\n\t{\n\t\tif(!unn->getType()->isUnionType())\n\t\t\terror(\"irbuilder: '%s' is not a union type\", unn->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::Union_GetVariantID, true, Type::getNativeWord(), { unn });\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\tValue* IRBuilder::SetUnionVariantID(Value* unn, size_t id, const std::string& vname)\n\t{\n\t\tif(!unn->getType()->isUnionType())\n\t\t\terror(\"irbuilder: '%s' is not a union type\", unn->getType());\n\n\t\tInstruction* instr = make_instr(OpKind::Union_SetVariantID, true, unn->getType(),\n\t\t\t{ unn, ConstantInt::getNative(id) });\n\n\t\treturn this->addInstruction(instr, vname);\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tvoid IRBuilder::Unreachable()\n\t{\n\t\tthis->addInstruction(make_instr(OpKind::Unreachable, true, Type::getVoid(), { }), \"\");\n\t}\n\n\tIRBlock* IRBuilder::addNewBlockInFunction(const std::string& name, Function* func)\n\t{\n\t\tIRBlock* block = new IRBlock(func);\n\t\tif(func != this->currentFunction)\n\t\t{\n\t\t\t// warn(\"changing current function in irbuilder (from %s to %s)\",\n\t\t\t// \t(this->currentFunction ? this->currentFunction->getName().str() : \"null\"),\n\t\t\t// \tfunc->getName()\n\t\t\t// );\n\n\t\t\tthis->currentFunction = block->parentFunction;\n\t\t}\n\n\t\tthis->currentFunction->blocks.push_back(block);\n\n\t\tsize_t cnt = 0;\n\t\tfor(auto b : this->currentFunction->blocks)\n\t\t\tif(b->getName().str() == name) cnt++;\n\n\t\tblock->setName(strprintf(\"%s%s\", name, cnt > 0 ? strprintf(\".%d\", cnt) : \"\"));\n\t\treturn block;\n\t}\n\n\tIRBlock* IRBuilder::addNewBlockAfter(const std::string& name, IRBlock* block)\n\t{\n\t\tIRBlock* nb = new IRBlock(block->parentFunction);\n\t\tif(nb->parentFunction != this->currentFunction)\n\t\t{\n\t\t\t// warn(\"changing current function in irbuilder (from %s to %s)\",\n\t\t\t// \t(this->currentFunction ? this->currentFunction->getName().str() : \"null\"),\n\t\t\t// \tnb->parentFunction->getName()\n\t\t\t// );\n\n\n\t\t\tthis->currentFunction = nb->parentFunction;\n\t\t}\n\n\t\tfor(size_t i = 0; i < this->currentFunction->blocks.size(); i++)\n\t\t{\n\t\t\tIRBlock* b = this->currentFunction->blocks[i];\n\t\t\tif(b == block)\n\t\t\t{\n\t\t\t\tsize_t cnt = 0;\n\t\t\t\tfor(auto bk : this->currentFunction->blocks)\n\t\t\t\t\tif(bk->getName().str() == name) cnt++;\n\n\t\t\t\tnb->setName(strprintf(\"%s%s\", name, cnt > 0 ? strprintf(\".%d\", cnt) : \"\"));\n\n\t\t\t\tthis->currentFunction->blocks.insert(this->currentFunction->blocks.begin() + i + 1, nb);\n\t\t\t\treturn nb;\n\t\t\t}\n\t\t}\n\n\t\ticeAssert(0 && \"no such block to insert after\");\n\t\tnb->setName(name);\n\t\treturn nb;\n\t}\n}\n\n\n\n\n"
  },
  {
    "path": "source/fir/Instruction.cpp",
    "content": "// Instruction.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ir/block.h\"\n#include \"ir/function.h\"\n#include \"ir/constant.h\"\n#include \"ir/instruction.h\"\n\n#include \"memorypool.h\"\n\nnamespace fir\n{\n\tstatic util::MemoryPool<Value, 1 << 16> value_pool;\n\tInstruction::Instruction(OpKind kind, bool sideeff, Type* out, const std::vector<Value*>& vals)\n\t\t: Instruction(kind, sideeff, out, vals, Value::Kind::prvalue) { }\n\n\tInstruction::Instruction(OpKind kind, bool sideeff, Type* out, const std::vector<Value*>& vals, Value::Kind k) : Value(out)\n\t{\n\t\tthis->opKind = kind;\n\t\tthis->operands = vals;\n\t\tthis->sideEffects = sideeff;\n\t\tthis->realOutput = value_pool.construct(out, k);\n\t}\n\n\tValue* Instruction::getResult()\n\t{\n\t\tif(this->realOutput) return this->realOutput;\n\t\terror(\"calling getActualValue() when not in function! (no real value)\");\n\t}\n\n\tbool Instruction::hasSideEffects()\n\t{\n\t\treturn this->sideEffects;\n\t}\n\n\tvoid Instruction::setValue(Value* v)\n\t{\n\t\tthis->realOutput = v;\n\t}\n\n\tvoid Instruction::clearValue()\n\t{\n\t\tthis->realOutput = 0;\n\t}\n\n\tstd::string Instruction::str()\n\t{\n\t\tstd::string instrname;\n\t\tswitch(this->opKind)\n\t\t{\n\t\t\tcase OpKind::Signed_Add:                        instrname = \"sadd\"; break;\n\t\t\tcase OpKind::Signed_Sub:                        instrname = \"ssub\"; break;\n\t\t\tcase OpKind::Signed_Mul:                        instrname = \"smul\"; break;\n\t\t\tcase OpKind::Signed_Div:                        instrname = \"sdiv\"; break;\n\t\t\tcase OpKind::Signed_Mod:                        instrname = \"srem\"; break;\n\t\t\tcase OpKind::Signed_Neg:                        instrname = \"neg\"; break;\n\t\t\tcase OpKind::Unsigned_Add:                      instrname = \"uadd\"; break;\n\t\t\tcase OpKind::Unsigned_Sub:                      instrname = \"usub\"; break;\n\t\t\tcase OpKind::Unsigned_Mul:                      instrname = \"umul\"; break;\n\t\t\tcase OpKind::Unsigned_Div:                      instrname = \"udiv\"; break;\n\t\t\tcase OpKind::Unsigned_Mod:                      instrname = \"urem\"; break;\n\t\t\tcase OpKind::Floating_Add:                      instrname = \"fadd\"; break;\n\t\t\tcase OpKind::Floating_Sub:                      instrname = \"fsub\"; break;\n\t\t\tcase OpKind::Floating_Mul:                      instrname = \"fmul\"; break;\n\t\t\tcase OpKind::Floating_Div:                      instrname = \"fdiv\"; break;\n\t\t\tcase OpKind::Floating_Mod:                      instrname = \"frem\"; break;\n\t\t\tcase OpKind::Floating_Neg:                      instrname = \"fneg\"; break;\n\t\t\tcase OpKind::Floating_Truncate:                 instrname = \"ftrunc\"; break;\n\t\t\tcase OpKind::Floating_Extend:                   instrname = \"fext\"; break;\n\t\t\tcase OpKind::ICompare_Equal:                    instrname = \"icmp eq\"; break;\n\t\t\tcase OpKind::ICompare_NotEqual:                 instrname = \"icmp ne\"; break;\n\t\t\tcase OpKind::ICompare_Greater:                  instrname = \"icmp gt\"; break;\n\t\t\tcase OpKind::ICompare_Less:                     instrname = \"icmp lt\"; break;\n\t\t\tcase OpKind::ICompare_GreaterEqual:             instrname = \"icmp ge\"; break;\n\t\t\tcase OpKind::ICompare_LessEqual:                instrname = \"icmp le\"; break;\n\t\t\tcase OpKind::FCompare_Equal_ORD:                instrname = \"fcmp ord eq\"; break;\n\t\t\tcase OpKind::FCompare_Equal_UNORD:              instrname = \"fcmp unord eq\"; break;\n\t\t\tcase OpKind::FCompare_NotEqual_ORD:             instrname = \"fcmp ord ne\"; break;\n\t\t\tcase OpKind::FCompare_NotEqual_UNORD:           instrname = \"fcmp unord ne\"; break;\n\t\t\tcase OpKind::FCompare_Greater_ORD:              instrname = \"fcmp ord gt\"; break;\n\t\t\tcase OpKind::FCompare_Greater_UNORD:            instrname = \"fcmp unord gt\"; break;\n\t\t\tcase OpKind::FCompare_Less_ORD:                 instrname = \"fcmp ord lt\"; break;\n\t\t\tcase OpKind::FCompare_Less_UNORD:               instrname = \"fcmp unord lt\"; break;\n\t\t\tcase OpKind::FCompare_GreaterEqual_ORD:         instrname = \"fcmp ord ge\"; break;\n\t\t\tcase OpKind::FCompare_GreaterEqual_UNORD:       instrname = \"fcmp unord ge\"; break;\n\t\t\tcase OpKind::FCompare_LessEqual_ORD:            instrname = \"fcmp ord le\"; break;\n\t\t\tcase OpKind::FCompare_LessEqual_UNORD:          instrname = \"fcmp unord le\"; break;\n\t\t\tcase OpKind::ICompare_Multi:                    instrname = \"icmp multi\"; break;\n\t\t\tcase OpKind::FCompare_Multi:                    instrname = \"fcmp multi\"; break;\n\t\t\tcase OpKind::Bitwise_Not:                       instrname = \"not\"; break;\n\t\t\tcase OpKind::Bitwise_Xor:                       instrname = \"xor\"; break;\n\t\t\tcase OpKind::Bitwise_Arithmetic_Shr:            instrname = \"ashr\"; break;\n\t\t\tcase OpKind::Bitwise_Logical_Shr:               instrname = \"lshr\"; break;\n\t\t\tcase OpKind::Bitwise_Shl:                       instrname = \"shl\"; break;\n\t\t\tcase OpKind::Bitwise_And:                       instrname = \"and\"; break;\n\t\t\tcase OpKind::Bitwise_Or:                        instrname = \"or\"; break;\n\t\t\tcase OpKind::Cast_Bitcast:                      instrname = \"bitcast\"; break;\n\t\t\tcase OpKind::Cast_IntSize:                      instrname = \"intszcast\"; break;\n\t\t\tcase OpKind::Cast_Signedness:                   instrname = \"signedcast\"; break;\n\t\t\tcase OpKind::Cast_FloatToInt:                   instrname = \"fptoint\"; break;\n\t\t\tcase OpKind::Cast_IntToFloat:                   instrname = \"inttofp\"; break;\n\t\t\tcase OpKind::Cast_PointerType:                  instrname = \"ptrcast\"; break;\n\t\t\tcase OpKind::Cast_PointerToInt:                 instrname = \"ptrtoint\"; break;\n\t\t\tcase OpKind::Cast_IntToPointer:                 instrname = \"inttoptr\"; break;\n\t\t\tcase OpKind::Cast_IntSignedness:                instrname = \"signcast\"; break;\n\t\t\tcase OpKind::Integer_ZeroExt:                   instrname = \"izeroext\"; break;\n\t\t\tcase OpKind::Integer_Truncate:                  instrname = \"itrunc\"; break;\n\t\t\tcase OpKind::Value_WritePtr:                    instrname = \"writemem\"; break;\n\t\t\tcase OpKind::Logical_Not:                       instrname = \"logicalNot\"; break;\n\t\t\tcase OpKind::Value_ReadPtr:                     instrname = \"readmem\"; break;\n\t\t\tcase OpKind::Value_StackAlloc:                  instrname = \"stackAlloc\"; break;\n\t\t\tcase OpKind::Value_CallFunction:                instrname = \"call\"; break;\n\t\t\tcase OpKind::Value_CallFunctionPointer:         instrname = \"callfp\"; break;\n\t\t\tcase OpKind::Value_CallVirtualMethod:           instrname = \"callvirtual\"; break;\n\t\t\tcase OpKind::Value_Return:                      instrname = \"ret\"; break;\n\t\t\tcase OpKind::Value_GetPointerToStructMember:    instrname = \"gep\"; break;\n\t\t\tcase OpKind::Value_GetStructMember:             instrname = \"gep\"; break;\n\t\t\tcase OpKind::Value_GetPointer:                  instrname = \"gep\"; break;\n\t\t\tcase OpKind::Value_GetGEP2:                     instrname = \"gep\"; break;\n\t\t\tcase OpKind::Value_InsertValue:                 instrname = \"insertval\"; break;\n\t\t\tcase OpKind::Value_ExtractValue:                instrname = \"extractval\"; break;\n\t\t\tcase OpKind::Value_Select:                      instrname = \"select\"; break;\n\t\t\tcase OpKind::Misc_Sizeof:                       instrname = \"sizeof\"; break;\n\t\t\tcase OpKind::Branch_UnCond:                     instrname = \"jump\"; break;\n\t\t\tcase OpKind::Branch_Cond:                       instrname = \"branch\"; break;\n\n\t\t\tcase OpKind::Value_CreatePHI:                   instrname = \"phi\"; break;\n\n\t\t\tcase OpKind::SAA_GetData:                       instrname = \"get_saa.data\"; break;\n\t\t\tcase OpKind::SAA_SetData:                       instrname = \"set_saa.data\"; break;\n\t\t\tcase OpKind::SAA_GetLength:                     instrname = \"get_saa.len\"; break;\n\t\t\tcase OpKind::SAA_SetLength:                     instrname = \"set_saa.len\"; break;\n\t\t\tcase OpKind::SAA_GetCapacity:                   instrname = \"get_saa.cap\"; break;\n\t\t\tcase OpKind::SAA_SetCapacity:                   instrname = \"set_saa.cap\"; break;\n\t\t\tcase OpKind::SAA_GetRefCountPtr:                instrname = \"get_saa.rc_ptr\"; break;\n\t\t\tcase OpKind::SAA_SetRefCountPtr:                instrname = \"set_saa.rc_ptr\"; break;\n\n\n\t\t\tcase OpKind::ArraySlice_GetData:                instrname = \"get_slice.data\"; break;\n\t\t\tcase OpKind::ArraySlice_SetData:                instrname = \"set_slice.data\"; break;\n\t\t\tcase OpKind::ArraySlice_GetLength:              instrname = \"get_slice.len\"; break;\n\t\t\tcase OpKind::ArraySlice_SetLength:              instrname = \"set_slice.len\"; break;\n\n\t\t\tcase OpKind::Any_GetData:                       instrname = \"get_any.data\"; break;\n\t\t\tcase OpKind::Any_SetData:                       instrname = \"set_any.data\"; break;\n\t\t\tcase OpKind::Any_GetTypeID:                     instrname = \"get_any.typeid\"; break;\n\t\t\tcase OpKind::Any_SetTypeID:                     instrname = \"set_any.typeid\"; break;\n\t\t\tcase OpKind::Any_GetRefCountPtr:                instrname = \"get_any.rc_ptr\"; break;\n\t\t\tcase OpKind::Any_SetRefCountPtr:                instrname = \"set_any.rc_ptr\"; break;\n\n\t\t\tcase OpKind::Range_GetLower:                    instrname = \"get_range.lower\"; break;\n\t\t\tcase OpKind::Range_SetLower:                    instrname = \"set_range.lower\"; break;\n\t\t\tcase OpKind::Range_GetUpper:                    instrname = \"get_range.upper\"; break;\n\t\t\tcase OpKind::Range_SetUpper:                    instrname = \"set_range.upper\"; break;\n\t\t\tcase OpKind::Range_GetStep:                     instrname = \"get_range.step\"; break;\n\t\t\tcase OpKind::Range_SetStep:                     instrname = \"set_range.step\"; break;\n\n\t\t\tcase OpKind::Enum_GetIndex:                     instrname = \"get_enum.index\"; break;\n\t\t\tcase OpKind::Enum_SetIndex:                     instrname = \"set_enum.index\"; break;\n\t\t\tcase OpKind::Enum_GetValue:                     instrname = \"get_enum.value\"; break;\n\t\t\tcase OpKind::Enum_SetValue:                     instrname = \"set_enum.value\"; break;\n\n\n\t\t\tcase OpKind::Union_SetValue:                    instrname = \"set_union.value\"; break;\n\t\t\tcase OpKind::Union_GetValue:                    instrname = \"get_union.value\"; break;\n\t\t\tcase OpKind::Union_GetVariantID:                instrname = \"get_union.id\"; break;\n\t\t\tcase OpKind::Union_SetVariantID:                instrname = \"set_union.id\"; break;\n\n\t\t\tcase OpKind::RawUnion_GEP:                      instrname = \"raw_union_gep\"; break;\n\n\t\t\tcase OpKind::Value_AddressOf:                   instrname = \"addrof\"; break;\n\t\t\tcase OpKind::Value_Store:                       instrname = \"store\"; break;\n\t\t\tcase OpKind::Value_Dereference:                 instrname = \"dereference\"; break;\n\t\t\tcase OpKind::Value_CreateLVal:                  instrname = \"make_lval\"; break;\n\n\t\t\tcase OpKind::Unreachable:                       instrname = \"<unreachable>\"; break;\n\t\t\tcase OpKind::Invalid:                           instrname = \"<unknown>\"; break;\n\t\t}\n\n\n\t\tstd::string ops;\n\t\tbool endswithfn = false;\n\n\t\tif(this->opKind == OpKind::Value_CreatePHI)\n\t\t{\n\t\t\tauto phi = dcast(PHINode, this->realOutput);\n\t\t\ticeAssert(phi);\n\t\t\tstd::string nodes;\n\n\t\t\tfor(auto i : phi->getValues())\n\t\t\t\tnodes += strprintf(\"[$%s -> %%%d], \", i.first->getName().name, i.second->id);\n\n\t\t\tops += nodes;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor(auto op : this->operands)\n\t\t\t{\n\t\t\t\tbool didfn = false;\n\t\t\t\tif(op->getType()->isFunctionType())\n\t\t\t\t{\n\t\t\t\t\tops += \"@\" + op->getName().str();\n\t\t\t\t\tif(this->opKind == OpKind::Value_CallFunction)\n\t\t\t\t\t{\n\t\t\t\t\t\tops += \", (\";\n\t\t\t\t\t\tdidfn = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(ConstantInt* ci = dcast(ConstantInt, op))\n\t\t\t\t{\n\t\t\t\t\tops += std::to_string(ci->getSignedValue());\n\t\t\t\t}\n\t\t\t\telse if(ConstantFP* cf = dcast(ConstantFP, op))\n\t\t\t\t{\n\t\t\t\t\tops += std::to_string(cf->getValue());\n\t\t\t\t}\n\t\t\t\telse if(ConstantBool* cb = dcast(ConstantBool, op))\n\t\t\t\t{\n\t\t\t\t\tops += cb->getValue() ? \"true\" : \"false\";\n\t\t\t\t}\n\t\t\t\telse if(ConstantArraySlice* cas = dcast(ConstantArraySlice, op))\n\t\t\t\t{\n\t\t\t\t\tops += \"(const slice %\" + std::to_string(op->id) + \": ptr: %\" + std::to_string(cas->getData()->id) + \", len: %\"\n\t\t\t\t\t\t+ std::to_string(cas->getLength()->id) + \") :: \" + op->getType()->str();\n\t\t\t\t}\n\t\t\t\telse if(dcast(ConstantValue, op))\n\t\t\t\t{\n\t\t\t\t\tops += \"(const %\" + std::to_string(op->id) + \" :: \" + op->getType()->str() + \")\";\n\t\t\t\t}\n\t\t\t\telse if(IRBlock* ib = dcast(IRBlock, op))\n\t\t\t\t{\n\t\t\t\t\tops += strprintf(\"$%d/%s\", ib->id, ib->getName().str());\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tauto name = op->getName().str();\n\t\t\t\t\tif(name.empty()) name += \" \";\n\n\t\t\t\t\tops += strprintf(\"%s(%s%%%d) :: %s\", name, op->islvalue() ? \"*\" : \"\", op->id, op->getType());\n\t\t\t\t}\n\n\t\t\t\tif(!didfn)\n\t\t\t\t\tops += \", \";\n\n\t\t\t\tendswithfn = didfn;\n\t\t\t}\n\t\t}\n\n\n\n\t\tif(ops.length() > 0 && !endswithfn)\n\t\t\tops = ops.substr(0, ops.length() - 2);\n\n\n\t\tif(this->opKind == OpKind::Value_CallFunction)\n\t\t\tops += \")\";\n\n\n\t\tstd::string ret = \"\";\n\t\tif(this->realOutput->getType()->isVoidType())\n\t\t{\n\t\t\tret = instrname + \" \" + ops;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto name = this->realOutput->getName().str();\n\t\t\tret = name + (name.empty() ? \"\" : \" \") + \"(%\" + std::to_string(this->realOutput->id) + \") :: \" + this->realOutput->getType()->str() + \" = \" + instrname + \" \" + ops;\n\t\t}\n\n\t\t// return strprintf(\"!%d \", this->id) + ret;\n\t\treturn ret;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/Module.cpp",
    "content": "// Module.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"string_consts.h\"\n\n#include \"ir/module.h\"\n#include \"ir/irbuilder.h\"\n\nnamespace fir\n{\n\tModule::Module(const std::string& nm)\n\t{\n\t\tthis->moduleName = nm;\n\t}\n\n\n\tvoid Module::finaliseGlobalConstructors()\n\t{\n\t\tauto builder = IRBuilder(this);\n\t\tauto entryfunc = this->entryFunction;\n\n\t\tif(!entryfunc)\n\t\t{\n\t\t\t// keep trying various things.\n\t\t\tstd::vector<std::string> trymains = { \"main\", \"_FF\" + this->getModuleName() + \"4main_FAv\" };\n\t\t\tfor(const auto& m : trymains)\n\t\t\t{\n\t\t\t\tentryfunc = this->getFunction(Name::of(m));\n\t\t\t\tif(entryfunc) break;\n\t\t\t}\n\n\t\t\tif(entryfunc)\n\t\t\t\tthis->entryFunction = entryfunc;\n\n\t\t\telse\n\t\t\t\terror(\"fir: no entry point marked with '@entry', and no 'main' function; cannot compile program\");\n\t\t}\n\n\t\t// it doesn't actually matter what the entry function is named -- we just need to insert some instructions at the beginning.\n\t\ticeAssert(entryfunc);\n\t\t{\n\t\t\ticeAssert(entryfunc->getBlockList().size() > 0);\n\n\t\t\tauto oldentry = entryfunc->getBlockList()[0];\n\t\t\tauto newentry = new IRBlock(entryfunc);\n\t\t\tnewentry->setName(\"entryblock_entry\");\n\n\t\t\tauto& blklist = entryfunc->getBlockList();\n\t\t\tblklist.insert(blklist.begin(), newentry);\n\n\t\t\tbuilder.setCurrentBlock(newentry);\n\n\t\t\tauto gif = this->getFunction(Name::obfuscate(strs::names::GLOBAL_INIT_FUNCTION));\n\t\t\tif(!gif) error(\"fir: failed to find global init function\");\n\n\t\t\tbuilder.Call(gif);\n\t\t\tbuilder.UnCondBranch(oldentry);\n\t\t}\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\tGlobalVariable* Module::createGlobalVariable(const Name& ident, Type* type, ConstantValue* initVal, bool isImmut, LinkageType linkage)\n\t{\n\t\tGlobalVariable* gv = new GlobalVariable(ident, this, type, isImmut, linkage, initVal);\n\t\tif(this->globals.find(ident) != this->globals.end())\n\t\t\terror(\"fir: already have a global with name '%s'\", ident.str());\n\n\t\tthis->globals[ident] = gv;\n\t\treturn gv;\n\t}\n\n\tGlobalVariable* Module::createGlobalVariable(const Name& id, Type* type, bool isImmut, LinkageType linkage)\n\t{\n\t\treturn this->createGlobalVariable(id, type, 0, isImmut, linkage);\n\t}\n\n\tGlobalVariable* Module::declareGlobalVariable(const Name& id, Type* type, bool isImmut)\n\t{\n\t\treturn this->createGlobalVariable(id, type, 0, isImmut, LinkageType::External);\n\t}\n\n\tGlobalVariable* Module::tryGetGlobalVariable(const Name& id)\n\t{\n\t\tif(this->globals.find(id) == this->globals.end())\n\t\t\treturn 0;\n\n\t\treturn this->globals[id];\n\t}\n\n\tGlobalVariable* Module::getGlobalVariable(const Name& id)\n\t{\n\t\tif(this->globals.find(id) == this->globals.end())\n\t\t\terror(\"fir: no such global with name '%s'\", id.str());\n\n\t\treturn this->globals[id];\n\t}\n\n\n\n\tGlobalVariable* Module::getOrCreateVirtualTableForClass(ClassType* cls)\n\t{\n\t\tif(this->vtables.find(cls) == this->vtables.end())\n\t\t{\n\t\t\tauto fmethods = std::vector<fir::Function*>(cls->virtualMethodCount);\n\t\t\tauto methods = std::vector<fir::ConstantValue*>(cls->virtualMethodCount);\n\n\t\t\tfor(auto meth : cls->reverseVirtualMethodMap)\n\t\t\t{\n\t\t\t\tmethods[meth.first] = ConstantBitcast::get(meth.second, FunctionType::get({ }, Type::getVoid()));\n\t\t\t\tfmethods[meth.first] = meth.second;\n\t\t\t}\n\n\t\t\t//! ACHTUNG !\n\t\t\t// TODO: should we make the vtable immutable?\n\n\t\t\tauto table = ConstantArray::get(ArrayType::get(FunctionType::get({ }, Type::getVoid()), cls->virtualMethodCount), methods);\n\t\t\tauto vtab = this->createGlobalVariable(Name::obfuscate(\"vtable\", cls->getTypeName().mangled()),\n\t\t\t\ttable->getType(), table, true, LinkageType::External);\n\n\t\t\tthis->vtables[cls] = { fmethods, vtab };\n\t\t}\n\n\t\treturn this->vtables[cls].second;\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tFunction* Module::getEntryFunction()\n\t{\n\t\treturn this->entryFunction;\n\t}\n\n\tvoid Module::setEntryFunction(Function* fn)\n\t{\n\t\tthis->entryFunction = fn;\n\t}\n\n\n\n\n\tType* Module::getNamedType(const Name& id)\n\t{\n\t\tif(this->namedTypes.find(id) == this->namedTypes.end())\n\t\t\terror(\"fir: no such type with name '%s'\", id.str());\n\n\t\treturn this->namedTypes[id];\n\t}\n\n\tvoid Module::addNamedType(const Name& id, Type* type)\n\t{\n\t\tif(this->namedTypes.find(id) != this->namedTypes.end())\n\t\t\terror(\"fir: type '%s' exists already\", id.str());\n\n\t\tthis->namedTypes[id] = type;\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\tvoid Module::addFunction(Function* func)\n\t{\n\t\tif(this->functions.find(func->getName()) != this->functions.end())\n\t\t\terror(\"fir: function '%s' exists already\", func->getName().str());\n\n\t\tthis->functions[func->getName()] = func;\n\t}\n\n\tvoid Module::removeFunction(Function* func)\n\t{\n\t\tif(this->functions.find(func->getName()) == this->functions.end())\n\t\t\terror(\"fir: function '%s' does not exist, cannot remove\", func->getName().str());\n\n\t\tthis->functions.erase(func->getName());\n\t}\n\n\n\tFunction* Module::declareFunction(const Name& id, FunctionType* ftype)\n\t{\n\t\treturn this->getOrCreateFunction(id, ftype, fir::LinkageType::External);\n\t}\n\n\tFunction* Module::getFunction(const Name& id)\n\t{\n\t\tif(this->functions.find(id) == this->functions.end())\n\t\t\treturn 0;\n\n\t\treturn this->functions[id];\n\t}\n\n\tstd::vector<Function*> Module::getFunctionsWithName(const Name& id)\n\t{\n\t\t// todo: *very* inefficient.\n\n\t\tstd::vector<Function*> ret;\n\t\tfor(const auto& [ ident, fn ] : this->functions)\n\t\t{\n\t\t\tif(ident == id)\n\t\t\t\tret.push_back(fn);\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\tFunction* Module::getOrCreateFunction(const Name& id, FunctionType* ftype, LinkageType linkage)\n\t{\n\t\tif(this->functions.find(id) != this->functions.end())\n\t\t{\n\t\t\tif(!this->functions[id]->getType()->isTypeEqual(ftype))\n\t\t\t{\n\t\t\t\terror(\"fir: function '%s' redeclared with different type (have '%s', new '%s')\", id.str(),\n\t\t\t\t\tthis->functions[id]->getType(), ftype);\n\t\t\t}\n\n\t\t\treturn this->functions[id];\n\t\t}\n\n\t\tFunction* f = new Function(id, ftype, this, linkage);\n\t\tthis->functions[id] = f;\n\n\t\treturn f;\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tGlobalVariable* Module::createGlobalString(const std::string& str)\n\t{\n\t\tstatic int stringId = 0;\n\n\t\tif(this->globalStrings.find(str) != this->globalStrings.end())\n\t\t\treturn this->globalStrings[str];\n\n\t\tGlobalVariable* gs = new GlobalVariable(Name::obfuscate(\"static_string\", std::to_string(stringId++)), this,\n\t\t\tType::getInt8Ptr(), true, LinkageType::Internal, 0);\n\n\t\tgs->setKind(Value::Kind::prvalue);\n\t\treturn (this->globalStrings[str] = gs);\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tstd::string Module::print()\n\t{\n\t\tstd::string ret;\n\t\tret = \"# MODULE = \" + this->getModuleName() + \"\\n\";\n\n\t\tfor(const auto& [ str, gv ] : this->globalStrings)\n\t\t{\n\t\t\tret += \"global string (%\" + std::to_string(gv->id);\n\n\t\t\tstd::string copy;\n\t\t\tfor(auto c : str)\n\t\t\t{\n\t\t\t\tif(c == '\\r') copy += \"\\\\r\";\n\t\t\t\telse if(c == '\\n') copy += \"\\\\n\";\n\t\t\t\telse if(c == '\\t') copy += \"\\\\t\";\n\t\t\t\telse copy += c;\n\t\t\t}\n\n\t\t\tret += \") [\" + std::to_string(str.length()) + \"] = \\\"\" + copy + \"\\\"\\n\";\n\t\t}\n\n\t\tfor(auto global : this->globals)\n\t\t{\n\t\t\tret += \"global \" + global.first.str() + \" (%\" + std::to_string(global.second->id) + \") :: \"\n\t\t\t\t+ global.second->getType()->str() + \"\\n\";\n\t\t}\n\n\t\tfor(auto type : this->namedTypes)\n\t\t{\n\t\t\t// should just automatically create it.\n\t\t\tstd::string tl;\n\t\t\tif(type.second->isStructType()) tl = fir::Type::typeListToString(type.second->toStructType()->getElements());\n\t\t\telse if(type.second->isClassType()) tl = fir::Type::typeListToString(type.second->toClassType()->getElements());\n\t\t\telse if(type.second->isTupleType()) tl = fir::Type::typeListToString(type.second->toTupleType()->getElements());\n\n\n\t\t\tret += \"declare type :: \" + type.second->str() + \" { \" + tl + \" }\\n\";\n\t\t}\n\n\t\tfor(const auto& [ id, fp ] : this->functions)\n\t\t{\n\t\t\tFunction* ffn = fp;\n\n\t\t\tstd::string decl;\n\n\t\t\t// note: .str() already gives us the parameters\n\t\t\tdecl += (ffn->isAlwaysInlined() ? \"inline func: \" : \"func: \") + ffn->getName().str();\n\n\t\t\tif(ffn->blocks.size() == 0)\n\t\t\t{\n\t\t\t\tdecl += \" -> \";\n\t\t\t\tdecl += ffn->getReturnType()->str();\n\t\t\t\tdecl += \"\\n\";\n\n\t\t\t\tret += \"declare \" + decl;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tret += decl;\n\n\t\t\tret += \" -> \";\n\t\t\tret += ffn->getReturnType()->str();\n\n\t\t\tret += \"    # mangled = \" + ffn->getName().mangled();\n\n\t\t\tret += \"\\n{\";\n\n\t\t\t// do the args\n\t\t\tfor(auto arg : ffn->getArguments())\n\t\t\t{\n\t\t\t\tret += strprintf(\"\\n    arg %s (%%%d) :: %s\", arg->getName().name, arg->id, arg->getType()->str());\n\t\t\t}\n\n\n\t\t\tfor(auto block : ffn->getBlockList())\n\t\t\t{\n\t\t\t\tret += \"\\n    (%\" + std::to_string(block->id) + \") \" + block->getName().str() + \":\\n\";\n\n\t\t\t\tfor(auto inst : block->instructions)\n\t\t\t\t\tret += \"        \" + inst->str() + \"\\n\";\n\t\t\t}\n\t\t\tret += (\"}\\n\\n\");\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\n\n\n\n\tFunction* Module::getIntrinsicFunction(const std::string& id)\n\t{\n\t\tauto name = Name::of(\"\");\n\t\tFunctionType* ft = 0;\n\t\tif(id == \"memcpy\")\n\t\t{\n\t\t\tname = Name::of(\"memcpy\");\n\t\t\tft = FunctionType::get({ fir::Type::getMutInt8Ptr(), fir::Type::getInt8Ptr(),\n\t\t\t\tfir::Type::getNativeWord(), fir::Type::getBool() },\n\t\t\t\tfir::Type::getVoid());\n\t\t}\n\t\telse if(id == \"memmove\")\n\t\t{\n\t\t\tname = Name::of(\"memmove\");\n\t\t\tft = FunctionType::get({ fir::Type::getMutInt8Ptr(), fir::Type::getMutInt8Ptr(),\n\t\t\t\tfir::Type::getNativeWord(), fir::Type::getBool() },\n\t\t\t\tfir::Type::getVoid());\n\t\t}\n\t\telse if(id == \"memset\")\n\t\t{\n\t\t\tname = Name::of(\"memset\");\n\t\t\tft = FunctionType::get({ fir::Type::getMutInt8Ptr(), fir::Type::getInt8(),\n\t\t\t\tfir::Type::getNativeWord(), fir::Type::getBool() },\n\t\t\t\tfir::Type::getVoid());\n\t\t}\n\t\telse if(id == \"memcmp\")\n\t\t{\n\t\t\t// note: memcmp isn't an actual llvm intrinsic, but we support it anyway\n\t\t\t// at llvm-translate-time, we make a function.\n\n\t\t\tname = Name::of(\"memcmp\");\n\t\t\tft = FunctionType::get({ fir::Type::getInt8Ptr(), fir::Type::getInt8Ptr(),\n\t\t\t\tfir::Type::getNativeWord(), fir::Type::getBool() },\n\t\t\t\tfir::Type::getInt32());\n\t\t}\n\t\telse if(id == \"roundup_pow2\")\n\t\t{\n\t\t\t// rounds up to the nearest power of 2\n\t\t\t// 127 -> 128\n\t\t\t// 1 -> 1\n\t\t\t// 40 -> 64\n\n\t\t\tname = Name::of(\"roundup_pow2\");\n\t\t\tft = FunctionType::get({ fir::Type::getNativeWord() }, fir::Type::getNativeWord());\n\t\t}\n\n\t\tif(this->intrinsicFunctions.find(name) != this->intrinsicFunctions.end())\n\t\t\treturn this->intrinsicFunctions[name];\n\n\t\tthis->intrinsicFunctions[name] = new Function(name, ft, this, LinkageType::Internal);\n\t\treturn this->intrinsicFunctions[name];\n\t}\n\n\n\n\n\n\n\n\n\tstd::vector<GlobalVariable*> Module::getGlobalVariables()\n\t{\n\t\tstd::vector<GlobalVariable*> ret;\n\t\tret.reserve(this->globals.size());\n\n\t\tfor(const auto& g : this->globals)\n\t\t\tret.push_back(g.second);\n\n\t\treturn ret;\n\t}\n\n\tstd::vector<Type*> Module::getNamedTypes()\n\t{\n\t\tstd::vector<Type*> ret;\n\t\tret.reserve(this->namedTypes.size());\n\n\t\tfor(const auto& g : this->namedTypes)\n\t\t\tret.push_back(g.second);\n\n\t\treturn ret;\n\t}\n\n\tstd::vector<Function*> Module::getAllFunctions()\n\t{\n\t\tstd::vector<Function*> ret;\n\t\tret.reserve(this->functions.size());\n\n\t\tfor(const auto& g : this->functions)\n\t\t\tret.push_back(g.second);\n\n\t\treturn ret;\n\t}\n\n\tstd::string Module::getModuleName()\n\t{\n\t\treturn this->moduleName;\n\t}\n\n\tvoid Module::setModuleName(const std::string& name)\n\t{\n\t\tthis->moduleName = name;\n\t}\n}\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/Name.cpp",
    "content": "// Name.cpp\n// Copyright (c) 2020, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ir/type.h\"\n\nnamespace fir\n{\n\tbool Name::operator== (const Name& other) const\n\t{\n\t\treturn this->name == other.name\n\t\t\t&& this->scope == other.scope\n\t\t\t&& this->params == other.params\n\t\t\t&& this->retty == other.retty\n\t\t\t&& this->kind == other.kind;\n\t}\n\n\tbool Name::operator!= (const Name& other) const\n\t{\n\t\treturn !(*this == other);\n\t}\n\n\tName Name::of(std::string name)\n\t{\n\t\treturn Name(NameKind::Name, name, { }, { }, nullptr);\n\t}\n\n\tName Name::of(std::string name, std::vector<std::string> scope)\n\t{\n\t\treturn Name(NameKind::Name, name, scope, { }, nullptr);\n\t}\n\n\tName Name::type(std::string name)\n\t{\n\t\treturn Name(NameKind::Type, name, { }, { }, nullptr);\n\t}\n\n\tName Name::type(std::string name, std::vector<std::string> scope)\n\t{\n\t\treturn Name(NameKind::Type, name, scope, { }, nullptr);\n\t}\n\n\tName Name::function(std::string name, std::vector<fir::Type*> params, fir::Type* retty)\n\t{\n\t\treturn Name(NameKind::Function, name, { }, params, retty);\n\t}\n\n\tName Name::function(std::string name, std::vector<std::string> scope, std::vector<fir::Type*> params, fir::Type* retty)\n\t{\n\t\treturn Name(NameKind::Function, name, scope, params, retty);\n\t}\n\n\n\n\n\n\tstatic std::string mangleScopeOnly(const fir::Name& id)\n\t{\n\t\tbool first = true;\n\t\tstd::string ret;\n\t\tfor(const auto& s : id.scope)\n\t\t{\n\t\t\tret += (!first ? std::to_string(s.length()) : \"\") + s;\n\t\t\tfirst = false;\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\tstatic inline std::string lentypestr(const std::string& s)\n\t{\n\t\treturn std::to_string(s.length()) + s;\n\t}\n\n\tstatic std::string mangleScopeName(const fir::Name& id)\n\t{\n\t\treturn mangleScopeOnly(id) + lentypestr(id.name);\n\t}\n\n\tstatic std::string mangleType(fir::Type* t)\n\t{\n\t\tif(t->isPrimitiveType())\n\t\t{\n\t\t\treturn lentypestr(t->encodedStr());\n\t\t}\n\t\tif(t->isBoolType())\n\t\t{\n\t\t\treturn lentypestr(t->encodedStr());\n\t\t}\n\t\telse if(t->isArrayType())\n\t\t{\n\t\t\treturn \"FA\" + lentypestr(mangleType(t->getArrayElementType())) + std::to_string(t->toArrayType()->getArraySize());\n\t\t}\n\t\telse if(t->isDynamicArrayType())\n\t\t{\n\t\t\treturn \"DA\" + lentypestr(mangleType(t->getArrayElementType()));\n\t\t}\n\t\telse if(t->isArraySliceType())\n\t\t{\n\t\t\treturn \"SL\" + lentypestr(mangleType(t->getArrayElementType()));\n\t\t}\n\t\telse if(t->isVoidType())\n\t\t{\n\t\t\treturn \"v\";\n\t\t}\n\t\telse if(t->isFunctionType())\n\t\t{\n\t\t\tstd::string ret = \"FN\" + std::to_string(t->toFunctionType()->getArgumentCount()) + \"FA\";\n\t\t\tfor(auto a : t->toFunctionType()->getArgumentTypes())\n\t\t\t{\n\t\t\t\tret += lentypestr(mangleType(a));\n\t\t\t}\n\n\t\t\tif(t->toFunctionType()->getArgumentTypes().empty())\n\t\t\t\tret += \"v\";\n\n\t\t\treturn ret;\n\t\t}\n\t\telse if(t->isStructType())\n\t\t{\n\t\t\treturn lentypestr(mangleScopeName(t->toStructType()->getTypeName()));\n\t\t}\n\t\telse if(t->isClassType())\n\t\t{\n\t\t\treturn lentypestr(mangleScopeName(t->toClassType()->getTypeName()));\n\t\t}\n\t\telse if(t->isTupleType())\n\t\t{\n\t\t\tstd::string ret = \"ST\" + std::to_string(t->toTupleType()->getElementCount()) + \"SM\";\n\t\t\tfor(auto m : t->toTupleType()->getElements())\n\t\t\t\tret += lentypestr(mangleType(m));\n\n\t\t\treturn ret;\n\t\t}\n\t\telse if(t->isPointerType())\n\t\t{\n\t\t\treturn \"PT\" + lentypestr(mangleType(t->getPointerElementType()));\n\t\t}\n\t\telse if(t->isStringType())\n\t\t{\n\t\t\treturn \"SR\";\n\t\t}\n\t\telse if(t->isCharType())\n\t\t{\n\t\t\treturn \"CH\";\n\t\t}\n\t\telse if(t->isEnumType())\n\t\t{\n\t\t\treturn \"EN\" + lentypestr(mangleType(t->toEnumType()->getCaseType())) + lentypestr(mangleScopeName(t->toEnumType()->getTypeName()));\n\t\t}\n\t\telse if(t->isAnyType())\n\t\t{\n\t\t\treturn \"AY\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_error_and_exit(\"unsupported ir type??? ('%s')\\n\", t);\n\t\t}\n\t}\n\n\tstatic std::string mangleName(const Name& id, bool includeScope)\n\t{\n\t\tif(id.kind == NameKind::Name || id.kind == NameKind::Type)\n\t\t{\n\t\t\tstd::string scp;\n\t\t\tif(includeScope)\n\t\t\t\tscp += mangleScopeOnly(id);\n\n\t\t\tif(includeScope && id.scope.size() > 0)\n\t\t\t\tscp += std::to_string(id.name.length());\n\n\t\t\treturn scp + id.name;\n\t\t}\n\t\telse if(!includeScope)\n\t\t{\n\t\t\tif(id.kind == NameKind::Function)\n\t\t\t{\n\t\t\t\tstd::string ret = id.name + \"(\";\n\n\t\t\t\tif(id.params.empty())\n\t\t\t\t{\n\t\t\t\t\tret += \")\";\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfor(auto t : id.params)\n\t\t\t\t\t\tret += t->str() + \",\";\n\n\t\t\t\t\tret = ret.substr(0, ret.length() - 1);\n\t\t\t\t\tret += \")\";\n\t\t\t\t}\n\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_error_and_exit(\"invalid\\n\");\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::string ret = \"_F\";\n\n\t\t\tif(id.kind == NameKind::Function)     ret += \"F\";\n\t\t\telse if(id.kind == NameKind::Type)    ret += \"T\";\n\t\t\telse                                ret += \"U\";\n\n\t\t\tif(includeScope)\n\t\t\t\tret += mangleScopeOnly(id);\n\n\t\t\tret += lentypestr(id.name);\n\n\t\t\tif(id.kind == NameKind::Function)\n\t\t\t{\n\t\t\t\tret += \"_FA\";\n\t\t\t\tfor(auto t : id.params)\n\t\t\t\t\tret += \"_\" + mangleType(t);\n\n\t\t\t\tif(id.params.empty())\n\t\t\t\t\tret += \"v\";\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\t}\n\n\tstd::string Name::str() const\n\t{\n\t\tstd::string ret = zfu::join(this->scope, \".\");\n\t\tret += this->name;\n\n\t\tif(this->kind == NameKind::Function)\n\t\t{\n\t\t\tret += \"(\";\n\t\t\tfor(const auto& p : this->params)\n\t\t\t\tret += p->str() + \", \";\n\n\t\t\tif(this->params.size() > 0)\n\t\t\t\tret.pop_back(), ret.pop_back();\n\n\t\t\tret += \")\";\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\tstd::string Name::mangled() const\n\t{\n\t\treturn mangleName(*this, true);\n\t}\n\n\tstd::string Name::mangledWithoutScope() const\n\t{\n\t\treturn mangleName(*this, false);\n\t}\n\n\tstd::string obfuscateName(const std::string& name)\n\t{\n\t\treturn zpr::sprint(\"__#%s\", name);\n\t}\n\tstd::string obfuscateName(const std::string& name, size_t id)\n\t{\n\t\treturn zpr::sprint(\"__#%s_%d\", name, id);\n\t}\n\tstd::string obfuscateName(const std::string& name, const std::string& extra)\n\t{\n\t\treturn zpr::sprint(\"__#%s_%s\", name, extra);\n\t}\n\n\tName Name::obfuscate(const std::string& name, NameKind kind)\n\t{\n\t\treturn Name(kind, obfuscateName(name), { }, { }, nullptr);\n\t}\n\tName Name::obfuscate(const std::string& name, size_t id, NameKind kind)\n\t{\n\t\treturn Name(kind, obfuscateName(name, id), { }, { }, nullptr);\n\t}\n\tName Name::obfuscate(const std::string& name, const std::string& extra, NameKind kind)\n\t{\n\t\treturn Name(kind, obfuscateName(name, extra), { }, { }, nullptr);\n\t}\n}\n\nnamespace zpr\n{\n\tstd::string print_formatter<fir::Name>::print(const fir::Name& x, const format_args& args)\n\t{\n\t\treturn x.str();\n\t}\n}\n"
  },
  {
    "path": "source/fir/Types/ArraySliceType.cpp",
    "content": "// ArraySliceType.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ir/type.h\"\n#include \"errors.h\"\n\nnamespace fir\n{\n\tArraySliceType::ArraySliceType(Type* elmType, bool mut) : Type(TypeKind::ArraySlice)\n\t{\n\t\tthis->isSliceMutable = mut;\n\t\tthis->arrayElementType = elmType;\n\n\t\tthis->isVariadic = false;\n\t}\n\n\tType* ArraySliceType::getElementType()\n\t{\n\t\treturn this->arrayElementType;\n\t}\n\n\tbool ArraySliceType::isMutable()\n\t{\n\t\treturn this->isSliceMutable;\n\t}\n\n\tType* ArraySliceType::getDataPointerType()\n\t{\n\t\tif(this->isSliceMutable)    return this->arrayElementType->getMutablePointerTo();\n\t\telse                        return this->arrayElementType->getPointerTo();\n\t}\n\n\tstd::string ArraySliceType::str()\n\t{\n\t\tif(this->isCharSliceType())\n\t\t\treturn (this->isSliceMutable ? \"mut str\" : \"str\");\n\n\t\telse\n\t\t\treturn strprintf(\"[%s%s:%s]\", this->isSliceMutable ? \"mut \" : \"\", this->arrayElementType->str(), this->isVariadic ? \" ...\" : \"\");\n\t}\n\n\tstd::string ArraySliceType::encodedStr()\n\t{\n\t\tif(this->isCharSliceType())\n\t\t\treturn (this->isSliceMutable ? \"mut str\" : \"str\");\n\n\t\telse\n\t\t\treturn strprintf(\"[%s%s:%s]\", this->isSliceMutable ? \"mut \" : \"\", this->arrayElementType->encodedStr(), this->isVariadic ? \" ...\" : \"\");\n\t}\n\n\tbool ArraySliceType::isTypeEqual(Type* other)\n\t{\n\t\tif(other->kind != TypeKind::ArraySlice)\n\t\t\treturn false;\n\n\t\tauto af = other->toArraySliceType();\n\t\treturn this->arrayElementType->isTypeEqual(af->arrayElementType) && (this->isSliceMutable == af->isSliceMutable)\n\t\t\t&& (this->isVariadic == af->isVariadic);\n\t}\n\n\tbool ArraySliceType::isVariadicType()\n\t{\n\t\treturn this->isVariadic;\n\t}\n\n\tArraySliceType* ArraySliceType::get(Type* elementType, bool mut)\n\t{\n\t\treturn TypeCache::get().getOrAddCachedType(new ArraySliceType(elementType, mut));\n\t}\n\n\tArraySliceType* ArraySliceType::getMutable(Type* elementType)\n\t{\n\t\treturn get(elementType, true);\n\t}\n\n\tArraySliceType* ArraySliceType::getImmutable(Type* elementType)\n\t{\n\t\treturn get(elementType, false);\n\t}\n\n\tArraySliceType* ArraySliceType::getVariadic(Type* elementType)\n\t{\n\t\tauto a = new ArraySliceType(elementType, false);\n\t\ta->isVariadic = true;\n\n\t\treturn TypeCache::get().getOrAddCachedType(a);\n\t}\n\n\n\tfir::Type* ArraySliceType::substitutePlaceholders(const util::hash_map<fir::Type*, fir::Type*>& subst)\n\t{\n\t\treturn ArraySliceType::get(this->arrayElementType->substitutePlaceholders(subst), this->isSliceMutable);\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/Types/ArrayType.cpp",
    "content": "// Type.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ir/type.h\"\n\nnamespace fir\n{\n\tArrayType::ArrayType(Type* elm, size_t num) : Type(TypeKind::Array)\n\t{\n\t\tthis->arrayElementType = elm;\n\t\tthis->arraySize = num;\n\t}\n\n\tArrayType* ArrayType::get(Type* elementType, size_t num)\n\t{\n\t\treturn TypeCache::get().getOrAddCachedType(new ArrayType(elementType, num));\n\t}\n\n\tstd::string ArrayType::str()\n\t{\n\t\treturn strprintf(\"[%s: %d]\", this->arrayElementType->str(), this->getArraySize());\n\t}\n\n\tstd::string ArrayType::encodedStr()\n\t{\n\t\treturn strprintf(\"[%s: %d]\", this->arrayElementType->encodedStr(), this->getArraySize());\n\t}\n\n\n\n\tbool ArrayType::isTypeEqual(Type* other)\n\t{\n\t\tif(other->kind != TypeKind::Array)\n\t\t\treturn false;\n\n\t\tauto af = other->toArrayType();\n\t\treturn this->arrayElementType->isTypeEqual(af->arrayElementType) && (this->arraySize == af->arraySize);\n\t}\n\n\n\n\n\n\n\t// array stuff\n\tType* ArrayType::getElementType()\n\t{\n\t\treturn this->arrayElementType;\n\t}\n\n\tsize_t ArrayType::getArraySize()\n\t{\n\t\treturn this->arraySize;\n\t}\n\n\n\tfir::Type* ArrayType::substitutePlaceholders(const util::hash_map<fir::Type*, fir::Type*>& subst)\n\t{\n\t\treturn ArrayType::get(this->arrayElementType->substitutePlaceholders(subst), this->arraySize);\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/Types/ClassType.cpp",
    "content": "// ClassType.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"errors.h\"\n#include \"ir/type.h\"\n#include \"ir/function.h\"\n\nnamespace fir\n{\n\t// structs\n\tClassType::ClassType(const Name& name, const std::vector<std::pair<std::string, Type*>>& mems, const std::vector<Function*>& methods,\n\t\tconst std::vector<Function*>& inits) : Type(TypeKind::Class), className(name)\n\t{\n\t\tthis->setMembers(mems);\n\t\tthis->setMethods(methods);\n\t\tthis->setInitialiserFunctions(inits);\n\t}\n\n\tstatic util::hash_map<Name, ClassType*> typeCache;\n\tClassType* ClassType::create(const Name& name, const std::vector<std::pair<std::string, Type*>>& members,\n\t\tconst std::vector<Function*>& methods, const std::vector<Function*>& inits)\n\t{\n\t\tif(auto it = typeCache.find(name); it != typeCache.end())\n\t\t\terror(\"class with name '%s' already exists\", name.str());\n\n\t\telse\n\t\t\treturn (typeCache[name] = new ClassType(name, members, methods, inits));\n\t}\n\n\tClassType* ClassType::createWithoutBody(const Name& name)\n\t{\n\t\treturn ClassType::create(name, { }, { }, { });\n\t}\n\n\n\n\n\n\n\t// various\n\tstd::string ClassType::str()\n\t{\n\t\treturn \"class(\" + this->className.name + \")\";\n\t}\n\n\tstd::string ClassType::encodedStr()\n\t{\n\t\treturn this->className.str();\n\t}\n\n\n\tbool ClassType::isTypeEqual(Type* other)\n\t{\n\t\tif(other->kind != TypeKind::Class)\n\t\t\treturn false;\n\n\t\treturn this->className == other->toClassType()->className;\n\t}\n\n\n\n\t// struct stuff\n\tName ClassType::getTypeName()\n\t{\n\t\treturn this->className;\n\t}\n\n\tsize_t ClassType::getElementCount()\n\t{\n\t\treturn this->typeList.size();\n\t}\n\n\tType* ClassType::getElement(const std::string& name)\n\t{\n\t\tauto cls = this;\n\t\twhile(cls->classMembers.find(name) == cls->classMembers.end())\n\t\t\tcls = cls->baseClass;\n\n\t\ticeAssert(cls && \"no such member\");\n\t\treturn cls->classMembers[name];\n\t}\n\n\tsize_t ClassType::getAbsoluteElementIndex(const std::string& name)\n\t{\n\t\tauto cls = this;\n\t\twhile(cls->classMembers.find(name) == cls->classMembers.end())\n\t\t\tcls = cls->baseClass;\n\n\t\ticeAssert(cls && \"no such member\");\n\n\t\treturn cls->indexMap[name];\n\t}\n\n\tvoid ClassType::setMembers(const std::vector<std::pair<std::string, Type*>>& members)\n\t{\n\t\tsize_t i = 0;\n\t\t{\n\t\t\tauto cls = this->baseClass;\n\t\t\twhile(cls)\n\t\t\t{\n\t\t\t\ti += cls->getElementCount();\n\t\t\t\tcls = cls->baseClass;\n\t\t\t}\n\t\t}\n\n\t\tfor(const auto& [ name, ty ] : members)\n\t\t{\n\t\t\tthis->classMembers[name] = ty;\n\t\t\tthis->indexMap[name] = i;\n\n\t\t\tthis->nameList.push_back(name);\n\t\t\tthis->typeList.push_back(ty);\n\n\t\t\ti++;\n\t\t}\n\t}\n\n\tbool ClassType::hasElementWithName(const std::string& name)\n\t{\n\t\tauto cls = this;\n\t\twhile(cls && cls->classMembers.find(name) == cls->classMembers.end())\n\t\t\tcls = cls->baseClass;\n\n\t\treturn cls != 0;\n\t}\n\n\n\n\tconst std::vector<Type*>& ClassType::getElements()\n\t{\n\t\treturn this->typeList;\n\t}\n\n\tconst std::vector<std::string>& ClassType::getNameList()\n\t{\n\t\treturn this->nameList;\n\t}\n\n\tstd::vector<Type*> ClassType::getAllElementsIncludingBase()\n\t{\n\t\tstd::vector<Type*> ret;\n\n\t\tstd::function<void (ClassType*, std::vector<Type*>*)>\n\t\taddMembers = [&addMembers](ClassType* cls, std::vector<Type*>* mems) -> void {\n\n\t\t\tif(!cls) return;\n\n\t\t\taddMembers(cls->getBaseClass(), mems);\n\n\t\t\tfor(auto f : cls->getElements())\n\t\t\t\tmems->push_back(f);\n\t\t};\n\n\t\taddMembers(this, &ret);\n\n\t\treturn ret;\n\t}\n\n\tconst util::hash_map<std::string, size_t>& ClassType::getElementNameMap()\n\t{\n\t\treturn this->indexMap;\n\t}\n\n\n\n\n\n\n\n\n\tconst std::vector<Function*>& ClassType::getInitialiserFunctions()\n\t{\n\t\treturn this->initialiserList;\n\t}\n\n\tvoid ClassType::setDestructor(Function* f)\n\t{\n\t\tthis->destructor = f;\n\t}\n\n\tvoid ClassType::setCopyConstructor(Function* f)\n\t{\n\t\tthis->copyConstructor = f;\n\t}\n\n\tvoid ClassType::setMoveConstructor(Function* f)\n\t{\n\t\tthis->moveConstructor = f;\n\t}\n\n\n\tFunction* ClassType::getDestructor()\n\t{\n\t\treturn this->destructor;\n\t}\n\n\tFunction* ClassType::getCopyConstructor()\n\t{\n\t\treturn this->copyConstructor;\n\t}\n\n\tFunction* ClassType::getMoveConstructor()\n\t{\n\t\treturn this->moveConstructor;\n\t}\n\n\n\n\n\tconst std::vector<Function*>& ClassType::getMethods()\n\t{\n\t\treturn this->methodList;\n\t}\n\n\tstd::vector<Function*> ClassType::getMethodsWithName(const std::string& id)\n\t{\n\t\tauto l = this->classMethodMap[id];\n\n\t\tstd::vector<Function*> ret;\n\t\tret.reserve(l.size());\n\n\t\tfor(auto f : l)\n\t\t\tret.push_back(f);\n\n\t\treturn ret;\n\t}\n\n\tFunction* ClassType::getMethodWithType(FunctionType* ftype)\n\t{\n\t\tfor(auto f : this->methodList)\n\t\t{\n\t\t\tif(f->getType() == ftype)\n\t\t\t\treturn f;\n\t\t}\n\n\t\terror(\"no method with type '%s'\", ftype);\n\t}\n\n\n\tbool ClassType::hasParent(Type* base)\n\t{\n\t\tauto target = dcast(ClassType, base);\n\t\tif(!target) return false;\n\n\t\tauto cls = this;\n\t\twhile(cls)\n\t\t{\n\t\t\tif(target == cls) return true;\n\n\t\t\tcls = cls->baseClass;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\n\tvoid ClassType::setMethods(const std::vector<Function*>& methods)\n\t{\n\t\tfor(auto m : methods)\n\t\t{\n\t\t\tthis->methodList.push_back(m);\n\t\t\tthis->classMethodMap[m->getName().name].push_back(m);\n\t\t}\n\t}\n\n\n\tvoid ClassType::setInitialiserFunctions(const std::vector<Function*>& inits)\n\t{\n\t\tfor(auto m : inits)\n\t\t{\n\t\t\tthis->initialiserList.push_back(m);\n\t\t\tthis->classMethodMap[m->getName().name].push_back(m);\n\t\t}\n\t}\n\n\n\tvoid ClassType::addTraitImpl(TraitType* trt)\n\t{\n\t\tif(zfu::contains(this->implTraits, trt))\n\t\t\terror(\"'%s' already implements trait '%s'\", this, trt);\n\n\t\tthis->implTraits.push_back(trt);\n\t}\n\n\tbool ClassType::implementsTrait(TraitType* trt)\n\t{\n\t\treturn zfu::contains(this->implTraits, trt);\n\t}\n\n\tstd::vector<TraitType*> ClassType::getImplementedTraits()\n\t{\n\t\treturn this->implTraits;\n\t}\n\n\n\tClassType* ClassType::getBaseClass()\n\t{\n\t\treturn this->baseClass;\n\t}\n\n\tvoid ClassType::setBaseClass(ClassType* ty)\n\t{\n\t\tthis->baseClass = ty;\n\n\t\t//* keeps things simple.\n\t\ticeAssert(this->virtualMethodMap.empty() || !\"cannot set base class after adding virtual methods\");\n\n\t\tthis->virtualMethodMap = this->baseClass->virtualMethodMap;\n\t\tthis->virtualMethodCount = this->baseClass->virtualMethodCount;\n\t\tthis->reverseVirtualMethodMap = this->baseClass->reverseVirtualMethodMap;\n\t}\n\n\n\tvoid ClassType::addVirtualMethod(Function* method)\n\t{\n\t\t//* note: the 'reverse' virtual method map is to allow us, at translation time, to easily create the vtable without\n\t\t//* unnecessary searching. When we set a base class, we copy its 'reverse' map; thus, if we don't override anything,\n\t\t//* our vtable will just refer to the methods in the base class.\n\n\t\t//* but if we do override something, we just set the method in our 'reverse' map, which is what we'll use to build\n\t\t//* the vtable. simple?\n\n\t\tauto list = zfu::drop(method->getType()->toFunctionType()->getArgumentTypes(), 1);\n\n\t\t// check every member of the current mapping -- not the fastest method i admit.\n\t\tbool found = false;\n\t\tfor(const auto& vm : this->virtualMethodMap)\n\t\t{\n\t\t\tif(vm.first.first == method->getName().name && areTypeListsContravariant(vm.first.second, list, /* trait checking: */ false))\n\t\t\t{\n\t\t\t\tfound = true;\n\t\t\t\tthis->virtualMethodMap[{ method->getName().name, list }] = vm.second;\n\t\t\t\tthis->reverseVirtualMethodMap[vm.second] = method;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif(!found)\n\t\t{\n\t\t\t// just make a new one.\n\t\t\tthis->virtualMethodMap[{ method->getName().name, list }] = this->virtualMethodCount;\n\t\t\tthis->reverseVirtualMethodMap[this->virtualMethodCount] = method;\n\t\t\tthis->virtualMethodCount++;\n\t\t}\n\t}\n\n\tsize_t ClassType::getVirtualMethodIndex(const std::string& name, FunctionType* ft)\n\t{\n\t\tauto withoutself = [](std::vector<Type*> p) -> std::vector<Type*> {\n\t\t\tp.erase(p.begin());\n\t\t\treturn p;\n\t\t};\n\n\t\tauto list = ft->getArgumentTypes();\n\n\t\tif(auto it = this->virtualMethodMap.find({ name, withoutself(list) }); it != this->virtualMethodMap.end())\n\t\t{\n\t\t\treturn it->second;\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(\"no method named '%s' matching signature '%s' in virtual method table of class '%s'\",\n\t\t\t\tname, ft, this->getTypeName().name);\n\t\t}\n\t}\n\n\tsize_t ClassType::getVirtualMethodCount()\n\t{\n\t\treturn this->virtualMethodCount;\n\t}\n\n\n\tFunction* ClassType::getInlineInitialiser()\n\t{\n\t\treturn this->inlineInitialiser;\n\t}\n\n\tvoid ClassType::setInlineInitialiser(Function* fn)\n\t{\n\t\tthis->inlineInitialiser = fn;\n\t}\n\n\n\tFunction* ClassType::getInlineDestructor()\n\t{\n\t\treturn this->inlineDestructor;\n\t}\n\n\tvoid ClassType::setInlineDestructor(Function* fn)\n\t{\n\t\tthis->inlineDestructor = fn;\n\t}\n\n\n\tfir::Type* ClassType::substitutePlaceholders(const util::hash_map<fir::Type*, fir::Type*>& subst)\n\t{\n\t\tif(this->containsPlaceholders())\n\t\t\terror(\"not supported!\");\n\n\t\treturn this;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/Types/DynamicArrayType.cpp",
    "content": "// DynamicArrayType.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ir/type.h\"\n#include \"errors.h\"\n\nnamespace fir\n{\n\tDynamicArrayType::DynamicArrayType(Type* elmType) : Type(TypeKind::DynamicArray)\n\t{\n\t\tthis->arrayElementType = elmType;\n\t}\n\n\tType* DynamicArrayType::getElementType()\n\t{\n\t\treturn this->arrayElementType;\n\t}\n\n\tstd::string DynamicArrayType::str()\n\t{\n\t\treturn strprintf(\"[%s]\", this->arrayElementType->str());\n\t}\n\n\tstd::string DynamicArrayType::encodedStr()\n\t{\n\t\treturn strprintf(\"[%s]\", this->arrayElementType->encodedStr());\n\t}\n\n\tbool DynamicArrayType::isTypeEqual(Type* other)\n\t{\n\t\tif(other->kind != TypeKind::DynamicArray)\n\t\t\treturn false;\n\n\t\treturn this->arrayElementType->isTypeEqual(other->toDynamicArrayType()->arrayElementType);\n\t}\n\n\tDynamicArrayType* DynamicArrayType::get(Type* elementType)\n\t{\n\t\treturn TypeCache::get().getOrAddCachedType(new DynamicArrayType(elementType));\n\t}\n\n\tfir::Type* DynamicArrayType::substitutePlaceholders(const util::hash_map<fir::Type*, fir::Type*>& subst)\n\t{\n\t\treturn DynamicArrayType::get(this->arrayElementType->substitutePlaceholders(subst));\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/Types/EnumType.cpp",
    "content": "// EnumType.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n\n#include \"ir/type.h\"\n#include \"ir/value.h\"\n#include \"ir/constant.h\"\n\n\nnamespace fir\n{\n\tEnumType::EnumType(const Name& name, Type* ct) : Type(TypeKind::Enum), typeName(name)\n\t{\n\t\tthis->caseType = ct;\n\t}\n\n\tName EnumType::getTypeName()\n\t{\n\t\treturn this->typeName;\n\t}\n\n\tType* EnumType::getCaseType()\n\t{\n\t\treturn this->caseType;\n\t}\n\n\tstd::string EnumType::str()\n\t{\n\t\treturn \"enum(\" + this->typeName.name + \")\";\n\t}\n\n\tstd::string EnumType::encodedStr()\n\t{\n\t\treturn this->typeName.str();\n\t}\n\n\tbool EnumType::isTypeEqual(Type* other)\n\t{\n\t\tif(other->kind != TypeKind::Enum)\n\t\t\treturn false;\n\n\t\treturn (this->typeName == other->toEnumType()->typeName) && (this->caseType->isTypeEqual(other->toEnumType()->caseType));\n\t}\n\n\tfir::ConstantValue* EnumType::getNameArray()\n\t{\n\t\treturn this->runtimeNameArray;\n\t}\n\n\tfir::ConstantValue* EnumType::getCaseArray()\n\t{\n\t\treturn this->runtimeCasesArray;\n\t}\n\n\n\tvoid EnumType::setNameArray(ConstantValue* arr)\n\t{\n\t\tthis->runtimeNameArray = arr;\n\t}\n\n\tvoid EnumType::setCaseArray(ConstantValue* arr)\n\t{\n\t\tthis->runtimeCasesArray = arr;\n\t}\n\n\tvoid EnumType::setCaseType(Type* t)\n\t{\n\t\tif(!this->caseType->isVoidType())\n\t\t\terror(\"cannot modify enum type! was previously '%s'\", this->caseType);\n\n\t\tthis->caseType = t;\n\t}\n\n\n\n\n\tstatic util::hash_map<Name, EnumType*> typeCache;\n\n\tEnumType* EnumType::get(const Name& name, Type* caseType)\n\t{\n\t\tif(auto it = typeCache.find(name); it != typeCache.end())\n\t\t\terror(\"enum with name '%s' already exists\", name.str());\n\n\t\telse\n\t\t\treturn (typeCache[name] = new EnumType(name, caseType));\n\t}\n\n\tfir::Type* EnumType::substitutePlaceholders(const util::hash_map<fir::Type*, fir::Type*>& subst)\n\t{\n\t\tif(this->containsPlaceholders())\n\t\t\terror(\"not supported!\");\n\n\t\treturn this;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/Types/FunctionType.cpp",
    "content": "// FunctionType.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ir/type.h\"\n#include \"ir/function.h\"\n\nnamespace Codegen\n{\n\tstd::string unwrapPointerType(const std::string&, int*);\n}\n\nnamespace fir\n{\n\tFunctionType::FunctionType(const std::vector<Type*>& args, Type* ret, bool iscva) : Type(TypeKind::Function)\n\t{\n\t\tthis->functionParams = args;\n\t\tthis->functionRetType = ret;\n\n\t\tthis->isFnCStyleVarArg = iscva;\n\t}\n\n\n\n\n\n\t// functions\n\tFunctionType* FunctionType::getCVariadicFunc(const std::vector<Type*>& args, Type* ret)\n\t{\n\t\treturn TypeCache::get().getOrAddCachedType(new FunctionType(args, ret, true));\n\t}\n\n\tFunctionType* FunctionType::getCVariadicFunc(const std::initializer_list<Type*>& args, Type* ret)\n\t{\n\t\treturn FunctionType::getCVariadicFunc(std::vector<Type*>(args.begin(), args.end()), ret);\n\t}\n\n\tFunctionType* FunctionType::get(const std::vector<Type*>& args, Type* ret)\n\t{\n\t\treturn TypeCache::get().getOrAddCachedType(new FunctionType(args, ret, false));\n\t}\n\n\tFunctionType* FunctionType::get(const std::initializer_list<Type*>& args, Type* ret)\n\t{\n\t\treturn FunctionType::get(std::vector<Type*>(args.begin(), args.end()), ret);\n\t}\n\n\n\n\n\n\n\n\t// various\n\tstd::string FunctionType::str()\n\t{\n\t\tstd::string ret;\n\t\tfor(auto p : this->functionParams)\n\t\t\tret += p->str() + \", \";\n\n\t\tif(ret.length() > 0)\n\t\t\tret = ret.substr(0, ret.length() - 2); // remove extra comma\n\n\t\ticeAssert(this->functionRetType);\n\t\treturn \"fn(\" + ret + \") -> \" + this->functionRetType->str();\n\t}\n\n\tstd::string FunctionType::encodedStr()\n\t{\n\t\treturn this->str();\n\t}\n\n\n\n\n\n\t// function stuff\n\tconst std::vector<Type*>& FunctionType::getArgumentTypes()\n\t{\n\t\treturn this->functionParams;\n\t}\n\n\tsize_t FunctionType::getArgumentCount()\n\t{\n\t\treturn this->functionParams.size();\n\t}\n\n\tType* FunctionType::getArgumentN(size_t n)\n\t{\n\t\treturn this->functionParams[n];\n\t}\n\n\tType* FunctionType::getReturnType()\n\t{\n\t\treturn this->functionRetType;\n\t}\n\n\tbool FunctionType::isCStyleVarArg()\n\t{\n\t\treturn this->isFnCStyleVarArg;\n\t}\n\n\tbool FunctionType::isVariadicFunc()\n\t{\n\t\treturn this->functionParams.size() > 0 && this->functionParams.back()->isArraySliceType()\n\t\t\t&& this->functionParams.back()->toArraySliceType()->isVariadicType();\n\t}\n\n\n\tbool FunctionType::isTypeEqual(Type* other)\n\t{\n\t\tif(other->kind != TypeKind::Function)\n\t\t\treturn false;\n\n\t\tauto of = other->toFunctionType();\n\t\tauto ret = (this->isFnCStyleVarArg == of->isFnCStyleVarArg) && (this->functionRetType == of->functionRetType)\n\t\t\t&& (this->functionParams.size() == of->functionParams.size());\n\n\t\tif(ret)\n\t\t{\n\t\t\tfor(size_t i = 0; i < this->functionParams.size(); i++)\n\t\t\t{\n\t\t\t\tif(this->functionParams[i] != of->functionParams[i])\n\t\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tfir::Type* FunctionType::substitutePlaceholders(const util::hash_map<fir::Type*, fir::Type*>& subst)\n\t{\n\t\tauto args = zfu::map(this->functionParams, [&subst](auto t) -> auto { return t->substitutePlaceholders(subst); });\n\t\tauto ret = this->functionRetType->substitutePlaceholders(subst);\n\n\t\tif(this->isFnCStyleVarArg)  return FunctionType::getCVariadicFunc(args, ret);\n\t\telse                        return FunctionType::get(args, ret);\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/Types/OpaqueType.cpp",
    "content": "// OpaqueType.cpp\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ir/type.h\"\n#include \"ir/value.h\"\n#include \"ir/constant.h\"\n\n\nnamespace fir\n{\n\tOpaqueType::OpaqueType(const std::string& name, size_t size) : Type(TypeKind::Opaque)\n\t{\n\t\tthis->typeName = name;\n\t\tthis->typeSizeInBits = size;\n\t}\n\n\tstd::string OpaqueType::str()\n\t{\n\t\treturn strprintf(\"opaque(%s)\", this->typeName);\n\t}\n\n\tstd::string OpaqueType::encodedStr()\n\t{\n\t\treturn strprintf(\"opaque(%s)\", this->typeName);\n\t}\n\n\tbool OpaqueType::isTypeEqual(Type* other)\n\t{\n\t\treturn other && other->isOpaqueType() && other->toOpaqueType()->typeName == this->typeName;\n\t}\n\n\tfir::Type* OpaqueType::substitutePlaceholders(const util::hash_map<fir::Type*, fir::Type*>& subst)\n\t{\n\t\treturn this;\n\t}\n\n\n\tstatic util::hash_map<std::string, OpaqueType*> typeCache;\n\tOpaqueType* OpaqueType::get(const std::string& name, size_t size)\n\t{\n\t\tif(size < 8)\n\t\t\terror(\"types must be >= 8 bits (for now) (%s)\", name);\n\n\n\t\tif(auto it = typeCache.find(name); it != typeCache.end())\n\t\t\treturn it->second;\n\n\t\telse\n\t\t\treturn (typeCache[name] = new OpaqueType(name, size));\n\t}\n}\n"
  },
  {
    "path": "source/fir/Types/PointerType.cpp",
    "content": "// Type.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ir/type.h\"\n\nnamespace fir\n{\n\tPointerType::PointerType(Type* base, bool mut) : Type(TypeKind::Pointer)\n\t{\n\t\tthis->baseType = base;\n\t\tthis->isPtrMutable = mut;\n\t}\n\n\tPointerType* PointerType::getMutable()\n\t{\n\t\tif(this->isPtrMutable) return this;\n\t\treturn this->baseType->getMutablePointerTo()->toPointerType();\n\t}\n\n\tPointerType* PointerType::getImmutable()\n\t{\n\t\tif(!this->isPtrMutable) return this;\n\t\treturn this->baseType->getPointerTo()->toPointerType();\n\t}\n\n\n\tbool PointerType::isMutable()\n\t{\n\t\treturn this->isPtrMutable;\n\t}\n\n\n\n\tPointerType* PointerType::getInt8Ptr()\n\t{\n\t\treturn Type::getInt8()->getPointerTo()->toPointerType();\n\t}\n\n\tPointerType* PointerType::getInt16Ptr()\n\t{\n\t\treturn Type::getInt16()->getPointerTo()->toPointerType();\n\t}\n\n\tPointerType* PointerType::getInt32Ptr()\n\t{\n\t\treturn Type::getInt32()->getPointerTo()->toPointerType();\n\t}\n\n\tPointerType* PointerType::getInt64Ptr()\n\t{\n\t\treturn Type::getInt64()->getPointerTo()->toPointerType();\n\t}\n\n\tPointerType* PointerType::getInt128Ptr()\n\t{\n\t\treturn Type::getInt128()->getPointerTo()->toPointerType();\n\t}\n\n\n\tPointerType* PointerType::getUint8Ptr()\n\t{\n\t\treturn Type::getUint8()->getPointerTo()->toPointerType();\n\t}\n\n\tPointerType* PointerType::getUint16Ptr()\n\t{\n\t\treturn Type::getUint16()->getPointerTo()->toPointerType();\n\t}\n\n\tPointerType* PointerType::getUint32Ptr()\n\t{\n\t\treturn Type::getUint32()->getPointerTo()->toPointerType();\n\t}\n\n\tPointerType* PointerType::getUint64Ptr()\n\t{\n\t\treturn Type::getUint64()->getPointerTo()->toPointerType();\n\t}\n\n\tPointerType* PointerType::getUint128Ptr()\n\t{\n\t\treturn Type::getUint128()->getPointerTo()->toPointerType();\n\t}\n\n\n\n\n\n\n\n\t// various\n\tstd::string PointerType::str()\n\t{\n\t\treturn (this->isPtrMutable ? \"&mut \" : \"&\") + this->baseType->str();\n\t}\n\n\tstd::string PointerType::encodedStr()\n\t{\n\t\treturn this->baseType->encodedStr() + (this->isPtrMutable ? \"MP\" : \"P\");\n\t}\n\n\n\tbool PointerType::isTypeEqual(Type* other)\n\t{\n\t\tif(other->kind != TypeKind::Pointer)\n\t\t\treturn false;\n\n\t\tauto op = other->toPointerType();\n\t\treturn this->baseType->isTypeEqual(op->baseType) && (this->isPtrMutable == op->isPtrMutable);\n\t}\n\n\tfir::Type* PointerType::substitutePlaceholders(const util::hash_map<fir::Type*, fir::Type*>& subst)\n\t{\n\t\tauto base = this->baseType->substitutePlaceholders(subst);\n\t\tif(this->isMutable())   return base->getMutablePointerTo();\n\t\telse                    return base->getPointerTo();\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/Types/PrimitiveType.cpp",
    "content": "// Type.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ir/type.h\"\n\nnamespace fir\n{\n\tPrimitiveType::PrimitiveType(size_t bits, bool issigned, Kind kind) : Type(TypeKind::Primitive)\n\t{\n\t\tthis->bitWidth = bits;\n\t\tthis->primKind = kind;\n\t\tthis->isTypeSigned = issigned;\n\t}\n\n\n\n\n\n\n\n\n\n\n\tstatic util::hash_map<size_t, std::vector<PrimitiveType*>> primitiveTypeCache;\n\tPrimitiveType* PrimitiveType::getIntWithBitWidthAndSignage(size_t bits, bool issigned)\n\t{\n\t\tstd::vector<PrimitiveType*>& types = primitiveTypeCache[bits];\n\n\t\tfor(auto t : types)\n\t\t{\n\t\t\ticeAssert(t->bitWidth == bits);\n\t\t\tif(t->isIntegerType() && !t->isFloatingPointType() && (t->isSigned() == issigned))\n\t\t\t\treturn t;\n\t\t}\n\n\n\t\treturn *types.insert(types.end(), new PrimitiveType(bits, issigned, Kind::Integer));\n\t}\n\n\tPrimitiveType* PrimitiveType::getFloatWithBitWidth(size_t bits)\n\t{\n\t\tstd::vector<PrimitiveType*>& types = primitiveTypeCache[bits];\n\n\t\tfor(auto t : types)\n\t\t{\n\t\t\ticeAssert(t->bitWidth == bits);\n\t\t\tif(t->isFloatingPointType())\n\t\t\t\treturn t;\n\t\t}\n\n\t\treturn *types.insert(types.end(), new PrimitiveType(bits, false, Kind::Floating));\n\t}\n\n\tPrimitiveType* PrimitiveType::getIntN(size_t bits)\n\t{\n\t\treturn PrimitiveType::getIntWithBitWidthAndSignage(bits, true);\n\t}\n\n\tPrimitiveType* PrimitiveType::getUintN(size_t bits)\n\t{\n\t\treturn PrimitiveType::getIntWithBitWidthAndSignage(bits, false);\n\t}\n\n\n\n\n\n\tPrimitiveType* PrimitiveType::getInt8()\n\t{\n\t\treturn PrimitiveType::getIntWithBitWidthAndSignage(8, true);\n\t}\n\n\tPrimitiveType* PrimitiveType::getInt16()\n\t{\n\t\treturn PrimitiveType::getIntWithBitWidthAndSignage(16, true);\n\t}\n\n\tPrimitiveType* PrimitiveType::getInt32()\n\t{\n\t\treturn PrimitiveType::getIntWithBitWidthAndSignage(32, true);\n\t}\n\n\tPrimitiveType* PrimitiveType::getInt64()\n\t{\n\t\treturn PrimitiveType::getIntWithBitWidthAndSignage(64, true);\n\t}\n\n\tPrimitiveType* PrimitiveType::getInt128()\n\t{\n\t\treturn PrimitiveType::getIntWithBitWidthAndSignage(128, true);\n\t}\n\n\n\n\n\n\tPrimitiveType* PrimitiveType::getUint8()\n\t{\n\t\treturn PrimitiveType::getIntWithBitWidthAndSignage(8, false);\n\t}\n\n\tPrimitiveType* PrimitiveType::getUint16()\n\t{\n\t\treturn PrimitiveType::getIntWithBitWidthAndSignage(16, false);\n\t}\n\n\tPrimitiveType* PrimitiveType::getUint32()\n\t{\n\t\treturn PrimitiveType::getIntWithBitWidthAndSignage(32, false);\n\t}\n\n\tPrimitiveType* PrimitiveType::getUint64()\n\t{\n\t\treturn PrimitiveType::getIntWithBitWidthAndSignage(64, false);\n\t}\n\n\tPrimitiveType* PrimitiveType::getUint128()\n\t{\n\t\treturn PrimitiveType::getIntWithBitWidthAndSignage(128, false);\n\t}\n\n\n\n\n\tPrimitiveType* PrimitiveType::getFloat32()\n\t{\n\t\treturn PrimitiveType::getFloatWithBitWidth(32);\n\t}\n\n\tPrimitiveType* PrimitiveType::getFloat64()\n\t{\n\t\treturn PrimitiveType::getFloatWithBitWidth(64);\n\t}\n\n\tPrimitiveType* PrimitiveType::getFloat128()\n\t{\n\t\treturn PrimitiveType::getFloatWithBitWidth(128);\n\t}\n\n\n\n\n\n\n\n\n\n\t// various\n\tstd::string PrimitiveType::str()\n\t{\n\t\t// is primitive.\n\t\tstd::string ret;\n\n\t\tif(this->primKind == Kind::Integer)\n\t\t{\n\t\t\tif(this->isSigned())\tret = \"i\";\n\t\t\telse\t\t\t\t\tret = \"u\";\n\n\t\t\tret += std::to_string(this->getIntegerBitWidth());\n\t\t}\n\t\telse if(this->primKind == Kind::Floating)\n\t\t{\n\t\t\tret = \"f\" + std::to_string(this->getFloatingPointBitWidth());\n\t\t}\n\t\telse\n\t\t{\n\t\t\ticeAssert(0);\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\tstd::string PrimitiveType::encodedStr()\n\t{\n\t\treturn this->str();\n\t}\n\n\n\tbool PrimitiveType::isTypeEqual(Type* other)\n\t{\n\t\tif(other->kind != TypeKind::Primitive)\n\t\t\treturn false;\n\n\t\tauto op = other->toPrimitiveType();\n\t\treturn (this->primKind == op->primKind) && (this->bitWidth == op->bitWidth) && (this->isTypeSigned == op->isTypeSigned);\n\t}\n\n\n\n\n\tbool PrimitiveType::isSigned()\n\t{\n\t\ticeAssert(this->primKind == Kind::Integer && \"not integer type\");\n\t\treturn this->isTypeSigned;\n\t}\n\n\tsize_t PrimitiveType::getIntegerBitWidth()\n\t{\n\t\ticeAssert(this->primKind == Kind::Integer && \"not integer type\");\n\t\treturn this->bitWidth;\n\t}\n\n\n\t// float stuff\n\tsize_t PrimitiveType::getFloatingPointBitWidth()\n\t{\n\t\ticeAssert(this->primKind == Kind::Floating && \"not floating point type\");\n\t\treturn this->bitWidth;\n\t}\n\n\tPrimitiveType* PrimitiveType::getOppositeSignedType()\n\t{\n\t\tif(this == Type::getInt8())\n\t\t{\n\t\t\treturn Type::getUint8();\n\t\t}\n\t\telse if(this == Type::getInt16())\n\t\t{\n\t\t\treturn Type::getUint16();\n\t\t}\n\t\telse if(this == Type::getInt32())\n\t\t{\n\t\t\treturn Type::getUint32();\n\t\t}\n\t\telse if(this == Type::getInt64())\n\t\t{\n\t\t\treturn Type::getUint64();\n\t\t}\n\t\telse if(this == Type::getInt128())\n\t\t{\n\t\t\treturn Type::getUint128();\n\t\t}\n\t\telse if(this == Type::getUint8())\n\t\t{\n\t\t\treturn Type::getInt8();\n\t\t}\n\t\telse if(this == Type::getUint16())\n\t\t{\n\t\t\treturn Type::getInt16();\n\t\t}\n\t\telse if(this == Type::getUint32())\n\t\t{\n\t\t\treturn Type::getInt32();\n\t\t}\n\t\telse if(this == Type::getUint64())\n\t\t{\n\t\t\treturn Type::getInt64();\n\t\t}\n\t\telse if(this == Type::getUint128())\n\t\t{\n\t\t\treturn Type::getInt128();\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn this;\n\t\t}\n\t}\n\n\tfir::Type* PrimitiveType::substitutePlaceholders(const util::hash_map<fir::Type*, fir::Type*>& subst)\n\t{\n\t\treturn this;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/Types/RawUnionType.cpp",
    "content": "// RawUnionType.cpp\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n\n#include \"errors.h\"\n#include \"ir/type.h\"\n\n#include \"pts.h\"\n\nnamespace fir\n{\n\t// structs\n\tRawUnionType::RawUnionType(const Name& name, const util::hash_map<std::string, Type*>& mems)\n\t\t: Type(TypeKind::RawUnion), unionName(name)\n\t{\n\t\tthis->setBody(mems);\n\t}\n\n\tstatic util::hash_map<Name, RawUnionType*> typeCache;\n\tRawUnionType* RawUnionType::create(const Name& name, const util::hash_map<std::string, Type*>& mems)\n\t{\n\t\tif(auto it = typeCache.find(name); it != typeCache.end())\n\t\t\terror(\"union with name '%s' already exists\", name.str());\n\n\t\telse\n\t\t\treturn (typeCache[name] = new RawUnionType(name, mems));\n\t}\n\n\tRawUnionType* RawUnionType::createWithoutBody(const Name& name)\n\t{\n\t\treturn RawUnionType::create(name, { });\n\t}\n\n\n\n\n\n\n\t// various\n\tstd::string RawUnionType::str()\n\t{\n\t\treturn \"raw_union(\" + this->unionName.name + \")\";\n\t}\n\n\tstd::string RawUnionType::encodedStr()\n\t{\n\t\treturn this->unionName.str();\n\t}\n\n\n\tbool RawUnionType::isTypeEqual(Type* other)\n\t{\n\t\tif(other->kind != TypeKind::Union)\n\t\t\treturn false;\n\n\t\treturn (this->unionName == other->toRawUnionType()->unionName);\n\t}\n\n\n\n\t// struct stuff\n\tName RawUnionType::getTypeName()\n\t{\n\t\treturn this->unionName;\n\t}\n\n\tsize_t RawUnionType::getVariantCount()\n\t{\n\t\treturn this->variants.size();\n\t}\n\n\tconst util::hash_map<std::string, Type*>& RawUnionType::getVariants()\n\t{\n\t\treturn this->variants;\n\t}\n\n\tbool RawUnionType::hasVariant(const std::string& name)\n\t{\n\t\treturn this->variants.find(name) != this->variants.end();\n\t}\n\n\tType* RawUnionType::getVariant(const std::string& name)\n\t{\n\t\tif(auto it = this->variants.find(name); it != this->variants.end())\n\t\t\treturn it->second;\n\n\t\telse\n\t\t\terror(\"no variant named '%s' in union '%s'\", name, this->getTypeName().str());\n\t}\n\n\n\n\tvoid RawUnionType::setBody(const util::hash_map<std::string, Type*>& members)\n\t{\n\t\tthis->variants = members;\n\t}\n\n\tfir::Type* RawUnionType::substitutePlaceholders(const util::hash_map<Type*, Type*>& subst)\n\t{\n\t\tif(this->containsPlaceholders())\n\t\t\terror(\"not supported!\");\n\n\t\treturn this;\n\t}\n}\n"
  },
  {
    "path": "source/fir/Types/SingleTypes.cpp",
    "content": "// SingleTypes.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"errors.h\"\n#include \"ir/type.h\"\n\nnamespace fir\n{\n\tusing PolySubst = util::hash_map<fir::Type*, fir::Type*>;\n\n\tstatic AnyType* singleAny = 0;\n\tAnyType::AnyType() : Type(TypeKind::Any)            { }\n\tstd::string AnyType::str()                          { return \"any\"; }\n\tstd::string AnyType::encodedStr()                   { return \"any\"; }\n\tbool AnyType::isTypeEqual(Type* other)              { return other && other->isAnyType(); }\n\tAnyType* AnyType::get()                             { return singleAny = (singleAny ? singleAny : new AnyType()); }\n\tfir::Type* AnyType::substitutePlaceholders(const PolySubst&)    { return this; }\n\n\n\tstatic BoolType* singleBool = 0;\n\tBoolType::BoolType() : Type(TypeKind::Bool)         { }\n\tstd::string BoolType::str()                         { return \"bool\"; }\n\tstd::string BoolType::encodedStr()                  { return \"bool\"; }\n\tbool BoolType::isTypeEqual(Type* other)             { return other && other->isBoolType(); }\n\tBoolType* BoolType::get()                           { return singleBool = (singleBool ? singleBool : new BoolType()); }\n\tfir::Type* BoolType::substitutePlaceholders(const PolySubst&)   { return this; }\n\n\n\tstatic VoidType* singleVoid = 0;\n\tVoidType::VoidType() : Type(TypeKind::Void)         { }\n\tstd::string VoidType::str()                         { return \"void\"; }\n\tstd::string VoidType::encodedStr()                  { return \"void\"; }\n\tbool VoidType::isTypeEqual(Type* other)             { return other && other->isVoidType(); }\n\tVoidType* VoidType::get()                           { return singleVoid = (singleVoid ? singleVoid : new VoidType()); }\n\tfir::Type* VoidType::substitutePlaceholders(const PolySubst&)   { return this; }\n\n\n\tstatic NullType* singleNull = 0;\n\tNullType::NullType() : Type(TypeKind::Null)         { }\n\tstd::string NullType::str()                         { return \"nulltype\"; }\n\tstd::string NullType::encodedStr()                  { return \"nulltype\"; }\n\tbool NullType::isTypeEqual(Type* other)             { return other && other->isNullType(); }\n\tNullType* NullType::get()                           { return singleNull = (singleNull ? singleNull : new NullType()); }\n\tfir::Type* NullType::substitutePlaceholders(const PolySubst&)   { return this; }\n\n\n\tstatic RangeType* singleRange = 0;\n\tRangeType::RangeType() : Type(TypeKind::Range)      { }\n\tstd::string RangeType::str()                        { return \"range\"; }\n\tstd::string RangeType::encodedStr()                 { return \"range\"; }\n\tbool RangeType::isTypeEqual(Type* other)            { return other && other->isRangeType(); }\n\tRangeType* RangeType::get()                         { return singleRange = (singleRange ? singleRange : new RangeType()); }\n\tfir::Type* RangeType::substitutePlaceholders(const PolySubst&)  { return this; }\n\n\n\tstatic StringType* singleString = 0;\n\tStringType::StringType() : Type(TypeKind::String)   { }\n\tstd::string StringType::str()                       { return \"string\"; }\n\tstd::string StringType::encodedStr()                { return \"string\"; }\n\tbool StringType::isTypeEqual(Type* other)           { return other && other->isStringType(); }\n\tStringType* StringType::get()                       { return singleString = (singleString ? singleString : new StringType()); }\n\tfir::Type* StringType::substitutePlaceholders(const PolySubst&) { return this; }\n\n\n\n\n\n\n\tstd::string ConstantNumberType::encodedStr()                { return \"number\"; }\n\tbool ConstantNumberType::isSigned()                         { return this->_signed; }\n\tbool ConstantNumberType::isFloating()                       { return this->_floating; }\n\tsize_t ConstantNumberType::getMinBits()                     { return this->_bits; }\n\tbool ConstantNumberType::isTypeEqual(Type* other)\n\t{\n\t\treturn other && other->isConstantNumberType()\n\t\t\t&& other->toConstantNumberType()->_bits == this->_bits\n\t\t\t&& other->toConstantNumberType()->_signed == this->_signed\n\t\t\t&& other->toConstantNumberType()->_floating == this->_floating;\n\t}\n\tConstantNumberType* ConstantNumberType::get(bool neg, bool flt, size_t bits)\n\t{\n\t\treturn TypeCache::get().getOrAddCachedType(new ConstantNumberType(neg, flt, bits));\n\t}\n\tConstantNumberType::ConstantNumberType(bool neg, bool flt, size_t bits) : Type(TypeKind::ConstantNumber)\n\t{\n\t\tthis->_bits = bits;\n\t\tthis->_signed = neg;\n\t\tthis->_floating = flt;\n\t}\n\tfir::Type* ConstantNumberType::substitutePlaceholders(const PolySubst& subst)\n\t{\n\t\treturn this;\n\t}\n\tstd::string ConstantNumberType::str()\n\t{\n\t\t// return strprintf(\"number(sgn: %s, flt: %s, bits: %d)\", _signed, _floating, _bits);\n\t\treturn strprintf(\"number\");\n\t}\n\n\n\n\n\tConstantNumberType* unifyConstantTypes(ConstantNumberType* a, ConstantNumberType* b)\n\t{\n\t\tauto sgn = a->isSigned() || b->isSigned();\n\t\tauto flt = a->isFloating() || b->isFloating();\n\t\tauto bit = std::max(a->getMinBits(), b->getMinBits());\n\n\t\treturn ConstantNumberType::get(sgn, flt, bit);\n\t}\n\n\tType* getBestFitTypeForConstant(ConstantNumberType* cnt)\n\t{\n\t\tif(cnt->isFloating())\n\t\t{\n\t\t\tif(cnt->getMinBits() > 64)\n\t\t\t\terror(\"constant number type '%s' requires too many bits\", cnt);\n\n\t\t\treturn fir::Type::getFloat64();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif(cnt->getMinBits() < fir::Type::getNativeWord()->getBitWidth())\n\t\t\t{\n\t\t\t\treturn fir::Type::getNativeWord();\n\t\t\t}\n\t\t\telse if(cnt->isSigned())\n\t\t\t{\n\t\t\t\terror(\"constant number type '%s' requires too many bits\", cnt);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif(cnt->getMinBits() > fir::Type::getNativeUWord()->getBitWidth())\n\t\t\t\t\terror(\"constant number type '%s' requires too many bits\", cnt);\n\n\t\t\t\treturn fir::Type::getNativeUWord();\n\t\t\t}\n\t\t}\n\t}\n\n\n\n\n\n\n\n\n\n\tstd::string PolyPlaceholderType::str()          { return strprintf(\"$%s/%d\", this->name, this->group); }\n\tstd::string PolyPlaceholderType::encodedStr()   { return strprintf(\"$%s/%d\", this->name, this->group); }\n\n\tstd::string PolyPlaceholderType::getName()      { return this->name; }\n\tint PolyPlaceholderType::getGroup()             { return this->group; }\n\n\tstatic std::vector<util::hash_map<std::string, PolyPlaceholderType*>> cache;\n\tPolyPlaceholderType* PolyPlaceholderType::get(const std::string& n, int group)\n\t{\n\t\twhile(static_cast<size_t>(group) >= cache.size())\n\t\t\tcache.push_back({ });\n\n\t\tif(auto it = cache[group].find(n); it != cache[group].end())\n\t\t\treturn it->second;\n\n\t\treturn cache[group][n] = new PolyPlaceholderType(n, group);\n\t}\n\n\tbool PolyPlaceholderType::isTypeEqual(Type* other)\n\t{\n\t\t// return other && other->isPolyPlaceholderType() && other->toPolyPlaceholderType()->name == this->name\n\t\t// \t&& other->toPolyPlaceholderType()->group == this->group;\n\n\t\t//! ACHTUNG !\n\t\t// performance optimisation: since all polys go through ::get, and we already guarantee interning\n\t\t// from that function, we should be able to just compare pointers.\n\t\treturn (other == this);\n\t}\n\n\tPolyPlaceholderType::PolyPlaceholderType(const std::string& n, int g) : Type(TypeKind::PolyPlaceholder)\n\t{\n\t\tthis->name = n;\n\t\tthis->group = g;\n\t}\n\n\n\tstatic fir::Type* _substitute(const PolySubst& subst, fir::Type* t)\n\t{\n\t\tif(auto it = subst.find(t); it != subst.end())\n\t\t\treturn it->second->substitutePlaceholders(subst);\n\n\t\treturn t;\n\t}\n\n\tfir::Type* PolyPlaceholderType::substitutePlaceholders(const PolySubst& subst)\n\t{\n\t\treturn _substitute(subst, this);\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/Types/StructType.cpp",
    "content": "// StructType.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"errors.h\"\n#include \"ir/type.h\"\n\n#include \"pts.h\"\n\nnamespace fir\n{\n\t// structs\n\tStructType::StructType(const Name& name, const std::vector<std::pair<std::string, Type*>>& mems, bool ispacked)\n\t\t: Type(TypeKind::Struct), structName(name)\n\t{\n\t\tthis->isTypePacked = ispacked;\n\t\tthis->setBody(mems);\n\t}\n\n\tstatic util::hash_map<Name, StructType*> typeCache;\n\tStructType* StructType::create(const Name& name, const std::vector<std::pair<std::string, Type*>>& members, bool packed)\n\t{\n\t\tif(auto it = typeCache.find(name); it != typeCache.end())\n\t\t\terror(\"struct with name '%s' already exists\", name.str());\n\n\t\telse\n\t\t\treturn (typeCache[name] = new StructType(name, members, packed));\n\t}\n\n\tStructType* StructType::createWithoutBody(const Name& name, bool isPacked)\n\t{\n\t\treturn StructType::create(name, { }, isPacked);\n\t}\n\n\n\n\n\n\n\t// various\n\tstd::string StructType::str()\n\t{\n\t\treturn \"struct(\" + this->structName.name + \")\";\n\t}\n\n\tstd::string StructType::encodedStr()\n\t{\n\t\treturn this->structName.str();\n\t}\n\n\n\tbool StructType::isTypeEqual(Type* other)\n\t{\n\t\tif(other->kind != TypeKind::Struct)\n\t\t\treturn false;\n\n\t\treturn (this->structName == other->toStructType()->structName) && (this->isTypePacked == other->toStructType()->isTypePacked);\n\t}\n\n\n\n\t// struct stuff\n\tName StructType::getTypeName()\n\t{\n\t\treturn this->structName;\n\t}\n\n\tsize_t StructType::getElementCount()\n\t{\n\t\treturn this->typeList.size();\n\t}\n\n\tType* StructType::getElementN(size_t n)\n\t{\n\t\ticeAssert(n < this->typeList.size() && \"out of bounds\");\n\n\t\treturn this->typeList[n];\n\t}\n\n\tType* StructType::getElement(const std::string& name)\n\t{\n\t\ticeAssert(this->structMembers.find(name) != this->structMembers.end() && \"no such member\");\n\n\t\treturn this->structMembers[name];\n\t}\n\n\tsize_t StructType::getElementIndex(const std::string& name)\n\t{\n\t\ticeAssert(this->structMembers.find(name) != this->structMembers.end() && \"no such member\");\n\n\t\treturn this->indexMap[name];\n\t}\n\n\tbool StructType::hasElementWithName(const std::string& name)\n\t{\n\t\treturn this->indexMap.find(name) != this->indexMap.end();\n\t}\n\n\tconst std::vector<Type*>& StructType::getElements()\n\t{\n\t\treturn this->typeList;\n\t}\n\n\tvoid StructType::addTraitImpl(TraitType* trt)\n\t{\n\t\tif(zfu::contains(this->implTraits, trt))\n\t\t\terror(\"'%s' already implements trait '%s'\", this, trt);\n\n\t\tthis->implTraits.push_back(trt);\n\t}\n\n\tbool StructType::implementsTrait(TraitType* trt)\n\t{\n\t\treturn zfu::contains(this->implTraits, trt);\n\t}\n\n\tstd::vector<TraitType*> StructType::getImplementedTraits()\n\t{\n\t\treturn this->implTraits;\n\t}\n\n\tconst util::hash_map<std::string, size_t>& StructType::getIndexMap()\n\t{\n\t\treturn this->indexMap;\n\t}\n\n\n\tvoid StructType::setBody(const std::vector<std::pair<std::string, Type*>>& members)\n\t{\n\t\tsize_t i = 0;\n\t\tfor(const auto& [ name, ty ] : members)\n\t\t{\n\t\t\tthis->structMembers[name] = ty;\n\t\t\tthis->indexMap[name] = i;\n\t\t\tthis->typeList.push_back(ty);\n\n\t\t\ti++;\n\t\t}\n\t}\n\n\tfir::Type* StructType::substitutePlaceholders(const util::hash_map<fir::Type*, fir::Type*>& subst)\n\t{\n\t\tif(this->containsPlaceholders())\n\t\t\terror(\"not supported!\");\n\n\t\treturn this;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/Types/TraitType.cpp",
    "content": "// TraitType.cpp\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n\n#include \"errors.h\"\n#include \"ir/type.h\"\n\n#include \"pts.h\"\n\nnamespace fir\n{\n\t// structs\n\tTraitType::TraitType(const Name& name,  const std::vector<std::pair<std::string, FunctionType*>>& meths)\n\t\t: Type(TypeKind::Trait), traitName(name)\n\t{\n\t\tthis->methods = meths;\n\t}\n\n\tstatic util::hash_map<Name, TraitType*> typeCache;\n\tTraitType* TraitType::create(const Name& name)\n\t{\n\t\tif(auto it = typeCache.find(name); it != typeCache.end())\n\t\t\terror(\"trait with name '%s' already exists\", name.str());\n\n\t\telse\n\t\t\treturn (typeCache[name] = new TraitType(name, { }));\n\t}\n\n\n\n\n\n\t// various\n\tstd::string TraitType::str()\n\t{\n\t\treturn \"trait(\" + this->traitName.name + \")\";\n\t}\n\n\tstd::string TraitType::encodedStr()\n\t{\n\t\treturn this->traitName.str();\n\t}\n\n\n\tbool TraitType::isTypeEqual(Type* other)\n\t{\n\t\tif(other->kind != TypeKind::Struct)\n\t\t\treturn false;\n\n\t\treturn (this->traitName == other->toTraitType()->traitName);\n\t}\n\n\n\n\t// struct stuff\n\tName TraitType::getTypeName()\n\t{\n\t\treturn this->traitName;\n\t}\n\n\tsize_t TraitType::getMethodCount()\n\t{\n\t\treturn this->methods.size();\n\t}\n\n\tconst std::vector<std::pair<std::string, FunctionType*>>& TraitType::getMethods()\n\t{\n\t\treturn this->methods;\n\t}\n\n\tvoid TraitType::setMethods(const std::vector<std::pair<std::string, FunctionType*>>& meths)\n\t{\n\t\tthis->methods = meths;\n\t}\n\n\tfir::Type* TraitType::substitutePlaceholders(const util::hash_map<fir::Type*, fir::Type*>& subst)\n\t{\n\t\tif(this->containsPlaceholders())\n\t\t\terror(\"not supported!\");\n\n\t\treturn this;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/Types/TupleType.cpp",
    "content": "// TupleType.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"errors.h\"\n#include \"ir/type.h\"\n\nnamespace fir\n{\n\tTupleType::TupleType(const std::vector<Type*>& mems) : Type(TypeKind::Tuple)\n\t{\n\t\tthis->members = mems;\n\t}\n\n\tsize_t TupleType::getElementCount()\n\t{\n\t\treturn this->members.size();\n\t}\n\n\tType* TupleType::getElementN(size_t n)\n\t{\n\t\ticeAssert(n < this->members.size());\n\t\treturn this->members[n];\n\t}\n\n\tconst std::vector<Type*>& TupleType::getElements()\n\t{\n\t\treturn this->members;\n\t}\n\n\n\tstd::string TupleType::str()\n\t{\n\t\treturn strprintf(\"(%s)\", typeListToString(this->members));\n\t}\n\n\tstd::string TupleType::encodedStr()\n\t{\n\t\treturn strprintf(\"(%s)\", typeListToString(this->members));\n\t}\n\n\tbool TupleType::isTypeEqual(Type* other)\n\t{\n\t\tif(other->kind != TypeKind::Tuple)\n\t\t\treturn false;\n\n\t\tauto ot = other->toTupleType();\n\t\treturn areTypeListsEqual(this->members, ot->members);\n\t}\n\n\n\n\tTupleType* TupleType::get(const std::vector<Type*>& mems)\n\t{\n\t\treturn TypeCache::get().getOrAddCachedType(new TupleType(mems));\n\t}\n\n\tTupleType* TupleType::get(const std::initializer_list<Type*>& mems)\n\t{\n\t\treturn TupleType::get(std::vector<Type*>(mems.begin(), mems.end()));\n\t}\n\n\tfir::Type* TupleType::substitutePlaceholders(const util::hash_map<fir::Type*, fir::Type*>& subst)\n\t{\n\t\tauto args = zfu::map(this->members, [&subst](auto t) -> auto { return t->substitutePlaceholders(subst); });\n\n\t\treturn TupleType::get(members);\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/Types/Type.cpp",
    "content": "// Type.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"errors.h\"\n#include \"ir/type.h\"\n\n#include \"gluecode.h\"\n\nnamespace pts\n{\n\tstd::string unwrapPointerType(const std::string&, int*);\n}\n\nnamespace fir\n{\n\tstatic TypeCache tc;\n\tTypeCache& TypeCache::get()\n\t{\n\t\treturn tc;\n\t}\n\n\n\tstatic size_t nativeWordSize = 64;\n\tvoid setNativeWordSizeInBits(size_t sz)\n\t{\n\t\tif(sz < 8 || sz > 64)\n\t\t\terror(\"native word size must be >= 8 and < 64, %d invalid\", sz);\n\n\t\t// we're not gonna check any further, anything becomes your problem once you change this.\n\t\tnativeWordSize = sz;\n\t}\n\n\tsize_t getNativeWordSizeInBits()\n\t{\n\t\treturn nativeWordSize;\n\t}\n\n\n\n\tint getCastDistance(Type* from, Type* to)\n\t{\n\t\tif(from == to) return 0;\n\n\t\tif(from->isConstantNumberType() && to->isPrimitiveType())\n\t\t{\n\t\t\tauto cty = from->toConstantNumberType();\n\t\t\tif(!cty->isFloating() && to->isIntegerType())\n\t\t\t\treturn 0;\n\n\t\t\telse if(!cty->isFloating() && to->isFloatingPointType())\n\t\t\t\treturn 1;\n\n\t\t\telse if(cty->isFloating())      // not isint means isfloat, so if we're doing float -> float the cost is 0\n\t\t\t\treturn 0;\n\n\t\t\telse                            // if we reach here, we're trying to do float -> int, which is a no-go.\n\t\t\t\treturn -1;\n\t\t}\n\t\telse if(from->isIntegerType() && to->isIntegerType())\n\t\t{\n\t\t\tif(from->isSignedIntType() == to->isSignedIntType())\n\t\t\t{\n\t\t\t\tauto bitdiff = std::abs(static_cast<int>(from->toPrimitiveType()->getIntegerBitWidth())\n\t\t\t\t\t- static_cast<int>(to->toPrimitiveType()->getIntegerBitWidth()));\n\n\t\t\t\tswitch(bitdiff)\n\t\t\t\t{\n\t\t\t\t\tcase 0:\t\treturn 0;\t// same\n\t\t\t\t\tcase 8:\t\treturn 1;\t// i16 - i8\n\t\t\t\t\tcase 16:\treturn 1;\t// i32 - i16\n\t\t\t\t\tcase 32:\treturn 1;\t// i64 - i32\n\n\t\t\t\t\tcase 24:\treturn 2;\t// i32 - i8\n\t\t\t\t\tcase 48:\treturn 2;\t// i64 - i16\n\n\t\t\t\t\tcase 56:\treturn 3;\t// i64 - i8\n\t\t\t\t\tdefault:\ticeAssert(0);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// only allow casting unsigned things to signed things... maybe??\n\t\t\t\t// TODO: investigate whether we want such loose casting.\n\n\t\t\t\t//? for now, no.\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t\telse if(from->isDynamicArrayType() && to->isArraySliceType() && from->getArrayElementType() == to->getArrayElementType())\n\t\t{\n\t\t\treturn 2;\n\t\t}\n\t\telse if(from->isDynamicArrayType() && from->getArrayElementType()->isVoidType() && (to->isDynamicArrayType() || to->isArraySliceType() || to->isArrayType()))\n\t\t{\n\t\t\treturn 2;\n\t\t}\n\t\telse if(from->isFloatingPointType() && to->isFloatingPointType())\n\t\t{\n\t\t\treturn 1;\n\t\t}\n\t\telse if(from->isStringType() && to == fir::Type::getInt8Ptr())\n\t\t{\n\t\t\treturn 5;\n\t\t}\n\t\telse if(from->isStringType() && to->isCharSliceType())\n\t\t{\n\t\t\treturn 3;\n\t\t}\n\t\telse if(from->isCharSliceType() && to == fir::Type::getInt8Ptr())\n\t\t{\n\t\t\treturn 3;\n\t\t}\n\t\telse if(from->isMutablePointer() && to->isImmutablePointer() && from->getPointerElementType() == to->getPointerElementType())\n\t\t{\n\t\t\t// cast from a mutable pointer type to an immutable one can be implicit.\n\t\t\treturn 1;\n\t\t}\n\t\telse if(from->isVariadicArrayType() && to->isArraySliceType() && from->getArrayElementType() == to->getArrayElementType())\n\t\t{\n\t\t\t// allow implicit casting from variadic slices to their normal counterparts.\n\t\t\treturn 4;\n\t\t}\n\t\telse if(from->isArraySliceType() && to->isArraySliceType() && (from->getArrayElementType() == to->getArrayElementType())\n\t\t\t&& from->toArraySliceType()->isMutable() && !to->toArraySliceType()->isMutable() && !from->isVariadicArrayType() && !to->isVariadicArrayType())\n\t\t{\n\t\t\t// same with slices -- cast from mutable slice to immut slice can be implicit.\n\t\t\treturn 1;\n\t\t}\n\t\t//* note: we don't need to check that 'to' is a class type, because if it's not then the parent check will fail anyway.\n\t\telse if(from->isPointerType() && to->isPointerType() && from->getPointerElementType()->isClassType()\n\t\t\t&& from->getPointerElementType()->toClassType()->hasParent(to->getPointerElementType()))\n\t\t{\n\t\t\t// cast from a derived class pointer to a base class pointer\n\t\t\treturn 2;\n\t\t}\n\t\telse if(from->isNullType() && to->isPointerType())\n\t\t{\n\t\t\treturn 1;\n\t\t}\n\t\telse if(from->isTupleType() && to->isTupleType() && from->toTupleType()->getElementCount() == to->toTupleType()->getElementCount())\n\t\t{\n\t\t\tint sum = 0;\n\n\t\t\tauto ftt = from->toTupleType();\n\t\t\tauto ttt = to->toTupleType();\n\n\t\t\tfor(size_t i = 0; i < ttt->getElementCount(); i++)\n\t\t\t{\n\t\t\t\tif(int k = fir::getCastDistance(ftt->getElementN(i), ttt->getElementN(i)); k < 0)\n\t\t\t\t\treturn -1;\n\n\t\t\t\telse\n\t\t\t\t\tsum += k;\n\t\t\t}\n\n\t\t\treturn sum;\n\t\t}\n\t\telse if(to->isAnyType())\n\t\t{\n\t\t\t// lol. completely arbitrary.\n\t\t\treturn 15;\n\t\t}\n\n\t\treturn -1;\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tPrimitiveType* Type::getNativeWord()\n\t{\n\t\treturn PrimitiveType::getIntN(nativeWordSize);\n\t}\n\n\tPrimitiveType* Type::getNativeUWord()\n\t{\n\t\treturn PrimitiveType::getUintN(nativeWordSize);\n\t}\n\n\tPointerType* Type::getNativeWordPtr()\n\t{\n\t\treturn Type::getNativeWord()->getPointerTo()->toPointerType();\n\t}\n\n\tstd::string Type::typeListToString(const std::initializer_list<Type*>& types, bool includeBraces)\n\t{\n\t\treturn typeListToString(std::vector<Type*>(types.begin(), types.end()), includeBraces);\n\t}\n\n\tstd::string Type::typeListToString(const std::vector<Type*>& types, bool braces)\n\t{\n\t\t// print types\n\t\tstd::string str = (braces ? \"{ \" : \"\");\n\t\tfor(auto t : types)\n\t\t\tstr += t->str() + \", \";\n\n\t\tif(str.length() > 2)\n\t\t\tstr = str.substr(0, str.length() - 2);\n\n\t\treturn str + (braces ? \" }\" : \"\");\n\t}\n\n\n\tbool Type::areTypeListsEqual(const std::vector<Type*>& a, const std::vector<Type*>& b)\n\t{\n\t\tif(a.size() != b.size()) return false;\n\t\tif(a.size() == 0 && b.size() == 0) return true;\n\n\t\tfor(size_t i = 0; i < a.size(); i++)\n\t\t{\n\t\t\tif(a[i] != b[i])\n\t\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tbool Type::areTypeListsEqual(const std::initializer_list<Type*>& a, const std::initializer_list<Type*>& b)\n\t{\n\t\treturn areTypeListsEqual(std::vector<Type*>(a.begin(), a.end()), std::vector<Type*>(b.begin(), b.end()));\n\t}\n\n\n\n\tType* Type::getPointerTo()\n\t{\n\t\t// cache the pointer internally\n\t\tif(!this->pointerTo)\n\t\t{\n\t\t\tPointerType* newType = new PointerType(this, false);\n\t\t\tthis->pointerTo = newType;\n\t\t}\n\n\t\treturn this->pointerTo;\n\t}\n\n\tType* Type::getMutablePointerTo()\n\t{\n\t\t// cache the pointer internally\n\t\tif(!this->mutablePointerTo)\n\t\t{\n\t\t\tPointerType* newType = new PointerType(this, true);\n\t\t\tthis->mutablePointerTo = newType;\n\t\t}\n\n\t\treturn this->mutablePointerTo;\n\t}\n\n\n\tType* Type::getMutablePointerVersion()\n\t{\n\t\ticeAssert(this->isPointerType() && \"not pointer type\");\n\t\treturn this->toPointerType()->getMutable();\n\t}\n\n\tType* Type::getImmutablePointerVersion()\n\t{\n\t\ticeAssert(this->isPointerType() && \"not pointer type\");\n\t\treturn this->toPointerType()->getImmutable();\n\t}\n\n\n\tType* Type::getPointerElementType()\n\t{\n\t\tif(!this->isPointerType())\n\t\t\terror(\"type is not a pointer ('%s')\", this);\n\n\t\tPointerType* ptrthis = this->toPointerType();\n\t\ticeAssert(ptrthis);\n\n\t\t// ptrthis could only have been obtained by calling getPointerTo\n\t\t// on an already normalised type, so this should not be needed\n\t\t// newType = tc->normaliseType(newType);\n\n\t\treturn ptrthis->baseType;\n\t}\n\n\n\tType* Type::getIndirectedType(int times)\n\t{\n\t\tType* ret = this;\n\t\tif(times > 0)\n\t\t{\n\t\t\tfor(int i = 0; i < times; i++)\n\t\t\t\tret = ret->getPointerTo();\n\t\t}\n\t\telse if(times < 0)\n\t\t{\n\t\t\tfor(int i = 0; i < -times; i++)\n\t\t\t\tret = ret->getPointerElementType();\n\t\t}\n\t\t// both getPointerTo and getPointerElementType should already\n\t\t// return normalised types\n\t\t// ret = tc->normaliseType(ret);\n\t\treturn ret;\n\t}\n\n\n\tType* Type::fromBuiltin(const std::string& builtin)\n\t{\n\n\t\tint indirections = 0;\n\t\tauto copy = pts::unwrapPointerType(builtin, &indirections);\n\n\t\tType* real = 0;\n\n\t\tif(copy == INT8_TYPE_STRING)                    real = Type::getInt8();\n\t\telse if(copy == INT16_TYPE_STRING)              real = Type::getInt16();\n\t\telse if(copy == INT32_TYPE_STRING)              real = Type::getInt32();\n\t\telse if(copy == INT64_TYPE_STRING)              real = Type::getInt64();\n\t\telse if(copy == INT128_TYPE_STRING)             real = Type::getInt128();\n\n\t\telse if(copy == UINT8_TYPE_STRING)              real = Type::getUint8();\n\t\telse if(copy == UINT16_TYPE_STRING)             real = Type::getUint16();\n\t\telse if(copy == UINT32_TYPE_STRING)             real = Type::getUint32();\n\t\telse if(copy == UINT64_TYPE_STRING)             real = Type::getUint64();\n\t\telse if(copy == UINT128_TYPE_STRING)            real = Type::getUint128();\n\n\t\telse if(copy == FLOAT32_TYPE_STRING)            real = Type::getFloat32();\n\t\telse if(copy == FLOAT64_TYPE_STRING)            real = Type::getFloat64();\n\t\telse if(copy == FLOAT128_TYPE_STRING)           real = Type::getFloat128();\n\n\t\telse if(copy == STRING_TYPE_STRING)             real = Type::getString();\n\n\t\telse if(copy == CHARACTER_SLICE_TYPE_STRING)    real = ArraySliceType::get(Type::getInt8(), false);\n\n\t\telse if(copy == BOOL_TYPE_STRING)               real = Type::getBool();\n\t\telse if(copy == VOID_TYPE_STRING)               real = Type::getVoid();\n\n\t\t// unspecified things\n\t\telse if(copy == INTUNSPEC_TYPE_STRING)          real = Type::getNativeWord();\n\t\telse if(copy == UINTUNSPEC_TYPE_STRING)         real = Type::getNativeUWord();\n\n\t\telse if(copy == FLOAT_TYPE_STRING)              real = Type::getFloat32();\n\t\telse if(copy == DOUBLE_TYPE_STRING)             real = Type::getFloat64();\n\n\t\telse if(copy == ANY_TYPE_STRING)                real = Type::getAny();\n\n\t\telse return 0;\n\n\t\ticeAssert(real);\n\n\t\treal = real->getIndirectedType(indirections);\n\t\treturn real;\n\t}\n\n\n\n\tType* Type::getArrayElementType()\n\t{\n\t\tif(this->isDynamicArrayType())\t\treturn this->toDynamicArrayType()->getElementType();\n\t\telse if(this->isArrayType())\t\treturn this->toArrayType()->getElementType();\n\t\telse if(this->isArraySliceType())\treturn this->toArraySliceType()->getElementType();\n\t\telse\t\t\t\t\t\t\t\terror(\"'%s' is not an array type\", this);\n\t}\n\n\n\n\tsize_t Type::getBitWidth()\n\t{\n\t\tif(this->isIntegerType())\n\t\t\treturn this->toPrimitiveType()->getIntegerBitWidth();\n\n\t\telse if(this->isFloatingPointType())\n\t\t\treturn this->toPrimitiveType()->getFloatingPointBitWidth();\n\n\t\telse if(this->isPointerType())\n\t\t\treturn sizeof(void*) * CHAR_BIT;\n\n\t\telse\n\t\t\treturn 0;\n\t}\n\n\n\tstatic bool _containsPlaceholders(fir::Type* ty, std::unordered_set<fir::Type*>& seen, std::vector<PolyPlaceholderType*>* found)\n\t{\n\t\tif(seen.find(ty) != seen.end())\n\t\t\treturn false;\n\n\t\tseen.insert(ty);\n\n\t\tif(ty->isPolyPlaceholderType())\n\t\t{\n\t\t\tif(found) found->push_back(ty->toPolyPlaceholderType());\n\t\t\treturn true;\n\t\t}\n\t\telse if(ty->isPointerType())        return _containsPlaceholders(ty->getPointerElementType(), seen, found);\n\t\telse if(ty->isArrayType())          return _containsPlaceholders(ty->getArrayElementType(), seen, found);\n\t\telse if(ty->isArraySliceType())     return _containsPlaceholders(ty->getArrayElementType(), seen, found);\n\t\telse if(ty->isDynamicArrayType())   return _containsPlaceholders(ty->getArrayElementType(), seen, found);\n\t\telse if(ty->isArrayType())          return _containsPlaceholders(ty->getArrayElementType(), seen, found);\n\t\telse if(ty->isUnionVariantType())   return _containsPlaceholders(ty->toUnionVariantType()->getInteriorType(), seen, found);\n\t\telse if(ty->isTupleType())\n\t\t{\n\t\t\tbool res = false;\n\t\t\tfor(auto t : ty->toTupleType()->getElements())\n\t\t\t\tres |= _containsPlaceholders(t, seen, found);\n\n\t\t\treturn res;\n\t\t}\n\t\telse if(ty->isClassType())\n\t\t{\n\t\t\tbool res = false;\n\t\t\tfor(auto t : ty->toClassType()->getElements())\n\t\t\t\tres |= _containsPlaceholders(t, seen, found);\n\n\t\t\treturn res;\n\t\t}\n\t\telse if(ty->isStructType())\n\t\t{\n\t\t\tbool res = false;\n\t\t\tfor(auto t : ty->toStructType()->getElements())\n\t\t\t\tres |= _containsPlaceholders(t, seen, found);\n\n\t\t\treturn res;\n\t\t}\n\t\telse if(ty->isFunctionType())\n\t\t{\n\t\t\tbool res = ty->toFunctionType()->getReturnType()->containsPlaceholders();\n\t\t\tfor(auto t : ty->toFunctionType()->getArgumentTypes())\n\t\t\t\tres |= _containsPlaceholders(t, seen, found);\n\n\t\t\treturn res;\n\t\t}\n\t\telse if(ty->isUnionType())\n\t\t{\n\t\t\tbool res = false;\n\t\t\tfor(const auto& t : ty->toUnionType()->getVariants())\n\t\t\t\tres |= _containsPlaceholders(t.second, seen, found);\n\n\t\t\treturn res;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\n\t// better to just handle this centrally i guess.\n\tbool Type::containsPlaceholders()\n\t{\n\t\tstd::unordered_set<fir::Type*> seen;\n\t\treturn _containsPlaceholders(this, seen, nullptr);\n\t}\n\n\tstd::vector<PolyPlaceholderType*> Type::getContainedPlaceholders()\n\t{\n\t\tstd::unordered_set<fir::Type*> seen;\n\t\tstd::vector<PolyPlaceholderType*> found;\n\n\t\t_containsPlaceholders(this, seen, &found);\n\t\treturn found;\n\t}\n\n\n\n\tbool Type::isPointerTo(Type* other)\n\t{\n\t\treturn other->getPointerTo() == this;\n\t}\n\n\tbool Type::isPointerElementOf(Type* other)\n\t{\n\t\treturn this->getPointerTo() == other;\n\t}\n\n\tPrimitiveType* Type::toPrimitiveType()\n\t{\n\t\tif(this->kind != TypeKind::Primitive) error(\"not primitive type\");\n\t\treturn static_cast<PrimitiveType*>(this);\n\t}\n\n\tFunctionType* Type::toFunctionType()\n\t{\n\t\tif(this->kind != TypeKind::Function) error(\"not function type\");\n\t\treturn static_cast<FunctionType*>(this);\n\t}\n\n\tPointerType* Type::toPointerType()\n\t{\n\t\tif(this->kind != TypeKind::Pointer) error(\"not pointer type\");\n\t\treturn static_cast<PointerType*>(this);\n\t}\n\n\tStructType* Type::toStructType()\n\t{\n\t\tif(this->kind != TypeKind::Struct) error(\"not struct type\");\n\t\treturn static_cast<StructType*>(this);\n\t}\n\n\tClassType* Type::toClassType()\n\t{\n\t\tif(this->kind != TypeKind::Class) error(\"not class type\");\n\t\treturn static_cast<ClassType*>(this);\n\t}\n\n\tTupleType* Type::toTupleType()\n\t{\n\t\tif(this->kind != TypeKind::Tuple) error(\"not tuple type\");\n\t\treturn static_cast<TupleType*>(this);\n\t}\n\n\tArrayType* Type::toArrayType()\n\t{\n\t\tif(this->kind != TypeKind::Array) error(\"not array type\");\n\t\treturn static_cast<ArrayType*>(this);\n\t}\n\n\tDynamicArrayType* Type::toDynamicArrayType()\n\t{\n\t\tif(this->kind != TypeKind::DynamicArray) error(\"not dynamic array type\");\n\t\treturn static_cast<DynamicArrayType*>(this);\n\t}\n\n\tArraySliceType* Type::toArraySliceType()\n\t{\n\t\tif(this->kind != TypeKind::ArraySlice) error(\"not array slice type\");\n\t\treturn static_cast<ArraySliceType*>(this);\n\t}\n\n\tRangeType* Type::toRangeType()\n\t{\n\t\tif(this->kind != TypeKind::Range) error(\"not range type\");\n\t\treturn static_cast<RangeType*>(this);\n\t}\n\n\tStringType* Type::toStringType()\n\t{\n\t\tif(this->kind != TypeKind::String) error(\"not string type\");\n\t\treturn static_cast<StringType*>(this);\n\t}\n\n\tEnumType* Type::toEnumType()\n\t{\n\t\tif(this->kind != TypeKind::Enum) error(\"not enum type\");\n\t\treturn static_cast<EnumType*>(this);\n\t}\n\n\tUnionType* Type::toUnionType()\n\t{\n\t\tif(this->kind != TypeKind::Union) error(\"not union type\");\n\t\treturn static_cast<UnionType*>(this);\n\t}\n\n\tRawUnionType* Type::toRawUnionType()\n\t{\n\t\tif(this->kind != TypeKind::RawUnion) error(\"not raw union type\");\n\t\treturn static_cast<RawUnionType*>(this);\n\t}\n\n\tAnyType* Type::toAnyType()\n\t{\n\t\tif(this->kind != TypeKind::Any) error(\"not any type\");\n\t\treturn static_cast<AnyType*>(this);\n\t}\n\n\tNullType* Type::toNullType()\n\t{\n\t\tif(this->kind != TypeKind::Null) error(\"not null type\");\n\t\treturn static_cast<NullType*>(this);\n\t}\n\n\tConstantNumberType* Type::toConstantNumberType()\n\t{\n\t\tif(this->kind != TypeKind::ConstantNumber) error(\"not constant number type\");\n\t\treturn static_cast<ConstantNumberType*>(this);\n\t}\n\n\tPolyPlaceholderType* Type::toPolyPlaceholderType()\n\t{\n\t\tif(this->kind != TypeKind::PolyPlaceholder) error(\"not poly placeholder type\");\n\t\treturn static_cast<PolyPlaceholderType*>(this);\n\t}\n\n\tUnionVariantType* Type::toUnionVariantType()\n\t{\n\t\tif(this->kind != TypeKind::UnionVariant) error(\"not union variant type\");\n\t\treturn static_cast<UnionVariantType*>(this);\n\t}\n\n\tOpaqueType* Type::toOpaqueType()\n\t{\n\t\tif(this->kind != TypeKind::Opaque) error(\"not opaque type\");\n\t\treturn static_cast<OpaqueType*>(this);\n\t}\n\n\tTraitType* Type::toTraitType()\n\t{\n\t\tif(this->kind != TypeKind::Trait) error(\"not trait type\");\n\t\treturn static_cast<TraitType*>(this);\n\t}\n\n\n\n\n\n\n\n\n\tbool Type::isConstantNumberType()\n\t{\n\t\treturn this->kind == TypeKind::ConstantNumber;\n\t}\n\n\tbool Type::isStructType()\n\t{\n\t\treturn this->kind == TypeKind::Struct;\n\t}\n\n\tbool Type::isTupleType()\n\t{\n\t\treturn this->kind == TypeKind::Tuple;\n\t}\n\n\tbool Type::isClassType()\n\t{\n\t\treturn this->kind == TypeKind::Class;\n\t}\n\n\tbool Type::isPackedStruct()\n\t{\n\t\treturn this->isStructType() && (this->toStructType()->isTypePacked);\n\t}\n\n\tbool Type::isArrayType()\n\t{\n\t\treturn this->kind == TypeKind::Array;\n\t}\n\n\tbool Type::isFloatingPointType()\n\t{\n\t\treturn this->kind == TypeKind::Primitive && (this->toPrimitiveType()->primKind == PrimitiveType::Kind::Floating);\n\t}\n\n\tbool Type::isIntegerType()\n\t{\n\t\treturn this->kind == TypeKind::Primitive && (this->toPrimitiveType()->primKind == PrimitiveType::Kind::Integer);\n\t}\n\n\tbool Type::isSignedIntType()\n\t{\n\t\treturn this->isIntegerType() && this->toPrimitiveType()->isSigned();\n\t}\n\n\tbool Type::isUnsignedIntType()\n\t{\n\t\treturn this->isIntegerType() && !this->toPrimitiveType()->isSigned();\n\t}\n\n\tbool Type::isFunctionType()\n\t{\n\t\treturn this->kind == TypeKind::Function;\n\t}\n\n\tbool Type::isPrimitiveType()\n\t{\n\t\treturn this->kind == TypeKind::Primitive;\n\t}\n\n\tbool Type::isPointerType()\n\t{\n\t\treturn this->kind == TypeKind::Pointer;\n\t}\n\n\tbool Type::isVoidType()\n\t{\n\t\treturn this->kind == TypeKind::Void;\n\t}\n\n\tbool Type::isDynamicArrayType()\n\t{\n\t\treturn this->kind == TypeKind::DynamicArray;\n\t}\n\n\tbool Type::isVariadicArrayType()\n\t{\n\t\treturn this->isArraySliceType() && this->toArraySliceType()->isVariadicType();\n\t}\n\n\tbool Type::isArraySliceType()\n\t{\n\t\treturn this->kind == TypeKind::ArraySlice;\n\t}\n\n\tbool Type::isRangeType()\n\t{\n\t\treturn this->kind == TypeKind::Range;\n\t}\n\n\tbool Type::isStringType()\n\t{\n\t\treturn this->kind == TypeKind::String;\n\t}\n\n\tbool Type::isCharType()\n\t{\n\t\treturn this == fir::Type::getInt8();\n\t}\n\n\tbool Type::isEnumType()\n\t{\n\t\treturn this->kind == TypeKind::Enum;\n\t}\n\n\tbool Type::isUnionType()\n\t{\n\t\treturn this->kind == TypeKind::Union;\n\t}\n\n\tbool Type::isRawUnionType()\n\t{\n\t\treturn this->kind == TypeKind::RawUnion;\n\t}\n\n\tbool Type::isAnyType()\n\t{\n\t\treturn this->kind == TypeKind::Any;\n\t}\n\n\tbool Type::isNullType()\n\t{\n\t\treturn this->kind == TypeKind::Null;\n\t}\n\n\tbool Type::isBoolType()\n\t{\n\t\treturn this == fir::Type::getBool();\n\t}\n\n\tbool Type::isMutablePointer()\n\t{\n\t\treturn this->isPointerType() && this->toPointerType()->isMutable();\n\t}\n\n\tbool Type::isImmutablePointer()\n\t{\n\t\treturn this->isPointerType() && !this->toPointerType()->isMutable();\n\t}\n\n\tbool Type::isCharSliceType()\n\t{\n\t\treturn this->isArraySliceType() && this->getArrayElementType() == fir::Type::getInt8();\n\t}\n\n\tbool Type::isPolyPlaceholderType()\n\t{\n\t\treturn this->kind == TypeKind::PolyPlaceholder;\n\t}\n\n\tbool Type::isUnionVariantType()\n\t{\n\t\treturn this->kind == TypeKind::UnionVariant;\n\t}\n\n\tbool Type::isOpaqueType()\n\t{\n\t\treturn this->kind == TypeKind::Opaque;\n\t}\n\n\tbool Type::isTraitType()\n\t{\n\t\treturn this->kind == TypeKind::Trait;\n\t}\n\n\n\t// static getting functions\n\tVoidType* Type::getVoid()\n\t{\n\t\treturn VoidType::get();\n\t}\n\n\tNullType* Type::getNull()\n\t{\n\t\treturn NullType::get();\n\t}\n\n\tType* Type::getVoidPtr()\n\t{\n\t\treturn VoidType::get()->getPointerTo();\n\t}\n\n\tBoolType* Type::getBool()\n\t{\n\t\treturn BoolType::get();\n\t}\n\n\tPrimitiveType* Type::getInt8()\n\t{\n\t\treturn PrimitiveType::getInt8();\n\t}\n\n\tPrimitiveType* Type::getInt16()\n\t{\n\t\treturn PrimitiveType::getInt16();\n\t}\n\n\tPrimitiveType* Type::getInt32()\n\t{\n\t\treturn PrimitiveType::getInt32();\n\t}\n\n\tPrimitiveType* Type::getInt64()\n\t{\n\t\treturn PrimitiveType::getInt64();\n\t}\n\n\tPrimitiveType* Type::getInt128()\n\t{\n\t\treturn PrimitiveType::getInt128();\n\t}\n\n\tPrimitiveType* Type::getUint8()\n\t{\n\t\treturn PrimitiveType::getUint8();\n\t}\n\n\tPrimitiveType* Type::getUint16()\n\t{\n\t\treturn PrimitiveType::getUint16();\n\t}\n\n\tPrimitiveType* Type::getUint32()\n\t{\n\t\treturn PrimitiveType::getUint32();\n\t}\n\n\tPrimitiveType* Type::getUint64()\n\t{\n\t\treturn PrimitiveType::getUint64();\n\t}\n\n\tPrimitiveType* Type::getUint128()\n\t{\n\t\treturn PrimitiveType::getUint128();\n\t}\n\n\tPrimitiveType* Type::getFloat32()\n\t{\n\t\treturn PrimitiveType::getFloat32();\n\t}\n\n\tPrimitiveType* Type::getFloat64()\n\t{\n\t\treturn PrimitiveType::getFloat64();\n\t}\n\n\tPrimitiveType* Type::getFloat128()\n\t{\n\t\treturn PrimitiveType::getFloat128();\n\t}\n\n\n\tPointerType* Type::getInt8Ptr()\n\t{\n\t\treturn PointerType::getInt8Ptr();\n\t}\n\n\tPointerType* Type::getInt16Ptr()\n\t{\n\t\treturn PointerType::getInt16Ptr();\n\t}\n\n\tPointerType* Type::getInt32Ptr()\n\t{\n\t\treturn PointerType::getInt32Ptr();\n\t}\n\n\tPointerType* Type::getInt64Ptr()\n\t{\n\t\treturn PointerType::getInt64Ptr();\n\t}\n\n\tPointerType* Type::getInt128Ptr()\n\t{\n\t\treturn PointerType::getInt128Ptr();\n\t}\n\n\tPointerType* Type::getUint8Ptr()\n\t{\n\t\treturn PointerType::getUint8Ptr();\n\t}\n\n\tPointerType* Type::getUint16Ptr()\n\t{\n\t\treturn PointerType::getUint16Ptr();\n\t}\n\n\tPointerType* Type::getUint32Ptr()\n\t{\n\t\treturn PointerType::getUint32Ptr();\n\t}\n\n\tPointerType* Type::getUint64Ptr()\n\t{\n\t\treturn PointerType::getUint64Ptr();\n\t}\n\n\tPointerType* Type::getUint128Ptr()\n\t{\n\t\treturn PointerType::getUint128Ptr();\n\t}\n\n\n\n\n\tPointerType* Type::getMutInt8Ptr()\n\t{\n\t\treturn PointerType::getInt8Ptr()->getMutable();\n\t}\n\n\tPointerType* Type::getMutInt16Ptr()\n\t{\n\t\treturn PointerType::getInt16Ptr()->getMutable();\n\t}\n\n\tPointerType* Type::getMutInt32Ptr()\n\t{\n\t\treturn PointerType::getInt32Ptr()->getMutable();\n\t}\n\n\tPointerType* Type::getMutInt64Ptr()\n\t{\n\t\treturn PointerType::getInt64Ptr()->getMutable();\n\t}\n\n\tPointerType* Type::getMutInt128Ptr()\n\t{\n\t\treturn PointerType::getInt128Ptr()->getMutable();\n\t}\n\n\tPointerType* Type::getMutUint8Ptr()\n\t{\n\t\treturn PointerType::getUint8Ptr()->getMutable();\n\t}\n\n\tPointerType* Type::getMutUint16Ptr()\n\t{\n\t\treturn PointerType::getUint16Ptr()->getMutable();\n\t}\n\n\tPointerType* Type::getMutUint32Ptr()\n\t{\n\t\treturn PointerType::getUint32Ptr()->getMutable();\n\t}\n\n\tPointerType* Type::getMutUint64Ptr()\n\t{\n\t\treturn PointerType::getUint64Ptr()->getMutable();\n\t}\n\n\tPointerType* Type::getMutUint128Ptr()\n\t{\n\t\treturn PointerType::getUint128Ptr()->getMutable();\n\t}\n\n\n\n\n\n\tArraySliceType* Type::getCharSlice(bool mut)\n\t{\n\t\treturn ArraySliceType::get(fir::Type::getInt8(), mut);\n\t}\n\n\tRangeType* Type::getRange()\n\t{\n\t\treturn RangeType::get();\n\t}\n\n\tStringType* Type::getString()\n\t{\n\t\treturn StringType::get();\n\t}\n\n\tAnyType* Type::getAny()\n\t{\n\t\treturn AnyType::get();\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tstatic size_t getAggregateSize(const std::vector<Type*>& tys, bool packed = false)\n\t{\n\t\tsize_t ptr = 0;\n\t\tsize_t aln = 0;\n\n\t\tif(packed)\n\t\t{\n\t\t\t// gg\n\t\t\t// return util::foldl(0, tys, [](Type* a, Type* b) -> size_t {\n\t\t\t// \treturn getSizeOfType(a) + getSizeOfType(b);\n\t\t\t// });\n\n\t\t\tsize_t ret = 0;\n\t\t\tfor(const auto& t : tys)\n\t\t\t\tret += getSizeOfType(t);\n\n\t\t\treturn ret;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor(auto ty : tys)\n\t\t\t{\n\t\t\t\tauto a = getAlignmentOfType(ty);\n\t\t\t\ticeAssert(a > 0);\n\n\t\t\t\tif(ptr % a > 0)\n\t\t\t\t\tptr += (a - (ptr % a));\n\n\t\t\t\tptr += getSizeOfType(ty);\n\t\t\t\taln = std::max(aln, a);\n\t\t\t}\n\n\t\t\ticeAssert(aln > 0);\n\t\t\tif(ptr % aln > 0)\n\t\t\t\tptr += (aln - (ptr % aln));\n\n\t\t\treturn ptr;\n\t\t}\n\t}\n\n\tsize_t getSizeOfType(Type* type)\n\t{\n\t\tauto ptrt = fir::Type::getInt8Ptr();\n\t\tauto wordty = fir::Type::getNativeWord();\n\n\t\tif(type->isVoidType())                                      return 0;\n\t\telse if(type->isBoolType())                                 return 1;\n\t\telse if(type->isPrimitiveType())                            return type->getBitWidth() / 8;\n\t\telse if(type->isArraySliceType())                           return getAggregateSize({ ptrt, wordty });\n\t\telse if(type->isStringType() || type->isDynamicArrayType()) return getAggregateSize({ ptrt, wordty, wordty, ptrt });\n\t\telse if(type->isRangeType())                                return getAggregateSize({ wordty, wordty, wordty });\n\t\telse if(type->isPointerType() || type->isFunctionType() || type->isNullType())\n\t\t{\n\t\t\treturn getSizeOfType(wordty);\n\t\t}\n\t\telse if(type->isArrayType())\n\t\t{\n\t\t\treturn type->toArrayType()->getArraySize() * getSizeOfType(type->getArrayElementType());\n\t\t}\n\t\telse if(type->isEnumType())\n\t\t{\n\t\t\treturn getAggregateSize({ wordty, type->toEnumType()->getCaseType() });\n\t\t}\n\t\telse if(type->isAnyType())\n\t\t{\n\t\t\treturn getAggregateSize({ wordty, ptrt, fir::ArrayType::get(fir::Type::getInt8(), BUILTIN_ANY_DATA_BYTECOUNT) });\n\t\t}\n\t\telse if(type->isClassType() || type->isStructType() || type->isTupleType())\n\t\t{\n\t\t\tbool packed = false;\n\t\t\tstd::vector<Type*> tys;\n\n\t\t\tif(type->isClassType())\n\t\t\t{\n\t\t\t\ttys = type->toClassType()->getAllElementsIncludingBase();\n\t\t\t\ttys.insert(tys.begin(), fir::Type::getInt8Ptr());\n\t\t\t}\n\t\t\telse if(type->isStructType())\n\t\t\t{\n\t\t\t\tpacked = type->toStructType()->isPackedStruct();\n\t\t\t\ttys = type->toStructType()->getElements();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttys = type->toTupleType()->getElements();\n\t\t\t}\n\n\t\t\treturn getAggregateSize(tys, packed);\n\t\t}\n\t\telse if(type->isUnionType() )\n\t\t{\n\t\t\tauto ut = type->toUnionType();\n\n\t\t\tsize_t maxSz = 0;\n\t\t\tfor(auto v : ut->getVariants())\n\t\t\t{\n\t\t\t\tif(!v.second->getInteriorType()->isVoidType())\n\t\t\t\t\tmaxSz = std::max(maxSz, getSizeOfType(v.second->getInteriorType()));\n\t\t\t}\n\n\t\t\tif(maxSz > 0)\n\t\t\t{\n\t\t\t\treturn getAggregateSize({ wordty, ArrayType::get(Type::getInt8(), maxSz) });\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn getAggregateSize({ wordty });\n\t\t\t}\n\t\t}\n\t\telse if(type->isRawUnionType())\n\t\t{\n\t\t\tauto ut = type->toRawUnionType();\n\n\t\t\tsize_t maxSz = 0;\n\t\t\tfor(const auto& v : ut->getVariants())\n\t\t\t\tmaxSz = std::max(maxSz, getSizeOfType(v.second));\n\n\t\t\ticeAssert(maxSz > 0);\n\t\t\treturn getAggregateSize({ ArrayType::get(Type::getInt8(), maxSz) });\n\t\t}\n\t\telse if(type->isUnionVariantType())\n\t\t{\n\t\t\treturn getSizeOfType(type->toUnionVariantType()->getInteriorType());\n\t\t}\n\t\telse if(type->isOpaqueType())\n\t\t{\n\t\t\treturn type->toOpaqueType()->getTypeSizeInBits() / 8;\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(\"cannot get size of unsupported type '%s'\", type);\n\t\t}\n\t}\n\n\tsize_t getAlignmentOfType(Type* type)\n\t{\n\t\tif(type->isArrayType())     return getAlignmentOfType(type->getArrayElementType());\n\t\telse                        return getSizeOfType(type);\n\t}\n\n\n\tbool isRefCountedType(Type* type)\n\t{\n\t\t// strings, and structs with rc inside\n\t\tif(type->isStructType())\n\t\t{\n\t\t\tfor(auto m : type->toStructType()->getElements())\n\t\t\t{\n\t\t\t\tif(isRefCountedType(m))\n\t\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\t\telse if(type->isClassType())\n\t\t{\n\t\t\tfor(auto m : type->toClassType()->getElements())\n\t\t\t{\n\t\t\t\tif(isRefCountedType(m))\n\t\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\t\telse if(type->isTupleType())\n\t\t{\n\t\t\tfor(auto m : type->toTupleType()->getElements())\n\t\t\t{\n\t\t\t\tif(isRefCountedType(m))\n\t\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\t\telse if(type->isArrayType())\t// note: no slices, because slices don't own memory\n\t\t{\n\t\t\treturn isRefCountedType(type->getArrayElementType());\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn type->isStringType() || type->isAnyType() || type->isDynamicArrayType();\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/Types/TypeUtils.cpp",
    "content": "// TypeUtils.cpp\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"errors.h\"\n#include \"ir/type.h\"\n#include \"ir/function.h\"\n\nnamespace fir\n{\n\tstatic bool _checkTypeVariance(Type* base, Type* derv, bool contra, bool trait)\n\t{\n\t\tif(base == derv)\n\t\t\treturn true;\n\n\t\t// for now, we only support inheritance and stuff on pointers.\n\t\tif(!base->isPointerType() || !derv->isPointerType())\n\t\t\treturn false;\n\n\t\tauto baseelm = base->getPointerElementType();\n\t\tauto dervelm = derv->getPointerElementType();\n\n\t\tif(baseelm->isClassType() && dervelm->isClassType())\n\t\t{\n\t\t\t// if contravariant, then derv must be more general than base.\n\t\t\tif(contra)  return baseelm->toClassType()->hasParent(dervelm);\n\t\t\telse        return dervelm->toClassType()->hasParent(baseelm);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// if contra, check if base implements derv as a trait\n\t\t\t// else check if derv implements base as a trait. of course, if the thing that\n\t\t\t// is supposed to be a trait isn't a trait, it doesn't work.\n\t\t\tif(contra)\n\t\t\t{\n\t\t\t\t// if contra *BUT* we are checking traits, then we should allow the case where the\n\t\t\t\t// derived type is covariant (ie. implements the trait!)\n\n\t\t\t\tif(trait)\n\t\t\t\t{\n\t\t\t\t\t// TODO: this might not be correct?\n\t\t\t\t\tstd::swap(baseelm, dervelm);\n\t\t\t\t}\n\n\t\t\t\tif(!dervelm->isTraitType())\n\t\t\t\t\treturn false;\n\n\t\t\t\treturn (baseelm->isStructType() && baseelm->toStructType()->implementsTrait(dervelm->toTraitType()))\n\t\t\t\t\t|| (dervelm->isStructType() && dervelm->toStructType()->implementsTrait(baseelm->toTraitType()));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif(!baseelm->isTraitType())\n\t\t\t\t\treturn false;\n\n\t\t\t\treturn (dervelm->isStructType() && dervelm->toStructType()->implementsTrait(baseelm->toTraitType()))\n\t\t\t\t\t|| (baseelm->isStructType() && baseelm->toStructType()->implementsTrait(dervelm->toTraitType()));\n\t\t\t}\n\t\t}\n\t}\n\n\tbool areTypesCovariant(Type* base, Type* derv)\n\t{\n\t\treturn _checkTypeVariance(base, derv, false, false);\n\t}\n\n\tbool areTypesContravariant(Type* base, Type* derv, bool traitChecking)\n\t{\n\t\treturn _checkTypeVariance(base, derv, true, traitChecking);\n\t}\n\n\tbool areTypeListsContravariant(const std::vector<Type*>& base, const std::vector<Type*>& derv, bool traitChecking)\n\t{\n\t\t// parameters must be contravariant, ie. fn must take more general types than base\n\t\t// return type must be covariant, ie. fn must return a more specific type than base.\n\n\t\t// duh\n\t\tif(base.size() != derv.size())\n\t\t\treturn false;\n\n\t\t// drop the first argument.\n\t\tfor(auto [ b, d ] : zfu::zip(base, derv))\n\t\t{\n\t\t\tif(!areTypesContravariant(b, d, traitChecking))\n\t\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tbool areMethodsVirtuallyCompatible(FunctionType* base, FunctionType* fn, bool traitChecking)\n\t{\n\t\tbool ret = areTypeListsContravariant(zfu::drop(base->getArgumentTypes(), 1),\n\t\t\tzfu::drop(fn->getArgumentTypes(), 1), traitChecking);\n\n\t\tif(!ret)\n\t\t\treturn false;\n\n\t\tauto baseRet = base->getReturnType();\n\t\tauto fnRet = fn->getReturnType();\n\n\t\t// ok now check the return type.\n\t\treturn areTypesCovariant(baseRet, fnRet);\n\t}\n}\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/Types/UnionType.cpp",
    "content": "// UnionType.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"errors.h\"\n#include \"ir/type.h\"\n\n#include \"pts.h\"\n\nnamespace fir\n{\n\t// structs\n\tUnionType::UnionType(const Name& name, const util::hash_map<std::string, std::pair<size_t, Type*>>& mems)\n\t\t: Type(TypeKind::Union), unionName(name)\n\t{\n\t\tthis->setBody(mems);\n\t}\n\n\tstatic util::hash_map<Name, UnionType*> typeCache;\n\tUnionType* UnionType::create(const Name& name, const util::hash_map<std::string, std::pair<size_t, Type*>>& mems)\n\t{\n\t\tif(auto it = typeCache.find(name); it != typeCache.end())\n\t\t\terror(\"union with name '%s' already exists\", name.str());\n\n\t\telse\n\t\t\treturn (typeCache[name] = new UnionType(name, mems));\n\t}\n\n\tUnionType* UnionType::createWithoutBody(const Name& name)\n\t{\n\t\treturn UnionType::create(name, { });\n\t}\n\n\n\n\n\n\n\t// various\n\tstd::string UnionType::str()\n\t{\n\t\treturn \"union(\" + this->unionName.name + \")\";\n\t}\n\n\tstd::string UnionType::encodedStr()\n\t{\n\t\treturn this->unionName.str();\n\t}\n\n\n\tbool UnionType::isTypeEqual(Type* other)\n\t{\n\t\tif(other->kind != TypeKind::Union)\n\t\t\treturn false;\n\n\t\treturn (this->unionName == other->toUnionType()->unionName);\n\t}\n\n\n\n\t// struct stuff\n\tName UnionType::getTypeName()\n\t{\n\t\treturn this->unionName;\n\t}\n\n\tsize_t UnionType::getVariantCount()\n\t{\n\t\treturn this->variants.size();\n\t}\n\n\tsize_t UnionType::getIdOfVariant(const std::string& name)\n\t{\n\t\tif(auto it = this->variants.find(name); it != this->variants.end())\n\t\t\treturn it->second->variantId;\n\n\t\telse\n\t\t\terror(\"no variant with name '%s'\", name);\n\t}\n\n\tconst util::hash_map<std::string, UnionVariantType*>& UnionType::getVariants()\n\t{\n\t\treturn this->variants;\n\t}\n\n\tbool UnionType::hasVariant(const std::string& name)\n\t{\n\t\treturn this->variants.find(name) != this->variants.end();\n\t}\n\n\tUnionVariantType* UnionType::getVariant(size_t id)\n\t{\n\t\tif(auto it = this->indexMap.find(id); it != this->indexMap.end())\n\t\t\treturn it->second;\n\n\t\telse\n\t\t\terror(\"no variant with id %d\", id);\n\t}\n\n\tUnionVariantType* UnionType::getVariant(const std::string& name)\n\t{\n\t\tif(auto it = this->variants.find(name); it != this->variants.end())\n\t\t\treturn it->second;\n\n\t\telse\n\t\t\terror(\"no variant named '%s' in union '%s'\", name, this->getTypeName().str());\n\t}\n\n\n\n\tvoid UnionType::setBody(const util::hash_map<std::string, std::pair<size_t, Type*>>& members)\n\t{\n\t\tfor(const auto& [ n, p ] : members)\n\t\t{\n\t\t\tauto uvt = new UnionVariantType(this, p.first, n, p.second);\n\n\t\t\tthis->variants[n] = uvt;\n\t\t\tthis->indexMap[p.first] = uvt;\n\t\t}\n\t}\n\n\tfir::Type* UnionType::substitutePlaceholders(const util::hash_map<Type*, Type*>& subst)\n\t{\n\t\tif(this->containsPlaceholders())\n\t\t\terror(\"not supported!\");\n\n\t\treturn this;\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\tstd::string UnionVariantType::str()\n\t{\n\t\treturn this->parent->str() + \"::\" + this->name;\n\t}\n\n\tstd::string UnionVariantType::encodedStr()\n\t{\n\t\treturn this->parent->encodedStr() + \"::\" + this->name;\n\t}\n\n\tbool UnionVariantType::isTypeEqual(Type* other)\n\t{\n\t\tif(auto uvt = dcast(UnionVariantType, other))\n\t\t\treturn uvt->parent == this->parent && uvt->name == this->name;\n\n\t\treturn false;\n\t}\n\n\tfir::Type* UnionVariantType::substitutePlaceholders(const util::hash_map<fir::Type*, fir::Type*>& subst)\n\t{\n\t\tif(this->containsPlaceholders())\n\t\t\terror(\"not supported!\");\n\n\t\treturn this;\n\t}\n\n\tUnionVariantType::UnionVariantType(UnionType* p, size_t id, const std::string& name, Type* actual) : Type(TypeKind::UnionVariant)\n\t{\n\t\tthis->parent = p;\n\t\tthis->name = name;\n\t\tthis->variantId = id;\n\t\tthis->interiorType = actual;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/Value.cpp",
    "content": "// Value.cpp\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ir/value.h\"\n#include \"ir/constant.h\"\n\nnamespace fir\n{\n\tstatic size_t vnames = 0;\n\tValue::Value(Type* t, Kind k) : ident(Name::of(\"\")), valueType(t), kind(k)\n\t{\n\t\tthis->id = vnames++;\n\t}\n\n\tType* Value::getType()\n\t{\n\t\tif(this->valueType) return this->valueType;\n\n\t\terror(\"value has no type????\");\n\t}\n\n\tbool Value::hasName()\n\t{\n\t\treturn this->ident.str() != \"\";\n\t}\n\n\tvoid Value::setName(const Name& name)\n\t{\n\t\tthis->ident = name;\n\t}\n\n\tvoid Value::setName(const std::string& name)\n\t{\n\t\tthis->ident = Name::of(name);\n\t}\n\n\tconst Name& Value::getName()\n\t{\n\t\treturn this->ident;\n\t}\n\n\tsize_t Value::getCurrentValueId()\n\t{\n\t\treturn vnames;\n\t}\n\n\n\n\n\n\n\n\tvoid PHINode::addIncoming(Value* v, IRBlock* block)\n\t{\n\t\ticeAssert(v->getType() == this->valueType && \"types not identical\");\n\t\tif(this->incoming.find(block) != this->incoming.end())\n\t\t\ticeAssert(0 && \"block already has incoming value\");\n\n\t\tthis->incoming[block] = v;\n\t}\n\n\tstd::map<IRBlock*, Value*> PHINode::getValues()\n\t{\n\t\treturn this->incoming;\n\t}\n\n\tPHINode::PHINode(Type* t) : fir::Value(t)\n\t{\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/interp/compiler.cpp",
    "content": "// compiler.cpp\n// Copyright (c) 2017, zhiayang@gmail.com\n// Licensed under the Apache License Version 2.0.\n\n#include \"ir/type.h\"\n#include \"ir/value.h\"\n#include \"ir/interp.h\"\n#include \"ir/module.h\"\n#include \"ir/function.h\"\n#include \"ir/instruction.h\"\n\nnamespace fir {\nnamespace interp\n{\n\tstatic interp::Instruction compileInstruction(InterpState* is, fir::Function* parent, fir::Instruction* finstr)\n\t{\n\t\ticeAssert(finstr);\n\n\t\tinterp::Instruction ret;\n\n\t\tret.result = finstr->realOutput;\n\t\tret.opcode = static_cast<uint64_t>(finstr->opKind);\n\n\t\tfor(auto a : finstr->operands)\n\t\t\tret.args.push_back(a);\n\n\t\treturn ret;\n\t}\n\n\tstatic interp::Block compileBlock(InterpState* is, fir::Function* parent, fir::IRBlock* fib)\n\t{\n\t\ticeAssert(fib);\n\n\t\tinterp::Block ret;\n\t\tret.blk = fib;\n\t\tret.instructions = zfu::map(fib->getInstructions(), [is, parent](fir::Instruction* i) -> interp::Instruction {\n\t\t\treturn compileInstruction(is, parent, i);\n\t\t});\n\n\t\treturn ret;\n\t}\n\n\tinterp::Function& InterpState::compileFunction(fir::Function* fn)\n\t{\n\t\ticeAssert(fn);\n\n\t\tinterp::Function ret;\n\t\tret.func = fn;\n\n\t\tret.blocks = zfu::map(fn->getBlockList(), [fn, this](fir::IRBlock* b) -> interp::Block {\n\t\t\treturn compileBlock(this, fn, b);\n\t\t});\n\n\t\tif(fn->isCStyleVarArg())\n\t\t\ticeAssert(ret.blocks.empty());\n\n\t\tif(ret.blocks.empty())\n\t\t\tret.isExternal = true, ret.extFuncName = fn->getName().name;\n\n\n\t\t// add it.\n\t\tthis->compiledFunctions[ret.func] = ret;\n\t\treturn this->compiledFunctions[ret.func];\n\t}\n}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/interp/interpreter.cpp",
    "content": "// interpreter.cpp\n// Copyright (c) 2017, zhiayang@gmail.com\n// Licensed under the Apache License Version 2.0.\n\n#include \"ir/type.h\"\n#include \"ir/value.h\"\n#include \"ir/interp.h\"\n#include \"ir/module.h\"\n#include \"ir/function.h\"\n#include \"ir/instruction.h\"\n\n#include \"frontend.h\"\n#include \"gluecode.h\"\n#include \"platform.h\"\n\n#define FFI_BUILDING\n#include <ffi.h>\n\n#define LARGE_DATA_SIZE 32\n\n#define SLICE_DATA_INDEX            0\n#define SLICE_LENGTH_INDEX          1\n\n#define SAA_DATA_INDEX              0\n#define SAA_LENGTH_INDEX            1\n#define SAA_CAPACITY_INDEX          2\n#define SAA_REFCOUNTPTR_INDEX       3\n\n#define ANY_TYPEID_INDEX            0\n#define ANY_REFCOUNTPTR_INDEX       1\n#define ANY_DATA_ARRAY_INDEX        2\n\n\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n\t#pragma warning(disable: 4018)\n#else\n\t/*\n\t\tso msvc doesn't really warn on this. we disable these warnings locally, because of the way we're doing the\n\t\toperations. we can guarantee (because IRBuilder says so) that we won't be doing strange things like\n\t\tbitwise-not-ing a boolean or left-shifting a floating point, but the compiler won't know so we just ignore\n\t\tthese things to clean up the output.\n\t*/\n\t#pragma GCC diagnostic push\n\t#pragma GCC diagnostic ignored \"-Wpragmas\"\n\t#pragma GCC diagnostic ignored \"-Wunknown-warning-option\"\n\n\t#pragma GCC diagnostic ignored \"-Wbool-operation\"\n\t#pragma GCC diagnostic ignored \"-Wint-in-bool-context\"\n\t#pragma GCC diagnostic ignored \"-Wimplicit-conversion-floating-point-to-bool\"\n\t#pragma GCC diagnostic ignored \"-Wdelete-incomplete\"\n#endif\n\n\n\nnamespace fir {\nnamespace interp\n{\n\t//! ACHTUNG !\n\t//* in the interpreter, we assume all structs are packed, and there are no padding/alignment bytes anywhere.\n\t//* this greatly simplifies everything, and the performance impact is probably insignificant next to the (power of the force)\n\t//* whole interpreter anyway.\n\n\n\ttemplate <typename T>\n\tstatic interp::Value makeValue(fir::Value* fv, const T& val)\n\t{\n\t\tinterp::Value ret;\n\t\tret.val = fv;\n\t\tret.type = fv->getType();\n\t\tret.dataSize = sizeof(T);\n\n\t\tif(auto fsz = getSizeOfType(ret.type); fsz != sizeof(T))\n\t\t\terror(\"packing error of type '%s': predicted size %d, actual size %d!\", ret.type, fsz, sizeof(T));\n\n\t\tmemset(&ret.data[0], 0, LARGE_DATA_SIZE);\n\n\t\tif(sizeof(T) > LARGE_DATA_SIZE)\n\t\t{\n\t\t\tret.ptr = malloc(sizeof(T));\n\t\t\tmemmove(ret.ptr, &val, sizeof(T));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tmemmove(&ret.data[0], &val, sizeof(T));\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\n\t// this lets us specify the type, instead of using the one in the Value\n\tstatic interp::Value makeValueOfType(fir::Value* fv, fir::Type* ty)\n\t{\n\t\tinterp::Value ret;\n\t\tret.val = fv;\n\t\tret.type = ty;\n\t\tret.dataSize = getSizeOfType(ret.type);\n\n\t\tmemset(&ret.data[0], 0, LARGE_DATA_SIZE);\n\n\t\tif(ret.dataSize > LARGE_DATA_SIZE)\n\t\t\tret.ptr = calloc(1, ret.dataSize);\n\n\t\treturn ret;\n\t}\n\n\n\tinterp::Value InterpState::makeValue(fir::Value* fv)\n\t{\n\t\treturn makeValueOfType(fv, fv->getType());\n\t}\n\n\n\ttemplate <typename T>\n\tstatic T getActualValue(const interp::Value& v)\n\t{\n\t\tif(v.dataSize > LARGE_DATA_SIZE)\n\t\t{\n\t\t\treturn *(static_cast<T*>(v.ptr));\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn *(reinterpret_cast<T*>(const_cast<uint8_t*>(&v.data[0])));\n\t\t}\n\t}\n\n\n\tstatic interp::Value cloneValue(const interp::Value& v)\n\t{\n\t\tinterp::Value ret = v;\n\n\t\tif(v.dataSize > LARGE_DATA_SIZE)\n\t\t{\n\t\t\tret.ptr = calloc(1, v.dataSize);\n\t\t\tmemmove(ret.ptr, v.ptr, v.dataSize);\n\t\t}\n\t\treturn ret;\n\t}\n\n\tstatic interp::Value cloneValue(fir::Value* fv, const interp::Value& v)\n\t{\n\t\tinterp::Value ret = v;\n\t\tret.val = fv;\n\t\tret.globalValTracker = v.globalValTracker;\n\n\t\tif(v.dataSize > LARGE_DATA_SIZE)\n\t\t{\n\t\t\tret.ptr = calloc(1, v.dataSize);\n\t\t\tmemmove(ret.ptr, v.ptr, v.dataSize);\n\t\t}\n\t\treturn ret;\n\t}\n\n\tstatic void setValueRaw(InterpState* is, interp::Value* target, void* value, size_t sz)\n\t{\n\t\tif(target->dataSize != sz)\n\t\t\terror(\"interp: cannot set value, size mismatch (%d vs %d)\", target->dataSize, sz);\n\n\t\tif(sz > LARGE_DATA_SIZE)\n\t\t{\n\t\t\tif(!target->ptr)\n\t\t\t\ttarget->ptr = calloc(1, sz);\n\n\t\t\tmemmove(target->ptr, value, sz);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tmemmove(&target->data[0], value, sz);\n\t\t}\n\t}\n\n\tstatic void setValue(InterpState* is, interp::Value* target, const interp::Value& val)\n\t{\n\t\tif(target->type != val.type)\n\t\t\terror(\"interp: cannot set value, conflicting types '%s' and '%s'\", target->type, val.type);\n\n\t\tif(val.dataSize > LARGE_DATA_SIZE)\n\t\t\tmemmove(target->ptr, val.ptr, val.dataSize);\n\n\t\telse\n\t\t\tmemmove(&target->data[0], &val.data[0], val.dataSize);\n\t}\n\n\tstatic char* makeGlobalString(InterpState* is, const std::string& str)\n\t{\n\t\tauto s = new char[str.size() + 1];\n\t\tmemmove(s, str.c_str(), str.size());\n\t\ts[str.size()] = 0;\n\n\t\tis->strings.push_back(s);\n\n\t\treturn s;\n\t}\n\n\tstatic interp::Value loadFromPtr(const interp::Value& x, fir::Type* ty)\n\t{\n\t\tauto ptr = reinterpret_cast<void*>(getActualValue<uintptr_t>(x));\n\n\t\tinterp::Value ret;\n\t\tret.dataSize = getSizeOfType(ty);\n\t\tret.type = ty;\n\n\t\tif(ret.dataSize > LARGE_DATA_SIZE)\n\t\t{\n\t\t\t// clone the memory and store it.\n\t\t\tauto newmem = malloc(ret.dataSize);\n\t\t\tmemmove(newmem, ptr, ret.dataSize);\n\t\t\tret.ptr = newmem;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// memcopy.\n\t\t\tmemmove(&ret.data[0], ptr, ret.dataSize);\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\n\tstatic std::map<ConstantValue*, interp::Value> cachedConstants;\n\tstatic interp::Value makeConstant(InterpState* is, ConstantValue* c)\n\t{\n\t\tauto constructStructThingy2 = [](fir::Value* val, size_t datasize, const std::vector<interp::Value>& inserts) -> interp::Value {\n\n\t\t\tuint8_t* buffer = 0;\n\n\t\t\tinterp::Value ret;\n\t\t\tret.dataSize = datasize;\n\t\t\tret.type = val->getType();\n\t\t\tret.val = val;\n\n\t\t\tif(datasize > LARGE_DATA_SIZE)  { buffer = new uint8_t[datasize]; ret.ptr = buffer; }\n\t\t\telse                            { buffer = &ret.data[0]; }\n\n\t\t\ticeAssert(buffer);\n\n\t\t\tuint8_t* ofs = buffer;\n\t\t\tfor(const auto& v : inserts)\n\t\t\t{\n\t\t\t\tif(v.dataSize > LARGE_DATA_SIZE)    memmove(ofs, v.ptr, v.dataSize);\n\t\t\t\telse                                memmove(ofs, &v.data[0], v.dataSize);\n\n\t\t\t\tofs += v.dataSize;\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t};\n\n\t\tauto constructStructThingy = [is, &constructStructThingy2](fir::Value* val, size_t datasize,\n\t\t\tconst std::vector<ConstantValue*>& inserts) -> interp::Value\n\t\t{\n\t\t\tstd::vector<interp::Value> vals;\n\t\t\tvals.reserve(inserts.size());\n\n\t\t\tfor(const auto& x : inserts)\n\t\t\t\tvals.push_back(makeConstant(is, x));\n\n\t\t\treturn constructStructThingy2(val, datasize, vals);\n\t\t};\n\n\n\t\tif(auto ci = dcast(fir::ConstantInt, c))\n\t\t{\n\t\t\tinterp::Value ret;\n\n\t\t\tif(ci->getType() == fir::Type::getInt8())        ret = makeValue(c, static_cast<int8_t>(ci->getSignedValue()));\n\t\t\telse if(ci->getType() == fir::Type::getInt16())  ret = makeValue(c, static_cast<int16_t>(ci->getSignedValue()));\n\t\t\telse if(ci->getType() == fir::Type::getInt32())  ret = makeValue(c, static_cast<int32_t>(ci->getSignedValue()));\n\t\t\telse if(ci->getType() == fir::Type::getInt64())  ret = makeValue(c, static_cast<int64_t>(ci->getSignedValue()));\n\t\t\telse if(ci->getType() == fir::Type::getUint8())  ret = makeValue(c, static_cast<uint8_t>(ci->getUnsignedValue()));\n\t\t\telse if(ci->getType() == fir::Type::getUint16()) ret = makeValue(c, static_cast<uint16_t>(ci->getUnsignedValue()));\n\t\t\telse if(ci->getType() == fir::Type::getUint32()) ret = makeValue(c, static_cast<uint32_t>(ci->getUnsignedValue()));\n\t\t\telse if(ci->getType() == fir::Type::getUint64()) ret = makeValue(c, static_cast<uint64_t>(ci->getUnsignedValue()));\n\t\t\telse error(\"interp: unsupported type '%s' for integer constant\", ci->getType());\n\n\t\t\treturn (cachedConstants[c] = ret);\n\t\t}\n\t\telse if(auto cf = dcast(fir::ConstantFP, c))\n\t\t{\n\t\t\treturn cachedConstants[c] = makeValue(c, cf->getValue());\n\t\t}\n\t\telse if(auto cb = dcast(fir::ConstantBool, c))\n\t\t{\n\t\t\treturn cachedConstants[c] = makeValue(c, cb->getValue());\n\t\t}\n\t\telse if(auto cs = dcast(fir::ConstantCharSlice, c))\n\t\t{\n\t\t\tauto str = makeGlobalString(is, cs->getValue());\n\t\t\tauto ptr = fir::ConstantBitcast::get(fir::ConstantInt::getUNative(reinterpret_cast<uintptr_t>(str)), fir::Type::getInt8Ptr());\n\t\t\tauto len = fir::ConstantInt::getNative(cs->getValue().size());\n\n\t\t\tauto bytecount = getSizeOfType(cs->getType());\n\n\t\t\tauto ret = constructStructThingy(cs, bytecount, { ptr, len });\n\n\t\t\treturn (cachedConstants[c] = ret);\n\t\t}\n\t\telse if(auto cbc = dcast(fir::ConstantBitcast, c))\n\t\t{\n\t\t\tauto thing = makeConstant(is, cbc->getValue());\n\t\t\tauto ret = cloneValue(cbc, thing);\n\n\t\t\treturn (cachedConstants[c] = ret);\n\t\t}\n\t\telse if(auto ca = dcast(fir::ConstantArray, c))\n\t\t{\n\t\t\tauto bytecount = getSizeOfType(ca->getType());\n\n\t\t\tauto ret = constructStructThingy(ca, bytecount, ca->getValues());\n\t\t\treturn (cachedConstants[c] = ret);\n\t\t}\n\t\telse if(auto ct = dcast(fir::ConstantTuple, c))\n\t\t{\n\t\t\tsize_t bytecount = getSizeOfType(ct->getType());\n\n\t\t\tauto ret = constructStructThingy(ct, bytecount, ct->getValues());\n\t\t\treturn (cachedConstants[c] = ret);\n\t\t}\n\t\telse if(auto cec = dcast(fir::ConstantEnumCase, c))\n\t\t{\n\t\t\tauto bytecount = getSizeOfType(cec->getType());\n\n\t\t\tauto ret = constructStructThingy(cec, bytecount, { cec->getIndex(), cec->getValue() });\n\t\t\treturn (cachedConstants[c] = ret);\n\t\t}\n\t\telse if(auto cas = dcast(fir::ConstantArraySlice, c))\n\t\t{\n\t\t\tauto ptr = cas->getData();\n\t\t\tauto len = cas->getLength();\n\n\t\t\tauto bytecount = getSizeOfType(cas->getType());\n\t\t\tauto ret = constructStructThingy(cas, bytecount, { ptr, len });\n\n\t\t\treturn (cachedConstants[c] = ret);\n\t\t}\n\t\telse if(auto cds = dcast(fir::ConstantDynamicString, c))\n\t\t{\n\t\t\tauto str = makeGlobalString(is, cds->getValue());\n\t\t\tauto ptr = fir::ConstantBitcast::get(fir::ConstantInt::getUNative(reinterpret_cast<uintptr_t>(str)), fir::Type::getInt8Ptr());\n\t\t\tauto len = fir::ConstantInt::getNative(cds->getValue().size());\n\n\t\t\tauto bytecount = getSizeOfType(cds->getType());\n\n\t\t\t// add -1 for capacity and 0 for refcountptr.\n\t\t\tauto ret = constructStructThingy(cds, bytecount, { ptr, len,\n\t\t\t\tfir::ConstantInt::getNative(-1), fir::ConstantInt::getNative(0) });\n\n\t\t\treturn (cachedConstants[c] = ret);\n\t\t}\n\t\telse if(auto cda = dcast(fir::ConstantDynamicArray, c))\n\t\t{\n\t\t\tstd::vector<interp::Value> mems;\n\t\t\tauto bytecount = getSizeOfType(cda->getType());\n\n\t\t\tif(cda->getArray())\n\t\t\t{\n\t\t\t\tauto theArray = cda->getArray();\n\t\t\t\tauto sz = getSizeOfType(theArray->getType());\n\n\t\t\t\tvoid* buffer = new uint8_t[sz]; memset(buffer, 0, sz);\n\t\t\t\tis->globalAllocs.push_back(buffer);\n\n\t\t\t\tuint8_t* ofs = reinterpret_cast<uint8_t*>(buffer);\n\t\t\t\tfor(auto x : theArray->getValues())\n\t\t\t\t{\n\t\t\t\t\tauto v = makeConstant(is, x);\n\n\t\t\t\t\tif(v.dataSize > LARGE_DATA_SIZE)    memmove(ofs, v.ptr, v.dataSize);\n\t\t\t\t\telse                                memmove(ofs, &v.data[0], v.dataSize);\n\n\t\t\t\t\tofs += v.dataSize;\n\t\t\t\t}\n\n\t\t\t\tinterp::Value fakeptr;\n\t\t\t\tfakeptr.val = 0;\n\t\t\t\tfakeptr.type = cda->getType()->getArrayElementType()->getMutablePointerTo();\n\t\t\t\tfakeptr.dataSize = sizeof(void*);\n\n\t\t\t\tsetValueRaw(is, &fakeptr, &buffer, sizeof(void*));\n\n\t\t\t\tmems = {\n\t\t\t\t\tfakeptr, makeConstant(is, fir::ConstantInt::getNative(theArray->getValues().size())),\n\t\t\t\t\tmakeConstant(is, fir::ConstantInt::getNative(-1)), makeConstant(is, fir::ConstantInt::getNative(0))\n\t\t\t\t};\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tmems = {\n\t\t\t\t\tmakeConstant(is, cda->getData()), makeConstant(is, cda->getLength()),\n\t\t\t\t\tmakeConstant(is, cda->getCapacity()), makeConstant(is, fir::ConstantInt::getNative(0))\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tauto ret = constructStructThingy2(cda, bytecount, mems);\n\t\t\treturn (cachedConstants[c] = ret);\n\t\t}\n\t\telse if(auto fn = dcast(fir::Function, c))\n\t\t{\n\t\t\t// ok -- when we get a \"function\" as a constant, what really happened in the source code is that we referred to a function\n\t\t\t// by name, without calling it. we expect, then, to get a function pointer out of it.\n\n\t\t\t// the problem is, we can also call function pointers that come from raw pointers that point to *real* CPU instructions\n\t\t\t// somewhere --- nobody is stopping the program from calling dlsym() or whatever and calling a function using\n\t\t\t// that pointer.\n\n\t\t\t// so, in order to support that, we return the fir::Function itself as a pointer. when we do the pointer-call, the\n\t\t\t// stub function will check the list of functions to see if it was a source-originated function, and if so call it\n\t\t\t// normally. if not, then we will use libffi to call it.\n\n\t\t\t// make sure we compile it first, so it gets added to InterpState::compiledFunctions\n\t\t\tis->compileFunction(fn);\n\n\t\t\tauto ret = makeValue(fn, reinterpret_cast<uintptr_t>(fn));\n\t\t\treturn (cachedConstants[c] = ret);\n\t\t}\n\t\telse if(auto glob = dcast(fir::GlobalValue, c))\n\t\t{\n\t\t\tif(auto it = is->globals.find(c); it != is->globals.end())\n\t\t\t\treturn it->second.first;\n\n\t\t\telse\n\t\t\t\terror(\"interp: global value '%s' id %d was not found\", glob->getName().str(), glob->id);\n\t\t}\n\t\telse\n\t\t{\n\t\t\ticeAssert(c);\n\n\t\t\tauto ret = is->makeValue(c);\n\t\t\treturn (cachedConstants[c] = ret);\n\t\t}\n\t}\n\n\n\n\tInterpState::InterpState(Module* mod) : module(mod)\n\t{\n\t}\n\n\tInterpState::~InterpState()\n\t{\n\t}\n\n\tvoid InterpState::initialise(bool runGlobalInit)\n\t{\n\t\ticeAssert(this->module);\n\t\tfor(const auto& [ str, glob ] : this->module->_getGlobalStrings())\n\t\t{\n\t\t\tauto val = makeValue(glob);\n\t\t\tauto s = makeGlobalString(this, str);\n\n\t\t\tsetValueRaw(this, &val, &s, sizeof(char*));\n\n\t\t\tval.globalValTracker = glob;\n\t\t\tthis->globals[glob] = { val, false };\n\t\t}\n\n\t\tfor(const auto& [ id, glob ] : this->module->_getGlobals())\n\t\t{\n\t\t\tauto ty = glob->getType();\n\t\t\tauto sz = getSizeOfType(ty);\n\n\t\t\tvoid* buffer = new uint8_t[sz];\n\t\t\tmemset(buffer, 0, sz);\n\n\t\t\tthis->globalAllocs.push_back(buffer);\n\n\t\t\tif(auto init = glob->getInitialValue(); init)\n\t\t\t{\n\t\t\t\tauto x = makeConstant(this, init);\n\t\t\t\tif(x.dataSize > LARGE_DATA_SIZE)    memmove(buffer, x.ptr, x.dataSize);\n\t\t\t\telse                                memmove(buffer, &x.data[0], x.dataSize);\n\t\t\t}\n\n\t\t\tauto ret = makeValueOfType(glob, ty->getPointerTo());\n\t\t\tsetValueRaw(this, &ret, &buffer, sizeof(void*));\n\n\t\t\tret.globalValTracker = glob;\n\t\t\tthis->globals[glob] = { ret, false };\n\t\t}\n\n\t\tfor(const auto& [ id, intr ] : this->module->_getIntrinsicFunctions())\n\t\t{\n\t\t\tauto fname = Name::of(zpr::sprint(\"__interp_intrinsic_%s\", id.str()));\n\t\t\tauto fn = this->module->getOrCreateFunction(fname, intr->getType(), fir::LinkageType::ExternalWeak);\n\n\t\t\t// interp::compileFunction already maps the newly compiled interp::Function, but since we created a\n\t\t\t// new function here `fn` that doesn't match the intrinsic function `intr`, we need to map that as well.\n\t\t\tthis->compiledFunctions[intr] = this->compileFunction(fn);\n\t\t}\n\n\n\t\t#if OS_WINDOWS\n\n\t\t// ok, this is mostly for windows --- printf and friends are not *real* functions, but rather\n\t\t// macros defined in stdio.h, or something like that. so, we make \"intrinsic wrappers\" that call\n\t\t// it in the interpreter, which we dlopen into the context anyway.\n\t\t{\n\t\t\tstd::vector<std::string> names = {\n\t\t\t\t\"printf\",\n\t\t\t\t\"sprintf\",\n\t\t\t\t\"snprintf\",\n\t\t\t\t\"fprintf\"\n\t\t\t};\n\n\t\t\tfor(const auto& name : names)\n\t\t\t{\n\t\t\t\tauto fn = this->module->getFunction(Name::of(name));\n\t\t\t\tif(fn)\n\t\t\t\t{\n\t\t\t\t\tauto wrapper = this->module->getOrCreateFunction(Name::of(zpr::sprint(\"__interp_wrapper_%s\", name)),\n\t\t\t\t\t\tfn->getType()->toFunctionType(), fir::LinkageType::ExternalWeak);\n\n\t\t\t\t\tthis->compiledFunctions[fn] = this->compileFunction(wrapper);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t#endif\n\n\t\t// printf(\"module:\\n%s\\n\", this->module->print().c_str());\n\n\t\t// truth be told it'll be more efficient to only get the function after checking runGlobalInit, but... meh.\n\t\tif(auto gif = this->module->getFunction(Name::obfuscate(strs::names::GLOBAL_INIT_FUNCTION));\n\t\t\trunGlobalInit && gif)\n\t\t{\n\t\t\tauto cgif = this->compileFunction(gif);\n\t\t\tthis->runFunction(cgif, { });\n\t\t}\n\t}\n\n\n\t// the purpose of this function is to write-back any changes we made to globals while interpreting,\n\t// back to the \"value\" of the global -- mainly for compile-time execution, so modifications will\n\t// propagate to the backend code generation.\n\tvoid InterpState::finalise()\n\t{\n\t\tfor(const auto& [ id, glob ] : this->module->_getGlobals())\n\t\t{\n\t\t\t// printf(\"global: %s\\n\", id.str().c_str());\n\n\t\t\t// by right we are not supposed to add (or even change the FIR module at all) between calling\n\t\t\t// initialise() and finalise(), but be defensive a bit.\n\t\t\tif(auto it = this->globals.find(glob); it != this->globals.end())\n\t\t\t{\n\t\t\t\t// printf(\"found: %s\\n\", id.str().c_str());\n\n\t\t\t\t// only write-back if we modified the global.\n\t\t\t\tif(it->second.second)\n\t\t\t\t{\n\t\t\t\t\tauto val = loadFromPtr(it->second.first, it->first->getType());\n\t\t\t\t\tauto x = this->unwrapInterpValueIntoConstant(val);\n\n\t\t\t\t\t// printf(\"write-back: %s = %s\\n\", id.name.c_str(), x->str().c_str());\n\t\t\t\t\tglob->setInitialValue(x);\n\n\t\t\t\t\tit->second.second = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor(void* p : this->globalAllocs)\n\t\t\tdelete[] p;\n\n\t\tthis->globalAllocs.clear();\n\t}\n\n\n\n\tstatic ffi_type* convertTypeToLibFFI(fir::Type* ty)\n\t{\n\t\tif(ty->isPointerType())\n\t\t{\n\t\t\treturn &ffi_type_pointer;\n\t\t}\n\t\telse if(ty->isBoolType())\n\t\t{\n\t\t\t//? HMMM....\n\t\t\treturn &ffi_type_uint8;\n\t\t}\n\t\telse if(ty->isVoidType())\n\t\t{\n\t\t\treturn &ffi_type_void;\n\t\t}\n\t\telse if(ty->isIntegerType())\n\t\t{\n\t\t\tif(ty == Type::getInt8())       return &ffi_type_sint8;\n\t\t\tif(ty == Type::getInt16())      return &ffi_type_sint16;\n\t\t\tif(ty == Type::getInt32())      return &ffi_type_sint32;\n\t\t\tif(ty == Type::getInt64())      return &ffi_type_sint64;\n\n\t\t\tif(ty == Type::getUint8())      return &ffi_type_uint8;\n\t\t\tif(ty == Type::getUint16())     return &ffi_type_uint16;\n\t\t\tif(ty == Type::getUint32())     return &ffi_type_uint32;\n\t\t\tif(ty == Type::getUint64())     return &ffi_type_uint64;\n\t\t}\n\t\telse if(ty->isFloatingPointType())\n\t\t{\n\t\t\tif(ty == Type::getFloat32())    return &ffi_type_float;\n\t\t\tif(ty == Type::getFloat64())    return &ffi_type_double;\n\t\t}\n\n\n\t\terror(\"interp: unsupported type '%s' in libffi-translation\", ty);\n\t}\n\n\n\n\n\n\n\tstatic size_t getOffsetOfTypeInTypeList(const std::vector<fir::Type*>& elms, size_t idx)\n\t{\n\t\tsize_t ofs = 0;\n\t\tfor(uint64_t i = 0; i < idx; i++)\n\t\t{\n\t\t\tauto aln = getAlignmentOfType(elms[i]);\n\t\t\tif(ofs % aln > 0)\n\t\t\t\tofs += (aln - (ofs % aln));\n\n\t\t\tofs += getSizeOfType(elms[i]);\n\t\t}\n\n\t\treturn ofs;\n\t}\n\n\tstatic std::vector<fir::Type*> getTypeListOfType(fir::Type* ty)\n\t{\n\t\tif(ty->isStructType())\n\t\t{\n\t\t\treturn ty->toStructType()->getElements();\n\t\t}\n\t\telse if(ty->isClassType())\n\t\t{\n\t\t\tauto ret = ty->toClassType()->getAllElementsIncludingBase();\n\t\t\tif(ty->toClassType()->getVirtualMethodCount() > 0)\n\t\t\t\tret.insert(ret.begin(), fir::Type::getInt8Ptr());\n\n\t\t\treturn ret;\n\t\t}\n\t\telse if(ty->isTupleType())\n\t\t{\n\t\t\treturn ty->toTupleType()->getElements();\n\t\t}\n\t\telse if(ty->isArraySliceType())\n\t\t{\n\t\t\tif(ty->toArraySliceType()->isMutable())\n\t\t\t\treturn { ty->getArrayElementType()->getMutablePointerTo(), fir::Type::getNativeWord() };\n\n\t\t\telse\n\t\t\t\treturn { ty->getArrayElementType()->getPointerTo(), fir::Type::getNativeWord() };\n\t\t}\n\t\telse if(ty->isAnyType())\n\t\t{\n\t\t\treturn {\n\t\t\t\tfir::Type::getNativeUWord(), fir::Type::getNativeWordPtr(),\n\t\t\t\tfir::ArrayType::get(fir::Type::getInt8(), BUILTIN_ANY_DATA_BYTECOUNT)\n\t\t\t};\n\t\t}\n\t\telse if(ty->isRangeType())\n\t\t{\n\t\t\treturn {\n\t\t\t\tfir::Type::getNativeWord(), fir::Type::getNativeWord(), fir::Type::getNativeWord()\n\t\t\t};\n\t\t}\n\t\telse if(ty->isEnumType())\n\t\t{\n\t\t\treturn {\n\t\t\t\tfir::Type::getNativeWord(), ty->toEnumType()->getCaseType()\n\t\t\t};\n\t\t}\n\t\telse if(ty->isStringType() || ty->isDynamicArrayType())\n\t\t{\n\t\t\tstd::vector<fir::Type*> mems(4);\n\n\t\t\tif(ty->isDynamicArrayType())    mems[SAA_DATA_INDEX] = ty->getArrayElementType()->getMutablePointerTo();\n\t\t\telse                            mems[SAA_DATA_INDEX] = fir::Type::getMutInt8Ptr();\n\n\t\t\tmems[SAA_LENGTH_INDEX]      = fir::Type::getNativeWord();\n\t\t\tmems[SAA_CAPACITY_INDEX]    = fir::Type::getNativeWord();\n\t\t\tmems[SAA_REFCOUNTPTR_INDEX] = fir::Type::getNativeWordPtr();\n\n\t\t\treturn mems;\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(\"interp: unsupported type '%s' for insert/extractvalue\", ty);\n\t\t}\n\t}\n\n\tstatic interp::Value doInsertValue(interp::InterpState* is, fir::Value* res, const interp::Value& str, const interp::Value& elm, size_t idx)\n\t{\n\t\t// we clone the value first\n\t\tauto ret = cloneValue(res, str);\n\n\t\tsize_t ofs = 0;\n\n\t\tif(str.type->isArrayType())\n\t\t{\n\t\t\tauto arrty = str.type->toArrayType();\n\t\t\ticeAssert(idx < arrty->getArraySize());\n\n\t\t\tofs = idx * getSizeOfType(arrty->getElementType());\n\t\t}\n\t\telse if(str.type->isUnionType())\n\t\t{\n\t\t\t// we only support getting the id with insert/extractvalue.\n\t\t\ticeAssert(idx == 0);\n\t\t\tofs = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto typelist = getTypeListOfType(str.type);\n\t\t\ticeAssert(idx < typelist.size());\n\n\t\t\tofs = getOffsetOfTypeInTypeList(typelist, idx);\n\t\t}\n\n\t\tuintptr_t dst = 0;\n\t\tif(str.dataSize > LARGE_DATA_SIZE)  dst = reinterpret_cast<uintptr_t>(ret.ptr);\n\t\telse                                dst = reinterpret_cast<uintptr_t>(&ret.data[0]);\n\n\t\tuintptr_t src = 0;\n\t\tif(elm.dataSize > LARGE_DATA_SIZE)  src = reinterpret_cast<uintptr_t>(elm.ptr);\n\t\telse                                src = reinterpret_cast<uintptr_t>(&elm.data[0]);\n\n\t\tmemmove(reinterpret_cast<void*>(dst + ofs), reinterpret_cast<void*>(src), elm.dataSize);\n\n\t\treturn ret;\n\t}\n\n\n\tstatic interp::Value doExtractValue(interp::InterpState* is, fir::Value* res, const interp::Value& str, size_t idx)\n\t{\n\t\tsize_t ofs = 0;\n\n\t\tfir::Type* elm = 0;\n\t\tif(str.type->isArrayType())\n\t\t{\n\t\t\tauto arrty = str.type->toArrayType();\n\t\t\ticeAssert(idx < arrty->getArraySize());\n\n\t\t\tofs = idx * getSizeOfType(arrty->getElementType());\n\t\t\telm = arrty->getElementType();\n\t\t}\n\t\telse if(str.type->isUnionType())\n\t\t{\n\t\t\t// we only support getting the id with insert/extractvalue.\n\t\t\ticeAssert(idx == 0);\n\t\t\telm = fir::Type::getNativeWord();\n\t\t\tofs = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto typelist = getTypeListOfType(str.type);\n\t\t\ticeAssert(idx < typelist.size());\n\n\t\t\tofs = getOffsetOfTypeInTypeList(typelist, idx);\n\t\t\telm = typelist[idx];\n\t\t}\n\n\t\tauto ret = is->makeValue(res);\n\t\ticeAssert(ret.type == elm);\n\n\t\tuintptr_t src = 0;\n\t\tif(str.dataSize > LARGE_DATA_SIZE)  src = reinterpret_cast<uintptr_t>(str.ptr);\n\t\telse                                src = reinterpret_cast<uintptr_t>(&str.data[0]);\n\n\t\tuintptr_t dst = 0;\n\t\tif(ret.dataSize > LARGE_DATA_SIZE)  dst = reinterpret_cast<uintptr_t>(ret.ptr);\n\t\telse                                dst = reinterpret_cast<uintptr_t>(&ret.data[0]);\n\n\t\tmemmove(reinterpret_cast<void*>(dst), reinterpret_cast<void*>(src + ofs), ret.dataSize);\n\n\t\treturn ret;\n\t}\n\n\t// this saves us a lot of copy/paste\n\n\ttemplate <typename Functor>\n\tstatic interp::Value oneArgumentOpIntOnly(InterpState* is, fir::Type* resty, const interp::Value& a, Functor op)\n\t{\n\t\tauto ty = a.type;\n\n\t\tinterp::Value res;\n\t\tres.dataSize = getSizeOfType(resty);\n\t\tres.type = resty;\n\n\t\tif(ty == Type::getInt8())   { auto tmp = op(getActualValue<int8_t>(a));    setValueRaw(is, &res, &tmp, sizeof(tmp)); return res; }\n\t\tif(ty == Type::getInt16())  { auto tmp = op(getActualValue<int16_t>(a));   setValueRaw(is, &res, &tmp, sizeof(tmp)); return res; }\n\t\tif(ty == Type::getInt32())  { auto tmp = op(getActualValue<int32_t>(a));   setValueRaw(is, &res, &tmp, sizeof(tmp)); return res; }\n\t\tif(ty == Type::getInt64())  { auto tmp = op(getActualValue<int64_t>(a));   setValueRaw(is, &res, &tmp, sizeof(tmp)); return res; }\n\t\tif(ty == Type::getUint8())  { auto tmp = op(getActualValue<uint8_t>(a));   setValueRaw(is, &res, &tmp, sizeof(tmp)); return res; }\n\t\tif(ty == Type::getUint16()) { auto tmp = op(getActualValue<uint16_t>(a));  setValueRaw(is, &res, &tmp, sizeof(tmp)); return res; }\n\t\tif(ty == Type::getUint32()) { auto tmp = op(getActualValue<uint32_t>(a));  setValueRaw(is, &res, &tmp, sizeof(tmp)); return res; }\n\t\tif(ty == Type::getUint64()) { auto tmp = op(getActualValue<uint64_t>(a));  setValueRaw(is, &res, &tmp, sizeof(tmp)); return res; }\n\t\tif(ty->isPointerType())     { auto tmp = op(getActualValue<uintptr_t>(a)); setValueRaw(is, &res, &tmp, sizeof(tmp)); return res; }\n\t\tif(ty->isBoolType())        { auto tmp = op(getActualValue<bool>(a));      setValueRaw(is, &res, &tmp, sizeof(tmp)); return res; }\n\t\telse                        error(\"interp: unsupported type '%s'\", ty);\n\t}\n\n\ttemplate <typename Functor>\n\tstatic interp::Value oneArgumentOpIntOnly(InterpState* is, const interp::Instruction& inst, const interp::Value& a, Functor op)\n\t{\n\t\tauto ret = oneArgumentOpIntOnly(is, inst.result->getType(), a, op);\n\t\tret.val = inst.result;\n\n\t\treturn ret;\n\t}\n\n\ttemplate <typename Functor>\n\tstatic interp::Value oneArgumentOp(InterpState* is, fir::Type* resty, const interp::Value& a, Functor op)\n\t{\n\t\tauto ty = a.type;\n\n\t\tif(!ty->isFloatingPointType())\n\t\t\treturn oneArgumentOpIntOnly(is, resty, a, op);\n\n\t\tinterp::Value res;\n\t\tres.dataSize = getSizeOfType(resty);\n\t\tres.type = resty;\n\n\t\tif(ty == Type::getFloat32())    { auto tmp = op(getActualValue<float>(a));  setValueRaw(is, &res, &tmp, sizeof(tmp)); return res; }\n\t\tif(ty == Type::getFloat64())    { auto tmp = op(getActualValue<double>(a)); setValueRaw(is, &res, &tmp, sizeof(tmp)); return res; }\n\t\telse                            error(\"interp: unsupported type '%s'\", ty);\n\t}\n\n\ttemplate <typename Functor>\n\tstatic interp::Value oneArgumentOp(InterpState* is, const interp::Instruction& inst, const interp::Value& a, Functor op)\n\t{\n\t\tauto ret = oneArgumentOp(is, inst.result->getType(), a, op);\n\t\tret.val = inst.result;\n\n\t\treturn ret;\n\t}\n\n\n\n\ttemplate <typename Functor>\n\tstatic interp::Value twoArgumentOpIntOnly(InterpState* is, fir::Type* resty, const interp::Value& a,\n\t\tconst interp::Value& b, Functor op)\n\t{\n\t\tauto aty = a.type;\n\t\tauto bty = b.type;\n\n\t\tusing i8tT  = int8_t;   auto i8t  = Type::getInt8();\n\t\tusing i16tT = int16_t;  auto i16t = Type::getInt16();\n\t\tusing i32tT = int32_t;  auto i32t = Type::getInt32();\n\t\tusing i64tT = int64_t;  auto i64t = Type::getInt64();\n\t\tusing u8tT  = uint8_t;  auto u8t  = Type::getUint8();\n\t\tusing u16tT = uint16_t; auto u16t = Type::getUint16();\n\t\tusing u32tT = uint32_t; auto u32t = Type::getUint32();\n\t\tusing u64tT = uint64_t; auto u64t = Type::getUint64();\n\n\t\t#define gav(t, x) getActualValue<t>(x)\n\n\t\tinterp::Value res;\n\t\tres.dataSize = getSizeOfType(resty);\n\t\tres.type = resty;\n\n\t\t#define If(at, bt) do { if(aty == (at) && bty == (bt)) {    \\\n\t\t\tauto tmp = op(gav(at##T, a), gav(bt##T, b));            \\\n\t\t\tsetValueRaw(is, &res, &tmp, sizeof(tmp));               \\\n\t\t\treturn res;                                             \\\n\t\t} } while(0)\n\n\t\t// FUCK LAH\n\t\tIf(i8t,  i8t); If(i8t,  i16t); If(i8t,  i32t); If(i8t,  i64t);\n\t\tIf(i16t, i8t); If(i16t, i16t); If(i16t, i32t); If(i16t, i64t);\n\t\tIf(i32t, i8t); If(i32t, i16t); If(i32t, i32t); If(i32t, i64t);\n\t\tIf(i64t, i8t); If(i64t, i16t); If(i64t, i32t); If(i64t, i64t);\n\n\t\tIf(u8t,  u8t); If(u8t,  u16t); If(u8t,  u32t); If(u8t,  u64t);\n\t\tIf(u16t, u8t); If(u16t, u16t); If(u16t, u32t); If(u16t, u64t);\n\t\tIf(u32t, u8t); If(u32t, u16t); If(u32t, u32t); If(u32t, u64t);\n\t\tIf(u64t, u8t); If(u64t, u16t); If(u64t, u32t); If(u64t, u64t);\n\n\t\tif(aty->isPointerType() && bty->isPointerType())\n\t\t{\n\t\t\tauto tmp = op(gav(uintptr_t, a), gav(uintptr_t, b));\n\t\t\tsetValueRaw(is, &res, &tmp, sizeof(tmp));\n\t\t\treturn res;\n\t\t}\n\t\tif(aty->isBoolType() && bty->isBoolType())\n\t\t{\n\t\t\tauto tmp = op(gav(bool, a), gav(bool, b));\n\t\t\tsetValueRaw(is, &res, &tmp, sizeof(tmp));\n\t\t\treturn res;\n\t\t}\n\n\t\terror(\"interp: unsupported types '%s' and '%s' for arithmetic\", aty, bty);\n\n\t\t#undef If\n\t\t#undef gav\n\t}\n\n\n\ttemplate <typename Functor>\n\tstatic interp::Value twoArgumentOp(InterpState* is, fir::Type* resty, const interp::Value& a,\n\t\t\tconst interp::Value& b, Functor op)\n\t{\n\t\tif(!(a.type->isFloatingPointType() || b.type->isFloatingPointType()))\n\t\t\treturn twoArgumentOpIntOnly(is, resty, a, b, op);\n\n\t\tauto aty = a.type;\n\t\tauto bty = b.type;\n\n\t\tusing i8tT  = int8_t;   auto i8t  = Type::getInt8();\n\t\tusing i16tT = int16_t;  auto i16t = Type::getInt16();\n\t\tusing i32tT = int32_t;  auto i32t = Type::getInt32();\n\t\tusing i64tT = int64_t;  auto i64t = Type::getInt64();\n\t\tusing u8tT  = uint8_t;  auto u8t  = Type::getUint8();\n\t\tusing u16tT = uint16_t; auto u16t = Type::getUint16();\n\t\tusing u32tT = uint32_t; auto u32t = Type::getUint32();\n\t\tusing u64tT = uint64_t; auto u64t = Type::getUint64();\n\t\tusing f32tT = float;    auto f32t = Type::getFloat32();\n\t\tusing f64tT = double;   auto f64t = Type::getFloat64();\n\n\t\t#define gav(t, x) getActualValue<t>(x)\n\n\t\tinterp::Value res;\n\t\tres.dataSize = getSizeOfType(resty);\n\t\tres.type = resty;\n\n\t\t#define If(at, bt) do { if(aty == (at) && bty == (bt)) {    \\\n\t\t\tauto tmp = op(gav(at##T, a), gav(bt##T, b));            \\\n\t\t\tsetValueRaw(is, &res, &tmp, sizeof(tmp));               \\\n\t\t\treturn res;                                             \\\n\t\t} } while(0)\n\n\t\t// FUCK LAH\n\t\tIf(i8t,  f32t); If(i8t,  f64t); If(u8t,  f32t); If(u8t,  f64t);\n\t\tIf(i16t, f32t); If(i16t, f64t); If(u16t, f32t); If(u16t, f64t);\n\t\tIf(i32t, f32t); If(i32t, f64t); If(u32t, f32t); If(u32t, f64t);\n\t\tIf(i64t, f32t); If(i64t, f64t); If(u64t, f32t); If(u64t, f64t);\n\n\t\tIf(f32t,  i8t); If(f64t,  i8t); If(f32t,  u8t); If(f64t,  u8t);\n\t\tIf(f32t, i16t); If(f64t, i16t); If(f32t, u16t); If(f64t, u16t);\n\t\tIf(f32t, i32t); If(f64t, i32t); If(f32t, u32t); If(f64t, u32t);\n\t\tIf(f32t, i64t); If(f64t, i64t); If(f32t, u64t); If(f64t, u64t);\n\n\t\tIf(f32t, f32t); If(f32t, f64t); If(f64t, f32t); If(f64t, f64t);\n\n\t\t#undef If\n\t\t#undef gav\n\n\t\terror(\"interp: unsupported types '%s' and '%s'\", aty, bty);\n\t}\n\n\n\n\n\ttemplate <typename Functor>\n\tstatic interp::Value twoArgumentOpIntOnly(InterpState* is, const interp::Instruction& inst, const interp::Value& a,\n\t\tconst interp::Value& b, Functor op)\n\t{\n\t\tauto ret = twoArgumentOpIntOnly(is, inst.result->getType(), a, b, op);\n\t\tret.val = inst.result;\n\n\t\treturn ret;\n\t}\n\n\ttemplate <typename Functor>\n\tstatic interp::Value twoArgumentOp(InterpState* is, const interp::Instruction& inst, const interp::Value& a,\n\t\tconst interp::Value& b, Functor op)\n\t{\n\t\tauto ret = twoArgumentOp(is, inst.result->getType(), a, b, op);\n\t\tret.val = inst.result;\n\n\t\treturn ret;\n\t}\n\n\n\n\n\tstatic void complainAboutFFIEscape(void* fnptr, fir::Type* fnty, const std::string& name)\n\t{\n\t\tif(frontend::getCanFFIEscape())\n\t\t\treturn;\n\n\t\tBareError* e = 0;\n\t\tif(name.empty())\n\t\t{\n\t\t\te = BareError::make(\"interp: cannot call external function (name unavailable; symbol address %p, function type '%s')\",\n\t\t\t\t\tfnptr, fnty->str());\n\t\t}\n\t\telse\n\t\t{\n\t\t\te = BareError::make(\"interp: cannot call external function '%s'\", name);\n\t\t}\n\n\t\te->append(BareError::make(MsgType::Note, \"to call external functions (ffi), pass '--ffi-escape' as a command-line flag\"));\n\t\te->postAndQuit();\n\t}\n\n\n\tstatic interp::Value runFunctionWithLibFFI(InterpState* is, void* fnptr, fir::FunctionType* fnty, const std::vector<interp::Value>& args,\n\t\tconst std::string& nameIfAvailable = \"\")\n\t{\n\t\tcomplainAboutFFIEscape(fnptr, fnty, nameIfAvailable);\n\n\t\t// we are assuming the values in 'args' are correct!\n\t\tffi_type** arg_types = new ffi_type*[args.size()];\n\t\t{\n\t\t\tstd::vector<ffi_type*> tmp;\n\t\t\tfor(size_t i = 0; i < args.size(); i++)\n\t\t\t{\n\t\t\t\ttmp.push_back(convertTypeToLibFFI(args[i].type));\n\t\t\t\targ_types[i] = tmp[i];\n\t\t\t}\n\t\t}\n\n\t\tffi_type* ffi_retty = 0;\n\t\tffi_cif fn_cif;\n\t\t{\n\t\t\tffi_retty = convertTypeToLibFFI(fnty->getReturnType());\n\n\t\t\tif(args.size() > fnty->getArgumentCount())\n\t\t\t{\n\t\t\t\ticeAssert(fnty->isCStyleVarArg());\n\t\t\t\tauto st = ffi_prep_cif_var(&fn_cif, FFI_DEFAULT_ABI, fnty->getArgumentCount(), args.size(), ffi_retty, arg_types);\n\t\t\t\tif(st != FFI_OK)\n\t\t\t\t\terror(\"interp: ffi_prep_cif_var failed! (%d)\", st);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto st = ffi_prep_cif(&fn_cif, FFI_DEFAULT_ABI, args.size(), ffi_retty, arg_types);\n\t\t\t\tif(st != FFI_OK)\n\t\t\t\t\terror(\"interp: ffi_prep_cif failed! (%d)\", st);\n\t\t\t}\n\t\t}\n\n\t\tvoid** arg_pointers = new void*[args.size()];\n\t\t{\n\t\t\tvoid** arg_values = new void*[args.size()];\n\n\t\t\t// because this thing is dumb\n\t\t\tfor(size_t i = 0; i < args.size(); i++)\n\t\t\t{\n\t\t\t\tif(args[i].dataSize <= LARGE_DATA_SIZE)\n\t\t\t\t\targ_values[i] = reinterpret_cast<void*>(const_cast<uint8_t*>(&args[i].data[0]));\n\t\t\t}\n\n\t\t\tfor(size_t i = 0; i < args.size(); i++)\n\t\t\t{\n\t\t\t\tif(args[i].dataSize <= LARGE_DATA_SIZE)\n\t\t\t\t\targ_pointers[i] = reinterpret_cast<void*>(arg_values[i]);\n\n\t\t\t\telse\n\t\t\t\t\targ_pointers[i] = reinterpret_cast<void*>(args[i].ptr);\n\t\t\t}\n\n\t\t\tdelete[] arg_values;\n\t\t}\n\n\t\tvoid* ret_buffer = new uint8_t[std::max(ffi_retty->size, size_t(8))];\n\t\tffi_call(&fn_cif, reinterpret_cast<void(*)()>(fnptr), ret_buffer, arg_pointers);\n\n\t\tinterp::Value ret = { 0 };\n\t\tret.type = fnty->getReturnType();\n\t\tret.dataSize = ffi_retty->size;\n\n\t\tsetValueRaw(is, &ret, ret_buffer, ret.dataSize);\n\t\tdelete[] ret_buffer;\n\n\t\tdelete[] arg_types;\n\t\tdelete[] arg_pointers;\n\n\t\treturn ret;\n\t}\n\n\tstatic interp::Value runFunctionWithLibFFI(InterpState* is, fir::Function* fn, const std::vector<interp::Value>& args)\n\t{\n\t\tvoid* fnptr = platform::compiler::getSymbol(fn->getName().str());\n\t\tif(!fnptr) error(\"interp: failed to find symbol named '%s'\\n\", fn->getName().str());\n\n\t\treturn runFunctionWithLibFFI(is, fnptr, fn->getType(), args, /* name: */ fn->getName().str());\n\t}\n\n\tstatic interp::Value runFunctionWithLibFFI(InterpState* is, const interp::Function& fn, const std::vector<interp::Value>& args)\n\t{\n\t\tvoid* fnptr = platform::compiler::getSymbol(fn.func->getName().str());\n\t\tif(!fnptr) error(\"interp: failed to find symbol named '%s'\\n\", fn.func->getName().str());\n\n\t\treturn runFunctionWithLibFFI(is, fnptr, fn.func->getType(), args, /* name: */ fn.extFuncName);\n\t}\n\n\n\tstatic const interp::Block* prepareFunctionToRun(InterpState* is, const interp::Function& fn, const std::vector<interp::Value>& args)\n\t{\n\t\ticeAssert(args.size() == fn.func->getArgumentCount());\n\n\t\t// when we start a function, clear the \"stack frame\".\n\t\tis->stackFrames.push_back({ });\n\n\t\tfor(size_t i = 0; i < args.size(); i++)\n\t\t{\n\t\t\tauto farg = fn.func->getArguments()[i];\n\t\t\tis->stackFrames.back().values[farg] = cloneValue(farg, args[i]);\n\t\t}\n\n\t\ticeAssert(!fn.blocks.empty());\n\n\t\tauto entry = &fn.blocks[0];\n\t\tis->stackFrames.back().currentFunction = &fn;\n\t\tis->stackFrames.back().currentBlock = entry;\n\t\tis->stackFrames.back().previousBlock = 0;\n\n\t\treturn entry;\n\t}\n\n\tstatic void leaveFunction(InterpState* is)\n\t{\n\t\tauto frame = is->stackFrames.back();\n\n\t\tfor(void* alloca : frame.stackAllocs)\n\t\t\tdelete[] alloca;\n\n\t\tis->stackFrames.pop_back();\n\t}\n\n\n\n\tconstexpr int FLOW_NORMAL = 0;\n\tconstexpr int FLOW_RETURN = 1;\n\tconstexpr int FLOW_BRANCH = 2;\n\tconstexpr int FLOW_FNCALL = 3;\n\tconstexpr int FLOW_DYCALL = 4;\n\n\n\tstruct InstrResult\n\t{\n\t\t// for ret\n\t\tinterp::Value returnValue;\n\n\t\t// for branches\n\t\tconst interp::Block* targetBlk = 0;\n\n\t\t// for calls\n\t\tinterp::Function* callTarget = 0;\n\t\tstd::vector<interp::Value> callArguments;\n\t\tfir::Value* callResultValue = 0;\n\n\t\t// for virtual calls. the args and resultvalue are shared.\n\t\tinterp::Value virtualCallTarget;\n\t};\n\n\tstatic int runInstruction(InterpState* is, const interp::Instruction& inst, InstrResult* instrRes);\n\n\tstatic interp::Value runBlock(InterpState* is, const interp::Block* blk)\n\t{\n\t\tfor(size_t i = 0; i < blk->instructions.size();)\n\t\t{\n\t\t\tis->stackFrames.back().currentInstrIndex = i;\n\n\t\t\tInstrResult res;\n\t\t\tint flow = runInstruction(is, blk->instructions[i], &res);\n\n\t\t\tswitch(flow)\n\t\t\t{\n\t\t\t\tcase FLOW_NORMAL: {\n\t\t\t\t\ti += 1;\n\t\t\t\t} break;\n\n\t\t\t\tcase FLOW_BRANCH: {\n\t\t\t\t\tis->stackFrames.back().previousBlock = blk;\n\t\t\t\t\tis->stackFrames.back().currentBlock = res.targetBlk;\n\n\t\t\t\t\tblk = res.targetBlk; i = 0;\n\t\t\t\t} break;\n\n\t\t\t\tcase FLOW_FNCALL: {\n\t\t\t\t\tif(res.callTarget->isExternal)\n\t\t\t\t\t{\n\t\t\t\t\t\tis->stackFrames.back().values[res.callResultValue] = runFunctionWithLibFFI(is, *res.callTarget, res.callArguments);\n\t\t\t\t\t\ti += 1;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tis->stackFrames.back().callResultOutput = res.callResultValue;\n\n\t\t\t\t\t\tauto newblk = prepareFunctionToRun(is, *res.callTarget, res.callArguments);\n\t\t\t\t\t\tblk = newblk; i = 0;\n\t\t\t\t\t}\n\t\t\t\t} break;\n\n\t\t\t\tcase FLOW_DYCALL: {\n\t\t\t\t\tauto ptr = getActualValue<uintptr_t>(res.virtualCallTarget);\n\t\t\t\t\tauto firfn = reinterpret_cast<fir::Function*>(ptr);\n\n\t\t\t\t\tif(auto it = is->compiledFunctions.find(firfn); it != is->compiledFunctions.end())\n\t\t\t\t\t{\n\t\t\t\t\t\tis->stackFrames.back().callResultOutput = res.callResultValue;\n\n\t\t\t\t\t\tauto newblk = prepareFunctionToRun(is, it->second, res.callArguments);\n\t\t\t\t\t\tblk = newblk; i = 0;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tauto targ = res.virtualCallTarget;\n\n\t\t\t\t\t\t// uwu. use libffi.\n\t\t\t\t\t\tfir::FunctionType* fnty = 0;\n\t\t\t\t\t\tif(targ.type->isFunctionType())\n\t\t\t\t\t\t\tfnty = targ.type->toFunctionType();\n\n\t\t\t\t\t\telse if(targ.type->isPointerType() && targ.type->getPointerElementType()->isFunctionType())\n\t\t\t\t\t\t\tfnty = targ.type->getPointerElementType()->toFunctionType();\n\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\terror(\"interp: call to function pointer with invalid type '%s'\", targ.type);\n\n\t\t\t\t\t\tis->stackFrames.back().values[res.callResultValue] = runFunctionWithLibFFI(is, reinterpret_cast<void*>(ptr),\n\t\t\t\t\t\t\tfnty, res.callArguments, /* name: */ res.callTarget->extFuncName);\n\n\t\t\t\t\t\ti += 1;\n\t\t\t\t\t}\n\t\t\t\t} break;\n\n\t\t\t\tcase FLOW_RETURN: {\n\t\t\t\t\tif(is->stackFrames.size() > 1)\n\t\t\t\t\t{\n\t\t\t\t\t\tleaveFunction(is);\n\t\t\t\t\t\tauto& frm = is->stackFrames.back();\n\n\t\t\t\t\t\tres.returnValue.val = frm.callResultOutput;\n\t\t\t\t\t\tfrm.values[frm.callResultOutput] = res.returnValue;\n\n\t\t\t\t\t\tblk = frm.currentBlock;\n\t\t\t\t\t\ti   = frm.currentInstrIndex + 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\treturn res.returnValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tdefault: {\n\t\t\t\t\terror(\"interp: invalid flow state\");\n\t\t\t\t} break;\n\t\t\t}\n\t\t}\n\n\t\terror(\"interp: invalid state\");\n\t}\n\n\n\n\n\tinterp::Value InterpState::runFunction(const interp::Function& fn, const std::vector<interp::Value>& args)\n\t{\n\t\tauto ffn = fn.func;\n\t\tif((!fn.func->isCStyleVarArg() && args.size() != fn.func->getArgumentCount())\n\t\t\t|| (fn.func->isCStyleVarArg() && args.size() < fn.func->getArgumentCount()))\n\t\t{\n\t\t\terror(\"interp: mismatched argument count in call to '%s': need %d, received %d\",\n\t\t\t\tfn.func->getName().str(), fn.func->getArgumentCount(), args.size());\n\t\t}\n\n\t\tif(fn.blocks.empty() || fn.func->isCStyleVarArg())\n\t\t{\n\t\t\t// it's probably an extern!\n\t\t\t// use libffi.\n\t\t\treturn runFunctionWithLibFFI(this, ffn, args);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto entry = prepareFunctionToRun(this, fn, args);\n\t\t\tauto ret = runBlock(this, entry);\n\t\t\tleaveFunction(this);\n\n\t\t\treturn ret;\n\t\t}\n\t}\n\n\n\n\tstatic interp::Value* getVal2(InterpState* is, fir::Value* fv)\n\t{\n\t\tif(auto it = is->stackFrames.back().values.find(fv); it != is->stackFrames.back().values.end())\n\t\t\treturn &it->second;\n\n\t\telse if(auto it2 = is->globals.find(fv); it2 != is->globals.end())\n\t\t\treturn &it2->second.first;\n\n\t\telse\n\t\t\treturn 0;\n\t}\n\n\tstatic interp::Value getVal(InterpState* is, fir::Value* fv)\n\t{\n\t\tif(auto hmm = getVal2(is, fv); hmm)\n\t\t\treturn *hmm;\n\n\t\telse if(auto cnst = dcast(fir::ConstantValue, fv); cnst)\n\t\t\treturn makeConstant(is, cnst);\n\n\t\telse\n\t\t\terror(\"interp: no value with id %d\", fv->id);\n\t}\n\n\n\tstatic interp::Value performGEP2(InterpState* is, fir::Type* resty, const interp::Value& ptr, const interp::Value& i1, const interp::Value& i2)\n\t{\n\t\ticeAssert(i1.type == i2.type);\n\n\t\t// so, ptr should be a pointer to an array.\n\t\ticeAssert(ptr.type->isPointerType() && ptr.type->getPointerElementType()->isArrayType());\n\n\t\tauto arrty = ptr.type->getPointerElementType();\n\t\tauto elmty = arrty->getArrayElementType();\n\n\t\tauto ofs = twoArgumentOp(is, resty, i1, i2, [arrty, elmty](auto a, auto b) -> auto {\n\t\t\treturn (getSizeOfType(arrty) * a) + (getSizeOfType(elmty) * b);\n\t\t});\n\n\t\tauto realptr = getActualValue<uintptr_t>(ptr);\n\t\tauto ret = oneArgumentOp(is, resty, ofs, [realptr](auto b) -> auto {\n\t\t\t// this is not pointer arithmetic!!\n\t\t\treturn realptr + b;\n\t\t});\n\n\t\tret.globalValTracker = ptr.globalValTracker;\n\t\treturn ret;\n\t}\n\n\n\tstatic interp::Value performStructGEP(InterpState* is, fir::Type* resty, const interp::Value& str, uint64_t idx)\n\t{\n\t\ticeAssert(str.type->isPointerType());\n\t\tauto strty = str.type->getPointerElementType();\n\n\t\tif(!strty->isStructType() && !strty->isClassType() && !strty->isTupleType())\n\t\t\terror(\"interp: unsupported type '%s' for struct gep\", strty);\n\n\t\tstd::vector<fir::Type*> elms = getTypeListOfType(strty);\n\n\t\tsize_t ofs = getOffsetOfTypeInTypeList(elms, idx);\n\t\tuintptr_t src = getActualValue<uintptr_t>(str);\n\t\tsrc += ofs;\n\n\t\tauto ret = cloneValue(str);\n\t\tret.type = resty;\n\t\tsetValueRaw(is, &ret, &src, sizeof(src));\n\n\t\tret.globalValTracker = str.globalValTracker;\n\t\treturn ret;\n\t}\n\n\tstatic interp::Value decay(const interp::Value& val)\n\t{\n\t\tif(val.val && val.val->islvalue())\n\t\t{\n\t\t\tauto ret = loadFromPtr(val, val.val->getType());\n\t\t\tret.val = val.val;\n\n\t\t\treturn ret;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn val;\n\t\t}\n\t}\n\n\tstatic interp::Value& getUndecayedArg(InterpState* is, const interp::Instruction& inst, size_t i)\n\t{\n\t\ticeAssert(i < inst.args.size());\n\t\tauto ret = getVal2(is, inst.args[i]);\n\t\ticeAssert(ret);\n\n\t\treturn *ret;\n\t}\n\n\tstatic interp::Value getArg(InterpState* is, const interp::Instruction& inst, size_t i)\n\t{\n\t\ticeAssert(i < inst.args.size());\n\t\treturn decay(getVal(is, inst.args[i]));\n\t}\n\n\tstatic void setRet(InterpState* is, const interp::Instruction& inst, const interp::Value& val)\n\t{\n\t\tis->stackFrames.back().values[inst.result] = val;\n\t}\n\n\tstatic bool areTypesSufficientlyEqual(fir::Type* a, fir::Type* b)\n\t{\n\t\treturn a == b || (a->isPointerType() && b->isPointerType() && a->getPointerElementType() == b->getPointerElementType());\n\t}\n\n\n\t// returns either FLOW_NORMAL, FLOW_BRANCH or FLOW_RETURN.\n\tstatic int runInstruction(InterpState* is, const interp::Instruction& inst, InstrResult* instrRes)\n\t{\n\t\tauto ok = static_cast<OpKind>(inst.opcode);\n\t\tswitch(ok)\n\t\t{\n\t\t\tcase OpKind::Signed_Add:\n\t\t\tcase OpKind::Unsigned_Add:\n\t\t\tcase OpKind::Floating_Add:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\ticeAssert(areTypesSufficientlyEqual(a.type, b.type));\n\t\t\t\tsetRet(is, inst, twoArgumentOp(is, inst, a, b, [](auto a, auto b) -> decltype(a) {\n\t\t\t\t\treturn a + b;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Signed_Sub:\n\t\t\tcase OpKind::Unsigned_Sub:\n\t\t\tcase OpKind::Floating_Sub:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\ticeAssert(areTypesSufficientlyEqual(a.type, b.type));\n\t\t\t\tsetRet(is, inst, twoArgumentOp(is, inst, a, b, [](auto a, auto b) -> decltype(a) {\n\t\t\t\t\treturn a - b;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Signed_Mul:\n\t\t\tcase OpKind::Unsigned_Mul:\n\t\t\tcase OpKind::Floating_Mul:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\ticeAssert(areTypesSufficientlyEqual(a.type, b.type));\n\t\t\t\tsetRet(is, inst, twoArgumentOp(is, inst, a, b, [](auto a, auto b) -> decltype(a) {\n\t\t\t\t\treturn a * b;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Signed_Div:\n\t\t\tcase OpKind::Unsigned_Div:\n\t\t\tcase OpKind::Floating_Div:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\ticeAssert(areTypesSufficientlyEqual(a.type, b.type));\n\t\t\t\tsetRet(is, inst, twoArgumentOp(is, inst, a, b, [](auto a, auto b) -> decltype(a) {\n\t\t\t\t\treturn a / b;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Signed_Mod:\n\t\t\tcase OpKind::Unsigned_Mod:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\ticeAssert(areTypesSufficientlyEqual(a.type, b.type));\n\t\t\t\tsetRet(is, inst, twoArgumentOpIntOnly(is, inst, a, b, [](auto a, auto b) -> decltype(a) {\n\t\t\t\t\treturn a % b;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Floating_Mod:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\ticeAssert(areTypesSufficientlyEqual(a.type, b.type));\n\t\t\t\tsetRet(is, inst, twoArgumentOp(is, inst, a, b, [](auto a, auto b) -> decltype(a) {\n\t\t\t\t\treturn fmod(a, b);\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\t\tcase OpKind::ICompare_Equal:\n\t\t\tcase OpKind::FCompare_Equal_ORD:\n\t\t\tcase OpKind::FCompare_Equal_UNORD:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\ticeAssert(areTypesSufficientlyEqual(a.type, b.type));\n\t\t\t\tsetRet(is, inst, twoArgumentOp(is, inst, a, b, [](auto a, auto b) -> bool {\n\t\t\t\t\treturn a == b;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::ICompare_NotEqual:\n\t\t\tcase OpKind::FCompare_NotEqual_ORD:\n\t\t\tcase OpKind::FCompare_NotEqual_UNORD:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\ticeAssert(areTypesSufficientlyEqual(a.type, b.type));\n\t\t\t\tsetRet(is, inst, twoArgumentOp(is, inst, a, b, [](auto a, auto b) -> bool {\n\t\t\t\t\treturn a != b;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::ICompare_Greater:\n\t\t\tcase OpKind::FCompare_Greater_ORD:\n\t\t\tcase OpKind::FCompare_Greater_UNORD:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\ticeAssert(areTypesSufficientlyEqual(a.type, b.type));\n\t\t\t\tsetRet(is, inst, twoArgumentOp(is, inst, a, b, [](auto a, auto b) -> bool {\n\t\t\t\t\treturn a > b;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::ICompare_Less:\n\t\t\tcase OpKind::FCompare_Less_ORD:\n\t\t\tcase OpKind::FCompare_Less_UNORD:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\ticeAssert(areTypesSufficientlyEqual(a.type, b.type));\n\t\t\t\tsetRet(is, inst, twoArgumentOp(is, inst, a, b, [](auto a, auto b) -> bool {\n\t\t\t\t\treturn a < b;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\t\tcase OpKind::ICompare_GreaterEqual:\n\t\t\tcase OpKind::FCompare_GreaterEqual_ORD:\n\t\t\tcase OpKind::FCompare_GreaterEqual_UNORD:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\ticeAssert(areTypesSufficientlyEqual(a.type, b.type));\n\t\t\t\tsetRet(is, inst, twoArgumentOp(is, inst, a, b, [](auto a, auto b) -> bool {\n\t\t\t\t\treturn a >= b;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::ICompare_LessEqual:\n\t\t\tcase OpKind::FCompare_LessEqual_ORD:\n\t\t\tcase OpKind::FCompare_LessEqual_UNORD:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\ticeAssert(areTypesSufficientlyEqual(a.type, b.type));\n\t\t\t\tsetRet(is, inst, twoArgumentOp(is, inst, a, b, [](auto a, auto b) -> bool {\n\t\t\t\t\treturn a <= b;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::ICompare_Multi:\n\t\t\tcase OpKind::FCompare_Multi:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\ticeAssert(areTypesSufficientlyEqual(a.type, b.type));\n\t\t\t\tsetRet(is, inst, twoArgumentOp(is, inst, a, b, [](auto a, auto b) -> int {\n\t\t\t\t\tif(a == b)  return 0;\n\t\t\t\t\tif(a > b)   return 1;\n\t\t\t\t\telse        return -1;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Bitwise_Xor:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\ticeAssert(areTypesSufficientlyEqual(a.type, b.type));\n\t\t\t\tsetRet(is, inst, twoArgumentOpIntOnly(is, inst, a, b, [](auto a, auto b) -> decltype(a) {\n\t\t\t\t\treturn a ^ b;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Bitwise_Logical_Shr:\n\t\t\tcase OpKind::Bitwise_Arithmetic_Shr:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\ticeAssert(a.type->isIntegerType());\n\t\t\t\tsetRet(is, inst, twoArgumentOpIntOnly(is, inst, a, b, [](auto a, auto b) -> decltype(a) {\n\t\t\t\t\treturn a >> b;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Bitwise_Shl:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\ticeAssert(a.type->isIntegerType());\n\t\t\t\tsetRet(is, inst, twoArgumentOpIntOnly(is, inst, a, b, [](auto a, auto b) -> decltype(a) {\n\t\t\t\t\treturn a << b;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Bitwise_And:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\ticeAssert(areTypesSufficientlyEqual(a.type, b.type));\n\t\t\t\tsetRet(is, inst, twoArgumentOpIntOnly(is, inst, a, b, [](auto a, auto b) -> decltype(a) {\n\t\t\t\t\treturn a & b;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Bitwise_Or:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\ticeAssert(areTypesSufficientlyEqual(a.type, b.type));\n\t\t\t\tsetRet(is, inst, twoArgumentOpIntOnly(is, inst, a, b, [](auto a, auto b) -> decltype(a) {\n\t\t\t\t\treturn a | b;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Signed_Neg:\n\t\t\tcase OpKind::Floating_Neg:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 1);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\n\t\t\t\tsetRet(is, inst, oneArgumentOp(is, inst, a, [](auto a) -> auto {\n\t\t\t\t\treturn -1 * a;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Bitwise_Not:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 1);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\n\t\t\t\tsetRet(is, inst, oneArgumentOpIntOnly(is, inst, a, [](auto a) -> auto {\n\t\t\t\t\treturn ~a;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Logical_Not:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 1);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\n\t\t\t\tsetRet(is, inst, oneArgumentOpIntOnly(is, inst, a, [](auto a) -> auto {\n\t\t\t\t\treturn !a;\n\t\t\t\t}));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Floating_Truncate:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 1);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto t = inst.args[1]->getType();\n\n\t\t\t\tinterp::Value ret;\n\t\t\t\tif(a.type == Type::getFloat64() && t == Type::getFloat32())\n\t\t\t\t\tret = makeValue(inst.result, static_cast<float>(getActualValue<double>(a)));\n\n\t\t\t\telse if(a.type == Type::getFloat32())   ret = makeValue(inst.result, getActualValue<float>(a));\n\t\t\t\telse if(a.type == Type::getFloat64())   ret = makeValue(inst.result, getActualValue<double>(a));\n\t\t\t\telse                                    error(\"interp: unsupported\");\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Floating_Extend:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 1);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto t = inst.args[1]->getType();\n\n\t\t\t\tinterp::Value ret;\n\t\t\t\tif(a.type == Type::getFloat32() && t == Type::getFloat64())\n\t\t\t\t\tret = makeValue(inst.result, static_cast<double>(getActualValue<float>(a)));\n\n\t\t\t\telse if(a.type == Type::getFloat32())   ret = makeValue(inst.result, getActualValue<float>(a));\n\t\t\t\telse if(a.type == Type::getFloat64())   ret = makeValue(inst.result, getActualValue<double>(a));\n\t\t\t\telse                                    error(\"interp: unsupported\");\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\n\n\t\t\tcase OpKind::Value_WritePtr:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\tif(a.type != b.type->getPointerElementType())\n\t\t\t\t\terror(\"interp: cannot write '%s' into '%s'\", a.type, b.type);\n\n\t\t\t\tauto ptr = reinterpret_cast<void*>(getActualValue<uintptr_t>(b));\n\t\t\t\tif(a.dataSize > LARGE_DATA_SIZE)\n\t\t\t\t{\n\t\t\t\t\t// just a memcopy.\n\t\t\t\t\tmemmove(ptr, a.ptr, a.dataSize);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// still a memcopy, but slightly more involved.\n\t\t\t\t\tmemmove(ptr, &a.data[0], a.dataSize);\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Value_ReadPtr:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 1);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\n\t\t\t\tauto ty = a.type->getPointerElementType();\n\n\t\t\t\tauto ret = loadFromPtr(a, ty);\n\t\t\t\tret.val = inst.result;\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\n\t\t\tcase OpKind::Value_CreatePHI:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 1);\n\t\t\t\tauto phi = dcast(fir::PHINode, inst.result);\n\t\t\t\ticeAssert(phi);\n\n\t\t\t\t// make the empty thing first\n\t\t\t\tauto val = is->makeValue(inst.result);\n\n\t\t\t\tbool found = false;\n\t\t\t\tfor(auto [ blk, v ] : phi->getValues())\n\t\t\t\t{\n\t\t\t\t\tif(blk == is->stackFrames.back().previousBlock->blk)\n\t\t\t\t\t{\n\t\t\t\t\t\tsetValue(is, &val, decay(getVal(is, v)));\n\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(!found) error(\"interp: predecessor was not listed in the PHI node (id %d)!\", phi->id);\n\n\t\t\t\tsetRet(is, inst, val);\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\n\n\n\t\t\tcase OpKind::Value_Return:\n\t\t\t{\n\t\t\t\tif(!inst.args.empty())\n\t\t\t\t\tinstrRes->returnValue = getArg(is, inst, 0);\n\n\t\t\t\treturn FLOW_RETURN;\n\t\t\t}\n\n\t\t\tcase OpKind::Branch_UnCond:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 1);\n\t\t\t\tauto blk = inst.args[0];\n\n\t\t\t\tconst interp::Block* target = 0;\n\t\t\t\tfor(const auto& b : is->stackFrames.back().currentFunction->blocks)\n\t\t\t\t{\n\t\t\t\t\tif(b.blk == blk)\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget = &b;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(!target) error(\"interp: branch to block %d not in current function\", blk->id);\n\n\t\t\t\tinstrRes->targetBlk = target;\n\t\t\t\treturn FLOW_BRANCH;\n\t\t\t}\n\n\t\t\tcase OpKind::Branch_Cond:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 3);\n\t\t\t\tauto cond = getArg(is, inst, 0);\n\t\t\t\ticeAssert(cond.type->isBoolType());\n\n\t\t\t\tconst interp::Block* trueblk = 0;\n\t\t\t\tconst interp::Block* falseblk = 0;\n\t\t\t\tfor(const auto& b : is->stackFrames.back().currentFunction->blocks)\n\t\t\t\t{\n\t\t\t\t\tif(b.blk == inst.args[1])\n\t\t\t\t\t\ttrueblk = &b;\n\n\t\t\t\t\telse if(b.blk == inst.args[2])\n\t\t\t\t\t\tfalseblk = &b;\n\n\t\t\t\t\tif(trueblk && falseblk)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif(!trueblk || !falseblk) error(\"interp: branch to blocks %d or %d not in current function\", trueblk->blk->id, falseblk->blk->id);\n\n\n\t\t\t\tif(getActualValue<bool>(cond))\n\t\t\t\t\tinstrRes->targetBlk = trueblk;\n\n\t\t\t\telse\n\t\t\t\t\tinstrRes->targetBlk = falseblk;\n\n\t\t\t\treturn FLOW_BRANCH;\n\t\t\t}\n\n\n\t\t\tcase OpKind::Value_CallFunction:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() >= 1);\n\t\t\t\tauto fn = inst.args[0];\n\n\t\t\t\tinterp::Function* target = 0;\n\n\t\t\t\t// we probably only compiled the entry function, so if we haven't compiled the target then please do\n\t\t\t\tif(auto it = is->compiledFunctions.find(fn); it != is->compiledFunctions.end())\n\t\t\t\t{\n\t\t\t\t\ttarget = &it->second;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfor(auto f : is->module->getAllFunctions())\n\t\t\t\t\t{\n\t\t\t\t\t\tif(f == fn)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttarget = &is->compileFunction(f);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(!target) error(\"interp: no function %d (name '%s')\", fn->id, fn->getName().str());\n\t\t\t\t}\n\n\t\t\t\ticeAssert(target);\n\n\t\t\t\tstd::vector<interp::Value> args;\n\t\t\t\tfor(size_t i = 1; i < inst.args.size(); i++)\n\t\t\t\t\targs.push_back(getArg(is, inst, i));\n\n\t\t\t\tinstrRes->callTarget = target;\n\t\t\t\tinstrRes->callArguments = args;\n\t\t\t\tinstrRes->callResultValue = inst.result;\n\n\t\t\t\treturn FLOW_FNCALL;\n\t\t\t}\n\n\n\n\t\t\tcase OpKind::Value_CallFunctionPointer:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() >= 1);\n\t\t\t\tauto fn = getArg(is, inst, 0);\n\n\t\t\t\tstd::vector<interp::Value> args;\n\t\t\t\tfor(size_t i = 1; i < inst.args.size(); i++)\n\t\t\t\t\targs.push_back(getArg(is, inst, i));\n\n\t\t\t\tinstrRes->callArguments = args;\n\t\t\t\tinstrRes->virtualCallTarget = fn;\n\t\t\t\tinstrRes->callResultValue = inst.result;\n\n\t\t\t\treturn FLOW_DYCALL;\n\t\t\t}\n\n\n\t\t\tcase OpKind::Value_CallVirtualMethod:\n\t\t\t{\n\t\t\t\t// args are: 0. classtype, 1. index, 2. functiontype, 3...N args\n\t\t\t\tauto clsty = inst.args[0]->getType()->toClassType();\n\t\t\t\tauto fnty = inst.args[2]->getType()->toFunctionType();\n\t\t\t\ticeAssert(clsty);\n\n\t\t\t\tstd::vector<interp::Value> args;\n\t\t\t\tfor(size_t i = 3; i < inst.args.size(); i++)\n\t\t\t\t\targs.push_back(getArg(is, inst, i));\n\n\t\t\t\t//* this is very hacky! we rely on these things not using ::val, because it's null!!\n\t\t\t\tauto vtable = loadFromPtr(performStructGEP(is, fir::Type::getInt8Ptr(), args[0], 0), fir::Type::getInt8Ptr());\n\t\t\t\tauto vtablety = fir::ArrayType::get(fir::FunctionType::get({ }, fir::Type::getVoid())->getPointerTo(), clsty->getVirtualMethodCount());\n\t\t\t\tvtable.type = vtablety->getPointerTo();\n\n\t\t\t\tvtable = performGEP2(is, vtablety->getPointerTo(), vtable, makeConstant(is, fir::ConstantInt::getNative(0)), getArg(is, inst, 1));\n\n\t\t\t\tauto fnptr = loadFromPtr(vtable, fnty->getPointerTo());\n\n\t\t\t\tinstrRes->callArguments = args;\n\t\t\t\tinstrRes->virtualCallTarget = fnptr;\n\t\t\t\tinstrRes->callResultValue = inst.result;\n\n\t\t\t\treturn FLOW_DYCALL;\n\t\t\t}\n\n\n\n\n\n\t\t\tcase OpKind::Cast_IntSize:\n\t\t\tcase OpKind::Integer_ZeroExt:\n\t\t\tcase OpKind::Integer_Truncate:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\tinterp::Value ret;\n\n\t\t\t\tif(a.type->isBoolType())\n\t\t\t\t{\n\t\t\t\t\t// since we don't want to add more cases to the thingy, we do a hack --\n\t\t\t\t\t// just get the value as a bool, then cast it to an i64 ourselves, then\n\t\t\t\t\t// pass *that* to the ops.\n\n\t\t\t\t\tauto boolval = static_cast<int64_t>(getActualValue<bool>(a));\n\t\t\t\t\tret = oneArgumentOp(is, inst, b, [boolval](auto b) -> auto {\n\t\t\t\t\t\treturn static_cast<decltype(b)>(boolval);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse if(b.type->isBoolType())\n\t\t\t\t{\n\t\t\t\t\tret = oneArgumentOp(is, inst, a, [](auto a) -> auto {\n\t\t\t\t\t\treturn static_cast<bool>(a);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tret = twoArgumentOp(is, inst, a, b, [](auto a, auto b) -> auto {\n\t\t\t\t\t\treturn static_cast<decltype(b)>(a);\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\t\t// TODO: these could be made more robust!!\n\t\t\tcase OpKind::Cast_Bitcast:\n\t\t\tcase OpKind::Cast_Signedness:\n\t\t\tcase OpKind::Cast_IntSignedness:\n\t\t\tcase OpKind::Cast_PointerType:\n\t\t\tcase OpKind::Cast_PointerToInt:\n\t\t\tcase OpKind::Cast_IntToPointer:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\n\t\t\t\tauto v = cloneValue(inst.result, getArg(is, inst, 0));\n\t\t\t\tv.type = inst.args[1]->getType();\n\n\t\t\t\tsetRet(is, inst, v);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Cast_FloatToInt:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\tinterp::Value ret = twoArgumentOp(is, inst, a, b, [](auto a, auto b) -> auto {\n\t\t\t\t\treturn static_cast<decltype(b)>(a);\n\t\t\t\t});\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Cast_IntToFloat:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\tinterp::Value ret = twoArgumentOp(is, inst, a, b, [](auto a, auto b) -> auto {\n\t\t\t\t\treturn static_cast<decltype(b)>(a);\n\t\t\t\t});\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\t\tcase OpKind::Value_GetPointer:\n\t\t\t{\n\t\t\t\t// equivalent to GEP(ptr*, index)\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto ptr = getArg(is, inst, 0);\n\t\t\t\tauto b = getArg(is, inst, 1);\n\n\t\t\t\ticeAssert(ptr.type->isPointerType());\n\t\t\t\ticeAssert(b.type->isIntegerType());\n\n\t\t\t\tauto elmty = ptr.type->getPointerElementType();\n\n\t\t\t\tauto realptr = getActualValue<uintptr_t>(ptr);\n\t\t\t\tsetRet(is, inst, oneArgumentOp(is, inst, b, [realptr, elmty](auto b) -> auto {\n\t\t\t\t\t// this doesn't do pointer arithmetic!! if it's a pointer type, the value we get\n\t\t\t\t\t// will be a uintptr_t.\n\t\t\t\t\treturn realptr + (getSizeOfType(elmty) * b);\n\t\t\t\t}));\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Value_GetGEP2:\n\t\t\t{\n\t\t\t\t// equivalent to GEP(ptr*, index1, index2)\n\t\t\t\ticeAssert(inst.args.size() == 3);\n\t\t\t\tauto ptr = getArg(is, inst, 0);\n\t\t\t\tauto i1 = getArg(is, inst, 1);\n\t\t\t\tauto i2 = getArg(is, inst, 2);\n\n\t\t\t\tauto ret = performGEP2(is, inst.result->getType(), ptr, i1, i2);\n\t\t\t\tret.val = inst.result;\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Value_GetStructMember:\n\t\t\t{\n\t\t\t\t// equivalent to GEP(ptr*, 0, memberIndex)\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto str = getUndecayedArg(is, inst, 0);\n\t\t\t\tauto idx = dcast(fir::ConstantInt, inst.args[1])->getUnsignedValue();\n\n\t\t\t\tauto ret = performStructGEP(is, inst.result->getType()->getPointerTo(), str, idx);\n\t\t\t\tret.val = inst.result;\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\n\t\t\tcase OpKind::Value_GetPointerToStructMember:\n\t\t\t{\n\t\t\t\t// equivalent to llvm's GEP(ptr*, ptrIndex, memberIndex)\n\t\t\t\terror(\"interp: enotsup\");\n\t\t\t}\n\n\n\n\n\n\t\t\tcase OpKind::Misc_Sizeof:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 1);\n\t\t\t\tauto ty = inst.args[0]->getType();\n\n\t\t\t\tauto ci = fir::ConstantInt::getNative(getSizeOfType(ty));\n\n\t\t\t\tif(fir::getNativeWordSizeInBits() == 64) setRet(is, inst, makeValue(inst.result, static_cast<int64_t>(ci->getSignedValue())));\n\t\t\t\tif(fir::getNativeWordSizeInBits() == 32) setRet(is, inst, makeValue(inst.result, static_cast<int32_t>(ci->getSignedValue())));\n\t\t\t\tif(fir::getNativeWordSizeInBits() == 16) setRet(is, inst, makeValue(inst.result, static_cast<int16_t>(ci->getSignedValue())));\n\t\t\t\tif(fir::getNativeWordSizeInBits() == 8)  setRet(is, inst, makeValue(inst.result, static_cast<int8_t>(ci->getSignedValue())));\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\t\tcase OpKind::Value_CreateLVal:\n\t\t\tcase OpKind::Value_StackAlloc:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 1);\n\n\t\t\t\tauto ty = inst.args[0]->getType();\n\t\t\t\tauto sz = getSizeOfType(ty);\n\n\t\t\t\tvoid* buffer = new uint8_t[sz];\n\t\t\t\tmemset(buffer, 0, sz);\n\n\t\t\t\tis->stackFrames.back().stackAllocs.push_back(buffer);\n\n\t\t\t\tauto ret = makeValueOfType(inst.result, ty->getPointerTo());\n\t\t\t\tsetValueRaw(is, &ret, &buffer, sizeof(void*));\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Value_Store:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto b = getUndecayedArg(is, inst, 1);\n\n\t\t\t\tauto ptr = reinterpret_cast<void*>(getActualValue<uintptr_t>(b));\n\t\t\t\tif(a.dataSize > LARGE_DATA_SIZE)    memmove(ptr, a.ptr, a.dataSize);\n\t\t\t\telse                                memmove(ptr, &a.data[0], a.dataSize);\n\n\t\t\t\tif(b.globalValTracker)\n\t\t\t\t{\n\t\t\t\t\t// set the modified flag to true!\n\t\t\t\t\tis->globals[b.globalValTracker].second = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Value_AddressOf:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 1);\n\t\t\t\tauto ret = cloneValue(inst.result, getUndecayedArg(is, inst, 0));\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Value_Dereference:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 1);\n\t\t\t\tauto a = getArg(is, inst, 0);\n\t\t\t\tauto ret = cloneValue(inst.result, a);\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Value_Select:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 3);\n\t\t\t\tauto cond = getArg(is, inst, 0);\n\t\t\t\ticeAssert(cond.type->isBoolType());\n\n\t\t\t\tauto trueval = getArg(is, inst, 1);\n\t\t\t\tauto falseval = getArg(is, inst, 2);\n\n\t\t\t\tif(getActualValue<bool>(cond))  setRet(is, inst, trueval);\n\t\t\t\telse                            setRet(is, inst, falseval);\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\n\t\t\tcase OpKind::Value_InsertValue:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 3);\n\n\t\t\t\tauto str = getArg(is, inst, 0);\n\t\t\t\tauto elm = getArg(is, inst, 1);\n\t\t\t\tauto idx = static_cast<size_t>(getActualValue<int64_t>(getArg(is, inst, 2)));\n\n\t\t\t\tsetRet(is, inst, doInsertValue(is, inst.result, str, elm, idx));\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\t\tcase OpKind::Value_ExtractValue:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() >= 2);\n\n\t\t\t\tauto str = getArg(is, inst, 0);\n\t\t\t\tauto idx = static_cast<size_t>(getActualValue<int64_t>(getArg(is, inst, 1)));\n\n\t\t\t\tsetRet(is, inst, doExtractValue(is, inst.result, str, idx));\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\t\tcase OpKind::SAA_GetData:\n\t\t\tcase OpKind::SAA_GetLength:\n\t\t\tcase OpKind::SAA_GetCapacity:\n\t\t\tcase OpKind::SAA_GetRefCountPtr:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 1);\n\t\t\t\tauto str = getArg(is, inst, 0);\n\n\t\t\t\tinterp::Value ret;\n\n\t\t\t\tif(ok == OpKind::SAA_GetData)\n\t\t\t\t\tret = doExtractValue(is, inst.result, str, SAA_DATA_INDEX);\n\n\t\t\t\telse if(ok == OpKind::SAA_GetLength)\n\t\t\t\t\tret = doExtractValue(is, inst.result, str, SAA_LENGTH_INDEX);\n\n\t\t\t\telse if(ok == OpKind::SAA_GetCapacity)\n\t\t\t\t\tret = doExtractValue(is, inst.result, str, SAA_CAPACITY_INDEX);\n\n\t\t\t\telse if(ok == OpKind::SAA_GetRefCountPtr)\n\t\t\t\t\tret = doExtractValue(is, inst.result, str, SAA_REFCOUNTPTR_INDEX);\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::SAA_SetData:\n\t\t\tcase OpKind::SAA_SetLength:\n\t\t\tcase OpKind::SAA_SetCapacity:\n\t\t\tcase OpKind::SAA_SetRefCountPtr:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto str = getArg(is, inst, 0);\n\t\t\t\tauto elm = getArg(is, inst, 1);\n\n\t\t\t\tinterp::Value ret;\n\n\t\t\t\tif(ok == OpKind::SAA_SetData)\n\t\t\t\t\tret = doInsertValue(is, inst.result, str, elm, SAA_DATA_INDEX);\n\n\t\t\t\telse if(ok == OpKind::SAA_SetLength)\n\t\t\t\t\tret = doInsertValue(is, inst.result, str, elm, SAA_LENGTH_INDEX);\n\n\t\t\t\telse if(ok == OpKind::SAA_SetCapacity)\n\t\t\t\t\tret = doInsertValue(is, inst.result, str, elm, SAA_CAPACITY_INDEX);\n\n\t\t\t\telse if(ok == OpKind::SAA_SetRefCountPtr)\n\t\t\t\t\tret = doInsertValue(is, inst.result, str, elm, SAA_REFCOUNTPTR_INDEX);\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::ArraySlice_GetData:\n\t\t\tcase OpKind::ArraySlice_GetLength:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 1);\n\t\t\t\tauto str = getArg(is, inst, 0);\n\n\t\t\t\tinterp::Value ret;\n\n\t\t\t\tif(ok == OpKind::ArraySlice_GetData)\n\t\t\t\t\tret = doExtractValue(is, inst.result, str, SLICE_DATA_INDEX);\n\n\t\t\t\telse if(ok == OpKind::ArraySlice_GetLength)\n\t\t\t\t\tret = doExtractValue(is, inst.result, str, SLICE_LENGTH_INDEX);\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\n\t\t\tcase OpKind::ArraySlice_SetData:\n\t\t\tcase OpKind::ArraySlice_SetLength:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto str = getArg(is, inst, 0);\n\t\t\t\tauto elm = getArg(is, inst, 1);\n\n\t\t\t\tinterp::Value ret;\n\n\t\t\t\tif(ok == OpKind::ArraySlice_SetData)\n\t\t\t\t\tret = doInsertValue(is, inst.result, str, elm, SLICE_DATA_INDEX);\n\n\t\t\t\telse if(ok == OpKind::ArraySlice_SetLength)\n\t\t\t\t\tret = doInsertValue(is, inst.result, str, elm, SLICE_LENGTH_INDEX);\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Any_GetData:\n\t\t\tcase OpKind::Any_GetTypeID:\n\t\t\tcase OpKind::Any_GetRefCountPtr:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 1);\n\t\t\t\tauto str = getArg(is, inst, 0);\n\n\t\t\t\tinterp::Value ret;\n\n\t\t\t\tif(ok == OpKind::Any_GetTypeID)\n\t\t\t\t\tret = doExtractValue(is, inst.result, str, ANY_TYPEID_INDEX);\n\n\t\t\t\telse if(ok == OpKind::Any_GetRefCountPtr)\n\t\t\t\t\tret = doExtractValue(is, inst.result, str, ANY_REFCOUNTPTR_INDEX);\n\n\t\t\t\telse if(ok == OpKind::Any_GetData)\n\t\t\t\t\tret = doExtractValue(is, inst.result, str, ANY_DATA_ARRAY_INDEX);\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Any_SetData:\n\t\t\tcase OpKind::Any_SetTypeID:\n\t\t\tcase OpKind::Any_SetRefCountPtr:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto str = getArg(is, inst, 0);\n\t\t\t\tauto elm = getArg(is, inst, 1);\n\n\t\t\t\tinterp::Value ret;\n\n\t\t\t\tif(ok == OpKind::Any_SetTypeID)\n\t\t\t\t\tret = doInsertValue(is, inst.result, str, elm, ANY_TYPEID_INDEX);\n\n\t\t\t\telse if(ok == OpKind::Any_SetRefCountPtr)\n\t\t\t\t\tret = doInsertValue(is, inst.result, str, elm, ANY_REFCOUNTPTR_INDEX);\n\n\t\t\t\telse if(ok == OpKind::Any_SetData)\n\t\t\t\t\tret = doInsertValue(is, inst.result, str, elm, ANY_DATA_ARRAY_INDEX);\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\n\t\t\tcase OpKind::Range_GetLower:\n\t\t\tcase OpKind::Range_GetUpper:\n\t\t\tcase OpKind::Range_GetStep:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 1);\n\t\t\t\tauto str = getArg(is, inst, 0);\n\n\t\t\t\tinterp::Value ret;\n\n\t\t\t\tif(ok == OpKind::Range_GetLower)\n\t\t\t\t\tret = doExtractValue(is, inst.result, str, 0);\n\n\t\t\t\telse if(ok == OpKind::Range_GetUpper)\n\t\t\t\t\tret = doExtractValue(is, inst.result, str, 1);\n\n\t\t\t\telse if(ok == OpKind::Range_GetStep)\n\t\t\t\t\tret = doExtractValue(is, inst.result, str, 2);\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\t\tcase OpKind::Range_SetLower:\n\t\t\tcase OpKind::Range_SetUpper:\n\t\t\tcase OpKind::Range_SetStep:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto str = getArg(is, inst, 0);\n\t\t\t\tauto elm = getArg(is, inst, 1);\n\n\t\t\t\tinterp::Value ret;\n\n\t\t\t\tif(ok == OpKind::Range_SetLower)\n\t\t\t\t\tret = doInsertValue(is, inst.result, str, elm, 0);\n\n\t\t\t\telse if(ok == OpKind::Range_SetUpper)\n\t\t\t\t\tret = doInsertValue(is, inst.result, str, elm, 1);\n\n\t\t\t\telse if(ok == OpKind::Range_SetStep)\n\t\t\t\t\tret = doInsertValue(is, inst.result, str, elm, 2);\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\n\t\t\tcase OpKind::Enum_GetIndex:\n\t\t\tcase OpKind::Enum_GetValue:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 1);\n\t\t\t\tauto str = getArg(is, inst, 0);\n\n\t\t\t\tinterp::Value ret;\n\n\t\t\t\tif(ok == OpKind::Enum_GetIndex)\n\t\t\t\t\tret = doExtractValue(is, inst.result, str, 0);\n\n\t\t\t\telse if(ok == OpKind::Enum_GetValue)\n\t\t\t\t\tret = doExtractValue(is, inst.result, str, 1);\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\t\tcase OpKind::Enum_SetIndex:\n\t\t\tcase OpKind::Enum_SetValue:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto str = getArg(is, inst, 0);\n\t\t\t\tauto elm = getArg(is, inst, 1);\n\n\t\t\t\tinterp::Value ret;\n\n\t\t\t\tif(ok == OpKind::Enum_SetIndex)\n\t\t\t\t\tret = doInsertValue(is, inst.result, str, elm, 0);\n\n\t\t\t\telse if(ok == OpKind::Enum_SetValue)\n\t\t\t\t\tret = doInsertValue(is, inst.result, str, elm, 1);\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\t\tcase OpKind::Union_GetVariantID:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 1);\n\t\t\t\tauto str = getArg(is, inst, 0);\n\n\t\t\t\tsetRet(is, inst, doExtractValue(is, inst.result, str, 0));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Union_SetVariantID:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto str = getArg(is, inst, 0);\n\t\t\t\tauto elm = getArg(is, inst, 1);\n\n\t\t\t\tsetRet(is, inst, doInsertValue(is, inst.result, str, elm, 0));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase OpKind::Union_GetValue:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\ticeAssert(inst.args[0]->getType()->isUnionType());\n\n\t\t\t\tauto ut = inst.args[0]->getType()->toUnionType();\n\t\t\t\tauto vid = dcast(fir::ConstantInt, inst.args[1])->getSignedValue();\n\n\t\t\t\ticeAssert(static_cast<size_t>(vid) < ut->getVariantCount());\n\t\t\t\tauto vt = ut->getVariant(vid)->getInteriorType();\n\n\t\t\t\t// because we can operate with the raw memory values, we can probably do this a bit more efficiently\n\t\t\t\t// than we can with LLVM, where we needed to create a temporary stack value to store the thing from\n\t\t\t\t// the extractvalue so we could cast-to-pointer then load.\n\n\t\t\t\t// first we just get the argument:\n\t\t\t\tauto theUnion = getArg(is, inst, 0);\n\n\t\t\t\t// then, get the array:\n\t\t\t\tuintptr_t arrayAddr = 0;\n\t\t\t\tif(theUnion.dataSize > LARGE_DATA_SIZE) arrayAddr = reinterpret_cast<uintptr_t>(theUnion.ptr);\n\t\t\t\telse                                    arrayAddr = reinterpret_cast<uintptr_t>(&theUnion.data[0]);\n\n\t\t\t\t// offset it appropriately:\n\t\t\t\tarrayAddr += getSizeOfType(fir::Type::getNativeWord());\n\n\t\t\t\t// ok so now we just do a 'setRaw' to get the value out.\n\t\t\t\tauto ret = is->makeValue(inst.result);\n\t\t\t\tsetValueRaw(is, &ret, reinterpret_cast<void*>(arrayAddr), getSizeOfType(vt));\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\t\tcase OpKind::Union_SetValue:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 3);\n\t\t\t\ticeAssert(inst.args[0]->getType()->isUnionType());\n\n\t\t\t\tauto ut = inst.args[0]->getType()->toUnionType();\n\t\t\t\tauto vid = static_cast<intptr_t>(dcast(fir::ConstantInt, inst.args[1])->getSignedValue());\n\n\t\t\t\ticeAssert(static_cast<size_t>(vid) < ut->getVariantCount());\n\n\t\t\t\t// again, we do this \"manually\" because we can access the raw bytes, so we don't have to\n\t\t\t\t// twist ourselves through hoops like with llvm.\n\n\t\t\t\t// first we just get the argument:\n\t\t\t\tauto theUnion = cloneValue(inst.result, getArg(is, inst, 0));\n\n\t\t\t\t// then, get the array:\n\t\t\t\tuintptr_t baseAddr = 0;\n\t\t\t\tif(theUnion.dataSize > LARGE_DATA_SIZE) baseAddr = reinterpret_cast<uintptr_t>(theUnion.ptr);\n\t\t\t\telse                                    baseAddr = reinterpret_cast<uintptr_t>(&theUnion.data[0]);\n\n\t\t\t\t// offset it appropriately:\n\t\t\t\tauto arrayAddr = baseAddr + getSizeOfType(fir::Type::getNativeWord());\n\n\t\t\t\t// ok, now we just do a memcpy into the struct.\n\t\t\t\ticeAssert(sizeof(intptr_t) == (fir::getNativeWordSizeInBits() / CHAR_BIT));\n\t\t\t\tmemmove(reinterpret_cast<void*>(baseAddr), &vid, sizeof(intptr_t));\n\n\t\t\t\tuintptr_t valueAddr = 0;\n\t\t\t\tauto theValue = getArg(is, inst, 2);\n\t\t\t\tif(theValue.dataSize > LARGE_DATA_SIZE) valueAddr = reinterpret_cast<uintptr_t>(theValue.ptr);\n\t\t\t\telse                                    valueAddr = reinterpret_cast<uintptr_t>(&theValue.data[0]);\n\n\t\t\t\tmemmove(reinterpret_cast<void*>(arrayAddr), reinterpret_cast<void*>(valueAddr), theValue.dataSize);\n\n\t\t\t\tsetRet(is, inst, theUnion);\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\t\tcase OpKind::RawUnion_GEP:\n\t\t\t{\n\t\t\t\ticeAssert(inst.args.size() == 2);\n\t\t\t\tauto targtype = inst.args[1]->getType();\n\n\t\t\t\t// again. just manipulate the memory.\n\t\t\t\tauto unn = getUndecayedArg(is, inst, 0);\n\t\t\t\tauto buffer = getActualValue<uintptr_t>(unn);\n\n\t\t\t\tauto ret = makeValueOfType(inst.result, targtype->getPointerTo());\n\t\t\t\tsetValueRaw(is, &ret, &buffer, sizeof(uintptr_t));\n\n\t\t\t\tsetRet(is, inst, ret);\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\n\t\t\tcase OpKind::Unreachable:\n\t\t\t{\n\t\t\t\terror(\"interp: unreachable op!\");\n\t\t\t}\n\n\t\t\tcase OpKind::Invalid:\n\t\t\tdefault:\n\t\t\t{\n\t\t\t\t// note we don't use \"default\" to catch\n\t\t\t\t// new opkinds that we forget to add.\n\t\t\t\terror(\"interp: invalid opcode %d!\", inst.opcode);\n\t\t\t}\n\t\t}\n\n\t\treturn FLOW_NORMAL;\n\t}\n\n\n\tfir::ConstantValue* InterpState::unwrapInterpValueIntoConstant(const interp::Value& val)\n\t{\n\t\tauto ty = val.type;\n\n\t\t#define gav getActualValue\n\n\t\tauto extractOneValue = [this](const interp::Value& v, size_t idx, fir::Type* ty) -> interp::Value {\n\t\t\tauto tmp = fir::ConstantValue::getZeroValue(ty);\n\t\t\tauto x = doExtractValue(this, tmp, v, idx);\n\t\t\tdelete tmp;\n\n\t\t\treturn x;\n\t\t};\n\n\t\tauto extractValueList = [this, extractOneValue](const interp::Value& v, const std::vector<fir::Type*>& tys)\n\t\t\t-> std::vector<fir::ConstantValue*>\n\t\t{\n\t\t\tstd::vector<fir::ConstantValue*> elms;\n\n\t\t\tfor(size_t i = 0; i < tys.size(); i++)\n\t\t\t{\n\t\t\t\tauto x = extractOneValue(v, i, tys[i]);\n\t\t\t\telms.push_back(this->unwrapInterpValueIntoConstant(x));\n\t\t\t}\n\n\t\t\treturn elms;\n\t\t};\n\n\t\tif(ty->isPrimitiveType() || ty->isBoolType())\n\t\t{\n\t\t\tif(ty == fir::Type::getBool())          return fir::ConstantBool::get(gav<bool>(val));\n\t\t\telse if(ty == fir::Type::getInt8())     return fir::ConstantInt::get(ty, gav<int8_t>(val));\n\t\t\telse if(ty == fir::Type::getInt16())    return fir::ConstantInt::get(ty, gav<int16_t>(val));\n\t\t\telse if(ty == fir::Type::getInt32())    return fir::ConstantInt::get(ty, gav<int32_t>(val));\n\t\t\telse if(ty == fir::Type::getInt64())    return fir::ConstantInt::get(ty, gav<int64_t>(val));\n\t\t\telse if(ty == fir::Type::getUint8())    return fir::ConstantInt::get(ty, gav<uint8_t>(val));\n\t\t\telse if(ty == fir::Type::getUint16())   return fir::ConstantInt::get(ty, gav<uint16_t>(val));\n\t\t\telse if(ty == fir::Type::getUint32())   return fir::ConstantInt::get(ty, gav<uint32_t>(val));\n\t\t\telse if(ty == fir::Type::getUint64())   return fir::ConstantInt::get(ty, gav<uint64_t>(val));\n\t\t\telse if(ty == fir::Type::getFloat32())  return fir::ConstantFP::get(ty, gav<float>(val));\n\t\t\telse if(ty == fir::Type::getFloat64())  return fir::ConstantFP::get(ty, gav<double>(val));\n\t\t}\n\t\telse if(ty->isTupleType())\n\t\t{\n\t\t\treturn fir::ConstantTuple::get(extractValueList(val, ty->toTupleType()->getElements()));\n\t\t}\n\t\telse if(ty->isArrayType())\n\t\t{\n\t\t\treturn fir::ConstantArray::get(ty, extractValueList(val,\n\t\t\t\tstd::vector<fir::Type*>(ty->toArrayType()->getArraySize(), ty->getArrayElementType())));\n\t\t}\n\t\telse if(ty->isCharSliceType())\n\t\t{\n\t\t\t// do a bit of stuff -- extract the pointer, then the length.\n\t\t\tchar* ptr = gav<char*>(extractOneValue(val, SLICE_DATA_INDEX, ty->toArraySliceType()->getDataPointerType()));\n\t\t\tint64_t len = gav<int64_t>(extractOneValue(val, SLICE_LENGTH_INDEX, fir::Type::getInt64()));\n\n\t\t\treturn fir::ConstantCharSlice::get(std::string(ptr, len));\n\t\t}\n\t\telse if(ty->isStringType())\n\t\t{\n\t\t\tchar* ptr = gav<char*>(extractOneValue(val, SAA_DATA_INDEX, fir::Type::getMutInt8Ptr()));\n\t\t\tint64_t len = gav<int64_t>(extractOneValue(val, SAA_LENGTH_INDEX, fir::Type::getInt64()));\n\n\t\t\treturn fir::ConstantDynamicString::get(std::string(ptr, len));\n\t\t}\n\t\telse if(ty->isArraySliceType())\n\t\t{\n\t\t\tauto ptr = this->unwrapInterpValueIntoConstant(extractOneValue(val, SLICE_DATA_INDEX,\n\t\t\t\tty->toArraySliceType()->getDataPointerType()));\n\n\t\t\tauto len = this->unwrapInterpValueIntoConstant(extractOneValue(val, SLICE_LENGTH_INDEX,\n\t\t\t\tfir::Type::getInt64()));\n\n\t\t\treturn fir::ConstantArraySlice::get(ty->toArraySliceType(), ptr, len);\n\t\t}\n\t\telse if(ty->isDynamicArrayType())\n\t\t{\n\t\t\tauto ptr = this->unwrapInterpValueIntoConstant(extractOneValue(val, SAA_DATA_INDEX,\n\t\t\t\tty->getArrayElementType()->getMutablePointerTo()));\n\n\t\t\tauto len = this->unwrapInterpValueIntoConstant(extractOneValue(val, SAA_LENGTH_INDEX, fir::Type::getInt64()));\n\t\t\tauto cap = this->unwrapInterpValueIntoConstant(extractOneValue(val, SAA_CAPACITY_INDEX, fir::Type::getInt64()));\n\n\t\t\treturn fir::ConstantDynamicArray::get(ty->toDynamicArrayType(), ptr, len, cap);\n\t\t}\n\t\telse if(ty->isStructType())\n\t\t{\n\t\t\tauto sty = ty->toStructType();\n\t\t\tstd::vector<fir::ConstantValue*> vals = extractValueList(val, sty->getElements());\n\n\t\t\treturn fir::ConstantStruct::get(sty, vals);\n\t\t}\n\n\t\t#undef gav\n\n\t\twarn(\"interp: cannot unwrap type '%s'\", ty);\n\t\treturn fir::ConstantValue::getZeroValue(ty);\n\t}\n}\n}\n\n\n#ifdef _MSC_VER\n\t#pragma warning(pop)\n#else\n\t#pragma GCC diagnostic pop\n#endif\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/fir/interp/wrappers.cpp",
    "content": "// wrappers.cpp\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"defs.h\"\n#include \"platform.h\"\n#include \"ir/module.h\"\n\n#include \"ir/interp.h\"\n\n\nPLATFORM_EXPORT_FUNCTION\nvoid __interp_intrinsic_memset(void* dst, int8_t val, size_t cnt, bool)\n{\n\tmemset(dst, val, cnt);\n}\n\nPLATFORM_EXPORT_FUNCTION\nvoid __interp_intrinsic_memcpy(void* dst, void* src, size_t cnt, bool)\n{\n\tmemcpy(dst, src, cnt);\n}\n\nPLATFORM_EXPORT_FUNCTION\nvoid __interp_intrinsic_memmove(void* dst, void* src, size_t cnt, bool)\n{\n\tmemmove(dst, src, cnt);\n}\n\nPLATFORM_EXPORT_FUNCTION\nint __interp_intrinsic_memcmp(void* a, void*b, size_t cnt, bool)\n{\n\treturn memcmp(a, b, cnt);\n}\n\nPLATFORM_EXPORT_FUNCTION\nint64_t __interp_intrinsic_roundup_pow2(int64_t x)\n{\n\tauto num = x;\n\tauto ret = 1;\n\n\twhile(num > 0)\n\t{\n\t\tnum >>= 1;\n\t\tret <<= 1;\n\t}\n\n\treturn ret;\n}\n\n\n\n\n\n\n\nPLATFORM_EXPORT_FUNCTION int __interp_wrapper_printf(char* fmt, ...)\n{\n\tva_list ap;\n\tva_start(ap, fmt);\n\n\tint ret = vprintf(fmt, ap);\n\n\tva_end(ap);\n\treturn ret;\n}\n\nPLATFORM_EXPORT_FUNCTION int __interp_wrapper_sprintf(char* buf, char* fmt, ...)\n{\n\tva_list ap;\n\tva_start(ap, fmt);\n\n\tint ret = vsprintf(buf, fmt, ap);\n\n\tva_end(ap);\n\treturn ret;\n}\n\nPLATFORM_EXPORT_FUNCTION int __interp_wrapper_snprintf(char* buf, size_t n, char* fmt, ...)\n{\n\tva_list ap;\n\tva_start(ap, fmt);\n\n\tint ret = vsnprintf(buf, n, fmt, ap);\n\n\tva_end(ap);\n\treturn ret;\n}\n\nPLATFORM_EXPORT_FUNCTION int __interp_wrapper_fprintf(void* stream, char* fmt, ...)\n{\n\tva_list ap;\n\tva_start(ap, fmt);\n\n\tint ret = vfprintf(static_cast<FILE*>(stream), fmt, ap);\n\n\tva_end(ap);\n\treturn ret;\n}\n\n\n\n"
  },
  {
    "path": "source/frontend/arguments.cpp",
    "content": "// frontend.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"defs.h\"\n#include \"frontend.h\"\n#include \"backend.h\"\n\n#define FLAX_VERSION_STRING \"0.41.7-pre\"\n\n#define ARG_COMPILE_ONLY                        \"-c\"\n#define ARG_BACKEND                             \"-backend\"\n#define ARG_EMIT_LLVM_IR                        \"-emit-llvm\"\n#define ARG_LINK_FRAMEWORK                      \"-framework\"\n#define ARG_FRAMEWORK_SEARCH_PATH               \"-F\"\n#define ARG_HELP                                \"--help\"\n#define ARG_VERSION                             \"--version\"\n#define ARG_JITPROGRAM                          \"-jit\"\n#define ARG_LINK_LIBRARY                        \"-l\"\n#define ARG_LIBRARY_SEARCH_PATH                 \"-L\"\n#define ARG_MCMODEL                             \"-mcmodel\"\n#define ARG_OUTPUT_FILE                         \"-o\"\n#define ARG_OPTIMISATION_LEVEL_SELECT           \"-O\"\n#define ARG_POSINDEPENDENT                      \"-pic\"\n#define ARG_PRINT_FIR                           \"-print-fir\"\n#define ARG_PRINT_LLVMIR                        \"-print-lir\"\n#define ARG_PROFILE                             \"-profile\"\n#define ARG_RUNPROGRAM                          \"-run\"\n#define ARG_SYSROOT                             \"-sysroot\"\n#define ARG_TARGET                              \"-target\"\n#define ARG_FFI_ESCAPE                          \"--ffi-escape\"\n#define ARG_FREESTANDING                        \"--freestanding\"\n#define ARG_NOSTDLIB                            \"--nostdlib\"\n#define ARG_NO_RUNTIME_CHECKS                   \"--no-runtime-checks\"\n#define ARG_NO_RUNTIME_ERROR_STRINGS            \"--no-runtime-error-strings\"\n#define ARG_REPL                                \"-repl\"\n\n// for internal use!\n#define ARG_ABORT_ON_ERROR                      \"-abort-on-error\"\n\n#define WARNING_DISABLE_ALL                     \"-w\"\n#define WARNINGS_AS_ERRORS                      \"-Werror\"\n\n\n// actual warnings\n#define WARNING_ENABLE_UNUSED_VARIABLE          \"-Wunused-variable\"\n#define WARNING_ENABLE_VARIABLE_CHECKER         \"-Wvar-checker\"\n\n#define WARNING_DISABLE_UNUSED_VARIABLE         \"-Wno-unused-variable\"\n#define WARNING_DISABLE_VARIABLE_CHECKER        \"-Wno-var-checker\"\n\n\nstatic std::vector<std::pair<std::string, std::string>> helpList;\nstatic void setupMap()\n{\n\thelpList.push_back({ ARG_COMPILE_ONLY, \"output an object file; do not call the linker\" });\n\thelpList.push_back({ ARG_BACKEND + std::string(\" <backend>\"), \"change the backend used for compilation\" });\n\thelpList.push_back({ ARG_EMIT_LLVM_IR, \"emit a bitcode (.bc) file instead of a program\" });\n\thelpList.push_back({ ARG_LINK_FRAMEWORK + std::string(\" <framework>\"), \"link to a framework (macOS only)\" });\n\thelpList.push_back({ ARG_LINK_FRAMEWORK + std::string(\" <path>\"), \"link to a framework (macOS only)\" });\n\thelpList.push_back({ ARG_HELP, \"print this message\" });\n\thelpList.push_back({ ARG_JITPROGRAM, \"use LLVM JIT to run the program, instead of compiling to a file\" });\n\thelpList.push_back({ ARG_LINK_LIBRARY + std::string(\" <library>\"), \"link to a library\" });\n\thelpList.push_back({ ARG_LIBRARY_SEARCH_PATH + std::string(\" <path>\"), \"search for libraries in <path>\" });\n\thelpList.push_back({ ARG_MCMODEL + std::string(\" <model>\"), \"change the mcmodel of the code\" });\n\thelpList.push_back({ ARG_OUTPUT_FILE + std::string(\" <file>\"), \"set the name of the output file\" });\n\thelpList.push_back({ ARG_OPTIMISATION_LEVEL_SELECT + std::string(\"<level>\"), \"change the optimisation level; (-O[0-3], -Ox)\" });\n\n\thelpList.push_back({ ARG_FREESTANDING, \"generate a freestanding executable or object file\" });\n\thelpList.push_back({ ARG_NOSTDLIB, \"do not link with default libraries (libc/libm/msvcrt)\" });\n\thelpList.push_back({ ARG_FFI_ESCAPE, \"allow calling external functions (eg. libc) at compile-time\" });\n\n\thelpList.push_back({ ARG_POSINDEPENDENT, \"generate position independent code\" });\n\thelpList.push_back({ ARG_PRINT_FIR, \"print the FlaxIR before compilation\" });\n\thelpList.push_back({ ARG_PRINT_LLVMIR, \"print the LLVM IR before compilation\" });\n\thelpList.push_back({ ARG_PROFILE, \"print internal compiler profiling statistics\" });\n\thelpList.push_back({ ARG_RUNPROGRAM, \"run the program directly, instead of compiling to a file; defaults to the llvm backend\" });\n\thelpList.push_back({ ARG_SYSROOT + std::string(\" <dir>\"), \"set the directory used as the sysroot\" });\n\thelpList.push_back({ ARG_TARGET + std::string(\" <target>\"), \"change the compilation target\" });\n\thelpList.push_back({ ARG_REPL, \"start in repl mode\" });\n\n\thelpList.push_back({ WARNING_DISABLE_ALL, \"disable all warnings\" });\n\thelpList.push_back({ WARNINGS_AS_ERRORS, \"treat all warnings as errors\" });\n\n\thelpList.push_back({ ARG_NO_RUNTIME_CHECKS, \"disable all runtime checks\" });\n\thelpList.push_back({ ARG_NO_RUNTIME_ERROR_STRINGS, \"disable runtime error messages (program will just abort)\" });\n\n\thelpList.push_back({ WARNING_ENABLE_UNUSED_VARIABLE, \"enable warnings for unused variables\" });\n\thelpList.push_back({ WARNING_ENABLE_VARIABLE_CHECKER, \"enable warnings from the variable state checker\" });\n\thelpList.push_back({ WARNING_DISABLE_UNUSED_VARIABLE, \"disable warnings for unused variables\" });\n\thelpList.push_back({ WARNING_DISABLE_VARIABLE_CHECKER, \"disable warnings from the variable state checker\" });\n}\n\nstatic void printHelp()\n{\n\tif(helpList.empty())\n\t\tsetupMap();\n\n\tprintf(\"Flax Compiler - Version %s\\n\\n\", FLAX_VERSION_STRING);\n\tprintf(\"usage: flaxc [options] <inputs>\\n\\n\");\n\n\tprintf(\"options:\\n\");\n\n\tsize_t maxl = 0;\n\tfor(const auto& p : helpList)\n\t{\n\t\tif(p.first.length() > maxl)\n\t\t\tmaxl = p.first.length();\n\t}\n\n\tmaxl += 4;\n\n\t// ok\n\tfor(const auto& [ opt, desc ] : helpList)\n\t\tprintf(\"  %s%s%s\\n\", opt.c_str(), std::string(maxl - opt.length(), ' ').c_str(), desc.c_str());\n\n\tprintf(\"\\n\");\n}\n\n\n\n\nstatic std::string parseQuotedString(char** argv, int& i)\n{\n\tstd::string ret;\n\tif(strlen(argv[i]) > 0)\n\t{\n\t\tif(argv[i][0] == '\"' || argv[i][0] == '\\'')\n\t\t{\n\t\t\twhile(std::string(argv[i]).back() != '\\'' && std::string(argv[i]).back() != '\"')\n\t\t\t{\n\t\t\t\tret += \" \" + std::string(argv[i]);\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tret = argv[i];\n\t\t}\n\t}\n\treturn ret;\n}\n\n\n\n\n\n\nnamespace frontend\n{\n\tstd::string getVersion()\n\t{\n\t\treturn FLAX_VERSION_STRING;\n\t}\n\n\tstatic std::vector<std::string> frameworksToLink;\n\tstatic std::vector<std::string> frameworkSearchPaths;\n\n\tstatic std::vector<std::string> librariesToLink;\n\tstatic std::vector<std::string> librarySearchPaths;\n\n\n\tstatic bool _isPIC = false;\n\tstatic bool _isRepl = false;\n\tstatic bool _printFIR = false;\n\tstatic bool _ffiEscape = false;\n\tstatic bool _doProfiler = false;\n\tstatic bool _printLLVMIR = false;\n\tstatic bool _abortOnError = false;\n\tstatic bool _isFreestanding = false;\n\tstatic bool _noStandardLibraries = false;\n\n\tstatic bool _noRuntimeChecks = false;\n\tstatic bool _noRuntimeErrorStrings = false;\n\n\tstatic std::string _mcModel;\n\tstatic std::string _targetArch;\n\tstatic std::string _sysrootPath;\n\tstatic const std::string _prefixPath = \"/usr/local/\";\n\n\tusing BackendOption = backend::BackendOption;\n\tusing ProgOutputMode = backend::ProgOutputMode;\n\tusing OptimisationLevel = backend::OptimisationLevel;\n\n\tstatic auto _optLevel = OptimisationLevel::Normal;\n\tstatic auto _outputMode = ProgOutputMode::Program;\n\tstatic auto _backendCodegen = BackendOption::LLVM;\n\n\tOptimisationLevel getOptLevel()\n\t{\n\t\treturn _optLevel;\n\t}\n\n\tProgOutputMode getOutputMode()\n\t{\n\t\treturn _outputMode;\n\t}\n\n\tBackendOption getBackendOption()\n\t{\n\t\treturn _backendCodegen;\n\t}\n\n\tbool getPrintProfileStats()\n\t{\n\t\treturn _doProfiler;\n\t}\n\n\tbool getIsNoRuntimeChecks()\n\t{\n\t\treturn _noRuntimeChecks;\n\t}\n\n\tbool getIsNoRuntimeErrorStrings()\n\t{\n\t\treturn _noRuntimeErrorStrings;\n\t}\n\n\tbool getAbortOnError()\n\t{\n\t\treturn _abortOnError;\n\t}\n\n\tbool getCanFFIEscape()\n\t{\n\t\treturn _ffiEscape;\n\t}\n\n\tbool getIsReplMode()\n\t{\n\t\treturn _isRepl;\n\t}\n\n\tbool getPrintFIR()\n\t{\n\t\treturn _printFIR;\n\t}\n\n\tbool getPrintLLVMIR()\n\t{\n\t\treturn _printLLVMIR;\n\t}\n\n\tstd::vector<std::string> getFrameworksToLink()\n\t{\n\t\treturn frameworksToLink;\n\t}\n\tstd::vector<std::string> getFrameworkSearchPaths()\n\t{\n\t\treturn frameworkSearchPaths;\n\t}\n\n\tstd::vector<std::string> getLibrariesToLink()\n\t{\n\t\treturn librariesToLink;\n\t}\n\n\tstd::vector<std::string> getLibrarySearchPaths()\n\t{\n\t\treturn librarySearchPaths;\n\t}\n\n\tbool getIsFreestanding()\n\t{\n\t\treturn _isFreestanding;\n\t}\n\n\tbool getIsNoStandardLibraries()\n\t{\n\t\treturn _noStandardLibraries;\n\t}\n\n\tbool getIsPositionIndependent()\n\t{\n\t\treturn _isPIC;\n\t}\n\n\n\tstd::string getParameter(const std::string& name)\n\t{\n\t\tif(name == \"mcmodel\")\n\t\t\treturn _mcModel;\n\n\t\telse if(name == \"targetarch\")\n\t\t\treturn _targetArch;\n\n\t\telse if(name == \"sysroot\")\n\t\t\treturn _sysrootPath;\n\n\t\telse if(name == \"prefix\")\n\t\t\treturn _prefixPath;\n\n\t\telse\n\t\t\ticeAssert(\"invalid\");\n\n\t\treturn \"\";\n\t}\n\n\n\n\t// nothing to do with synchronisation!!\n\t// TODO: this is a bit dumb given our current boolean flags, but... meh\n\tstatic std::unordered_set<std::string> setOptions;\n\tstatic util::hash_map<std::string, std::unordered_set<std::string>> mutualExclusions;\n\tstatic void setupFlagMutexes()\n\t{\n\t\t// repl is basically incompatible with everything, so list it first.\n\t\tmutualExclusions[ARG_REPL].insert(ARG_RUNPROGRAM);\n\t\tmutualExclusions[ARG_REPL].insert(ARG_TARGET);\n\t\tmutualExclusions[ARG_REPL].insert(ARG_BACKEND);\n\t\tmutualExclusions[ARG_REPL].insert(ARG_MCMODEL);\n\t\tmutualExclusions[ARG_REPL].insert(ARG_JITPROGRAM);\n\t\tmutualExclusions[ARG_REPL].insert(ARG_OUTPUT_FILE);\n\t\tmutualExclusions[ARG_REPL].insert(ARG_COMPILE_ONLY);\n\t\tmutualExclusions[ARG_REPL].insert(ARG_FREESTANDING);\n\t\tmutualExclusions[ARG_REPL].insert(ARG_POSINDEPENDENT);\n\t\tmutualExclusions[ARG_REPL].insert(ARG_OPTIMISATION_LEVEL_SELECT);\n\n\t\t// don't try to run/jit and compile/output at the same time\n\t\tmutualExclusions[ARG_RUNPROGRAM].insert(ARG_TARGET);\n\t\tmutualExclusions[ARG_RUNPROGRAM].insert(ARG_MCMODEL);\n\t\tmutualExclusions[ARG_RUNPROGRAM].insert(ARG_OUTPUT_FILE);\n\t\tmutualExclusions[ARG_RUNPROGRAM].insert(ARG_COMPILE_ONLY);\n\t\tmutualExclusions[ARG_RUNPROGRAM].insert(ARG_FREESTANDING);\n\t\tmutualExclusions[ARG_RUNPROGRAM].insert(ARG_POSINDEPENDENT);\n\n\t\t// just copy it.\n\t\tmutualExclusions[ARG_JITPROGRAM] = mutualExclusions[ARG_RUNPROGRAM];\n\n\t\t// ok now the trick is, for each exclusion, add the reverse.\n\t\tfor(const auto& [ x, xs ] : mutualExclusions)\n\t\t\tfor(const auto& y : xs)\n\t\t\t\tmutualExclusions[y].insert(x);\n\t}\n\n\tstatic void checkOptionExclusivity(const std::string& a)\n\t{\n\t\tfor(const auto& ex : mutualExclusions[a])\n\t\t{\n\t\t\tif(setOptions.find(ex) != setOptions.end())\n\t\t\t\t_error_and_exit(\"error: options '%s' and '%s' are mutually exclusive\", a, ex);\n\t\t}\n\t}\n\n\n\n\n\n\n\n\n\tstd::pair<std::string, std::string> parseCmdLineOpts(int argc, char** argv)\n\t{\n\t\tsetupFlagMutexes();\n\n\t\t// quick thing: usually programs will not do anything if --help or --version is anywhere in the flags.\n\t\tfor(int i = 1; i < argc; i++)\n\t\t{\n\t\t\tif(!strcmp(argv[i], ARG_HELP))\n\t\t\t{\n\t\t\t\tprintHelp();\n\t\t\t\texit(0);\n\t\t\t}\n\t\t\telse if(!strcmp(argv[i], ARG_VERSION))\n\t\t\t{\n\t\t\t\tprintf(\"Flax Compiler (flaxc), version %s\\n\", FLAX_VERSION_STRING);\n\t\t\t\texit(0);\n\t\t\t}\n\t\t}\n\n\t\t// parse arguments\n\t\tstd::vector<std::string> filenames;\n\t\tstd::string outname;\n\n\t\tif(argc > 1)\n\t\t{\n\t\t\t// parse the command line opts\n\t\t\tfor(int i = 1; i < argc; i++)\n\t\t\t{\n\t\t\t\tbool wasFilename = false;\n\t\t\t\tif(!strcmp(argv[i], ARG_LINK_FRAMEWORK))\n\t\t\t\t{\n\t\t\t\t\tif(i != argc - 1)\n\t\t\t\t\t{\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\tframeworksToLink.push_back(argv[i]);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_error_and_exit(\"error: expected framework name after '-framework' option\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], ARG_FRAMEWORK_SEARCH_PATH))\n\t\t\t\t{\n\t\t\t\t\tif(i != argc - 1)\n\t\t\t\t\t{\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\tframeworkSearchPaths.push_back(argv[i]);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_error_and_exit(\"error: expected path after '-F' option\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(strstr(argv[i], ARG_LINK_LIBRARY) == argv[i])\n\t\t\t\t{\n\t\t\t\t\t// handles -lfoo\n\n\t\t\t\t\tif(strlen(argv[i]) > strlen(ARG_LINK_LIBRARY))\n\t\t\t\t\t{\n\t\t\t\t\t\targv[i] += strlen(ARG_LINK_LIBRARY);\n\t\t\t\t\t\tlibrariesToLink.push_back(parseQuotedString(argv, i));\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_error_and_exit(\"error: expected library name after '-l' option\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], ARG_LINK_LIBRARY))\n\t\t\t\t{\n\t\t\t\t\t// handles -l foo\n\n\t\t\t\t\tif(i != argc - 1)\n\t\t\t\t\t{\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\tlibrariesToLink.push_back(argv[i]);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_error_and_exit(\"error: expected library name after '-l' option\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(strstr(argv[i], ARG_LIBRARY_SEARCH_PATH) == argv[i])\n\t\t\t\t{\n\t\t\t\t\t// handles -Lpath\n\t\t\t\t\tif(strlen(argv[i]) > strlen(ARG_LIBRARY_SEARCH_PATH))\n\t\t\t\t\t{\n\t\t\t\t\t\targv[i] += strlen(ARG_LIBRARY_SEARCH_PATH);\n\t\t\t\t\t\tlibrarySearchPaths.push_back(parseQuotedString(argv, i));\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_error_and_exit(\"error: expected path after '-L' option\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], ARG_LIBRARY_SEARCH_PATH))\n\t\t\t\t{\n\t\t\t\t\t// handles -L path\n\n\t\t\t\t\tif(i != argc - 1)\n\t\t\t\t\t{\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\tlibrarySearchPaths.push_back(argv[i]);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_error_and_exit(\"error: expected path after '-L' option\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], ARG_SYSROOT))\n\t\t\t\t{\n\t\t\t\t\tif(i != argc - 1)\n\t\t\t\t\t{\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\tfrontend::_sysrootPath = parseQuotedString(argv, i);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_error_and_exit(\"error: expected directory name after '-sysroot' option\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(!strcmp(argv[i], ARG_TARGET))\n\t\t\t\t{\n\t\t\t\t\tif(i != argc - 1)\n\t\t\t\t\t{\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\tfrontend::_targetArch = parseQuotedString(argv, i);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_error_and_exit(\"error: expected target string after '-target' option\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], ARG_FREESTANDING))\n\t\t\t\t{\n\t\t\t\t\t// set freestanding mode\n\t\t\t\t\tfrontend::_isFreestanding = true;\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], ARG_NO_RUNTIME_CHECKS))\n\t\t\t\t{\n\t\t\t\t\tfrontend::_noRuntimeChecks = true;\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], ARG_NO_RUNTIME_ERROR_STRINGS))\n\t\t\t\t{\n\t\t\t\t\tfrontend::_noRuntimeErrorStrings = true;\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], ARG_FFI_ESCAPE))\n\t\t\t\t{\n\t\t\t\t\tfrontend::_ffiEscape = true;\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], ARG_REPL))\n\t\t\t\t{\n\t\t\t\t\tfrontend::_isRepl = true;\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], ARG_BACKEND))\n\t\t\t\t{\n\t\t\t\t\tif(i != argc - 1)\n\t\t\t\t\t{\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\tauto str = parseQuotedString(argv, i);\n\n\t\t\t\t\t\tif(str == \"llvm\")\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfrontend::_backendCodegen = BackendOption::LLVM;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(str == \"interp\")\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfrontend::_backendCodegen = BackendOption::Interpreter;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(str == \"x64asm\")\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfrontend::_backendCodegen = BackendOption::Assembly_x64;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(str == \"none\")\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfrontend::_backendCodegen = BackendOption::None;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_error_and_exit(\"error: '%s' is not a valid backend (valid options are 'llvm' and 'x64asm')\\n\", str);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_error_and_exit(\"error: expected backend name after '-backend' option\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], ARG_OUTPUT_FILE))\n\t\t\t\t{\n\t\t\t\t\tif(i != argc - 1)\n\t\t\t\t\t{\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\toutname = parseQuotedString(argv, i);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_error_and_exit(\"error: expected filename name after '-o' option\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], ARG_POSINDEPENDENT))\n\t\t\t\t{\n\t\t\t\t\tfrontend::_isPIC = true;\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], ARG_PROFILE))\n\t\t\t\t{\n\t\t\t\t\tfrontend::_doProfiler = true;\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], ARG_MCMODEL))\n\t\t\t\t{\n\t\t\t\t\tif(i != argc - 1)\n\t\t\t\t\t{\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\tstd::string mm = parseQuotedString(argv, i);\n\t\t\t\t\t\tif(mm != \"kernel\" && mm != \"small\" && mm != \"medium\" && mm != \"large\")\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_error_and_exit(\"error: valid options for '-mcmodel' are 'small', 'medium', 'large' and 'kernel'.\\n\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfrontend::_mcModel = mm;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_error_and_exit(\"error: expected mcmodel name after '-mcmodel' option\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], WARNINGS_AS_ERRORS))\n\t\t\t\t{\n\t\t\t\t\t// frontend::Flags |= (uint64_t) frontend::Flag::WarningsAsErrors;\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], WARNING_DISABLE_ALL))\n\t\t\t\t{\n\t\t\t\t\t// frontend::Flags |= (uint64_t) frontend::Flag::NoWarnings;\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], ARG_PRINT_LLVMIR))\n\t\t\t\t{\n\t\t\t\t\tfrontend::_printLLVMIR = true;\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], ARG_PRINT_FIR))\n\t\t\t\t{\n\t\t\t\t\tfrontend::_printFIR = true;\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], ARG_COMPILE_ONLY))\n\t\t\t\t{\n\t\t\t\t\tif(frontend::_outputMode != ProgOutputMode::RunJit && frontend::_outputMode != ProgOutputMode::LLVMBitcode)\n\t\t\t\t\t{\n\t\t\t\t\t\tfrontend::_outputMode = ProgOutputMode::ObjectFile;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], ARG_JITPROGRAM) || !strcmp(argv[i], ARG_RUNPROGRAM))\n\t\t\t\t{\n\t\t\t\t\tif(frontend::_outputMode != ProgOutputMode::ObjectFile && frontend::_outputMode != ProgOutputMode::LLVMBitcode)\n\t\t\t\t\t{\n\t\t\t\t\t\tfrontend::_outputMode = ProgOutputMode::RunJit;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(strstr(argv[i], ARG_OPTIMISATION_LEVEL_SELECT) == argv[i])\n\t\t\t\t{\n\t\t\t\t\t// make sure we have at least 3 chars\n\t\t\t\t\tif(strlen(argv[i]) < 3)\n\t\t\t\t\t{\n\t\t\t\t\t\t_error_and_exit(\"error: '-O' is not a valid option on its own\\n\");\n\t\t\t\t\t}\n\t\t\t\t\telse if(strlen(argv[i]) > 3)\n\t\t\t\t\t{\n\t\t\t\t\t\t_error_and_exit(\"error: '%s' is not a valid option\\n\", argv[i]);\n\t\t\t\t\t}\n\n\t\t\t\t\tif(argv[i][2] == 'x')\n\t\t\t\t\t{\n\t\t\t\t\t\t// literally nothing\n\t\t\t\t\t\tfrontend::_optLevel = OptimisationLevel::Debug;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tswitch(argv[i][2])\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase '0':\tfrontend::_optLevel = OptimisationLevel::None;\t\t\tbreak;\n\t\t\t\t\t\t\tcase '1':\tfrontend::_optLevel = OptimisationLevel::Minimal;\t\tbreak;\n\t\t\t\t\t\t\tcase '2':\tfrontend::_optLevel = OptimisationLevel::Normal;\t\tbreak;\n\t\t\t\t\t\t\tcase '3':\tfrontend::_optLevel = OptimisationLevel::Aggressive;\tbreak;\n\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t_error_and_exit(\"error: '%c' is not a valid optimisation level (must be between 0 and 3)\\n\", argv[i][2]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], ARG_ABORT_ON_ERROR))\n\t\t\t\t{\n\t\t\t\t\tfrontend::_abortOnError = true;\n\t\t\t\t}\n\n\t\t\t\t// warnings.\n\t\t\t\telse if(!strcmp(argv[i], WARNING_DISABLE_UNUSED_VARIABLE))\n\t\t\t\t{\n\t\t\t\t\t// frontend::setWarning(frontend::Warning::UnusedVariable, false);\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], WARNING_ENABLE_UNUSED_VARIABLE))\n\t\t\t\t{\n\t\t\t\t\t// frontend::setWarning(frontend::Warning::UnusedVariable, true);\n\t\t\t\t}\n\n\t\t\t\telse if(!strcmp(argv[i], WARNING_DISABLE_VARIABLE_CHECKER))\n\t\t\t\t{\n\t\t\t\t\t// frontend::setWarning(frontend::Warning::UseAfterFree, false);\n\t\t\t\t\t// frontend::setWarning(frontend::Warning::UseBeforeAssign, false);\n\t\t\t\t}\n\t\t\t\telse if(!strcmp(argv[i], WARNING_ENABLE_VARIABLE_CHECKER))\n\t\t\t\t{\n\t\t\t\t\t// frontend::setWarning(frontend::Warning::UseAfterFree, true);\n\t\t\t\t\t// frontend::setWarning(frontend::Warning::UseBeforeAssign, true);\n\t\t\t\t}\n\t\t\t\telse if(argv[i][0] == '-')\n\t\t\t\t{\n\t\t\t\t\t_error_and_exit(\"error: unrecognised option '%s'\\n\", argv[i]);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\twasFilename = true;\n\t\t\t\t\tfilenames.push_back(argv[i]);\n\t\t\t\t}\n\n\n\t\t\t\tif(!wasFilename)\n\t\t\t\t{\n\t\t\t\t\tsetOptions.insert(argv[i]);\n\t\t\t\t\tcheckOptionExclusivity(argv[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\n\n\t\tif(filenames.empty() && !frontend::_isRepl)\n\t\t\t_error_and_exit(\"error: no input files\\n\");\n\n\t\tif(filenames.size() > 1)\n\t\t\t_error_and_exit(\"only one input file is supported at the moment\\n\");\n\n\t\treturn { filenames.empty() ? \"\" : filenames[0], outname };\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/frontend/collector.cpp",
    "content": "// collector.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include <sys/stat.h>\n\n#include <unordered_map>\n\n#include \"errors.h\"\n#include \"codegen.h\"\n#include \"frontend.h\"\n#include \"typecheck.h\"\n\nnamespace frontend\n{\n\tvoid collectFiles(const std::string& _filename, CollectorState* state)\n\t{\n\t\t// first, collect and parse the first file\n\t\tstd::string full = getFullPathOfFile(_filename);\n\n\t\tauto graph = new DependencyGraph();\n\n\t\tutil::hash_map<std::string, bool> visited;\n\n\t\tstate->allFiles = checkForCycles(full, buildDependencyGraph(graph, full, visited));\n\t\tstate->fullMainFile = full;\n\t\tstate->graph = graph;\n\n\n\t\t// pre-lex everything.\n\t\tfor(const auto& f : state->allFiles)\n\t\t{\n\t\t\tfrontend::getFileTokens(f);\n\t\t\tstate->totalLinesOfCode += frontend::getFileLines(frontend::getFileIDFromFilename(f)).size();\n\t\t}\n\t}\n\n\n\tvoid parseFiles(CollectorState* state)\n\t{\n\t\t// parse\n\t\tfor(const auto& file : state->allFiles)\n\t\t{\n\t\t\t// parse it all\n\t\t\tauto opers = parser::parseOperators(frontend::getFileTokens(file));\n\n\t\t\t{\n\t\t\t\t// TODO: clean this up maybe.\n\t\t\t\tauto checkDupes = [](const util::hash_map<std::string, parser::CustomOperatorDecl>& existing,\n\t\t\t\t\tconst util::hash_map<std::string, parser::CustomOperatorDecl>& newops, const std::string& kind) {\n\n\t\t\t\t\tfor(const auto& op : newops)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(auto it = existing.find(op.first); it != existing.end())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tSimpleError::make(op.second.loc, \"duplicate declaration for %s operator '%s'\", kind, op.second.symbol)\n\t\t\t\t\t\t\t\t->append(SimpleError::make(MsgType::Note, it->second.loc, \"previous declaration was here:\"))\n\t\t\t\t\t\t\t\t->postAndQuit();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tcheckDupes(state->binaryOps, std::get<0>(opers), \"infix\");\n\t\t\t\tcheckDupes(state->prefixOps, std::get<1>(opers), \"prefix\");\n\t\t\t\tcheckDupes(state->postfixOps, std::get<2>(opers), \"postfix\");\n\n\t\t\t\tfor(const auto& op : std::get<0>(opers))\n\t\t\t\t\tstate->binaryOps[op.first] = op.second;\n\n\t\t\t\tfor(const auto& op : std::get<1>(opers))\n\t\t\t\t\tstate->prefixOps[op.first] = op.second;\n\n\t\t\t\tfor(const auto& op : std::get<2>(opers))\n\t\t\t\t\tstate->postfixOps[op.first] = op.second;\n\t\t\t}\n\n\n\t\t\tstate->parsed[file] = parser::parseFile(file, frontend::getFileState(file), *state);\n\t\t}\n\t}\n\n\n\n\tsst::DefinitionTree* typecheckFiles(CollectorState* state)\n\t{\n\t\t// do a simple thing.\n\t\tif(state->nativeWordSize != 0)  fir::setNativeWordSizeInBits(state->nativeWordSize);\n\t\telse                            fir::setNativeWordSizeInBits(64);\n\n\t\t// typecheck\n\t\tfor(const auto& file : state->allFiles)\n\t\t{\n\t\t\t// note that we're guaranteed (because that's the whole point)\n\t\t\t// that any module we encounter here will have had all of its dependencies checked already\n\n\t\t\tstd::vector<std::pair<ImportThing, sst::DefinitionTree*>> imports;\n\t\t\tfor(auto d : state->graph->getDependenciesOf(file))\n\t\t\t{\n\t\t\t\tauto imported = d->to;\n\n\t\t\t\tauto dtree = state->dtrees[imported->name];\n\t\t\t\ticeAssert(dtree);\n\n\t\t\t\tImportThing ithing { imported->name, d->ithing.importAs, d->ithing.pubImport, d->ithing.loc };\n\t\t\t\tif(auto it = std::find_if(imports.begin(), imports.end(), [&ithing](const auto& x) -> bool { return x.first.name == ithing.name; });\n\t\t\t\t\tit != imports.end())\n\t\t\t\t{\n\t\t\t\t\tSimpleError::make(ithing.loc, \"importing previously imported module '%s'\", ithing.name)\n\t\t\t\t\t\t->append(SimpleError::make(MsgType::Note, it->first.loc, \"previous import was here:\"))\n\t\t\t\t\t\t->postAndQuit();\n\t\t\t\t}\n\n\t\t\t\timports.push_back({ ithing, dtree });\n\t\t\t}\n\n\t\t\t// i guess we always add prelude definitions?\n\t\t\tstate->dtrees[file] = sst::typecheck(state, state->parsed[file], imports, /* addPreludeDefinitions: */ true);\n\t\t}\n\n\t\treturn state->dtrees[state->fullMainFile];\n\t}\n\n\n\tfir::Module* generateFIRModule(CollectorState* state, sst::DefinitionTree* maintree)\n\t{\n\t\ticeAssert(maintree && maintree->topLevel);\n\n\t\tfor(const auto& dt : state->dtrees)\n\t\t{\n\t\t\tfor(const auto& def : dt.second->typeDefnMap)\n\t\t\t{\n\t\t\t\tif(auto it = maintree->typeDefnMap.find(def.first); it != maintree->typeDefnMap.end())\n\t\t\t\t\ticeAssert(it->second == def.second);\n\n\t\t\t\tmaintree->typeDefnMap[def.first] = def.second;\n\t\t\t}\n\t\t}\n\n\t\treturn cgn::codegen(maintree);\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/frontend/dependencies.cpp",
    "content": "// dependencies.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"frontend.h\"\n\nnamespace frontend\n{\n\tstatic void stronglyConnect(DependencyGraph* graph, int& index, std::vector<std::vector<DepNode*>>& connected, DepNode* node);\n\n\tvoid DependencyGraph::addModuleDependency(const std::string& from, const std::string& to, const ImportThing& ithing)\n\t{\n\t\t// find existing node\n\t\tDepNode* src = 0;\n\t\tDepNode* dst = 0;\n\t\tfor(auto d : this->nodes)\n\t\t{\n\t\t\tif(!src && d->name == from)\n\t\t\t{\n\t\t\t\tsrc = d;\n\t\t\t}\n\t\t\telse if(!dst && d->name == to)\n\t\t\t{\n\t\t\t\tdst = d;\n\t\t\t}\n\t\t}\n\n\t\tif(!src)\n\t\t{\n\t\t\tsrc = new DepNode();\n\t\t\tsrc->name = from;\n\n\t\t\tthis->nodes.push_back(src);\n\t\t}\n\n\t\tif(!dst)\n\t\t{\n\t\t\tdst = new DepNode();\n\t\t\tdst->name = to;\n\n\t\t\tthis->nodes.push_back(dst);\n\t\t}\n\n\t\tdst->users.push_back({ src, ithing.loc });\n\n\t\tDep* d = new Dep();\n\t\td->from = src;\n\t\td->to = dst;\n\t\td->ithing = ithing;\n\n\t\tthis->edgesFrom[src].push_back(d);\n\t}\n\n\n\n\tstd::vector<std::vector<DepNode*>> DependencyGraph::findCyclicDependencies()\n\t{\n\t\tint index = 0;\n\t\tstd::vector<std::vector<DepNode*>> ret;\n\n\t\tfor(auto n : this->nodes)\n\t\t{\n\t\t\tn->index = -1;\n\t\t\tn->onStack = false;\n\t\t\tn->lowlink = -1;\n\t\t}\n\n\t\tfor(auto n : this->nodes)\n\t\t{\n\t\t\tif(n->index == -1)\n\t\t\t\tstronglyConnect(this, index, ret, n);\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\tstd::vector<Dep*> DependencyGraph::getDependenciesOf(const std::string& name)\n\t{\n\t\tDepNode* node = 0;\n\t\tfor(auto n : this->nodes)\n\t\t{\n\t\t\tif(n->name == name)\n\t\t\t{\n\t\t\t\tnode = n;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif(!node) return { };\n\n\t\treturn this->edgesFrom[node];\n\t}\n\n\n\tstatic void stronglyConnect(DependencyGraph* graph, int& index, std::vector<std::vector<DepNode*>>& connected, DepNode* node)\n\t{\n\t\tnode->index = index;\n\t\tnode->lowlink = index;\n\n\t\tindex++;\n\n\n\t\tgraph->stack.push(node);\n\t\tnode->onStack = true;\n\n\n\t\tstd::vector<Dep*> edges = graph->edgesFrom[node];\n\t\tfor(auto edge : edges)\n\t\t{\n\t\t\tDepNode* w = edge->to;\n\t\t\tif(w->index == -1)\n\t\t\t{\n\t\t\t\tstronglyConnect(graph, index, connected, w);\n\t\t\t\tnode->lowlink = (node->lowlink < w->lowlink ? node->lowlink : w->lowlink);\n\t\t\t}\n\t\t\telse if(w->onStack)\n\t\t\t{\n\t\t\t\tnode->lowlink = (node->lowlink < w->index ? node->lowlink : w->index);\n\t\t\t}\n\t\t}\n\n\n\n\t\tif(node->lowlink == node->index)\n\t\t{\n\t\t\tstd::vector<DepNode*> set;\n\n\t\t\twhile(true)\n\t\t\t{\n\t\t\t\tDepNode* w = graph->stack.top();\n\t\t\t\tgraph->stack.pop();\n\n\t\t\t\tw->onStack = false;\n\n\t\t\t\tset.push_back(w);\n\n\t\t\t\tif(w == node)\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tconnected.push_back(set);\n\t\t}\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\tstd::vector<std::string> checkForCycles(const std::string& topmod, frontend::DependencyGraph* graph)\n\t{\n\t\tauto groups = graph->findCyclicDependencies();\n\t\tfor(const auto& grp : groups)\n\t\t{\n\t\t\tif(grp.size() > 1)\n\t\t\t{\n\t\t\t\tstd::string modlist;\n\t\t\t\tstd::vector<Location> locs;\n\n\t\t\t\tfor(auto m : grp)\n\t\t\t\t{\n\t\t\t\t\tstd::string fn = getFilenameFromPath(m->name);\n\t\t\t\t\tfn = fn.substr(0, fn.find_last_of('.'));\n\n\t\t\t\t\tmodlist += \"    \" + fn + \"\\n\";\n\t\t\t\t}\n\n\t\t\t\tinfo(\"cyclic import dependencies between these modules:\\n%s\", modlist.c_str());\n\t\t\t\tinfo(\"offending import statements:\");\n\n\t\t\t\tfor(auto m : grp)\n\t\t\t\t{\n\t\t\t\t\tfor(auto u : m->users)\n\t\t\t\t\t{\n\t\t\t\t\t\tinfo(u.second, \"\");\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\terror(\"cyclic dependencies found, cannot continue\");\n\t\t\t}\n\t\t}\n\n\n\n\t\tif(groups.size() == 0)\n\t\t{\n\t\t\tfrontend::DepNode* dn = new frontend::DepNode();\n\t\t\tdn->name = topmod;\n\t\t\tgroups.insert(groups.begin(), { dn });\n\t\t}\n\n\t\tstd::vector<std::string> fulls;\n\t\tfor(auto grp : groups)\n\t\t{\n\t\t\t// make sure it's 1\n\t\t\ticeAssert(grp.size() == 1);\n\n\t\t\tfulls.push_back(frontend::getFullPathOfFile(grp[0]->name));\n\t\t}\n\n\t\treturn fulls;\n\t}\n\n\tfrontend::DependencyGraph* buildDependencyGraph(frontend::DependencyGraph* graph, const std::string& full,\n\t\tutil::hash_map<std::string, bool>& visited)\n\t{\n\t\tauto tokens = frontend::getFileTokens(full);\n\t\tauto imports = parser::parseImports(full, tokens);\n\n\t\t// get the proper import of each 'import'\n\t\tstd::vector<std::string> fullpaths;\n\t\tfor(const auto& imp : imports)\n\t\t{\n\t\t\tauto tovisit = resolveImport(imp.name, imp.loc, full);\n\t\t\tgraph->addModuleDependency(full, tovisit, imp);\n\n\t\t\tif(!visited[tovisit])\n\t\t\t{\n\t\t\t\tvisited[tovisit] = true;\n\t\t\t\tbuildDependencyGraph(graph, tovisit, visited);\n\t\t\t}\n\t\t}\n\n\t\treturn graph;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/frontend/errors.cpp",
    "content": "// errors.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"defs.h\"\n#include \"errors.h\"\n\n#include \"ast.h\"\n#include \"sst.h\"\n#include \"frontend.h\"\n\n#include \"memorypool.h\"\n\n#define LEFT_PADDING TAB_WIDTH\n\n\nstatic std::string repeat(std::string str, size_t n)\n{\n\tif(n == 0)\n\t{\n\t\tstr.clear();\n\t\tstr.shrink_to_fit();\n\t\treturn str;\n\t}\n\telse if(n == 1 || str.empty())\n\t{\n\t\treturn str;\n\t}\n\n\tauto period = str.size();\n\tif(period == 1)\n\t{\n\t\tstr.append(n - 1, str.front());\n\t\treturn str;\n\t}\n\n\tstr.reserve(period * n);\n\tsize_t m = 2;\n\tfor(; m < n; m *= 2)\n\t\tstr += str;\n\n\tstr.append(str.c_str(), (n - (m / 2)) * period);\n\n\treturn str;\n}\n\nstatic std::string spaces(size_t n)\n{\n\treturn repeat(\" \", n);\n}\n\nstatic std::string fetchContextLine(Location loc, size_t* adjust)\n{\n\tif(loc.fileID == 0) return \"\";\n\n\tconst auto& lines = frontend::getFileLines(loc.fileID);\n\tif(lines.size() > loc.line)\n\t{\n\t\tstd::stringstream ln;\n\t\tauto orig = std::string(lines[loc.line]);\n\n\t\t// skip all leading whitespace.\n\t\tbool ws = true;\n\t\tfor(auto c : orig)\n\t\t{\n\t\t\tif(ws && c == '\\t')                 { *adjust += TAB_WIDTH; continue;   }\n\t\t\telse if(ws && c == ' ')             { *adjust += 1; continue;           }\n\t\t\telse if(c == '\\n')                  { break;                            }\n\t\t\telse                                { ws = false; ln << c;              }\n\t\t}\n\n\t\treturn strprintf(\"%s%s\", spaces(LEFT_PADDING), ln.str().c_str());\n\t}\n\n\treturn \"\";\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n// #define UNDERLINE_CHARACTER \"^\"\n#define UNDERLINE_CHARACTER \"\\u203e\"\n\n\nstatic std::string getSpannedContext(const Location& loc, const std::vector<util::ESpan>& spans, size_t* adjust, size_t* num_width,\n\tsize_t* margin, bool underline, bool bottompad, const std::string& underlineColour, const std::string& overrideLineContent)\n{\n\tstd::string ret;\n\n\ticeAssert(adjust && margin && num_width);\n\ticeAssert((underline == bottompad || bottompad) && \"cannot underline without bottom pad\");\n\n\tif(!std::is_sorted(spans.begin(), spans.end(), [](const auto& a, const auto& b) -> bool { return a.loc.col < b.loc.col; }))\n\t\t_error_and_exit(\"spans must be sorted!\\n\");\n\n\t*num_width = std::to_string(loc.line + 1).length();\n\n\t// one spacing line\n\t*margin = *num_width + 2;\n\tret += strprintf(\"%s |\\n\", spaces(*num_width));\n\n\tif(overrideLineContent.empty()) ret += strprintf(\"%d |%s\\n\", loc.line + 1, fetchContextLine(loc, adjust));\n\telse                            ret += strprintf(\"%s |%s%s\\n\", spaces(*num_width), spaces(LEFT_PADDING), overrideLineContent);\n\n\tif(bottompad)\n\t\tret += strprintf(\"%s |\", spaces(*num_width));\n\n\t// ok, now loop through each err, and draw the underline.\n\tif(underline)\n\t{\n\t\t//* cursor represents the 'virtual' position -- excluding the left margin\n\t\tsize_t cursor = 0;\n\n\t\t// columns actually start at 1 for some reason.\n\t\tret += spaces(LEFT_PADDING - 1);\n\n\t\tfor(const auto& span : spans)\n\t\t{\n\t\t\tstd::string underliner;\n\t\t\tif(span.msg.empty())\n\t\t\t\tunderliner = repeat(span.loc.len < 3 ? \"^\" : UNDERLINE_CHARACTER, span.loc.len);\n\n\t\t\telse\n\t\t\t\tunderliner = \"\\u0305|\" + repeat(UNDERLINE_CHARACTER, span.loc.len - 1);\n\n\n\t\t\t// pad out.\n\t\t\tauto tmp = strprintf(\"%s\", spaces(1 + span.loc.col - *adjust - cursor)); cursor += tmp.length();\n\t\t\tret += tmp + strprintf(\"%s\", span.colour.empty() ? underlineColour : span.colour);\n\n\t\t\ttmp = strprintf(\"%s\", underliner); cursor += span.loc.len;\n\t\t\tret += tmp + strprintf(\"%s\", COLOUR_RESET);\n\t\t}\n\t}\n\n\treturn ret;\n}\n\nstatic std::string getSingleContext(const Location& loc, const std::string& underlineColour = COLOUR_RED_BOLD,\n\tconst std::string& overrideLineContent = \"\", bool underline = true, bool bottompad = true)\n{\n\tif(loc.fileID == 0 && overrideLineContent.empty()) return \"\";\n\n\tsize_t a = 0;\n\tsize_t b = 0;\n\tsize_t c = 0;\n\treturn getSpannedContext(loc, { util::ESpan(loc, \"\") }, &a, &b, &c, underline, bottompad, underlineColour, overrideLineContent);\n}\n\n\n\n\n\n\nstd::string __error_gen_internal(const Location& loc, const std::string& msg, const char* type, bool context, bool multipart)\n{\n\tstd::string ret;\n\n\tauto colour = COLOUR_RED_BOLD;\n\tif(strcmp(type, \"warning\") == 0)\n\t\tcolour = COLOUR_MAGENTA_BOLD;\n\n\telse if(strcmp(type, \"note\") == 0)\n\t\tcolour = COLOUR_GREY_BOLD;\n\n\t// bool empty = strcmp(type, \"\") == 0;\n\t// bool dobold = strcmp(type, \"note\") != 0;\n\n\t//? do we want to truncate the file path?\n\t//? we're doing it now, might want to change (or use a flag)\n\n\tstd::string filename = frontend::getFilenameFromPath(loc.fileID == 0 ? \"(unknown)\"\n\t\t: frontend::getFilenameFromID(loc.fileID));\n\n\tret += strprintf(\"%s%s%s:%s %s\\n\", COLOUR_RESET, colour, type, COLOUR_RESET, msg);\n\n\tif(loc.fileID > 0)\n\t{\n\t\tauto location = strprintf(\"%s:%d:%d\", filename, loc.line + 1, loc.col + 1);\n\t\tret += strprintf(\"%s%sat:%s %s%s\\n\", COLOUR_RESET, COLOUR_GREY_BOLD, spaces(strlen(type) - 2), COLOUR_RESET, location);\n\t}\n\n\n\tif(context && loc.fileID > 0)\n\t{\n\t\tauto underlineColour = COLOUR_RED_BOLD;\n\n\t\tif(strcmp(type, \"note\") == 0)\n\t\t\tunderlineColour = COLOUR_BLUE_BOLD;\n\n\t\tret += getSingleContext(loc, underlineColour) + \"\\n\";\n\t}\n\n\tif(!multipart) ret += \"\\n\";\n\treturn ret;\n}\n\n\n\n\n\n\n\n\n\n\nstatic std::string typestr(MsgType t)\n{\n\tswitch(t)\n\t{\n\t\tcase MsgType::Note:     return \"note\";\n\t\tcase MsgType::Error:    return \"error\";\n\t\tcase MsgType::Warning:  return \"warning\";\n\t\tdefault:                iceAssert(0); return \"\";\n\t}\n}\n\ntemplate <typename... Ts>\nstatic size_t strprinterrf(const char* fmt, Ts... ts)\n{\n\treturn static_cast<size_t>(fprintf(stderr, \"%s\", strprintf(fmt, ts...).c_str()));\n}\n\n// template <typename... Ts>\nstatic void outputWithoutContext(const char* type, const Location& loc, const char* s, bool multi)\n{\n\tstrprinterrf(\"%s\", __error_gen_internal(loc, s, type, false, multi));\n}\n\n\n\n\n\n\n\nvoid BareError::post()\n{\n\tif(!this->msg.empty())\n\t\toutputWithoutContext(typestr(this->type).c_str(), Location(), this->msg.c_str(), !this->subs.empty());\n\n\tfor(auto other : this->subs)\n\t\tother->post();\n}\n\n\nvoid SimpleError::post()\n{\n\tif(!this->msg.empty())\n\t{\n\t\toutputWithoutContext(typestr(this->type).c_str(), this->loc, this->msg.c_str(), true);\n\t\tstrprinterrf(\"%s%s%s\", this->wordsBeforeContext, this->wordsBeforeContext.size() > 0 ? \"\\n\" : \"\",\n\t\t\tthis->printContext ? getSingleContext(this->loc, this->type == MsgType::Note ? COLOUR_BLUE_BOLD : COLOUR_RED_BOLD) + \"\\n\" : \"\");\n\t}\n\n\tfor(auto other : this->subs)\n\t\tother->post();\n}\n\n\nvoid ExampleMsg::post()\n{\n\toutputWithoutContext(typestr(this->type).c_str(), Location(), \"for example:\", !this->subs.empty());\n\tstrprinterrf(\"%s\\n\\n\", getSingleContext(Location(), COLOUR_BLUE_BOLD, this->example));\n\n\tfor(auto other : this->subs)\n\t\tother->post();\n}\n\n\nnamespace util\n{\n\tstatic bool operator == (const util::ESpan& a, const util::ESpan& b) { return a.loc == b.loc && a.msg == b.msg; }\n\n\n\tBareError* make_BareError(const std::string& m, MsgType t)\n\t{\n\t\treturn util::pool<BareError>(m, t);\n\t}\n\n\tSpanError* make_SpanError(SimpleError* se, const std::vector<ESpan>& s, MsgType t)\n\t{\n\t\treturn util::pool<SpanError>(se, s, t);\n\t}\n\n\tSimpleError* make_SimpleError(const Location& l, const std::string& m, MsgType t)\n\t{\n\t\treturn util::pool<SimpleError>(l, m, t);\n\t}\n\n\tOverloadError* make_OverloadError(SimpleError* se, MsgType t)\n\t{\n\t\treturn util::pool<OverloadError>(se, t);\n\t}\n\n\tExampleMsg* make_ExampleMsg(const std::string& eg, MsgType t)\n\t{\n\t\treturn util::pool<ExampleMsg>(eg, t);\n\t}\n}\n\n\nSpanError* SpanError::add(const util::ESpan& s)\n{\n\tthis->spans.push_back(s);\n\treturn this;\n}\n\nvoid SpanError::post()\n{\n\tthis->top->printContext = false;\n\tthis->top->post();\n\n\t{\n\t\tsize_t adjust = 0;\n\t\tsize_t margin = 0;\n\t\tsize_t num_width = 0;\n\n\t\tbool didExtra = false;\n\t\tif(this->highlightActual && std::find_if(this->spans.begin(), this->spans.end(), [this](const util::ESpan& s) -> bool {\n\t\t\treturn s.loc == this->top->loc;\n\t\t}) == this->spans.end())\n\t\t{\n\t\t\tdidExtra = true;\n\n\t\t\tauto sp = util::ESpan(this->top->loc, \"\");\n\t\t\tsp.colour = COLOUR_RED_BOLD;\n\n\t\t\tthis->spans.push_back(sp);\n\t\t}\n\n\t\tstd::sort(this->spans.begin(), this->spans.end(), [](const auto& a, const auto& b) -> bool { return a.loc.col < b.loc.col; });\n\t\tthis->spans.erase(std::unique(this->spans.begin(), this->spans.end()), this->spans.end());\n\n\t\tstrprinterrf(\"%s\\n\", getSpannedContext(this->top->loc, this->spans, &adjust, &num_width, &margin, true, true, COLOUR_CYAN_BOLD, \"\"));\n\n\t\t// ok now remove the extra thing.\n\t\tif(didExtra)\n\t\t\tthis->spans.erase(std::find(this->spans.begin(), this->spans.end(), util::ESpan(this->top->loc, \"\")));\n\n\t\tsize_t cursor = 0;\n\t\tsize_t width = static_cast<size_t>(0.85 * platform::getTerminalWidth());\n\n\t\t// there's probably a more efficient way to do this, but since we're throwing an error and already going to die,\n\t\t// it doesn't really matter.\n\n\t\t// don't mutate the spans, make a copy\n\t\tauto spanscopy = this->spans;\n\n\t\tsize_t counter = 0;\n\t\twhile(counter < spanscopy.size())\n\t\t{\n\t\t\tstrprinterrf(\"%s\", spaces(margin));\n\n\t\t\tfor(size_t i = 0; i < spanscopy.size() - counter; i++)\n\t\t\t{\n\t\t\t\tauto col = spanscopy[i].loc.col;\n\n\t\t\t\tif(i == spanscopy.size() - counter - 1)\n\t\t\t\t{\n\t\t\t\t\tauto remaining = spanscopy[i].msg;\n\n\t\t\t\t\t// complex math shit to predict where the cursor will be once we print,\n\t\t\t\t\t// and more importantly whether or not we'll finish printing the message in the current iteration.\n\t\t\t\t\tauto realcursor = margin + col;\n\n\t\t\t\t\tauto splitpos = std::min(remaining.length(), width - realcursor);\n\n\t\t\t\t\t// refuse to split words in half.\n\t\t\t\t\twhile(splitpos > 0 && splitpos < remaining.length() && remaining[splitpos - 1] != ' ')\n\t\t\t\t\t\tsplitpos--;\n\n\t\t\t\t\tauto segment = remaining.substr(0, splitpos);\n\t\t\t\t\tif(segment.empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tcounter++;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tcursor += 3 + strprinterrf(\"%s\", spaces((LEFT_PADDING - 1) + 1 + col - adjust - cursor));\n\t\t\t\t\t\tstrprinterrf(\"%s|>%s \", COLOUR_CYAN_BOLD, COLOUR_RESET);\n\n\t\t\t\t\t\tspanscopy[i].msg = remaining.substr(segment.length());\n\t\t\t\t\t\tcursor += strprinterrf(\"%s\", segment);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tcursor += 1 + strprinterrf(\"%s\", spaces((LEFT_PADDING - 1) + 1 + col - adjust - cursor));\n\t\t\t\t\tstrprinterrf(\"%s|%s\", COLOUR_CYAN_BOLD, COLOUR_RESET);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcursor = 0;\n\t\t\tstrprinterrf(\"\\n\");\n\t\t}\n\t}\n\n\n\tfor(auto other : this->subs)\n\t\tother->post();\n}\n\n\n\n\n\n\n\n\n\n\n\n\nvoid OverloadError::clear()\n{\n\tthis->cands.clear();\n\tthis->top = 0;\n}\n\nOverloadError& OverloadError::addCand(Locatable* d, ErrorMsg* sp)\n{\n\tthis->cands[d] = sp;\n\treturn *this;\n}\n\n\n\nvoid OverloadError::post()\n{\n\t// first, post the original error.\n\tthis->top->wordsBeforeContext = \"(call site)\";\n\tthis->top->post();\n\n\t// sort the candidates by line number\n\t// (idk maybe it's a windows thing but it feels like the order changes every so often)\n\tauto cds = std::vector<std::pair<Locatable*, ErrorMsg*>>(this->cands.begin(), this->cands.end());\n\tstd::sort(cds.begin(), cds.end(), [](auto a, auto b) -> bool { return a.first->loc.line < b.first->loc.line; });\n\n\t// go through each candidate.\n\tint cand_counter = 1;\n\tfor(auto [ loc, emg ] : cds)\n\t{\n\t\tif(emg->kind != ErrKind::Span)\n\t\t{\n\t\t\temg->type = MsgType::Note;\n\t\t\temg->post();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto spe = dcast(SpanError, emg);\n\t\t\ticeAssert(spe);\n\n\t\t\tspe->top = SimpleError::make(MsgType::Note, loc->loc, \"candidate %d was defined here:\", cand_counter++);\n\t\t\tspe->highlightActual = false;\n\t\t\tspe->post();\n\t\t}\n\t}\n\n\tfor(auto sub : this->subs)\n\t\tsub->post();\n}\n\n\n\n\n\n\n\n[[noreturn]] void doTheExit(bool trace)\n{\n\tfprintf(stderr, \"\\nthere were errors, compilation cannot continue\\n\");\n\n\tif(frontend::getAbortOnError()) abort();\n\telse                            exit(-1);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/frontend/file.cpp",
    "content": "// file.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include <string>\n#include <vector>\n#include <fstream>\n#include <unordered_map>\n\n#include <fcntl.h>\n#include <assert.h>\n#include <sys/stat.h>\n\n#include \"lexer.h\"\n#include \"errors.h\"\n#include \"frontend.h\"\n\nnamespace frontend\n{\n\tstatic util::hash_map<std::string, FileInnards> fileList;\n\n\n\tstatic void getRawLines(const std::string_view& fileContents, bool* crlf, util::FastInsertVector<std::string_view>* rawlines)\n\t{\n\t\tstd::string_view view = fileContents;\n\n\t\tbool first = true;\n\t\twhile(true)\n\t\t{\n\t\t\tsize_t ln = 0;\n\n\t\t\tif(first || *crlf)\n\t\t\t{\n\t\t\t\tln = view.find(\"\\r\\n\");\n\t\t\t\tif(ln != std::string_view::npos && first)\n\t\t\t\t\t*crlf = true;\n\t\t\t}\n\n\t\t\tif((!first && !*crlf) || (first && !*crlf && ln == std::string_view::npos))\n\t\t\t\tln = view.find('\\n');\n\n\t\t\tfirst = false;\n\n\t\t\tif(ln != std::string_view::npos)\n\t\t\t{\n\t\t\t\tnew (rawlines->getNextSlotAndIncrement()) std::string_view(view.data(), ln + (*crlf ? 2 : 1));\n\t\t\t\tview.remove_prefix(ln + (*crlf ? 2 : 1));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// account for the case when there's no trailing newline, and we still have some stuff stuck in the view.\n\t\tif(!view.empty())\n\t\t{\n\t\t\tnew (rawlines->getNextSlotAndIncrement()) std::string_view(view.data(), view.length());\n\t\t}\n\t}\n\n\tstatic void tokenise(lexer::TokenList* ts, bool crlf, const std::string_view& fileContents,\n\t\tconst util::FastInsertVector<std::string_view>& lines, Location* pos, std::vector<size_t>* importIndices)\n\t{\n\t\tsize_t curLine = 0;\n\t\tsize_t curOffset = 0;\n\n\t\tbool flag = true;\n\t\tsize_t i = 0;\n\n\t\tdo {\n\t\t\t// store it here so we can fiddle with it later, if we need to.\n\t\t\tauto tok_out = ts->getNextSlotAndIncrement();\n\n\t\t\tauto type = lexer::getNextToken(lines, &curLine, &curOffset, fileContents, *pos,\n\t\t\t\ttok_out, crlf);\n\n\t\t\t// if we reached the end of file, do everybody a favour and insert a newline before the\n\t\t\t// EOF token. the lexer itself can't do this, because it can only operate on one token\n\t\t\t// at a time!\n\n\t\t\tif(type == lexer::TokenType::EndOfFile)\n\t\t\t{\n\t\t\t\t// here is the aforementioned fiddling.\n\t\t\t\ttok_out->type = lexer::TokenType::NewLine;\n\t\t\t\ttok_out->text = \"\\n\";\n\n\t\t\t\t// ok, now we can make another one.\n\t\t\t\tauto real_eof  = ts->getNextSlotAndIncrement();\n\t\t\t\treal_eof->loc  = tok_out->loc;\n\t\t\t\treal_eof->type = lexer::TokenType::EndOfFile;\n\t\t\t}\n\n\t\t\tflag = (type != lexer::TokenType::EndOfFile);\n\n\t\t\tif(type == lexer::TokenType::Import)\n\t\t\t\timportIndices->push_back(i);\n\n\t\t\telse if(type == lexer::TokenType::Invalid)\n\t\t\t\terror(*pos, \"invalid token\");\n\n\t\t\ti++;\n\n\t\t} while(flag);\n\n\t\t(*ts)[ts->size() - 1].loc.len = 0;\n\t}\n\n\n\n\n\tstatic void lex(FileInnards* innards, bool crlf, Location* pos)\n\t{\n\t\tlexer::TokenList& ts = innards->tokens;\n\t\ttokenise(&ts, crlf, innards->fileContents, innards->lines, pos, &innards->importIndices);\n\n\t\tinnards->didLex = true;\n\t}\n\n\tFileInnards lexTokensFromString(const std::string& fakename, const std::string_view& fileContents)\n\t{\n\t\t// split into lines\n\t\tbool crlf = false;\n\t\tutil::FastInsertVector<std::string_view> rawlines;\n\n\t\tgetRawLines(fileContents, &crlf, &rawlines);\n\n\t\tLocation pos;\n\t\tFileInnards innards;\n\t\t{\n\t\t\tpos.fileID = getFileIDFromFilename(fakename);\n\n\t\t\tinnards.fileContents = fileContents;\n\t\t\tinnards.lines = std::move(rawlines);\n\t\t}\n\n\t\tlex(&innards, crlf, &pos);\n\t\treturn innards;\n\t}\n\n\tstatic FileInnards& readFileIfNecessary(const std::string& fullPath)\n\t{\n\t\t// break early if we can\n\t\t{\n\t\t\tauto it = fileList.find(fullPath);\n\t\t\tif(it != fileList.end())\n\t\t\t\treturn it->second;\n\t\t}\n\n\t\tstd::string_view fileContents = platform::readEntireFile(fullPath);\n\n\n\t\t// split into lines\n\t\tbool crlf = false;\n\t\tutil::FastInsertVector<std::string_view> rawlines;\n\t\tgetRawLines(fileContents, &crlf, &rawlines);\n\n\t\tLocation pos;\n\t\tFileInnards& innards = fileList[fullPath];\n\t\t{\n\t\t\tpos.fileID = getFileIDFromFilename(fullPath);\n\n\t\t\tinnards.fileContents = fileContents;\n\t\t\tinnards.lines = std::move(rawlines);\n\t\t}\n\n\t\tlex(&innards, crlf, &pos);\n\t\treturn innards;\n\t}\n\n\tFileInnards& getFileState(const std::string& name)\n\t{\n\t\treturn readFileIfNecessary(name);\n\t}\n\n\tlexer::TokenList& getFileTokens(const std::string& fullPath)\n\t{\n\t\treturn readFileIfNecessary(fullPath).tokens;\n\t}\n\n\tstd::string getFileContents(const std::string& fullPath)\n\t{\n\t\treturn std::string(readFileIfNecessary(fullPath).fileContents);\n\t}\n\n\n\tstatic std::vector<std::string> fileNames { \"null\" };\n\tstatic util::hash_map<std::string, size_t> existingNames;\n\tvoid cachePreExistingFilename(const std::string& name)\n\t{\n\t\tfileNames.push_back(name);\n\t}\n\n\tconst std::string& getFilenameFromID(size_t fileID)\n\t{\n\t\ticeAssert(fileID > 0 && fileID < fileNames.size());\n\t\treturn fileNames[fileID];\n\t}\n\n\tsize_t getFileIDFromFilename(const std::string& name)\n\t{\n\t\tif(existingNames.find(name) != existingNames.end())\n\t\t{\n\t\t\treturn existingNames[name];\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfileNames.push_back(name);\n\t\t\texistingNames[name] = fileNames.size() - 1;\n\n\t\t\treturn fileNames.size() - 1;\n\t\t}\n\t}\n\n\tconst util::FastInsertVector<std::string_view>& getFileLines(size_t id)\n\t{\n\t\treturn readFileIfNecessary(getFilenameFromID(id)).lines;\n\t}\n\n\tconst std::vector<size_t>& getImportTokenLocationsForFile(const std::string& filename)\n\t{\n\t\treturn fileList[filename].importIndices;\n\t}\n\n\n\n\n\tstd::string getPathFromFile(const std::string& path)\n\t{\n\t\tstd::string ret;\n\n\t\tsize_t sep = path.find_last_of(\"\\\\/\");\n\t\tif(sep != std::string::npos)\n\t\t\tret = path.substr(0, sep);\n\n\t\treturn ret;\n\t}\n\n\tstd::string getFilenameFromPath(const std::string& path)\n\t{\n\t\tstd::string ret;\n\n\t\tsize_t sep = path.find_last_of(\"\\\\/\");\n\t\tif(sep != std::string::npos)\n\t\t\tret = path.substr(sep + 1);\n\n\t\treturn ret;\n\t}\n\n\n\tstd::string getFullPathOfFile(const std::string& partial)\n\t{\n\t\tstd::string full = platform::getFullPath(partial);\n\t\tif(full.empty())\n\t\t\terror(\"nonexistent file %s\", partial.c_str());\n\n\t\treturn full;\n\t}\n\n\tstd::string removeExtensionFromFilename(const std::string& name)\n\t{\n\t\tauto i = name.find_last_of('.');\n\t\treturn name.substr(0, i);\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/frontend/import.cpp",
    "content": "// import.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include <sys/stat.h>\n\n#include \"errors.h\"\n#include \"frontend.h\"\n#include \"parser_internal.h\"\n\nnamespace frontend\n{\n\t// map from (imp, fullPath) -> resolvedPath\n\tstatic util::hash_map<std::pair<std::string, std::string>, std::string> importCache;\n\n\t// 'imp' is always a path\n\tstd::string resolveImport(const std::string& imp, const Location& loc, const std::string& fullPath)\n\t{\n\t\tif(auto it = importCache.find({ imp, fullPath }); it != importCache.end())\n\t\t\treturn it->second;\n\n\t\t// std::string ext = \".flx\";\n\t\t// if(imp.size() > ext.size() && imp.find(\".flx\") == imp.size() - ext.size())\n\t\t// \text = \"\";\n\n\t\tstd::string curpath = getPathFromFile(fullPath);\n\t\tstd::string fullname = curpath + \"/\" + imp;\n\n\t\tif(fullname == fullPath)\n\t\t\terror(loc, \"cannot import module from within itself\");\n\n\t\tstd::string resolved;\n\n\t\t// a file here\n\t\tif(auto fname = platform::getFullPath(fullname); !fname.empty())\n\t\t{\n\t\t\tresolved = fname;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::string builtinlib = frontend::getParameter(\"sysroot\") + \"/\" + frontend::getParameter(\"prefix\") + \"/lib/flaxlibs/\" + imp;\n\n\t\t\tif(platform::checkFileExists(builtinlib))\n\t\t\t{\n\t\t\t\tresolved = getFullPathOfFile(builtinlib);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tSimpleError::make(loc, \"no module or library at the path '%s' could be found\", imp)\n\t\t\t\t\t->append(BareError::make(MsgType::Note, \"'%s' does not exist\", fullname))\n\t\t\t\t\t->append(BareError::make(MsgType::Note, \"'%s' does not exist\", builtinlib))\n\t\t\t\t\t->postAndQuit();\n\t\t\t}\n\t\t}\n\n\n\t\timportCache[{ imp, fullPath }] = resolved;\n\t\treturn resolved;\n\t}\n}\n\n\n\n\n\n\nnamespace parser\n{\n\t// TODO: do we want to combine this \"pre-parsing\" with the actual import parsing??\n\t// note that the 'real' parse that we do (to make an AST) makes a useless AST, because we have no\n\t// use for imports after the files are collected.\n\n\tstd::vector<frontend::ImportThing> parseImports(const std::string& filename, const lexer::TokenList& tokens)\n\t{\n\t\tusing Token = lexer::Token;\n\t\tusing TT = lexer::TokenType;\n\n\t\tstd::vector<frontend::ImportThing> imports;\n\n\t\t// basically, this is how it goes:\n\t\t// only allow comments to occur before imports\n\t\t// all imports must happen before anything else in the file\n\t\t// comments can be interspersed between import statements, of course.\n\t\tfor(size_t i = 0; i < tokens.size(); i++)\n\t\t{\n\t\t\tconst Token& tok = tokens[i];\n\t\t\tif(tok == TT::Import || ((tok == TT::Public || tok == TT::Private) && i + 1 < tokens.size() && tokens[i + 1] == TT::Import))\n\t\t\t{\n\t\t\t\tbool pub = false;\n\t\t\t\tif(tok == TT::Public)       i++, pub = true;\n\t\t\t\telse if(tok == TT::Private) i++, warn(tok.loc, \"imports are private by default, 'private import' is redundant\");\n\n\t\t\t\ti++;\n\n\t\t\t\tstd::string name;\n\t\t\t\tLocation impLoc = tok.loc;\n\t\t\t\tstd::vector<std::string> impAs;\n\n\t\t\t\tif(tokens[i] == TT::StringLiteral)\n\t\t\t\t{\n\t\t\t\t\tname = tokens[i].str();\n\t\t\t\t\timpLoc = impLoc.unionWith(tokens[i].loc);\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t\telse if(tokens[i] == TT::Identifier)\n\t\t\t\t{\n\t\t\t\t\tauto [ loc, bits ] = parseIdentPath(tokens, &i);\n\n\t\t\t\t\t//* we concatanate the thing, using '/' as the path separator, and appending '.flx' to the end.\n\t\t\t\t\tname = zfu::join(bits, \"/\") + \".flx\";\n\t\t\t\t\timpLoc = impLoc.unionWith(loc);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\texpectedAfter(tokens[i].loc, \"string literal or identifier path\", \"'import'\", tokens[i].str());\n\t\t\t\t}\n\n\t\t\t\t// check for 'import as foo'\n\t\t\t\tif(tokens[i] == TT::As)\n\t\t\t\t{\n\t\t\t\t\ti++;\n\t\t\t\t\tif(tokens[i] == TT::Identifier)\n\t\t\t\t\t\timpAs = parseIdentPath(tokens, &i).second;\n\n\t\t\t\t\telse\n\t\t\t\t\t\texpectedAfter(tokens[i - 1].loc, \"identifier\", \"'import-as'\", tokens[i - 1].str());\n\t\t\t\t}\n\n\n\t\t\t\tif(tokens[i] != TT::NewLine && tokens[i] != TT::Semicolon && tokens[i] != TT::Comment)\n\t\t\t\t{\n\t\t\t\t\terror(tokens[i].loc, \"expected newline or semicolon to terminate import statement, found '%s'\", tokens[i].str());\n\t\t\t\t}\n\n\t\t\t\tfrontend::ImportThing it { name, impAs, pub, impLoc };\n\t\t\t\timports.push_back(it);\n\n\t\t\t\t// i++ handled by loop\n\t\t\t}\n\t\t\telse if(tok == TT::Export)\n\t\t\t{\n\t\t\t\t// skip until a newline.\n\t\t\t\twhile(tokens[i] != TT::Comment && tokens[i] != TT::NewLine)\n\t\t\t\t\ti++;\n\t\t\t}\n\t\t\telse if(tok == TT::Comment || tok == TT::NewLine)\n\t\t\t{\n\t\t\t\t// skipped\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// stop imports.\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn imports;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/frontend/lexer.cpp",
    "content": "// lexer.cpp\n// Copyright (c) 2014 - 2015, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"lexer.h\"\n#include \"errors.h\"\n\n#include \"utf8rewind/include/utf8rewind/utf8rewind.h\"\n\nusing string_view = std::string_view;\n\nnamespace lexer\n{\n\tstatic void skipWhitespace(string_view& line, Location& pos, size_t* offset)\n\t{\n\t\tsize_t skip = 0;\n\t\twhile(line.length() > skip && (line[skip] == '\\t' || line[skip] == ' '))\n\t\t{\n\t\t\t(line[skip] == ' ' ? pos.col++ : pos.col += TAB_WIDTH);\n\t\t\tskip++;\n\t\t}\n\n\t\tline.remove_prefix(skip);\n\t\t(*offset) += skip;\n\t}\n\n\ttemplate <size_t N>\n\tstatic bool hasPrefix(const string_view& str, char const (&literal)[N])\n\t{\n\t\tif(str.length() < N - 1) return false;\n\t\tfor(size_t i = 0; i < N - 1; i++)\n\t\t\tif(str[i] != literal[i]) return false;\n\n\t\treturn true;\n\t}\n\n\ttemplate <size_t N>\n\tstatic bool compare(const string_view& str, char const (&literal)[N])\n\t{\n\t\tif(str.length() != N - 1) return false;\n\t\tfor(size_t i = 0; i < N - 1; i++)\n\t\t\tif(str[i] != literal[i]) return false;\n\n\t\treturn true;\n\t}\n\n\n\n\tstatic TokenType prevType = TokenType::Invalid;\n\tstatic size_t prevID = 0;\n\tstatic bool shouldConsiderUnaryLiteral(string_view& stream, Location& pos)\n\t{\n\t\t// check the previous token\n\t\tbool should = (prevType != TokenType::Invalid && prevID == pos.fileID && (\n\t\t\tprevType != TokenType::RParen &&\n\t\t\tprevType != TokenType::RSquare &&\n\t\t\tprevType != TokenType::Identifier &&\n\t\t\tprevType != TokenType::Number &&\n\t\t\tprevType != TokenType::Dollar &&\n\t\t\tprevType != TokenType::StringLiteral\n\t\t));\n\n\t\tif(!should) return false;\n\n\t\t// check if the current char is a + or -\n\t\tif(stream.length() == 0) return false;\n\t\tif(stream[0] != '+' && stream[0] != '-') return false;\n\n\t\t// check if there's only spaces between this and the number itself\n\t\tfor(size_t i = 1; i < stream.length(); i++)\n\t\t{\n\t\t\tif(isdigit(stream[i])) return true;\n\t\t\telse if(stream[i] != ' ') return false;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\n\tstatic util::hash_map<std::string_view, TokenType> keywordMap;\n\tstatic void initKeywordMap()\n\t{\n\t\tif(keywordMap.size() > 0) return;\n\n\t\tkeywordMap[\"as\"]        = TokenType::As;\n\t\tkeywordMap[\"do\"]        = TokenType::Do;\n\t\tkeywordMap[\"if\"]        = TokenType::If;\n\t\tkeywordMap[\"is\"]        = TokenType::Is;\n\t\tkeywordMap[\"let\"]       = TokenType::Val;\n\t\tkeywordMap[\"var\"]       = TokenType::Var;\n\t\tkeywordMap[\"for\"]       = TokenType::For;\n\t\tkeywordMap[\"fn\"]        = TokenType::Func;\n\t\tkeywordMap[\"else\"]      = TokenType::Else;\n\t\tkeywordMap[\"true\"]      = TokenType::True;\n\t\tkeywordMap[\"enum\"]      = TokenType::Enum;\n\t\tkeywordMap[\"null\"]      = TokenType::Null;\n\t\tkeywordMap[\"case\"]      = TokenType::Case;\n\t\tkeywordMap[\"trait\"]     = TokenType::Trait;\n\t\tkeywordMap[\"defer\"]     = TokenType::Defer;\n\t\tkeywordMap[\"alloc\"]     = TokenType::Alloc;\n\t\tkeywordMap[\"false\"]     = TokenType::False;\n\t\tkeywordMap[\"while\"]     = TokenType::While;\n\t\tkeywordMap[\"break\"]     = TokenType::Break;\n\t\tkeywordMap[\"class\"]     = TokenType::Class;\n\t\tkeywordMap[\"using\"]     = TokenType::Using;\n\t\tkeywordMap[\"union\"]     = TokenType::Union;\n\t\tkeywordMap[\"struct\"]    = TokenType::Struct;\n\t\tkeywordMap[\"import\"]    = TokenType::Import;\n\t\tkeywordMap[\"public\"]    = TokenType::Public;\n\t\tkeywordMap[\"switch\"]    = TokenType::Switch;\n\t\tkeywordMap[\"return\"]    = TokenType::Return;\n\t\tkeywordMap[\"export\"]    = TokenType::Export;\n\t\tkeywordMap[\"sizeof\"]    = TokenType::Sizeof;\n\t\tkeywordMap[\"typeof\"]    = TokenType::Typeof;\n\t\tkeywordMap[\"typeid\"]    = TokenType::Typeid;\n\t\tkeywordMap[\"static\"]    = TokenType::Static;\n\t\tkeywordMap[\"mut\"]       = TokenType::Mutable;\n\t\tkeywordMap[\"free\"]      = TokenType::Dealloc;\n\t\tkeywordMap[\"private\"]   = TokenType::Private;\n\t\tkeywordMap[\"virtual\"]   = TokenType::Virtual;\n\t\tkeywordMap[\"internal\"]  = TokenType::Internal;\n\t\tkeywordMap[\"override\"]  = TokenType::Override;\n\t\tkeywordMap[\"operator\"]  = TokenType::Operator;\n\t\tkeywordMap[\"continue\"]  = TokenType::Continue;\n\t\tkeywordMap[\"typealias\"] = TokenType::TypeAlias;\n\t\tkeywordMap[\"extension\"] = TokenType::Extension;\n\t\tkeywordMap[\"namespace\"] = TokenType::Namespace;\n\t\tkeywordMap[\"ffi\"]       = TokenType::ForeignFunc;\n\t}\n\n\n\n\n\n\n\tTokenType getNextToken(const util::FastInsertVector<string_view>& lines, size_t* line, size_t* offset, const string_view& whole,\n\t\tLocation& pos, Token* out, bool crlf)\n\t{\n\t\tbool flag = true;\n\n\t\tif(*line == lines.size())\n\t\t{\n\t\t\tout->loc = pos;\n\t\t\tout->type = TokenType::EndOfFile;\n\t\t\treturn TokenType::EndOfFile;\n\t\t}\n\n\t\tstring_view stream = lines[*line].substr(*offset);\n\t\tskipWhitespace(stream, pos, offset);\n\t\tif(stream.empty() || stream[0] == 0)\n\t\t{\n\t\t\tout->loc = pos;\n\t\t\tout->type = TokenType::EndOfFile;\n\t\t\treturn TokenType::EndOfFile;\n\t\t}\n\n\n\t\tsize_t read = 0;\n\t\tsize_t unicodeLength = 0;\n\n\n\t\tToken& tok = *out;\n\t\ttok.loc = pos;\n\t\ttok.type = TokenType::Invalid;\n\n\t\t// check compound symbols first.\n\t\tif(hasPrefix(stream, \"//\"))\n\t\t{\n\t\t\ttok.type = TokenType::Comment;\n\t\t\t// stream = stream.substr(0, 0);\n\t\t\t(*line)++;\n\t\t\tpos.line++;\n\t\t\tpos.col = 0;\n\n\n\t\t\t(*offset) = 0;\n\n\t\t\t// don't assign lines[line] = stream, since over here we've changed 'line' to be the next one.\n\t\t\tflag = false;\n\t\t\ttok.text = \"\";\n\t\t}\n\t\telse if(hasPrefix(stream, \"==\"))\n\t\t{\n\t\t\ttok.type = TokenType::EqualsTo;\n\t\t\ttok.text = \"==\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \">=\"))\n\t\t{\n\t\t\ttok.type = TokenType::GreaterEquals;\n\t\t\ttok.text = \">=\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"<=\"))\n\t\t{\n\t\t\ttok.type = TokenType::LessThanEquals;\n\t\t\ttok.text = \"<=\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"!=\"))\n\t\t{\n\t\t\ttok.type = TokenType::NotEquals;\n\t\t\ttok.text = \"!=\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"||\"))\n\t\t{\n\t\t\ttok.type = TokenType::LogicalOr;\n\t\t\ttok.text = \"||\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"&&\"))\n\t\t{\n\t\t\ttok.type = TokenType::LogicalAnd;\n\t\t\ttok.text = \"&&\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"<-\"))\n\t\t{\n\t\t\ttok.type = TokenType::LeftArrow;\n\t\t\ttok.text = \"<-\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"->\"))\n\t\t{\n\t\t\ttok.type = TokenType::RightArrow;\n\t\t\ttok.text = \"->\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"<=\"))\n\t\t{\n\t\t\ttok.type = TokenType::FatLeftArrow;\n\t\t\ttok.text = \"<=\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"=>\"))\n\t\t{\n\t\t\ttok.type = TokenType::FatRightArrow;\n\t\t\ttok.text = \"=>\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"++\"))\n\t\t{\n\t\t\ttok.type = TokenType::DoublePlus;\n\t\t\ttok.text = \"++\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"--\"))\n\t\t{\n\t\t\ttok.type = TokenType::DoubleMinus;\n\t\t\ttok.text = \"--\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"+=\"))\n\t\t{\n\t\t\ttok.type = TokenType::PlusEq;\n\t\t\ttok.text = \"+=\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"-=\"))\n\t\t{\n\t\t\ttok.type = TokenType::MinusEq;\n\t\t\ttok.text = \"-=\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"*=\"))\n\t\t{\n\t\t\ttok.type = TokenType::MultiplyEq;\n\t\t\ttok.text = \"*=\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"/=\"))\n\t\t{\n\t\t\ttok.type = TokenType::DivideEq;\n\t\t\ttok.text = \"/=\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"%=\"))\n\t\t{\n\t\t\ttok.type = TokenType::ModEq;\n\t\t\ttok.text = \"%=\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"&=\"))\n\t\t{\n\t\t\ttok.type = TokenType::AmpersandEq;\n\t\t\ttok.text = \"&=\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"|=\"))\n\t\t{\n\t\t\ttok.type = TokenType::PipeEq;\n\t\t\ttok.text = \"|=\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"^=\"))\n\t\t{\n\t\t\ttok.type = TokenType::CaretEq;\n\t\t\ttok.text = \"^=\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"::\"))\n\t\t{\n\t\t\ttok.type = TokenType::DoubleColon;\n\t\t\ttok.text = \"::\";\n\t\t\tread = 2;\n\t\t}\n\t\telse if(hasPrefix(stream, \"...\"))\n\t\t{\n\t\t\ttok.type = TokenType::Ellipsis;\n\t\t\ttok.text = \"...\";\n\t\t\tread = 3;\n\t\t}\n\t\telse if(hasPrefix(stream, \"..<\"))\n\t\t{\n\t\t\ttok.type = TokenType::HalfOpenEllipsis;\n\t\t\ttok.text = \"..<\";\n\t\t\tread = 3;\n\t\t}\n\t\telse if(hasPrefix(stream, \"/*\"))\n\t\t{\n\t\t\tint currentNest = 1;\n\n\t\t\t// support nested, so basically we have to loop until we find either a /* or a */\n\t\t\tstream.remove_prefix(2);\n\t\t\t(*offset) += 2;\n\t\t\tpos.col += 2;\n\n\n\t\t\tLocation opening = pos;\n\t\t\tLocation curpos = pos;\n\n\t\t\tsize_t k = 0;\n\t\t\twhile(currentNest > 0)\n\t\t\t{\n\t\t\t\t// we can do this, because we know the closing token (*/) is 2 chars long\n\t\t\t\t// so if we have 1 char left, gg.\n\t\t\t\tif(k + 1 == stream.size() || stream[k] == '\\n')\n\t\t\t\t{\n\t\t\t\t\tif(*line + 1 == lines.size())\n\t\t\t\t\t\terror(opening, \"expected closing */ (reached EOF), for block comment started here:\");\n\n\t\t\t\t\t// else, get the next line.\n\t\t\t\t\t// also note: if we're in this loop, we're inside a block comment.\n\t\t\t\t\t// since the ending token cannot be split across lines, we know that this last char\n\t\t\t\t\t// must also be part of the comment. hence, just skip over it.\n\n\t\t\t\t\tk = 0;\n\t\t\t\t\tcurpos.line++;\n\t\t\t\t\tcurpos.col = 0;\n\t\t\t\t\t(*offset) = 0;\n\t\t\t\t\t(*line)++;\n\n\t\t\t\t\tstream = lines[*line];\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\n\t\t\t\tif(stream[k] == '/' && stream[k + 1] == '*')\n\t\t\t\t\tcurrentNest++, k++, curpos.col++, opening = curpos;\n\n\t\t\t\telse if(stream[k] == '*' && stream[k + 1] == '/')\n\t\t\t\t\tcurrentNest--, k++, curpos.col++;\n\n\t\t\t\tk++;\n\t\t\t\tcurpos.col++;\n\t\t\t}\n\n\n\t\t\tif(currentNest != 0)\n\t\t\t\terror(opening, \"expected closing */ (reached EOF), for block comment started here:\");\n\n\t\t\tpos = curpos;\n\n\t\t\t// don't actually store the text, because it's pointless and memory-wasting\n\t\t\t// tok.text = \"/* I used to be a comment like you, until I took a memory-leak to the knee. */\";\n\t\t\ttok.type = TokenType::Comment;\n\t\t\ttok.text = \"\";\n\t\t\tread = k;\n\t\t}\n\t\telse if(hasPrefix(stream, \"*/\"))\n\t\t{\n\t\t\terror(tok.loc, \"unexpected '*/'\");\n\t\t}\n\n\n\n\t\t// attrs\n\t\telse if(hasPrefix(stream, \"@nomangle\"))\n\t\t{\n\t\t\ttok.type = TokenType::Attr_NoMangle;\n\t\t\ttok.text = \"@nomangle\";\n\t\t\tread = 9;\n\t\t}\n\t\telse if(hasPrefix(stream, \"@entry\"))\n\t\t{\n\t\t\ttok.type = TokenType::Attr_EntryFn;\n\t\t\ttok.text = \"@entry\";\n\t\t\tread = 6;\n\t\t}\n\t\telse if(hasPrefix(stream, \"@packed\"))\n\t\t{\n\t\t\ttok.type = TokenType::Attr_Packed;\n\t\t\ttok.text = \"@packed\";\n\t\t\tread = 7;\n\t\t}\n\t\telse if(hasPrefix(stream, \"@raw\"))\n\t\t{\n\t\t\ttok.type = TokenType::Attr_Raw;\n\t\t\ttok.text = \"@raw\";\n\t\t\tread = 4;\n\t\t}\n\t\telse if(hasPrefix(stream, \"@operator\"))\n\t\t{\n\t\t\ttok.type = TokenType::Attr_Operator;\n\t\t\ttok.text = \"@operator\";\n\t\t\tread = 9;\n\t\t}\n\t\telse if(hasPrefix(stream, \"@platform\"))\n\t\t{\n\t\t\ttok.type = TokenType::Attr_Platform;\n\t\t\ttok.text = \"@platform\";\n\t\t\tread = 9;\n\t\t}\n\n\t\t// directives\n\t\telse if(hasPrefix(stream, \"#if\"))\n\t\t{\n\t\t\ttok.type = TokenType::Directive_If;\n\t\t\ttok.text = \"#if\";\n\t\t\tread = 3;\n\t\t}\n\t\telse if(hasPrefix(stream, \"#run\"))\n\t\t{\n\t\t\ttok.type = TokenType::Directive_Run;\n\t\t\ttok.text = \"#run\";\n\t\t\tread = 4;\n\t\t}\n\n\n\t\t// unicode stuff\n\t\telse if(hasPrefix(stream, \"ƒ\"))\n\t\t{\n\t\t\ttok.type = TokenType::Func;\n\t\t\tread = std::string(\"ƒ\").length();\n\t\t\ttok.text = \"ƒ\";\n\n\t\t\tunicodeLength = 1;\n\t\t}\n\t\telse if(hasPrefix(stream, \"ﬁ\"))\n\t\t{\n\t\t\ttok.type = TokenType::ForeignFunc;\n\t\t\tread = std::string(\"ﬁ\").length();\n\t\t\ttok.text = \"ﬁ\";\n\n\t\t\tunicodeLength = 1;\n\t\t}\n\t\telse if(hasPrefix(stream, \"÷\"))\n\t\t{\n\t\t\ttok.type = TokenType::Divide;\n\t\t\tread = std::string(\"÷\").length();\n\t\t\ttok.text = \"÷\";\n\n\t\t\tunicodeLength = 1;\n\t\t}\n\t\telse if(hasPrefix(stream, \"≠\"))\n\t\t{\n\t\t\ttok.type = TokenType::NotEquals;\n\t\t\tread = std::string(\"≠\").length();\n\t\t\ttok.text = \"≠\";\n\n\t\t\tunicodeLength = 1;\n\t\t}\n\t\telse if(hasPrefix(stream, \"≤\"))\n\t\t{\n\t\t\ttok.type = TokenType::LessThanEquals;\n\t\t\tread = std::string(\"≤\").length();\n\t\t\ttok.text = \"≤\";\n\n\t\t\tunicodeLength = 1;\n\t\t}\n\t\telse if(hasPrefix(stream, \"≥\"))\n\t\t{\n\t\t\ttok.type = TokenType::GreaterEquals;\n\t\t\tread = std::string(\"≥\").length();\n\t\t\ttok.text = \"≥\";\n\n\t\t\tunicodeLength = 1;\n\t\t}\n\n\t\telse if(hasPrefix(stream, \"'\") && stream.size() > 2)\n\t\t{\n\t\t\ttok.type = TokenType::CharacterLiteral;\n\n\t\t\tif(stream[1] == '\\\\')\n\t\t\t{\n\t\t\t\tswitch(stream[2])\n\t\t\t\t{\n\t\t\t\t\tcase 'n':   tok.text = \"\\n\"; break;\n\t\t\t\t\tcase 'b':   tok.text = \"\\b\"; break;\n\t\t\t\t\tcase 'a':   tok.text = \"\\a\"; break;\n\t\t\t\t\tcase 'r':   tok.text = \"\\r\"; break;\n\t\t\t\t\tcase 't':   tok.text = \"\\t\"; break;\n\t\t\t\t\tcase '\\'':  tok.text = \"'\"; break;\n\t\t\t\t\tcase '\\\\':  tok.text = \"\\\\\"; break;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\terror(pos, \"invalid escape sequence ('\\\\%c') in character literal\", stream[2]);\n\t\t\t\t}\n\n\t\t\t\tread = 4;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttok.text = stream.substr(1, 1);\n\t\t\t\tread = 3;\n\t\t\t}\n\n\t\t\tif(stream[read - 1] != '\\'')\n\t\t\t\terror(pos, \"expected closing '\");\n\t\t}\n\n\t\t// note some special-casing is needed to differentiate between unary +/- and binary +/-\n\t\t// cases where we want binary:\n\t\t// ...) + 3   |   ...] + 3   |   ident + 3   |   number + 3   |   string + 3\n\t\t// so in every other case we want unary +/-.\n\t\t// note: a sane implementation would just return false if isdigit() was passed something weird, like a negative number\n\t\t// (because we tried to dissect a UTF-8 codepoint). so we just check if it's ascii first, which would solve the issue.\n\t\telse if((!stream.empty() && ((isascii(stream[0]) && isdigit(stream[0])) || shouldConsiderUnaryLiteral(stream, pos)))\n\t\t\t/* handle cases like '+ 3' or '- 14' (ie. space between sign and number) */\n\t\t\t&& ((isascii(stream[0]) && isdigit(stream[0]) ? true : false) || (stream.size() > 1 && isascii(stream[1]) && isdigit(stream[1]))))\n\t\t{\n\t\t\t// copy it.\n\t\t\tauto tmp = stream;\n\n\t\t\tif(tmp.find('-') == 0 || tmp.find('+') == 0)\n\t\t\t\ttmp.remove_prefix(1);\n\n\t\t\tint base = 10;\n\t\t\tif(tmp.find(\"0x\") == 0 || tmp.find(\"0X\") == 0)\n\t\t\t\tbase = 16, tmp.remove_prefix(2);\n\n\t\t\telse if(tmp.find(\"0b\") == 0 || tmp.find(\"0B\") == 0)\n\t\t\t\tbase = 2, tmp.remove_prefix(2);\n\n\n\t\t\t// find that shit\n\t\t\tauto end = std::find_if_not(tmp.begin(), tmp.end(), [base](const char& c) -> bool {\n\t\t\t\tif(base == 10)\treturn isdigit(c);\n\t\t\t\tif(base == 16)\treturn isdigit(c) || (toupper(c) >= 'A' && toupper(c) <= 'F');\n\t\t\t\telse\t\t\treturn (c == '0' || c == '1');\n\t\t\t});\n\n\t\t\ttmp.remove_prefix((end - tmp.begin()));\n\n\t\t\t// check if we have 'e' or 'E'\n\t\t\tbool hadExp = false;\n\t\t\tif(tmp.size() > 0 && (tmp[0] == 'e' || tmp[0] == 'E'))\n\t\t\t{\n\t\t\t\tif(base != 10)\n\t\t\t\t\terror(\"exponential form is supported with neither hexadecimal nor binary literals\");\n\n\t\t\t\t// find that shit\n\t\t\t\tauto next = std::find_if_not(tmp.begin() + 1, tmp.end(), isdigit);\n\n\t\t\t\t// this does the 'e' as well.\n\t\t\t\ttmp.remove_prefix(next - tmp.begin());\n\n\t\t\t\thadExp = true;\n\t\t\t}\n\n\t\t\tsize_t didRead = stream.size() - tmp.size();\n\t\t\tauto post = stream.substr(didRead);\n\n\t\t\tif(!post.empty() && post[0] == '.')\n\t\t\t{\n\t\t\t\tif(base != 10)\n\t\t\t\t\terror(\"invalid floating point literal; only valid in base 10\");\n\n\t\t\t\telse if(hadExp)\n\t\t\t\t\terror(\"invalid floating point literal; decimal point cannot occur after the exponent ('e' or 'E').\");\n\n\t\t\t\t// if the previous token was a '.' as well, then we're doing some tuple access\n\t\t\t\t// eg. x.0.1 (we would be at '0', having a period both ahead and behind us)\n\n\t\t\t\t// if the next token is not a number, then same thing, eg.\n\t\t\t\t// x.0.z, where the first tuple element of 'x' is a struct or something.\n\n\t\t\t\t// so -- lex a floating point *iff* the previous token was not '.', and the next token is a digit.\n\t\t\t\tif(prevType != TokenType::Period && post.size() > 1 && isdigit(post[1]))\n\t\t\t\t{\n\t\t\t\t\t// yes, parse a floating point\n\t\t\t\t\tpost.remove_prefix(1), didRead++;\n\n\t\t\t\t\twhile(post.size() > 0 && isdigit(post.front()))\n\t\t\t\t\t\tpost.remove_prefix(1), didRead++;\n\n\t\t\t\t\t// ok.\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// no, just return the integer token.\n\t\t\t\t\t// (which we do below, so just do nothing here)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttok.text = stream.substr(0, didRead);\n\n\t\t\ttok.type = TokenType::Number;\n\t\t\ttok.loc.len = didRead;\n\n\t\t\tread = didRead;\n\t\t}\n\t\telse if(!stream.empty() && (stream[0] == '_'  || utf8iscategory(stream.data(), stream.size(), UTF8_CATEGORY_LETTER) > 0))\n\t\t{\n\t\t\t// get as many letters as possible first\n\t\t\tsize_t identLength = utf8iscategory(stream.data(), stream.size(),\n\t\t\t\tUTF8_CATEGORY_LETTER | UTF8_CATEGORY_PUNCTUATION_CONNECTOR | UTF8_CATEGORY_NUMBER);\n\n\t\t\tread = identLength;\n\t\t\ttok.text = stream.substr(0, identLength);\n\n\t\t\tinitKeywordMap();\n\t\t\tif(auto it = keywordMap.find(tok.text); it != keywordMap.end())\n\t\t\t\ttok.type = it->second;\n\n\t\t\telse\n\t\t\t\ttok.type = TokenType::Identifier;\n\n\t\t\t// again, assume that one codepoint is 1 character wide?\n\t\t\t// note: we convert to std::string because I believe utf8len expects null-term strings, but\n\t\t\t// tok.text is a string_view.\n\t\t\tunicodeLength = utf8len(std::string(tok.text).c_str());\n\t\t}\n\t\telse if(!stream.empty() && stream[0] == '\"')\n\t\t{\n\t\t\t// string literal\n\t\t\t// because we want to avoid using std::string (ie. copying) in the lexer (Token), we must send the string over verbatim.\n\n\t\t\t// store the starting position\n\t\t\tsize_t start = (stream.data() - whole.data() + 1);\n\n\t\t\t// opening \"\n\t\t\tpos.col++;\n\n\t\t\tsize_t i = 1;\n\t\t\tsize_t didRead = 0;\n\t\t\tfor(; stream[i] != '\"'; i++)\n\t\t\t{\n\t\t\t\tif(stream[i] == '\\\\')\n\t\t\t\t{\n\t\t\t\t\tif(i + 1 == stream.size())\n\t\t\t\t\t{\n\t\t\t\t\t\terror(pos, \"unexpected end of input\");\n\t\t\t\t\t}\n\t\t\t\t\telse if(stream[i + 1] == '\"')\n\t\t\t\t\t{\n\t\t\t\t\t\t// add the quote and the backslash, and skip it.\n\t\t\t\t\t\tdidRead += 2;\n\t\t\t\t\t\tpos.col += 2;\n\t\t\t\t\t\ti++;\n\t\t\t\t\t}\n\t\t\t\t\t// breaking string over two lines\n\t\t\t\t\telse if(stream[i + 1] == '\\n')\n\t\t\t\t\t{\n\t\t\t\t\t\t// skip it, then move to the next line\n\t\t\t\t\t\tpos.line++;\n\t\t\t\t\t\tpos.col = 0;\n\t\t\t\t\t\t(*line)++;\n\n\t\t\t\t\t\tif(*line == lines.size())\n\t\t\t\t\t\t\terror(pos, \"unexpected end of input\");\n\n\t\t\t\t\t\ti = 0;\n\n\t\t\t\t\t\t// just a fudge factor gotten from empirical evidence\n\t\t\t\t\t\t// 3 extra holds for multiple lines, so all is well.\n\n\t\t\t\t\t\tdidRead += 3;\n\t\t\t\t\t\tstream = lines[*line];\n\t\t\t\t\t\t(*offset) = 0;\n\t\t\t\t\t}\n\t\t\t\t\telse if(stream[i + 1] == '\\\\')\n\t\t\t\t\t{\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\tdidRead += 2;\n\t\t\t\t\t\tpos.col += 2;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// just put the backslash in.\n\t\t\t\t\t\t// and don't skip the next one.\n\t\t\t\t\t\tdidRead++;\n\t\t\t\t\t\tpos.col++;\n\t\t\t\t\t}\n\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tdidRead++;\n\t\t\t\tpos.col++;\n\n\t\t\t\tif(i == stream.size() - 1 || stream[i] == '\\n')\n\t\t\t\t{\n\t\t\t\t\terror(pos, \"expected closing '\\\"'\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// closing \"\n\t\t\tpos.col++;\n\n\n\t\t\ttok.type = TokenType::StringLiteral;\n\t\t\ttok.text = whole.substr(start, didRead);\n\n\t\t\ttok.loc.len = 2 + didRead;\n\n\t\t\tstream = stream.substr(i + 1);\n\t\t\t(*offset) += i + 1;\n\n\t\t\tread = 0;\n\t\t\tflag = false;\n\t\t}\n\t\telse if(crlf && hasPrefix(stream, \"\\r\\n\"))\n\t\t{\n\t\t\tread = 2;\n\t\t\tflag = false;\n\n\t\t\ttok.type = TokenType::NewLine;\n\t\t\ttok.text = \"\\n\";\n\t\t}\n\t\telse if(!stream.empty())\n\t\t{\n\t\t\tif(isascii(stream[0]))\n\t\t\t{\n\t\t\t\t// check the first char\n\t\t\t\tswitch(stream[0])\n\t\t\t\t{\n\t\t\t\t\t// for single-char things\n\t\t\t\t\tcase '\\n':  tok.type = TokenType::NewLine;      break;\n\t\t\t\t\tcase '{':   tok.type = TokenType::LBrace;       break;\n\t\t\t\t\tcase '}':   tok.type = TokenType::RBrace;       break;\n\t\t\t\t\tcase '(':   tok.type = TokenType::LParen;       break;\n\t\t\t\t\tcase ')':   tok.type = TokenType::RParen;       break;\n\t\t\t\t\tcase '[':   tok.type = TokenType::LSquare;      break;\n\t\t\t\t\tcase ']':   tok.type = TokenType::RSquare;      break;\n\t\t\t\t\tcase '<':   tok.type = TokenType::LAngle;       break;\n\t\t\t\t\tcase '>':   tok.type = TokenType::RAngle;       break;\n\t\t\t\t\tcase '+':   tok.type = TokenType::Plus;         break;\n\t\t\t\t\tcase '-':   tok.type = TokenType::Minus;        break;\n\t\t\t\t\tcase '*':   tok.type = TokenType::Asterisk;     break;\n\t\t\t\t\tcase '/':   tok.type = TokenType::Divide;       break;\n\t\t\t\t\tcase '\\'':  tok.type = TokenType::SQuote;       break;\n\t\t\t\t\tcase '.':   tok.type = TokenType::Period;       break;\n\t\t\t\t\tcase ',':   tok.type = TokenType::Comma;        break;\n\t\t\t\t\tcase ':':   tok.type = TokenType::Colon;        break;\n\t\t\t\t\tcase '=':   tok.type = TokenType::Equal;        break;\n\t\t\t\t\tcase '?':   tok.type = TokenType::Question;     break;\n\t\t\t\t\tcase '!':   tok.type = TokenType::Exclamation;  break;\n\t\t\t\t\tcase ';':   tok.type = TokenType::Semicolon;    break;\n\t\t\t\t\tcase '&':   tok.type = TokenType::Ampersand;    break;\n\t\t\t\t\tcase '%':   tok.type = TokenType::Percent;      break;\n\t\t\t\t\tcase '|':   tok.type = TokenType::Pipe;         break;\n\t\t\t\t\tcase '@':   tok.type = TokenType::At;           break;\n\t\t\t\t\tcase '#':   tok.type = TokenType::Pound;        break;\n\t\t\t\t\tcase '~':   tok.type = TokenType::Tilde;        break;\n\t\t\t\t\tcase '^':   tok.type = TokenType::Caret;        break;\n\t\t\t\t\tcase '$':   tok.type = TokenType::Dollar;       break;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\terror(tok.loc, \"unknown token '%c'\", stream[0]);\n\t\t\t\t}\n\n\t\t\t\ttok.text = stream.substr(0, 1);\n\t\t\t\t// tok.loc.col += 1;\n\t\t\t\tread = 1;\n\t\t\t}\n\t\t\telse if(utf8iscategory(stream.data(), stream.size(), UTF8_CATEGORY_SYMBOL_MATH | UTF8_CATEGORY_PUNCTUATION_OTHER) > 0)\n\t\t\t{\n\t\t\t\tread = utf8iscategory(stream.data(), stream.size(), UTF8_CATEGORY_SYMBOL_MATH | UTF8_CATEGORY_PUNCTUATION_OTHER);\n\n\t\t\t\ttok.text = stream.substr(0, read);\n\t\t\t\ttok.type = TokenType::UnicodeSymbol;\n\n\t\t\t\t// assume that everything is one character wide only!\n\t\t\t\tunicodeLength = 1;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// one char wide, at least. not in bytes.\n\t\t\t\tauto l = tok.loc; l.len = 1;\n\n\t\t\t\t// get the number of bytes of the next codepoint, by seeking +1 and subtracting the pointer.\n\t\t\t\tauto cplen = utf8seek(stream.data(), stream.size(), stream.data(), 1, SEEK_SET) - stream.data();\n\n\t\t\t\terror(l, \"unknown token '%s'\", stream.substr(0, cplen));\n\t\t\t}\n\t\t}\n\n\t\tstream.remove_prefix(read);\n\n\t\tif(flag)\n\t\t\t(*offset) += read;\n\n\t\tif(tok.type != TokenType::NewLine)\n\t\t{\n\t\t\tif(read > 0)\n\t\t\t{\n\t\t\t\t// note(debatable): put the actual \"position\" in the front of the token\n\t\t\t\tpos.col += (unicodeLength > 0 ? unicodeLength : read);\n\n\t\t\t\t// special handling -- things like ƒ, ≤ etc. are one character wide, but can be several *bytes* long.\n\t\t\t\tpos.len = (unicodeLength > 0 ? unicodeLength : read);\n\t\t\t\ttok.loc.len = (unicodeLength > 0 ? unicodeLength : read);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpos.col = 0;\n\t\t\tpos.line++;\n\n\t\t\t(*line)++;\n\t\t\t(*offset) = 0;\n\t\t}\n\n\n\t\tprevType = tok.type;\n\t\tprevID = tok.loc.fileID;\n\n\t\treturn prevType;\n\t}\n}\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/frontend/parser/controlflow.cpp",
    "content": "// controlflow.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"parser_internal.h\"\n\n#include \"memorypool.h\"\n\nnamespace parser\n{\n\tusing TT = lexer::TokenType;\n\tusing namespace ast;\n\n\tPResult<Stmt> parseIfStmt(State& st)\n\t{\n\t\tusing Case = IfStmt::Case;\n\n\t\tauto tok_if = st.eat();\n\t\ticeAssert(tok_if == TT::If || tok_if == TT::Directive_If);\n\n\t\tbool isStaticIf = tok_if == TT::Directive_If;\n\n\t\t// of this form:\n\t\t// if(var x = 30; var k = 30; x == k) { ... } else if(cond) { ... }\n\t\t// braces are compulsory\n\t\t// parentheses around the condition are not\n\n\t\tBlock* elseCase = 0;\n\t\tstd::vector<Case> cases;\n\t\tcases.push_back(Case());\n\n\n\t\t// first one\n\t\t{\n\t\t\t// ok -- the first one we must do manually.\n\t\t\t// probably not, but i'm lazy.\n\t\t\twhile(st.front() == TT::Val || st.front() == TT::Var)\n\t\t\t{\n\t\t\t\tcases.back().inits.push_back(parseVariable(st));\n\t\t\t\tst.skipWS();\n\n\t\t\t\tif(st.front() != TT::Semicolon)\n\t\t\t\t\texpectedAfter(st, \"semicolon ';'\", \"if-variable-initialisation\", st.front().str());\n\n\t\t\t\tst.eat();\n\t\t\t}\n\n\t\t\t// ok, we finished doing the variables.\n\t\t\tcases.back().cond = parseExpr(st);\n\n\t\t\tif(auto x = parseBracedBlock(st); x.isError())\n\t\t\t\treturn PResult<Stmt>::copyError(x);\n\n\t\t\telse\n\t\t\t\tcases.back().body = x.val();\n\t\t}\n\n\n\t\t// ok, do the else-if chain\n\t\twhile(st.frontAfterWS() == TT::Else)\n\t\t{\n\t\t\tst.eat();\n\n\t\t\tif(st.front() == TT::If)\n\t\t\t{\n\t\t\t\tCase c;\n\n\t\t\t\t// ok, it's an else-if.\n\t\t\t\tst.eat();\n\n\t\t\t\twhile(st.front() == TT::Val || st.front() == TT::Var)\n\t\t\t\t{\n\t\t\t\t\tc.inits.push_back(parseVariable(st));\n\t\t\t\t\tst.skipWS();\n\n\t\t\t\t\tif(st.front() != TT::Semicolon)\n\t\t\t\t\t\texpectedAfter(st, \"semicolon ';'\", \"if-variable-initialisation\", st.front().str());\n\n\t\t\t\t\tst.eat();\n\t\t\t\t}\n\n\t\t\t\tc.cond = parseExpr(st);\n\n\t\t\t\tif(auto x = parseBracedBlock(st); x.isError())\n\t\t\t\t\treturn PResult<Stmt>::copyError(x);\n\n\t\t\t\telse\n\t\t\t\t\tc.body = x.val();\n\n\t\t\t\tcases.push_back(c);\n\t\t\t}\n\t\t\telse if(st.frontAfterWS() == TT::LBrace || st.frontAfterWS() == TT::FatRightArrow)\n\t\t\t{\n\t\t\t\t// ok, parse an else\n\t\t\t\telseCase = parseBracedBlock(st).val();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// um.\n\t\t\t\texpectedAfter(st, \"'if' or '{'\", \"'else'\", st.frontAfterWS().str());\n\t\t\t}\n\t\t}\n\n\t\tif(isStaticIf)\n\t\t{\n\t\t\t// compile-time if\n\t\t\tauto ret = util::pool<IfDirective>(tok_if.loc);\n\t\t\tret->cases = cases;\n\t\t\tret->elseCase = elseCase;\n\n\t\t\tfor(auto& c : ret->cases)\n\t\t\t\tc.body->doNotPushNewScope = true;\n\n\t\t\tif(ret->elseCase)\n\t\t\t\tret->elseCase->doNotPushNewScope = true;\n\n\t\t\treturn ret;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// normal runtime if\n\t\t\tauto ret = util::pool<IfStmt>(tok_if.loc);\n\t\t\tret->cases = cases;\n\t\t\tret->elseCase = elseCase;\n\n\t\t\treturn ret;\n\t\t}\n\t}\n\n\tReturnStmt* parseReturn(State& st)\n\t{\n\t\ticeAssert(st.front() == TT::Return);\n\n\t\tauto ret = util::pool<ReturnStmt>(st.loc());\n\t\tst.eat();\n\n\t\t// check what's the next thing. problem: return has an *optional* value\n\t\t// solution: the value must not be separated by any whitespace or comment tokens\n\t\tif(st.front() != TT::Comment && st.front() != TT::NewLine && st.front() != TT::RBrace && st.front() != TT::EndOfFile)\n\t\t{\n\t\t\tret->value = parseExpr(st);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// do nothing\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\n\n\n\n\n\tStmt* parseForLoop(State& st)\n\t{\n\t\ticeAssert(st.front() == TT::For);\n\t\tst.eat();\n\n\t\tif(!zfu::match(st.front(), TT::Identifier, TT::LParen))\n\t\t\texpectedAfter(st.loc(), \"'(' or identifier\", \"'for'\", st.front().str());\n\n\t\tauto ret = util::pool<ForeachLoop>(st.ploc());\n\n\t\tif(st.front() == TT::LParen)\n\t\t{\n\t\t\tret->bindings = parseTupleDecomp(st);\n\t\t}\n\t\telse if(st.front() == TT::Ampersand || st.front() == TT::Identifier)\n\t\t{\n\t\t\tif(st.front() == TT::Ampersand)\n\t\t\t\tret->bindings.ref = true, st.pop();\n\n\t\t\tret->bindings.loc = st.loc();\n\t\t\tret->bindings.name = st.eat().str();\n\t\t}\n\t\telse\n\t\t{\n\t\t\texpectedAfter(st.loc(), \"one or more variable bindings\", \"'for'\", st.front().str());\n\t\t}\n\n\t\t// check for the comma for the index variable\n\t\tif(st.front() == TT::Comma)\n\t\t{\n\t\t\tst.pop();\n\t\t\tif(st.front() != TT::Identifier)\n\t\t\t\texpectedAfter(st.loc(), \"identifier for index binding\", \"',' in for loop\", st.front().str());\n\n\t\t\telse if(st.front().str() == \"_\")\n\t\t\t\terror(\"redundant use of '_' in binding for index variable in for loop; omit the binding entirely to ignore the index variable\");\n\n\t\t\tret->indexVar = st.eat().str();\n\t\t}\n\n\t\tif(st.front() != TT::Identifier || st.front().str() != \"in\")\n\t\t\texpected(st.loc(), \"'in' in for-loop\", st.front().str());\n\n\t\tst.eat();\n\n\t\t// get the array.\n\t\tret->array = parseExpr(st);\n\n\t\tst.skipWS();\n\t\tret->body = parseBracedBlock(st).val();\n\t\treturn ret;\n\t}\n\n\n\n\tPResult<WhileLoop> parseWhileLoop(State& st)\n\t{\n\t\t// 1. do { }\t\t\t-- body = block, cond = 0, doVariant = true\n\t\t// 2. while x { }\t\t-- body = block, cond = x, doVariant = false\n\t\t// 3. do { } while x\t-- body = block, cond = x, doVariant = true\n\n\t\tauto loc = st.loc();\n\n\t\tExpr* cond = 0;\n\t\tBlock* body = 0;\n\t\tbool isdo = false;\n\n\t\ticeAssert(st.front() == TT::While || st.front() == TT::Do);\n\n\t\tif(st.front() == TT::While)\n\t\t{\n\t\t\tst.eat();\n\t\t\tcond = parseExpr(st);\n\t\t\tst.skipWS();\n\n\t\t\tauto res = parseBracedBlock(st);\n\t\t\tif(res.isError())\n\t\t\t\treturn PResult<WhileLoop>::copyError(res);\n\n\t\t\tbody = res.val();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tisdo = true;\n\n\t\t\tst.eat();\n\n\t\t\tauto res = parseBracedBlock(st);\n\t\t\tif(res.isError())\n\t\t\t\treturn PResult<WhileLoop>::copyError(res);\n\n\t\t\tbody = res.val();\n\n\t\t\tif(st.front() == TT::While)\n\t\t\t{\n\t\t\t\tst.eat();\n\n\t\t\t\t// do a check for stupid \"do { } while { }\"\n\t\t\t\tif(st.frontAfterWS() == TT::LBrace)\n\t\t\t\t\texpected(st.frontAfterWS().loc, \"conditional expression after while\", st.frontAfterWS().str());\n\n\t\t\t\tcond = parseExpr(st);\n\t\t\t}\n\t\t}\n\n\t\tauto ret = util::pool<WhileLoop>(loc);\n\t\tret->isDoVariant = isdo;\n\t\tret->body = body;\n\t\tret->cond = cond;\n\n\t\treturn ret;\n\t}\n\n\n\tStmt* parseBreak(State& st)\n\t{\n\t\ticeAssert(st.front() == TT::Break);\n\t\treturn util::pool<BreakStmt>(st.eat().loc);\n\t}\n\n\tStmt* parseContinue(State& st)\n\t{\n\t\ticeAssert(st.front() == TT::Continue);\n\t\treturn util::pool<ContinueStmt>(st.eat().loc);\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/frontend/parser/expr.cpp",
    "content": "// expr.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"parser.h\"\n#include \"parser_internal.h\"\n\n#include \"memorypool.h\"\n\nusing namespace ast;\nusing namespace lexer;\n\n\n\nnamespace parser\n{\n\tusing TT = lexer::TokenType;\n\n\tPResult<Stmt> parseStmtWithAccessSpec(State& st)\n\t{\n\t\ticeAssert(st.front() == TT::Public || st.front() == TT::Private || st.front() == TT::Internal);\n\t\tauto vis = VisibilityLevel::Invalid;\n\t\tswitch(st.front())\n\t\t{\n\t\t\tcase TT::Public:\t\tvis = VisibilityLevel::Public; break;\n\t\t\tcase TT::Private:\t\tvis = VisibilityLevel::Private; break;\n\t\t\tcase TT::Internal:\t\tvis = VisibilityLevel::Internal; break;\n\t\t\tdefault: iceAssert(0);\n\t\t}\n\n\t\tst.pop();\n\t\treturn parseStmt(st, /* allowExprs: */ false).mutate([&](auto stmt) -> void {\n\t\t\tif(auto fd = dcast(FuncDefn, stmt))\n\t\t\t\tfd->visibility = vis;\n\n\t\t\telse if(auto ffd = dcast(ForeignFuncDefn, stmt))\n\t\t\t\tffd->visibility = vis;\n\n\t\t\telse if(auto vd = dcast(VarDefn, stmt))\n\t\t\t\tvd->visibility = vis;\n\n\t\t\telse if(auto td = dcast(TypeDefn, stmt))\n\t\t\t\ttd->visibility = vis;\n\n\t\t\telse\n\t\t\t\terror(st, \"access specifier cannot be applied to this statement\");\n\t\t});\n\t}\n\n\tPResult<Stmt> parseStmt(State& st, bool allowExprs)\n\t{\n\t\tif(!st.hasTokens())\n\t\t\treturn PResult<Stmt>::insufficientTokensError();\n\n\t\tst.skipWS();\n\n\t\tstd::function<PResult<Stmt> (bool, bool, bool)> checkMethodModifiers = [&st, &checkMethodModifiers]\n\t\t\t(bool mut, bool virt, bool ovrd) -> PResult<Stmt>\n\t\t{\n\t\t\tif(st.front() == TT::Mutable)\n\t\t\t{\n\t\t\t\tif(mut) error(st.loc(), \"duplicate 'mut' modifier\");\n\n\t\t\t\tst.eat();\n\t\t\t\treturn checkMethodModifiers(true, virt, ovrd);\n\t\t\t}\n\t\t\telse if(st.front() == TT::Virtual)\n\t\t\t{\n\t\t\t\tif(virt) error(st.loc(), \"duplicate 'virtual' modifier\");\n\t\t\t\tif(ovrd) error(st.loc(), \"'override' implies 'virtual', just use 'override'\");\n\n\t\t\t\tst.eat();\n\n\t\t\t\t//* but virtual does not imply override\n\t\t\t\treturn checkMethodModifiers(mut, true, ovrd);\n\t\t\t}\n\t\t\telse if(st.front() == TT::Override)\n\t\t\t{\n\t\t\t\tif(ovrd) error(st.loc(), \"duplicate 'override' modifier\");\n\t\t\t\tif(virt) error(st.loc(), \"'override' implies 'virtual', just use 'override'\");\n\n\t\t\t\tst.eat();\n\n\t\t\t\t//* override implies virtual\n\t\t\t\treturn checkMethodModifiers(mut, true, true);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn PResult(parseFunction(st)).mutate([&](auto ret) -> void {\n\t\t\t\t\tret->isVirtual = virt;\n\t\t\t\t\tret->isOverride = ovrd;\n\t\t\t\t\tret->isMutating = mut;\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\tauto tok = st.front();\n\t\tif(tok != TT::EndOfFile)\n\t\t{\n\t\t\tauto attrs = parseAttributes(st);\n\t\t\tauto enforceAttrs = [&attrs](const PResult<Stmt>& ret, const AttribSet& allowed = AttribSet::of(attr::NONE)) -> PResult<Stmt> {\n\n\t\t\t\tusing namespace attr;\n\n\t\t\t\treturn ret.map([&allowed, &attrs](auto ret) -> Stmt* {\n\t\t\t\t\t// there's probably a better way to do this, but bleugh\n\t\t\t\t\tif((attrs.flags & RAW) && !(allowed.flags & RAW))\n\t\t\t\t\t\terror(ret, \"unsupported attribute '@raw' on %s\", ret->readableName);\n\n\t\t\t\t\tif((attrs.flags & NO_MANGLE) && !(allowed.flags & NO_MANGLE))\n\t\t\t\t\t\terror(ret, \"unsupported attribute '@nomangle' on %s\", ret->readableName);\n\n\t\t\t\t\tif((attrs.flags & FN_ENTRYPOINT) && !(allowed.flags & FN_ENTRYPOINT))\n\t\t\t\t\t\terror(ret, \"unsupported attribute '@entry' on %s\", ret->readableName);\n\n\t\t\t\t\tif((attrs.flags & PACKED) && !(allowed.flags & PACKED))\n\t\t\t\t\t\terror(ret, \"unsupported attribute '@packed' on %s\", ret->readableName);\n\n\n\t\t\t\t\t// here let's check the arguments and stuff for default attributes.\n\t\t\t\t\t// note: due to poor API design on my part, if there is no attribute with that name then ::get()\n\t\t\t\t\t// returns an empty UA, which has a blank name -- so we check that instead.\n\n\t\t\t\t\tif(auto ua = attrs.get(\"compiler_support\"); !ua.name.empty() && ua.args.size() != 1)\n\t\t\t\t\t\terror(ret, \"@compiler_support requires exactly one argument\");\n\n\t\t\t\t\t// actually that's it\n\t\t\t\t\tret->attrs = attrs;\n\t\t\t\t\treturn ret;\n\t\t\t\t});\n\t\t\t};\n\n\t\t\t// handle the things that are OK to appear anywhere first:\n\t\t\ttok = st.front();\n\t\t\tswitch(tok.type)\n\t\t\t{\n\t\t\t\tcase TT::Var:   [[fallthrough]];\n\t\t\t\tcase TT::Val:\n\t\t\t\t\treturn enforceAttrs(parseVariable(st), AttribSet::of(attr::NO_MANGLE));\n\n\t\t\t\tcase TT::Func:\n\t\t\t\t\treturn enforceAttrs(parseFunction(st), AttribSet::of(attr::NO_MANGLE | attr::FN_ENTRYPOINT));\n\n\t\t\t\tcase TT::ForeignFunc:\n\t\t\t\t\treturn enforceAttrs(parseForeignFunction(st));\n\n\t\t\t\tcase TT::Public:    [[fallthrough]];\n\t\t\t\tcase TT::Private:   [[fallthrough]];\n\t\t\t\tcase TT::Internal:\n\t\t\t\t\treturn enforceAttrs(parseStmtWithAccessSpec(st));\n\n\t\t\t\tcase TT::Directive_If:\n\t\t\t\t\treturn enforceAttrs(parseIfStmt(st));\n\n\t\t\t\tcase TT::Directive_Run:\n\t\t\t\t\treturn enforceAttrs(parseRunDirective(st));\n\n\t\t\t\tcase TT::Union:\n\t\t\t\t\treturn enforceAttrs(parseUnion(st, attrs.has(attr::RAW), /* nameless: */ false), AttribSet::of(attr::RAW));\n\n\t\t\t\tcase TT::Struct:\n\t\t\t\t\treturn enforceAttrs(parseStruct(st, /* nameless: */ false), AttribSet::of(attr::PACKED));\n\n\t\t\t\tcase TT::Class:\n\t\t\t\t\treturn enforceAttrs(parseClass(st));\n\n\t\t\t\tcase TT::Enum:\n\t\t\t\t\treturn enforceAttrs(parseEnum(st));\n\n\t\t\t\tcase TT::Trait:\n\t\t\t\t\treturn enforceAttrs(parseTrait(st));\n\n\t\t\t\tcase TT::Static:\n\t\t\t\t\treturn enforceAttrs(parseStaticDecl(st));\n\n\t\t\t\tcase TT::Operator:\n\t\t\t\t\treturn enforceAttrs(parseOperatorOverload(st));\n\n\t\t\t\tcase TT::Using:\n\t\t\t\t\treturn enforceAttrs(parseUsingStmt(st));\n\n\t\t\t\tcase TT::Mutable:   [[fallthrough]];\n\t\t\t\tcase TT::Virtual:   [[fallthrough]];\n\t\t\t\tcase TT::Override:\n\t\t\t\t\treturn enforceAttrs(checkMethodModifiers(false, false, false), AttribSet::of(attr::NO_MANGLE));\n\n\t\t\t\tcase TT::Extension: [[fallthrough]];\n\t\t\t\tcase TT::TypeAlias:\n\t\t\t\t\terror(st, \"notsup\");\n\n\t\t\t\tcase TT::Else:\n\t\t\t\t\terror(st, \"cannot have 'else' without preceeding 'if'\");\n\n\t\t\t\tcase TT::Namespace:\n\t\t\t\t\terror(st, \"namespaces can only be defined at the top-level scope\");\n\n\t\t\t\tcase TT::Import:\n\t\t\t\t\terror(st, \"all imports must happen at the top-level scope\");\n\n\t\t\t\tcase TT::Attr_Operator:\n\t\t\t\t\terror(st, \"all operator declarations must happen at the top-level scope\");\n\n\t\t\t\tcase TT::Export:\n\t\t\t\t\terror(st, \"export declaration must be the first non-comment line in the file\");\n\n\t\t\t\tdefault:\n\t\t\t\t\t// do nothing.\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\t\t// if we got here, then it wasn't any of those things.\n\t\t\t// we store it first, so we can give better error messages (after knowing what it is)\n\t\t\t// in the event that it wasn't allowed at top-level.\n\n\n\t\t\tauto ret = [&st, &tok, &allowExprs]() -> PResult<Stmt> {\n\t\t\t\tswitch(tok.type)\n\t\t\t\t{\n\t\t\t\t\tcase TT::Return:\n\t\t\t\t\t\treturn parseReturn(st);\n\n\t\t\t\t\tcase TT::If:\n\t\t\t\t\t\treturn parseIfStmt(st);\n\n\t\t\t\t\tcase TT::Else:\n\t\t\t\t\t\terror(st, \"cannot have 'else' without preceeding 'if'\");\n\n\t\t\t\t\tcase TT::Do:    [[fallthrough]];\n\t\t\t\t\tcase TT::While:\n\t\t\t\t\t\treturn parseWhileLoop(st);\n\n\t\t\t\t\tcase TT::For:\n\t\t\t\t\t\treturn parseForLoop(st);\n\n\t\t\t\t\tcase TT::Break:\n\t\t\t\t\t\treturn parseBreak(st);\n\n\t\t\t\t\tcase TT::Continue:\n\t\t\t\t\t\treturn parseContinue(st);\n\n\t\t\t\t\tcase TT::Dealloc:\n\t\t\t\t\t\treturn parseDealloc(st);\n\n\t\t\t\t\tcase TT::Defer:\n\t\t\t\t\t\treturn parseDefer(st);\n\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tif(st.isInStructBody() && tok.type == TT::Identifier)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif(tok.str() == \"init\")\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn parseInitFunction(st);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if(tok.str() == \"deinit\")\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn parseDeinitFunction(st);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if(tok.str() == \"copy\" || tok.str() == \"move\")\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn parseCopyOrMoveInitFunction(st, tok.str());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// we want to error on invalid tokens first. so, we parse the expression regardless,\n\t\t\t\t\t\t// then if they're not allowed we error.\n\t\t\t\t\t\treturn PResult(parseExpr(st)).mutate([&](auto expr) -> void {\n\t\t\t\t\t\t\tif(!allowExprs)\n\t\t\t\t\t\t\t\terror(expr, \"expressions are not allowed at the top-level\");\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}();\n\n\t\t\treturn ret.mutate([&](auto ret) {\n\t\t\t\tif(!allowExprs && !st.isInFunctionBody() && !st.isInStructBody())\n\t\t\t\t\terror(ret, \"%s is not allowed at the top-level\", ret->readableName);\n\t\t\t});\n\t\t}\n\n\t\treturn PResult<Stmt>::insufficientTokensError();\n\t}\n\n\n\tstatic bool isRightAssociative(TT tt)\n\t{\n\t\treturn false;\n\t}\n\n\tstatic bool isPostfixUnaryOperator(State& st, const Token& tk)\n\t{\n\t\tbool res = (tk == TT::LParen) || (tk == TT::LSquare) || (tk == TT::DoublePlus) || (tk == TT::DoubleMinus);\n\n\t\tif(auto it = st.postfixOps.find(tk.str()); !res && it != st.postfixOps.end())\n\t\t{\n\t\t\ticeAssert(it->second.kind == CustomOperatorDecl::Kind::Postfix);\n\t\t\tres = true;\n\t\t}\n\n\t\treturn res;\n\t}\n\n\tstatic int unaryPrecedence(const std::string& op)\n\t{\n\t\tif(op == \"!\" || op == \"+\" || op == \"-\" || op == \"~\" || op == \"*\" || op == \"&\" || op == \"...\")\n\t\t\treturn 950;\n\n\t\treturn -1;\n\t}\n\n\tstatic int tok_precedence(State& st, TokenType t)\n\t{\n\t\tswitch(t)\n\t\t{\n\t\t\t/*\n\t\t\t\t! ACHTUNG !\n\t\t\t\t* DOCUMENT THIS SOMEWHERE PROPERLY!!! *\n\n\t\t\t\tdue to how we handle identifiers and scope paths (foo::bar), function calls must have higher precedence\n\t\t\t\tthan scope resolution.\n\n\t\t\t\tthis might seem counter-intuitive (i should be resolving the complete identifier first, then calling it with\n\t\t\t\t()! why would it be any other way???), this is a sad fact of how the typechecker works.\n\n\t\t\t\tas it stands, identifiers are units; paths consist of multiple identifiers in a DotOp with the :: operator, which\n\t\t\t\tis left-associative. so for something like foo::bar::qux, it's ((foo)::(bar))::qux.\n\n\t\t\t\tto resolve a function call, eg. foo::bar::qux(), the DotOp is laid out as [foo::bar]::[qux()] (with [] for grouping),\n\t\t\t\tinstead of the 'intuitive' [[foo::bar]::qux](). the reason for this design was the original rewrite goal of not\n\t\t\t\trelying on string manipulation in the compiler; having identifiers contain :: would have been counter to that\n\t\t\t\tgoal.\n\n\t\t\t\t(note: currently we are forced to manipulate ::s in the pts->fir type converter!!)\n\n\t\t\t\tthe current typechecker will thus first find a namespace 'foo', and within that a namespace 'bar', and within that\n\t\t\t\ta function 'qux'. this is opposed to finding a namespace 'foo', then 'bar', then an identifier 'qux', and leaving\n\t\t\t\tthat to be resolved later.\n\n\t\t\t\talso, another potential issue is how we deal with references to functions (ie. function pointers). our resolver\n\t\t\t\tfor ExprCall is strictly less advanced than that for a normal FunctionCall (for reasons i can't reCALL (lmao)), so\n\t\t\t\twe would prefer to return a FuncCall rather than an ExprCall.\n\n\n\t\t\t\tthis model could be re-architected without a *major* rewrite, but it would be a non-trivial task and a considerable amount\n\t\t\t\tof work and debugging. for reference:\n\n\t\t\t\t1.  make Idents be able to refer to entire paths; just a datastructure change\n\t\t\t\t2.  make :: have higher precedence than (), to take advantage of (1)\n\t\t\t\t3.  parse ExprCall and FuncCall identically -- they should both just be a NewCall, with an Expr as the callee\n\n\t\t\t\t4.  in typechecking a NewCall, just call ->typecheck() on the LHS; the current implementation of Ident::typecheck\n\t\t\t\t\treturns an sst::VarRef, which has an sst::VarDefn field which we can use.\n\n\t\t\t\t4a. if the Defn was a VarDefn, they cannot overload, and we can just do what we currently do for ExprCall.\n\t\t\t\t\tif it was a function defn, then things get more complicated.\n\n\t\t\t\t5.  the Defn was a FuncDefn. currently Ident cannot return more than one Defn in the event of ambiguous results (eg.\n\t\t\t\t\twhen overloading!), which means we are unable to properly do overload resolution! (duh) we need to make a mechanism\n\t\t\t\t\tfor Ident to return a list of Defns.\n\n\t\t\t\t\tpotential solution (A): make an sst::AmbiguousDefn struct that itself holds a list of Defns. the VarRef returned by\n\t\t\t\t\tIdent would then return that in the ->def field. this would only happen when the target is function; i presume we\n\t\t\t\t\thave existing mechanisms to detect invalid \"overload\" scenarios.\n\n\t\t\t\t\tback to (4), we should in theory be able to resolve functions from a list of defns.\n\n\n\t\t\t\tthe problem with this is that while it might seem like a simple 5.5-step plan, a lot of the supporting resolver functions\n\t\t\t\tneed to change, and effort is better spent elsewhere tbh\n\n\t\t\t\tfor now we just stick to parsing () at higher precedence than ::.\n\t\t\t*/\n\n\n\t\t\tcase TT::LParen:\n\t\t\t\treturn 9001;    // very funny\n\n\t\t\tcase TT::DoubleColon:\n\t\t\t\treturn 5000;\n\n\t\t\tcase TT::Period:\n\t\t\t\treturn 1500;\n\n\t\t\tcase TT::LSquare:\n\t\t\t\treturn 1000;\n\n\n\t\t\t// unary !\n\t\t\t// unary +/-\n\t\t\t// bitwise ~\n\t\t\t// unary &\n\t\t\t// unary *\n\t\t\t// unary ... (splat)\n\t\t\t// ^^ all have 950.\n\n\t\t\tcase TT::As:            [[fallthrough]];\n\t\t\tcase TT::Is:\n\t\t\t\treturn 900;\n\n\t\t\tcase TT::DoublePlus:    [[fallthrough]];\n\t\t\tcase TT::DoubleMinus:\n\t\t\t\treturn 850;\n\n\t\t\tcase TT::Asterisk:      [[fallthrough]];\n\t\t\tcase TT::Divide:        [[fallthrough]];\n\t\t\tcase TT::Percent:\n\t\t\t\treturn 800;\n\n\t\t\tcase TT::Plus:          [[fallthrough]];\n\t\t\tcase TT::Minus:\n\t\t\t\treturn 750;\n\n\t\t\t// << and >>\n\t\t\t// precedence = 700\n\n\n\t\t\tcase TT::Ampersand:\n\t\t\t\treturn 650;\n\n\t\t\tcase TT::Caret:\n\t\t\t\treturn 600;\n\n\t\t\tcase TT::Pipe:\n\t\t\t\treturn 550;\n\n\t\t\tcase TT::LAngle:        [[fallthrough]];\n\t\t\tcase TT::RAngle:        [[fallthrough]];\n\t\t\tcase TT::LessThanEquals:[[fallthrough]];\n\t\t\tcase TT::GreaterEquals: [[fallthrough]];\n\t\t\tcase TT::EqualsTo:      [[fallthrough]];\n\t\t\tcase TT::NotEquals:\n\t\t\t\treturn 500;\n\n\t\t\tcase TT::Ellipsis:      [[fallthrough]];\n\t\t\tcase TT::HalfOpenEllipsis:\n\t\t\t\treturn 475;\n\n\t\t\tcase TT::LogicalAnd:\n\t\t\t\treturn 400;\n\n\t\t\tcase TT::LogicalOr:\n\t\t\t\treturn 350;\n\n\t\t\tcase TT::Equal:         [[fallthrough]];\n\t\t\tcase TT::PlusEq:        [[fallthrough]];\n\t\t\tcase TT::MinusEq:       [[fallthrough]];\n\t\t\tcase TT::MultiplyEq:    [[fallthrough]];\n\t\t\tcase TT::DivideEq:      [[fallthrough]];\n\t\t\tcase TT::ModEq:         [[fallthrough]];\n\t\t\tcase TT::AmpersandEq:   [[fallthrough]];\n\t\t\tcase TT::PipeEq:        [[fallthrough]];\n\t\t\tcase TT::CaretEq:\n\t\t\t\treturn 100;\n\n\t\t\tdefault:\n\t\t\t\tif(auto it = st.binaryOps.find(st.front().str()); it != st.binaryOps.end())\n\t\t\t\t\treturn it->second.precedence;\n\n\t\t\t\telse if(it = st.postfixOps.find(st.front().str()); it != st.postfixOps.end())\n\t\t\t\t\treturn it->second.precedence;\n\n\t\t\t\treturn -1;\n\t\t}\n\t}\n\n\tstatic int precedence(State& st)\n\t{\n\t\tif(st.remaining() > 1 && (st.front() == TT::LAngle || st.front() == TT::RAngle))\n\t\t{\n\t\t\t// check if the next one matches.\n\t\t\tif(st.front().type == TT::LAngle && st.lookahead(1).type == TT::LAngle)\n\t\t\t\treturn 650;\n\n\t\t\telse if(st.front().type == TT::RAngle && st.lookahead(1).type == TT::RAngle)\n\t\t\t\treturn 650;\n\n\t\t\telse if(st.front().type == TT::LAngle && st.lookahead(1).type == TT::LessThanEquals)\n\t\t\t\treturn 100;\n\n\t\t\telse if(st.front().type == TT::RAngle && st.lookahead(1).type == TT::GreaterEquals)\n\t\t\t\treturn 100;\n\t\t}\n\n\t\treturn tok_precedence(st, st.front());\n\t}\n\n\n\tstatic Expr* parseUnary(State& st);\n\tstatic Expr* parsePrimary(State& st);\n\tstatic Expr* parsePostfixUnary(State& st, Expr* lhs, Token op);\n\n\tstatic Expr* parseRhs(State& st, Expr* lhs, int prio)\n\t{\n\t\tif(!st.hasTokens() || st.front() == TT::EndOfFile)\n\t\t\treturn lhs;\n\n\t\twhile(true)\n\t\t{\n\t\t\tint prec = precedence(st);\n\t\t\tif((prec < prio && !isRightAssociative(st.front())) || (st.front() == TT::As && st.isParsingUsing()))\n\t\t\t\treturn lhs;\n\n\t\t\t// we don't really need to check, because if it's botched we'll have returned due to -1 < everything\n\n\t\t\tif(auto tok_op = st.front(); isPostfixUnaryOperator(st, tok_op))\n\t\t\t{\n\t\t\t\tst.eat();\n\t\t\t\tlhs = parsePostfixUnary(st, dcast(Expr, lhs), tok_op);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tauto loc = st.loc();\n\t\t\tauto op = parseOperatorTokens(st);\n\t\t\tif(op.empty())\n\t\t\t\terror(loc, \"invalid operator '%s'\", st.prev().str());\n\n\n\n\t\t\tExpr* rhs = 0;\n\t\t\tif(op == Operator::TypeCast)\n\t\t\t{\n\t\t\t\tif(st.front() == TT::Mutable || (st.front() == TT::Exclamation && st.lookahead(1) == TT::Mutable))\n\t\t\t\t{\n\t\t\t\t\tif(st.front() == TT::Mutable)\n\t\t\t\t\t{\n\t\t\t\t\t\tst.pop();\n\t\t\t\t\t\trhs = util::pool<MutabilityTypeExpr>(loc, true);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tst.pop();\n\t\t\t\t\t\tst.pop();\n\t\t\t\t\t\trhs = util::pool<MutabilityTypeExpr>(loc, false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// rhs = util::pool<TypeExpr>(loc, parseType(st));\n\t\t\t\t\trhs = parseExpr(st);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(op == Operator::TypeIs)\n\t\t\t{\n\t\t\t\t// rhs = util::pool<TypeExpr>(loc, parseType(st));\n\t\t\t\trhs = parseExpr(st);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\trhs = parseUnary(st);\n\t\t\t}\n\n\t\t\tint next = precedence(st);\n\n\t\t\tif(next > prec || isRightAssociative(st.front()))\n\t\t\t\trhs = parseRhs(st, rhs, prec + 1);\n\n\n\t\t\tif(op == \".\" || op == \"::\")\n\t\t\t{\n\t\t\t\tloc.col = lhs->loc.col;\n\t\t\t\tloc.len = rhs->loc.col + rhs->loc.len - lhs->loc.col;\n\n\t\t\t\tauto dot = util::pool<DotOperator>(loc, dcast(Expr, lhs), rhs);\n\t\t\t\tdot->isStatic = (op == \"::\");\n\n\t\t\t\tlhs = dot;\n\t\t\t}\n\t\t\telse if(op == \"...\" || op == \"..<\")\n\t\t\t{\n\t\t\t\tExpr* start = lhs;\n\t\t\t\ticeAssert(start);\n\n\t\t\t\t// current token now starts the ending expression (ie. '...' or '..<' are no longer in the token stream)\n\t\t\t\tExpr* end = rhs;\n\t\t\t\tExpr* step = 0;\n\n\t\t\t\t// check if we got a step.\n\t\t\t\tif(st.front() == TT::Identifier && st.front().text == \"step\")\n\t\t\t\t{\n\t\t\t\t\tst.eat();\n\t\t\t\t\tstep = parseExpr(st);\n\t\t\t\t}\n\n\t\t\t\t// ok\n\t\t\t\tauto ret = util::pool<RangeExpr>(loc);\n\t\t\t\tret->start = start;\n\t\t\t\tret->end = end;\n\t\t\t\tret->halfOpen = (op == \"..<\");\n\t\t\t\tret->step = step;\n\n\t\t\t\tlhs = ret;\n\t\t\t}\n\t\t\telse if(Operator::isAssignment(op))\n\t\t\t{\n\t\t\t\tauto newlhs = util::pool<AssignOp>(loc);\n\n\t\t\t\tnewlhs->left = dcast(Expr, lhs);\n\t\t\t\tnewlhs->right = rhs;\n\t\t\t\tnewlhs->op = op;\n\n\t\t\t\tlhs = newlhs;\n\t\t\t}\n\t\t\telse if(Operator::isComparison(op))\n\t\t\t{\n\t\t\t\tif(auto cmp = dcast(ComparisonOp, lhs))\n\t\t\t\t{\n\t\t\t\t\tcmp->ops.push_back({ op, loc });\n\t\t\t\t\tcmp->exprs.push_back(rhs);\n\t\t\t\t\tlhs = cmp;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ticeAssert(lhs);\n\t\t\t\t\tauto newlhs = util::pool<ComparisonOp>(loc);\n\t\t\t\t\tnewlhs->exprs.push_back(lhs);\n\t\t\t\t\tnewlhs->exprs.push_back(rhs);\n\t\t\t\t\tnewlhs->ops.push_back({ op, loc });\n\n\t\t\t\t\tlhs = newlhs;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlhs = util::pool<BinaryOp>(loc, op, dcast(Expr, lhs), rhs);\n\t\t\t}\n\t\t}\n\t}\n\n\n\tExpr* parseCaretOrColonScopeExpr(State& st)\n\t{\n\t\ticeAssert(zfu::match(st.front(), TT::DoubleColon, TT::Caret));\n\n\t\tauto str = st.front().str();\n\t\tauto loc = st.loc();\n\n\t\tif(st.front() == TT::Caret)\n\t\t{\n\t\t\tst.eat();\n\t\t\tif(st.front() != TT::DoubleColon)\n\t\t\t\texpectedAfter(st.loc(), \"'::'\", \"'^' in scope-path-specifier\", st.front().str());\n\t\t}\n\n\t\t// ^::(^::((foo::bar)::qux))\n\n\t\tauto ident = util::pool<ast::Ident>(loc, str);\n\t\treturn parseRhs(st, ident, tok_precedence(st, TT::DoubleColon));\n\t}\n\n\n\tstatic Expr* parseTuple(State& st, Expr* lhs)\n\t{\n\t\ticeAssert(lhs);\n\n\t\tstd::vector<Expr*> values { lhs };\n\n\t\tToken t = st.front();\n\t\twhile(true)\n\t\t{\n\t\t\tvalues.push_back(parseExpr(st));\n\t\t\tif(st.front().type == TT::RParen)\n\t\t\t\tbreak;\n\n\t\t\tif(st.front().type != TT::Comma)\n\t\t\t\texpected(st, \"either ')' or ',' in tuple\", st.front().str());\n\n\t\t\tst.eat();\n\t\t\tt = st.front();\n\t\t}\n\n\t\t// leave the last rparen\n\t\ticeAssert(st.front().type == TT::RParen);\n\n\t\tLocation loc = lhs->loc;\n\t\tloc.col -= 1;\n\t\tloc.len = (st.front().loc.col - loc.col + 1);\n\t\treturn util::pool<LitTuple>(loc, values);\n\t}\n\n\tExpr* parseDollarExpr(State& st)\n\t{\n\t\tif(st.isInSubscript())\n\t\t{\n\t\t\treturn util::pool<SubscriptDollarOp>(st.pop().loc);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tunexpected(st.loc(), \"'$' in non-subscript context\");\n\t\t\treturn nullptr; // PRESULT FIXUP\n\t\t}\n\t}\n\n\n\tstatic Expr* parseParenthesised(State& st)\n\t{\n\t\tToken opening = st.eat();\n\t\ticeAssert(opening.type == TT::LParen);\n\n\t\tif(st.front() == TT::RParen)\n\t\t\terror(st.loc(), \"empty tuples are not supported\");\n\n\t\tExpr* within = parseExpr(st);\n\t\tst.skipWS();\n\n\t\tif(st.front().type != TT::Comma && st.front().type != TT::RParen)\n\t\t{\n\t\t\tSpanError::make(SimpleError::make(st.loc(), \"expected ',' to begin a tuple, or a closing ')'\"))->add(\n\t\t\t\tutil::ESpan(opening.loc, \"opening parenthesis was here\")\n\t\t\t)->append(BareError::make(MsgType::Note, \"named tuples are not supported\"))->postAndQuit();\n\t\t}\n\n\t\t// if we're a tuple, get ready for this shit.\n\t\tif(st.front().type == TT::Comma)\n\t\t{\n\t\t\t// remove the comma\n\t\t\tst.eat();\n\n\t\t\t// parse a tuple\n\t\t\tExpr* tup = parseTuple(st, within);\n\t\t\twithin = tup;\n\t\t}\n\n\t\ticeAssert(st.front().type == TT::RParen);\n\t\tst.eat();\n\n\t\treturn within;\n\t}\n\n\tstatic Expr* parseUnary(State& st)\n\t{\n\t\tauto tk = st.front();\n\n\t\t// check for unary shit\n\t\tstd::string op;\n\n\t\t//* note: we use the binary versions of the operator; since the unary AST and binary AST are separate,\n\t\t//* there's no confusion here. It also makes custom operators less troublesome to implement.\n\n\n\t\tif(tk.type == TT::Exclamation || tk.type == TT::Plus || tk.type == TT::Minus\n\t\t\t|| tk.type == TT::Tilde || tk.type == TT::Asterisk || tk.type == TT::Ampersand\n\t\t\t|| tk.type == TT::Ellipsis)\n\t\t{\n\t\t\top = tk.str();\n\t\t}\n\n\n\t\tint prec = -1;\n\t\tif(auto it = st.prefixOps.find(tk.str()); op.empty() && it != st.prefixOps.end())\n\t\t{\n\t\t\t// great.\n\t\t\tauto cop = it->second;\n\t\t\ticeAssert(cop.kind == CustomOperatorDecl::Kind::Prefix);\n\n\t\t\tprec = cop.precedence;\n\t\t\top = cop.symbol;\n\n\t\t\t// debuglog(\"symbol = '%s'\\n\", op);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tprec = unaryPrecedence(op);\n\t\t}\n\n\n\t\tif(op == \"...\")\n\t\t{\n\t\t\tst.eat();\n\n\t\t\tExpr* e = parseUnary(st);\n\n\t\t\tauto ret = util::pool<SplatOp>(tk.loc);\n\t\t\tret->expr = e;\n\n\t\t\treturn ret;\n\t\t}\n\t\telse if(!op.empty())\n\t\t{\n\t\t\tst.eat();\n\n\t\t\tExpr* un = parseUnary(st);\n\t\t\tExpr* thing = parseRhs(st, un, prec);\n\n\t\t\tauto ret = util::pool<UnaryOp>(tk.loc);\n\n\t\t\tret->expr = thing;\n\t\t\tret->op = op;\n\n\t\t\treturn ret;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn parsePrimary(st);\n\t\t}\n\t}\n\n\n\tstd::vector<std::pair<std::string, Expr*>> parseCallArgumentList(State& st)\n\t{\n\t\tstd::unordered_set<std::string> seenNames;\n\t\tstd::vector<std::pair<std::string, Expr*>> ret;\n\n\t\twhile(st.front() != TT::RParen)\n\t\t{\n\t\t\tstd::string argname;\n\n\t\t\tauto ex = parseExpr(st);\n\t\t\tif(auto id = dcast(Ident, ex); id && st.front() == TT::Colon)\n\t\t\t{\n\t\t\t\targname = id->name;\n\t\t\t\tif(seenNames.find(argname) != seenNames.end())\n\t\t\t\t\terror(id->loc, \"argument '%s' was already provided\", argname);\n\n\t\t\t\tseenNames.insert(argname);\n\n\t\t\t\t// eat the colon, get the actual argument.\n\t\t\t\tst.eat();\n\t\t\t\tex = parseExpr(st);\n\t\t\t}\n\n\t\t\tret.push_back({ argname, ex });\n\t\t\tst.skipWS();\n\n\t\t\tif(st.front() == TT::Comma)\n\t\t\t\tst.pop();\n\n\t\t\telse if(st.front() != TT::RParen)\n\t\t\t\texpected(st, \"',' or ')' in function call argument list\", st.front().str());\n\t\t}\n\n\t\ticeAssert(st.front().type == TT::RParen);\n\t\tst.pop();\n\n\t\treturn ret;\n\t}\n\n\tstatic FunctionCall* parseFunctionCall(State& st, const Location& loc, const std::string& name)\n\t{\n\t\tauto ret = util::pool<FunctionCall>(loc, name);\n\n\t\tst.skipWS();\n\t\tret->args = parseCallArgumentList(st);\n\n\t\treturn ret;\n\t}\n\n\n\tstatic Expr* parseCall(State& st, Expr* lhs, Token op)\n\t{\n\t\tif(Ident* id = dcast(Ident, lhs))\n\t\t{\n\t\t\tauto ret = parseFunctionCall(st, id->loc, id->name);\n\t\t\tret->mappings = id->mappings;\n\n\t\t\treturn ret;\n\t\t}\n\n\t\tauto ret = util::pool<ExprCall>(op.loc);\n\t\ticeAssert(op == TT::LParen);\n\n\t\tret->args = parseCallArgumentList(st);\n\t\tret->callee = lhs;\n\n\t\treturn ret;\n\t}\n\n\n\tstatic Expr* parseIdentifier(State& st)\n\t{\n\t\ticeAssert(zfu::match(st.front(), TT::Identifier, TT::UnicodeSymbol));\n\t\tstd::string name = st.pop().str();\n\n\t\tauto ident = util::pool<Ident>(st.ploc(), name);\n\n\t\t//* we've modified our generic thing to be Foo!<...>, so there shouldn't\n\t\t//* be any ambiguity left. once we see '!' and '<' we know for sure.\n\t\t//? as long as we don't make '!' a postfix operator...\n\t\t//? for now, we'll leave in the try-and-restore mechanism.\n\t\tif(st.front() == TT::Exclamation && st.lookahead(1) == TT::LAngle)\n\t\t{\n\t\t\tbool fail = false;\n\t\t\tauto restore = st.getIndex();\n\n\t\t\tauto pams = parsePAMs(st, &fail);\n\t\t\tif(fail)\n\t\t\t{\n\t\t\t\tst.rewindTo(restore);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tident->mappings = pams;\n\t\t\t\tident->loc.len += (st.ploc().col - st.getTokenList()[restore].loc.col) + 1;\n\t\t\t}\n\t\t}\n\n\t\treturn ident;\n\t}\n\n\n\n\tstatic Expr* parsePostfixUnary(State& st, Expr* lhs, Token op)\n\t{\n\t\tif(op.type == TT::LParen)\n\t\t{\n\t\t\treturn parseCall(st, lhs, op);\n\t\t}\n\t\telse if(op.type == TT::LSquare)\n\t\t{\n\t\t\tst.enterSubscript();\n\t\t\tdefer(st.leaveSubscript());\n\n\t\t\t// if we're a colon immediately, then it's a slice expr already.\n\t\t\t// either [:x] or [:]\n\t\t\tExpr* slcbegin = 0;\n\t\t\tExpr* slcend = 0;\n\n\t\t\tbool isSlice = false;\n\n\t\t\tif(st.front().type == TT::Colon)\n\t\t\t{\n\t\t\t\tst.eat();\n\t\t\t\tisSlice = true;\n\n\t\t\t\tif(st.front().type == TT::RSquare)\n\t\t\t\t{\n\t\t\t\t\tst.eat();\n\n\t\t\t\t\t// just return here.\n\t\t\t\t\tauto ret = util::pool<SliceOp>(op.loc);\n\t\t\t\t\tret->expr = lhs;\n\t\t\t\t\tret->start = 0;\n\t\t\t\t\tret->end = 0;\n\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// parse the inside expression\n\t\t\tExpr* inside = parseExpr(st);\n\n\t\t\tif(!isSlice && st.front().type == TT::RSquare)\n\t\t\t{\n\t\t\t\tauto end = st.eat().loc;\n\t\t\t\ticeAssert(inside);\n\n\t\t\t\tauto ret = util::pool<SubscriptOp>(op.loc);\n\t\t\t\tret->expr = lhs;\n\t\t\t\tret->inside = inside;\n\n\t\t\t\t// custom thingy\n\t\t\t\tret->loc.col = lhs->loc.col;\n\t\t\t\tret->loc.len = end.col - ret->loc.col + 1;\n\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t\telse if(isSlice && st.front().type == TT::RSquare)\n\t\t\t{\n\t\t\t\tst.eat();\n\n\t\t\t\t// x[:N]\n\t\t\t\tslcbegin = 0;\n\t\t\t\tslcend = inside;\n\n\t\t\t\tauto ret = util::pool<SliceOp>(op.loc);\n\t\t\t\tret->expr = lhs;\n\t\t\t\tret->start = slcbegin;\n\t\t\t\tret->end = slcend;\n\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t\telse if(st.front().type == TT::Colon)\n\t\t\t{\n\t\t\t\tst.eat();\n\t\t\t\t// x[N:M]\n\t\t\t\tslcbegin = inside;\n\n\t\t\t\tif(st.front() != TT::RSquare)\n\t\t\t\t\tslcend = parseExpr(st);\n\n\t\t\t\t//* note: looks duplicated and wrong, but rest assured it's fine. if we get arr[x:], that's valid.\n\t\t\t\tif(st.front() != TT::RSquare)\n\t\t\t\t\texpectedAfter(st.loc(), \"']'\", \"expression for slice operation\", st.front().str());\n\n\t\t\t\tst.eat();\n\n\t\t\t\tauto ret = util::pool<SliceOp>(op.loc);\n\t\t\t\tret->expr = lhs;\n\t\t\t\tret->start = slcbegin;\n\t\t\t\tret->end = slcend;\n\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\texpectedAfter(st.loc(), \"']'\", \"'[' for array subscript\", st.front().str());\n\t\t\t}\n\t\t}\n\t\telse if(auto it = st.postfixOps.find(op.str()); it != st.postfixOps.end())\n\t\t{\n\t\t\t// yay...?\n\t\t\t//* note: custom postfix ops are handled internally in the AST as normal unary ops.\n\t\t\tauto ret = util::pool<UnaryOp>(op.loc);\n\n\t\t\tret->expr = lhs;\n\t\t\tret->op = op.str();\n\t\t\tret->isPostfix = true;\n\n\t\t\treturn ret;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// todo: ++ and --.\n\t\t\terror(\"enotsup\");\n\t\t}\n\n\t\treturn nullptr; // PRESULT FIXUP\n\t}\n\n\n\tstatic Expr* parseAlloc(State& st, bool raw)\n\t{\n\t\ticeAssert(st.front() == TT::Alloc);\n\t\tauto loc = st.eat().loc;\n\n\t\tauto ret = util::pool<AllocOp>(loc);\n\n\t\tif(st.front() == TT::Mutable)\n\t\t\tret->isMutable = true, st.pop();\n\n\t\tif(raw)\n\t\t\tret->attrs.set(attr::RAW);\n\n\t\tret->allocTy = parseType(st);\n\n\t\tif(st.front() == TT::LParen)\n\t\t{\n\t\t\tauto leftloc = st.loc();\n\n\t\t\tst.pop();\n\t\t\tret->args = parseCallArgumentList(st);\n\n\t\t\tif(ret->args.empty())\n\t\t\t{\n\t\t\t\t// parseCallArgumentList consumes the closing )\n\t\t\t\tauto tmp = Location::unionOf(leftloc, st.ploc());\n\t\t\t\tinfo(tmp, \"empty argument list in alloc expression () can be omitted\");\n\t\t\t}\n\t\t}\n\n\n\t\tif(st.front() == TT::LSquare)\n\t\t{\n\t\t\tst.eat();\n\t\t\twhile(st.front() != TT::RSquare)\n\t\t\t{\n\t\t\t\tret->counts.push_back(parseExpr(st));\n\t\t\t\tif(st.front() == TT::Comma)\n\t\t\t\t\tst.eat();\n\n\t\t\t\telse if(st.front() != TT::RSquare)\n\t\t\t\t\texpected(st.loc(), \"',' or ')' in dimension list for alloc expression\", st.front().str());\n\t\t\t}\n\n\t\t\tif(st.eat() != TT::RSquare)\n\t\t\t\texpectedAfter(st.ploc(), \"']'\", \"'alloc(...)'\", st.prev().str());\n\n\t\t\tif(ret->counts.empty())\n\t\t\t\terror(st.ploc(), \"dimension list in 'alloc' cannot be empty\");\n\t\t}\n\n\t\tif(st.front() == TT::LBrace)\n\t\t{\n\t\t\tif(raw) error(st.loc(), \"initialisation body cannot be used with raw array allocations\");\n\n\t\t\t// ok, get it\n\t\t\tret->initBody = parseBracedBlock(st).val();\n\t\t}\n\n\n\t\treturn ret;\n\t}\n\n\tDeallocOp* parseDealloc(State& st)\n\t{\n\t\ticeAssert(st.front() == TT::Dealloc);\n\t\tauto loc = st.eat().loc;\n\n\t\tauto ret = util::pool<DeallocOp>(loc);\n\t\tret->expr = parseExpr(st);\n\n\t\treturn ret;\n\t}\n\n\tDeferredStmt* parseDefer(State& st)\n\t{\n\t\ticeAssert(st.front() == TT::Defer);\n\t\tauto ret = util::pool<DeferredStmt>(st.eat().loc);\n\n\t\tif(st.front() == TT::LBrace)\n\t\t\tret->actual = parseBracedBlock(st).val();\n\n\t\telse\n\t\t\tret->actual = parseStmt(st).val();\n\n\t\treturn ret;\n\t}\n\n\tSizeofOp* parseSizeof(State& st)\n\t{\n\t\tToken tok = st.eat();\n\t\ticeAssert(tok == TT::Sizeof);\n\n\t\tif(st.eat() != TT::LParen)\n\t\t\texpectedAfter(st.ploc(), \"'('\", \"sizeof\", st.prev().str());\n\n\t\tauto ret = util::pool<SizeofOp>(tok.loc);\n\t\tret->expr = parseExpr(st);\n\n\t\tif(st.eat() != TT::RParen)\n\t\t\texpectedAfter(st.ploc(), \"')'\", \"expression in sizeof\", st.prev().str());\n\n\t\treturn ret;\n\t}\n\n\n\tTypeidOp* parseTypeid(State& st)\n\t{\n\t\tToken tok = st.eat();\n\t\ticeAssert(tok == TT::Typeid);\n\n\t\tif(st.eat() != TT::LParen)\n\t\t\texpectedAfter(st.ploc(), \"'('\", \"typeid\", st.prev().str());\n\n\t\tauto ret = util::pool<TypeidOp>(tok.loc);\n\t\tret->expr = parseExpr(st);\n\n\t\tif(st.eat() != TT::RParen)\n\t\t\texpectedAfter(st.ploc(), \"')'\", \"expression in typeid\", st.prev().str());\n\n\t\treturn ret;\n\t}\n\n\n\tExpr* parseExpr(State& st)\n\t{\n\t\tExpr* lhs = parseUnary(st);\n\t\ticeAssert(lhs);\n\n\t\treturn parseRhs(st, lhs, 0);\n\t}\n\n\n\n\n\n\n\tstatic Expr* parsePrimary(State& st)\n\t{\n\t\tif(!st.hasTokens())\n\t\t\tunexpected(st, \"end of file\");\n\n\t\tst.skipWS();\n\n\t\tauto tok = st.front();\n\t\tif(tok != TT::EndOfFile)\n\t\t{\n\t\t\tswitch(tok.type)\n\t\t\t{\n\t\t\t\tcase TT::Var:\n\t\t\t\tcase TT::Val:\n\t\t\t\tcase TT::Func:\n\t\t\t\tcase TT::Enum:\n\t\t\t\tcase TT::Class:\n\t\t\t\tcase TT::Using:\n\t\t\t\tcase TT::Union:\n\t\t\t\tcase TT::Static:\n\t\t\t\tcase TT::Struct:\n\t\t\t\tcase TT::Public:\n\t\t\t\tcase TT::Private:\n\t\t\t\tcase TT::Operator:\n\t\t\t\tcase TT::Trait:\n\t\t\t\tcase TT::Internal:\n\t\t\t\tcase TT::Override:\n\t\t\t\tcase TT::Extension:\n\t\t\t\tcase TT::Namespace:\n\t\t\t\tcase TT::TypeAlias:\n\t\t\t\tcase TT::ForeignFunc:\n\t\t\t\t\terror(st, \"declarations are not expressions (%s)\", tok.str());\n\n\t\t\t\tcase TT::Dealloc:\n\t\t\t\t\terror(st, \"deallocation statements are not expressions\");\n\n\t\t\t\tcase TT::Defer:\n\t\t\t\t\terror(st, \"defer statements are not expressions\");\n\n\t\t\t\tcase TT::Return:\n\t\t\t\t\terror(st, \"return statements are not expressions\");\n\n\t\t\t\tcase TT::Break:\n\t\t\t\t\terror(st, \"break statements are not expressions\");\n\n\t\t\t\tcase TT::Continue:\n\t\t\t\t\terror(st, \"continue statements are not expressions\");\n\n\t\t\t\tcase TT::If:\n\t\t\t\t\terror(st, \"if statements are not expressions\");\n\n\t\t\t\tcase TT::Do:\n\t\t\t\tcase TT::While:\n\t\t\t\tcase TT::For:\n\t\t\t\t\terror(st, \"loops are not expressions\");\n\n\n\n\n\n\t\t\t\tcase TT::Dollar:\n\t\t\t\t\treturn parseDollarExpr(st);\n\n\t\t\t\tcase TT::LParen:\n\t\t\t\t\treturn parseParenthesised(st);\n\n\t\t\t\tcase TT::Identifier:\n\t\t\t\tcase TT::UnicodeSymbol:\n\t\t\t\t\treturn parseIdentifier(st);\n\n\t\t\t\tcase TT::Caret:\n\t\t\t\tcase TT::DoubleColon:\n\t\t\t\t\treturn parseCaretOrColonScopeExpr(st);\n\n\t\t\t\tcase TT::Alloc:\n\t\t\t\t\treturn parseAlloc(st, false);\n\n\t\t\t\t// case TT::Typeof:\n\t\t\t\t// \treturn parseTypeof(ps);\n\n\t\t\t\tcase TT::Typeid:\n\t\t\t\t\treturn parseTypeid(st);\n\n\t\t\t\tcase TT::Sizeof:\n\t\t\t\t\treturn parseSizeof(st);\n\n\t\t\t\tcase TT::Attr_Raw:\n\t\t\t\t\tst.pop();\n\t\t\t\t\tif(st.front() == TT::StringLiteral)\n\t\t\t\t\t\treturn parseString(st, /* isRaw: */ true);\n\n\t\t\t\t\telse if(st.front() == TT::LSquare)\n\t\t\t\t\t\treturn parseArray(st, /* isRaw: */ true);\n\n\t\t\t\t\telse if(st.front() == TT::Alloc)\n\t\t\t\t\t\treturn parseAlloc(st, /* isRaw: */ true);\n\n\t\t\t\t\telse\n\t\t\t\t\t\texpectedAfter(st, \"one of string-literal, array, or alloc\", \"'@raw' while parsing expression\", st.front().str());\n\n\t\t\t\tcase TT::StringLiteral:\n\t\t\t\t\treturn parseString(st, false);\n\n\t\t\t\tcase TT::Number:\n\t\t\t\t\treturn parseNumber(st);\n\n\t\t\t\tcase TT::LSquare:\n\t\t\t\t\treturn parseArray(st, /* isRaw: */ false);\n\n\t\t\t\tcase TT::CharacterLiteral:\n\t\t\t\t\tst.pop();\n\t\t\t\t\treturn util::pool<LitChar>(tok.loc, static_cast<uint32_t>(tok.text[0]));\n\n\t\t\t\t// no point creating separate functions for these\n\t\t\t\tcase TT::True:\n\t\t\t\t\tst.pop();\n\t\t\t\t\treturn util::pool<LitBool>(tok.loc, true);\n\n\t\t\t\tcase TT::False:\n\t\t\t\t\tst.pop();\n\t\t\t\t\treturn util::pool<LitBool>(tok.loc, false);\n\n\t\t\t\t// nor for this\n\t\t\t\tcase TT::Null:\n\t\t\t\t\tst.pop();\n\t\t\t\t\treturn util::pool<LitNull>(tok.loc);\n\n\t\t\t\tcase TT::Directive_Run:\n\t\t\t\t\treturn parseRunDirective(st);\n\n\t\t\t\tcase TT::LBrace:\n\t\t\t\t\tunexpected(st, \"block; to create a nested scope, use 'do { ... }'\");\n\n\t\t\t\tdefault:\n\t\t\t\t\terror(tok.loc, \"unexpected token '%s' (id = %d)\", tok.str(), tok.type);\n\t\t\t}\n\t\t}\n\n\t\treturn 0;\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/frontend/parser/function.cpp",
    "content": "// function.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"defs.h\"\n#include \"pts.h\"\n#include \"parser_internal.h\"\n\n#include \"memorypool.h\"\n\nusing namespace ast;\nusing namespace lexer;\n\nusing TT = lexer::TokenType;\nnamespace parser\n{\n\tstd::tuple<std::vector<FuncDefn::Param>, std::vector<std::pair<std::string, TypeConstraints_t>>, pts::Type*, bool, Location>\n\tparseFunctionLookingDecl(State& st)\n\t{\n\t\tpts::Type* returnType = 0;\n\t\tstd::vector<FuncDefn::Param> params;\n\t\tstd::vector<std::pair<std::string, TypeConstraints_t>> generics;\n\n\t\t// check for generic function\n\t\tif(st.front() == TT::LAngle)\n\t\t{\n\t\t\tst.eat();\n\t\t\t// parse generic\n\t\t\tif(st.front() == TT::RAngle)\n\t\t\t\terror(st, \"empty type parameter lists are not allowed\");\n\n\t\t\tgenerics = parseGenericTypeList(st);\n\t\t}\n\n\t\tif(st.front() != TT::LParen)\n\t\t\texpectedAfter(st, \"'('\", \"function declaration to begin argument list\", st.front().str());\n\n\t\tst.eat();\n\t\tLocation varloc;\n\n\t\tbool isfvar = false;    // flax-variadic\n\t\tbool iscvar = false;    // c-variadic\n\t\tbool startedOptional = false;\n\t\twhile(st.front() != TT::RParen)\n\t\t{\n\t\t\tst.skipWS();\n\n\t\t\tif(iscvar || isfvar)\n\t\t\t\terror(st, \"variadic parameter list must be the last function parameter\");\n\n\t\t\tif(st.front() == TT::Ellipsis)\n\t\t\t{\n\t\t\t\tiscvar = true;\n\t\t\t\tvarloc = st.loc();\n\t\t\t\tst.pop();\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif(st.front() != TT::Identifier)\n\t\t\t\texpected(st, \"identifier in function parameter list\", st.front().str());\n\n\t\t\tstd::string name = st.front().str();\n\t\t\tauto loc = st.loc();\n\n\t\t\tst.eat();\n\n\t\t\tif(st.front() != TT::Colon)\n\t\t\t\texpected(st, \"':' after identifier to specify type\", st.front().str());\n\n\t\t\tst.eat();\n\t\t\tauto type = parseType(st);\n\t\t\tif(type->isVariadicArrayType())\n\t\t\t\tisfvar = true;\n\n\t\t\tExpr* defaultVal = 0;\n\t\t\tif(st.front() == TT::Equal)\n\t\t\t{\n\t\t\t\tif(type->isVariadicArrayType())\n\t\t\t\t\terror(st, \"variadic parameter list cannot have a default value\");\n\n\t\t\t\tst.pop();\n\t\t\t\tstartedOptional = true;\n\t\t\t\tdefaultVal = parseExpr(st);\n\t\t\t}\n\t\t\t// we can have a variadic list after optional arguments\n\t\t\telse if(startedOptional && !isfvar)\n\t\t\t{\n\t\t\t\terror(loc, \"mandatory arguments must be declared before any optional arguments\");\n\t\t\t}\n\n\t\t\tparams.push_back(FuncDefn::Param { name, loc, type, defaultVal });\n\n\t\t\tif(st.front() == TT::Comma)\n\t\t\t\tst.eat();\n\n\t\t\telse if(st.front() != TT::RParen)\n\t\t\t\texpected(st, \"')' or ',' in function parameter list\", st.front().str());\n\n\t\t\tst.skipWS();\n\t\t}\n\n\t\ticeAssert(st.front() == TT::RParen);\n\t\tst.eat();\n\n\t\tif(st.front() == TT::RightArrow)\n\t\t{\n\t\t\tst.eat();\n\t\t\treturnType = parseType(st);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturnType = 0;\n\t\t}\n\n\t\treturn std::make_tuple(params, generics, returnType, iscvar, varloc);\n\t}\n\n\n\tstd::tuple<FuncDefn*, bool, Location> parseFunctionDecl(State& st)\n\t{\n\t\ticeAssert(st.front() == TT::Func);\n\t\tst.eat();\n\n\t\tif(st.front() != TT::Identifier)\n\t\t\texpectedAfter(st, \"identifier\", \"'fn'\", st.front().str());\n\n\t\tFuncDefn* defn = util::pool<FuncDefn>(st.loc());\n\t\tdefn->name = st.eat().str();\n\n\t\tLocation loc;\n\t\tbool isvar = false;\n\t\tstd::tie(defn->params, defn->generics, defn->returnType, isvar, loc) = parseFunctionLookingDecl(st);\n\n\t\tif(defn->returnType == 0)\n\t\t\tdefn->returnType = pts::NamedType::create(defn->loc, VOID_TYPE_STRING);\n\n\t\treturn std::make_tuple(defn, isvar, loc);\n\t}\n\n\n\n\n\tPResult<FuncDefn> parseFunction(State& st)\n\t{\n\t\tauto [ defn, isvar, varloc ] = parseFunctionDecl(st);\n\t\tif(isvar)\n\t\t\terror(varloc, \"C-style variadic arguments are not supported on non-foreign functions\");\n\n\t\tst.skipWS();\n\t\tif(st.front() != TT::LBrace && st.front() != TT::FatRightArrow)\n\t\t\texpected(st, \"'{' to begin function body\", st.front().str());\n\n\t\tst.enterFunctionBody();\n\t\t{\n\t\t\tauto body = parseBracedBlock(st);\n\n\t\t\tif(body.hasValue()) defn->body = body.val();\n\t\t\telse                return PResult<FuncDefn>::copyError(body);\n\t\t}\n\t\tst.leaveFunctionBody();\n\n\t\treturn defn;\n\t}\n\n\n\n\n\n\tForeignFuncDefn* parseForeignFunction(State& st)\n\t{\n\t\ticeAssert(st.front() == TT::ForeignFunc);\n\t\tst.pop();\n\t\tst.skipWS();\n\n\t\tif(st.front() != TT::Func)\n\t\t\texpectedAfter(st, \"'fn'\", \"'ffi'\", st.front().str());\n\n\t\tauto ffn = util::pool<ForeignFuncDefn>(st.loc());\n\n\t\t// copy the things over\n\t\tauto [ defn, isvar, varloc ] = parseFunctionDecl(st);\n\t\t(void) varloc;\n\n\t\tif(!defn->generics.empty())\n\t\t\terror(ffn->loc, \"foreign functions cannot be generic\");\n\n\t\tffn->loc = defn->loc;\n\t\tffn->isVarArg = isvar;\n\t\tffn->name = defn->name;\n\t\tffn->params = defn->params;\n\t\tffn->visibility = defn->visibility;\n\t\tffn->returnType = defn->returnType;\n\n\t\t// make sure we don't have optional arguments here\n\t\tzfu::foreach(ffn->params, [](const auto& a) {\n\t\t\tif(a.defaultValue)\n\t\t\t\terror(a.loc, \"foreign functions cannot have optional arguments\");\n\t\t});\n\n\t\t// check for 'as'\n\t\tif(st.front() == TT::As)\n\t\t{\n\t\t\tst.pop();\n\t\t\tif(st.front() != TT::StringLiteral)\n\t\t\t\texpectedAfter(st.loc(), \"string literal\", \"'as' in foreign function declaration\", st.front().str());\n\n\t\t\tffn->realName = parseStringEscapes(st.loc(), st.eat().str());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tffn->realName = ffn->name;\n\t\t}\n\n\t\treturn ffn;\n\t}\n\n\n\tInitFunctionDefn* parseInitFunction(State& st)\n\t{\n\t\tToken tok = st.pop();\n\t\ticeAssert(tok.str() == \"init\");\n\n\t\tauto [ params, generics, retty, isvar, varloc ] = parseFunctionLookingDecl(st);\n\t\tif(generics.size() > 0)\n\t\t\terror(st.ploc(), \"class initialiser functions cannot be generic\");\n\n\t\telse if(retty != 0)\n\t\t\terror(st.ploc(), \"class initialisers cannot have a return type\");\n\n\t\telse if(isvar)\n\t\t\terror(varloc, \"C-style variadic arguments are not supported on non-foreign functions\");\n\n\t\t// ok loh\n\t\tauto ret = util::pool<InitFunctionDefn>(tok.loc);\n\t\tret->name = \"init\";\n\t\tret->params = params;\n\n\t\t// check for super-class args.\n\t\tif(st.front() == TT::Colon)\n\t\t{\n\t\t\tst.eat();\n\t\t\tif(st.eat().str() != \"super\")\n\t\t\t\texpectedAfter(st.ploc(), \"'super'\", \"':' in init function definition\", st.prev().str());\n\n\t\t\tif(st.eat() != TT::LParen)\n\t\t\t\texpectedAfter(st.ploc(), \"'('\", \"'super' in call to base-class initialiser\", st.prev().str());\n\n\t\t\tret->superArgs = parseCallArgumentList(st);\n\t\t\tret->didCallSuper = true;\n\t\t}\n\n\t\tst.enterFunctionBody();\n\t\t{\n\t\t\tret->body = parseBracedBlock(st).val();\n\t\t}\n\t\tst.leaveFunctionBody();\n\n\t\treturn ret;\n\t}\n\n\n\tInitFunctionDefn* parseCopyOrMoveInitFunction(State& st, const std::string& name)\n\t{\n\t\tToken tok = st.pop();\n\t\ticeAssert(tok.str() == name);\n\n\t\tauto [ params, generics, retty, isvar, varloc ] = parseFunctionLookingDecl(st);\n\t\tif(generics.size() > 0)\n\t\t\terror(st.ploc(), \"class initialiser functions cannot be generic\");\n\n\t\telse if(retty != 0)\n\t\t\terror(st.ploc(), \"class initialisers cannot have a return type\");\n\n\t\telse if(isvar)\n\t\t\terror(varloc, \"C-style variadic arguments are not supported on non-foreign functions\");\n\n\t\t// ok loh\n\t\tauto ret = util::pool<InitFunctionDefn>(tok.loc);\n\t\tret->name = name;\n\t\tret->params = params;\n\n\t\tst.enterFunctionBody();\n\t\t{\n\t\t\tret->body = parseBracedBlock(st).val();\n\t\t}\n\t\tst.leaveFunctionBody();\n\n\t\treturn ret;\n\t}\n\n\n\tInitFunctionDefn* parseDeinitFunction(State& st)\n\t{\n\t\tToken tok = st.pop();\n\t\ticeAssert(tok.str() == \"deinit\");\n\n\t\tauto ret = util::pool<InitFunctionDefn>(tok.loc);\n\t\tret->name = \"deinit\";\n\n\t\tst.enterFunctionBody();\n\t\t{\n\t\t\tret->body = parseBracedBlock(st).val();\n\t\t}\n\t\tst.leaveFunctionBody();\n\n\t\treturn ret;\n\t}\n\n\n\n\n\n\n\n\n\tstd::vector<std::pair<std::string, TypeConstraints_t>> parseGenericTypeList(State& st)\n\t{\n\t\tstd::unordered_set<std::string> seen;\n\t\tstd::vector<std::pair<std::string, TypeConstraints_t>> ret;\n\n\t\twhile(st.front().type != TT::RAngle)\n\t\t{\n\t\t\tif(st.front().type == TT::Identifier)\n\t\t\t{\n\t\t\t\tstd::string gt = st.eat().str();\n\t\t\t\tTypeConstraints_t constrs;\n\n\t\t\t\tif(st.front().type == TT::Colon)\n\t\t\t\t{\n\t\t\t\t\tst.eat();\n\t\t\t\t\tif(st.front().type != TT::Identifier)\n\t\t\t\t\t\terror(st, \"expected identifier after beginning of type constraint list\");\n\n\t\t\t\t\twhile(st.front().type == TT::Identifier)\n\t\t\t\t\t{\n\t\t\t\t\t\tconstrs.protocols.push_back(st.eat().str());\n\n\t\t\t\t\t\tif(st.front().type == TT::Ampersand)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tst.eat();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(st.front().type != TT::Comma && st.front().type != TT::RAngle)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\terror(st, \"expected ',' or '>' to end type parameter list (1)\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(st.front().type != TT::Comma && st.front().type != TT::RAngle)\n\t\t\t\t{\n\t\t\t\t\terror(st, \"expected ',' or '>' to end type parameter list (2)\");\n\t\t\t\t}\n\n\t\t\t\tif(seen.find(gt) != seen.end())\n\t\t\t\t\terror(st, \"duplicate type parameter '%s'\", gt);\n\n\t\t\t\tseen.insert(gt);\n\t\t\t\tret.push_back({ gt, constrs });\n\t\t\t}\n\t\t\telse if(st.front().type == TT::Comma)\n\t\t\t{\n\t\t\t\tst.eat();\n\t\t\t}\n\t\t\telse if(st.front().type != TT::RAngle)\n\t\t\t{\n\t\t\t\terror(st, \"expected '>' to end type parameter list\");\n\t\t\t}\n\t\t}\n\n\t\ticeAssert(st.front().type == TT::RAngle);\n\t\tst.eat();\n\n\t\treturn ret;\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tPResult<Block> parseBracedBlock(State& st)\n\t{\n\t\tst.skipWS();\n\n\t\tif(st.front() == TT::LBrace)\n\t\t{\n\t\t\tBlock* ret = util::pool<Block>(st.eat().loc);\n\n\t\t\tst.skipWS();\n\t\t\twhile(st.front() != TT::RBrace)\n\t\t\t{\n\t\t\t\tif(!st.hasTokens())\n\t\t\t\t\treturn PResult<Block>::insufficientTokensError();\n\n\t\t\t\tauto s = parseStmt(st).mutate([&](auto stmt) {\n\t\t\t\t\tif(auto defer = dcast(DeferredStmt, stmt))\n\t\t\t\t\t\tret->deferredStatements.push_back(defer);\n\n\t\t\t\t\telse\n\t\t\t\t\t\tret->statements.push_back(stmt);\n\n\n\t\t\t\t\tif(st.front() == TT::NewLine || st.front() == TT::Comment || st.front() == TT::Semicolon)\n\t\t\t\t\t\tst.pop();\n\n\t\t\t\t\telse if(st.frontAfterWS() == TT::RBrace)\n\t\t\t\t\t\treturn;\n\n\t\t\t\t\telse\n\t\t\t\t\t\texpected(st, \"newline or semicolon to terminate a statement\", st.front().str());\n\n\t\t\t\t\tst.skipWS();\n\t\t\t\t});\n\n\t\t\t\tif(s.isError())\n\t\t\t\t\treturn PResult<Block>::copyError(s);\n\t\t\t}\n\n\t\t\tauto closing = st.eat();\n\t\t\ticeAssert(closing == TT::RBrace);\n\t\t\tret->closingBrace = closing.loc;\n\t\t\tret->isArrow = false;\n\n\t\t\treturn ret;\n\t\t}\n\t\telse if(st.front() == TT::FatRightArrow)\n\t\t{\n\t\t\tBlock* ret = util::pool<Block>(st.eat().loc);\n\t\t\tret->statements.push_back(parseStmt(st).val());\n\t\t\tret->closingBrace = st.loc();\n\t\t\tret->isArrow = true;\n\n\t\t\treturn ret;\n\t\t}\n\t\telse\n\t\t{\n\t\t\texpected(st, \"'{' to begin braced block\", st.front().str());\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/frontend/parser/literal.cpp",
    "content": "// literal.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"defs.h\"\n#include \"platform.h\"\n#include \"parser_internal.h\"\n\n#include \"memorypool.h\"\n\n#include \"utf8rewind/include/utf8rewind/utf8rewind.h\"\n\n#include <sstream>\n\nusing namespace ast;\nusing namespace lexer;\n\n\nusing TT = lexer::TokenType;\nnamespace parser\n{\n\tLitNumber* parseNumber(State& st)\n\t{\n\t\ticeAssert(st.front() == TT::Number);\n\t\tauto t = st.eat();\n\n\t\treturn util::pool<LitNumber>(st.ploc(), t.str());\n\t}\n\n\tstatic std::string parseHexEscapes(const Location& loc, std::string_view sv, size_t* ofs)\n\t{\n\t\tif(sv[0] == 'x')\n\t\t{\n\t\t\tif(sv.size() < 3)\n\t\t\t\terror(loc, \"malformed escape sequence: unexpected end of string\");\n\n\t\t\tif(!isxdigit(sv[1]) || !isxdigit(sv[2]))\n\t\t\t\terror(loc, \"malformed escape sequence: non-hex character in \\\\x escape\");\n\n\t\t\t// ok then.\n\t\t\tchar s[2] = { sv[1], sv[2] };\n\t\t\tchar val = static_cast<char>(std::stol(s, /* pos: */ 0, /* base: */ 16));\n\n\t\t\t*ofs = 3;\n\t\t\treturn std::string(&val, 1);\n\t\t}\n\t\telse if(sv[0] == 'u')\n\t\t{\n\t\t\tif(sv.size() < 3)\n\t\t\t\terror(loc, \"malformed escape sequence: unexpected end of string\");\n\n\t\t\tsv.remove_prefix(1);\n\t\t\tif(sv[0] != '{')\n\t\t\t\terror(loc, \"malformed escape sequence: expected '{' after \\\\u\");\n\n\t\t\tsv.remove_prefix(1);\n\n\t\t\tstd::string digits;\n\t\t\tsize_t i = 0;\n\t\t\tfor(i = 0; i < sv.size(); i++)\n\t\t\t{\n\t\t\t\tif(sv[i] == '}') break;\n\n\t\t\t\tif(!isxdigit(sv[i]))\n\t\t\t\t\terror(loc, \"malformed escape sequence: non-hex character '%c' inside \\\\u{...}\", sv[i]);\n\n\t\t\t\tif(digits.size() == 8)\n\t\t\t\t\terror(loc, \"malformed escape sequence: too many digits inside \\\\u{...}; up to 8 are allowed\");\n\n\t\t\t\tdigits += sv[i];\n\t\t\t}\n\n\t\t\tif(sv[i] != '}')\n\t\t\t\terror(loc, \"malformed escape sequence: expcected '}' to end codepoint escape\");\n\n\t\t\tuint32_t codepoint = std::stol(digits, /* pos: */ 0, /* base: */ 16);\n\n\t\t\tchar output[8] = { 0 };\n\t\t\tint err = 0;\n\t\t\tauto sz = utf32toutf8(&codepoint, 4, output, 8, &err);\n\t\t\tif(err != UTF8_ERR_NONE)\n\t\t\t\terror(loc, \"invalid utf32 codepoint!\");\n\n\t\t\t*ofs = 3 + digits.size();\n\t\t\treturn std::string(output, sz);\n\t\t}\n\t\telse\n\t\t{\n\t\t\ticeAssert(\"wtf yo\" && 0);\n\t\t\treturn \"\";\n\t\t}\n\t}\n\n\tstd::string parseStringEscapes(const Location& loc, const std::string& str)\n\t{\n\t\tstd::stringstream ss;\n\n\t\tfor(size_t i = 0; i < str.length(); i++)\n\t\t{\n\t\t\tif(str[i] == '\\\\')\n\t\t\t{\n\t\t\t\ti++;\n\t\t\t\tswitch(str[i])\n\t\t\t\t{\n\t\t\t\t\tcase 'n':   ss << \"\\n\"; break;\n\t\t\t\t\tcase 'b':   ss << \"\\b\"; break;\n\t\t\t\t\tcase 'r':   ss << \"\\r\"; break;\n\t\t\t\t\tcase 't':   ss << \"\\t\"; break;\n\t\t\t\t\tcase '\"':   ss << \"\\\"\"; break;\n\t\t\t\t\tcase '\\\\':  ss << \"\\\\\"; break;\n\n\t\t\t\t\tcase 'x':   // fallthrough\n\t\t\t\t\tcase 'u': {\n\t\t\t\t\t\tsize_t ofs = 0;\n\t\t\t\t\t\tss << parseHexEscapes(loc, std::string_view(str.c_str() + i, str.size() - i), &ofs);\n\t\t\t\t\t\ti += ofs - 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tss << std::string(\"\\\\\") + str[i];\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tss << str[i];\n\t\t\t}\n\t\t}\n\n\t\treturn ss.str();\n\t}\n\n\tLitString* parseString(State& st, bool israw)\n\t{\n\t\ticeAssert(st.front() == TT::StringLiteral);\n\t\tauto t = st.eat();\n\n\t\treturn util::pool<LitString>(st.ploc(), parseStringEscapes(st.ploc(), t.str()), israw);\n\t}\n\n\tLitArray* parseArray(State& st, bool israw)\n\t{\n\t\ticeAssert(st.front() == TT::LSquare);\n\t\tToken front = st.eat();\n\n\t\tpts::Type* explType = 0;\n\t\tif(st.front() == TT::As)\n\t\t{\n\t\t\t// get an explicit type.\n\t\t\tst.pop();\n\t\t\texplType = parseType(st);\n\n\t\t\tif(st.pop() != TT::Colon)\n\t\t\t\texpectedAfter(st.ploc(), \":\", \"explicit type in array literal\", st.prev().str());\n\t\t}\n\n\t\tstd::vector<Expr*> values;\n\t\twhile(true)\n\t\t{\n\t\t\tToken tok = st.frontAfterWS();\n\t\t\tif(tok.type == TT::Comma)\n\t\t\t{\n\t\t\t\tst.pop();\n\n\t\t\t\tif(st.frontAfterWS() == TT::RSquare)\n\t\t\t\t\terror(tok.loc, \"trailing commas are not allowed\");\n\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\telse if(tok.type == TT::RSquare)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tst.skipWS();\n\t\t\t\tvalues.push_back(parseExpr(st));\n\t\t\t}\n\t\t}\n\n\t\tst.skipWS();\n\t\ticeAssert(st.front() == TT::RSquare);\n\n\t\tauto end = st.eat();\n\n\t\tauto ret = util::pool<LitArray>(front.loc, values);\n\t\tret->explicitType = explType;               // don't matter if null.\n\t\tret->raw = israw;\n\n\t\t// ret->loc.col = front.loc.col + 1;\n\t\tret->loc.len = (end.loc.col - front.loc.col) + 1;\n\t\treturn ret;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/frontend/parser/misc.cpp",
    "content": "// misc.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"frontend.h\"\n#include \"parser_internal.h\"\n\n#include \"memorypool.h\"\n\nusing namespace ast;\nusing namespace lexer;\n\nnamespace parser\n{\n\tusing TT = lexer::TokenType;\n\tImportStmt* parseImport(State& st)\n\t{\n\t\ticeAssert(st.front() == TT::Import);\n\t\tauto ret = util::pool<ImportStmt>(st.loc());\n\n\t\tst.eat();\n\t\tst.skipWS();\n\n\t\tif(st.front() == TT::StringLiteral)\n\t\t{\n\t\t\tst.eat();\n\t\t}\n\t\telse if(st.front() == TT::Identifier)\n\t\t{\n\t\t\t// just consume.\n\t\t\tsize_t i = st.getIndex();\n\t\t\tparseIdentPath(st.getTokenList(), &i);\n\t\t\tst.setIndex(i);\n\t\t}\n\t\telse\n\t\t{\n\t\t\texpectedAfter(st, \"string literal or identifier path\", \"'import'\", st.front().str());\n\t\t}\n\n\n\t\t{\n\t\t\tst.skipWS();\n\n\t\t\t// check for 'import as foo'\n\t\t\tif(st.front() == TT::As)\n\t\t\t{\n\t\t\t\tst.eat();\n\t\t\t\tif(st.front() != TT::Identifier)\n\t\t\t\t\texpectedAfter(st.loc(), \"identifier\", \"'import-as'\", st.front().str());\n\n\t\t\t\tsize_t i = st.getIndex();\n\t\t\t\tparseIdentPath(st.getTokenList(), &i);\n\t\t\t\tst.setIndex(i);\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\t}\n\n\tUsingStmt* parseUsingStmt(State& st)\n\t{\n\t\ticeAssert(st.front() == TT::Using);\n\t\tst.eat();\n\n\t\tst.enterUsingParse();\n\t\tdefer(st.leaveUsingParse());\n\n\t\tauto ret = util::pool<UsingStmt>(st.ploc());\n\t\tret->expr = parseExpr(st);\n\n\t\tif(st.front() != TT::As)\n\t\t\texpectedAfter(st.loc(), \"'as'\", \"scope in 'using'\", st.front().str());\n\n\t\tst.eat();\n\t\tif(st.front() != TT::Identifier)\n\t\t\texpectedAfter(st.loc(), \"identifier\", \"'as' in 'using' declaration\", st.front().str());\n\n\t\tret->useAs = st.eat().str();\n\t\treturn ret;\n\t}\n\n\n\n\tRunDirective* parseRunDirective(State& st)\n\t{\n\t\ticeAssert(st.front() == TT::Directive_Run);\n\n\t\tauto ret = util::pool<RunDirective>(st.eat().loc);\n\n\t\t// trick the parser. when we do a #run, we will run it in a function wrapper, so we\n\t\t// are technically \"inside\" a function.\n\t\tst.enterFunctionBody();\n\t\tdefer(st.leaveFunctionBody());\n\n\t\tif(st.front() == TT::LBrace)    ret->block = parseBracedBlock(st).val();\n\t\telse                            ret->insideExpr = parseExpr(st);\n\n\t\treturn ret;\n\t}\n\n\n\n\tAttribSet parseAttributes(State& st)\n\t{\n\t\tusing UA = AttribSet::UserAttrib;\n\n\t\tif(st.front() != TT::At && (st.front() <= TT::Attr_ATTRS_BEGIN || st.front() >= TT::Attr_ATTRS_END))\n\t\t\treturn AttribSet::of(attr::NONE);\n\n\t\tauto parseUA = [](State& st) -> UA {\n\n\t\t\ticeAssert(st.front() == TT::At);\n\t\t\tst.pop();\n\n\t\t\tauto ret = UA(st.eat().str(), {});\n\n\t\t\tif(st.front() == TT::LSquare)\n\t\t\t{\n\t\t\t\tauto begin = st.loc();\n\n\t\t\t\tst.eat();\n\n\t\t\t\t//* this means that attributes can only take tokens as arguments. if you want more complex stuff,\n\t\t\t\t//* then it needs to be wrapped up in a string literal.\n\t\t\t\twhile(st.front() != TT::RSquare)\n\t\t\t\t{\n\t\t\t\t\tret.args.push_back(st.eat().str());\n\n\t\t\t\t\tif(st.front() == TT::Comma)\n\t\t\t\t\t\tst.eat();\n\n\t\t\t\t\telse if(st.front() != TT::RSquare)\n\t\t\t\t\t\texpected(st.loc(), \"']' to end argument list\", st.prev().str());\n\t\t\t\t}\n\n\t\t\t\ticeAssert(st.front() == TT::RSquare);\n\t\t\t\tst.pop();\n\n\t\t\t\tif(ret.args.empty())\n\t\t\t\t\twarn(Location::unionOf(begin, st.ploc()), \"empty argument list to attribute\");\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t};\n\n\n\t\tAttribSet ret;\n\t\twhile(true)\n\t\t{\n\t\t\t// i would love me some static reflection right now\n\t\t\tswitch(st.front())\n\t\t\t{\n\t\t\t\tcase TT::Attr_Raw:      ret.set(attr::RAW); st.pop(); break;\n\t\t\t\tcase TT::Attr_Packed:   ret.set(attr::PACKED); st.pop(); break;\n\t\t\t\tcase TT::Attr_NoMangle: ret.set(attr::NO_MANGLE); st.pop(); break;\n\t\t\t\tcase TT::Attr_EntryFn:  ret.set(attr::FN_ENTRYPOINT); st.pop(); break;\n\t\t\t\tcase TT::Attr_Platform: unexpected(st.loc(), \"@platform definition\");\n\t\t\t\tcase TT::Attr_Operator: unexpected(st.loc(), \"@operator declaration\");\n\n\t\t\t\tcase TT::At:\n\t\t\t\t\tret.add(parseUA(st));\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tgoto out;\n\t\t\t}\n\t\t}\n\n\t\t// sue me\n\t\tout:\n\t\treturn ret;\n\t}\n\n\n\t// TODO: switch this to the new attribute system. after the whole cddc19 shitshow @platform functionality\n\t// TODO: remains unused.\n\tPlatformDefn* parsePlatformDefn(State& st)\n\t{\n\t\ticeAssert(st.front() == TT::Attr_Platform);\n\t\tauto l = st.loc();\n\n\t\tst.eat();\n\n\t\tif(st.eat() != TT::LSquare)\n\t\t\texpectedAfter(st.ploc(), \"'['\", \"@platform definition\", st.prev().str());\n\n\t\tPlatformDefn* pd = util::pool<PlatformDefn>(l);\n\n\t\t// see what the thing is.\n\t\tif(st.front() == TT::Identifier && st.front().str() == \"intrinsic\")\n\t\t{\n\t\t\tst.eat();\n\t\t\tpd->defnType = PlatformDefn::Type::Intrinsic;\n\n\t\t\tif(st.eat() != TT::Comma)\n\t\t\t\texpected(st.ploc(), \"',' in argument list to @platform\", st.prev().str());\n\n\t\t\tif(st.front() != TT::StringLiteral)\n\t\t\t\texpected(st.loc(), \"string literal to specify intrinsic name\", st.front().str());\n\n\t\t\tauto realname = st.eat().str();\n\n\t\t\tif(st.eat() != TT::RSquare)\n\t\t\t\texpectedAfter(st.ploc(), \"']'\", \"@platform definition\", st.prev().str());\n\n\t\t\tif(st.front() != TT::Func)\n\t\t\t\texpectedAfter(st.loc(), \"function declaration\", \"@platform\", st.front().str());\n\n\t\t\tauto [ defn, isvar, varloc ] = parseFunctionDecl(st);\n\t\t\t(void) varloc;\n\n\t\t\tif(!defn->generics.empty())\n\t\t\t\terror(defn->loc, \"platform intrinsics cannot be generic\");\n\n\t\t\tauto ffn = util::pool<ForeignFuncDefn>(st.loc());\n\t\t\tffn->realName = realname;\n\n\t\t\tffn->loc = defn->loc;\n\t\t\tffn->isVarArg = isvar;\n\t\t\tffn->name = defn->name;\n\t\t\tffn->params = defn->params;\n\t\t\tffn->visibility = defn->visibility;\n\t\t\tffn->returnType = defn->returnType;\n\n\n\t\t\tpd->intrinsicDefn = ffn;\n\t\t}\n\t\telse if(st.front() == TT::Identifier && st.front().str() == \"integer_type\")\n\t\t{\n\t\t\tst.eat();\n\t\t\tpd->defnType = PlatformDefn::Type::IntegerType;\n\n\t\t\tif(st.eat() != TT::Comma)\n\t\t\t\texpected(st.ploc(), \"',' in argument list to @platform\", st.prev().str());\n\n\t\t\tauto num = st.front().str();\n\t\t\tif(st.front() != TT::Number || num.find('.') != std::string::npos)\n\t\t\t\texpected(st.ploc(), \"integer value to specify type size (in bits)\", st.front().str());\n\n\t\t\tst.eat();\n\n\t\t\tint sz = std::stoi(num);\n\t\t\tif(sz <= 0)     expected(st.ploc(), \"non-zero and non-negative size\", num);\n\t\t\telse if(sz < 8) error(st.ploc(), \"types less than 8-bits wide are currently not supported\");\n\n\t\t\tpd->typeSizeInBits = sz;\n\n\t\t\tif(st.eat() != TT::RSquare)\n\t\t\t\texpectedAfter(st.ploc(), \"']'\", \"@platform definition\", st.prev().str());\n\n\t\t\tif(st.front() != TT::Identifier)\n\t\t\t\texpectedAfter(st.loc(), \"identifier as type name\", \"@platform definition\", st.front().str());\n\n\t\t\tpd->typeName = st.eat().str();\n\t\t}\n\t\telse if(st.front() == TT::Identifier && st.front().str() == \"native_word_size\")\n\t\t{\n\t\t\tif(!st.nativeWordSizeStillValid)\n\t\t\t{\n\t\t\t\tSimpleError::make(st.loc(), \"setting the native word size is no longer possible at this point\")->append(\n\t\t\t\t\tBareError::make(MsgType::Note, \"@platform[native_word_size] must appear before any code declarations, \"\n\t\t\t\t\t\t\"and be the first '@platform' declaration\"))->postAndQuit();\n\t\t\t}\n\n\t\t\tst.eat();\n\n\t\t\tif(st.eat() != TT::RSquare)\n\t\t\t\texpectedAfter(st.ploc(), \"']'\", \"@platform definition\", st.prev().str());\n\n\t\t\tauto num = st.front().str();\n\t\t\tif(st.front() != TT::Number || num.find('.') != std::string::npos)\n\t\t\t\texpected(st.ploc(), \"integer value to specify word size (in bits)\", st.front().str());\n\n\t\t\tst.eat();\n\n\t\t\tint sz = std::stoi(num);\n\t\t\tif(sz <= 0)     expected(st.ploc(), \"non-zero and non-negative size\", num);\n\t\t\telse if(sz < 8) error(st.ploc(), \"types less than 8-bits wide are currently not supported\");\n\n\t\t\t//? should we warn if it was already set?\n\t\t\tst.cState->nativeWordSize = sz;\n\n\t\t\treturn 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(st.loc(), \"invalid platform declaration of type '%s'\", st.front().str());\n\t\t}\n\n\t\treturn pd;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/frontend/parser/operators.cpp",
    "content": "// operators.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"defs.h\"\n#include \"pts.h\"\n#include \"parser.h\"\n#include \"parser_internal.h\"\n\n#include \"memorypool.h\"\n\n\nusing namespace ast;\nusing namespace lexer;\n\nusing TT = lexer::TokenType;\nnamespace parser\n{\n\tOperatorOverloadDefn* parseOperatorOverload(State& st)\n\t{\n\t\tusing Kind = OperatorOverloadDefn::Kind;\n\n\t\ticeAssert(st.front() == TT::Operator);\n\t\tauto ret = util::pool<OperatorOverloadDefn>(st.eat().loc);\n\n\t\tif(st.front().str() == \"prefix\")\n\t\t\tret->kind = Kind::Prefix;\n\n\t\telse if(st.front().str() == \"postfix\")\n\t\t\tret->kind = Kind::Postfix;\n\n\t\telse if(st.front().str() == \"infix\")\n\t\t\tret->kind = Kind::Infix;\n\n\t\telse\n\t\t\texpectedAfter(st, \"either 'infix', 'prefix' or 'postfix'\", \"'operator'\", st.front().str());\n\n\t\tst.eat();\n\t\tret->symbol = parseOperatorTokens(st);\n\n\n\n\n\t\tbool isvar = false;\n\t\tstd::tie(ret->params, ret->generics, ret->returnType, isvar, std::ignore) = parseFunctionLookingDecl(st);\n\n\t\tif(ret->returnType == 0)\n\t\t\tret->returnType = pts::NamedType::create(ret->loc, VOID_TYPE_STRING);\n\n\t\tif(isvar) error(ret, \"C-style variadic arguments are not supported on non-foreign functions\");\n\n\t\tst.skipWS();\n\t\tif(st.front() != TT::LBrace && st.front() != TT::FatRightArrow)\n\t\t\texpected(st, \"'{' to begin function body\", st.front().str());\n\n\t\tst.enterFunctionBody();\n\n\t\tret->body = parseBracedBlock(st).val();\n\t\tret->name = ret->symbol;\n\n\t\tst.leaveFunctionBody();\n\t\treturn ret;\n\t}\n\n\n\n\n\tstd::string parseOperatorTokens(State& st)\n\t{\n\t\tusing TT = lexer::TokenType;\n\n\t\tauto tok_op = st.eat();\n\n\t\tif(tok_op == TT::LAngle || tok_op == TT::RAngle)\n\t\t{\n\t\t\t// check if the next one matches.\n\t\t\tif(tok_op == TT::LAngle)\n\t\t\t{\n\t\t\t\tif(st.front() == TT::LAngle)\n\t\t\t\t{\n\t\t\t\t\t// < < is <<\n\t\t\t\t\tst.eat();\n\t\t\t\t\treturn Operator::BitwiseShiftLeft;\n\t\t\t\t}\n\t\t\t\telse if(st.front() == TT::LessThanEquals)\n\t\t\t\t{\n\t\t\t\t\t// < <= is <<=\n\t\t\t\t\tst.eat();\n\t\t\t\t\treturn Operator::BitwiseShiftLeftEquals;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(tok_op == TT::RAngle)\n\t\t\t{\n\t\t\t\tif(st.front() == TT::RAngle)\n\t\t\t\t{\n\t\t\t\t\t// > > is >>\n\t\t\t\t\tst.eat();\n\t\t\t\t\treturn Operator::BitwiseShiftRight;\n\t\t\t\t}\n\t\t\t\telse if(st.front() == TT::GreaterEquals)\n\t\t\t\t{\n\t\t\t\t\t// > >= is >>=\n\t\t\t\t\tst.eat();\n\t\t\t\t\treturn Operator::BitwiseShiftRightEquals;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\n\t\tswitch(tok_op.type)\n\t\t{\n\t\t\tcase TT::Plus:              return Operator::Plus;\n\t\t\tcase TT::Minus:             return Operator::Minus;\n\t\t\tcase TT::Asterisk:          return Operator::Multiply;\n\t\t\tcase TT::Divide:            return Operator::Divide;\n\t\t\tcase TT::Percent:           return Operator::Modulo;\n\t\t\tcase TT::Equal:             return Operator::Assign;\n\n\t\t\tcase TT::LAngle:            return Operator::CompareLT;\n\t\t\tcase TT::RAngle:            return Operator::CompareGT;\n\t\t\tcase TT::LessThanEquals:    return Operator::CompareLEQ;\n\t\t\tcase TT::GreaterEquals:     return Operator::CompareGEQ;\n\t\t\tcase TT::EqualsTo:          return Operator::CompareEQ;\n\t\t\tcase TT::NotEquals:         return Operator::CompareNEQ;\n\n\t\t\tcase TT::Ampersand:         return Operator::BitwiseAnd;\n\t\t\tcase TT::Pipe:              return Operator::BitwiseOr;\n\t\t\tcase TT::Caret:             return Operator::BitwiseXor;\n\t\t\tcase TT::LogicalOr:         return Operator::LogicalOr;\n\t\t\tcase TT::LogicalAnd:        return Operator::LogicalAnd;\n\n\t\t\tcase TT::PlusEq:            return Operator::PlusEquals;\n\t\t\tcase TT::MinusEq:           return Operator::MinusEquals;\n\t\t\tcase TT::MultiplyEq:        return Operator::MultiplyEquals;\n\t\t\tcase TT::DivideEq:          return Operator::DivideEquals;\n\t\t\tcase TT::ModEq:             return Operator::ModuloEquals;\n\t\t\tcase TT::AmpersandEq:       return Operator::BitwiseAndEquals;\n\t\t\tcase TT::PipeEq:            return Operator::BitwiseOrEquals;\n\t\t\tcase TT::CaretEq:           return Operator::BitwiseXorEquals;\n\n\t\t\tcase TT::As:                return Operator::TypeCast;\n\t\t\tcase TT::Is:                return Operator::TypeIs;\n\n\t\t\tcase TT::DoubleColon:       return \"::\";\n\t\t\tcase TT::Period:            return \".\";\n\t\t\tcase TT::At:                return \"@\";\n\n\t\t\tcase TT::Ellipsis:          return \"...\";\n\t\t\tcase TT::HalfOpenEllipsis:  return \"..<\";\n\n\t\t\tdefault:                    break;\n\t\t}\n\n\t\t// check custom operators.\n\t\tif(tok_op.type == TT::Identifier || tok_op.type == TT::UnicodeSymbol)\n\t\t\treturn tok_op.str();\n\n\t\treturn \"\";\n\t}\n\n\t// TODO: move this over to the new attribute system if possible.\n\tsize_t parseOperatorDecl(const lexer::TokenList& tokens, size_t idx, int* _kind, CustomOperatorDecl* out)\n\t{\n\t\ticeAssert(tokens[idx] == TT::Attr_Operator);\n\t\tconst Token tok = tokens[idx];\n\n\t\tusing Kind = CustomOperatorDecl::Kind;\n\t\tCustomOperatorDecl oper;\n\t\toper.loc = tok.loc;\n\n\t\tidx++;\n\t\tif(tokens[idx] != TT::LSquare)\n\t\t\texpectedAfter(tokens[idx].loc, \"'['\", \"'@operator' in custom operator declaration\", tokens[idx].str());\n\n\t\tidx++;\n\n\t\tif(tokens[idx].str() != \"prefix\" && tokens[idx].str() != \"postfix\" && tokens[idx].str() != \"infix\")\n\t\t{\n\t\t\texpectedAfter(tokens[idx].loc, \"either 'prefix', 'postfix' or 'infix'\", \"'@operator' in custom operator declaration\",\n\t\t\t\ttokens[idx].str());\n\t\t}\n\n\t\tint kind = 0;\n\t\tif(tokens[idx].str() == \"infix\")        kind = 1, oper.kind = Kind::Infix;\n\t\telse if(tokens[idx].str() == \"prefix\")  kind = 2, oper.kind = Kind::Prefix;\n\t\telse if(tokens[idx].str() == \"postfix\") kind = 3, oper.kind = Kind::Postfix;\n\t\telse                                    iceAssert(0);\n\n\t\tidx++;\n\t\tif(tokens[idx] != TT::Comma)\n\t\t\texpected(tokens[idx].loc, \"',' in argument list to '@operator'\", tokens[idx].str());\n\n\t\tidx++;\n\n\t\t{\n\t\t\tauto num = tokens[idx].str();\n\n\t\t\tif(tokens[idx] != TT::Number || num.find('.') != std::string::npos)\n\t\t\t\texpected(tokens[idx].loc, \"integer value for precedence\", num);\n\n\t\t\tint prec = std::stoi(num);\n\t\t\tif(prec <= 0)\n\t\t\t\texpected(tokens[idx].loc, \"a precedence value greater than zero\", num);\n\n\t\t\toper.precedence = prec;\n\t\t\tidx++;\n\t\t}\n\n\t\tif(tokens[idx] != TT::Comma)\n\t\t\texpected(tokens[idx].loc, \"',' in argument list to '@operator'\", tokens[idx].str());\n\n\t\tidx++;\n\n\n\t\tif(tokens[idx] != TT::UnicodeSymbol && tokens[idx] != TT::Identifier)\n\t\t{\n\t\t\terror(tokens[idx].loc, \"custom operator symbol must be a unicode symbol or regular identifier, '%s' is invalid\",\n\t\t\t\ttokens[idx].str());\n\t\t}\n\n\t\toper.symbol = tokens[idx].str();\n\t\tidx++;\n\n\t\tif(tokens[idx] != TT::RSquare)\n\t\t\terror(tokens[idx].loc, \"expected ']' to terminate operator declaration, found '%s'\", tokens[idx].str());\n\n\t\tidx++;\n\n\n\t\tif(_kind)   *_kind = kind;\n\t\tif(out)     *out = oper;\n\n\t\treturn idx;\n\t}\n\n\n\tstd::tuple<util::hash_map<std::string, parser::CustomOperatorDecl>,\n\t\t\t\tutil::hash_map<std::string, parser::CustomOperatorDecl>,\n\t\t\t\tutil::hash_map<std::string, parser::CustomOperatorDecl>>\n\tparseOperators(const lexer::TokenList& tokens)\n\t{\n\t\tusing Token = lexer::Token;\n\t\tusing TT = lexer::TokenType;\n\n\t\tutil::hash_map<std::string, CustomOperatorDecl> infix;\n\t\tutil::hash_map<std::string, CustomOperatorDecl> prefix;\n\t\tutil::hash_map<std::string, CustomOperatorDecl> postfix;\n\n\t\t// basically, this is how it goes:\n\t\t// only allow comments to occur before imports\n\t\t// all imports must happen before anything else in the file\n\t\t// comments can be interspersed between import statements, of course.\n\t\tfor(size_t i = 0; i < tokens.size(); i++)\n\t\t{\n\t\t\tconst Token& tok = tokens[i];\n\t\t\tif(tok == TT::Attr_Operator)\n\t\t\t{\n\t\t\t\tCustomOperatorDecl oper;\n\t\t\t\tint kind = 0;\n\n\t\t\t\ti = parseOperatorDecl(tokens, i, &kind, &oper);\n\n\t\t\t\tif(kind == 1)\t\tinfix[oper.symbol] = oper;\n\t\t\t\telse if(kind == 2)\tprefix[oper.symbol] = oper;\n\t\t\t\telse if(kind == 3)\tpostfix[oper.symbol] = oper;\n\t\t\t}\n\t\t\telse if(tok == TT::Export || tok == TT::Import)\n\t\t\t{\n\t\t\t\t// skip until a newline.\n\t\t\t\twhile(tokens[i] != TT::Comment && tokens[i] != TT::NewLine)\n\t\t\t\t\ti++;\n\t\t\t}\n\t\t\telse if(tok == TT::Comment || tok == TT::NewLine)\n\t\t\t{\n\t\t\t\t// skipped\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// stop imports.\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn std::make_tuple(infix, prefix, postfix);\n\t}\n}\n\n\n\n\n\n\n\n\n\n\nnamespace Operator\n{\n\tconst std::string Plus                      = \"+\";\n\tconst std::string Minus                     = \"-\";\n\tconst std::string Multiply                  = \"*\";\n\tconst std::string Divide                    = \"/\";\n\tconst std::string Modulo                    = \"%\";\n\n\tconst std::string UnaryPlus                 = \"+\";\n\tconst std::string UnaryMinus                = \"-\";\n\n\tconst std::string PointerDeref              = \"*\";\n\tconst std::string AddressOf                 = \"&\";\n\n\tconst std::string BitwiseNot                = \"~\";\n\tconst std::string BitwiseAnd                = \"&\";\n\tconst std::string BitwiseOr                 = \"|\";\n\tconst std::string BitwiseXor                = \"^\";\n\tconst std::string BitwiseShiftLeft          = \"<<\";\n\tconst std::string BitwiseShiftRight         = \">>\";\n\n\tconst std::string LogicalNot                = \"!\";\n\tconst std::string LogicalAnd                = \"&&\";\n\tconst std::string LogicalOr                 = \"||\";\n\n\tconst std::string CompareEQ                 = \"==\";\n\tconst std::string CompareNEQ                = \"!=\";\n\tconst std::string CompareLT                 = \"<\";\n\tconst std::string CompareLEQ                = \"<=\";\n\tconst std::string CompareGT                 = \">\";\n\tconst std::string CompareGEQ                = \">=\";\n\n\tconst std::string Assign                    = \"=\";\n\tconst std::string PlusEquals                = \"+=\";\n\tconst std::string MinusEquals               = \"-=\";\n\tconst std::string MultiplyEquals            = \"*=\";\n\tconst std::string DivideEquals              = \"/=\";\n\tconst std::string ModuloEquals              = \"%=\";\n\tconst std::string BitwiseShiftLeftEquals    = \"<<=\";\n\tconst std::string BitwiseShiftRightEquals   = \">>=\";\n\tconst std::string BitwiseXorEquals          = \"^=\";\n\tconst std::string BitwiseAndEquals          = \"&=\";\n\tconst std::string BitwiseOrEquals           = \"|=\";\n\n\tconst std::string TypeCast                  = \"as\";\n\tconst std::string TypeIs                    = \"is\";\n\n\n\tbool isArithmetic(const std::string& op)\n\t{\n\t\treturn (op == Operator::Plus || op == Operator::Minus || op == Operator::Multiply || op == Operator::Divide || op == Operator::Modulo);\n\t}\n\n\tbool isBitwise(const std::string& op)\n\t{\n\t\treturn (op == Operator::BitwiseAnd || op == Operator::BitwiseOr || op == Operator::BitwiseXor\n\t\t\t|| op == Operator::BitwiseShiftLeft || op == Operator::BitwiseShiftRight);\n\t}\n\n\tbool isAssignment(const std::string& op)\n\t{\n\t\treturn (op == Operator::Assign || op == Operator::PlusEquals || op == Operator::MinusEquals || op == Operator::MultiplyEquals\n\t\t\t|| op == Operator::DivideEquals || op == Operator::ModuloEquals || op == Operator::BitwiseShiftLeftEquals\n\t\t\t|| op == Operator::BitwiseShiftRightEquals || op == Operator::BitwiseAndEquals || op == Operator::BitwiseOrEquals\n\t\t\t|| op == Operator::BitwiseXorEquals);\n\t}\n\n\tbool isComparison(const std::string& op)\n\t{\n\t\treturn (op == Operator::CompareEQ || op == Operator::CompareNEQ || op == Operator::CompareLT || op == Operator::CompareGT\n\t\t\t|| op == Operator::CompareLEQ || op == Operator::CompareGEQ);\n\t}\n\n\n\tstd::string getNonAssignmentVersion(const std::string& op)\n\t{\n\t\tif(op == Operator::PlusEquals)                      return Operator::Plus;\n\t\telse if(op == Operator::MinusEquals)                return Operator::Minus;\n\t\telse if(op == Operator::MultiplyEquals)             return Operator::Multiply;\n\t\telse if(op == Operator::DivideEquals)               return Operator::Divide;\n\t\telse if(op == Operator::ModuloEquals)               return Operator::Modulo;\n\t\telse if(op == Operator::BitwiseShiftLeftEquals)     return Operator::BitwiseShiftLeft;\n\t\telse if(op == Operator::BitwiseShiftRightEquals)    return Operator::BitwiseShiftRight;\n\t\telse if(op == Operator::BitwiseAndEquals)           return Operator::BitwiseAnd;\n\t\telse if(op == Operator::BitwiseOrEquals)            return Operator::BitwiseOr;\n\t\telse if(op == Operator::BitwiseXorEquals)           return Operator::BitwiseXor;\n\n\t\terror(\"no\");\n\t}\n\n\n\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/frontend/parser/toplevel.cpp",
    "content": "// toplevel.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"defs.h\"\n#include \"pts.h\"\n#include \"errors.h\"\n#include \"parser.h\"\n#include \"frontend.h\"\n\n#include \"parser_internal.h\"\n\n#include \"memorypool.h\"\n\nusing namespace lexer;\nusing namespace ast;\n\nnamespace parser\n{\n\tstd::pair<Location, std::vector<std::string>> parseIdentPath(const lexer::TokenList& tokens, size_t* idx)\n\t{\n\t\tusing TT = lexer::TokenType;\n\t\tstd::vector<std::string> path;\n\n\t\tsize_t i = *idx;\n\t\tLocation loc = tokens[i].loc;\n\t\twhile(tokens[i] == TT::Identifier)\n\t\t{\n\t\t\tloc = loc.unionWith(tokens[i].loc);\n\n\t\t\tpath.push_back(tokens[i].str());\n\t\t\ti++;\n\n\t\t\tif(tokens[i] == TT::DoubleColon)\n\t\t\t{\n\t\t\t\ti++;\n\t\t\t\tif(tokens[i] != TT::Identifier)\n\t\t\t\t\texpectedAfter(tokens[i - 1].loc, \"identifier\", \"'::' in path\", tokens[i].str());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t*idx = i;\n\t\treturn { loc, path };\n\t}\n\n\n\tstatic std::pair<std::string, std::vector<std::string>> parseModuleName(const std::string& fullname,\n\t\tconst frontend::FileInnards& fileinnards)\n\t{\n\t\tusing TT = lexer::TokenType;\n\t\tconst auto& tokens = fileinnards.tokens;\n\n\t\tstd::vector<std::string> path;\n\n\t\t// basically, this is how it goes:\n\t\t// only allow comments to occur before the module name.\n\t\tfor(size_t i = 0; i < tokens.size(); i++)\n\t\t{\n\t\t\tconst Token& tok = tokens[i];\n\t\t\tif(tok.type == TT::Export)\n\t\t\t{\n\t\t\t\ti++;\n\n\t\t\t\tif(tokens[i].type == TT::Identifier)\n\t\t\t\t{\n\t\t\t\t\tpath = parseIdentPath(tokens, &i).second;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\texpectedAfter(tokens[i].loc, \"identifier for export declaration\", \"'module'\", tokens[i].str());\n\t\t\t\t}\n\n\t\t\t\tif(tokens[i].type != TT::NewLine && tokens[i].type != TT::Semicolon && tokens[i].type != TT::Comment)\n\t\t\t\t{\n\t\t\t\t\texpected(tokens[i].loc, \"newline or semicolon to terminate export statement\", tokens[i].str());\n\t\t\t\t}\n\n\t\t\t\t// i++ handled by loop\n\t\t\t}\n\t\t\telse if(tok.type == TT::Comment || tok.type == TT::NewLine)\n\t\t\t{\n\t\t\t\t// skipped\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// stop\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif(path.empty())\n\t\t\tpath = { frontend::removeExtensionFromFilename(frontend::getFilenameFromPath(fullname)) };\n\n\t\treturn { path.back(), zfu::take(path, path.size() - 1) };\n\t}\n\n\n\n\tTopLevelBlock* parseTopLevel(State& st, const std::string& name)\n\t{\n\t\tusing TT = lexer::TokenType;\n\t\tTopLevelBlock* root = util::pool<TopLevelBlock>(st.loc(), name);\n\n\t\t// if it's not empty, then it's an actual user-defined namespace\n\t\tbool hadLBrace = false;\n\t\tif(name != \"\")\n\t\t{\n\t\t\t// expect \"namespace FOO { ... }\"\n\n\t\t\thadLBrace = true;\n\t\t\ticeAssert(st.front() == TT::Identifier);\n\t\t\tst.eat();\n\n\t\t\tif(st.eat() != TT::LBrace)\n\t\t\t\texpected(st.ploc(), \"'{' to start namespace declaration\", st.prev().str());\n\t\t}\n\n\t\tbool isFirst = true;\n\t\tauto priv = VisibilityLevel::Invalid;\n\t\tsize_t tix = static_cast<size_t>(-1);\n\n\n\t\twhile(st.hasTokens() && st.front() != TT::EndOfFile)\n\t\t{\n\t\t\tswitch(st.front())\n\t\t\t{\n\t\t\t\tcase TT::Import: {\n\t\t\t\t\tif(name != \"\" || !st.importsStillValid)\n\t\t\t\t\t\terror(st, \"import statements are not allowed here\");\n\n\t\t\t\t\troot->statements.push_back(parseImport(st));\n\t\t\t\t} break;\n\n\t\t\t\tcase TT::Attr_Operator: {\n\t\t\t\t\tif(name != \"\" || !st.operatorsStillValid)\n\t\t\t\t\t\terror(st, \"custom operator declarations are not allowed here\");\n\n\t\t\t\t\t// just skip it.\n\t\t\t\t\tst.setIndex(parseOperatorDecl(st.getTokenList(), st.getIndex(), 0, 0));\n\n\t\t\t\t\tst.importsStillValid = false;\n\t\t\t\t\tst.nativeWordSizeStillValid = false;\n\t\t\t\t} break;\n\n\t\t\t\tcase TT::Attr_Platform: {\n\n\t\t\t\t\tauto ret = parsePlatformDefn(st);\n\n\t\t\t\t\tif(ret) // sometimes we set a setting, but it doesn't need to have an AST node.\n\t\t\t\t\t\troot->statements.push_back(ret);\n\n\t\t\t\t\tst.importsStillValid = false;\n\t\t\t\t\tst.nativeWordSizeStillValid = false;\n\t\t\t\t} break;\n\n\t\t\t\tcase TT::Namespace: {\n\t\t\t\t\tst.eat();\n\t\t\t\t\tToken tok = st.front();\n\t\t\t\t\tif(tok != TT::Identifier)\n\t\t\t\t\t\texpectedAfter(st, \"identifier\", \"'namespace'\", st.front().str());\n\n\t\t\t\t\tauto ns = parseTopLevel(st, tok.str());\n\t\t\t\t\tif(priv != VisibilityLevel::Invalid)\n\t\t\t\t\t{\n\t\t\t\t\t\tns->visibility = priv;\n\t\t\t\t\t\tpriv = VisibilityLevel::Invalid;\n\t\t\t\t\t\ttix = static_cast<size_t>(-1);\n\t\t\t\t\t}\n\n\t\t\t\t\troot->statements.push_back(ns);\n\n\t\t\t\t\tst.importsStillValid = false;\n\t\t\t\t\tst.operatorsStillValid = false;\n\t\t\t\t\tst.nativeWordSizeStillValid = false;\n\n\t\t\t\t} break;\n\n\t\t\t\tcase TT::Attr_NoMangle: {\n\t\t\t\t\tst.pop();\n\t\t\t\t\tauto stmt = parseStmt(st).val();\n\t\t\t\t\tif(!dcast(FuncDefn, stmt) && !dcast(VarDefn, stmt))\n\t\t\t\t\t\terror(st, \"attribute '@nomangle' can only be applied on function and variable declarations\");\n\n\t\t\t\t\telse if(dcast(ForeignFuncDefn, stmt))\n\t\t\t\t\t\twarn(st, \"attribute '@nomangle' is redundant on 'ffi' functions\");\n\n\t\t\t\t\telse if(auto fd = dcast(FuncDefn, stmt))\n\t\t\t\t\t\tfd->attrs.set(attr::NO_MANGLE);\n\n\t\t\t\t\telse if(auto vd = dcast(VarDefn, stmt))\n\t\t\t\t\t\tvd->attrs.set(attr::NO_MANGLE);\n\n\t\t\t\t\troot->statements.push_back(stmt);\n\n\t\t\t\t\tst.importsStillValid = false;\n\t\t\t\t\tst.operatorsStillValid = false;\n\t\t\t\t\tst.nativeWordSizeStillValid = false;\n\n\t\t\t\t} break;\n\n\t\t\t\tcase TT::Attr_EntryFn: {\n\t\t\t\t\tst.pop();\n\t\t\t\t\tauto stmt = parseStmt(st).val();\n\t\t\t\t\tif(auto fd = dcast(FuncDefn, stmt))\n\t\t\t\t\t\tfd->attrs.set(attr::FN_ENTRYPOINT);\n\n\t\t\t\t\telse\n\t\t\t\t\t\terror(st, \"'@entry' attribute is only applicable to function definitions\");\n\n\t\t\t\t\troot->statements.push_back(stmt);\n\n\t\t\t\t\tst.importsStillValid = false;\n\t\t\t\t\tst.operatorsStillValid = false;\n\t\t\t\t\tst.nativeWordSizeStillValid = false;\n\n\t\t\t\t} break;\n\n\t\t\t\tcase TT::Public:\n\t\t\t\t\tpriv = VisibilityLevel::Public;\n\t\t\t\t\ttix = st.getIndex();\n\t\t\t\t\tst.pop();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TT::Private:\n\t\t\t\t\tpriv = VisibilityLevel::Private;\n\t\t\t\t\ttix = st.getIndex();\n\t\t\t\t\tst.pop();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TT::Internal:\n\t\t\t\t\tpriv = VisibilityLevel::Internal;\n\t\t\t\t\ttix = st.getIndex();\n\t\t\t\t\tst.pop();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TT::Comment:\n\t\t\t\tcase TT::NewLine:\n\t\t\t\t\tisFirst = true;\n\t\t\t\t\tst.skipWS();\n\t\t\t\t\tcontinue;\n\n\t\t\t\tcase TT::RBrace:\n\t\t\t\t\tif(!hadLBrace) error(st, \"unexpected '}'\");\n\t\t\t\t\tgoto out;\n\n\t\t\t\tdefault: {\n\t\t\t\t\tif(priv != VisibilityLevel::Invalid)\n\t\t\t\t\t{\n\t\t\t\t\t\tst.rewindTo(tix);\n\n\t\t\t\t\t\ttix = static_cast<size_t>(-1);\n\t\t\t\t\t\tpriv = VisibilityLevel::Invalid;\n\t\t\t\t\t}\n\n\t\t\t\t\tif(st.front() == TT::Export)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!isFirst || name != \"\")\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\terror(st, \"export declaration not allowed here (%s / %d)\", name, isFirst);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tst.eat();\n\n\t\t\t\t\t\t\tsize_t i = st.getIndex();\n\t\t\t\t\t\t\tparseIdentPath(st.getTokenList(), &i);\n\t\t\t\t\t\t\tst.setIndex(i);\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tst.importsStillValid = false;\n\t\t\t\t\tst.operatorsStillValid = false;\n\t\t\t\t\tst.nativeWordSizeStillValid = false;\n\n\t\t\t\t\troot->statements.push_back(parseStmt(st, /* allowExprs: */ false).val());\n\t\t\t\t} break;\n\t\t\t}\n\n\t\t\tisFirst = false;\n\t\t\tst.skipWS();\n\t\t}\n\n\t\tout:\n\t\tif(name != \"\")\n\t\t{\n\t\t\tif(st.front() != TT::RBrace)\n\t\t\t\texpected(st, \"'}' to close namespace declaration\", st.front().str());\n\n\t\t\tst.eat();\n\t\t}\n\n\t\t// throw in all anonymous types to the top level\n\t\troot->statements.insert(root->statements.begin(), st.anonymousTypeDefns.begin(), st.anonymousTypeDefns.end());\n\n\t\treturn root;\n\t}\n\n\tParsedFile parseFile(const std::string& fullname, const frontend::FileInnards& file, frontend::CollectorState& cs)\n\t{\n\t\tconst TokenList& tokens = file.tokens;\n\t\tauto state = State(tokens);\n\t\tstate.currentFilePath = fullname;\n\n\t\t// copy this stuff over.\n\t\tstate.binaryOps = cs.binaryOps;\n\t\tstate.prefixOps = cs.prefixOps;\n\t\tstate.postfixOps = cs.postfixOps;\n\n\t\tstate.cState = &cs;\n\n\t\tauto [ modname, modpath ] = parseModuleName(fullname, file);\n\t\tauto toplevel = parseTopLevel(state, \"\");\n\n\n\t\treturn ParsedFile {\n\t\t\tfullname,\n\t\t\tmodname,\n\t\t\tmodpath,\n\t\t\ttoplevel,\n\t\t};\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/frontend/parser/type.cpp",
    "content": "// type.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"pts.h\"\n#include \"parser_internal.h\"\n\n#include \"memorypool.h\"\n\nusing namespace ast;\nusing namespace lexer;\n\n// defined in fir/name.cpp\nnamespace fir\n{\n\tstd::string obfuscateName(const std::string& name, size_t id);\n}\n\n\nnamespace parser\n{\n\tusing TT = lexer::TokenType;\n\n\ttemplate <typename T>\n\tstatic void addSelfToMethod(T* thing, bool mutating)\n\t{\n\t\t// insert the self argument in the front.\n\t\tFuncDefn::Param self;\n\t\tself.name = \"this\";\n\t\tself.loc = thing->loc;\n\t\tself.type = util::pool<pts::PointerType>(self.loc, pts::NamedType::create(self.loc, \"self\"), mutating);\n\n\t\tthing->params.insert(thing->params.begin(), self);\n\t}\n\n\n\n\tClassDefn* parseClass(State& st)\n\t{\n\t\ticeAssert(st.front() == TT::Class);\n\t\tst.eat();\n\n\t\tif(st.front() != TT::Identifier)\n\t\t\texpectedAfter(st, \"identifier\", \"'struct'\", st.front().str());\n\n\t\tClassDefn* defn = util::pool<ClassDefn>(st.loc());\n\t\tdefn->name = st.eat().str();\n\n\t\t// check for generic function\n\t\tif(st.front() == TT::LAngle)\n\t\t{\n\t\t\tst.eat();\n\t\t\t// parse generic\n\t\t\tif(st.front() == TT::RAngle)\n\t\t\t\terror(st, \"empty type parameter lists are not allowed\");\n\n\t\t\tdefn->generics = parseGenericTypeList(st);\n\t\t}\n\n\t\tst.skipWS();\n\t\tif(st.front() == TT::Colon)\n\t\t{\n\t\t\t// the inheritance list.\n\t\t\tst.eat();\n\n\t\t\twhile(true)\n\t\t\t{\n\t\t\t\tdefn->bases.push_back(parseType(st));\n\t\t\t\tif(st.front() == TT::Comma)\n\t\t\t\t{\n\t\t\t\t\tst.pop();\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tst.skipWS();\n\t\tif(st.front() != TT::LBrace)\n\t\t\texpectedAfter(st, \"'{'\", \"'class'\", st.front().str());\n\n\t\tst.enterStructBody();\n\n\t\tauto blk = parseBracedBlock(st).val();\n\t\tfor(auto s : blk->statements)\n\t\t{\n\t\t\tif(auto v = dcast(VarDefn, s))\n\t\t\t{\n\t\t\t\tif(v->type == pts::InferredType::get())\n\t\t\t\t\terror(v, \"class fields must have types explicitly specified\");\n\n\t\t\t\tv->isField = true;\n\t\t\t\tdefn->fields.push_back(v);\n\t\t\t}\n\t\t\telse if(auto f = dcast(FuncDefn, s))\n\t\t\t{\n\t\t\t\taddSelfToMethod(f, f->isMutating);\n\t\t\t\tdefn->methods.push_back(f);\n\t\t\t}\n\t\t\telse if(auto t = dcast(TypeDefn, s))\n\t\t\t{\n\t\t\t\tdefn->nestedTypes.push_back(t);\n\t\t\t}\n\t\t\telse if(auto sd = dcast(StaticDecl, s))\n\t\t\t{\n\t\t\t\tif(auto fn = dcast(FuncDefn, sd->actual))\n\t\t\t\t\tdefn->staticMethods.push_back(fn);\n\n\t\t\t\telse if(auto vr = dcast(VarDefn, sd->actual))\n\t\t\t\t\tdefn->staticFields.push_back(vr);\n\n\t\t\t\telse\n\t\t\t\t\terror(st, \"unsupported static statement in class body\");\n\t\t\t}\n\t\t\telse if(auto init = dcast(InitFunctionDefn, s))\n\t\t\t{\n\t\t\t\taddSelfToMethod(init, /* mutating: */ true);\n\n\t\t\t\tif(init->name == \"init\")\n\t\t\t\t{\n\t\t\t\t\tdefn->initialisers.push_back(init);\n\t\t\t\t}\n\t\t\t\telse if(init->name == \"deinit\")\n\t\t\t\t{\n\t\t\t\t\tif(defn->deinitialiser)\n\t\t\t\t\t\terror(init, \"deinitialisers cannot be overloaded\");\n\n\t\t\t\t\tdefn->deinitialiser = init;\n\t\t\t\t}\n\t\t\t\telse if(init->name == \"copy\")\n\t\t\t\t{\n\t\t\t\t\tif(defn->copyInitialiser)\n\t\t\t\t\t\terror(init, \"copy initialisers cannot be overloaded\");\n\n\t\t\t\t\tdefn->copyInitialiser = init;\n\t\t\t\t}\n\t\t\t\telse if(init->name == \"move\")\n\t\t\t\t{\n\t\t\t\t\tif(defn->moveInitialiser)\n\t\t\t\t\t\terror(init, \"move initialisers cannot be overloaded\");\n\n\t\t\t\t\tdefn->moveInitialiser = init;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\terror(s, \"wtf? '%s'\", init->name);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\terror(s, \"unsupported expression or statement in class body\");\n\t\t\t}\n\t\t}\n\n\t\tif(!blk->deferredStatements.empty())\n\t\t\terror(blk->deferredStatements[0], \"unsupported expression or statement in class body\");\n\n\t\tst.leaveStructBody();\n\t\treturn defn;\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\tPResult<StructDefn> parseStruct(State& st, bool nameless)\n\t{\n\t\tstatic size_t anon_counter = 0;\n\n\t\ticeAssert(st.front() == TT::Struct);\n\t\tst.eat();\n\n\t\tStructDefn* defn = util::pool<StructDefn>(st.loc());\n\t\tif(nameless)\n\t\t{\n\t\t\tdefn->name = fir::obfuscateName(\"anon_struct\", anon_counter++);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif(st.front() == TT::LBrace)\n\t\t\t\terror(st, \"declared structs (in non-type usage) must be named\");\n\n\t\t\telse if(st.front() != TT::Identifier)\n\t\t\t\texpectedAfter(st, \"identifier\", \"'struct'\", st.front().str());\n\n\t\t\telse\n\t\t\t\tdefn->name = st.eat().str();\n\t\t}\n\n\n\t\t// check for generic function\n\t\tif(st.front() == TT::LAngle)\n\t\t{\n\t\t\tst.eat();\n\t\t\t// parse generic\n\t\t\tif(st.front() == TT::RAngle)\n\t\t\t\terror(st, \"empty type parameter lists are not allowed\");\n\n\t\t\tdefn->generics = parseGenericTypeList(st);\n\t\t}\n\n\t\tst.skipWS();\n\t\tif(st.front() == TT::Colon)\n\t\t{\n\t\t\t// the inheritance list.\n\t\t\tst.eat();\n\n\t\t\twhile(true)\n\t\t\t{\n\t\t\t\tdefn->bases.push_back(parseType(st));\n\t\t\t\tif(st.front() == TT::Comma)\n\t\t\t\t{\n\t\t\t\t\tst.pop();\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tst.skipWS();\n\t\tif(st.eat() != TT::LBrace)\n\t\t\texpectedAfter(st.ploc(), \"opening brace\", \"'struct'\", st.front().str());\n\n\t\tst.enterStructBody();\n\t\tst.skipWS();\n\n\t\tsize_t index = 0;\n\t\twhile(st.front() != TT::RBrace)\n\t\t{\n\t\t\tst.skipWS();\n\t\t\tif(!st.hasTokens())\n\t\t\t\treturn PResult<StructDefn>::insufficientTokensError();\n\n\t\t\tif(st.front() == TT::Identifier)\n\t\t\t{\n\t\t\t\tauto loc = st.loc();\n\t\t\t\tstd::string name = st.eat().str();\n\n\t\t\t\t// we can't check for duplicates when it's transparent, duh\n\t\t\t\t// we'll collapse and collect and check during typechecking.\n\t\t\t\tif(name != \"_\")\n\t\t\t\t{\n\t\t\t\t\tif(auto it = std::find_if(defn->fields.begin(), defn->fields.end(), [&name](const auto& p) -> bool {\n\t\t\t\t\t\treturn std::get<0>(p) == name;\n\t\t\t\t\t}); it != defn->fields.end())\n\t\t\t\t\t{\n\t\t\t\t\t\tSimpleError::make(loc, \"duplicate field '%s' in struct definition\", name)\n\t\t\t\t\t\t\t->append(SimpleError::make(MsgType::Note, std::get<1>(*it), \"field '%s' previously defined here:\", name))\n\t\t\t\t\t\t\t->postAndQuit();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(st.eat() != TT::Colon)\n\t\t\t\t\terror(st.ploc(), \"expected type specifier after field name in struct\");\n\n\t\t\t\tpts::Type* type = parseType(st);\n\t\t\t\tdefn->fields.push_back(std::make_tuple(name, loc, type));\n\n\t\t\t\tif(st.front() == TT::Equal)\n\t\t\t\t\terror(st.loc(), \"struct fields cannot have initialisers\");\n\t\t\t}\n\t\t\telse if(st.front() == TT::Func)\n\t\t\t{\n\t\t\t\t// ok parse a func as usual\n\t\t\t\tauto method = parseFunction(st).val();\n\t\t\t\taddSelfToMethod(method, method->isMutating);\n\n\t\t\t\tdefn->methods.push_back(method);\n\t\t\t}\n\t\t\telse if(st.front() == TT::Var || st.front() == TT::Val)\n\t\t\t{\n\t\t\t\terror(st.loc(), \"struct fields are declared as 'name: type'; val/let is omitted\");\n\t\t\t}\n\t\t\telse if(st.front() == TT::Static)\n\t\t\t{\n\t\t\t\terror(st.loc(), \"structs cannot have static declarations\");\n\t\t\t}\n\t\t\telse if(st.front() == TT::NewLine || st.front() == TT::Semicolon)\n\t\t\t{\n\t\t\t\tst.pop();\n\t\t\t}\n\t\t\telse if(st.front() == TT::RBrace)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\terror(st.loc(), \"unexpected token '%s' (%d) inside struct body\", st.front().str(), st.front().type);\n\t\t\t}\n\n\t\t\tindex++;\n\t\t}\n\n\t\ticeAssert(st.front() == TT::RBrace);\n\t\tst.eat();\n\n\t\tst.leaveStructBody();\n\t\treturn defn;\n\t}\n\n\n\tUnionDefn* parseUnion(State& st, bool israw, bool nameless)\n\t{\n\t\tstatic size_t anon_counter = 0;\n\t\ticeAssert(st.front() == TT::Union);\n\t\tst.eat();\n\n\t\tUnionDefn* defn = util::pool<UnionDefn>(st.loc());\n\t\tif(nameless)\n\t\t{\n\t\t\tdefn->name = fir::obfuscateName(\"anon_union\", anon_counter++);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif(st.front() == TT::LBrace)\n\t\t\t\terror(st, \"declared unions (in non-type usage) must be named\");\n\n\t\t\telse if(st.front() != TT::Identifier)\n\t\t\t\texpectedAfter(st, \"identifier\", \"'union'\", st.front().str());\n\n\t\t\telse\n\t\t\t\tdefn->name = st.eat().str();\n\t\t}\n\n\n\t\t// check for generic function\n\t\tif(st.front() == TT::LAngle)\n\t\t{\n\t\t\tst.eat();\n\t\t\t// parse generic\n\t\t\tif(st.front() == TT::RAngle)\n\t\t\t\terror(st, \"empty type parameter lists are not allowed\");\n\n\t\t\tdefn->generics = parseGenericTypeList(st);\n\t\t}\n\n\t\t// unions don't inherit stuff (for now????) so we don't check for it.\n\n\t\tst.skipWS();\n\t\tif(st.eat() != TT::LBrace)\n\t\t\texpectedAfter(st.ploc(), \"opening brace\", \"'union'\", st.front().str());\n\n\t\tst.skipWS();\n\t\tif(st.front() == TT::RBrace)\n\t\t\terror(st, \"union must contain at least one variant\");\n\n\t\tsize_t index = 0;\n\t\twhile(st.front() != TT::RBrace)\n\t\t{\n\t\t\tst.skipWS();\n\n\t\t\tif(st.front() != TT::Identifier)\n\t\t\t{\n\t\t\t\tif(st.front() == TT::Var || st.front() == TT::Val)\n\t\t\t\t\terror(st.loc(), \"union fields are declared as 'name: type'; val/let is omitted\");\n\n\t\t\t\telse\n\t\t\t\t\texpected(st.loc(), \"identifier inside union body\", st.front().str());\n\t\t\t}\n\n\t\t\tauto loc = st.loc();\n\t\t\tpts::Type* type = 0;\n\t\t\tstd::string name = st.eat().str();\n\n\t\t\t// to improve code flow, handle the type first.\n\t\t\tif(st.front() == TT::Colon)\n\t\t\t{\n\t\t\t\tst.eat();\n\t\t\t\ttype = parseType(st);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif(israw)\n\t\t\t\t\terror(st.loc(), \"raw unions cannot have empty variants (must have a type)\");\n\n\t\t\t\telse if(st.front() != TT::NewLine)\n\t\t\t\t\terror(st.loc(), \"expected newline after union variant\");\n\t\t\t}\n\n\t\t\tif(name == \"_\")\n\t\t\t{\n\t\t\t\tif(!israw)\n\t\t\t\t\terror(loc, \"transparent fields can only be present in raw unions\");\n\n\t\t\t\ticeAssert(type);\n\t\t\t\tdefn->transparentFields.push_back({ loc, type });\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif(auto it = defn->cases.find(name); it != defn->cases.end())\n\t\t\t\t{\n\t\t\t\t\tSimpleError::make(loc, \"duplicate variant '%s' in union definition\", name)\n\t\t\t\t\t\t->append(SimpleError::make(MsgType::Note, std::get<1>(it->second), \"variant '%s' previously defined here:\", name))\n\t\t\t\t\t\t->postAndQuit();\n\t\t\t\t}\n\n\t\t\t\tif(type == nullptr) type = pts::NamedType::create(loc, VOID_TYPE_STRING);\n\t\t\t\tdefn->cases[name] = { index, loc, type };\n\t\t\t}\n\n\t\t\t// do some things\n\t\t\tif(st.front() == TT::NewLine || st.front() == TT::Semicolon)\n\t\t\t{\n\t\t\t\tst.pop();\n\t\t\t}\n\t\t\telse if(st.front() == TT::RBrace)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\terror(st.loc(), \"unexpected token '%s' inside union body\", st.front().str());\n\t\t\t}\n\n\t\t\tindex++;\n\t\t}\n\n\t\ticeAssert(st.front() == TT::RBrace);\n\t\tst.eat();\n\n\t\tif(israw)\n\t\t\tdefn->attrs.set(attr::RAW);\n\n\t\treturn defn;\n\t}\n\n\n\n\n\tEnumDefn* parseEnum(State& st)\n\t{\n\t\ticeAssert(st.front() == TT::Enum);\n\t\tst.eat();\n\n\t\tif(st.front() != TT::Identifier)\n\t\t\texpectedAfter(st, \"identifier\", \"'enum'\", st.front().str());\n\n\t\tauto idloc = st.loc();\n\t\tstd::string name = st.eat().str();\n\t\tpts::Type* memberType = 0;\n\n\t\tif(st.front() == TT::Colon)\n\t\t{\n\t\t\tst.eat();\n\t\t\tmemberType = parseType(st);\n\t\t}\n\n\t\t// ok...\n\t\tst.skipWS();\n\t\tif(st.eat() != TT::LBrace)\n\t\t\texpectedAfter(st.ploc(), \"opening brace\", \"'enum'\", st.front().str());\n\n\t\tbool hadValue = false;\n\t\tstd::vector<EnumDefn::Case> cases;\n\t\twhile(st.front() != TT::RBrace)\n\t\t{\n\t\t\tst.skipWS();\n\n\t\t\tif(st.front() == TT::RBrace)\n\t\t\t\tbreak;\n\n\t\t\tif(st.eat() != TT::Case)\n\t\t\t\texpected(st.ploc(), \"'case' inside enum body\", st.prev().str());\n\n\t\t\tif(st.front() != TT::Identifier)\n\t\t\t\texpectedAfter(st.loc(), \"identifier\", \"'case' in enum body\", st.front().str());\n\n\t\t\tstd::string cn = st.eat().str();\n\t\t\tExpr* value = 0;\n\n\t\t\tif(st.frontAfterWS() == TT::Equal)\n\t\t\t{\n\t\t\t\tif(memberType == 0)\n\t\t\t\t{\n\t\t\t\t\tSimpleError::make(st.loc(), \"enumeration member type must be specified when assigning explicit values to cases\")\n\t\t\t\t\t\t->append(SimpleError::make(MsgType::Note, idloc, \"add the type here\"))\n\t\t\t\t\t\t->postAndQuit();\n\t\t\t\t}\n\n\t\t\t\t// ok, parse a value\n\t\t\t\tst.eat();\n\t\t\t\tvalue = parseExpr(st);\n\n\t\t\t\thadValue = true;\n\t\t\t}\n\t\t\telse if(hadValue)\n\t\t\t{\n\t\t\t\t//? this is mostly because we don't want to deal with auto-incrementing stuff\n\t\t\t\terror(st.loc(), \"enumeration cases must either all have no values, or all have values; a mix is not allowed.\");\n\t\t\t}\n\n\t\t\t// ok.\n\t\t\tcases.push_back(EnumDefn::Case { st.loc(), cn, value });\n\n\t\t\t// do some things\n\t\t\tif(st.front() == TT::NewLine || st.front() == TT::Semicolon)\n\t\t\t{\n\t\t\t\tst.pop();\n\t\t\t}\n\t\t\telse if(st.front() == TT::RBrace)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\terror(st.loc(), \"unexpected token '%s' inside enum body\", st.front().str());\n\t\t\t}\n\t\t}\n\n\t\ticeAssert(st.front() == TT::RBrace);\n\t\tst.eat();\n\n\t\tauto ret = util::pool<EnumDefn>(idloc);\n\t\tret->name = name;\n\t\tret->cases = cases;\n\t\tret->memberType = memberType;\n\n\n\t\treturn ret;\n\t}\n\n\n\n\tTraitDefn* parseTrait(State& st)\n\t{\n\t\ticeAssert(st.front() == TT::Trait);\n\t\tst.eat();\n\n\t\tif(st.front() != TT::Identifier)\n\t\t\texpectedAfter(st, \"identifier\", \"'trait'\", st.front().str());\n\n\t\tTraitDefn* defn = util::pool<TraitDefn>(st.loc());\n\t\tdefn->name = st.eat().str();\n\n\t\tst.skipWS();\n\t\tif(st.front() == TT::Colon)\n\t\t{\n\t\t\t// the inheritance list.\n\t\t\tst.eat();\n\n\t\t\twhile(true)\n\t\t\t{\n\t\t\t\tdefn->bases.push_back(parseType(st));\n\t\t\t\tif(st.front() == TT::Comma)\n\t\t\t\t{\n\t\t\t\t\tst.pop();\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// ok...\n\t\tst.skipWS();\n\t\tif(st.eat() != TT::LBrace)\n\t\t\texpectedAfter(st.ploc(), \"opening brace\", \"'trait'\", st.front().str());\n\n\t\tst.enterStructBody();\n\t\tst.skipWS();\n\n\t\tsize_t index = 0;\n\t\twhile(st.front() != TT::RBrace)\n\t\t{\n\t\t\tst.skipWS();\n\n\t\t\tif(st.front() == TT::Func)\n\t\t\t{\n\t\t\t\t// ok parse a func as usual\n\t\t\t\tauto [ method, isvar, varloc ] = parseFunctionDecl(st);\n\t\t\t\tif(isvar)\n\t\t\t\t\terror(varloc, \"C-style variadic arguments are not supported on non-foreign functions\");\n\n\t\t\t\taddSelfToMethod(method, method->isMutating);\n\t\t\t\tdefn->methods.push_back(method);\n\t\t\t}\n\t\t\telse if(st.front() == TT::Var || st.front() == TT::Val)\n\t\t\t{\n\t\t\t\terror(st.loc(), \"traits cannot contain fields\");\n\t\t\t}\n\t\t\telse if(st.front() == TT::Static)\n\t\t\t{\n\t\t\t\terror(st.loc(), \"traits cannot contain static declarations\");\n\t\t\t}\n\t\t\telse if(st.front() == TT::NewLine || st.front() == TT::Semicolon)\n\t\t\t{\n\t\t\t\tst.pop();\n\t\t\t}\n\t\t\telse if(st.front() == TT::RBrace)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\terror(st.loc(), \"unexpected token '%s' inside trait body\", st.front().str());\n\t\t\t}\n\n\t\t\tindex++;\n\t\t}\n\n\t\ticeAssert(st.front() == TT::RBrace);\n\t\tst.eat();\n\n\t\tst.leaveStructBody();\n\t\treturn defn;\n\t}\n\n\n\n\n\n\n\tStaticDecl* parseStaticDecl(State& st)\n\t{\n\t\ticeAssert(st.front() == TT::Static);\n\t\tst.eat();\n\n\t\tauto stmt = parseStmt(st).val();\n\t\tif(dcast(FuncDefn, stmt) || dcast(VarDefn, stmt))\n\t\t\treturn util::pool<StaticDecl>(stmt);\n\n\t\telse\n\t\t\terror(stmt, \"'static' can only be used on function and field definitions inside class bodies\");\n\t}\n\n\n\n\n\n\tpts::Type* parseType(State& st)\n\t{\n\t\tusing TT = lexer::TokenType;\n\t\tif(st.front() == TT::Ampersand)\n\t\t{\n\t\t\tauto l = st.loc();\n\t\t\tst.pop();\n\n\t\t\t// check for mutability.\n\t\t\tbool mut = st.front() == TT::Mutable;\n\t\t\tif(mut) st.pop();\n\n\t\t\tauto base = parseType(st);\n\t\t\tl.len = base->loc.col - l.col + base->loc.len;\n\n\t\t\treturn util::pool<pts::PointerType>(l, base, mut);\n\t\t}\n\t\telse if(st.front() == TT::LogicalAnd)\n\t\t{\n\t\t\t// lmao.\n\t\t\tauto l = st.loc();\n\t\t\tst.pop();\n\n\t\t\tbool mut = st.front() == TT::Mutable;\n\t\t\tif(mut) st.pop();\n\n\t\t\t//* note: this handles cases like & (&mut T)\n\t\t\t//* so, the outer pointer is never mutable, but the inner one might be.\n\n\t\t\tauto base = parseType(st);\n\t\t\tl.len = base->loc.col - l.col + base->loc.len;\n\n\t\t\treturn util::pool<pts::PointerType>(l, util::pool<pts::PointerType>(l, base, mut), false);\n\t\t}\n\t\telse if(st.front() == TT::LSquare)\n\t\t{\n\t\t\t// [T] is a dynamic array\n\t\t\t// [T:] is a slice\n\t\t\t// [T: N] is a fixed array of size 'N'\n\n\t\t\tauto loc = st.loc();\n\n\t\t\tst.pop();\n\n\t\t\tbool mut = false;\n\t\t\tif(st.front() == TT::Mutable)\n\t\t\t\tmut = true, st.pop();\n\n\t\t\tauto elm = parseType(st);\n\n\t\t\tif(st.front() == TT::Colon)\n\t\t\t{\n\t\t\t\tst.pop();\n\t\t\t\tif(st.front() == TT::RSquare)\n\t\t\t\t{\n\t\t\t\t\tloc.len = st.loc().col - loc.col + st.loc().len;\n\t\t\t\t\tst.pop();\n\t\t\t\t\treturn util::pool<pts::ArraySliceType>(loc, elm, mut);\n\t\t\t\t}\n\t\t\t\telse if(st.front() == TT::Ellipsis)\n\t\t\t\t{\n\t\t\t\t\tst.pop();\n\t\t\t\t\tloc.len = st.loc().col - loc.col + st.loc().len;\n\n\t\t\t\t\tif(st.pop() != TT::RSquare)\n\t\t\t\t\t\texpectedAfter(st, \"']'\", \"... in variadic array type\", st.front().str());\n\n\t\t\t\t\treturn util::pool<pts::VariadicArrayType>(loc, elm);\n\t\t\t\t}\n\t\t\t\telse if(st.front() != TT::Number)\n\t\t\t\t{\n\t\t\t\t\texpected(st, \"positive, non-zero size for fixed array\", st.front().str());\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tlong sz = std::stol(st.front().str());\n\t\t\t\t\tif(sz <= 0)\n\t\t\t\t\t\texpected(st, \"positive, non-zero size for fixed array\", st.front().str());\n\n\t\t\t\t\tst.pop();\n\t\t\t\t\tloc.len = st.loc().col - loc.col + st.loc().len;\n\n\t\t\t\t\tif(st.eat() != TT::RSquare)\n\t\t\t\t\t\texpectedAfter(st, \"closing ']'\", \"array type\", st.front().str());\n\n\t\t\t\t\t//! ACHTUNG !\n\t\t\t\t\t// TODO: support mutable arrays??\n\t\t\t\t\treturn util::pool<pts::FixedArrayType>(loc, elm, sz);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(st.front() == TT::RSquare)\n\t\t\t{\n\t\t\t\t// dynamic array.\n\t\t\t\tif(mut) error(st.loc(), \"dynamic arrays are always mutable, specifying 'mut' is unnecessary\");\n\n\t\t\t\tloc.len = st.loc().col - loc.col + st.loc().len;\n\n\t\t\t\tst.pop();\n\t\t\t\treturn util::pool<pts::DynamicArrayType>(loc, elm);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\texpected(st.loc(), \"']' in array type specifier\", st.front().str());\n\t\t\t}\n\t\t}\n\t\telse if(st.front() == TT::Identifier || st.front() == TT::DoubleColon || st.front() == TT::Caret)\n\t\t{\n\t\t\tif(st.front() == TT::Caret && st.lookahead(1) != TT::DoubleColon)\n\t\t\t\terror(st, \"'^' in type specifier must be followed by '::' (to specify parent scope)\");\n\n\t\t\tauto loc = st.loc();\n\t\t\tstd::string s = st.eat().str();\n\n\t\t\twhile(st.hasTokens())\n\t\t\t{\n\t\t\t\tif(st.front() == TT::DoubleColon)\n\t\t\t\t{\n\t\t\t\t\ts += st.eat().str();\n\t\t\t\t}\n\t\t\t\telse if(st.front() == TT::Caret)\n\t\t\t\t{\n\t\t\t\t\ts += st.eat().str();\n\t\t\t\t\tif(st.front() != TT::DoubleColon)\n\t\t\t\t\t\terror(st, \"expected '::' after '^' in scope path\");\n\t\t\t\t}\n\t\t\t\telse if(st.front() == TT::Identifier)\n\t\t\t\t{\n\t\t\t\t\tif(s.back() != ':')\n\t\t\t\t\t\terror(st, \"unexpected identifer '%s' in type\", st.front().str());\n\n\t\t\t\t\telse\n\t\t\t\t\t\ts += st.eat().str();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// check generic mapping\n\t\t\tPolyArgMapping_t pams;\n\t\t\tif(st.front() == TT::Exclamation && st.lookahead(1) == TT::LAngle)\n\t\t\t{\n\t\t\t\t//? note: if *failed is nullptr, then we will throw errors where we usually would return.\n\t\t\t\tpams = parsePAMs(st, /* fail: */ nullptr);\n\t\t\t}\n\n\t\t\tloc.len = st.ploc().col - loc.col + st.ploc().len;\n\t\t\treturn pts::NamedType::create(loc, s, pams);\n\t\t}\n\t\telse if(auto isfn = (st.front() == TT::Func); st.front() == TT::LParen || st.front() == TT::Func)\n\t\t{\n\t\t\t// tuple or function\n\t\t\tauto loc = st.loc();\n\n\t\t\tst.pop();\n\n\t\t\tif(isfn) st.pop();\n\n\t\t\t// parse a tuple.\n\t\t\tstd::vector<pts::Type*> types;\n\t\t\twhile(st.hasTokens() && st.front().type != TT::RParen)\n\t\t\t{\n\t\t\t\t// do things.\n\t\t\t\tauto ty = parseType(st);\n\n\t\t\t\tif(st.front() != TT::Comma && st.front() != TT::RParen)\n\t\t\t\t\terror(st, \"unexpected token '%s' in type specifier, expected either ',' or ')'\", st.front().str());\n\n\t\t\t\telse if(st.front() == TT::Comma)\n\t\t\t\t\tst.eat();\n\n\t\t\t\ttypes.push_back(ty);\n\t\t\t}\n\n\t\t\tloc.len = st.loc().col - loc.col + st.loc().len;\n\t\t\tif(st.eat().type != TT::RParen)\n\t\t\t\texpected(st, \"')' to end type list\", st.prev().str());\n\n\n\t\t\tif(isfn)\n\t\t\t{\n\t\t\t\tif(st.front() != TT::RightArrow)\n\t\t\t\t\texpected(st, \"'->' in function type specifier after parameter types\", st.front().str());\n\n\t\t\t\tst.eat();\n\n\t\t\t\t// eat the arrow, parse the type\n\t\t\t\tauto retty = parseType(st);\n\n\t\t\t\tloc.len = st.ploc().col - loc.col + st.ploc().len;\n\n\t\t\t\treturn util::pool<pts::FunctionType>(loc, types, retty);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// this *should* allow us to 'group' types together\n\t\t\t\t// eg. ((i64, i64) -> i64)[] would allow us to create an array of functions\n\t\t\t\t// whereas (i64, i64) -> i64[] would parse as a function returning an array of i64s.\n\n\t\t\t\tif(types.size() == 0)\n\t\t\t\t\terror(st, \"empty tuples '()' are not supported\");\n\n\t\t\t\telse if(types.size() == 1)\n\t\t\t\t\treturn types[0];\n\n\t\t\t\treturn util::pool<pts::TupleType>(loc, types);\n\t\t\t}\n\t\t}\n\t\telse if(st.front() == TT::Struct)\n\t\t{\n\t\t\tauto str = parseStruct(st, /* nameless: */ true).val();\n\t\t\tst.anonymousTypeDefns.push_back(str);\n\n\t\t\treturn pts::NamedType::create(str->loc, str->name);\n\t\t}\n\t\telse if(st.front() == TT::Union || (st.front() == TT::Attr_Raw && st.lookahead(1) == TT::Union))\n\t\t{\n\t\t\tbool israw = st.front() == TT::Attr_Raw;\n\t\t\tif(israw) st.eat();\n\n\t\t\tauto unn = parseUnion(st, israw, /* nameless: */ true);\n\t\t\tst.anonymousTypeDefns.push_back(unn);\n\n\t\t\treturn pts::NamedType::create(unn->loc, unn->name);\n\t\t}\n\t\telse if(st.front() == TT::Class)\n\t\t{\n\t\t\terror(st, \"classes cannot be defined anonymously\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(st, \"unexpected token '%s' while parsing type\", st.front().str());\n\t\t}\n\t}\n\n\n\t// PAM == PolyArgMapping\n\tPolyArgMapping_t parsePAMs(State& st, bool* failed)\n\t{\n\t\ticeAssert(st.front() == TT::Exclamation && st.lookahead(1) == TT::LAngle);\n\t\tauto openLoc = st.loc();\n\n\t\tst.pop();\n\t\tst.pop();\n\n\t\tstd::unordered_set<std::string> seen;\n\t\tPolyArgMapping_t mappings;\n\t\t{\n\t\t\t//* foo!<> is an error regardless of whether we're doing expression parsing or call parsing.\n\t\t\tif(st.front() == TT::RAngle)\n\t\t\t\terror(Location::unionOf(openLoc, st.loc()), \"type parameter list cannot be empty\");\n\n\t\t\t// step 2A: start parsing.\n\t\t\tsize_t idx = 0;\n\t\t\twhile(st.front() != TT::RAngle)\n\t\t\t{\n\t\t\t\tif(st.front() != TT::Identifier)\n\t\t\t\t{\n\t\t\t\t\tif(failed)\n\t\t\t\t\t{\n\t\t\t\t\t\t*failed = true;\n\t\t\t\t\t\treturn mappings;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\texpected(st.loc(), \"identifier in type argument list\", st.front().str());\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(st.front() == TT::Identifier && st.lookahead(1) == TT::Colon)\n\t\t\t\t{\n\t\t\t\t\tauto id = st.pop().str();\n\t\t\t\t\tst.pop();\n\n\t\t\t\t\t//? I think beyond this point we pretty much can't fail since we have the colon.\n\t\t\t\t\t//? so, we shouldn't need to handle the case where we fail to parse a type here.\n\t\t\t\t\tif(seen.find(id) != seen.end())\n\t\t\t\t\t\terror(st.loc(), \"duplicate type argument '%s'\", id);\n\n\t\t\t\t\tauto ty = parseType(st);\n\t\t\t\t\tmappings.add(id, ty);\n\t\t\t\t\tseen.insert(id);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif(!seen.empty())\n\t\t\t\t\t\terror(st.loc(), \"cannot have positional type arguments after named arguments\");\n\n\t\t\t\t\tauto ty = parseType(st);\n\t\t\t\t\tmappings.add(idx++, ty);\n\t\t\t\t}\n\n\t\t\t\tif(st.front() == TT::Comma)\n\t\t\t\t\tst.pop();\n\n\t\t\t\telse if(st.front() != TT::RAngle)\n\t\t\t\t\texpected(st.loc(), \"',' or '>' in type argument list\", st.front().str());\n\t\t\t}\n\n\t\t\ticeAssert(st.front() == TT::RAngle);\n\t\t\tst.pop();\n\n\t\t\treturn mappings;\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/frontend/parser/variable.cpp",
    "content": "// variable.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"pts.h\"\n#include \"parser_internal.h\"\n\n#include \"memorypool.h\"\n\n#include <set>\n\nusing namespace ast;\nusing namespace lexer;\n\nnamespace parser\n{\n\tstatic DecompMapping recursivelyParseDecomp(State& st)\n\t{\n\t\tusing TT = lexer::TokenType;\n\t\tDecompMapping outer;\n\n\t\touter.loc = st.loc();\n\n\t\ticeAssert(st.front() == TT::LSquare || st.front() == TT::LParen);\n\t\tif(st.pop() == TT::LSquare)\n\t\t\touter.array = true;\n\n\t\tbool didRest = false;\n\t\twhile(st.front() != (outer.array ? TT::RSquare : TT::RParen))\n\t\t{\n\t\t\tDecompMapping inside;\n\t\t\tinside.loc = st.loc();\n\n\t\t\tif(st.front() == TT::Ampersand)\n\t\t\t\tinside.ref = true, st.pop();\n\n\t\t\tif(st.front() == TT::LParen || st.front() == TT::LSquare)\n\t\t\t{\n\t\t\t\tif(inside.ref) error(st, \"cannot bind by reference in nested decomposition; modify the binding type for each identifier\");\n\n\t\t\t\touter.inner.push_back(recursivelyParseDecomp(st));\n\t\t\t}\n\t\t\telse if(st.front() == TT::Ellipsis)\n\t\t\t{\n\t\t\t\tif(!outer.array)    error(st, \"'...' cannot be used in a tuple destructure\");\n\t\t\t\telse if(didRest)    error(st, \"'...' must be the last binding in an array destructure\");\n\t\t\t\telse if(inside.ref) error(st, \"invalid use of '&' before '...' binding\");\n\n\t\t\t\tst.pop();\n\t\t\t\tif(st.front() == TT::Ampersand)\n\t\t\t\t\touter.restRef = true, st.pop();\n\n\t\t\t\tif(st.front() == TT::Identifier)\n\t\t\t\t\touter.restName = st.front().str(), st.pop();\n\n\t\t\t\tif(outer.restName == \"_\" && outer.restRef)\n\t\t\t\t\terror(st.ploc(), \"invalid combination of '_' and '&'\");\n\n\t\t\t\tdidRest = true;\n\t\t\t}\n\t\t\telse if(st.front() == TT::Identifier)\n\t\t\t{\n\t\t\t\tinside.name = st.pop().str();\n\t\t\t\tif(inside.name == \"_\" && inside.ref)\n\t\t\t\t\terror(st.loc(), \"invalid combination of '_' and '&'\");\n\n\t\t\t\touter.inner.push_back(inside);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\texpected(st.loc(), \"identifier or '...' in destructuring declaration\", st.front().str());\n\t\t\t}\n\n\t\t\tif(st.front() != TT::Comma && st.front() != (outer.array ? TT::RSquare : TT::RParen))\n\t\t\t\texpected(st, \"')', ']' or ',' in destructuring declaration\", st.front().str());\n\n\t\t\tif(st.front() == TT::Comma)\n\t\t\t\tst.pop();\n\t\t}\n\n\t\tif(outer.array && !didRest)\n\t\t\terror(st, \"'...' is mandatory for array destructuring, regardless of binding\");\n\n\t\ticeAssert(st.front() == (outer.array ? TT::RSquare : TT::RParen));\n\t\tst.pop();\n\n\t\treturn outer;\n\t}\n\n\n\n\tDecompVarDefn* parseDecompDecl(State& st)\n\t{\n\t\tusing TT = lexer::TokenType;\n\t\ticeAssert(st.front() == TT::LSquare || st.front() == TT::LParen);\n\n\t\tauto decomp = util::pool<DecompVarDefn>(st.loc());\n\t\tdecomp->bindings = recursivelyParseDecomp(st);\n\n\t\t// we need to ensure there're no duplicate names.\n\t\tstd::function<void (const DecompMapping& dm, std::map<std::string, Location>& names)> visit;\n\n\t\tvisit = [&visit](const DecompMapping& dm, std::map<std::string, Location>& seen) -> void {\n\n\t\t\tif(!dm.name.empty() && dm.name != \"_\")\n\t\t\t{\n\t\t\t\tif(seen.find(dm.name) != seen.end())\n\t\t\t\t{\n\t\t\t\t\tSimpleError::make(dm.loc, \"duplicate binding '%s' in destructuring declaration\", dm.name)\n\t\t\t\t\t\t->append(SimpleError::make(MsgType::Note, seen[dm.name], \"previous binding was here:\"))\n\t\t\t\t\t\t->postAndQuit();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tseen[dm.name] = dm.loc;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(dm.name.empty())\n\t\t\t{\n\t\t\t\tfor(const auto& b : dm.inner)\n\t\t\t\t\tvisit(b, seen);\n\t\t\t}\n\t\t};\n\n\t\tstd::map<std::string, Location> seen;\n\t\tvisit(decomp->bindings, seen);\n\n\t\tif(st.front() != TT::Equal)\n\t\t\texpected(st, \"'=' for assignment to decomposition\", st.front().str());\n\n\t\tst.pop();\n\t\tdecomp->initialiser = parseExpr(st);\n\n\t\treturn decomp;\n\t}\n\n\tDecompMapping parseTupleDecomp(State& st)\n\t{\n\t\treturn recursivelyParseDecomp(st);\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tStmt* parseVariable(State& st)\n\t{\n\t\tusing TT = lexer::TokenType;\n\n\t\ticeAssert(st.front() == TT::Var || st.front() == TT::Val);\n\n\t\tbool isImmut = (st.eat() == TT::Val);\n\t\tif(st.front() == TT::LParen || st.front() == TT::LSquare)\n\t\t{\n\t\t\tauto ret = parseDecompDecl(st);\n\t\t\tret->immut = isImmut;\n\n\t\t\treturn ret;\n\t\t}\n\t\telse if(st.front() != TT::Identifier)\n\t\t{\n\t\t\texpectedAfter(st, \"identifier\", \"'\" + std::string(isImmut ? \"let\" : \"var\") + \"'\", st.front().str());\n\t\t}\n\n\t\tauto loc = st.front().loc;\n\n\t\tstd::string name = st.eat().str();\n\t\tpts::Type* type = pts::InferredType::get();\n\t\tExpr* value = 0;\n\n\t\tif(st.front() == TT::Colon)\n\t\t{\n\t\t\tst.pop();\n\t\t\ttype = parseType(st);\n\t\t}\n\t\telse if(st.front() != TT::Equal)\n\t\t{\n\t\t\terror(st, \"expected initial value for type inference on variable '%s'\", name);\n\t\t}\n\n\t\tif(st.front() == TT::Equal)\n\t\t{\n\t\t\tst.pop();\n\t\t\tvalue = parseExpr(st);\n\t\t}\n\t\telse if(isImmut)\n\t\t{\n\t\t\terror(st, \"expected initial value for immutable variable '%s'\", name);\n\t\t}\n\n\t\tauto ret = util::pool<VarDefn>(loc);\n\t\tret->initialiser = value;\n\t\tret->immut = isImmut;\n\t\tret->type = type;\n\t\tret->name = name;\n\n\t\treturn ret;\n\t}\n\n\n\n}\n"
  },
  {
    "path": "source/frontend/pts.cpp",
    "content": "// pts.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"pts.h\"\n#include \"memorypool.h\"\n\nnamespace pts\n{\n\tstd::string unwrapPointerType(const std::string& type, int* _indirections)\n\t{\n\t\tstd::string sptr = \"*\";\n\t\tsize_t ptrStrLength = sptr.length();\n\n\t\tint tmp = 0;\n\t\tif(!_indirections)\n\t\t\t_indirections = &tmp;\n\n\t\tstd::string actualType = type;\n\t\tif(actualType.length() > ptrStrLength && std::equal(sptr.rbegin(), sptr.rend(), actualType.rbegin()))\n\t\t{\n\t\t\tint& indirections = *_indirections;\n\n\t\t\twhile(actualType.length() > ptrStrLength && std::equal(sptr.rbegin(), sptr.rend(), actualType.rbegin()))\n\t\t\t\tactualType = actualType.substr(0, actualType.length() - ptrStrLength), indirections++;\n\t\t}\n\n\t\treturn actualType;\n\t}\n\n\n\n\n\tNamedType* Type::toNamedType()\n\t{\n\t\treturn dcast(NamedType, this);\n\t}\n\n\tPointerType* Type::toPointerType()\n\t{\n\t\treturn dcast(PointerType, this);\n\t}\n\n\tTupleType* Type::toTupleType()\n\t{\n\t\treturn dcast(TupleType, this);\n\t}\n\n\tFixedArrayType* Type::toFixedArrayType()\n\t{\n\t\treturn dcast(FixedArrayType, this);\n\t}\n\n\tDynamicArrayType* Type::toDynamicArrayType()\n\t{\n\t\treturn dcast(DynamicArrayType, this);\n\t}\n\n\tVariadicArrayType* Type::toVariadicArrayType()\n\t{\n\t\treturn dcast(VariadicArrayType, this);\n\t}\n\n\tFunctionType* Type::toFunctionType()\n\t{\n\t\treturn dcast(FunctionType, this);\n\t}\n\n\tArraySliceType* Type::toArraySliceType()\n\t{\n\t\treturn dcast(ArraySliceType, this);\n\t}\n\n\n\tbool Type::isNamedType()\n\t{\n\t\treturn dcast(NamedType, this) != 0;\n\t}\n\n\tbool Type::isPointerType()\n\t{\n\t\treturn dcast(PointerType, this) != 0;\n\t}\n\n\tbool Type::isTupleType()\n\t{\n\t\treturn dcast(TupleType, this) != 0;\n\t}\n\n\tbool Type::isFixedArrayType()\n\t{\n\t\treturn dcast(FixedArrayType, this) != 0;\n\t}\n\n\tbool Type::isDynamicArrayType()\n\t{\n\t\treturn dcast(DynamicArrayType, this) != 0;\n\t}\n\n\tbool Type::isVariadicArrayType()\n\t{\n\t\treturn dcast(VariadicArrayType, this) != 0;\n\t}\n\n\tbool Type::isFunctionType()\n\t{\n\t\treturn dcast(FunctionType, this) != 0;\n\t}\n\n\tbool Type::isArraySliceType()\n\t{\n\t\treturn dcast(ArraySliceType, this) != 0;\n\t}\n\n\n\n\n\tstd::string Type::str()\n\t{\n\t\treturn \"??\";\n\t}\n\n\n\tstatic InferredType* it = 0;\n\tInferredType* InferredType::get()\n\t{\n\t\tif(it) return it;\n\t\treturn (it = util::pool<InferredType>(Location()));\n\t}\n\n\tNamedType* NamedType::create(const Location& l, const std::string& s)\n\t{\n\t\treturn NamedType::create(l, s, { });\n\t}\n\n\tNamedType* NamedType::create(const Location& l, const std::string& s, const PolyArgMapping_t& tm)\n\t{\n\t\tauto ret = util::pool<NamedType>(l, s);\n\t\tret->genericMapping = tm;\n\n\t\treturn ret;\n\t}\n\n\n\n\t// these shits are supposed to be reversibly-parse-able, so omit any \"beautification\" spaces and whatnot.\n\tstd::string NamedType::str()\n\t{\n\t\tauto ret = this->name;\n\n\t\tif(!this->genericMapping.empty())\n\t\t{\n\t\t\tstd::string m;\n\t\t\tfor(auto p : this->genericMapping.maps)\n\t\t\t\tm += strprintf(\"%s: %s, \", p.name.empty() ? std::to_string(p.index) : p.name, p.type->str());\n\n\t\t\tif(this->genericMapping.maps.size() > 0)\n\t\t\t\tm.pop_back(), m.pop_back();\n\n\t\t\tret += \"<\" + m + \">\";\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\tstd::string PointerType::str()\n\t{\n\t\treturn (this->isMutable ? \"&mut \" : \"&\") + this->base->str();\n\t}\n\n\tstd::string TupleType::str()\n\t{\n\t\tstd::string ret = \"(\";\n\t\tfor(auto t : this->types)\n\t\t\tret += t->str() + \", \";\n\n\t\tif(this->types.size() > 0)\n\t\t\tret.pop_back(), ret.pop_back();\n\n\t\treturn ret + \")\";\n\t}\n\n\tstd::string FixedArrayType::str()\n\t{\n\t\tstd::string b = this->base->str();\n\t\tif(this->base->isFunctionType())\n\t\t\tb = \"(\" + b + \")\";\n\n\t\treturn strprintf(\"[%s: %d]\", b, std::to_string(this->size));\n\t}\n\n\tstd::string DynamicArrayType::str()\n\t{\n\t\tstd::string b = this->base->str();\n\t\tif(this->base->isFunctionType())\n\t\t\tb = \"(\" + b + \")\";\n\n\t\treturn strprintf(\"[%s]\", b);\n\t}\n\n\tstd::string VariadicArrayType::str()\n\t{\n\t\tstd::string b = this->base->str();\n\t\tif(this->base->isFunctionType())\n\t\t\tb = \"(\" + b + \")\";\n\n\t\treturn strprintf(\"[%s: ...]\", b);\n\t}\n\n\tstd::string ArraySliceType::str()\n\t{\n\t\tstd::string b = this->base->str();\n\t\tif(this->base->isFunctionType())\n\t\t\tb = \"(\" + b + \")\";\n\n\t\treturn strprintf(\"[%s:]\", b);\n\t}\n\n\tstd::string FunctionType::str()\n\t{\n\t\tstd::string ret = \"fn(\";\n\n\t\tfor(auto t : this->argTypes)\n\t\t\tret += t->str() + \", \";\n\n\t\tif(this->argTypes.size() > 0)\n\t\t\tret.pop_back(), ret.pop_back();\n\n\t\treturn ret + \") -> \" + this->returnType->str();\n\t}\n}\n\n\n\n\n"
  },
  {
    "path": "source/include/allocator.h",
    "content": "// allocator.h\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n#include <stdint.h>\n#include <stddef.h>\n\nnamespace mem\n{\n\tvoid* allocate_memory(size_t bytes);\n\tvoid deallocate_memory(void* ptr, size_t bytes);\n\n\n\tsize_t getAllocatedCount();\n\tsize_t getDeallocatedCount();\n\tsize_t getWatermark();\n\tvoid resetStats();\n}\n\n\n\n"
  },
  {
    "path": "source/include/ast.h",
    "content": "// ast.h\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n#include \"defs.h\"\n#include \"sst_expr.h\"\n#include \"stcommon.h\"\n#include \"precompile.h\"\n\n#include <unordered_set>\n\nnamespace pts\n{\n\tstruct Type;\n}\n\nnamespace fir\n{\n\tstruct Type;\n}\n\nnamespace sst\n{\n\tstruct TypecheckState;\n\tstruct FunctionDefn;\n\tstruct FunctionDecl;\n}\n\nnamespace ast\n{\n\tstruct Stmt : Locatable\n\t{\n\t\tStmt(const Location& l) : Locatable(l, \"statement\") { }\n\t\tvirtual ~Stmt();\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) = 0;\n\n\t\tAttribSet attrs;\n\t};\n\n\tstruct Expr : Stmt\n\t{\n\t\tExpr(const Location& l) : Stmt(l) { this->readableName = \"expression\"; }\n\t\t~Expr();\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) = 0;\n\n\t\t//? this flag is used in very specific cases (as of now [27/10/18] only for union variants), to tell the typecheck\n\t\t//? method to treat the expression as if it were evaluating a type, instead of trying to yield a value.\n\t\t//* specifically, ast::Ident uses this flag if it sees that its target is an sst::UnionVariantDefn;\n\t\t//* if checkAsType == true, it will target the VariantDefn; if checkAsType == false (as default), then\n\t\t//* it will make a UnionVariantConstructor instead.\n\t\tbool checkAsType = false;\n\t};\n\n\tstruct DeferredStmt : Stmt\n\t{\n\t\tDeferredStmt(const Location& l) : Stmt(l) { this->readableName = \"deferred statement\"; }\n\t\t~DeferredStmt() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tStmt* actual = 0;\n\t};\n\n\tstruct TypeDefn;\n\tstruct Parameterisable : Stmt\n\t{\n\t\tParameterisable(const Location& l) : Stmt(l) { this->readableName = \"<Parameterisable>\"; }\n\t\t~Parameterisable() { }\n\n\t\tvirtual std::string getKind() = 0;\n\t\tvirtual TCResult generateDeclaration(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps) = 0;\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps) = 0;\n\n\t\t//* anything with generic abilities must implement the version of generateDeclaration and typecheck that accommodates the mapping argument\n\t\t//* if not we won't be able to know anything about anything.\n\n\t\t//? typecheck method is implemented for Parameterisable (and marked final) in typecheck/misc.cpp, where it simply calls the generic typecheck\n\t\t//? with an empty mapping. It is up to the individual AST during typechecking to verify `!gmaps.empty()` if `this->generics.size() > 0`.\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) final override;\n\n\t\tstd::pair<bool, sst::Defn*> checkForExistingDeclaration(sst::TypecheckState* fs, const TypeParamMap_t& gmaps);\n\n\t\tstd::string name;\n\n\t\tstd::vector<std::pair<std::string, TypeConstraints_t>> generics;\n\t\tstd::vector<std::pair<sst::Defn*, std::vector<TypeParamMap_t>>> genericVersions;\n\n\t\t// kind of a hack.\n\t\tstd::unordered_set<sst::Defn*> finishedTypechecking;\n\n\t\t// another hack-y thing\n\t\tTypeDefn* parentType = 0;\n\n\t\tVisibilityLevel visibility = VisibilityLevel::Internal;\n\n\t\t// hacky thing #3\n\t\t// explanation: the 'scope' of a type is always fixed, and it is the scope at the point of definition.\n\t\t// however, as we typecheck users of the type, our 'currentScope' moves around -- so we need to remember\n\t\t// the real, original scope of the type.\n\t\t//? we set this in typecheck/toplevel.cpp when generating the declarations.\n\t\t//? for methods & nested types, we set them in structs.cpp/classes.cpp\n\t\t//? in repl mode, we set this manually.\n\t\tsst::Scope enclosingScope;\n\t};\n\n\n\t//* this does nothing!!\n\tstruct ImportStmt : Stmt\n\t{\n\t\tImportStmt(const Location& l) : Stmt(l) { this->readableName = \"import statement\"; }\n\t\t~ImportStmt() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\t};\n\n\tstruct Block : Stmt\n\t{\n\t\tBlock(const Location& l) : Stmt(l) { this->readableName = \"block\"; }\n\t\t~Block() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tLocation closingBrace;\n\n\t\tbool doNotPushNewScope = false;\n\n\t\tbool isArrow = false;\n\t\tbool isFunctionBody = false;\n\t\tstd::vector<Stmt*> statements;\n\t\tstd::vector<Stmt*> deferredStatements;\n\t};\n\n\n\n\tstruct FuncDefn : Parameterisable\n\t{\n\t\tFuncDefn(const Location& l) : Parameterisable(l) { this->readableName = \"function defintion\"; }\n\t\t~FuncDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"function\"; }\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps) override;\n\t\tvirtual TCResult generateDeclaration(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps) override;\n\n\t\tstruct Param\n\t\t{\n\t\t\tstd::string name;\n\t\t\tLocation loc;\n\t\t\tpts::Type* type = 0;\n\n\t\t\tExpr* defaultValue = 0;\n\t\t};\n\n\n\t\tstd::vector<Param> params;\n\t\tpts::Type* returnType = 0;\n\n\t\tBlock* body = 0;\n\n\t\tbool isMutating = false;\n\n\t\tbool isVirtual = false;\n\t\tbool isOverride = false;\n\t};\n\n\tstruct InitFunctionDefn : Parameterisable\n\t{\n\t\tInitFunctionDefn(const Location& l) : Parameterisable(l) { this->readableName = \"class initialiser definition\"; }\n\t\t~InitFunctionDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"initialiser\"; }\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps) override;\n\t\tvirtual TCResult generateDeclaration(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps) override;\n\n\t\tusing Param = FuncDefn::Param;\n\n\t\tstd::vector<Param> params;\n\n\t\tbool didCallSuper = false;\n\t\tstd::vector<std::pair<std::string, Expr*>> superArgs;\n\n\t\tBlock* body = 0;\n\t\tFuncDefn* actualDefn = 0;\n\t};\n\n\n\tstruct ForeignFuncDefn : Stmt\n\t{\n\t\tForeignFuncDefn(const Location& l) : Stmt(l) { this->readableName = \"foreign function definition\"; }\n\t\t~ForeignFuncDefn() { }\n\n\t\tsst::FunctionDecl* generatedDecl = 0;\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tusing Param = FuncDefn::Param;\n\n\t\tstd::string name;\n\t\tstd::string realName;\n\n\t\tstd::vector<Param> params;\n\t\tpts::Type* returnType = 0;\n\n\t\tbool isVarArg = false;\n\t\tbool isIntrinsic = false;\n\n\t\t//* note: foriegn functions are not Parameterisable, so they don't have the 'visibility' -- so we add it.\n\t\tVisibilityLevel visibility = VisibilityLevel::Internal;\n\t};\n\n\tstruct OperatorOverloadDefn : FuncDefn\n\t{\n\t\tOperatorOverloadDefn(const Location& l) : FuncDefn(l) { this->readableName = \"operator overload defintion\"; }\n\t\t~OperatorOverloadDefn() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps) override;\n\t\tvirtual TCResult generateDeclaration(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps) override;\n\n\t\tenum class Kind\n\t\t{\n\t\t\tInvalid,\n\t\t\tInfix,\n\t\t\tPrefix,\n\t\t\tPostfix\n\t\t};\n\n\t\tstd::string symbol;\n\t\tKind kind = Kind::Invalid;\n\t};\n\n\tstruct VarDefn : Stmt\n\t{\n\t\tVarDefn(const Location& l) : Stmt(l) { this->readableName = \"variable defintion\"; }\n\t\t~VarDefn() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tstd::string name;\n\t\tpts::Type* type = 0;\n\n\t\tbool immut = false;\n\t\tExpr* initialiser = 0;\n\n\t\tbool isField = false;\n\n\t\t//* note: foriegn functions are not Parameterisable, so they don't have the 'visibility' -- so we add it.\n\t\tVisibilityLevel visibility = VisibilityLevel::Internal;\n\n\t\tbool noMangle = false;\n\t};\n\n\n\tstruct DecompVarDefn : Stmt\n\t{\n\t\tDecompVarDefn(const Location& l) : Stmt(l) { this->readableName = \"destructuring variable defintion\"; }\n\t\t~DecompVarDefn() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tbool immut = false;\n\t\tExpr* initialiser = 0;\n\t\tDecompMapping bindings;\n\t};\n\n\n\tstruct PlatformDefn : Stmt\n\t{\n\t\tPlatformDefn(const Location& l) : Stmt(l) { this->readableName = \"platform-specific definition\"; }\n\t\t~PlatformDefn() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tenum class Type\n\t\t{\n\t\t\tInvalid,\n\t\t\tIntrinsic,\n\t\t\tIntegerType\n\t\t};\n\n\t\tType defnType = Type::Invalid;\n\n\t\t// only valid if defnType == Intrinsic\n\t\tForeignFuncDefn* intrinsicDefn = 0;\n\n\t\t// only valid if defnType == IntegerType\n\t\tstd::string typeName;\n\t\tsize_t typeSizeInBits = 0;\n\t};\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tstruct IfStmt : Stmt\n\t{\n\t\tIfStmt(const Location& l) : Stmt(l) { this->readableName = \"if statement\"; }\n\t\t~IfStmt() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tstruct Case\n\t\t{\n\t\t\tExpr* cond = 0;\n\t\t\tBlock* body = 0;\n\n\t\t\tstd::vector<Stmt*> inits;\n\t\t};\n\n\t\tstd::vector<Case> cases;\n\t\tBlock* elseCase = 0;\n\t};\n\n\tstruct ReturnStmt : Stmt\n\t{\n\t\tReturnStmt(const Location& l) : Stmt(l) { this->readableName = \"return statement\"; }\n\t\t~ReturnStmt() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tExpr* value = 0;\n\t};\n\n\tstruct WhileLoop : Stmt\n\t{\n\t\tWhileLoop(const Location& l) : Stmt(l) { this->readableName = \"while loop\"; }\n\t\t~WhileLoop() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tExpr* cond = 0;\n\t\tBlock* body = 0;\n\n\t\tbool isDoVariant = false;\n\t};\n\n\tstruct ForLoop : Stmt\n\t{\n\t\tForLoop(const Location& l) : Stmt(l) { this->readableName = \"for loop\"; }\n\t\t~ForLoop() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override = 0;\n\n\t\tBlock* body = 0;\n\t};\n\n\tstruct ForeachLoop : ForLoop\n\t{\n\t\tForeachLoop(const Location& l) : ForLoop(l) { this->readableName = \"for loop\"; }\n\t\t~ForeachLoop() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tExpr* array = 0;\n\n\t\tstd::string indexVar;\n\t\tDecompMapping bindings;\n\t};\n\n\n\tstruct BreakStmt : Stmt\n\t{\n\t\tBreakStmt(const Location& l) : Stmt(l) { this->readableName = \"break statement\"; }\n\t\t~BreakStmt() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\t};\n\n\tstruct ContinueStmt : Stmt\n\t{\n\t\tContinueStmt(const Location& l) : Stmt(l) { this->readableName = \"continue statement\"; }\n\t\t~ContinueStmt() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\t};\n\n\tstruct UsingStmt : Stmt\n\t{\n\t\tUsingStmt(const Location& l) : Stmt(l) { this->readableName = \"using statement\"; }\n\t\t~UsingStmt() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tExpr* expr = 0;\n\t\tstd::string useAs;\n\t};\n\n\tstruct StaticDecl : Stmt\n\t{\n\t\tStaticDecl(Stmt* s) : Stmt(s->loc), actual(s) { this->readableName = \"static declaration\"; }\n\t\t~StaticDecl() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* inf = 0) override { return this->actual->typecheck(fs, inf); }\n\n\t\tStmt* actual = 0;\n\t};\n\n\n\tstruct VirtualDecl : Stmt\n\t{\n\t\tVirtualDecl(Stmt* s) : Stmt(s->loc), actual(s) { this->readableName = \"virtual declaration\"; }\n\t\t~VirtualDecl() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* inf = 0) override { return this->actual->typecheck(fs, inf); }\n\n\t\tStmt* actual = 0;\n\t\tbool isOverride = false;\n\t};\n\n\n\tstruct TypeDefn : Parameterisable\n\t{\n\t\tTypeDefn(const Location& l) : Parameterisable(l) { this->readableName = \"type definition\"; }\n\t\t~TypeDefn() { }\n\t};\n\n\tstruct StructDefn : TypeDefn\n\t{\n\t\tStructDefn(const Location& l) : TypeDefn(l) { this->readableName = \"struct definition\"; }\n\t\t~StructDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"struct\"; }\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps) override;\n\t\tvirtual TCResult generateDeclaration(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps) override;\n\n\t\tstd::vector<pts::Type*> bases;\n\n\t\tstd::vector<std::tuple<std::string, Location, pts::Type*>> fields;\n\t\tstd::vector<FuncDefn*> methods;\n\t};\n\n\tstruct ClassDefn : TypeDefn\n\t{\n\t\tClassDefn(const Location& l) : TypeDefn(l) { this->readableName = \"class definition\"; }\n\t\t~ClassDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"class\"; }\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps) override;\n\t\tvirtual TCResult generateDeclaration(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps) override;\n\n\t\tstd::vector<pts::Type*> bases;\n\n\t\tstd::vector<InitFunctionDefn*> initialisers;\n\t\tInitFunctionDefn* deinitialiser = 0;\n\t\tInitFunctionDefn* copyInitialiser = 0;\n\t\tInitFunctionDefn* moveInitialiser = 0;\n\n\t\tstd::vector<VarDefn*> fields;\n\t\tstd::vector<FuncDefn*> methods;\n\n\t\tstd::vector<VarDefn*> staticFields;\n\t\tstd::vector<FuncDefn*> staticMethods;\n\n\t\tstd::vector<TypeDefn*> nestedTypes;\n\t};\n\n\tstruct EnumDefn : TypeDefn\n\t{\n\t\tEnumDefn(const Location& l) : TypeDefn(l) { this->readableName = \"enum definition\"; }\n\t\t~EnumDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"enum\"; }\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps) override;\n\t\tvirtual TCResult generateDeclaration(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps) override;\n\n\t\tstruct Case\n\t\t{\n\t\t\tLocation loc;\n\t\t\tstd::string name;\n\t\t\tExpr* value = 0;\n\t\t};\n\n\t\tstd::vector<Case> cases;\n\t\tpts::Type* memberType = 0;\n\t};\n\n\tstruct UnionDefn : TypeDefn\n\t{\n\t\tUnionDefn(const Location& l) : TypeDefn(l) { this->readableName = \"union definition\"; }\n\t\t~UnionDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"union\"; }\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps) override;\n\t\tvirtual TCResult generateDeclaration(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps) override;\n\n\t\tutil::hash_map<std::string, std::tuple<size_t, Location, pts::Type*>> cases;\n\n\t\tstd::vector<std::pair<Location, pts::Type*>> transparentFields;\n\t};\n\n\tstruct TraitDefn : TypeDefn\n\t{\n\t\tTraitDefn(const Location& l) : TypeDefn(l) { this->readableName = \"trait definition\"; }\n\t\t~TraitDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"trait\"; }\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps) override;\n\t\tvirtual TCResult generateDeclaration(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps) override;\n\n\t\tstd::vector<pts::Type*> bases;\n\t\tstd::vector<FuncDefn*> methods;\n\t};\n\n\tstruct TypeExpr : Expr\n\t{\n\t\tTypeExpr(const Location& l, pts::Type* t) : Expr(l), type(t) { this->readableName = \"<TYPE EXPRESSION>\"; }\n\t\t~TypeExpr() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tpts::Type* type = 0;\n\t};\n\n\t// a bit of a strange thing, but basically it's a kind of cast.\n\tstruct MutabilityTypeExpr : Expr\n\t{\n\t\tMutabilityTypeExpr(const Location& l, bool m) : Expr(l), mut(m) { this->readableName = \"<TYPE EXPRESSION>\"; }\n\t\t~MutabilityTypeExpr() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tbool mut;\n\t};\n\n\tstruct Ident : Expr\n\t{\n\t\tIdent(const Location& l, const std::string& n) : Expr(l), name(n) { this->readableName = \"identifier\"; }\n\t\t~Ident() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tstd::string name;\n\t\tbool traverseUpwards = true;\n\n\t\t// for these cases: Foo<T: int>(...) and Foo<T: int>.staticAccess\n\t\t// where Foo is, respectively, a generic function and a generic type.\n\t\tPolyArgMapping_t mappings;\n\t};\n\n\n\tstruct RangeExpr : Expr\n\t{\n\t\tRangeExpr(const Location& loc) : Expr(loc) { this->readableName = \"range expression\"; }\n\t\t~RangeExpr() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tExpr* start = 0;\n\t\tExpr* end = 0;\n\n\t\tExpr* step = 0;\n\n\t\tbool halfOpen = false;\n\t};\n\n\n\n\tstruct AllocOp : Expr\n\t{\n\t\tAllocOp(const Location& l) : Expr(l) { this->readableName = \"alloc statement\"; }\n\t\t~AllocOp() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tpts::Type* allocTy = 0;\n\t\tstd::vector<Expr*> counts;\n\t\tstd::vector<std::pair<std::string, Expr*>> args;\n\n\t\tBlock* initBody = 0;\n\n\t\tbool isMutable = false;\n\t};\n\n\tstruct DeallocOp : Stmt\n\t{\n\t\tDeallocOp(const Location& l) : Stmt(l) { this->readableName = \"free statement\"; }\n\t\t~DeallocOp() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\t\tExpr* expr = 0;\n\t};\n\n\tstruct SizeofOp : Expr\n\t{\n\t\tSizeofOp(const Location& l) : Expr(l) { this->readableName = \"sizeof expression\"; }\n\t\t~SizeofOp() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tExpr* expr = 0;\n\t};\n\n\tstruct TypeidOp : Expr\n\t{\n\t\tTypeidOp(const Location& l) : Expr(l) { this->readableName = \"typeid expression\"; }\n\t\t~TypeidOp() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\t\tExpr* expr = 0;\n\t};\n\n\tstruct ComparisonOp : Expr\n\t{\n\t\tComparisonOp(const Location& loc) : Expr(loc) { this->readableName = \"comparsion expression\"; }\n\t\t~ComparisonOp() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tstd::vector<Expr*> exprs;\n\t\tstd::vector<std::pair<std::string, Location>> ops;\n\t};\n\n\tstruct BinaryOp : Expr\n\t{\n\t\tBinaryOp(const Location& loc, const std::string& o, Expr* l, Expr* r)\n\t\t\t: Expr(loc), op(o), left(l), right(r) { this->readableName = \"binary expression\"; }\n\t\t~BinaryOp() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tstd::string op;\n\n\t\tExpr* left = 0;\n\t\tExpr* right = 0;\n\t};\n\n\tstruct UnaryOp : Expr\n\t{\n\t\tUnaryOp(const Location& l) : Expr(l) { this->readableName = \"unary expression\"; }\n\t\t~UnaryOp() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tstd::string op;\n\t\tExpr* expr = 0;\n\t\tbool isPostfix = false;\n\t};\n\n\tstruct AssignOp : Expr\n\t{\n\t\tAssignOp(const Location& l) : Expr(l) { this->readableName = \"assignment statement\"; }\n\t\t~AssignOp() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tstd::string op;\n\n\t\tExpr* left = 0;\n\t\tExpr* right = 0;\n\t};\n\n\tstruct SubscriptOp : Expr\n\t{\n\t\tSubscriptOp(const Location& l) : Expr(l) { }\n\t\t~SubscriptOp() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tExpr* expr = 0;\n\t\tExpr* inside = 0;\n\t};\n\n\tstruct SliceOp : Expr\n\t{\n\t\tSliceOp(const Location& l) : Expr(l) { this->readableName = \"slice expression\"; }\n\t\t~SliceOp() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tExpr* expr = 0;\n\n\t\tExpr* start = 0;\n\t\tExpr* end = 0;\n\t};\n\n\tstruct SplatOp : Expr\n\t{\n\t\tSplatOp(const Location& l) : Expr(l) { this->readableName = \"splat expression\"; }\n\t\t~SplatOp() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tExpr* expr = 0;\n\t};\n\n\tstruct SubscriptDollarOp : Expr\n\t{\n\t\tSubscriptDollarOp(const Location& l) : Expr(l) { this->readableName = \"dollar expression\"; }\n\t\t~SubscriptDollarOp() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\t};\n\n\n\n\tstruct FunctionCall : Expr\n\t{\n\t\tFunctionCall(const Location& l, const std::string& n) : Expr(l), name(n) { this->readableName = \"function call\"; }\n\t\t~FunctionCall() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\t\tsst::Expr* typecheckWithArguments(sst::TypecheckState* fs, const std::vector<FnCallArgument>& args, fir::Type* inferred);\n\n\t\tstd::string name;\n\t\tstd::vector<std::pair<std::string, Expr*>> args;\n\n\t\tPolyArgMapping_t mappings;\n\n\t\tbool traverseUpwards = true;\n\t};\n\n\tstruct ExprCall : Expr\n\t{\n\t\tExprCall(const Location& l) : Expr(l) { this->readableName = \"function call\"; }\n\t\t~ExprCall() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\t\tsst::Expr* typecheckWithArguments(sst::TypecheckState* fs, const std::vector<FnCallArgument>& args, fir::Type* inferred);\n\n\t\tExpr* callee = 0;\n\t\tstd::vector<std::pair<std::string, Expr*>> args;\n\t};\n\n\n\n\tstruct DotOperator : Expr\n\t{\n\t\tDotOperator(const Location& loc, Expr* l, Expr* r) : Expr(loc), left(l), right(r) { this->readableName = \"dot operator\"; }\n\t\t~DotOperator() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tExpr* left = 0;\n\t\tExpr* right = 0;\n\t\tbool isStatic = false;\n\t};\n\n\n\n\n\tstruct LitNumber : Expr\n\t{\n\t\tLitNumber(const Location& l, const std::string& n) : Expr(l), num(n) { this->readableName = \"number literal\"; }\n\t\t~LitNumber() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tstd::string num;\n\t};\n\n\tstruct LitChar : Expr\n\t{\n\t\tLitChar(const Location& l, uint32_t val) : Expr(l), value(val) { this->readableName = \"character literal\"; }\n\t\t~LitChar() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tuint32_t value = false;\n\t};\n\n\tstruct LitBool : Expr\n\t{\n\t\tLitBool(const Location& l, bool val) : Expr(l), value(val) { this->readableName = \"boolean literal\"; }\n\t\t~LitBool() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tbool value = false;\n\t};\n\n\tstruct LitString : Expr\n\t{\n\t\tLitString(const Location& l, const std::string& s, bool isc)\n\t\t\t: Expr(l), str(s), isCString(isc) { this->readableName = \"string literal\"; }\n\n\t\t~LitString() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tstd::string str;\n\t\tbool isCString = false;\n\t};\n\n\tstruct LitNull : Expr\n\t{\n\t\tLitNull(const Location& l) : Expr(l) { this->readableName = \"null literal\"; }\n\t\t~LitNull() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\t};\n\n\tstruct LitTuple : Expr\n\t{\n\t\tLitTuple(const Location& l, const std::vector<Expr*>& its) : Expr(l), values(its) { this->readableName = \"tuple literal\"; }\n\t\t~LitTuple() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tstd::vector<Expr*> values;\n\t};\n\n\tstruct LitArray : Expr\n\t{\n\t\tLitArray(const Location& l, const std::vector<Expr*>& its) : Expr(l), values(its) { this->readableName = \"array literal\"; }\n\t\t~LitArray() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tbool raw = false;\n\t\tpts::Type* explicitType = 0;\n\t\tstd::vector<Expr*> values;\n\t};\n\n\n\n\tstruct RunDirective : Expr\n\t{\n\t\tRunDirective(const Location& l) : Expr(l) { this->readableName = \"#run directive\"; }\n\t\t~RunDirective() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\t// note: these two are mutually exclusive!\n\t\tBlock* block = 0;\n\t\tExpr* insideExpr = 0;\n\t};\n\n\tstruct IfDirective : Stmt\n\t{\n\t\tIfDirective(const Location& l) : Stmt(l) { this->readableName = \"#if directive\"; }\n\t\t~IfDirective() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tstd::vector<IfStmt::Case> cases;\n\t\tBlock* elseCase = 0;\n\t};\n\n\n\n\tstruct TopLevelBlock : Stmt\n\t{\n\t\tTopLevelBlock(const Location& l, const std::string& n) : Stmt(l), name(n) { this->readableName = \"namespace\"; }\n\t\t~TopLevelBlock() { }\n\n\t\tvirtual TCResult typecheck(sst::TypecheckState* fs, fir::Type* infer = 0) override;\n\n\t\tstd::string name;\n\t\tstd::vector<Stmt*> statements;\n\t\tVisibilityLevel visibility = VisibilityLevel::Internal;\n\t};\n}\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/backend.h",
    "content": "// backend.h\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#include \"defs.h\"\n\nnamespace fir\n{\n\tstruct Module;\n\tstruct Function;\n}\n\nnamespace backend\n{\n\tstruct CompiledData\n\t{\n\t\tfir::Module* module = 0;\n\t};\n\n\tnamespace BackendCaps\n\t{\n\t\tenum Capabilities : int\n\t\t{\n\t\t\tEmitProgram\t\t= 0x01,\n\t\t\tEmitObject\t\t= 0x02,\n\t\t\tEmitAssembly\t= 0x04,\n\t\t\tJIT\t\t\t\t= 0x08,\n\t\t};\n\t}\n\n\n\tenum class OptimisationLevel\n\t{\n\t\tInvalid,\n\n\t\tDebug,\t\t// -Ox\n\t\tNone,\t\t// -O0\n\n\t\tMinimal,\t// -O1\n\t\tNormal,\t\t// -O2\n\t\tAggressive\t// -O3\n\t};\n\n\tenum class ProgOutputMode\n\t{\n\t\tInvalid,\n\n\t\tRunJit,\t\t\t// -run or -jit\n\t\tObjectFile,\t\t// -c\n\t\tLLVMBitcode,\t// -emit-llvm\n\t\tProgram\t\t\t// (default)\n\t};\n\n\tenum class BackendOption\n\t{\n\t\tInvalid,\n\n\t\tNone,\n\t\tLLVM,\n\t\tInterpreter,\n\t\tAssembly_x64,\n\t};\n\n\tstd::string capabilitiesToString(BackendCaps::Capabilities caps);\n\n\tstruct Backend\n\t{\n\t\tBackendCaps::Capabilities getCapabilities() { return static_cast<BackendCaps::Capabilities>(this->capabilities); }\n\t\tbool hasCapability(BackendCaps::Capabilities cap) { return this->capabilities & cap; }\n\n\t\tstatic Backend* getBackendFromOption(BackendOption opt, CompiledData& cd, const std::vector<std::string>& in,\n\t\t\tconst std::string& out);\n\n\t\tvirtual ~Backend() { }\n\n\t\t// in order of calling.\n\t\tvirtual void performCompilation() = 0;\n\t\tvirtual void optimiseProgram() = 0;\n\t\tvirtual void writeOutput() = 0;\n\n\t\tvirtual std::string str() = 0;\n\n\t\tprotected:\n\t\tBackend(int caps, CompiledData& dat, const std::vector<std::string>& inputs, const std::string& output)\n\t\t\t: capabilities(caps), compiledData(dat), inputFilenames(inputs), outputFilename(output) { }\n\n\t\tint capabilities;\n\t\tCompiledData& compiledData;\n\t\tstd::vector<std::string> inputFilenames;\n\t\tstd::string outputFilename;\n\t};\n\n\tstruct x64Backend : Backend\n\t{\n\t\tx64Backend(CompiledData& dat, const std::vector<std::string>& inputs, const std::string& output);\n\t\tvirtual ~x64Backend() { }\n\n\t\tvirtual void performCompilation() override;\n\t\tvirtual void optimiseProgram() override;\n\t\tvirtual void writeOutput() override;\n\n\t\tvirtual std::string str() override;\n\t};\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/backends/interp.h",
    "content": "// interp.h\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n#include \"backend.h\"\n\nnamespace fir::interp\n{\n\tstruct InterpState;\n}\n\nnamespace backend\n{\n\tstruct FIRInterpBackend : Backend\n\t{\n\t\tFIRInterpBackend(CompiledData& dat, const std::vector<std::string>& inputs, const std::string& output);\n\t\tvirtual ~FIRInterpBackend();\n\n\t\tvirtual void performCompilation() override;\n\t\tvirtual void optimiseProgram() override;\n\t\tvirtual void writeOutput() override;\n\n\t\tvirtual std::string str() override;\n\n\t\tprotected:\n\t\t\tfir::interp::InterpState* is = 0;\n\t};\n}\n"
  },
  {
    "path": "source/include/backends/llvm.h",
    "content": "// llvm.h\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#ifndef __STDC_CONSTANT_MACROS\n#define __STDC_CONSTANT_MACROS\n#endif\n\n#ifndef __STDC_LIMIT_MACROS\n#define __STDC_LIMIT_MACROS\n#endif\n\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n#else\n\t#pragma GCC diagnostic push\n\t#pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#endif\n\n\n#include \"llvm/IR/Mangler.h\"\n#include \"llvm/IR/DataLayout.h\"\n\n#include \"llvm/ADT/SmallVector.h\"\n\n#include \"llvm/Target/TargetMachine.h\"\n\n#include \"llvm/Support/raw_ostream.h\"\n#include \"llvm/Support/DynamicLibrary.h\"\n\n#include \"llvm/ExecutionEngine/JITSymbol.h\"\n#include \"llvm/ExecutionEngine/ExecutionEngine.h\"\n#include \"llvm/ExecutionEngine/RTDyldMemoryManager.h\"\n#include \"llvm/ExecutionEngine/SectionMemoryManager.h\"\n\n#include \"llvm/ExecutionEngine/Orc/CompileUtils.h\"\n#include \"llvm/ExecutionEngine/Orc/LambdaResolver.h\"\n#include \"llvm/ExecutionEngine/Orc/ExecutionUtils.h\"\n#include \"llvm/ExecutionEngine/Orc/IRCompileLayer.h\"\n#include \"llvm/ExecutionEngine/Orc/IRTransformLayer.h\"\n#include \"llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h\"\n#include \"llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h\"\n\n#ifdef _MSC_VER\n\t#pragma warning(pop)\n#else\n\t#pragma GCC diagnostic pop\n#endif\n\n#include \"backend.h\"\n\n\nnamespace llvm\n{\n\tclass Module;\n\tclass TargetMachine;\n\tclass ExecutionEngine;\n\tclass LLVMContext;\n\tclass Function;\n}\n\n\nnamespace backend\n{\n\tusing EntryPoint_t = int (*)(int, const char**);\n\n\tstruct LLVMJit\n\t{\n\t\tusing OptimiseFunction = std::function<std::unique_ptr<llvm::Module>(std::unique_ptr<llvm::Module>)>;\n\n\t\tvoid addModule(std::unique_ptr<llvm::Module> mod);\n\t\tllvm::JITEvaluatedSymbol findSymbol(const std::string& name);\n\t\tllvm::JITTargetAddress getSymbolAddress(const std::string& name);\n\n\t\tstatic LLVMJit* create();\n\n\t\tprivate:\n\t\tLLVMJit(llvm::orc::JITTargetMachineBuilder JTMB, llvm::DataLayout DL);\n\t\tstatic llvm::Expected<llvm::orc::ThreadSafeModule> optimiseModule(llvm::orc::ThreadSafeModule TSM,\n\t\t\tconst llvm::orc::MaterializationResponsibility& R);\n\n\t\tllvm::orc::ExecutionSession ES;\n\t\tllvm::orc::RTDyldObjectLinkingLayer ObjectLayer;\n\t\tllvm::orc::IRCompileLayer CompileLayer;\n\t\tllvm::orc::IRTransformLayer OptimiseLayer;\n\n\t\tllvm::DataLayout DL;\n\t\tllvm::orc::MangleAndInterner Mangle;\n\t\tllvm::orc::ThreadSafeContext Ctx;\n\n\t\tllvm::orc::JITDylib& dylib;\n\t};\n\n\tstruct LLVMBackend : Backend\n\t{\n\t\tLLVMBackend(CompiledData& dat, const std::vector<std::string>& inputs, const std::string& output);\n\t\tvirtual ~LLVMBackend() { }\n\n\t\tvirtual void performCompilation() override;\n\t\tvirtual void optimiseProgram() override;\n\t\tvirtual void writeOutput() override;\n\n\t\tvirtual std::string str() override;\n\n\t\tstatic llvm::LLVMContext& getLLVMContext();\n\n\t\tstatic llvm::Module* translateFIRtoLLVM(fir::Module* mod);\n\n\t\tprivate:\n\t\tvoid setupTargetMachine();\n\t\tEntryPoint_t getEntryFunctionFromJIT();\n\n\t\tllvm::Function* entryFunction = 0;\n\t\tllvm::TargetMachine* targetMachine = 0;\n\t\tstd::unique_ptr<llvm::Module> linkedModule;\n\n\t\tLLVMJit* jitInstance = 0;\n\t};\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/codegen.h",
    "content": "// codegen.h\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#include \"defs.h\"\n#include \"stcommon.h\"\n#include \"ir/irbuilder.h\"\n\nnamespace fir\n{\n\tstruct Module;\n\tstruct IRBuilder;\n\n\tnamespace interp\n\t{\n\t\tstruct InterpState;\n\t}\n}\n\nnamespace sst\n{\n\tstruct Expr;\n\tstruct Stmt;\n\tstruct Defn;\n\tstruct Block;\n\tstruct TypeDefn;\n\tstruct BinaryOp;\n\tstruct StateTree;\n\tstruct FunctionDecl;\n\tstruct FunctionDefn;\n\tstruct FunctionCall;\n\tstruct DefinitionTree;\n}\n\nnamespace cgn\n{\n\tstruct ControlFlowPoint\n\t{\n\t\tControlFlowPoint(sst::Block* b, fir::IRBlock* bp, fir::IRBlock* cp) :\n\t\t\tblock(b), breakPoint(bp), continuePoint(cp) { }\n\n\t\tsst::Block* block = 0;\n\n\t\tfir::IRBlock* breakPoint = 0;\n\t\tfir::IRBlock* continuePoint = 0;\n\t};\n\n\tstruct BlockPoint\n\t{\n\t\tBlockPoint(sst::Block* b) : block(b) { }\n\n\t\tsst::Block* block = 0;\n\n\t\tstd::vector<fir::Value*> refCountedValues;\n\t\tstd::vector<fir::Value*> raiiValues;\n\t};\n\n\n\tstruct CodegenState\n\t{\n\t\tenum class OperatorFn\n\t\t{\n\t\t\tNone,\n\n\t\t\tBuiltin,\n\t\t\tUserDefined\n\t\t};\n\n\t\tCodegenState(const fir::IRBuilder& i);\n\n\t\tsize_t id = 0;\n\t\tfir::Module* module = 0;\n\n\t\tfir::IRBuilder irb;\n\n\t\tstd::pair<fir::Function*, Location> entryFunction = { };\n\n\t\tstd::vector<Location> locationStack;\n\t\tutil::hash_map<sst::Defn*, CGResult> valueMap;\n\t\tstd::vector<fir::Value*> methodSelfStack;\n\n\n\t\tutil::hash_map<fir::Function*, fir::Type*> methodList;\n\n\t\tutil::hash_map<fir::Type*, sst::TypeDefn*> typeDefnMap;\n\t\tutil::hash_map<std::string, sst::Defn*> compilerSupportDefinitions;\n\n\n\t\tsize_t _debugIRIndent = 0;\n\t\tvoid pushIRDebugIndentation();\n\t\tvoid printIRDebugMessage(const std::string& msg, const std::vector<fir::Value*>& vals);\n\t\tvoid popIRDebugIndentation();\n\n\n\t\tvoid pushLoc(const Location& l);\n\t\tvoid pushLoc(sst::Stmt* stmt);\n\t\tvoid popLoc();\n\n\t\tLocation loc();\n\n\t\tvoid enterMethodBody(fir::Function* method, fir::Value* self);\n\t\tvoid leaveMethodBody();\n\n\t\tbool isInMethodBody();\n\t\tfir::Value* getMethodSelf();\n\n\t\tstd::vector<fir::Function*> functionStack;\n\t\tfir::Function* getCurrentFunction();\n\t\tvoid enterFunction(fir::Function* fn);\n\t\tvoid leaveFunction();\n\n\t\tstd::vector<ControlFlowPoint> breakingPointStack;\n\t\tControlFlowPoint getCurrentCFPoint();\n\n\t\tvoid enterBreakableBody(const ControlFlowPoint& cfp);\n\t\tControlFlowPoint leaveBreakableBody();\n\n\t\tstd::vector<BlockPoint> blockPointStack;\n\t\tBlockPoint getCurrentBlockPoint();\n\t\tvoid enterBlock(const BlockPoint& bp);\n\t\tvoid leaveBlock();\n\n\t\tstd::vector<fir::Value*> subscriptArrayLengthStack;\n\t\tfir::Value* getCurrentSubscriptArrayLength();\n\t\tvoid enterSubscriptWithLength(fir::Value* len);\n\t\tvoid leaveSubscript();\n\n\n\t\tCGResult performBinaryOperation(const Location& loc, std::pair<Location, fir::Value*> lhs, std::pair<Location, fir::Value*> rhs,\n\t\t\tstd::string op);\n\t\tCGResult performLogicalBinaryOperation(sst::BinaryOp* bo);\n\n\t\tstd::pair<fir::Value*, fir::Value*> autoCastValueTypes(fir::Value* lhs, fir::Value* rhs);\n\t\tfir::Value* oneWayAutocast(fir::Value* from, fir::Type* target);\n\n\t\tfir::Value* getDefaultValue(fir::Type* type);\n\n\t\tfir::Value* getConstructedStructValue(fir::StructType* str, const std::vector<FnCallArgument>& args);\n\t\tfir::Value* constructClassWithArguments(fir::ClassType* cls, sst::FunctionDefn* constr, const std::vector<FnCallArgument>& args);\n\n\t\tfir::Value* callVirtualMethod(sst::FunctionCall* call);\n\n\t\tfir::ConstantValue* unwrapConstantNumber(fir::ConstantValue* cv);\n\t\tfir::ConstantValue* unwrapConstantNumber(fir::ConstantNumber* cv, fir::Type* target);\n\n\t\tCGResult getStructFieldImplicitly(std::string name);\n\n\t\tfir::Function* getOrDeclareLibCFunction(std::string name);\n\n\n\t\tbool isInsideGlobalInitFunc = false;\n\n\t\t// this one holds the finalised global initialiser function -- this one is supposed to\n\t\t// call all the pieces; we always regenerate this function when we call finishGlobalInitFunction().\n\t\tfir::Function* finalisedGlobalInitFunction = 0;\n\n\t\t// this is getting a bit complicated. this holds each \"piece\" of the global init function,\n\t\t// where each piece probably corresponds to the initialisation of a single global value.\n\t\tstd::vector<std::pair<fir::GlobalValue*, fir::Function*>> globalInitPieces;\n\n\t\tbool isWithinGlobalInitFunction();\n\t\tfir::IRBlock* enterGlobalInitFunction(fir::GlobalValue* val);\n\t\tvoid leaveGlobalInitFunction(fir::IRBlock* restore);\n\t\tvoid finishGlobalInitFunction();\n\n\n\n\n\n\t\tvoid generateDecompositionBindings(const DecompMapping& bind, CGResult rhs, bool allowref);\n\n\t\tutil::hash_map<std::string, size_t> getNameIndexMap(sst::FunctionDefn* fd);\n\n\t\tstd::vector<fir::Value*> codegenAndArrangeFunctionCallArguments(sst::Defn* target, fir::FunctionType* ft, const std::vector<FnCallArgument>& args);\n\n\n\n\t\tvoid addVariableUsingStorage(sst::VarDefn* var, fir::Value* ptr);\n\n\t\tvoid createWhileLoop(const std::function<void (fir::IRBlock*, fir::IRBlock*)>& check, const std::function<void ()>& body);\n\n\t\tstd::pair<OperatorFn, fir::Function*> getOperatorFunctionForTypes(fir::Type* a, fir::Type* b, std::string op);\n\n\t\tbool isRefCountedType(fir::Type* type);\n\t\tvoid incrementRefCount(fir::Value* val);\n\t\tvoid decrementRefCount(fir::Value* val);\n\n\t\tvoid addRefCountedValue(fir::Value* val);\n\t\tvoid removeRefCountedValue(fir::Value* val);\n\n\t\tstd::vector<fir::Value*> getRefCountedValues();\n\n\t\tvoid autoAssignRefCountedValue(fir::Value* lhs, fir::Value* rhs, bool isInitial);\n\n\t\tvoid addRAIIOrRCValueIfNecessary(fir::Value* val, fir::Type* typeOverride = 0);\n\n\t\tvoid addRAIIValue(fir::Value* val);\n\t\tvoid removeRAIIValue(fir::Value* val);\n\t\tstd::vector<fir::Value*> getRAIIValues();\n\n\t\tsst::FunctionDefn* findMatchingMethodInType(sst::TypeDefn* td, sst::FunctionDecl* fn);\n\n\t\tbool isRAIIType(fir::Type* ty);\n\t\tbool typeHasDestructor(fir::Type* ty);\n\t\tbool typeHasCopyConstructor(fir::Type* ty);\n\t\tbool typeHasMoveConstructor(fir::Type* ty);\n\n\t\tvoid callDestructor(fir::Value* val);\n\n\t\tfir::Value* copyRAIIValue(fir::Value* value);\n\t\tvoid copyRAIIValue(fir::Value* from, fir::Value* target, bool enableMoving = true);\n\t\tvoid moveRAIIValue(fir::Value* from, fir::Value* target);\n\t};\n\n\tfir::Module* codegen(sst::DefinitionTree* dtree);\n}\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/container.h",
    "content": "// container.h\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n#include <stdint.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <assert.h>\n\n#include <vector>\n#include <utility>\n\n#include \"allocator.h\"\n\nnamespace util\n{\n\t// only allows for insertions.\n\t// hopefully faster than FastVector.\n\ttemplate <typename ValueType, size_t ChunkSize = 256>\n\tstruct FastInsertVector\n\t{\n\t\tFastInsertVector()\n\t\t{\n\t\t\tthis->length = 0;\n\t\t}\n\n\t\tFastInsertVector(const FastInsertVector& other)\n\t\t{\n\t\t\tfor(auto c : other.chunks)\n\t\t\t{\n\t\t\t\tauto nc = static_cast<ValueType*>(mem::allocate_memory(sizeof(ValueType) * ChunkSize));\n\t\t\t\tmemmove(nc, c, sizeof(ValueType) * ChunkSize);\n\t\t\t\tthis->chunks.push_back(nc);\n\t\t\t}\n\n\t\t\tthis->length = other.length;\n\t\t}\n\n\t\tFastInsertVector& operator = (const FastInsertVector& other)\n\t\t{\n\t\t\tauto copy = other;\n\t\t\tstd::swap(copy, *this);\n\t\t\treturn *this;\n\t\t}\n\n\t\tFastInsertVector(FastInsertVector&& other) noexcept\n\t\t{\n\t\t\t// move.\n\t\t\tthis->chunks = std::move(other.chunks);\n\t\t\tthis->length = other.length;\n\n\t\t\tother.length = 0;\n\t\t}\n\n\t\tFastInsertVector& operator = (FastInsertVector&& other) noexcept\n\t\t{\n\t\t\tif(this != &other)\n\t\t\t{\n\t\t\t\tfor(auto p : this->chunks)\n\t\t\t\t\tmem::deallocate_memory(p, sizeof(ValueType) * ChunkSize);\n\n\t\t\t\t// move.\n\t\t\t\tthis->chunks = std::move(other.chunks);\n\t\t\t\tthis->length = other.length;\n\n\t\t\t\tother.length = 0;\n\t\t\t}\n\n\t\t\treturn *this;\n\t\t}\n\n\t\t~FastInsertVector()\n\t\t{\n\t\t\tthis->clear();\n\t\t}\n\n\n\t\tValueType& operator [] (size_t index) const\n\t\t{\n\t\t\tsize_t cind = index / ChunkSize;\n\t\t\tsize_t offs = index % ChunkSize;\n\n\t\t\tassert(cind < this->chunks.size());\n\t\t\treturn *(static_cast<ValueType*>(this->chunks[cind] + offs));\n\t\t}\n\n\t\tValueType* getNextSlotAndIncrement()\n\t\t{\n\t\t\tsize_t addr = this->length;\n\t\t\tif(addr >= (ChunkSize * this->chunks.size()))\n\t\t\t\tmakeNewChunk();\n\n\t\t\tthis->length++;\n\t\t\tauto ret = (chunks.back() + (addr % ChunkSize));\n\n\t\t\treturn ret;\n\t\t}\n\n\t\tsize_t size() const\n\t\t{\n\t\t\treturn this->length;\n\t\t}\n\n\t\tvoid clear()\n\t\t{\n\t\t\tsize_t i = 0;\n\t\t\tfor(auto c : this->chunks)\n\t\t\t{\n\t\t\t\tfor(size_t k = 0; k < ChunkSize && i < this->length; k++, i++)\n\t\t\t\t\t(c + k)->~ValueType();\n\n\t\t\t\tmem::deallocate_memory(c, sizeof(ValueType) * ChunkSize);\n\t\t\t}\n\n\t\t\tthis->length = 0;\n\t\t\tthis->chunks.clear();\n\t\t}\n\n\t\tprivate:\n\t\tvoid makeNewChunk()\n\t\t{\n\t\t\tthis->chunks.push_back(static_cast<ValueType*>(mem::allocate_memory(sizeof(ValueType) * ChunkSize)));\n\t\t}\n\n\t\t// possibly use a faster implementation?? since we're just storing pointers idk if there's a point.\n\t\tsize_t length;\n\t\tstd::vector<ValueType*> chunks;\n\t};\n\n\tstruct MemoryPool_base\n\t{\n\t\tvirtual void clear() = 0;\n\t\tvirtual ~MemoryPool_base() { }\n\t};\n\n\ttemplate <typename ValueType, size_t ChunkSize = 256>\n\tstruct MemoryPool : MemoryPool_base\n\t{\n\t\tMemoryPool() { }\n\t\t~MemoryPool() { this->storage.clear(); }\n\n\t\tMemoryPool(const MemoryPool& other)\n\t\t{\n\t\t\tthis->storage = other.storage;\n\t\t}\n\n\t\tMemoryPool& operator = (const MemoryPool& other)\n\t\t{\n\t\t\tauto copy = other;\n\t\t\tstd::swap(copy, *this);\n\t\t\treturn *this;\n\t\t}\n\n\t\tMemoryPool(MemoryPool&& other) noexcept\n\t\t{\n\t\t\tthis->storage = std::move(other.storage);\n\t\t}\n\n\t\tMemoryPool& operator = (MemoryPool&& other) noexcept\n\t\t{\n\t\t\tif(this != &other) this->storage = std::move(other.storage);\n\t\t\treturn *this;\n\t\t}\n\n\t\ttemplate <typename... Args>\n\t\tValueType* operator () (Args&&... args)\n\t\t{\n\t\t\treturn this->construct(std::forward<Args>(args)...);\n\t\t}\n\n\t\ttemplate <typename... Args>\n\t\tValueType* construct(Args&&... args)\n\t\t{\n\t\t\treturn new (this->storage.getNextSlotAndIncrement()) ValueType(std::forward<Args>(args)...);\n\t\t}\n\n\t\tvirtual void clear() override\n\t\t{\n\t\t\tthis->storage.clear();\n\t\t}\n\n\t\tprivate:\n\t\tFastInsertVector<ValueType, ChunkSize> storage;\n\t};\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/defs.h",
    "content": "// defs.h\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n#include <limits.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"container.h\"\n\nstruct Identifier;\nenum class VisibilityLevel;\n\nnamespace fir { struct Type; struct Name; }\nnamespace pts { struct Type; }\n\n\nnamespace zpr\n{\n\ttemplate <typename T>\n\tstruct print_formatter<T, typename std::enable_if<\n\t\t(std::is_same_v<fir::Type*, T>) ||\n\t\t(std::is_pointer_v<T> && std::is_base_of_v<fir::Type, std::remove_pointer_t<T>>)\n\t>::type>\n\t{\n\t\tstd::string print(const T& x, const format_args&)\n\t\t{\n\t\t\treturn x->str();\n\t\t}\n\t};\n\n\ttemplate <>\n\tstruct print_formatter<Identifier>\n\t{\n\t\tstd::string print(const Identifier& x, const format_args& args);\n\t};\n\n\ttemplate <>\n\tstruct print_formatter<VisibilityLevel>\n\t{\n\t\tstd::string print(const VisibilityLevel& x, const format_args& args);\n\t};\n}\n\n\n\n\n[[noreturn]] void doTheExit(bool trace = true);\n\ntemplate <typename... Ts>\n[[noreturn]] inline void _error_and_exit(const char* fmt, Ts&&... ts)\n{\n\t// tinyformat::format(std::cerr, fmt, ts...);\n\tfprintf(stderr, \"%s\\n\", zpr::sprint(fmt, ts...).c_str());\n\tdoTheExit();\n}\nnamespace platform { void printStackTrace(); }\n\ntemplate <typename... Ts>\n[[noreturn]] inline void compiler_crash(const char* fmt, Ts&&... ts)\n{\n\tfprintf(stderr, \"%s\\n\", zpr::sprint(fmt, ts...).c_str());\n\n\tplatform::printStackTrace();\n\tabort();\n}\n\n\ntemplate <typename... Ts>\nstd::string strprintf(const char* fmt, Ts&&... ts)\n{\n\t// return tinyformat::format(fmt, ts...);\n\treturn zpr::sprint(fmt, ts...);\n}\n\n\n#define __nothing\n\n#ifdef NDEBUG\n#define iceAssert(x)    ((void) (x))\n#else\n#define iceAssert(x)    ((x) ? ((void) (0)) : _error_and_exit(\"compiler assertion at %s:%d, cause:\\n'%s' evaluated to false\\n\", __FILE__, __LINE__, #x))\n#endif\n\n#define TAB_WIDTH       4\n#define dcast(t, v)     (dynamic_cast<t*>(v))\n\nnamespace util\n{\n\ttemplate<typename K, typename V>\n\tusing hash_map = std::unordered_map<K, V>;\n}\n\nnamespace fir\n{\n\tstruct Type;\n\tstruct Value;\n}\n\nnamespace sst\n{\n\tstruct Expr;\n\tstruct Stmt;\n\tstruct Defn;\n}\n\nenum class IdKind\n{\n\tInvalid,\n\tName,\n\tFunction,\n\n\tType,\n};\n\n\n#define COLOUR_RESET\t\t\t\"\\033[0m\"\n#define COLOUR_BLACK\t\t\t\"\\033[30m\"\t\t\t// Black\n#define COLOUR_RED\t\t\t\t\"\\033[31m\"\t\t\t// Red\n#define COLOUR_GREEN\t\t\t\"\\033[32m\"\t\t\t// Green\n#define COLOUR_YELLOW\t\t\t\"\\033[33m\"\t\t\t// Yellow\n#define COLOUR_BLUE\t\t\t\t\"\\033[34m\"\t\t\t// Blue\n#define COLOUR_MAGENTA\t\t\t\"\\033[35m\"\t\t\t// Magenta\n#define COLOUR_CYAN\t\t\t\t\"\\033[36m\"\t\t\t// Cyan\n#define COLOUR_WHITE\t\t\t\"\\033[37m\"\t\t\t// White\n#define COLOUR_BLACK_BOLD\t\t\"\\033[1m\"\t\t\t// Bold Black\n#define COLOUR_RED_BOLD\t\t\t\"\\033[1m\\033[31m\"\t// Bold Red\n#define COLOUR_GREEN_BOLD\t\t\"\\033[1m\\033[32m\"\t// Bold Green\n#define COLOUR_YELLOW_BOLD\t\t\"\\033[1m\\033[33m\"\t// Bold Yellow\n#define COLOUR_BLUE_BOLD\t\t\"\\033[1m\\033[34m\"\t// Bold Blue\n#define COLOUR_MAGENTA_BOLD\t\t\"\\033[1m\\033[35m\"\t// Bold Magenta\n#define COLOUR_CYAN_BOLD\t\t\"\\033[1m\\033[36m\"\t// Bold Cyan\n#define COLOUR_WHITE_BOLD\t\t\"\\033[1m\\033[37m\"\t// Bold White\n#define COLOUR_GREY_BOLD\t\t\"\\033[30;1m\"\t\t// Bold Grey\n\ntemplate <typename... Ts> std::string strbold(const char* fmt, Ts&&... ts)\n{\n\treturn std::string(COLOUR_RESET) + std::string(COLOUR_BLACK_BOLD) + strprintf(fmt, ts...) + std::string(COLOUR_RESET);\n}\n\nnamespace sst\n{\n\tstruct StateTree;\n\n\tstruct Scope\n\t{\n\t\tScope() { }\n\t\tScope(StateTree* st);\n\n\t\tStateTree* stree = 0;\n\t\tconst Scope* prev = 0;\n\n\t\tmutable std::vector<std::string> cachedComponents;\n\n\t\tstd::string string() const;\n\t\tconst std::vector<std::string>& components() const;\n\t\tconst Scope& appending(const std::string& name) const;\n\t};\n}\n\nstruct Identifier\n{\n\tIdentifier() : name(\"\"), kind(IdKind::Invalid) { }\n\tIdentifier(const std::string& n, IdKind k) : name(n), kind(k) { }\n\n\tstd::string name;\n\tsst::Scope scope;\n\tstd::vector<fir::Type*> params;\n\tfir::Type* returnType = nullptr;\n\n\tIdKind kind;\n\n\tstd::string str() const;\n\tstd::string mangled___() const;\n\tfir::Name convertToName() const;\n\n\tbool operator == (const Identifier& other) const;\n\tbool operator != (const Identifier& other) const;\n};\n\n\nstruct Location\n{\n\tsize_t fileID = 0;\n\tsize_t line = 0;\n\tsize_t col = 0;\n\tsize_t len = 0;\n\n\tbool operator == (const Location& other) const\n\t{\n\t\treturn this->col == other.col && this->line == other.line && this->len == other.len && this->fileID == other.fileID;\n\t}\n\n\tbool operator != (const Location& other) const\n\t{\n\t\treturn !(*this == other);\n\t}\n\n\tLocation unionWith(const Location& x) const\n\t{\n\t\treturn unionOf(*this, x);\n\t}\n\n\tstatic Location unionOf(const Location& a, const Location& b)\n\t{\n\t\tif(a.fileID != b.fileID || a.line != b.line)\n\t\t\treturn a;\n\n\t\tLocation ret;\n\t\tret.fileID = a.fileID;\n\t\tret.line = a.line;\n\n\t\tauto end = std::max(a.col + a.len, b.col + b.len);\n\t\tif(a.col <= b.col)\n\t\t{\n\t\t\tret.col = a.col;\n\t\t}\n\t\telse if(b.col < a.col)\n\t\t{\n\t\t\tret.col = b.col;\n\t\t}\n\n\t\tret.len = (end - ret.col);\n\n\t\treturn ret;\n\t}\n\n\tstd::string toString() const;\n\tstd::string shortString() const;\n};\n\nstruct Locatable\n{\n\tLocatable(const Location& l, const std::string& readable) : loc(l), readableName(readable) { }\n\tvirtual ~Locatable() { }\n\n\tLocation loc;\n\tstd::string readableName;\n};\n\n\nstruct BareError;\nstruct SpanError;\nstruct SimpleError;\nstruct OverloadError;\nstruct ExampleMsg;\n\n//? in order of complexity, i guess?\nenum class ErrKind\n{\n\tBare,           // error without context\n\tSimple,         // error with context\n\n\tSpan,           // error with context, but with squiggles within those (general case of\n\tOverload,       // most complex one; built specifically to handle multiple candidates and such\n\n\tExample,        // same as a SimpleError, but we give the \"context\" as a string.\n};\n\nenum class MsgType\n{\n\tNote,\n\tWarning,\n\tError\n};\n\nnamespace util\n{\n\tstruct ESpan\n\t{\n\t\tESpan() { }\n\t\tESpan(const Location& l, const std::string& m) : loc(l), msg(m) { }\n\n\t\tLocation loc;\n\t\tstd::string msg;\n\t\tstd::string colour;\n\t};\n\n\tBareError* make_BareError(const std::string& m, MsgType t = MsgType::Error);\n\tSpanError* make_SpanError(SimpleError* se, const std::vector<ESpan>& s = { }, MsgType t = MsgType::Error);\n\tSimpleError* make_SimpleError(const Location& l, const std::string& m, MsgType t = MsgType::Error);\n\tOverloadError* make_OverloadError(SimpleError* se, MsgType t = MsgType::Error);\n\tExampleMsg* make_ExampleMsg(const std::string& eg, MsgType t = MsgType::Note);\n\n\n}\n\n\n\n\nstruct ErrorMsg\n{\n\tvirtual ~ErrorMsg() { }\n\n\tvirtual void post() = 0;\n\tvirtual ErrorMsg* append(ErrorMsg* e) { this->subs.push_back(e); return this; }\n\tvirtual ErrorMsg* prepend(ErrorMsg* e) { this->subs.insert(this->subs.begin(), e); return this; }\n\n\t[[noreturn]] void postAndQuit()\n\t{\n\t\tthis->post();\n\t\tdoTheExit();\n\t}\n\n\tErrKind kind;\n\tMsgType type;\n\tstd::vector<ErrorMsg*> subs;\n\n\tprotected:\n\tErrorMsg(ErrKind k, MsgType t) : kind(k), type(t) { }\n\n\ttemplate <typename, size_t> friend struct util::MemoryPool;\n\ttemplate <typename, size_t> friend struct util::FastInsertVector;\n};\n\nstruct BareError : ErrorMsg\n{\n\ttemplate <typename... Ts>\n\tstatic BareError* make(const char* fmt, Ts&&... ts) { return util::make_BareError(strprintf(fmt, ts...)); }\n\n\ttemplate <typename... Ts>\n\tstatic BareError* make(MsgType t, const char* fmt, Ts&&... ts) { return util::make_BareError(strprintf(fmt, ts...), t); }\n\n\tvirtual void post() override;\n\tvirtual BareError* append(ErrorMsg* e) override { this->subs.push_back(e); return this; }\n\tvirtual BareError* prepend(ErrorMsg* e) override { this->subs.insert(this->subs.begin(), e); return this; }\n\n\tstd::string msg;\n\n\tprotected:\n\tBareError() : ErrorMsg(ErrKind::Bare, MsgType::Error) { }\n\tBareError(const std::string& m, MsgType t) : ErrorMsg(ErrKind::Bare, t), msg(m) { }\n\n\ttemplate <typename, size_t> friend struct util::MemoryPool;\n\ttemplate <typename, size_t> friend struct util::FastInsertVector;\n};\n\nstruct SimpleError : ErrorMsg\n{\n\ttemplate <typename... Ts>\n\tstatic SimpleError* make(const Location& l, const char* fmt, Ts&&... ts)\n\t{ return util::make_SimpleError(l, strprintf(fmt, ts...)); }\n\n\ttemplate <typename... Ts>\n\tstatic SimpleError* make(MsgType t, const Location& l, const char* fmt, Ts&&... ts)\n\t{ return util::make_SimpleError(l, strprintf(fmt, ts...), t); }\n\n\n\tvirtual void post() override;\n\tvirtual SimpleError* append(ErrorMsg* e) override { this->subs.push_back(e); return this; }\n\tvirtual SimpleError* prepend(ErrorMsg* e) override { this->subs.insert(this->subs.begin(), e); return this; }\n\n\tLocation loc;\n\tstd::string msg;\n\n\t// just a hacky thing to print some words (eg. '(call site)') before the context.\n\tbool printContext = true;\n\tstd::string wordsBeforeContext;\n\n\tprotected:\n\tSimpleError() : ErrorMsg(ErrKind::Simple, MsgType::Error) { }\n\tSimpleError(const Location& l, const std::string& m, MsgType t) : ErrorMsg(ErrKind::Bare, t), loc(l), msg(m) { }\n\n\ttemplate <typename, size_t> friend struct util::MemoryPool;\n\ttemplate <typename, size_t> friend struct util::FastInsertVector;\n};\n\nstruct ExampleMsg : ErrorMsg\n{\n\tstatic ExampleMsg* make(const std::string& eg) { return util::make_ExampleMsg(eg); }\n\n\tvirtual void post() override;\n\tvirtual ExampleMsg* append(ErrorMsg* e) override { this->subs.push_back(e); return this; }\n\tvirtual ExampleMsg* prepend(ErrorMsg* e) override { this->subs.insert(this->subs.begin(), e); return this; }\n\n\tstd::string example;\n\n\tprotected:\n\tExampleMsg() : ErrorMsg(ErrKind::Example, MsgType::Note) { }\n\tExampleMsg(const std::string& eg, MsgType t) : ErrorMsg(ErrKind::Example, t), example(eg) { }\n\n\ttemplate <typename, size_t> friend struct util::MemoryPool;\n\ttemplate <typename, size_t> friend struct util::FastInsertVector;\n};\n\n\n\n\nstruct SpanError : ErrorMsg\n{\n\tSpanError* add(const util::ESpan& s);\n\n\tstatic SpanError* make(SimpleError* se = 0, const std::vector<util::ESpan>& s = { }) { return util::make_SpanError(se, s, MsgType::Error); }\n\tstatic SpanError* make(MsgType t, SimpleError* se = 0, const std::vector<util::ESpan>& s = { }) { return util::make_SpanError(se, s, t); }\n\n\n\tvirtual void post() override;\n\tvirtual SpanError* append(ErrorMsg* e) override { this->subs.push_back(e); return this; }\n\tvirtual SpanError* prepend(ErrorMsg* e) override { this->subs.insert(this->subs.begin(), e); return this; }\n\n\tSimpleError* top = 0;\n\tstd::vector<util::ESpan> spans;\n\n\t// again, another internal flag; this one controls whether or not to underline the original location.\n\tbool highlightActual = true;\n\n\tprotected:\n\tSpanError() : SpanError(0, { }, MsgType::Error) { }\n\tSpanError(SimpleError* se, const std::vector<util::ESpan>& s, MsgType t) : ErrorMsg(ErrKind::Span, t), top(se), spans(s) { }\n\n\n\ttemplate <typename, size_t> friend struct util::MemoryPool;\n\ttemplate <typename, size_t> friend struct util::FastInsertVector;\n};\n\n\n\nstruct OverloadError : ErrorMsg\n{\n\tvoid clear();\n\n\tstatic OverloadError* make(SimpleError* se = 0) { return util::make_OverloadError(se, MsgType::Error); }\n\tstatic OverloadError* make(MsgType t, SimpleError* se = 0) { return util::make_OverloadError(se, t); }\n\n\tvirtual void post() override;\n\tvirtual OverloadError* append(ErrorMsg* e) override { this->subs.push_back(e); return this; }\n\tvirtual OverloadError* prepend(ErrorMsg* e) override { this->subs.insert(this->subs.begin(), e); return this; }\n\n\tOverloadError& addCand(Locatable* d, ErrorMsg* e);\n\n\n\tSimpleError* top = 0;\n\tutil::hash_map<Locatable*, ErrorMsg*> cands;\n\n\tprotected:\n\tOverloadError() : ErrorMsg(ErrKind::Overload, MsgType::Error) { }\n\tOverloadError(SimpleError* se, MsgType t) : ErrorMsg(ErrKind::Overload, t), top(se) { }\n\n\ttemplate <typename, size_t> friend struct util::MemoryPool;\n\ttemplate <typename, size_t> friend struct util::FastInsertVector;\n};\n\n\n\n\nstruct ErrorException : public std::exception\n{\n\tErrorException(ErrorMsg* msg) : err(msg) { }\n\n\tErrorMsg* err;\n};\n\n\nstruct TCResult\n{\n\tenum class RK\n\t{\n\t\tInvalid,\n\n\t\tStatement,\n\t\tExpression,\n\t\tDefinition,\n\n\t\tParametric,\n\t\tDummy,\n\n\t\tError\n\t};\n\n\tunion {\n\t\tsst::Stmt* _st;\n\t\tsst::Expr* _ex;\n\t\tsst::Defn* _df;\n\t\tErrorMsg* _pe;\n\t};\n\n\tRK _kind = RK::Invalid;\n\n\t~TCResult() { }\n\n\tTCResult(RK k) :  _kind(k)                                  { _st = 0; }\n\texplicit TCResult(sst::Stmt* s) : _kind(RK::Statement)      { _st = s; }\n\texplicit TCResult(sst::Expr* e) : _kind(RK::Expression)     { _ex = e; }\n\texplicit TCResult(sst::Defn* d) : _kind(RK::Definition)     { _df = d; }\n\n\texplicit TCResult(ErrorMsg* pe) : _kind(RK::Error) { _pe = pe; }\n\n\tTCResult(const TCResult& r)\n\t{\n\t\tthis->_kind = r._kind;\n\n\t\tif(this->isError())     this->_pe = r._pe;\n\t\telse if(this->isStmt()) this->_st = r._st;\n\t\telse if(this->isExpr()) this->_ex = r._ex;\n\t\telse if(this->isDefn()) this->_df = r._df;\n\t}\n\n\tTCResult(TCResult&& r) noexcept\n\t{\n\t\tthis->_kind = r._kind;\n\n\t\tif(this->isError())     { this->_pe = r._pe; r._pe = 0; }\n\t\telse if(this->isStmt()) { this->_st = r._st; r._st = 0; }\n\t\telse if(this->isExpr()) { this->_ex = r._ex; r._ex = 0; }\n\t\telse if(this->isDefn()) { this->_df = r._df; r._df = 0; }\n\t}\n\n\tTCResult& operator = (const TCResult& r)\n\t{\n\t\tTCResult tmp(r);\n\t\t*this = std::move(tmp);\n\t\treturn *this;\n\t}\n\n\tTCResult& operator = (TCResult&& r) noexcept\n\t{\n\t\tif(&r != this)\n\t\t{\n\t\t\tthis->_kind = r._kind;\n\n\t\t\tif(this->isError())     { this->_pe = r._pe; r._pe = 0; }\n\t\t\telse if(this->isStmt()) { this->_st = r._st; r._st = 0; }\n\t\t\telse if(this->isExpr()) { this->_ex = r._ex; r._ex = 0; }\n\t\t\telse if(this->isDefn()) { this->_df = r._df; r._df = 0; }\n\t\t}\n\n\t\treturn *this;\n\t}\n\n\n\n\tErrorMsg* error() const    { if(this->_kind != RK::Error || !this->_pe) { _error_and_exit(\"not error\\n\"); } return this->_pe; }\n\n\tsst::Expr* expr() const;\n\tsst::Defn* defn() const;\n\n\t//* stmt() is the most general case -- definitions and expressions are both statements.\n\t// note: we need the definition of sst::Stmt and sst::Expr to do safe dynamic casting, so it's in identifier.cpp.\n\tsst::Stmt* stmt() const;\n\n\tbool isError() const        { return this->_kind == RK::Error; }\n\tbool isStmt() const         { return this->_kind == RK::Statement; }\n\tbool isExpr() const         { return this->_kind == RK::Expression; }\n\tbool isDefn() const         { return this->_kind == RK::Definition; }\n\tbool isParametric() const   { return this->_kind == RK::Parametric; }\n\tbool isDummy() const        { return this->_kind == RK::Dummy; }\n\n\tstatic TCResult getParametric() { return TCResult(RK::Parametric); }\n\tstatic TCResult getDummy()      { return TCResult(RK::Dummy); }\n};\n\n\n\n\n\n\n\n\nstruct CGResult\n{\n\tenum class VK\n\t{\n\t\tInvalid,\n\n\t\tNormal,\n\t\tEarlyOut,\n\t};\n\n\tCGResult() : CGResult(0) { }\n\texplicit CGResult(fir::Value* v) noexcept : value(v), kind(VK::Normal) { }\n\texplicit CGResult(fir::Value* v, VK k) noexcept : value(v), kind(k) { }\n\n\tfir::Value* operator -> () { return this->value; }\n\n\tfir::Value* value = 0;\n\tVK kind = VK::Invalid;\n};\n\nnamespace std\n{\n\ttemplate<>\n\tstruct hash<Identifier>\n\t{\n\t\tstd::size_t operator()(const Identifier& k) const\n\t\t{\n\t\t\tusing std::size_t;\n\t\t\tusing std::hash;\n\t\t\tusing std::string;\n\n\t\t\t// Compute individual hash values for first,\n\t\t\t// second and third and combine them using XOR\n\t\t\t// and bit shifting:\n\n\t\t\t// return ((hash<string>()(k.name) ^ (hash<std::vector<std::string>>()(k.scope) << 1)) >> 1) ^ (hash<int>()(k.third) << 1);\n\t\t\treturn hash<string>()(k.str());\n\t\t}\n\t};\n}\n\n\nenum class VisibilityLevel\n{\n\tInvalid,\n\n\tPublic,\n\tPrivate,\n\tInternal,\n};\n\nstruct TypeConstraints_t\n{\n\tstd::vector<std::string> protocols;\n\tint pointerDegree = 0;\n\n\tbool operator == (const TypeConstraints_t& other) const\n\t{\n\t\treturn this->protocols == other.protocols && this->pointerDegree == other.pointerDegree;\n\t}\n};\n\nusing TypeParamMap_t = util::hash_map<std::string, fir::Type*>;\n\nstruct PolyArgMapping_t\n{\n\tstruct SingleArg\n\t{\n\t\tsize_t index;\n\t\tstd::string name;\n\n\t\tpts::Type* type;\n\t};\n\n\tstd::vector<SingleArg> maps;\n\n\tbool empty() const { return maps.empty(); }\n\tvoid add(const std::string& name, pts::Type* t);\n\tvoid add(size_t idx, pts::Type* t);\n\n\tstd::string print() const;\n\n\tstatic inline PolyArgMapping_t none() { return PolyArgMapping_t(); }\n};\n\n\nnamespace util\n{\n\tstd::string typeParamMapToString(const std::string& name, const TypeParamMap_t& map);\n\n\ttemplate <typename T>\n\tstd::string listToEnglish(const std::vector<T>& list, bool quote = true)\n\t{\n\t\tauto printitem = [quote](const T& i) -> std::string {\n\t\t\treturn strprintf(\"%s%s%s\", quote ? \"'\" : \"\", i, quote ? \"'\" : \"\");\n\t\t};\n\n\t\tstd::string mstr;\n\t\tif(list.size() == 1)\n\t\t{\n\t\t\tmstr = printitem(list[0]);\n\t\t}\n\t\telse if(list.size() == 2)\n\t\t{\n\t\t\tmstr = strprintf(\"%s and %s\", printitem(list[0]), printitem(list[1]));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor(size_t i = 0; i < list.size() - 1; i++)\n\t\t\t\tmstr += strprintf(\"%s, \", printitem(list[i]));\n\n\t\t\t// oxford comma is important.\n\t\t\tmstr += strprintf(\"and %s\", printitem(list.back()));\n\t\t}\n\n\t\treturn mstr;\n\t}\n\n}\n\n\n\n\n\n\n\nnamespace Operator\n{\n\textern const std::string Plus;\n\textern const std::string Minus;\n\textern const std::string Multiply;\n\textern const std::string Divide;\n\textern const std::string Modulo;\n\n\textern const std::string UnaryPlus;\n\textern const std::string UnaryMinus;\n\n\textern const std::string PointerDeref;\n\textern const std::string AddressOf;\n\n\textern const std::string BitwiseNot;\n\textern const std::string BitwiseAnd;\n\textern const std::string BitwiseOr;\n\textern const std::string BitwiseXor;\n\textern const std::string BitwiseShiftLeft;\n\textern const std::string BitwiseShiftRight;\n\n\textern const std::string LogicalNot;\n\textern const std::string LogicalAnd;\n\textern const std::string LogicalOr;\n\n\textern const std::string CompareEQ;\n\textern const std::string CompareNEQ;\n\textern const std::string CompareLT;\n\textern const std::string CompareLEQ;\n\textern const std::string CompareGT;\n\textern const std::string CompareGEQ;\n\n\textern const std::string Assign;\n\textern const std::string PlusEquals;\n\textern const std::string MinusEquals;\n\textern const std::string MultiplyEquals;\n\textern const std::string DivideEquals;\n\textern const std::string ModuloEquals;\n\textern const std::string BitwiseShiftLeftEquals;\n\textern const std::string BitwiseShiftRightEquals;\n\textern const std::string BitwiseXorEquals;\n\textern const std::string BitwiseAndEquals;\n\textern const std::string BitwiseOrEquals;\n\n\textern const std::string TypeCast;\n\textern const std::string TypeIs;\n\n\n\tstd::string getNonAssignmentVersion(const std::string& op);\n\tbool isArithmetic(const std::string& op);\n\tbool isComparison(const std::string& op);\n\tbool isAssignment(const std::string& op);\n\tbool isBitwise(const std::string& op);\n}\n\n\n\n// https://stackoverflow.com/questions/28367913/how-to-stdhash-an-unordered-stdpair\n\ntemplate<typename T>\nvoid _hash_combine(std::size_t& seed, const T& key)\n{\n\tstd::hash<T> hasher;\n\tseed ^= hasher(key) + 0x9e3779b9 + (seed << 6) + (seed >> 2);\n}\n\nnamespace std\n{\n\ttemplate<typename T1, typename T2>\n\tstruct hash<std::pair<T1, T2>>\n\t{\n\t\tsize_t operator () (const std::pair<T1, T2>& p) const\n\t\t{\n\t\t\tsize_t seed = 0;\n\t\t\t_hash_combine(seed, p.first);\n\t\t\t_hash_combine(seed, p.second);\n\t\t\treturn seed;\n\t\t}\n\t};\n}\n\n\n\n\n\n\n\n\n// defer implementation\n// credit: gingerBill\n// shamelessly stolen from https://github.com/gingerBill/gb\n\n\nnamespace __dontlook\n{\n\t// NOTE(bill): Stupid fucking templates\n\ttemplate <typename T> struct gbRemoveReference       { typedef T Type; };\n\ttemplate <typename T> struct gbRemoveReference<T &>  { typedef T Type; };\n\ttemplate <typename T> struct gbRemoveReference<T &&> { typedef T Type; };\n\n\t/// NOTE(bill): \"Move\" semantics - invented because the C++ committee are idiots (as a collective not as indiviuals (well a least some aren't))\n\ttemplate <typename T> inline T &&gb_forward(typename gbRemoveReference<T>::Type &t)  { return static_cast<T &&>(t); }\n\ttemplate <typename T> inline T &&gb_forward(typename gbRemoveReference<T>::Type &&t) { return static_cast<T &&>(t); }\n\ttemplate <typename T> inline T &&gb_move   (T &&t)                                   { return static_cast<typename gbRemoveReference<T>::Type &&>(t); }\n\ttemplate <typename F>\n\tstruct gbprivDefer {\n\t\tF f;\n\t\tgbprivDefer(F &&f) : f(gb_forward<F>(f)) {}\n\t\t~gbprivDefer() { f(); }\n\t};\n\ttemplate <typename F> gbprivDefer<F> gb__defer_func(F &&f) { return gbprivDefer<F>(gb_forward<F>(f)); }\n}\n\n#define GB_DEFER_1(x, y) x##y\n#define GB_DEFER_2(x, y) GB_DEFER_1(x, y)\n#define GB_DEFER_3(x)    GB_DEFER_2(x, __COUNTER__)\n#define defer(code) auto GB_DEFER_3(_defer_) = __dontlook::gb__defer_func([&]()->void{code;})\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/errors.h",
    "content": "// errors.h\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#include \"defs.h\"\n\n#include \"precompile.h\"\n\ntemplate <typename... Ts>\ninline void debuglog(const char* s, Ts&&... ts)\n{\n\t// auto out = tinyformat::format(s, ts...);\n\tauto out = strprintf(s, ts...);\n\tfprintf(stderr, \"%s\", out.c_str());\n}\n\ntemplate <typename... Ts>\ninline void debuglogln(const char* s, Ts&&... ts)\n{\n\tauto out = strprintf(s, ts...);\n\tfprintf(stderr, \"%s\\n\", out.c_str());\n}\n\n\n\n#define INTUNSPEC_TYPE_STRING\t\t\t\"int\"\n#define UINTUNSPEC_TYPE_STRING\t\t\t\"uint\"\n\n#define FLOAT_TYPE_STRING\t\t\t\t\"float\"\n#define DOUBLE_TYPE_STRING\t\t\t\t\"double\"\n\n#define INT8_TYPE_STRING\t\t\t\t\"i8\"\n#define INT16_TYPE_STRING\t\t\t\t\"i16\"\n#define INT32_TYPE_STRING\t\t\t\t\"i32\"\n#define INT64_TYPE_STRING\t\t\t\t\"i64\"\n#define INT128_TYPE_STRING\t\t\t\t\"i128\"\n\n#define UINT8_TYPE_STRING\t\t\t\t\"u8\"\n#define UINT16_TYPE_STRING\t\t\t\t\"u16\"\n#define UINT32_TYPE_STRING\t\t\t\t\"u32\"\n#define UINT64_TYPE_STRING\t\t\t\t\"u64\"\n#define UINT128_TYPE_STRING\t\t\t\t\"u128\"\n\n#define FLOAT32_TYPE_STRING\t\t\t\t\"f32\"\n#define FLOAT64_TYPE_STRING\t\t\t\t\"f64\"\n#define FLOAT128_TYPE_STRING\t\t\t\"f128\"\n\n#define STRING_TYPE_STRING\t\t\t\t\"string\"\n#define CHARACTER_TYPE_STRING\t\t\t\"char\"\n#define CHARACTER_SLICE_TYPE_STRING\t\t\"str\"\n\n#define UNICODE_STRING_TYPE_STRING\t\t\"ustring\"\n#define UNICODE_CHARACTER_TYPE_STRING\t\"rune\"\n\n#define BOOL_TYPE_STRING\t\t\t\t\"bool\"\n#define VOID_TYPE_STRING\t\t\t\t\"void\"\n\n#define ANY_TYPE_STRING\t\t\t\t\t\"any\"\n\n\n\n\n\n\n\n\nnamespace frontend\n{\n\tconst std::string& getFilenameFromID(size_t fileID);\n\tstd::string getFilenameFromPath(const std::string& path);\n}\n\n\nstd::string __error_gen_internal(const Location& loc, const std::string& msg, const char* type, bool context, bool multiPart);\n\ntemplate <typename... Ts>\nstd::string __error_gen(const Location& loc, const char* msg, const char* type, bool, Ts&&... ts)\n{\n\treturn __error_gen_internal(loc, strprintf(msg, ts...), type, true, false);\n}\n\n\n#define ERROR_FUNCTION(name, type, attr, doexit)                                                                        \\\ntemplate <typename... Ts> [[attr]] void name (const char* fmt, Ts&&... ts)                                              \\\n{ fputs(__error_gen(Location(), fmt, type, doexit, ts...).c_str(), stderr); if(doexit) doTheExit(false); }              \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\ntemplate <typename... Ts> [[attr]] void name (Locatable* e, const char* fmt, Ts&&... ts)                                \\\n{ fputs(__error_gen(e ? e->loc : Location(), fmt, type, doexit, ts...).c_str(), stderr); if(doexit) doTheExit(false); } \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\ntemplate <typename... Ts> [[attr]] void name (const Location& loc, const char* fmt, Ts&&... ts)                         \\\n{ fputs(__error_gen(loc, fmt, type, doexit, ts...).c_str(), stderr); if(doexit) doTheExit(false); }\n\n\n\nERROR_FUNCTION(error, \"error\", noreturn, true);\nERROR_FUNCTION(info, \"note\", maybe_unused, false);\nERROR_FUNCTION(warn, \"warning\", maybe_unused, false);\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/frontend.h",
    "content": "// frontend.h\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#include \"precompile.h\"\n\n#include \"lexer.h\"\n#include \"parser.h\"\n#include \"platform.h\"\n\n#include <stack>\n#include <unordered_set>\n\n\nnamespace sst\n{\n\tstruct DefinitionTree;\n}\n\nnamespace fir\n{\n\tstruct Module;\n}\n\nnamespace backend\n{\n\tenum class BackendOption;\n\tenum class ProgOutputMode;\n\tenum class OptimisationLevel;\n}\n\nnamespace frontend\n{\n\tstd::string getParameter(const std::string& arg);\n\tstd::string getVersion();\n\n\tbackend::ProgOutputMode getOutputMode();\n\tbackend::OptimisationLevel getOptLevel();\n\tbackend::BackendOption getBackendOption();\n\n\tbool getPrintFIR();\n\tbool getPrintLLVMIR();\n\n\tbool getPrintProfileStats();\n\tbool getAbortOnError();\n\n\tbool getCanFFIEscape();\n\tbool getIsFreestanding();\n\tbool getIsNoStandardLibraries();\n\tbool getIsPositionIndependent();\n\n\tbool getIsNoRuntimeChecks();\n\tbool getIsNoRuntimeErrorStrings();\n\n\tbool getIsReplMode();\n\n\tstd::vector<std::string> getFrameworksToLink();\n\tstd::vector<std::string> getFrameworkSearchPaths();\n\tstd::vector<std::string> getLibrariesToLink();\n\tstd::vector<std::string> getLibrarySearchPaths();\n\n\tstruct DependencyGraph;\n\tstruct CollectorState\n\t{\n\t\tstd::unordered_set<std::string> importedFiles;\n\t\tstd::map<std::string, parser::ParsedFile> parsed;\n\t\tutil::hash_map<std::string, sst::DefinitionTree*> dtrees;\n\n\t\tutil::hash_map<std::string, parser::CustomOperatorDecl> binaryOps;\n\t\tutil::hash_map<std::string, parser::CustomOperatorDecl> prefixOps;\n\t\tutil::hash_map<std::string, parser::CustomOperatorDecl> postfixOps;\n\n\t\tDependencyGraph* graph = 0;\n\t\tstd::string fullMainFile;\n\t\tstd::vector<std::string> allFiles;\n\n\t\tsize_t nativeWordSize = 0;\n\n\t\t// for statistics i guess\n\t\tsize_t totalLinesOfCode = 0;\n\t};\n\n\t// fir::Module* collectFiles(std::string filename);\n\tvoid collectFiles(const std::string& mainfile, CollectorState* state);\n\tvoid parseFiles(CollectorState* state);\n\tsst::DefinitionTree* typecheckFiles(CollectorState* state);\n\tfir::Module* generateFIRModule(CollectorState* state, sst::DefinitionTree* maintree);\n\n\n\tstd::pair<std::string, std::string> parseCmdLineOpts(int argc, char** argv);\n\n\n\tstruct FileInnards\n\t{\n\t\tlexer::TokenList tokens;\n\t\tstd::string_view fileContents;\n\t\tutil::FastInsertVector<std::string_view> lines;\n\t\tstd::vector<size_t> importIndices;\n\n\t\tbool didLex = false;\n\t};\n\n\tFileInnards& getFileState(const std::string& name);\n\tFileInnards lexTokensFromString(const std::string& fakename, const std::string_view& str);\n\n\tstd::string getPathFromFile(const std::string& path);\n\tstd::string getFilenameFromPath(const std::string& path);\n\tstd::string getFullPathOfFile(const std::string& partial);\n\tstd::string removeExtensionFromFilename(const std::string& name);\n\n\tvoid cachePreExistingFilename(const std::string& name);\n\tstd::string getFileContents(const std::string& fullPath);\n\tconst std::string& getFilenameFromID(size_t fileID);\n\tsize_t getFileIDFromFilename(const std::string& name);\n\tlexer::TokenList& getFileTokens(const std::string& fullPath);\n\tconst util::FastInsertVector<std::string_view>& getFileLines(size_t id);\n\tconst std::vector<size_t>& getImportTokenLocationsForFile(const std::string& filename);\n\n\tstd::string resolveImport(const std::string& imp, const Location& loc, const std::string& fullPath);\n\n\tstruct ImportThing\n\t{\n\t\tstd::string name;\n\t\tstd::vector<std::string> importAs;\n\t\tbool pubImport = false;\n\n\t\tLocation loc;\n\t};\n\n\n\t// dependency system\n\tstruct DepNode\n\t{\n\t\tstd::string name;\n\n\t\t// mainly to aid error reporting\n\t\tstd::vector<std::pair<DepNode*, Location>> users;\n\n\t\tint index = -1;\n\t\tint lowlink = -1;\n\t\tbool onStack = false;\n\t};\n\n\tstruct Dep\n\t{\n\t\tDepNode* from = 0;\n\t\tDepNode* to = 0;\n\n\t\tImportThing ithing;\n\t};\n\n\tstruct DependencyGraph\n\t{\n\t\tstd::vector<DepNode*> nodes;\n\t\tstd::map<DepNode*, std::vector<Dep*>> edgesFrom;\n\n\t\tstd::stack<DepNode*> stack;\n\n\t\tstd::vector<Dep*> getDependenciesOf(const std::string& name);\n\t\tvoid addModuleDependency(const std::string& from, const std::string& to, const ImportThing& ithing);\n\t\tstd::vector<std::vector<DepNode*>> findCyclicDependencies();\n\t};\n\n\tstd::vector<std::string> checkForCycles(const std::string& topmod, frontend::DependencyGraph* graph);\n\tfrontend::DependencyGraph* buildDependencyGraph(frontend::DependencyGraph* graph, const std::string& full,\n\t\tutil::hash_map<std::string, bool>& visited);\n}\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/gluecode.h",
    "content": "// gluecode.h\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#include <stdint.h>\n\n#include <string>\n#include <vector>\n\n#include \"stcommon.h\"\n#include \"string_consts.h\"\n\n#define DEBUG_RUNTIME_GLUE_MASTER\t0\n\n#define DEBUG_STRING_MASTER\t\t\t(0 & DEBUG_RUNTIME_GLUE_MASTER)\n#define DEBUG_STRING_ALLOCATION\t\t(1 & DEBUG_STRING_MASTER)\n#define DEBUG_STRING_REFCOUNTING\t(1 & DEBUG_STRING_MASTER)\n\n#define DEBUG_ARRAY_MASTER\t\t\t(0 & DEBUG_RUNTIME_GLUE_MASTER)\n#define DEBUG_ARRAY_ALLOCATION\t\t(1 & DEBUG_ARRAY_MASTER)\n#define DEBUG_ARRAY_REFCOUNTING\t\t(1 & DEBUG_ARRAY_MASTER)\n\n#define DEBUG_ANY_MASTER\t\t\t(1 & DEBUG_RUNTIME_GLUE_MASTER)\n#define DEBUG_ANY_ALLOCATION\t\t(1 & DEBUG_ANY_MASTER)\n#define DEBUG_ANY_REFCOUNTING\t\t(1 & DEBUG_ANY_MASTER)\n\n#define BUILTIN_ANY_DATA_BYTECOUNT  32\n#define BUILTIN_ANY_FLAG_MASK       0x8000000000000000\n\n\nnamespace fir\n{\n\tstruct Value;\n\tstruct Function;\n\tstruct ClassType;\n\tstruct UnionType;\n\tstruct ArraySliceType;\n\tstruct DynamicArrayType;\n}\n\nnamespace sst\n{\n\tstruct FunctionDefn;\n}\n\nnamespace cgn\n{\n\tstruct CodegenState;\n\n\tnamespace glue\n\t{\n\t\tvoid printRuntimeError(CodegenState* cs, fir::Value* pos, const std::string& msg, const std::vector<fir::Value*>& args);\n\n\t\tnamespace string\n\t\t{\n\t\t\tfir::Function* getCloneFunction(CodegenState* cs);\n\t\t\tfir::Function* getAppendFunction(CodegenState* cs);\n\t\t\tfir::Function* getCompareFunction(CodegenState* cs);\n\t\t\tfir::Function* getCharAppendFunction(CodegenState* cs);\n\t\t\tfir::Function* getUnicodeLengthFunction(CodegenState* cs);\n\t\t\tfir::Function* getConstructFromTwoFunction(CodegenState* cs);\n\t\t\tfir::Function* getConstructWithCharFunction(CodegenState* cs);\n\t\t\tfir::Function* getRefCountIncrementFunction(CodegenState* cs);\n\t\t\tfir::Function* getRefCountDecrementFunction(CodegenState* cs);\n\t\t\tfir::Function* getBoundsCheckFunction(CodegenState* cs, bool isDecomp);\n\t\t}\n\n\t\tnamespace array\n\t\t{\n\t\t\tfir::Function* getCloneFunction(CodegenState* cs, fir::Type* arrtype);\n\t\t\tfir::Function* getAppendFunction(CodegenState* cs, fir::DynamicArrayType* arrtype);\n\t\t\tfir::Function* getPopElementFromBackFunction(CodegenState* cs, fir::Type* arrtype);\n\t\t\tfir::Function* getBoundsCheckFunction(CodegenState* cs, bool isPerformingDecomposition);\n\t\t\tfir::Function* getElementAppendFunction(CodegenState* cs, fir::DynamicArrayType* arrtype);\n\t\t\tfir::Function* getCompareFunction(CodegenState* cs, fir::Type* arrtype, fir::Function* opf);\n\t\t\tfir::Function* getConstructFromTwoFunction(CodegenState* cs, fir::DynamicArrayType* arrtype);\n\t\t\tfir::Function* getIncrementArrayRefCountFunction(CodegenState* cs, fir::Type* arrtype);\n\t\t\tfir::Function* getDecrementArrayRefCountFunction(CodegenState* cs, fir::Type* arrtype);\n\n\t\t\tfir::Function* getReserveExtraFunction(CodegenState* cs, fir::DynamicArrayType* arrtype);\n\t\t\tfir::Function* getReserveAtLeastFunction(CodegenState* cs, fir::DynamicArrayType* arrtype);\n\n\t\t\tfir::Function* getSetElementsToValueFunction(CodegenState* cs, fir::Type* elmType);\n\t\t\tfir::Function* getSetElementsToDefaultValueFunction(CodegenState* cs, fir::Type* elmType);\n\n\t\t\tfir::Function* getCallClassConstructorOnElementsFunction(CodegenState* cs, fir::ClassType* cls, sst::FunctionDefn* constr,\n\t\t\t\tconst std::vector<FnCallArgument>& args);\n\t\t}\n\n\t\tnamespace saa_common\n\t\t{\n\t\t\tfir::Function* generateCloneFunction(CodegenState* cs, fir::Type* saa);\n\t\t\tfir::Function* generateAppendFunction(CodegenState* cs, fir::Type* saa);\n\t\t\tfir::Function* generateElementAppendFunction(CodegenState* cs, fir::Type* saa);\n\t\t\tfir::Function* generateConstructFromTwoFunction(CodegenState* cs, fir::Type* saa);\n\t\t\tfir::Function* generateConstructWithElementFunction(CodegenState* cs, fir::Type* saa);\n\n\t\t\tfir::Function* generateAppropriateAppendFunction(CodegenState* cs, fir::Type* saa, fir::Type* appendee);\n\n\t\t\tfir::Function* generateBoundsCheckFunction(CodegenState* cs, bool isstring, bool isDecomp);\n\n\t\t\tfir::Function* generateReserveExtraFunction(CodegenState* cs, fir::Type* saa);\n\t\t\tfir::Function* generateReserveAtLeastFunction(CodegenState* cs, fir::Type* saa);\n\n\t\t\tfir::Value* makeNewRefCountPointer(CodegenState* cs, fir::Value* rc);\n\t\t\tfir::Value* initSAAWithRefCount(CodegenState* cs, fir::Value* str, fir::Value* rc);\n\t\t}\n\n\t\tnamespace any\n\t\t{\n\t\t\tfir::Function* getRefCountIncrementFunction(CodegenState* cs);\n\t\t\tfir::Function* getRefCountDecrementFunction(CodegenState* cs);\n\n\t\t\tfir::Function* generateCreateAnyWithValueFunction(CodegenState* cs, fir::Type* type);\n\t\t\tfir::Function* generateGetValueFromAnyFunction(CodegenState* cs, fir::Type* type);\n\t\t}\n\n\t\tnamespace misc\n\t\t{\n\t\t\tfir::Function* getMallocWrapperFunction(CodegenState* cs);\n\t\t\tfir::Function* getRangeSanityCheckFunction(CodegenState* cs);\n\n\t\t\tfir::Name getCompare_FName(fir::Type* t);\n\t\t\tfir::Name getSetElements_FName(fir::Type* t);\n\t\t\tfir::Name getSetElementsDefault_FName(fir::Type* t);\n\t\t\tfir::Name getCallClassConstructor_FName(fir::Type* t);\n\n\t\t\tfir::Name getClone_FName(fir::Type* t);\n\t\t\tfir::Name getAppend_FName(fir::Type* t);\n\t\t\tfir::Name getPopBack_FName(fir::Type* t);\n\t\t\tfir::Name getMakeFromTwo_FName(fir::Type* t);\n\t\t\tfir::Name getMakeFromOne_FName(fir::Type* t);\n\t\t\tfir::Name getReserveExtra_FName(fir::Type* t);\n\t\t\tfir::Name getAppendElement_FName(fir::Type* t);\n\t\t\tfir::Name getReserveEnough_FName(fir::Type* t);\n\t\t\tfir::Name getRecursiveRefcount_FName(fir::Type* t, bool incr);\n\n\t\t\tfir::Name getIncrRefcount_FName(fir::Type* t);\n\t\t\tfir::Name getDecrRefcount_FName(fir::Type* t);\n\n\t\t\tfir::Name getLoopIncrRefcount_FName(fir::Type* t);\n\t\t\tfir::Name getLoopDecrRefcount_FName(fir::Type* t);\n\n\t\t\tfir::Name getCreateAnyOf_FName(fir::Type* t);\n\t\t\tfir::Name getGetValueFromAny_FName(fir::Type* t);\n\n\t\t\tfir::Name getBoundsCheck_FName();\n\t\t\tfir::Name getDecompBoundsCheck_FName();\n\n\t\t\tfir::Name getMallocWrapper_FName();\n\t\t\tfir::Name getRangeSanityCheck_FName();\n\n\t\t\tfir::Name getUtf8Length_FName();\n\t\t}\n\t}\n}\n\n\n\n\n\n"
  },
  {
    "path": "source/include/ir/block.h",
    "content": "// block.h\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#include <stdint.h>\n#include <stddef.h>\n#include <limits.h>\n\n#include \"value.h\"\n#include \"instruction.h\"\n\nnamespace fir\n{\n\tstruct Function;\n\tstruct IRBuilder;\n\n\tstruct IRBlock : Value\n\t{\n\t\tfriend struct Module;\n\t\tfriend struct IRBuilder;\n\n\t\tIRBlock();\n\t\tIRBlock(Function* parentFunc);\n\n\t\tFunction* getParentFunction();\n\n\t\tvoid setFunction(Function* fn);\n\t\tvoid addInstruction(Instruction* inst);\n\t\tvoid eraseFromParentFunction();\n\n\t\tbool isTerminated();\n\n\t\tstd::vector<Instruction*>& getInstructions();\n\n\t\tprivate:\n\t\tFunction* parentFunction = 0;\n\t\tstd::vector<Instruction*> instructions;\n\t};\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/ir/constant.h",
    "content": "// constant.h\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#include <stdint.h>\n#include <stddef.h>\n#include <limits.h>\n\n#include \"value.h\"\n#include \"mpreal/mpreal.h\"\n\nnamespace fir\n{\n\tstruct Value;\n\tstruct ConstantValue;\n\n\t// base class implicitly stores null\n\tstruct ConstantValue : Value\n\t{\n\t\tfriend struct Module;\n\t\tfriend struct IRBuilder;\n\n\t\t// static stuff\n\t\tstatic ConstantValue* getZeroValue(Type* type);\n\t\tstatic ConstantValue* getNull();\n\n\t\tvirtual std::string str();\n\n\t\tprotected:\n\t\tConstantValue(Type* type);\n\t};\n\n\tstruct ConstantNumber : ConstantValue\n\t{\n\t\tfriend struct Module;\n\n\t\tstatic ConstantNumber* get(ConstantNumberType* cnt, const mpfr::mpreal& n);\n\n\t\tint8_t getInt8()        { return static_cast<int8_t>(this->number.toLLong()); }\n\t\tint16_t getInt16()      { return static_cast<int16_t>(this->number.toLLong()); }\n\t\tint32_t getInt32()      { return static_cast<int32_t>(this->number.toLLong()); }\n\t\tint64_t getInt64()      { return static_cast<int64_t>(this->number.toLLong()); }\n\t\tuint8_t getUint8()      { return static_cast<uint8_t>(this->number.toULLong()); }\n\t\tuint16_t getUint16()    { return static_cast<uint16_t>(this->number.toULLong()); }\n\t\tuint32_t getUint32()    { return static_cast<uint32_t>(this->number.toULLong()); }\n\t\tuint64_t getUint64()    { return static_cast<uint64_t>(this->number.toULLong()); }\n\n\t\tfloat getFloat()        { return this->number.toFloat(); }\n\t\tdouble getDouble()      { return this->number.toDouble(); }\n\n\t\tvirtual std::string str() override;\n\n\t\tprotected:\n\t\tConstantNumber(ConstantNumberType* cnt, const mpfr::mpreal& n);\n\n\t\tmpfr::mpreal number;\n\t};\n\n\tstruct ConstantBool : ConstantValue\n\t{\n\t\tfriend struct Module;\n\n\t\tstatic ConstantBool* get(bool value);\n\t\tbool getValue();\n\n\t\tvirtual std::string str() override;\n\n\t\tprotected:\n\t\tConstantBool(bool val);\n\n\t\tbool value;\n\t};\n\n\tstruct ConstantInt : ConstantValue\n\t{\n\t\tfriend struct Module;\n\n\t\tstatic ConstantInt* get(Type* intType, uint64_t val);\n\n\t\tstatic ConstantInt* getInt8(int8_t value);\n\t\tstatic ConstantInt* getInt16(int16_t value);\n\t\tstatic ConstantInt* getInt32(int32_t value);\n\t\tstatic ConstantInt* getInt64(int64_t value);\n\t\tstatic ConstantInt* getUint8(uint8_t value);\n\t\tstatic ConstantInt* getUint16(uint16_t value);\n\t\tstatic ConstantInt* getUint32(uint32_t value);\n\t\tstatic ConstantInt* getUint64(uint64_t value);\n\n\t\tstatic ConstantInt* getNative(int64_t value);\n\t\tstatic ConstantInt* getUNative(uint64_t value);\n\n\t\tint64_t getSignedValue();\n\t\tuint64_t getUnsignedValue();\n\n\t\tvirtual std::string str() override;\n\n\t\tprotected:\n\t\tConstantInt(Type* type, int64_t val);\n\t\tConstantInt(Type* type, uint64_t val);\n\n\t\tuint64_t value;\n\t};\n\n\n\tstruct ConstantFP : ConstantValue\n\t{\n\t\tfriend struct Module;\n\n\t\tstatic ConstantFP* get(Type* intType, float val);\n\t\tstatic ConstantFP* get(Type* intType, double val);\n\n\t\tstatic ConstantFP* getFloat32(float value);\n\t\tstatic ConstantFP* getFloat64(double value);\n\n\t\tdouble getValue();\n\n\t\tvirtual std::string str() override;\n\n\t\tprotected:\n\t\tConstantFP(Type* type, float val);\n\t\tConstantFP(Type* type, double val);\n\n\t\tdouble value;\n\t};\n\n\tstruct ConstantArray : ConstantValue\n\t{\n\t\tfriend struct Module;\n\n\t\tstatic ConstantArray* get(Type* type, const std::vector<ConstantValue*>& vals);\n\n\t\tstd::vector<ConstantValue*> getValues() { return this->values; }\n\n\t\tvirtual std::string str() override;\n\n\t\tprotected:\n\t\tConstantArray(Type* type, const std::vector<ConstantValue*>& vals);\n\n\t\tstd::vector<ConstantValue*> values;\n\t};\n\n\tstruct ConstantStruct : ConstantValue\n\t{\n\t\tfriend struct Module;\n\n\t\tstatic ConstantStruct* get(StructType* st, const std::vector<ConstantValue*>& members);\n\n\t\tvirtual std::string str() override;\n\n\t\tprotected:\n\t\tConstantStruct(StructType* st, const std::vector<ConstantValue*>& members);\n\t\tstd::vector<ConstantValue*> members;\n\t};\n\n\tstruct ConstantEnumCase : ConstantValue\n\t{\n\t\tfriend struct Module;\n\n\t\tstatic ConstantEnumCase* get(EnumType* en, ConstantInt* index, ConstantValue* value);\n\n\t\tConstantInt* getIndex();\n\t\tConstantValue* getValue();\n\n\t\tvirtual std::string str() override;\n\n\t\tprotected:\n\t\tConstantEnumCase(EnumType* en, ConstantInt* index, ConstantValue* value);\n\n\t\tConstantInt* index = 0;\n\t\tConstantValue* value = 0;\n\t};\n\n\tstruct ConstantCharSlice : ConstantValue\n\t{\n\t\tfriend struct Module;\n\n\t\tstatic ConstantCharSlice* get(const std::string& value);\n\t\tstd::string getValue();\n\n\t\tvirtual std::string str() override;\n\n\t\tprotected:\n\t\tConstantCharSlice(const std::string& str);\n\n\t\tstd::string value;\n\t};\n\n\tstruct ConstantTuple : ConstantValue\n\t{\n\t\tfriend struct Module;\n\n\t\tstatic ConstantTuple* get(const std::vector<ConstantValue*>& mems);\n\t\tstd::vector<ConstantValue*> getValues();\n\n\t\tvirtual std::string str() override;\n\n\t\tprotected:\n\t\tConstantTuple(const std::vector<ConstantValue*>& mems);\n\t\tstd::vector<ConstantValue*> values;\n\t};\n\n\tstruct ConstantDynamicArray : ConstantValue\n\t{\n\t\tfriend struct Module;\n\n\t\tstatic ConstantDynamicArray* get(DynamicArrayType* type, ConstantValue* data, ConstantValue* length, ConstantValue* capacity);\n\t\tstatic ConstantDynamicArray* get(ConstantArray* arr);\n\n\t\tConstantValue* getData() { return this->data; }\n\t\tConstantValue* getLength() { return this->length; }\n\t\tConstantValue* getCapacity() { return this->capacity; }\n\n\t\tConstantArray* getArray() { return this->arr; }\n\n\t\tvirtual std::string str() override;\n\n\t\tprotected:\n\t\tConstantDynamicArray(DynamicArrayType* type);\n\n\t\tConstantValue* data = 0;\n\t\tConstantValue* length = 0;\n\t\tConstantValue* capacity = 0;\n\n\t\tConstantArray* arr = 0;\n\t};\n\n\t// this is the 'string' type!!\n\tstruct ConstantDynamicString : ConstantValue\n\t{\n\t\tfriend struct Module;\n\n\t\tstatic ConstantDynamicString* get(const std::string& s);\n\t\tstd::string getValue();\n\n\t\tvirtual std::string str() override;\n\n\t\tprotected:\n\t\tConstantDynamicString(const std::string& s);\n\n\t\tstd::string value;\n\t};\n\n\n\tstruct ConstantArraySlice : ConstantValue\n\t{\n\t\tfriend struct Module;\n\n\t\tstatic ConstantArraySlice* get(ArraySliceType* type, ConstantValue* data, ConstantValue* length);\n\n\t\tConstantValue* getData() { return this->data; }\n\t\tConstantValue* getLength() { return this->length; }\n\n\t\tvirtual std::string str() override;\n\n\t\tprotected:\n\t\tConstantArraySlice(ArraySliceType* type);\n\n\t\tConstantValue* data = 0;\n\t\tConstantValue* length = 0;\n\t};\n\n\tstruct ConstantBitcast : ConstantValue\n\t{\n\t\tfriend struct Module;\n\n\t\tstatic ConstantBitcast* get(ConstantValue* v, Type* target);\n\n\t\tConstantValue* getValue() { return this->value; }\n\n\t\tvirtual std::string str() override;\n\n\t\tprotected:\n\t\tConstantBitcast(ConstantValue* v, Type* target);\n\n\t\tConstantValue* value = 0;\n\t\tType* target = 0;\n\t};\n\n\n\tstruct GlobalValue : ConstantValue\n\t{\n\t\tfriend struct Module;\n\n\t\tLinkageType linkageType;\n\n\t\tModule* getParentModule() { return this->parentModule; }\n\n\t\tvirtual std::string str() override;\n\n\t\tprotected:\n\t\tGlobalValue(Module* mod, Type* type, LinkageType linkage, bool mut = false);\n\n\t\tModule* parentModule = 0;\n\t};\n\n\tstruct GlobalVariable : GlobalValue\n\t{\n\t\tfriend struct Module;\n\n\t\tGlobalVariable(const Name& idt, Module* module, Type* type, bool immutable, LinkageType linkage, ConstantValue* initValue);\n\t\tvoid setInitialValue(ConstantValue* constVal);\n\t\tConstantValue* getInitialValue();\n\n\t\tvirtual std::string str() override;\n\n\t\tprotected:\n\t\tConstantValue* initValue = 0;\n\t};\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/ir/function.h",
    "content": "// function.h\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#include <stdint.h>\n#include <stddef.h>\n#include <limits.h>\n\n#include \"block.h\"\n#include \"constant.h\"\n\nnamespace fir\n{\n\tstruct Function;\n\tstruct IRBuilder;\n\tstruct Argument : Value\n\t{\n\t\tfriend struct Function;\n\t\tfriend struct IRBuilder;\n\n\t\t// virtual stuff\n\t\t// default: virtual Type* getType()\n\n\n\t\t// methods\n\t\tArgument(Function* fn, Type* type);\n\t\t~Argument();\n\n\t\tValue* getActualValue();\n\t\tFunction* getParentFunction();\n\n\n\t\tvoid setValue(Value* v);\n\t\tvoid clearValue();\n\n\t\t// fields\n\t\tprotected:\n\t\tFunction* parentFunction;\n\t\tValue* realValue = 0;\n\t};\n\n\n\tstruct Function : GlobalValue\n\t{\n\t\tfriend struct Module;\n\t\tfriend struct Argument;\n\t\tfriend struct IRBuilder;\n\n\t\tbool isCStyleVarArg();\n\t\tbool isVariadic();\n\n\t\tType* getReturnType();\n\t\tsize_t getArgumentCount();\n\t\tconst std::vector<Argument*>& getArguments();\n\t\tArgument* getArgumentWithName(std::string name);\n\n\t\tstd::vector<IRBlock*>& getBlockList();\n\t\tvoid deleteBody();\n\n\t\tbool wasDeclaredWithBodyElsewhere();\n\t\tvoid setHadBodyElsewhere();\n\n\t\tbool isAlwaysInlined();\n\t\tvoid setAlwaysInline();\n\n\t\tbool isIntrinsicFunction();\n\t\tvoid setIsIntrinsic();\n\n\t\t// this is used so the function knows how much space it needs to reserve for\n\t\t// allocas.\n\t\tvoid addStackAllocation(Type* ty);\n\t\tconst std::vector<Type*>& getStackAllocations();\n\n\t\tvoid cullUnusedValues();\n\n\t\t// overridden stuff\n\t\tvirtual FunctionType* getType() override; // override because better (more specific) return type.\n\n\t\tstatic Function* create(const Name& name, FunctionType* fnType, Module* module, LinkageType linkage);\n\n\n\t\t// fields\n\t\tprotected:\n\t\tFunction(const Name& name, FunctionType* fnType, Module* module, LinkageType linkage);\n\t\tstd::vector<Argument*> fnArguments;\n\t\tstd::vector<IRBlock*> blocks;\n\t\tstd::vector<Type*> stackAllocs;\n\n\t\tbool alwaysInlined = false;\n\t\tbool hadBodyElsewhere = false;\n\t\tbool fnIsIntrinsicFunction = false;\n\t};\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/ir/instruction.h",
    "content": "// instruction.h\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#include <stdint.h>\n#include <stddef.h>\n#include <limits.h>\n\n#include \"value.h\"\n\n\nnamespace fir\n{\n\tenum class OpKind\n\t{\n\t\tInvalid,\n\n\t\t// signed\n\t\tSigned_Add,\n\t\tSigned_Sub,\n\t\tSigned_Mul,\n\t\tSigned_Div,\n\t\tSigned_Mod,\n\t\tSigned_Neg,\n\n\t\t// unsigned\n\t\tUnsigned_Add,\n\t\tUnsigned_Sub,\n\t\tUnsigned_Mul,\n\t\tUnsigned_Div,\n\t\tUnsigned_Mod,\n\n\t\t// floating point\n\t\tFloating_Add,\n\t\tFloating_Sub,\n\t\tFloating_Mul,\n\t\tFloating_Div,\n\t\tFloating_Mod,\n\t\tFloating_Neg,\n\n\t\tFloating_Truncate,\n\t\tFloating_Extend,\n\n\t\t// comparison\n\t\tICompare_Equal,\n\t\tICompare_NotEqual,\n\t\tICompare_Greater,\n\t\tICompare_Less,\n\t\tICompare_GreaterEqual,\n\t\tICompare_LessEqual,\n\n\t\tICompare_Multi,\n\t\tFCompare_Multi,\n\n\t\tFCompare_Equal_ORD,\n\t\tFCompare_Equal_UNORD,\n\t\tFCompare_NotEqual_ORD,\n\t\tFCompare_NotEqual_UNORD,\n\t\tFCompare_Greater_ORD,\n\t\tFCompare_Greater_UNORD,\n\t\tFCompare_Less_ORD,\n\t\tFCompare_Less_UNORD,\n\t\tFCompare_GreaterEqual_ORD,\n\t\tFCompare_GreaterEqual_UNORD,\n\t\tFCompare_LessEqual_ORD,\n\t\tFCompare_LessEqual_UNORD,\n\n\t\t// bitwise\n\t\tBitwise_Not,\n\t\tBitwise_Xor,\n\t\tBitwise_Arithmetic_Shr,\n\t\tBitwise_Logical_Shr,\n\t\tBitwise_Shl,\n\t\tBitwise_And,\n\t\tBitwise_Or,\n\n\t\t// casting\n\t\tCast_Bitcast,\n\t\tCast_IntSize,\n\t\tCast_Signedness,\n\t\tCast_FloatToInt,\n\t\tCast_IntToFloat,\n\t\tCast_PointerType,\n\t\tCast_PointerToInt,\n\t\tCast_IntToPointer,\n\t\tCast_IntSignedness,\n\n\t\tInteger_ZeroExt,\n\t\tInteger_Truncate,\n\n\t\t// unary\n\t\tLogical_Not,\n\n\t\t// values\n\t\tValue_ReadPtr,\n\t\tValue_WritePtr,\n\t\tValue_StackAlloc,\n\t\tValue_CallFunction,\n\t\tValue_CallFunctionPointer,\n\t\tValue_CallVirtualMethod,\n\t\tValue_Return,\n\t\tValue_GetPointerToStructMember,\t\t// equivalent to GEP(ptr*, ptrIndex, memberIndex) -- for structs.\n\t\tValue_GetStructMember,\t\t\t\t// equivalent to GEP(ptr*, 0, memberIndex)\n\t\tValue_GetPointer,\t\t\t\t\t// equivalent to GEP(ptr*, index)\n\t\tValue_GetGEP2,\t\t\t\t\t\t// equivalent to GEP(ptr*, ptrIndex, elmIndex) -- for arrays/pointers\n\n\t\tValue_InsertValue,\t\t\t\t\t// corresponds to llvm.\n\t\tValue_ExtractValue,\t\t\t\t\t// same\n\n\t\tValue_Select,\t\t\t\t\t\t// same as llvm: takes 3 operands, the first being a bool and the others being a condition.\n\t\t\t\t\t\t\t\t\t\t\t// if the bool == true, returns the first value, else returns the second.\n\t\tValue_CreatePHI,\n\n\t\tMisc_Sizeof,\t\t\t\t\t\t// portable sizeof using GEP\n\n\t\tValue_Dereference,\n\t\tValue_AddressOf,\n\t\tValue_Store,\n\t\tValue_CreateLVal,\n\n\n\t\t// string-specific things\n\t\tSAA_GetData,\n\t\tSAA_SetData,\n\t\tSAA_GetLength,\n\t\tSAA_SetLength,\n\t\tSAA_GetCapacity,\n\t\tSAA_SetCapacity,\n\t\tSAA_GetRefCountPtr,\n\t\tSAA_SetRefCountPtr,\n\n\t\tArraySlice_GetData,\n\t\tArraySlice_SetData,\n\t\tArraySlice_GetLength,\n\t\tArraySlice_SetLength,\n\n\t\tAny_GetData,\n\t\tAny_SetData,\n\t\tAny_GetTypeID,\n\t\tAny_SetTypeID,\n\t\tAny_GetRefCountPtr,\n\t\tAny_SetRefCountPtr,\n\n\t\tRange_GetLower,\n\t\tRange_SetLower,\n\t\tRange_GetUpper,\n\t\tRange_SetUpper,\n\t\tRange_GetStep,\n\t\tRange_SetStep,\n\n\t\tEnum_GetIndex,\n\t\tEnum_SetIndex,\n\t\tEnum_GetValue,\n\t\tEnum_SetValue,\n\n\t\tUnion_SetValue,\n\t\tUnion_GetValue,\n\t\tUnion_GetVariantID,\n\t\tUnion_SetVariantID,\n\n\t\tRawUnion_GEP,\n\n\t\tBranch_UnCond,\n\t\tBranch_Cond,\n\n\n\t\tUnreachable,\n\t};\n\n\n\n\n\tstruct IRBuilder;\n\tstruct Instruction : Value\n\t{\n\t\tfriend struct Module;\n\t\tfriend struct IRBuilder;\n\n\t\tInstruction(OpKind kind, bool sideEffects, Type* out, const std::vector<Value*>& vals);\n\t\tInstruction(OpKind kind, bool sideEffects, Type* out, const std::vector<Value*>& vals, Value::Kind k);\n\t\tstd::string str();\n\n\t\tValue* getResult();\n\n\t\tvoid setValue(Value* v);\n\t\tvoid clearValue();\n\t\tbool hasSideEffects();\n\n\t\t// static Instruction* GetBinaryOpInstruction(Ast::ArithmeticOp ao, Value* lhs, Value* rhs);\n\n\n\t\t// protected:\n\t\tOpKind opKind;\n\n\t\tbool sideEffects;\n\t\tValue* realOutput;\n\t\tstd::vector<Value*> operands;\n\t};\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/ir/interp.h",
    "content": "// interp.h\n// Copyright (c) 2017, zhiayang@gmail.com\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#include <stdint.h>\n#include <stddef.h>\n\n#include <vector>\n#include <string>\n#include <unordered_map>\n\nnamespace fir\n{\n\tstruct Type;\n\tstruct Value;\n\tstruct Module;\n\tstruct IRBlock;\n\tstruct Function;\n\tstruct GlobalValue;\n\tstruct ConstantValue;\n\n\tnamespace interp\n\t{\n\t\t//? is it bad form to name these the same as our fir structs??\n\n\t\tstruct Value\n\t\t{\n\t\t\tfir::Value* val = 0;\n\n\t\t\tfir::Type* type = 0;\n\t\t\tsize_t dataSize = 0;\n\t\t\tunion {\n\t\t\t\tvoid* ptr;\n\t\t\t\tuint8_t data[32];\n\t\t\t};\n\n\t\t\t// kinda a dirty hack, we need to know whether or not to write-back the global after the interpreter\n\t\t\t// is done, cases where we modify stuff during compile-time execution. of course, the real value could\n\t\t\t// be *derived* from a global, eg. a GEP on a struct, or something. so, we persistently tag it.\n\t\t\tfir::GlobalValue* globalValTracker = 0;\n\t\t};\n\n\t\tstruct Instruction\n\t\t{\n\t\t\tsize_t opcode;\n\t\t\tfir::Value* result = 0;\n\t\t\tstd::vector<fir::Value*> args;\n\t\t};\n\n\t\tstruct Block\n\t\t{\n\t\t\tfir::IRBlock* blk = 0;\n\t\t\tstd::vector<interp::Instruction> instructions;\n\t\t};\n\n\t\tstruct Function\n\t\t{\n\t\t\tfir::Function* func = 0;\n\t\t\tbool isExternal = false;\n\n\t\t\tstd::string extFuncName;\n\t\t\tinterp::Block* entryBlock = 0;\n\t\t\tstd::vector<interp::Block> blocks;\n\t\t};\n\n\t\tstruct InterpState\n\t\t{\n\t\t\tInterpState(fir::Module* mod);\n\t\t\t~InterpState();\n\n\t\t\tvoid initialise(bool runGlobalInit);\n\t\t\tvoid finalise();\n\n\t\t\tinterp::Function& compileFunction(fir::Function* fn);\n\t\t\tinterp::Value runFunction(const interp::Function& fn, const std::vector<interp::Value>& args);\n\n\t\t\tinterp::Value makeValue(fir::Value* ty);\n\n\t\t\tfir::ConstantValue* unwrapInterpValueIntoConstant(const interp::Value& val);\n\n\t\t\tstruct Frame\n\t\t\t{\n\t\t\t\tsize_t currentInstrIndex = 0;\n\t\t\t\tconst interp::Block* currentBlock = 0;\n\t\t\t\tconst interp::Block* previousBlock = 0;\n\t\t\t\tconst interp::Function* currentFunction = 0;\n\n\t\t\t\tstd::vector<void*> stackAllocs;\n\n\t\t\t\tfir::Value* callResultOutput = 0;\n\n\t\t\t\tstd::unordered_map<fir::Value*, interp::Value> values;\n\t\t\t};\n\n\t\t\t// this is the executing state.\n\t\t\tstd::vector<Frame> stackFrames;\n\n\t\t\tstd::unordered_map<fir::Value*, std::pair<interp::Value, bool>> globals;\n\t\t\tstd::vector<void*> globalAllocs;\n\n\t\t\tstd::vector<char*> strings;\n\n\t\t\t// map from the id to the real function.\n\t\t\t// we don't want 'inheritance' here\n\t\t\tstd::unordered_map<fir::Value*, interp::Function> compiledFunctions;\n\n\t\t\tfir::Module* module = 0;\n\t\t};\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/ir/irbuilder.h",
    "content": "// irbuilder.h\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#include <stdint.h>\n#include <stddef.h>\n#include <limits.h>\n\n#include \"block.h\"\n#include \"value.h\"\n#include \"module.h\"\n#include \"function.h\"\n#include \"constant.h\"\n\nnamespace fir\n{\n\tstruct IRBuilder\n\t{\n\t\tIRBuilder(Module* mod);\n\n\t\tValue* Negate(Value* a, const std::string& vname = \"\");\n\t\tValue* Add(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* Subtract(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* Multiply(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* Divide(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* Modulo(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* ICmpEQ(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* ICmpNEQ(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* ICmpGT(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* ICmpLT(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* ICmpGEQ(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* ICmpLEQ(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* FCmpEQ_ORD(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* FCmpEQ_UNORD(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* FCmpNEQ_ORD(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* FCmpNEQ_UNORD(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* FCmpGT_ORD(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* FCmpGT_UNORD(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* FCmpLT_ORD(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* FCmpLT_UNORD(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* FCmpGEQ_ORD(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* FCmpGEQ_UNORD(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* FCmpLEQ_ORD(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* FCmpLEQ_UNORD(Value* a, Value* b, const std::string& vname = \"\");\n\n\t\tValue* ICmpMulti(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* FCmpMulti(Value* a, Value* b, const std::string& vname = \"\");\n\n\t\tValue* BitwiseXOR(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* BitwiseLogicalSHR(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* BitwiseArithmeticSHR(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* BitwiseSHL(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* BitwiseAND(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* BitwiseOR(Value* a, Value* b, const std::string& vname = \"\");\n\t\tValue* BitwiseNOT(Value* a, const std::string& vname = \"\");\n\n\t\tValue* Bitcast(Value* v, Type* targetType, const std::string& vname = \"\");\n\t\tValue* IntSizeCast(Value* v, Type* targetType, const std::string& vname = \"\");\n\t\tValue* FloatToIntCast(Value* v, Type* targetType, const std::string& vname = \"\");\n\t\tValue* IntToFloatCast(Value* v, Type* targetType, const std::string& vname = \"\");\n\t\tValue* PointerTypeCast(Value* v, Type* targetType, const std::string& vname = \"\");\n\t\tValue* PointerToIntCast(Value* v, Type* targetType, const std::string& vname = \"\");\n\t\tValue* IntToPointerCast(Value* v, Type* targetType, const std::string& vname = \"\");\n\t\tValue* IntSignednessCast(Value* v, Type* targetType, const std::string& vname = \"\");\n\n\t\tValue* AppropriateCast(Value* v, Type* targetType, const std::string& vname = \"\");\n\n\t\tValue* IntTruncate(Value* v, Type* targetType, const std::string& vname = \"\");\n\t\tValue* IntZeroExt(Value* v, Type* targetType, const std::string& vname = \"\");\n\n\t\tValue* FTruncate(Value* v, Type* targetType, const std::string& vname = \"\");\n\t\tValue* FExtend(Value* v, Type* targetType, const std::string& vname = \"\");\n\n\t\tValue* Call(Function* fn, const std::string& vname = \"\");\n\t\tValue* Call(Function* fn, Value* p1, const std::string& vname = \"\");\n\t\tValue* Call(Function* fn, Value* p1, Value* p2, const std::string& vname = \"\");\n\t\tValue* Call(Function* fn, Value* p1, Value* p2, Value* p3, const std::string& vname = \"\");\n\t\tValue* Call(Function* fn, Value* p1, Value* p2, Value* p3, Value* p4, const std::string& vname = \"\");\n\n\t\tValue* Call(Function* fn, const std::vector<Value*>& args, const std::string& vname = \"\");\n\t\tValue* Call(Function* fn, const std::initializer_list<Value*>& args, const std::string& vname = \"\");\n\n\t\tValue* CallToFunctionPointer(Value* fn, FunctionType* ft, const std::vector<Value*>& args, const std::string& vname = \"\");\n\n\t\tValue* CallVirtualMethod(ClassType* cls, FunctionType* ft, size_t index, const std::vector<Value*>& args, const std::string& vname = \"\");\n\n\t\tValue* Return(Value* v);\n\t\tValue* ReturnVoid();\n\n\t\tValue* LogicalNot(Value* v, const std::string& vname = \"\");\n\n\t\tPHINode* CreatePHINode(Type* type, const std::string& vname = \"\");\n\t\tValue* StackAlloc(Type* type, const std::string& vname = \"\");\n\t\tValue* ImmutStackAlloc(Type* type, Value* initialValue, const std::string& vname = \"\");\n\n\t\t// given an l or cl value of raw_union type, return an l or cl value of the correct type of the field\n\t\tValue* GetRawUnionField(Value* lval, const std::string& field, const std::string& vname = \"\");\n\n\t\t// same as the above, but give it a type instead -- this is hacky cos it's not checked.\n\t\t// the backend will just do some pointer magic regardless, so it doesn't really matter.\n\t\tValue* GetRawUnionFieldByType(Value* lval, Type* type, const std::string& vname = \"\");\n\n\t\t// equivalent to GEP(ptr*, 0, memberIndex)\n\t\tValue* GetStructMember(Value* ptr, const std::string& memberName);\n\t\tValue* StructGEP(Value* structPtr, size_t memberIndex, const std::string& vname = \"\");\n\n\t\t// equivalent to GEP(ptr*, index)\n\t\tValue* GetPointer(Value* ptr, Value* ptrIndex, const std::string& vname = \"\");\n\n\t\t// equivalent to GEP(ptr*, ptrIndex, elmIndex)\n\t\tValue* GEP2(Value* ptr, Value* ptrIndex, Value* elmIndex, const std::string& vname = \"\");\n\t\tValue* ConstGEP2(Value* ptr, size_t ptrIndex, size_t elmIndex, const std::string& vname = \"\");\n\n\t\tvoid SetVtable(Value* ptr, Value* table);\n\n\t\tvoid CondBranch(Value* condition, IRBlock* trueBlock, IRBlock* falseBlock);\n\t\tvoid UnCondBranch(IRBlock* target);\n\n\n\t\tValue* Sizeof(Type* t, const std::string& vname = \"\");\n\n\t\tValue* Select(Value* cond, Value* one, Value* two, const std::string& vname = \"\");\n\n\t\tValue* BinaryOp(const std::string& ao, Value* a, Value* b, const std::string& vname = \"\");\n\n\t\tValue* CreateValue(Type* t, const std::string& vname = \"\");\n\n\t\tValue* ExtractValue(Value* val, const std::vector<size_t>& inds, const std::string& vname = \"\");\n\t\tValue* ExtractValueByName(Value* val, const std::string& mem, const std::string& vname = \"\");\n\n\t\t[[nodiscard]] Value* InsertValueByName(Value* val, const std::string& mem, Value* elm, const std::string& vname = \"\");\n\t\t[[nodiscard]] Value* InsertValue(Value* val, const std::vector<size_t>& inds, Value* elm, const std::string& vname = \"\");\n\n\n\t\t//! ACHTUNG !\n\t\t//* 'generic' function that works for both strings and dynamic arrays,\n\t\t//* since they now function almost exactly the same.\n\t\t//? SAA -- String Array Analogue\n\t\tValue* GetSAAData(Value* str, const std::string& vname = \"\");\n\t\tValue* GetSAALength(Value* str, const std::string& vname = \"\");\n\t\tValue* GetSAACapacity(Value* str, const std::string& vname = \"\");\n\t\tValue* GetSAARefCount(Value* str, const std::string& vname = \"\");\n\t\tValue* GetSAARefCountPointer(Value* str, const std::string& vname = \"\");\n\n\t\t[[nodiscard]] Value* SetSAARefCountPointer(Value* str, Value* val, const std::string& vname = \"\");\n\t\t[[nodiscard]] Value* SetSAACapacity(Value* str, Value* val, const std::string& vname = \"\");\n\t\t[[nodiscard]] Value* SetSAALength(Value* str, Value* val, const std::string& vname = \"\");\n\t\t[[nodiscard]] Value* SetSAAData(Value* str, Value* val, const std::string& vname = \"\");\n\t\tvoid SetSAARefCount(Value* str, Value* val);\n\n\n\t\tValue* CreateSliceFromSAA(Value* str, bool mut, const std::string& vname = \"\");\n\n\n\n\n\t\tValue* GetArraySliceData(Value* arr, const std::string& vname = \"\");\n\t\tValue* GetArraySliceLength(Value* arr, const std::string& vname = \"\");\n\n\t\t[[nodiscard]] Value* SetArraySliceData(Value* arr, Value* val, const std::string& vname = \"\");\n\t\t[[nodiscard]] Value* SetArraySliceLength(Value* arr, Value* val, const std::string& vname = \"\");\n\n\n\t\tValue* GetAnyData(Value* any, const std::string& vname = \"\");\n\t\tValue* GetAnyTypeID(Value* any, const std::string& vname = \"\");\n\t\tValue* GetAnyRefCount(Value* str, const std::string& vname = \"\");\n\t\tValue* GetAnyRefCountPointer(Value* any, const std::string& vname = \"\");\n\n\t\tvoid SetAnyRefCount(Value* str, Value* val);\n\t\t[[nodiscard]] Value* SetAnyData(Value* any, Value* val, const std::string& vname = \"\");\n\t\t[[nodiscard]] Value* SetAnyTypeID(Value* any, Value* val, const std::string& vname = \"\");\n\t\t[[nodiscard]] Value* SetAnyRefCountPointer(Value* str, Value* val, const std::string& vname = \"\");\n\n\n\t\tValue* GetRangeLower(Value* range, const std::string& vname = \"\");\n\t\tValue* GetRangeUpper(Value* range, const std::string& vname = \"\");\n\t\tValue* GetRangeStep(Value* range, const std::string& vname = \"\");\n\n\t\t[[nodiscard]] Value* SetRangeLower(Value* range, Value* val, const std::string& vname = \"\");\n\t\t[[nodiscard]] Value* SetRangeUpper(Value* range, Value* val, const std::string& vname = \"\");\n\t\t[[nodiscard]] Value* SetRangeStep(Value* range, Value* step, const std::string& vname = \"\");\n\n\t\tValue* GetEnumCaseIndex(Value* ecs, const std::string& vname = \"\");\n\t\tValue* GetEnumCaseValue(Value* ecs, const std::string& vname = \"\");\n\n\t\t[[nodiscard]] Value* SetEnumCaseIndex(Value* ecs, Value* idx, const std::string& vname = \"\");\n\t\t[[nodiscard]] Value* SetEnumCaseValue(Value* ecs, Value* val, const std::string& vname = \"\");\n\n\n\n\t\t[[nodiscard]] Value* SetUnionVariantData(Value* unn, size_t id, Value* data, const std::string& vname = \"\");\n\t\t[[nodiscard]] Value* GetUnionVariantData(Value* unn, size_t id, const std::string& vname = \"\");\n\n\t\t[[nodiscard]] Value* GetUnionVariantID(Value* unn, const std::string& vname = \"\");\n\t\t[[nodiscard]] Value* SetUnionVariantID(Value* unn, size_t id, const std::string& vname = \"\");\n\n\n\n\t\t//* V2 api\n\n\t\tValue* ReadPtr(Value* ptr, const std::string& vname = \"\");\n\t\tvoid WritePtr(Value* v, Value* ptr);\n\n\t\tvoid Store(Value* val, Value* lval);\n\t\tValue* CreateLValue(Type* t, const std::string& vname = \"\");\n\n\t\tValue* Dereference(Value* val, const std::string& vname = \"\");\n\t\tValue* AddressOf(Value* lval, bool mut, const std::string& vname = \"\");\n\n\n\n\n\n\n\t\tvoid Unreachable();\n\n\n\t\tIRBlock* addNewBlockInFunction(const std::string& name, Function* func);\n\t\tIRBlock* addNewBlockAfter(const std::string& name, IRBlock* block);\n\n\n\t\tvoid setCurrentBlock(IRBlock* block);\n\t\tvoid restorePreviousBlock();\n\n\t\tFunction* getCurrentFunction();\n\t\tIRBlock* getCurrentBlock();\n\n\n\t\tprivate:\n\t\tValue* addInstruction(Instruction* instr, const std::string& vname);\n\n\t\tModule* module = 0;\n\t\tFunction* currentFunction = 0;\n\t\tIRBlock* currentBlock = 0;\n\t\tIRBlock* previousBlock = 0;\n\t};\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/ir/module.h",
    "content": "// module.h\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#include <stdint.h>\n#include <stddef.h>\n#include <limits.h>\n\n#include \"value.h\"\n#include \"function.h\"\n\n\nnamespace fir\n{\n\tstruct Module\n\t{\n\t\tfriend struct GlobalValue;\n\t\tfriend struct GlobalVariable;\n\n\t\tModule(const std::string& nm);\n\n\t\tGlobalVariable* createGlobalVariable(const Name& id, Type* type, ConstantValue* initVal, bool isImmut, LinkageType linkage);\n\t\tGlobalVariable* createGlobalVariable(const Name& id, Type* type, bool isImmut, LinkageType linkage);\n\t\tGlobalVariable* declareGlobalVariable(const Name& id, Type* type, bool isImmut);\n\t\tGlobalVariable* tryGetGlobalVariable(const Name& id);\n\t\tGlobalVariable* getGlobalVariable(const Name& id);\n\n\t\tGlobalVariable* getOrCreateVirtualTableForClass(ClassType* cls);\n\n\t\tGlobalVariable* createGlobalString(const std::string& str);\n\n\t\tstd::vector<GlobalVariable*> getGlobalVariables();\n\t\tstd::vector<Function*> getAllFunctions();\n\t\tstd::vector<Type*> getNamedTypes();\n\n\t\t// note: only looks at the name + scope, excludes the parameter list.\n\t\tstd::vector<Function*> getFunctionsWithName(const Name& id);\n\t\tFunction* getIntrinsicFunction(const std::string& id);\n\n\t\tType* getNamedType(const Name& name);\n\t\tvoid addNamedType(const Name& name, Type* type);\n\n\t\tvoid addFunction(Function* func);\n\t\tvoid removeFunction(Function* func);\n\n\t\tFunction* declareFunction(const Name& id, FunctionType* ftype);\n\t\tFunction* getFunction(const Name& id);\n\t\tFunction* getOrCreateFunction(const Name& id, FunctionType* ftype, LinkageType linkage);\n\n\t\tstd::string getModuleName();\n\t\tvoid setModuleName(const std::string& name);\n\n\t\tstd::string print();\n\n\t\tFunction* getEntryFunction();\n\t\tvoid setEntryFunction(Function* fn);\n\n\n\t\tvoid finaliseGlobalConstructors();\n\n\t\tconst util::hash_map<ClassType*, std::pair<std::vector<Function*>, GlobalVariable*>>& _getVtables() { return this->vtables; }\n\t\tconst util::hash_map<Name, Function*>& _getIntrinsicFunctions() { return this->intrinsicFunctions; }\n\t\tconst util::hash_map<std::string, GlobalVariable*>& _getGlobalStrings() { return this->globalStrings; }\n\t\tconst util::hash_map<Name, GlobalVariable*>& _getGlobals() { return this->globals; }\n\t\tconst util::hash_map<Name, Function*>& _getFunctions() { return this->functions; }\n\t\tconst util::hash_map<Name, Type*>& _getNamedTypes() { return this->namedTypes; }\n\n\n\t\tprivate:\n\t\tstd::string moduleName;\n\t\tutil::hash_map<ClassType*, std::pair<std::vector<Function*>, GlobalVariable*>> vtables;\n\t\tutil::hash_map<std::string, GlobalVariable*> globalStrings;\n\n\t\tutil::hash_map<Name, GlobalVariable*> globals;\n\t\tutil::hash_map<Name, Function*> functions;\n\t\tutil::hash_map<Name, Type*> namedTypes;\n\n\t\tutil::hash_map<Name, Function*> intrinsicFunctions;\n\n\t\tFunction* entryFunction = 0;\n\t};\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/ir/type.h",
    "content": "// type.h\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#include \"defs.h\"\n#include \"precompile.h\"\n\nnamespace fir\n{\n\tenum class NameKind\n\t{\n\t\tName,\n\t\tType,\n\t\tFunction\n\t};\n\n\tstruct Type;\n\n\tstruct Name\n\t{\n\t\tNameKind kind;\n\n\t\tstd::string name;\n\t\tstd::vector<std::string> scope;\n\t\tstd::vector<fir::Type*> params;\n\t\tfir::Type* retty;\n\n\t\tstd::string str() const;\n\t\tstd::string mangled() const;\n\t\tstd::string mangledWithoutScope() const;\n\n\t\tbool operator== (const Name& other) const;\n\t\tbool operator!= (const Name& other) const;\n\n\t\tstatic Name of(std::string name);\n\t\tstatic Name of(std::string name, std::vector<std::string> scope);\n\n\t\tstatic Name type(std::string name);\n\t\tstatic Name type(std::string name, std::vector<std::string> scope);\n\n\t\tstatic Name function(std::string name, std::vector<fir::Type*> params, fir::Type* retty);\n\t\tstatic Name function(std::string name, std::vector<std::string> scope, std::vector<fir::Type*> params, fir::Type* retty);\n\n\t\tstatic Name obfuscate(const std::string& name, NameKind kind = NameKind::Name);\n\t\tstatic Name obfuscate(const std::string& name, size_t id, NameKind kind = NameKind::Name);\n\t\tstatic Name obfuscate(const std::string& name, const std::string& extra, NameKind kind = NameKind::Name);\n\n\tprivate:\n\t\tName(NameKind kind, std::string name, std::vector<std::string> scope, std::vector<fir::Type*> params, fir::Type* retty)\n\t\t\t: kind(kind), name(std::move(name)), scope(std::move(scope)), params(std::move(params)), retty(retty) { }\n\t};\n\n\tstd::string obfuscateName(const std::string& name);\n\tstd::string obfuscateName(const std::string& name, size_t id);\n\tstd::string obfuscateName(const std::string& name, const std::string& extra);\n}\n\ntemplate <>\nstruct zpr::print_formatter<fir::Name>\n{\n\tstd::string print(const fir::Name& x, const format_args& args);\n};\n\nnamespace std\n{\n\ttemplate<>\n\tstruct hash<fir::Name>\n\t{\n\t\tstd::size_t operator()(const fir::Name& k) const\n\t\t{\n\t\t\tusing std::size_t;\n\t\t\tusing std::hash;\n\t\t\tusing std::string;\n\n\t\t\t// Compute individual hash values for first,\n\t\t\t// second and third and combine them using XOR\n\t\t\t// and bit shifting:\n\n\t\t\t// return ((hash<string>()(k.name) ^ (hash<std::vector<std::string>>()(k.scope) << 1)) >> 1) ^ (hash<int>()(k.third) << 1);\n\t\t\treturn hash<string>()(k.str());\n\t\t}\n\t};\n}\n\n\nnamespace fir\n{\n\t// NOTE: i don't really want to deal with inheritance stuff right now,\n\t// so Type will encapsulate everything.\n\t// we shouldn't be making any copies anyway, so space/performance is a negligible concern\n\n\tstruct Type;\n\tstruct Module;\n\tstruct AnyType;\n\tstruct BoolType;\n\tstruct EnumType;\n\tstruct NullType;\n\tstruct VoidType;\n\tstruct ArrayType;\n\tstruct ClassType;\n\tstruct RangeType;\n\tstruct TraitType;\n\tstruct TupleType;\n\tstruct UnionType;\n\tstruct StringType;\n\tstruct StructType;\n\tstruct OpaqueType;\n\tstruct PointerType;\n\tstruct FunctionType;\n\tstruct RawUnionType;\n\tstruct PrimitiveType;\n\tstruct ArraySliceType;\n\tstruct DynamicArrayType;\n\tstruct UnionVariantType;\n\tstruct ConstantNumberType;\n\tstruct PolyPlaceholderType;\n\n\tstruct ConstantValue;\n\tstruct ConstantArray;\n\tstruct Function;\n\n\tConstantNumberType* unifyConstantTypes(ConstantNumberType* a, ConstantNumberType* b);\n\tType* getBestFitTypeForConstant(ConstantNumberType* cnt);\n\n\tint getCastDistance(Type* from, Type* to);\n\tbool isRefCountedType(Type* ty);\n\n\tvoid setNativeWordSizeInBits(size_t sz);\n\tsize_t getNativeWordSizeInBits();\n\n\t// in theory.\n\tsize_t getSizeOfType(Type* type);\n\tsize_t getAlignmentOfType(Type* type);\n\n\tbool areTypesCovariant(Type* base, Type* derv);\n\tbool areTypesContravariant(Type* base, Type* derv, bool traitChecking);\n\tbool areMethodsVirtuallyCompatible(FunctionType* base, FunctionType* fn, bool traitChecking);\n\tbool areTypeListsContravariant(const std::vector<Type*>& base, const std::vector<Type*>& derv, bool traitChecking);\n\n\n\tenum class TypeKind\n\t{\n\t\tInvalid,\n\n\t\tAny,\n\t\tNull,\n\t\tVoid,\n\t\tEnum,\n\t\tBool,\n\t\tArray,\n\t\tTuple,\n\t\tClass,\n\t\tRange,\n\t\tUnion,\n\t\tTrait,\n\t\tStruct,\n\t\tString,\n\t\tOpaque,\n\t\tPointer,\n\t\tFunction,\n\t\tRawUnion,\n\t\tPrimitive,\n\t\tArraySlice,\n\t\tDynamicArray,\n\t\tUnionVariant,\n\t\tConstantNumber,\n\t\tPolyPlaceholder,\n\t};\n\n\tstruct Type\n\t{\n\t\t// stuff\n\t\tstatic Type* fromBuiltin(const std::string& builtin);\n\n\t\tstatic std::string typeListToString(const std::vector<Type*>& types, bool includeBraces = false);\n\t\tstatic std::string typeListToString(const std::initializer_list<Type*>& types, bool includeBraces = false);\n\n\t\tstatic bool areTypeListsEqual(const std::vector<Type*>& a, const std::vector<Type*>& b);\n\t\tstatic bool areTypeListsEqual(const std::initializer_list<Type*>& a, const std::initializer_list<Type*>& b);\n\n\t\t// various\n\t\tvirtual std::string str() = 0;\n\t\tvirtual std::string encodedStr() = 0;\n\t\tvirtual bool isTypeEqual(Type* other) = 0;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) = 0;\n\n\t\tType* getPointerTo();\n\t\tType* getMutablePointerTo();\n\t\tType* getPointerElementType();\n\n\t\tType* getMutablePointerVersion();\n\t\tType* getImmutablePointerVersion();\n\n\t\t// note: works for all array types, be it dynamic, fixed, or slices\n\t\tType* getArrayElementType();\n\n\t\tPolyPlaceholderType* toPolyPlaceholderType();\n\t\tConstantNumberType* toConstantNumberType();\n\t\tDynamicArrayType* toDynamicArrayType();\n\t\tUnionVariantType* toUnionVariantType();\n\t\tArraySliceType* toArraySliceType();\n\t\tPrimitiveType* toPrimitiveType();\n\t\tRawUnionType* toRawUnionType();\n\t\tFunctionType* toFunctionType();\n\t\tPointerType* toPointerType();\n\t\tOpaqueType* toOpaqueType();\n\t\tStructType* toStructType();\n\t\tStringType* toStringType();\n\t\tTraitType* toTraitType();\n\t\tRangeType* toRangeType();\n\t\tClassType* toClassType();\n\t\tUnionType* toUnionType();\n\t\tTupleType* toTupleType();\n\t\tArrayType* toArrayType();\n\t\tBoolType* toBoolType();\n\t\tEnumType* toEnumType();\n\t\tNullType* toNullType();\n\t\tAnyType* toAnyType();\n\n\t\tbool isPointerTo(Type* other);\n\t\tbool isPointerElementOf(Type* other);\n\n\t\tbool isTraitType();\n\t\tbool isUnionType();\n\t\tbool isTupleType();\n\t\tbool isClassType();\n\t\tbool isStructType();\n\t\tbool isPackedStruct();\n\t\tbool isRawUnionType();\n\t\tbool isUnionVariantType();\n\n\t\tbool isRangeType();\n\n\t\tbool isCharType();\n\t\tbool isStringType();\n\n\t\tbool isOpaqueType();\n\n\t\tbool isAnyType();\n\t\tbool isEnumType();\n\t\tbool isArrayType();\n\t\tbool isIntegerType();\n\t\tbool isFunctionType();\n\t\tbool isSignedIntType();\n\t\tbool isUnsignedIntType();\n\t\tbool isFloatingPointType();\n\n\t\tbool isArraySliceType();\n\t\tbool isDynamicArrayType();\n\t\tbool isVariadicArrayType();\n\n\t\tbool isCharSliceType();\n\n\t\tbool isPrimitiveType();\n\t\tbool isPointerType();\n\t\tbool isVoidType();\n\t\tbool isNullType();\n\t\tbool isBoolType();\n\n\t\tbool isMutablePointer();\n\t\tbool isImmutablePointer();\n\t\tbool isConstantNumberType();\n\t\tbool isPolyPlaceholderType();\n\n\t\tbool containsPlaceholders();\n\t\tstd::vector<PolyPlaceholderType*> getContainedPlaceholders();\n\n\t\tsize_t getBitWidth();\n\n\t\tType* getIndirectedType(int times);\n\n\t\tsize_t getID() { return this->id; }\n\n\n\t\t// convenience\n\t\tstatic VoidType* getVoid();\n\t\tstatic NullType* getNull();\n\n\t\tstatic Type* getVoidPtr();\n\n\t\tstatic BoolType* getBool();\n\n\t\tstatic PrimitiveType* getInt8();\n\t\tstatic PrimitiveType* getInt16();\n\t\tstatic PrimitiveType* getInt32();\n\t\tstatic PrimitiveType* getInt64();\n\t\tstatic PrimitiveType* getInt128();\n\n\t\tstatic PrimitiveType* getUint8();\n\t\tstatic PrimitiveType* getUint16();\n\t\tstatic PrimitiveType* getUint32();\n\t\tstatic PrimitiveType* getUint64();\n\t\tstatic PrimitiveType* getUint128();\n\n\t\tstatic PrimitiveType* getFloat32();\n\t\tstatic PrimitiveType* getFloat64();\n\t\tstatic PrimitiveType* getFloat128();\n\n\t\tstatic PointerType* getInt8Ptr();\n\t\tstatic PointerType* getInt16Ptr();\n\t\tstatic PointerType* getInt32Ptr();\n\t\tstatic PointerType* getInt64Ptr();\n\t\tstatic PointerType* getInt128Ptr();\n\n\t\tstatic PointerType* getUint8Ptr();\n\t\tstatic PointerType* getUint16Ptr();\n\t\tstatic PointerType* getUint32Ptr();\n\t\tstatic PointerType* getUint64Ptr();\n\t\tstatic PointerType* getUint128Ptr();\n\n\t\tstatic PointerType* getMutInt8Ptr();\n\t\tstatic PointerType* getMutInt16Ptr();\n\t\tstatic PointerType* getMutInt32Ptr();\n\t\tstatic PointerType* getMutInt64Ptr();\n\t\tstatic PointerType* getMutInt128Ptr();\n\n\t\tstatic PointerType* getMutUint8Ptr();\n\t\tstatic PointerType* getMutUint16Ptr();\n\t\tstatic PointerType* getMutUint32Ptr();\n\t\tstatic PointerType* getMutUint64Ptr();\n\t\tstatic PointerType* getMutUint128Ptr();\n\n\t\tstatic ArraySliceType* getCharSlice(bool mut);\n\t\tstatic StringType* getString();\n\t\tstatic RangeType* getRange();\n\n\t\tstatic AnyType* getAny();\n\n\t\tstatic PrimitiveType* getNativeWord();\n\t\tstatic PrimitiveType* getNativeUWord();\n\n\t\tstatic PointerType* getNativeWordPtr();\n\n\n\t\tvirtual ~Type() { }\n\t\tconst TypeKind kind;\n\n\t\tprotected:\n\t\tType(TypeKind k) : kind(k)\n\t\t{\n\t\t\tstatic size_t __id = 0;\n\t\t\tthis->id = __id++;\n\t\t}\n\n\n\t\t// base things\n\t\tsize_t id = 0;\n\n\t\tPointerType* pointerTo = 0;\n\t\tPointerType* mutablePointerTo = 0;\n\n\t\tstatic Type* getOrCreateFloatingTypeWithConstraints(size_t bits);\n\t\tstatic Type* getOrCreateIntegerTypeWithConstraints(bool issigned, size_t bits);\n\t\tstatic Type* getOrCreateArrayTypeWithConstraints(size_t arrsize, Type* elm);\n\t\tstatic Type* getOrCreateStructTypeWithConstraints(bool islit, std::string name,\n\t\t\tstd::vector<Type*> mems);\n\n\t\tstatic Type* getOrCreateFunctionTypeWithConstraints(bool isva, std::vector<Type*> args,\n\t\t\tType* ret);\n\t};\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tstruct BoolType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\t\t// protected constructor\n\t\tvirtual ~BoolType() override { }\n\n\t\tBoolType();\n\t\tprotected:\n\n\t\tpublic:\n\t\tstatic BoolType* get();\n\t};\n\n\tstruct VoidType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\t\t// protected constructor\n\t\tvirtual ~VoidType() override { }\n\t\tVoidType();\n\t\tprotected:\n\n\t\tpublic:\n\t\tstatic VoidType* get();\n\t};\n\n\n\tstruct NullType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\t\t// protected constructor\n\t\tvirtual ~NullType() override { }\n\t\tNullType();\n\t\tprotected:\n\n\t\tpublic:\n\t\tstatic NullType* get();\n\t};\n\n\n\t// special case -- the type also needs to store the number, to know things like\n\t// whether it's signed, negative, an integer, and other stuff.\n\tstruct ConstantNumberType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\tbool isSigned();\n\t\tbool isFloating();\n\t\tsize_t getMinBits();\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\t\tstatic ConstantNumberType* get(bool neg, bool flt, size_t bits);\n\n\t\tvirtual ~ConstantNumberType() override { }\n\n\n\t\tprotected:\n\t\tConstantNumberType(bool neg, bool floating, size_t bits);\n\n\t\tbool _floating = false;\n\t\tbool _signed = false;\n\t\tsize_t _bits = 0;\n\t};\n\n\n\tstruct PolyPlaceholderType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\t\tstd::string getName();\n\t\tint getGroup();\n\n\t\t// session allows placeholders to share a name while being unrelated.\n\t\tstatic PolyPlaceholderType* get(const std::string& name, int session);\n\t\tvirtual ~PolyPlaceholderType() override { }\n\n\t\tprotected:\n\t\tPolyPlaceholderType(const std::string& n, int ses);\n\n\t\tstd::string name;\n\t\tint group = 0;\n\t};\n\n\n\n\n\n\tstruct PrimitiveType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\t// methods\n\t\tbool isSigned();\n\t\tsize_t getIntegerBitWidth();\n\t\tsize_t getFloatingPointBitWidth();\n\t\tPrimitiveType* getOppositeSignedType();\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\n\t\tenum class Kind\n\t\t{\n\t\t\tInvalid,\n\n\t\t\tInteger,\n\t\t\tFloating,\n\t\t};\n\n\n\t\t// protected constructor\n\t\tvirtual ~PrimitiveType() override { }\n\n\t\tprotected:\n\t\tPrimitiveType(size_t bits, bool issigned, Kind _kind);\n\n\n\t\t// fields (protected)\n\t\tbool isTypeSigned = 0;\n\t\tsize_t bitWidth = 0;\n\n\t\tKind primKind = Kind::Invalid;\n\n\t\tstatic PrimitiveType* getIntWithBitWidthAndSignage(size_t bits, bool issigned);\n\t\tstatic PrimitiveType* getFloatWithBitWidth(size_t bits);\n\n\n\t\tpublic:\n\n\t\tstatic PrimitiveType* getIntN(size_t bits);\n\t\tstatic PrimitiveType* getUintN(size_t bits);\n\n\t\tstatic PrimitiveType* getInt8();\n\t\tstatic PrimitiveType* getInt16();\n\t\tstatic PrimitiveType* getInt32();\n\t\tstatic PrimitiveType* getInt64();\n\t\tstatic PrimitiveType* getInt128();\n\n\t\tstatic PrimitiveType* getUint8();\n\t\tstatic PrimitiveType* getUint16();\n\t\tstatic PrimitiveType* getUint32();\n\t\tstatic PrimitiveType* getUint64();\n\t\tstatic PrimitiveType* getUint128();\n\n\t\tstatic PrimitiveType* getFloat32();\n\t\tstatic PrimitiveType* getFloat64();\n\t\tstatic PrimitiveType* getFloat128();\n\t};\n\n\n\n\tstruct PointerType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\n\t\tPointerType* getMutable();\n\t\tPointerType* getImmutable();\n\n\t\tbool isMutable();\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\t\t// protected constructor\n\t\tvirtual ~PointerType() override { }\n\t\tprotected:\n\t\tPointerType(Type* base, bool mut);\n\n\t\tType* baseType = 0;\n\t\tbool isPtrMutable = false;\n\n\t\t// static funcs\n\t\tpublic:\n\n\t\tstatic PointerType* getInt8Ptr();\n\t\tstatic PointerType* getInt16Ptr();\n\t\tstatic PointerType* getInt32Ptr();\n\t\tstatic PointerType* getInt64Ptr();\n\t\tstatic PointerType* getInt128Ptr();\n\n\t\tstatic PointerType* getUint8Ptr();\n\t\tstatic PointerType* getUint16Ptr();\n\t\tstatic PointerType* getUint32Ptr();\n\t\tstatic PointerType* getUint64Ptr();\n\t\tstatic PointerType* getUint128Ptr();\n\t};\n\n\n\n\tstruct TupleType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\t// methods\n\t\tsize_t getElementCount();\n\t\tType* getElementN(size_t n);\n\t\tconst std::vector<Type*>& getElements();\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\t\t// protected constructor\n\t\tvirtual ~TupleType() override { }\n\t\tprotected:\n\t\tTupleType(const std::vector<Type*>& mems);\n\n\t\t// fields (protected)\n\t\tstd::vector<Type*> members;\n\n\t\tpublic:\n\t\tstatic TupleType* get(const std::initializer_list<Type*>& members);\n\t\tstatic TupleType* get(const std::vector<Type*>& members);\n\t};\n\n\tstruct UnionVariantType;\n\tstruct UnionType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\t\tName getTypeName();\n\n\t\tsize_t getVariantCount();\n\t\tsize_t getIdOfVariant(const std::string& name);\n\t\tconst util::hash_map<std::string, UnionVariantType*>& getVariants();\n\n\t\tbool hasVariant(const std::string& name);\n\t\tUnionVariantType* getVariant(const std::string& name);\n\t\tUnionVariantType* getVariant(size_t id);\n\t\tvoid setBody(const util::hash_map<std::string, std::pair<size_t, Type*>>& variants);\n\n\t\tvirtual ~UnionType() override { }\n\t\tprotected:\n\n\t\tUnionType(const Name& id, const util::hash_map<std::string, std::pair<size_t, Type*>>& variants);\n\n\t\tName unionName;\n\t\tutil::hash_map<size_t, UnionVariantType*> indexMap;\n\t\tutil::hash_map<std::string, UnionVariantType*> variants;\n\n\t\tpublic:\n\t\tstatic UnionType* create(const Name& id, const util::hash_map<std::string, std::pair<size_t, Type*>>& variants);\n\t\tstatic UnionType* createWithoutBody(const Name& id);\n\t};\n\n\n\tstruct UnionVariantType : Type\n\t{\n\t\tfriend struct Type;\n\t\tfriend struct UnionType;\n\n\t\t// methods\n\t\tstd::string getName() { return this->name; }\n\t\tsize_t getVariantId() { return this->variantId; }\n\t\tType* getInteriorType() { return this->interiorType; }\n\t\tUnionType* getParentUnion() { return this->parent; }\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\t\t// protected constructor\n\t\tvirtual ~UnionVariantType() override { }\n\n\t\tprotected:\n\t\tUnionVariantType(UnionType* parent, size_t id, const std::string& name, Type* actual);\n\n\t\t// fields (protected)\n\t\tUnionType* parent;\n\t\tType* interiorType;\n\t\tstd::string name;\n\t\tsize_t variantId;\n\t};\n\n\n\n\tstruct RawUnionType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\tName getTypeName();\n\t\tsize_t getVariantCount();\n\n\t\tbool hasVariant(const std::string& name);\n\t\tType* getVariant(const std::string& name);\n\t\tconst util::hash_map<std::string, Type*>& getVariants();\n\n\t\tvoid setBody(const util::hash_map<std::string, Type*>& variants);\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\n\t\tvirtual ~RawUnionType() override { }\n\t\tprotected:\n\n\t\tRawUnionType(const Name& id, const util::hash_map<std::string, Type*>& variants);\n\n\t\tName unionName;\n\t\tutil::hash_map<std::string, Type*> variants;\n\n\t\tpublic:\n\t\tstatic RawUnionType* create(const Name& id, const util::hash_map<std::string, Type*>& variants);\n\t\tstatic RawUnionType* createWithoutBody(const Name& id);\n\t};\n\n\n\n\tstruct TraitType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\t// methods\n\t\tName getTypeName();\n\t\tsize_t getMethodCount();\n\t\tconst std::vector<std::pair<std::string, FunctionType*>>& getMethods();\n\t\tvoid setMethods(const std::vector<std::pair<std::string, FunctionType*>>& m);\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\t\t// protected constructor\n\t\tvirtual ~TraitType() override { }\n\t\tprotected:\n\t\tTraitType(const Name& name, const std::vector<std::pair<std::string, FunctionType*>>& meths);\n\n\t\t// fields\n\t\tName traitName;\n\t\tstd::vector<std::pair<std::string, FunctionType*>> methods;\n\n\t\t// static funcs\n\t\tpublic:\n\t\tstatic TraitType* create(const Name& name);\n\t};\n\n\n\n\tstruct StructType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\t// methods\n\t\tName getTypeName();\n\t\tsize_t getElementCount();\n\t\tType* getElementN(size_t n);\n\t\tType* getElement(const std::string& name);\n\t\tbool hasElementWithName(const std::string& name);\n\t\tsize_t getElementIndex(const std::string& name);\n\t\tconst std::vector<Type*>& getElements();\n\n\t\tvoid setBody(const std::vector<std::pair<std::string, Type*>>& members);\n\n\t\tvoid addTraitImpl(TraitType* trt);\n\t\tbool implementsTrait(TraitType* trt);\n\t\tstd::vector<TraitType*> getImplementedTraits();\n\t\tconst util::hash_map<std::string, size_t>& getIndexMap();\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\t\t// protected constructor\n\t\tvirtual ~StructType() override { }\n\t\tprotected:\n\t\tStructType(const Name& name, const std::vector<std::pair<std::string, Type*>>& mems, bool ispacked);\n\n\t\t// fields (protected)\n\t\tbool isTypePacked;\n\t\tName structName;\n\t\tstd::vector<Type*> typeList;\n\t\tstd::vector<TraitType*> implTraits;\n\t\tutil::hash_map<std::string, size_t> indexMap;\n\t\tutil::hash_map<std::string, Type*> structMembers;\n\n\t\t// static funcs\n\t\tpublic:\n\t\tstatic StructType* createWithoutBody(const Name& name, bool isPacked = false);\n\t\tstatic StructType* create(const Name& name, const std::vector<std::pair<std::string, Type*>>& members,\n\t\t\tbool isPacked = false);\n\t};\n\n\n\n\n\n\tstruct ClassType : Type\n\t{\n\t\tfriend struct Type;\n\t\tfriend struct Module;\n\n\t\t// methods\n\t\tName getTypeName();\n\t\tsize_t getElementCount();\n\t\t// Type* getElementN(size_t n);\n\t\tType* getElement(const std::string& name);\n\t\tbool hasElementWithName(const std::string& name);\n\t\tsize_t getAbsoluteElementIndex(const std::string& name);\n\t\tconst std::vector<Type*>& getElements();\n\t\tstd::vector<Type*> getAllElementsIncludingBase();\n\t\tconst std::vector<std::string>& getNameList();\n\n\t\tconst util::hash_map<std::string, size_t>& getElementNameMap();\n\n\t\tconst std::vector<Function*>& getMethods();\n\t\tstd::vector<Function*> getMethodsWithName(const std::string& id);\n\t\tFunction* getMethodWithType(FunctionType* ftype);\n\n\t\tconst std::vector<Function*>& getInitialiserFunctions();\n\t\tvoid setInitialiserFunctions(const std::vector<Function*>& list);\n\n\t\tFunction* getInlineInitialiser();\n\t\tvoid setInlineInitialiser(Function* fn);\n\n\t\tFunction* getInlineDestructor();\n\t\tvoid setInlineDestructor(Function* fn);\n\n\t\tvoid setMembers(const std::vector<std::pair<std::string, Type*>>& members);\n\t\tvoid setMethods(const std::vector<Function*>& methods);\n\n\t\tClassType* getBaseClass();\n\t\tvoid setBaseClass(ClassType* ty);\n\n\t\tvoid setDestructor(Function* f);\n\t\tvoid setCopyConstructor(Function* f);\n\t\tvoid setMoveConstructor(Function* f);\n\n\t\tFunction* getDestructor();\n\t\tFunction* getCopyConstructor();\n\t\tFunction* getMoveConstructor();\n\n\t\tvoid addTraitImpl(TraitType* trt);\n\t\tbool implementsTrait(TraitType* trt);\n\t\tstd::vector<TraitType*> getImplementedTraits();\n\n\t\tbool hasParent(Type* base);\n\n\t\tvoid addVirtualMethod(Function* method);\n\t\tsize_t getVirtualMethodIndex(const std::string& name, FunctionType* ft);\n\n\t\tsize_t getVirtualMethodCount();\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\t\t// protected constructor\n\t\tvirtual ~ClassType() override { }\n\t\tprotected:\n\t\tClassType(const Name& name, const std::vector<std::pair<std::string, Type*>>& mems, const std::vector<Function*>& methods,\n\t\t\tconst std::vector<Function*>& inits);\n\n\n\t\t// fields (protected)\n\t\tName className;\n\t\tstd::vector<Type*> typeList;\n\t\tstd::vector<std::string> nameList;\n\t\tstd::vector<Function*> methodList;\n\t\tstd::vector<Function*> initialiserList;\n\n\t\tstd::vector<TraitType*> implTraits;\n\n\t\tutil::hash_map<std::string, size_t> indexMap;\n\t\tutil::hash_map<std::string, Type*> classMembers;\n\t\tutil::hash_map<std::string, std::vector<Function*>> classMethodMap;\n\n\t\t//* how it works is that we will add in the mappings from the base class,\n\t\t//* and for our own matching virtual methods, we'll map to the same index.\n\n\n\t\tsize_t virtualMethodCount = 0;\n\t\t// util::hash_map<Function*, size_t> virtualMethodMap;\n\t\tutil::hash_map<size_t, Function*> reverseVirtualMethodMap;\n\n\t\t//* note: we do it this way (where we *EXCLUDE THE SELF POINTER*), because it's just easier -- to compare, and everything.\n\t\t//* we really don't have a use for mapping a Function to an index, only the other way.\n\t\tstd::map<std::pair<std::string, std::vector<Type*>>, size_t> virtualMethodMap;\n\n\t\tClassType* baseClass = 0;\n\n\t\tFunction* inlineInitialiser = 0;\n\t\tFunction* inlineDestructor = 0;\n\n\t\tFunction* destructor = 0;\n\t\tFunction* copyConstructor = 0;\n\t\tFunction* moveConstructor = 0;\n\n\t\t// static funcs\n\t\tpublic:\n\t\tstatic ClassType* createWithoutBody(const Name& name);\n\t\tstatic ClassType* create(const Name& name, const std::vector<std::pair<std::string, Type*>>& members,\n\t\t\tconst std::vector<Function*>& methods, const std::vector<Function*>& inits);\n\t};\n\n\n\tstruct EnumType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\tType* getCaseType();\n\t\tName getTypeName();\n\n\t\tConstantValue* getNameArray();\n\t\tConstantValue* getCaseArray();\n\n\t\tvoid setCaseType(Type* t);\n\t\tvoid setNameArray(ConstantValue* arr);\n\t\tvoid setCaseArray(ConstantValue* arr);\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\t\t// protected constructor\n\t\tvirtual ~EnumType() override { }\n\t\tprotected:\n\t\tEnumType(const Name& name, Type* ty);\n\n\t\tType* caseType;\n\t\tName typeName;\n\n\t\tConstantValue* runtimeNameArray = 0;\n\t\tConstantValue* runtimeCasesArray = 0;\n\n\t\t// static funcs\n\t\tpublic:\n\t\tstatic EnumType* get(const Name& name, Type* caseType);\n\t};\n\n\n\n\n\n\n\tstruct ArrayType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\t// methods\n\t\tType* getElementType();\n\t\tsize_t getArraySize();\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\t\t// protected constructor\n\t\tvirtual ~ArrayType() override { }\n\t\tprotected:\n\t\tArrayType(Type* elmType, size_t sz);\n\n\t\t// fields (protected)\n\t\tsize_t arraySize;\n\t\tType* arrayElementType;\n\n\t\t// static funcs\n\t\tpublic:\n\t\tstatic ArrayType* get(Type* elementType, size_t num);\n\t};\n\n\n\tstruct DynamicArrayType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\t// methods\n\t\tType* getElementType();\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\t\t// protected constructor\n\t\tvirtual ~DynamicArrayType() override { }\n\t\tprotected:\n\t\tDynamicArrayType(Type* elmType);\n\n\t\t// fields\n\t\tType* arrayElementType;\n\n\t\t// static funcs\n\t\tpublic:\n\t\tstatic DynamicArrayType* get(Type* elementType);\n\t};\n\n\n\tstruct ArraySliceType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\t// methods\n\t\tType* getElementType();\n\n\t\tbool isMutable();\n\t\tbool isVariadicType();\n\n\t\t// simplifies the mutability checking and stuff.\n\t\tType* getDataPointerType();\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\t\t// protected constructor\n\t\tvirtual ~ArraySliceType() override { }\n\t\tprotected:\n\t\tArraySliceType(Type* elmType, bool mut);\n\n\t\t// fields\n\t\tbool isSliceMutable;\n\t\tType* arrayElementType;\n\n\t\tbool isVariadic = false;\n\n\t\t// static funcs\n\t\tpublic:\n\t\tstatic ArraySliceType* get(Type* elementType, bool mut);\n\t\tstatic ArraySliceType* getMutable(Type* elementType);\n\t\tstatic ArraySliceType* getImmutable(Type* elementType);\n\n\t\tstatic ArraySliceType* getVariadic(Type* elementType);\n\t};\n\n\n\n\n\tstruct FunctionType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\t// methods\n\t\tconst std::vector<Type*>& getArgumentTypes();\n\t\tsize_t getArgumentCount();\n\t\tType* getArgumentN(size_t n);\n\t\tType* getReturnType();\n\n\t\tbool isCStyleVarArg();\n\t\tbool isVariadicFunc();\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\t\t// protected constructor\n\t\tvirtual ~FunctionType() override { }\n\t\tprotected:\n\t\tFunctionType(const std::vector<Type*>& args, Type* ret, bool iscva);\n\n\t\t// fields (protected)\n\t\tbool isFnCStyleVarArg;\n\n\t\tstd::vector<Type*> functionParams;\n\t\tType* functionRetType;\n\n\t\t// static funcs\n\t\tpublic:\n\t\tstatic FunctionType* getCVariadicFunc(const std::vector<Type*>& args, Type* ret);\n\t\tstatic FunctionType* getCVariadicFunc(const std::initializer_list<Type*>& args, Type* ret);\n\n\t\tstatic FunctionType* get(const std::vector<Type*>& args, Type* ret);\n\t\tstatic FunctionType* get(const std::initializer_list<Type*>& args, Type* ret);\n\t};\n\n\n\tstruct RangeType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\n\t\t// protected constructor\n\t\tvirtual ~RangeType() override { }\n\t\tprotected:\n\t\tRangeType();\n\n\t\tpublic:\n\t\tstatic RangeType* get();\n\t};\n\n\n\tstruct StringType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\n\t\t// protected constructor\n\t\tvirtual ~StringType() override { }\n\t\tprotected:\n\t\tStringType();\n\n\t\tpublic:\n\t\tstatic StringType* get();\n\t};\n\n\n\n\tstruct AnyType : Type\n\t{\n\t\tfriend struct Type;\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\n\t\t// protected constructor\n\t\tvirtual ~AnyType() override { }\n\t\tprotected:\n\t\tAnyType();\n\n\t\tpublic:\n\t\tstatic AnyType* get();\n\t};\n\n\n\tstruct OpaqueType : Type\n\t{\n\t\tfriend struct Type;\n\n\n\t\tvirtual std::string str() override;\n\t\tvirtual std::string encodedStr() override;\n\t\tvirtual bool isTypeEqual(Type* other) override;\n\t\tvirtual Type* substitutePlaceholders(const util::hash_map<Type*, Type*>& subst) override;\n\n\t\tsize_t getTypeSizeInBits() { return this->typeSizeInBits; }\n\n\t\t// protected constructor\n\t\tvirtual ~OpaqueType() override { }\n\t\tprotected:\n\t\tOpaqueType(const std::string& name, size_t sizeInBits);\n\n\t\tstd::string typeName;\n\t\tsize_t typeSizeInBits;\n\n\t\tpublic:\n\t\tstatic OpaqueType* get(const std::string& name, size_t sizeInBits);\n\t};\n\n\n\n\n\n\n\tstruct LocatedType\n\t{\n\t\tLocatedType() { }\n\t\texplicit LocatedType(Type* t) : type(t) { }\n\t\tLocatedType(Type* t, const Location& l) : type(t), loc(l) { }\n\n\t\toperator Type* () const { return this->type; }\n\t\tType* operator -> () const { return this->type; }\n\n\t\tType* type = 0;\n\t\tLocation loc;\n\t};\n\n\n\n\n\n\n\n\n\tstruct HashTypeByStr\n\t{\n\t\tsize_t operator() (Type* t) const\n\t\t{\n\t\t\treturn std::hash<std::string>()(t->str());\n\t\t}\n\t};\n\n\tstruct TypesEqual\n\t{\n\t\tbool operator() (Type* a, Type* b) const\n\t\t{\n\t\t\treturn a->isTypeEqual(b);\n\t\t}\n\t};\n\n\tstruct TypeCache\n\t{\n\t\tstd::unordered_set<Type*, HashTypeByStr, TypesEqual> cache;\n\n\t\ttemplate <typename T>\n\t\tT* getOrAddCachedType(T* type)\n\t\t{\n\t\t\tif(auto it = cache.find(type); it != cache.end())\n\t\t\t{\n\t\t\t\tdelete type;\n\t\t\t\treturn dynamic_cast<T*>(*it);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcache.insert(type);\n\t\t\t\treturn type;\n\t\t\t}\n\t\t}\n\n\t\tstatic TypeCache& get();\n\t};\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/ir/value.h",
    "content": "// value.h\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#include <stdint.h>\n#include <stddef.h>\n#include <limits.h>\n\n#include \"type.h\"\n#include \"errors.h\"\n#include \"container.h\"\n\nnamespace fir\n{\n\tenum class LinkageType\n\t{\n\t\tInvalid,\n\n\t\tInternal,\n\t\tExternal,\n\t\tExternalWeak,\n\t};\n\n\tstruct ConstantValue;\n\tstruct GlobalValue;\n\tstruct Instruction;\n\tstruct IRBlock;\n\n\tstruct Value\n\t{\n\t\tfriend struct Module;\n\t\tfriend struct Argument;\n\t\tfriend struct IRBuilder;\n\t\tfriend struct Instruction;\n\t\tfriend struct ConstantValue;\n\n\t\ttemplate <typename, size_t> friend struct util::MemoryPool;\n\t\ttemplate <typename, size_t> friend struct util::FastInsertVector;\n\n\t\t// congratulations, i fucking played myself.\n\t\tenum class Kind\n\t\t{\n\t\t\tlvalue,     // has identity, cannot be moved from\n\t\t\txvalue,     // has identity, can be moved from\n\t\t\tprvalue,    // no identity, can be moved from\n\t\t};\n\n\t\t// virtual funcs\n\t\tvirtual Type* getType();\n\t\tvoid setType(Type* t)   { this->valueType = t; }\n\t\tvoid setKind(Kind k)    { this->kind = k; }\n\n\t\tbool islvalue()     { return this->kind == Kind::lvalue; }\n\t\tbool canmove()      { return this->kind == Kind::xvalue || this->kind == Kind::prvalue; }\n\n\t\tbool isConst()      { return this->isconst; }\n\t\tvoid makeConst()    { this->isconst = true; }\n\n\t\t// methods\n\t\tvoid setName(const Name& idt);\n\t\tvoid setName(const std::string& s);\n\t\tconst Name& getName();\n\t\tbool hasName();\n\n\t\tstatic size_t getCurrentValueId();\n\n\t\t// protected shit\n\t\tsize_t id;\n\t\tprotected:\n\n\t\tvirtual ~Value() { }\n\t\tValue(Type* type, Kind k = Kind::prvalue);\n\n\n\t\t// fields\n\t\tName ident;\n\t\tType* valueType;\n\t\tKind kind;\n\t\tbool isconst = false;\n\t};\n\n\tstruct PHINode : Value\n\t{\n\t\tfriend struct IRBuilder;\n\t\tvoid addIncoming(Value* v, IRBlock* block);\n\n\t\tstd::map<IRBlock*, Value*> getValues();\n\n\t\tprotected:\n\t\tPHINode(Type* type);\n\n\t\tstd::map<IRBlock*, Value*> incoming;\n\t};\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/lexer.h",
    "content": "// lexer.h\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n#include \"defs.h\"\n#include \"container.h\"\n\nnamespace lexer\n{\n\tenum class TokenType\n\t{\n\t\tInvalid,\n\t\tFunc,\n\t\tClass,\n\t\tImport,\n\t\tVar,\n\t\tVal,\n\t\tIf,\n\t\tElse,\n\t\tReturn,\n\t\tAs,\n\t\tAsExclamation,\n\t\tIs,\n\t\tSwitch,\n\t\tCase,\n\t\tMatch,\n\t\tEnum,\n\t\tForeignFunc,\n\t\tStruct,\n\t\tUnion,\n\t\tStatic,\n\t\tTrue,\n\t\tFalse,\n\t\tFor,\n\t\tWhile,\n\t\tDo,\n\t\tDefer,\n\t\tBreak,\n\t\tContinue,\n\t\tNull,\n\t\tPrivate,\n\t\tPublic,\n\t\tInternal,\n\t\tExtension,\n\t\tTypeAlias,\n\t\tTypeof,\n\t\tTypeid,\n\t\tSizeof,\n\t\tAlloc,\n\t\tDealloc,\n\t\tExport,\n\t\tNamespace,\n\t\tOverride,\n\t\tTrait,\n\t\tVirtual,\n\t\tUsing,\n\t\tMutable,\n\t\tOperator,\n\t\tLBrace,\n\t\tRBrace,\n\t\tLParen,\n\t\tRParen,\n\t\tLSquare,\n\t\tRSquare,\n\t\tLAngle,\n\t\tRAngle,\n\t\tPlus,\n\t\tMinus,\n\t\tAsterisk,\n\t\tDivide,\n\t\tSQuote,\n\t\tDQuote,\n\t\tPeriod,\n\t\tComma,\n\t\tColon,\n\t\tEqual,\n\t\tQuestion,\n\t\tExclamation,\n\t\tSemicolon,\n\t\tAmpersand,\n\t\tPercent,\n\t\tPipe,\n\t\tDollar,\n\t\tLogicalOr,\n\t\tLogicalAnd,\n\t\tAt,\n\t\tPound,\n\t\tTilde,\n\t\tCaret,\n\t\tLeftArrow,\n\t\tRightArrow,\n\t\tFatLeftArrow,\n\t\tFatRightArrow,\n\t\tEqualsTo,\n\t\tNotEquals,\n\t\tGreaterEquals,\n\t\tLessThanEquals,\n\t\tDoublePlus,\n\t\tDoubleMinus,\n\t\tPlusEq,\n\t\tMinusEq,\n\t\tMultiplyEq,\n\t\tDivideEq,\n\t\tModEq,\n\t\tAmpersandEq,\n\t\tPipeEq,\n\t\tCaretEq,\n\t\tEllipsis,\n\t\tHalfOpenEllipsis,\n\t\tDoubleColon,\n\t\tIdentifier,\n\t\tUnicodeSymbol,\n\t\tNumber,\n\t\tStringLiteral,\n\t\tCharacterLiteral,\n\t\tNewLine,\n\t\tComment,\n\t\tEndOfFile,\n\n\t\tAttr_ATTRS_BEGIN,\n\n\t\tAttr_Raw,\n\t\tAttr_Packed,\n\t\tAttr_EntryFn,\n\t\tAttr_NoMangle,\n\t\tAttr_Operator,\n\t\tAttr_Platform,\n\n\t\tAttr_ATTRS_END,\n\n\t\tDirective_Run,\n\t\tDirective_If,\n\t};\n\n\tstruct Token\n\t{\n\t\tLocation loc;\n\t\tTokenType type = TokenType::Invalid;\n\t\tstd::string_view text;\n\n\t\toperator TokenType() const { return this->type; }\n\t\tbool operator == (const std::string& s) { return this->str() == s; }\n\t\tstd::string str() const { return std::string(this->text); }\n\t};\n\n\tusing TokenList = util::FastInsertVector<Token>;\n\n\tlexer::TokenType getNextToken(const util::FastInsertVector<std::string_view>& lines, size_t* line, size_t* offset,\n\t\tconst std::string_view& whole, Location& pos, Token* out, bool crlf);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/memorypool.h",
    "content": "// memorypool.h\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#include \"container.h\"\n\nnamespace util\n{\n\tvoid addPool(MemoryPool_base* pool);\n\tvoid clearAllPools();\n\n\n\ttemplate <typename T, typename... Args>\n\tT* pool(Args&&... args)\n\t{\n\t\tstatic MemoryPool<T, 1 << 9> _pool;\n\t\taddPool(&_pool);\n\t\treturn _pool.construct(std::forward<Args>(args)...);\n\t}\n}\n"
  },
  {
    "path": "source/include/parser.h",
    "content": "// parser.h\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n#include \"defs.h\"\n#include \"lexer.h\"\n\nnamespace ast\n{\n\tstruct TopLevelBlock;\n}\n\nnamespace frontend\n{\n\tstruct ImportThing;\n\tstruct FileInnards;\n\tstruct CollectorState;\n}\n\nnamespace parser\n{\n\tstruct ParsedFile\n\t{\n\t\tstd::string name;\n\t\tstd::string moduleName;\n\t\tstd::vector<std::string> modulePath;\n\n\t\tast::TopLevelBlock* root = 0;\n\t};\n\n\n\tstruct CustomOperatorDecl\n\t{\n\t\tLocation loc;\n\t\tstd::string symbol;\n\t\tint precedence = 0;\n\n\t\tenum class Kind { Invalid, Infix, Prefix, Postfix };\n\t\tKind kind = Kind::Invalid;\n\t};\n\n\tstd::tuple<util::hash_map<std::string, parser::CustomOperatorDecl>,\tutil::hash_map<std::string, parser::CustomOperatorDecl>,\n\t\tutil::hash_map<std::string, parser::CustomOperatorDecl>> parseOperators(const lexer::TokenList& tokens);\n\n\t// strange api\n\tsize_t parseOperatorDecl(const lexer::TokenList& tokens, size_t i, int* kind, CustomOperatorDecl* out);\n\n\tstd::vector<frontend::ImportThing> parseImports(const std::string& filename, const lexer::TokenList& tokens);\n\tParsedFile parseFile(const std::string& filename, const frontend::FileInnards& file, frontend::CollectorState& cs);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/parser_internal.h",
    "content": "// parser_internal.h\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#include \"defs.h\"\n#include \"errors.h\"\n\n#include \"ast.h\"\n#include \"lexer.h\"\n#include \"parser.h\"\n\nnamespace pts\n{\n\tstruct Type;\n}\n\nnamespace parser\n{\n\tstruct State\n\t{\n\t\tState(const lexer::TokenList& tl) : tokens(tl) { }\n\n\t\tconst lexer::Token& lookahead(size_t num) const\n\t\t{\n\t\t\tif(this->index + num < this->tokens.size())\n\t\t\t\treturn this->tokens[this->index + num];\n\n\t\t\telse\n\t\t\t\terror(\"lookahead %d tokens > size %d\", num, this->tokens.size());\n\t\t}\n\n\t\tvoid skip(size_t num)\n\t\t{\n\t\t\tif(this->index + num < this->tokens.size())\n\t\t\t\tthis->index += num;\n\n\t\t\telse\n\t\t\t\terror(\"skip %d tokens > size %d\", num, this->tokens.size());\n\t\t}\n\n\t\tvoid rewind(size_t num)\n\t\t{\n\t\t\tif(this->index > num)\n\t\t\t\tthis->index -= num;\n\n\t\t\telse\n\t\t\t\terror(\"rewind %d tokens > index %d\", num, this->index);\n\t\t}\n\n\t\tvoid rewindTo(size_t ix)\n\t\t{\n\t\t\tif(ix >= this->tokens.size())\n\t\t\t\terror(\"ix %d > size %d\", ix, this->tokens.size());\n\n\t\t\tthis->index = ix;\n\t\t}\n\n\t\tconst lexer::Token& pop()\n\t\t{\n\t\t\tif(this->index + 1 < this->tokens.size())\n\t\t\t\treturn this->tokens[this->index++];\n\n\t\t\telse\n\t\t\t\terror(\"pop() on last token\");\n\t\t}\n\n\t\tconst lexer::Token& eat()\n\t\t{\n\t\t\tthis->skipWS();\n\t\t\tif(this->index + 1 < this->tokens.size())\n\t\t\t\treturn this->tokens[this->index++];\n\n\t\t\telse\n\t\t\t\terror(\"eat() on last token\");\n\t\t}\n\n\t\tvoid skipWS()\n\t\t{\n\t\t\twhile(this->index < this->tokens.size() && (this->tokens[this->index] == lexer::TokenType::NewLine\n\t\t\t\t|| this->tokens[this->index] == lexer::TokenType::Comment))\n\t\t\t{\n\t\t\t\tthis->index++;\n\t\t\t}\n\t\t}\n\n\t\tconst lexer::Token& front() const\n\t\t{\n\t\t\treturn this->tokens[this->index];\n\t\t}\n\n\n\t\tconst lexer::Token& frontAfterWS()\n\t\t{\n\t\t\tsize_t ofs = 0;\n\t\t\twhile(this->tokens[this->index + ofs] == lexer::TokenType::NewLine\n\t\t\t\t|| this->tokens[this->index + ofs] == lexer::TokenType::Comment)\n\t\t\t{\n\t\t\t\tofs++;\n\t\t\t}\n\t\t\treturn this->tokens[this->index + ofs];\n\t\t}\n\n\t\tconst lexer::Token& prev()\n\t\t{\n\t\t\treturn this->tokens[this->index - 1];\n\t\t}\n\n\t\tconst Location& loc() const\n\t\t{\n\t\t\treturn this->front().loc;\n\t\t}\n\n\t\tconst Location& ploc() const\n\t\t{\n\t\t\ticeAssert(this->index > 0);\n\t\t\treturn this->tokens[this->index - 1].loc;\n\t\t}\n\n\t\tsize_t remaining() const\n\t\t{\n\t\t\treturn this->tokens.size() - this->index - 1;\n\t\t}\n\n\t\tsize_t getIndex() const\n\t\t{\n\t\t\treturn this->index;\n\t\t}\n\n\t\tvoid setIndex(size_t i)\n\t\t{\n\t\t\ticeAssert(i < tokens.size());\n\t\t\tthis->index = i;\n\t\t}\n\n\t\tbool frontIsWS() const\n\t\t{\n\t\t\treturn this->front() == lexer::TokenType::Comment || this->front() == lexer::TokenType::NewLine;\n\t\t}\n\n\t\tbool hasTokens() const\n\t\t{\n\t\t\treturn this->index < this->tokens.size() && this->tokens[this->index] != lexer::TokenType::EndOfFile;\n\t\t}\n\n\t\tconst lexer::TokenList& getTokenList()\n\t\t{\n\t\t\treturn this->tokens;\n\t\t}\n\n\n\t\tvoid enterFunctionBody()\n\t\t{\n\t\t\tthis->bodyNesting.push_back(1);\n\t\t}\n\n\t\tvoid leaveFunctionBody()\n\t\t{\n\t\t\ticeAssert(this->bodyNesting.size() > 0 && this->bodyNesting.back() == 1);\n\t\t\tthis->bodyNesting.pop_back();\n\t\t}\n\n\t\tbool isInFunctionBody()\n\t\t{\n\t\t\treturn this->bodyNesting.size() > 0 && this->bodyNesting.back() == 1;\n\t\t}\n\n\n\n\t\tvoid enterStructBody()\n\t\t{\n\t\t\tthis->bodyNesting.push_back(2);\n\t\t}\n\n\t\tvoid leaveStructBody()\n\t\t{\n\t\t\ticeAssert(this->bodyNesting.size() > 0 && this->bodyNesting.back() == 2);\n\t\t\tthis->bodyNesting.pop_back();\n\t\t}\n\n\t\tbool isInStructBody()\n\t\t{\n\t\t\treturn this->bodyNesting.size() > 0 && this->bodyNesting.back() == 2;\n\t\t}\n\n\n\t\tvoid enterSubscript()\n\t\t{\n\t\t\tthis->bodyNesting.push_back(3);\n\t\t}\n\n\t\tvoid leaveSubscript()\n\t\t{\n\t\t\ticeAssert(this->bodyNesting.size() > 0 && this->bodyNesting.back() == 3);\n\t\t\tthis->bodyNesting.pop_back();\n\t\t}\n\n\t\tbool isInSubscript()\n\t\t{\n\t\t\treturn this->bodyNesting.size() > 0 && this->bodyNesting.back() == 3;\n\t\t}\n\n\n\t\tvoid enterUsingParse()\n\t\t{\n\t\t\tthis->bodyNesting.push_back(4);\n\t\t}\n\n\t\tvoid leaveUsingParse()\n\t\t{\n\t\t\ticeAssert(this->bodyNesting.size() > 0 && this->bodyNesting.back() == 4);\n\t\t\tthis->bodyNesting.pop_back();\n\t\t}\n\n\t\tbool isParsingUsing()\n\t\t{\n\t\t\treturn this->bodyNesting.size() > 0 && this->bodyNesting.back() == 4;\n\t\t}\n\n\n\n\t\t// implicitly coerce to location, so we can\n\t\t// error(st, ...)\n\t\toperator const Location&() const\n\t\t{\n\t\t\treturn this->loc();\n\t\t}\n\n\t\tstd::vector<ast::TypeDefn*> anonymousTypeDefns;\n\n\t\tstd::string currentFilePath;\n\n\t\tutil::hash_map<std::string, parser::CustomOperatorDecl> binaryOps;\n\t\tutil::hash_map<std::string, parser::CustomOperatorDecl> prefixOps;\n\t\tutil::hash_map<std::string, parser::CustomOperatorDecl> postfixOps;\n\n\t\t// flags that determine whether or not 'import' and '@operator' things can still be done.\n\t\tbool importsStillValid = true;\n\t\tbool operatorsStillValid = true;\n\t\tbool nativeWordSizeStillValid = true;\n\n\t\tfrontend::CollectorState* cState = 0;\n\n\t\tprivate:\n\t\t\t// 1 = inside function\n\t\t\t// 2 = inside struct\n\t\t\t// 3 = inside subscript\n\t\t\t// 4 = inside using (specifically, in `using X as Y`, we're parsing 'X')\n\t\t\tstd::vector<int> bodyNesting;\n\n\t\t\tsize_t index = 0;\n\t\t\tconst lexer::TokenList& tokens;\n\t};\n\n\n\t// like TCResult i guess.\n\ttemplate <typename T>\n\tstruct PResult\n\t{\n\t\tPResult(T* val)\n\t\t{\n\t\t\tthis->state = 0;\n\t\t\tthis->value = val;\n\t\t}\n\n\t\texplicit PResult(ErrorMsg* err, bool needsmore = false)\n\t\t{\n\t\t\tthis->error = err;\n\t\t\tthis->state = (needsmore ? 2 : 1);\n\t\t}\n\n\tprivate:\n\t\texplicit PResult(ErrorMsg* err, int stt)\n\t\t{\n\t\t\tthis->error = err;\n\t\t\tthis->state = stt;\n\t\t}\n\tpublic:\n\n\n\t\tPResult(const PResult& r)\n\t\t{\n\t\t\tthis->state = r.state;\n\t\t\tif(this->state == 0)    this->value = r.value;\n\t\t\telse                    this->error = r.error;\n\t\t}\n\n\t\tPResult(PResult&& r) noexcept\n\t\t{\n\t\t\tthis->state = r.state;\n\t\t\tr.state = -1;\n\n\t\t\tif(this->state == 0)    this->value = std::move(r.value);\n\t\t\telse                    this->error = std::move(r.error);\n\t\t}\n\n\t\tPResult& operator = (const PResult& r)\n\t\t{\n\t\t\tPResult tmp(r);\n\t\t\t*this = std::move(tmp);\n\t\t\treturn *this;\n\t\t}\n\n\t\tPResult& operator = (PResult&& r) noexcept\n\t\t{\n\t\t\tif(&r != this)\n\t\t\t{\n\t\t\t\tthis->state = r.state;\n\t\t\t\tr.state = -1;\n\n\t\t\t\tif(this->state == 0)    this->value = std::move(r.value);\n\t\t\t\telse                    this->error = std::move(r.error);\n\t\t\t}\n\n\t\t\treturn *this;\n\t\t}\n\n\t\t// implicit conversion operator.\n\t\ttemplate <typename A, typename X = std::enable_if_t<std::is_base_of_v<typename A::value_t, T>>>\n\t\toperator A() const\n\t\t{\n\t\t\tif(this->state == 0)    return PResult<typename A::value_t>(this->value);\n\t\t\telse                    return PResult<typename A::value_t>(this->error, this->state);\n\t\t}\n\n\n\n\n\t\ttemplate <typename F>\n\t\tPResult<T> mutate(const F& fn)\n\t\t{\n\t\t\tif(this->state == 0) fn(this->value);\n\t\t\treturn *this;\n\t\t}\n\n\t\ttemplate <typename F>\n\t\tauto map(const F& fn) const -> PResult<std::decay_t<decltype(*fn(std::declval<T*>()))>>\n\t\t{\n\t\t\tusing U = std::decay_t<decltype(*fn(std::declval<T*>()))>;\n\n\t\t\tif(this->state > 0) return PResult<U>(this->error, this->state);\n\t\t\telse                return PResult<U>(fn(this->value));\n\t\t}\n\n\t\tErrorMsg* err() const\n\t\t{\n\t\t\tif(this->state < 1) compiler_crash(\"not error\");\n\t\t\telse                return this->error;\n\t\t}\n\n\t\tT* val() const\n\t\t{\n\t\t\tif(this->state != 0)    this->error->postAndQuit();\n\t\t\telse                    return this->value;\n\t\t}\n\n\t\tbool isError() const\n\t\t{\n\t\t\treturn this->state > 0;\n\t\t}\n\n\t\tbool hasValue() const\n\t\t{\n\t\t\treturn this->state == 0;\n\t\t}\n\n\t\tbool needsMoreTokens() const\n\t\t{\n\t\t\treturn this->state == 2;\n\t\t}\n\n\t\tstatic PResult<T> insufficientTokensError()\n\t\t{\n\t\t\treturn PResult<T>(BareError::make(\"unexpected end of input\"), /* needmore: */ true);\n\t\t}\n\n\t\ttemplate <typename U>\n\t\tstatic PResult<T> copyError(const PResult<U>& other)\n\t\t{\n\t\t\t// only for error.\n\t\t\tif(other.state < 1)\n\t\t\t\tcompiler_crash(\"not error\");\n\n\t\t\treturn PResult<T>(other.err(), other.state);\n\t\t}\n\n\t\ttemplate <typename U>\n\t\tfriend struct PResult;\n\n\t\tusing value_t = T;\n\n\tprivate:\n\t\t// 0 = result, 1 = error, 2 = needsmoretokens\n\t\tint state;\n\n\t\tunion {\n\t\t\tT* value;\n\t\t\tErrorMsg* error;\n\t\t};\n\t};\n\n\t// Expected $, found '$' instead\n\t[[noreturn]] inline void expected(const Location& loc, std::string a, std::string b)\n\t{\n\t\terror(loc, \"expected %s, found '%s' instead\", a, b);\n\t}\n\n\t// Expected $ after $, found '$' instead\n\t[[noreturn]] inline void expectedAfter(const Location& loc, std::string a, std::string b, std::string c)\n\t{\n\t\terror(loc, \"expected %s after %s, found '%s' instead\", a, b, c);\n\t}\n\n\t// Unexpected $\n\t[[noreturn]] inline void unexpected(const Location& loc, std::string a)\n\t{\n\t\terror(loc, \"unexpected %s\", a);\n\t}\n\n\n\n\tstd::string parseStringEscapes(const Location& loc, const std::string& str);\n\n\tstd::string parseOperatorTokens(State& st);\n\n\tpts::Type* parseType(State& st);\n\tast::Expr* parseExpr(State& st);\n\tPResult<ast::Stmt> parseStmt(State& st, bool allowExprs = true);\n\n\n\tast::DeferredStmt* parseDefer(State& st);\n\n\tast::Stmt* parseVariable(State& st);\n\tast::ReturnStmt* parseReturn(State& st);\n\tast::ImportStmt* parseImport(State& st);\n\tPResult<ast::FuncDefn> parseFunction(State& st);\n\tPResult<ast::Stmt> parseStmtWithAccessSpec(State& st);\n\tast::ForeignFuncDefn* parseForeignFunction(State& st);\n\tast::OperatorOverloadDefn* parseOperatorOverload(State& st);\n\n\tstd::vector<std::pair<std::string, ast::Expr*>> parseCallArgumentList(State& st);\n\n\tast::UsingStmt* parseUsingStmt(State& st);\n\n\tDecompMapping parseArrayDecomp(State& st);\n\tDecompMapping parseTupleDecomp(State& st);\n\n\tstd::tuple<ast::FuncDefn*, bool, Location> parseFunctionDecl(State& st);\n\tast::PlatformDefn* parsePlatformDefn(State& st);\n\n\tast::RunDirective* parseRunDirective(State& st);\n\n\tast::TraitDefn* parseTrait(State& st);\n\tast::EnumDefn* parseEnum(State& st);\n\tast::ClassDefn* parseClass(State& st);\n\tast::StaticDecl* parseStaticDecl(State& st);\n\n\tPResult<ast::StructDefn> parseStruct(State& st, bool nameless);\n\tast::UnionDefn* parseUnion(State& st, bool israw, bool nameless);\n\n\tast::Expr* parseDollarExpr(State& st);\n\n\tast::InitFunctionDefn* parseInitFunction(State& st);\n\tast::InitFunctionDefn* parseDeinitFunction(State& st);\n\tast::InitFunctionDefn* parseCopyOrMoveInitFunction(State& st, const std::string& name);\n\n\tast::DeallocOp* parseDealloc(State& st);\n\tast::SizeofOp* parseSizeof(State& st);\n\n\tPResult<ast::Block> parseBracedBlock(State& st);\n\n\tast::LitNumber* parseNumber(State& st);\n\tast::LitString* parseString(State& st, bool israw);\n\tast::LitArray* parseArray(State& st, bool israw);\n\n\tast::Stmt* parseForLoop(State& st);\n\tPResult<ast::Stmt> parseIfStmt(State& st);\n\tPResult<ast::WhileLoop> parseWhileLoop(State& st);\n\n\tast::TopLevelBlock* parseTopLevel(State& st, const std::string& name);\n\n\tast::Stmt* parseBreak(State& st);\n\tast::Stmt* parseContinue(State& st);\n\n\tast::Expr* parseCaretOrColonScopeExpr(State& st);\n\n\tstd::vector<std::pair<std::string, TypeConstraints_t>> parseGenericTypeList(State& st);\n\n\tPolyArgMapping_t parsePAMs(State& st, bool* failed);\n\tAttribSet parseAttributes(State& st);\n\n\tstd::tuple<std::vector<ast::FuncDefn::Param>, std::vector<std::pair<std::string, TypeConstraints_t>>,\n\t\tpts::Type*, bool, Location> parseFunctionLookingDecl(State& st);\n\n\tstd::pair<Location, std::vector<std::string>> parseIdentPath(const lexer::TokenList& tokens, size_t* idx);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/platform.h",
    "content": "// platform.h\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n// platform-specific things\n\n#pragma once\n\n#include \"defs.h\"\n\n\t#define ALLOCATE_MEMORY_FUNC\t\t\t\t\t\t\"malloc\"\n\t#define REALLOCATE_MEMORY_FUNC\t\t\t\t\t\t\"realloc\"\n\t#define FREE_MEMORY_FUNC\t\t\t\t\t\t\t\"free\"\n\n\t#if defined(_WIN32)\n\t\t#define OS_WINDOWS  1\n\t\t#define OS_DARWIN   0\n\t\t#define OS_UNIX     0\n\t#elif __APPLE__\n\t\t#define OS_WINDOWS  0\n\t\t#define OS_DARWIN   1\n\t\t#define OS_UNIX     0\n\t#elif __unix__\n\t\t#define OS_WINDOWS  0\n\t\t#define OS_DARWIN   0\n\t\t#define OS_UNIX     1\n\t#else\n\t\t#error \"invalid host os!\"\n\t#endif\n\n\t#if defined(__x86_64__) || defined(__aarch64__) || defined(_M_X64)\n\t\t#define ARCH_64 1\n\t\t#define ARCH_32 0\n\t#else\n\t\t#define ARCH_32 1\n\t\t#define ARCH_64 0\n\t#endif\n\n\n\n\n\t#if OS_WINDOWS\n\t\tusing filehandle_t = void*;\n\n\t\t#define CRT_FDOPEN\t\t\t\"_fdopen\"\n\t\t#define PLATFORM_NEWLINE\t\"\\r\\n\"\n\n\t\t#define PLATFORM_EXPORT_FUNCTION    extern \"C\" __declspec(dllexport)\n\n\t\tnamespace platform\n\t\t{\n\t\t\tstd::wstring convertStringToWChar(const std::string& s);\n\t\t\tstd::string convertWCharToString(const std::wstring& s);\n\t\t}\n\t#else\n\t\t#include <unistd.h>\n\t\t#include <sys/stat.h>\n\n\t\tnamespace platform\n\t\t{\n\t\t\tusing filehandle_t = int;\n\t\t}\n\n\t\t#define CRT_FDOPEN\t\t\t\"fdopen\"\n\t\t#define PLATFORM_NEWLINE\t\"\\n\"\n\t\t#define PLATFORM_EXPORT_FUNCTION    extern \"C\" __attribute__((visibility(\"default\")))\n\t#endif\n\n\t#define REFCOUNT_SIZE\t\t8\n\nnamespace platform\n{\n\textern filehandle_t InvalidFileHandle;\n\n\tfilehandle_t openFile(const char* name, int mode, int flags);\n\tvoid closeFile(filehandle_t fd);\n\n\tsize_t readFile(filehandle_t fd, void* buf, size_t count);\n\tsize_t writeFile(filehandle_t fd, void* buf, size_t count);\n\n\tsize_t getFileSize(const std::string& path);\n\tbool checkFileExists(const std::string& path);\n\n\tstd::string_view readEntireFile(const std::string& path);\n\tvoid cachePreExistingFile(const std::string& path, const std::string& contents);\n\n\tstd::string getFullPath(const std::string& partial);\n\n\tsize_t getTerminalWidth();\n\tvoid setupTerminalIfNecessary();\n\n\tstd::string getEnvironmentVar(const std::string& name);\n\n\tvoid pushEnvironmentVar(const std::string& name, const std::string& value);\n\tvoid popEnvironmentVar(const std::string& name);\n\n\tvoid printStackTrace();\n\tvoid setupCrashHandlers();\n\n\tnamespace compiler\n\t{\n\t\tvoid performSelfDlOpen();\n\t\tvoid performSelfDlClose();\n\n\t\tvoid* getSymbol(const std::string& name);\n\n\t\t// call these as a pair\n\t\tvoid addLibrarySearchPaths();\n\t\tvoid restoreLibrarySearchPaths();\n\n\t\tstd::vector<std::string> getDefaultSharedLibraries();\n\n\t\tstd::string getExecutableName(const std::string& name);\n\t\tstd::string getObjectFileName(const std::string& name);\n\t\tstd::string getSharedLibraryName(const std::string& name);\n\n\t\tstd::string getCompilerCommandLine(const std::vector<std::string>& inputObjects, const std::string& outputFilename);\n\n\t\t#if OS_WINDOWS\n\t\t\tstd::string getWindowsSDKLocation();\n\t\t\tstd::string getVSToolchainLibLocation();\n\t\t\tstd::string getVSToolchainBinLocation();\n\t\t#endif\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/polymorph.h",
    "content": "// polymorph.h\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n#include \"defs.h\"\n\n#include \"ast.h\"\n#include \"stcommon.h\"\n\n#include \"ir/type.h\"\n\nnamespace pts\n{\n\tstruct Type;\n}\n\nnamespace ast\n{\n\tstruct FuncDefn;\n\tstruct Parameterisable;\n}\n\nnamespace fir\n{\n\tstruct LocatedType;\n}\n\nnamespace sst\n{\n\tstruct TypecheckState;\n\n\tnamespace poly\n\t{\n\t\tusing ProblemSpace_t = std::vector<std::pair<std::string, TypeConstraints_t>>;\n\n\t\tstruct ArgType\n\t\t{\n\t\t\tArgType() { }\n\t\t\texplicit ArgType(fir::Type* t) : type(t) { }\n\t\t\tArgType(const std::string& n, fir::Type* t, const Location& l) : name(n), type(t), loc(l) { }\n\t\t\tArgType(const std::string& n, fir::Type* t, const Location& l, bool opt) : name(n), type(t), loc(l), optional(opt) { }\n\t\t\tArgType(const std::string& n, fir::Type* t, const Location& l, bool opt, bool ignore) : name(n), type(t), loc(l), optional(opt),\n\t\t\t\tignoreName(ignore) { }\n\n\t\t\toperator fir::Type* () const { return this->type; }\n\t\t\tfir::Type* operator -> () const { return this->type; }\n\t\t\tfir::LocatedType toFLT() const { return fir::LocatedType(this->type, this->loc); }\n\n\t\t\tstd::string name;\n\t\t\tfir::Type* type = 0;\n\t\t\tLocation loc;\n\t\t\tbool optional = false;\n\t\t\tbool ignoreName = false;\n\t\t};\n\n\t\tstruct Solution_t\n\t\t{\n\t\t\tSolution_t() { }\n\t\t\texplicit Solution_t(const util::hash_map<std::string, fir::Type*>& p) : solutions(p) { }\n\n\t\t\tbool hasSolution(const std::string& n) const ;\n\t\t\tfir::LocatedType getSolution(const std::string& n) const;\n\t\t\tvoid addSolution(const std::string& x, const fir::LocatedType& y);\n\n\t\t\tfir::Type* substitute(fir::Type* x) const;\n\t\t\tvoid resubstituteIntoSolutions();\n\t\t\tvoid addSubstitution(fir::Type* x, fir::Type* y);\n\n\t\t\tbool operator == (const Solution_t& other) const;\n\t\t\tbool operator != (const Solution_t& other) const;\n\n\t\t\t// incorporate distance so we can use this shit for our function resolution.\n\t\t\tint distance = 0;\n\t\t\tutil::hash_map<std::string, fir::Type*> solutions;\n\t\t\tutil::hash_map<fir::Type*, fir::Type*> substitutions;\n\t\t};\n\n\n\t\tstd::pair<Solution_t, ErrorMsg*> solveTypeList(const Location& callLoc, const std::vector<ArgType>& target,\n\t\t\tconst std::vector<ArgType>& given, const Solution_t& partial, bool isFnCall);\n\n\t\tTCResult fullyInstantiatePolymorph(TypecheckState* fs, ast::Parameterisable* thing, const TypeParamMap_t& mappings);\n\n\t\tstruct PolyRefResult\n\t\t{\n\t\t\tPolyRefResult(const TCResult& r, const Solution_t& s, ast::Parameterisable* t) :\n\t\t\t\tres(r), soln(s), thing(t) { }\n\n\t\t\tTCResult res;\n\t\t\tSolution_t soln;\n\t\t\tast::Parameterisable* thing;\n\t\t};\n\n\t\tstd::vector<PolyRefResult> findPolymorphReferences(TypecheckState* fs, const std::string& name,\n\t\t\tconst std::vector<ast::Parameterisable*>& gdefs, const PolyArgMapping_t& _gmaps, fir::Type* return_infer,\n\t\t\tfir::Type* type_infer, bool isFnCall, std::vector<FnCallArgument>* args);\n\n\t\tstd::pair<TCResult, Solution_t> attemptToInstantiatePolymorph(TypecheckState* fs, ast::Parameterisable* thing, const std::string& name,\n\t\t\tconst TypeParamMap_t& _gmaps, fir::Type* return_infer, fir::Type* type_infer, bool isFnCall, std::vector<FnCallArgument>* args,\n\t\t\tbool fillplaceholders, fir::Type* problem_infer = 0);\n\n\n\t\tnamespace internal\n\t\t{\n\t\t\tenum class TrfType\n\t\t\t{\n\t\t\t\tNone,\n\t\t\t\tSlice,\n\t\t\t\tPointer,\n\t\t\t\tFixedArray,\n\t\t\t\tDynamicArray,\n\t\t\t\tVariadicArray,\n\t\t\t};\n\n\t\t\tstruct Trf\n\t\t\t{\n\t\t\t\tbool operator == (const Trf& other) const { return this->type == other.type && this->data == other.data; }\n\t\t\t\tbool operator != (const Trf& other) const { return !(*this == other); }\n\n\t\t\t\tTrf(TrfType t, size_t d = 0) : type(t), data(d) { }\n\n\t\t\t\tTrfType type = TrfType::None;\n\t\t\t\tsize_t data = 0;\n\t\t\t};\n\n\t\t\tfir::Type* applyTransforms(fir::Type* base, const std::vector<Trf>& trfs);\n\n\t\t\tstd::pair<fir::Type*, std::vector<Trf>> decomposeIntoTransforms(fir::Type* t, size_t max);\n\t\t\tstd::pair<pts::Type*, std::vector<Trf>> decomposeIntoTransforms(pts::Type* t);\n\n\t\t\tint getNextSessionId();\n\n\n\n\t\t\tfir::Type* mergeNumberTypes(fir::Type* a, fir::Type* b);\n\t\t\tstd::vector<fir::Type*> convertPtsTypeList(TypecheckState* fs, const ProblemSpace_t& problems,\n\t\t\t\tconst std::vector<pts::Type*>& input, int polysession);\n\n\t\t\tfir::Type* convertPtsType(TypecheckState* fs, const ProblemSpace_t& problems,\n\t\t\t\tpts::Type* input, int polysession);\n\n\t\t\tstd::vector<ArgType> unwrapFunctionParameters(TypecheckState* fs, const ProblemSpace_t& problems,\n\t\t\t\tconst std::vector<ast::FuncDefn::Param>& args, int polysession);\n\n\n\n\t\t\tstd::pair<TCResult, Solution_t> solvePolymorphWithPlaceholders(TypecheckState* fs, ast::Parameterisable* thing, const std::string& name,\n\t\t\t\tconst TypeParamMap_t& partial);\n\n\t\t\tstd::vector<std::string> getMissingSolutions(const ProblemSpace_t& needed, const TypeParamMap_t& solution,\n\t\t\t\tbool allowPlaceholders);\n\n\n\t\t\tstd::pair<Solution_t, ErrorMsg*> inferTypesForPolymorph(TypecheckState* fs, ast::Parameterisable* thing, const std::string& name,\n\t\t\t\tconst ProblemSpace_t& problems, const std::vector<FnCallArgument>& _input, const TypeParamMap_t& partial,\n\t\t\t\tfir::Type* return_infer, fir::Type*, bool isFnCall, fir::Type* problem_infer, util::hash_map<std::string, size_t>* origParamOrder);\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/precompile.h",
    "content": "// precompile.h\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n#if !defined(PRECOMPILE_H) && !defined(DO_NOT_INCLUDE_PRECOMPILE)\n#define PRECOMPILE_H\n\n#include <stdio.h>\n#include <stdint.h>\n#include <stddef.h>\n#include <stdarg.h>\n#include <string.h>\n\n#include <map>\n#include <string>\n#include <vector>\n#include <utility>\n#include <charconv>\n#include <algorithm>\n#include <functional>\n#include <type_traits>\n#include <string_view>\n#include <unordered_map>\n#include <unordered_set>\n\n#include <cmath>\n#include <cfloat>\n#include <limits>\n#include <complex>\n#include <sstream>\n#include <iostream>\n#include <stdexcept>\n#include <algorithm>\n\n#include \"zpr.h\"\n#include \"zfu.h\"\n\n#endif\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/pts.h",
    "content": "// pts.h\n// Copyright (c) 2014 - 2016, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#include \"defs.h\"\n#include \"precompile.h\"\n\n// Parser Type System\n// why in the ever-living fuck does this even exist?\n// type system upon type system...\n\n// it's not meant to be full-fledged (nor transferrable)\n// so i'm gonna use a bunch of shortcuts -- dynamic_cast everywhere, direct constructing, etc.\nnamespace pts\n{\n\tstruct Type;\n\tstruct NamedType;\n\tstruct PointerType;\n\tstruct TupleType;\n\tstruct ArraySliceType;\n\tstruct FixedArrayType;\n\tstruct DynamicArrayType;\n\tstruct VariadicArrayType;\n\tstruct FunctionType;\n\n\n\n\tstruct Type\n\t{\n\t\tvirtual ~Type() { }\n\t\tvirtual std::string str();\n\n\t\tNamedType* toNamedType();\n\t\tTupleType* toTupleType();\n\t\tPointerType* toPointerType();\n\t\tFunctionType* toFunctionType();\n\t\tFixedArrayType* toFixedArrayType();\n\t\tArraySliceType* toArraySliceType();\n\t\tDynamicArrayType* toDynamicArrayType();\n\t\tVariadicArrayType* toVariadicArrayType();\n\n\t\tbool isNamedType();\n\t\tbool isTupleType();\n\t\tbool isPointerType();\n\t\tbool isFunctionType();\n\t\tbool isArraySliceType();\n\t\tbool isFixedArrayType();\n\t\tbool isDynamicArrayType();\n\t\tbool isVariadicArrayType();\n\n\t\tLocation loc;\n\n\t\tprotected:\n\t\t\tType(const Location& l) : loc(l) { }\n\t};\n\n\n\tstruct InferredType : Type\n\t{\n\t\tvirtual ~InferredType() { }\n\t\tInferredType(const Location& l) : Type(l) { }\n\n\t\tvirtual std::string str() override { return \"?\"; }\n\n\n\t\tstatic InferredType* get();\n\t};\n\n\n\tstruct NamedType : Type\n\t{\n\t\tvirtual ~NamedType() { }\n\n\t\tvirtual std::string str() override;\n\t\tstd::string name;\n\n\t\tPolyArgMapping_t genericMapping;\n\n\t\tstatic NamedType* create(const Location& l, const std::string& s);\n\t\tstatic NamedType* create(const Location& l, const std::string& s, const PolyArgMapping_t& genericMapping);\n\n\t\t// private:\n\t\texplicit NamedType(const Location& l, const std::string& n) : Type(l), name(n) { }\n\t};\n\n\n\tstruct PointerType : Type\n\t{\n\t\tvirtual ~PointerType() { }\n\t\texplicit PointerType(const Location& l, pts::Type* b, bool mut) : Type(l), base(b), isMutable(mut) { }\n\t\tvirtual std::string str() override;\n\n\t\tpts::Type* base = 0;\n\t\tbool isMutable = false;\n\t};\n\n\n\tstruct TupleType : Type\n\t{\n\t\tvirtual ~TupleType() { }\n\t\texplicit TupleType(const Location& l, const std::vector<pts::Type*>& ts) : Type(l), types(ts) { }\n\t\tvirtual std::string str() override;\n\n\t\tstd::vector<pts::Type*> types;\n\t};\n\n\n\t// int[x], where x *is* a literal (eg. 4, 10, 0xF00D)\n\tstruct FixedArrayType : Type\n\t{\n\t\tvirtual ~FixedArrayType() { }\n\t\texplicit FixedArrayType(const Location& l, pts::Type* b, size_t s) : Type(l), base(b), size(s) { }\n\t\tvirtual std::string str() override;\n\n\t\tpts::Type* base = 0;\n\t\tsize_t size = 0;\n\t};\n\n\n\t// int[x], where x is *not* a literal\n\tstruct DynamicArrayType : Type\n\t{\n\t\tvirtual ~DynamicArrayType() { }\n\t\texplicit DynamicArrayType(const Location& l, pts::Type* b) : Type(l), base(b) { }\n\t\tvirtual std::string str() override;\n\n\t\tpts::Type* base = 0;\n\t};\n\n\n\tstruct VariadicArrayType : Type\n\t{\n\t\tvirtual ~VariadicArrayType() { }\n\t\texplicit VariadicArrayType(const Location& l, pts::Type* b) : Type(l), base(b) { }\n\t\tvirtual std::string str() override;\n\n\t\tpts::Type* base = 0;\n\t};\n\n\n\tstruct ArraySliceType : Type\n\t{\n\t\tvirtual ~ArraySliceType() { }\n\t\texplicit ArraySliceType(const Location& l, pts::Type* b, bool m) : Type(l), base(b), mut(m) { }\n\t\tvirtual std::string str() override;\n\n\t\tpts::Type* base = 0;\n\t\tbool mut = false;\n\t};\n\n\n\tstruct FunctionType : Type\n\t{\n\t\tvirtual ~FunctionType() { }\n\t\texplicit FunctionType(const Location& l, const std::vector<pts::Type*>& args, pts::Type* ret) : Type(l), argTypes(args), returnType(ret) { }\n\t\tvirtual std::string str() override;\n\n\t\tutil::hash_map<std::string, TypeConstraints_t> genericTypes;\n\t\tstd::vector<pts::Type*> argTypes;\n\t\tpts::Type* returnType = 0;\n\t};\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/repl.h",
    "content": "// repl.h\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n#include \"defs.h\"\n\n#include <optional>\n\n\nnamespace ztmu\n{\n\tstruct State;\n}\n\n\nnamespace repl\n{\n\tstruct State;\n\n\tvoid start();\n\tvoid setupEnvironment();\n\n\tbool processLine(const std::string& line);\n\tstd::optional<sst::Stmt*> parseAndTypecheck(const std::string& line, bool* needmore);\n\n\tbool runCommand(const std::string& command, ztmu::State* consoleState);\n\n\t// used to save/restore if we wanna do weird things.\n\tvoid setEnvironment(State* st);\n\tState* getEnvironment();\n\n\tvoid saveHistory(const std::vector<std::vector<std::string>>& history);\n\tstd::vector<std::vector<std::string>> loadHistory();\n\n\n\ttemplate <typename... Args>\n\tstatic void error(const std::string& fmt, Args&&... args)\n\t{\n\t\tfprintf(stderr, \" %s*%s %s\\n\", COLOUR_RED_BOLD, COLOUR_RESET, zpr::sprint(fmt, args...).c_str());\n\t}\n\n\ttemplate <typename... Args>\n\tstatic void log(const std::string& fmt, Args&&... args)\n\t{\n\t\tprintf(\" %s*%s %s\\n\", COLOUR_GREEN_BOLD, COLOUR_RESET, zpr::sprint(fmt, args...).c_str());\n\t}\n}\n"
  },
  {
    "path": "source/include/resolver.h",
    "content": "// resolver.h\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#include \"ast.h\"\n#include \"sst.h\"\n#include \"stcommon.h\"\n\n#include <set>\n\nnamespace fir\n{\n\tstruct LocatedType;\n}\n\nnamespace sst\n{\n\tstruct TypecheckState;\n\n\tnamespace poly\n\t{\n\t\tstruct ArgType;\n\t}\n\n\tnamespace resolver\n\t{\n\t\tstd::pair<int, ErrorMsg*> computeNamedOverloadDistance(const Location& fnLoc, const std::vector<FnParam>& target,\n\t\t\tconst std::vector<FnCallArgument>& _args, bool cvararg, const Location& callLoc);\n\n\t\tstd::pair<int, ErrorMsg*> computeOverloadDistance(const Location& fnLoc, const std::vector<fir::LocatedType>& target,\n\t\t\tconst std::vector<fir::LocatedType>& _args, bool cvararg, const Location& callLoc);\n\n\n\t\tTCResult resolveFunctionCall(TypecheckState* fs, const Location& callLoc, const std::string& name, std::vector<FnCallArgument>* arguments,\n\t\t\tconst PolyArgMapping_t& gmaps, bool traverseUp, fir::Type* inferredRetType);\n\n\t\tTCResult resolveFunctionCallFromCandidates(TypecheckState* fs, const Location& callLoc, const std::vector<Defn*>& cs,\n\t\t\tstd::vector<FnCallArgument>* arguments, const PolyArgMapping_t& gmaps, bool allowImplicitSelf);\n\n\t\tTCResult resolveConstructorCall(TypecheckState* fs, const Location& callLoc, TypeDefn* defn, const std::vector<FnCallArgument>& arguments,\n\t\t\tconst PolyArgMapping_t& gmaps);\n\n\n\t\tstd::pair<util::hash_map<std::string, size_t>, ErrorMsg*> verifyStructConstructorArguments(const Location& callLoc,\n\t\t\tconst std::string& name, const std::vector<std::string>& fieldNames, const std::vector<FnCallArgument>& arguments);\n\n\t\tTCResult resolveAndInstantiatePolymorphicUnion(TypecheckState* fs, sst::UnionVariantDefn* uvd, std::vector<FnCallArgument>* arguments,\n\t\t\tfir::Type* return_infer, bool isFnCall);\n\n\n\t\tErrorMsg* createErrorFromFailedCandidates(TypecheckState* fs, const Location& callLoc, const std::string& name,\n\t\t\tconst std::vector<FnCallArgument>& args, const std::vector<std::pair<Locatable*, ErrorMsg*>>& fails);\n\n\n\t\tnamespace misc\n\t\t{\n\t\t\tstd::pair<TypeParamMap_t, ErrorMsg*> canonicalisePolyArguments(TypecheckState* fs, ast::Parameterisable* thing, const PolyArgMapping_t& pams);\n\n\t\t\tstd::vector<FnCallArgument> typecheckCallArguments(TypecheckState* fs, const std::vector<std::pair<std::string, ast::Expr*>>& args);\n\n\t\t\ttemplate <typename T>\n\t\t\tutil::hash_map<std::string, size_t> getNameIndexMap(const std::vector<T>& params)\n\t\t\t{\n\t\t\t\tutil::hash_map<std::string, size_t> ret;\n\t\t\t\tfor(size_t i = 0; i < params.size(); i++)\n\t\t\t\t{\n\t\t\t\t\tconst auto& arg = params[i];\n\t\t\t\t\tret[arg.name] = i;\n\t\t\t\t}\n\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t}\n\n\t\tnamespace internal\n\t\t{\n\t\t\tstd::pair<TCResult, std::vector<FnCallArgument>> resolveFunctionCallFromCandidates(TypecheckState* fs, const Location& callLoc,\n\t\t\t\tconst std::vector<std::pair<Defn*, std::vector<FnCallArgument>>>& cands, const PolyArgMapping_t& gmaps, bool allowImplicitSelf,\n\t\t\t\tfir::Type* return_infer);\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/sst.h",
    "content": "// sst.h\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n#include \"defs.h\"\n#include \"sst_expr.h\"\n\n\n#include \"mpreal/mpreal.h\"\n\n\n\nnamespace fir\n{\n\tstruct Type;\n\tstruct ClassType;\n\tstruct FunctionType;\n\n\tstruct Function;\n\tstruct ConstantValue;\n}\n\nnamespace cgn\n{\n\tstruct CodegenState;\n}\n\nnamespace ast\n{\n\tstruct FuncDefn;\n\tstruct TypeDefn;\n}\n\nnamespace sst\n{\n\t//! ACHTUNG !\n\t//* note: this is the thing that everyone calls to check the mutability of a slice of something\n\t//* defined in typecheck/slice.cpp\n\tbool getMutabilityOfSliceOfType(fir::Type* ty);\n\n\tstruct StateTree;\n\tstruct Block;\n\n\tstruct HasBlocks\n\t{\n\t\tHasBlocks() { }\n\t\tvirtual ~HasBlocks() { }\n\t\tvirtual std::vector<Block*> getBlocks() = 0;\n\n\t\tbool elideMergeBlock = false;\n\t};\n\n\tstruct TypeDefn : Defn\n\t{\n\t\tTypeDefn(const Location& l) : Defn(l) { this->readableName = \"type definition\"; }\n\t\t~TypeDefn() { }\n\n\t\tast::TypeDefn* original = 0;\n\t\tScope innerScope;\n\t};\n\n\n\tstruct TypeExpr : Expr\n\t{\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\t//* allows us to intern this, so we don't leak memory.\n\t\tstatic TypeExpr* make(const Location& l, fir::Type* t);\n\n\t\tTypeExpr(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"<TYPE EXPRESSION>\"; }\n\t\t~TypeExpr() { }\n\t};\n\n\tstruct RawValueExpr : Expr\n\t{\n\t\tRawValueExpr(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"<RAW VALUE EXPRESSION>\"; }\n\t\t~RawValueExpr() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState*, fir::Type* = 0) override { return this->rawValue; }\n\n\t\tCGResult rawValue;\n\t};\n\n\n\tstruct ArgumentDefn;\n\tstruct Block : Stmt\n\t{\n\t\tBlock(const Location& l) : Stmt(l) { this->readableName = \"block\"; }\n\t\t~Block() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tLocation closingBrace;\n\n\t\tbool isSingleExpr = false;\n\t\tstd::vector<Stmt*> statements;\n\t\tstd::vector<Stmt*> deferred;\n\n\t\tstd::function<void ()> preBodyCode;\n\t\tstd::function<void ()> postBodyCode;\n\t};\n\n\tstruct IfStmt : Stmt, HasBlocks\n\t{\n\t\tIfStmt(const Location& l) : Stmt(l) { this->readableName = \"if statement\"; }\n\t\t~IfStmt() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\t\tvirtual std::vector<Block*> getBlocks() override;\n\n\t\tstruct Case\n\t\t{\n\t\t\tExpr* cond = 0;\n\t\t\tBlock* body = 0;\n\n\t\t\tstd::vector<Stmt*> inits;\n\n\t\t\tCase(Expr* c, Block* b, const std::vector<Stmt*>& i) : cond(c), body(b), inits(i) { }\n\t\t};\n\n\t\tstd::vector<Case> cases;\n\t\tBlock* elseCase = 0;\n\t};\n\n\tstruct ReturnStmt : Stmt\n\t{\n\t\tReturnStmt(const Location& l) : Stmt(l) { this->readableName = \"return statement\"; }\n\t\t~ReturnStmt() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tExpr* value = 0;\n\t\tfir::Type* expectedType = 0;\n\t};\n\n\tstruct WhileLoop : Stmt, HasBlocks\n\t{\n\t\tWhileLoop(const Location& l) : Stmt(l) { this->readableName = \"while loop\"; }\n\t\t~WhileLoop() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\t\tvirtual std::vector<Block*> getBlocks() override;\n\n\t\tExpr* cond = 0;\n\t\tBlock* body = 0;\n\n\t\tbool isDoVariant = false;\n\t};\n\n\tstruct VarDefn;\n\tstruct ForeachLoop : Stmt, HasBlocks\n\t{\n\t\tForeachLoop(const Location& l) : Stmt(l) { this->readableName = \"for loop\"; }\n\t\t~ForeachLoop() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\t\tvirtual std::vector<Block*> getBlocks() override;\n\n\t\tVarDefn* indexVar = 0;\n\t\tDecompMapping mappings;\n\n\t\tExpr* array = 0;\n\t\tBlock* body = 0;\n\t};\n\n\n\tstruct BreakStmt : Stmt\n\t{\n\t\tBreakStmt(const Location& l) : Stmt(l) { this->readableName = \"break statement\"; }\n\t\t~BreakStmt() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\t};\n\n\tstruct ContinueStmt : Stmt\n\t{\n\t\tContinueStmt(const Location& l) : Stmt(l) { this->readableName = \"continue statement\"; }\n\t\t~ContinueStmt() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\t};\n\n\tstruct SizeofOp : Expr\n\t{\n\t\tSizeofOp(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"sizeof expression\"; }\n\t\t~SizeofOp() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tfir::Type* typeToSize = 0;\n\t};\n\n\tstruct TypeidOp : Expr\n\t{\n\t\tTypeidOp(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"sizeof expression\"; }\n\t\t~TypeidOp() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tfir::Type* typeToId = 0;\n\t};\n\n\tstruct FunctionDefn;\n\tstruct AllocOp : Expr\n\t{\n\t\tAllocOp(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"alloc statement\"; }\n\t\t~AllocOp() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tfir::Type* elmType = 0;\n\t\tstd::vector<Expr*> counts;\n\t\tstd::vector<FnCallArgument> arguments;\n\n\t\tDefn* constructor = 0;\n\n\t\tVarDefn* initBlockVar = 0;\n\t\tVarDefn* initBlockIdx = 0;\n\t\tBlock* initBlock = 0;\n\n\t\tbool isMutable = false;\n\t};\n\n\tstruct DeallocOp : Stmt\n\t{\n\t\tDeallocOp(const Location& l) : Stmt(l) { this->readableName = \"free statement\"; }\n\t\t~DeallocOp() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\t\tExpr* expr = 0;\n\t};\n\n\tstruct BinaryOp : Expr\n\t{\n\t\tBinaryOp(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"binary expression\"; }\n\t\t~BinaryOp() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tExpr* left = 0;\n\t\tExpr* right = 0;\n\t\tstd::string op;\n\n\t\tFunctionDefn* overloadedOpFunction = 0;\n\t};\n\n\tstruct UnaryOp : Expr\n\t{\n\t\tUnaryOp(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"unary expression\"; }\n\t\t~UnaryOp() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tExpr* expr = 0;\n\t\tstd::string op;\n\n\t\tFunctionDefn* overloadedOpFunction = 0;\n\t};\n\n\tstruct AssignOp : Expr\n\t{\n\t\tAssignOp(const Location& l);\n\t\t~AssignOp() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tstd::string op;\n\n\t\tExpr* left = 0;\n\t\tExpr* right = 0;\n\t};\n\n\t//* for the case where we assign to a tuple literal, to enable (a, b) = (b, a) (or really (a, b) = anything)\n\tstruct TupleAssignOp : Expr\n\t{\n\t\tTupleAssignOp(const Location& l);\n\t\t~TupleAssignOp() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tstd::vector<Expr*> lefts;\n\t\tExpr* right = 0;\n\t};\n\n\n\tstruct SubscriptDollarOp : Expr\n\t{\n\t\tSubscriptDollarOp(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"dollar expression\"; }\n\t\t~SubscriptDollarOp() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\t};\n\n\tstruct SubscriptOp : Expr\n\t{\n\t\tSubscriptOp(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"subscript expression\"; }\n\t\t~SubscriptOp() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tExpr* expr = 0;\n\t\tExpr* inside = 0;\n\t};\n\n\tstruct SliceOp : Expr\n\t{\n\t\tSliceOp(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"slice expression\"; }\n\t\t~SliceOp() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tExpr* expr = 0;\n\t\tExpr* begin = 0;\n\t\tExpr* end = 0;\n\t};\n\n\n\n\n\n\tstruct FunctionCall : Expr\n\t{\n\t\tFunctionCall(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"function call\"; }\n\t\t~FunctionCall() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tstd::string name;\n\t\tDefn* target = 0;\n\t\tstd::vector<FnCallArgument> arguments;\n\t\tbool isImplicitMethodCall = false;\n\t};\n\n\tstruct ExprCall : Expr\n\t{\n\t\tExprCall(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"function call\"; }\n\t\t~ExprCall() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tExpr* callee = 0;\n\t\tstd::vector<Expr*> arguments;\n\t};\n\n\n\tstruct StructDefn;\n\tstruct ClassDefn;\n\tstruct StructConstructorCall : Expr\n\t{\n\t\tStructConstructorCall(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"struct constructor call\"; }\n\t\t~StructConstructorCall() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tStructDefn* target = 0;\n\t\tstd::vector<FnCallArgument> arguments;\n\t};\n\n\tstruct ClassConstructorCall : Expr\n\t{\n\t\tClassConstructorCall(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"class constructor call\"; }\n\t\t~ClassConstructorCall() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tClassDefn* classty = 0;\n\t\tFunctionDefn* target = 0;\n\t\tstd::vector<FnCallArgument> arguments;\n\t};\n\n\tstruct BaseClassConstructorCall : ClassConstructorCall\n\t{\n\t\tBaseClassConstructorCall(const Location& l, fir::Type* t) : ClassConstructorCall(l, t) { this->readableName = \"base class constructor call\"; }\n\t\t~BaseClassConstructorCall() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\t};\n\n\n\tstruct VarDefn;\n\tstruct VarRef : Expr\n\t{\n\t\tVarRef(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"identifier\"; }\n\t\t~VarRef() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tstd::string name;\n\t\tDefn* def = 0;\n\t\tbool isImplicitField = false;\n\t};\n\n\tstruct SelfVarRef : Expr\n\t{\n\t\tSelfVarRef(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"this\"; }\n\t\t~SelfVarRef() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\t};\n\n\tstruct ScopeExpr : Expr\n\t{\n\t\tScopeExpr(const Location& l, fir::Type* t, const Scope& scope) : Expr(l, t), scope(scope)\n\t\t\t{ this->readableName = \"<SCOPE EXPRESSION>\"; }\n\n\t\t~ScopeExpr() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tScope scope;\n\t};\n\n\tstruct FieldDotOp : Expr\n\t{\n\t\tFieldDotOp(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"field access\"; }\n\t\t~FieldDotOp() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tExpr* lhs = 0;\n\t\tstd::string rhsIdent;\n\t\tbool isMethodRef = false;\n\n\t\tbool isTransparentField = false;\n\t\tsize_t indexOfTransparentField = 0;\n\t};\n\n\tstruct MethodDotOp : Expr\n\t{\n\t\tMethodDotOp(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"method call\"; }\n\t\t~MethodDotOp() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tExpr* lhs = 0;\n\t\tExpr* call = 0;\n\t};\n\n\tstruct TupleDotOp : Expr\n\t{\n\t\tTupleDotOp(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"tuple access\"; }\n\t\t~TupleDotOp() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tExpr* lhs = 0;\n\t\tsize_t index = 0;\n\t};\n\n\tstruct BuiltinDotOp : Expr\n\t{\n\t\tBuiltinDotOp(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"dot operator\"; }\n\t\t~BuiltinDotOp() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tExpr* lhs = 0;\n\t\tstd::string name;\n\n\t\tbool isFunctionCall = false;\n\t\tstd::vector<Expr*> args;\n\t};\n\n\tstruct EnumDefn;\n\tstruct EnumDotOp : Expr\n\t{\n\t\tEnumDotOp(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"enum case access\"; }\n\t\t~EnumDotOp() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tstd::string caseName;\n\t\tEnumDefn* enumeration = 0;\n\t};\n\n\n\n\tstruct LiteralNumber : Expr\n\t{\n\t\tLiteralNumber(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"number literal\"; }\n\t\t~LiteralNumber() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tmpfr::mpreal num;\n\t};\n\n\tstruct LiteralString : Expr\n\t{\n\t\tLiteralString(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"string literal\"; }\n\t\t~LiteralString() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tstd::string str;\n\t\tbool isCString = false;\n\t};\n\n\tstruct LiteralNull : Expr\n\t{\n\t\tLiteralNull(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"null literal\"; }\n\t\t~LiteralNull() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\t};\n\n\tstruct LiteralBool : Expr\n\t{\n\t\tLiteralBool(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"boolean literal\"; }\n\t\t~LiteralBool() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tbool value = false;\n\t};\n\n\tstruct LiteralChar : Expr\n\t{\n\t\tLiteralChar(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"character literal\"; }\n\t\t~LiteralChar() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tuint32_t value = false;\n\t};\n\n\tstruct LiteralTuple : Expr\n\t{\n\t\tLiteralTuple(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"tuple literal\"; }\n\t\t~LiteralTuple() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tstd::vector<Expr*> values;\n\t};\n\n\tstruct LiteralArray : Expr\n\t{\n\t\tLiteralArray(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"array literal\"; }\n\t\t~LiteralArray() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tstd::vector<Expr*> values;\n\t};\n\n\n\n\tstruct RangeExpr : Expr\n\t{\n\t\tRangeExpr(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"range expression\"; }\n\t\t~RangeExpr() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tExpr* start = 0;\n\t\tExpr* end = 0;\n\n\t\tExpr* step = 0;\n\t\tbool halfOpen = false;\n\t};\n\n\tstruct SplatExpr : Expr\n\t{\n\t\tSplatExpr(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"splat expression\"; }\n\t\t~SplatExpr() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* infer = 0) override;\n\n\t\tExpr* inside = 0;\n\t};\n\n\n\tstruct NamespaceDefn : Stmt\n\t{\n\t\tNamespaceDefn(const Location& l) : Stmt(l) { this->readableName = \"namespace\"; }\n\t\t~NamespaceDefn() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tstd::string name;\n\t\tstd::vector<Stmt*> statements;\n\t};\n\n\n\tstruct VarDefn : Defn\n\t{\n\t\tVarDefn(const Location& l) : Defn(l) { this->readableName = \"variable definition\"; }\n\t\t~VarDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"variable\"; }\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tExpr* init = 0;\n\t\tbool immutable = false;\n\t\tFunctionDefn* definingFunction = 0;\n\t};\n\n\tstruct ArgumentDefn : VarDefn\n\t{\n\t\tArgumentDefn(const Location& l) : VarDefn(l) { this->readableName = \"<ARGUMENT DEFINITION>\"; this->immutable = true; }\n\t\t~ArgumentDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"argument\"; }\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\t};\n\n\tstruct FunctionDecl : Defn\n\t{\n\t\tstd::vector<FnParam> params;\n\t\tfir::Type* returnType = 0;\n\t\tfir::Type* parentTypeForMethod = 0;\n\n\t\tbool isVarArg = false;\n\n\t\tvirtual std::string getKind() override { return \"function\"; }\n\n\t\tprotected:\n\t\tFunctionDecl(const Location& l) : Defn(l) { this->readableName = \"function declaration\"; }\n\t\t~FunctionDecl() { }\n\t};\n\n\tstruct FunctionDefn : FunctionDecl\n\t{\n\t\tFunctionDefn(const Location& l) : FunctionDecl(l) { this->readableName = \"function definition\"; }\n\t\t~FunctionDefn() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tstd::vector<ArgumentDefn*> arguments;\n\n\t\t// bleh, this exists so we can go *into* the scope to inspect stuff if necessary\n\t\tStateTree* insideTree = 0;\n\n\t\tBlock* body = 0;\n\t\tbool needReturnVoid = false;\n\n\t\tbool isVirtual = false;\n\t\tbool isOverride = false;\n\t\tbool isMutating = false;\n\n\t\tast::FuncDefn* original = 0;\n\t};\n\n\tstruct ForeignFuncDefn : FunctionDecl\n\t{\n\t\tForeignFuncDefn(const Location& l) : FunctionDecl(l) { this->readableName = \"foreign function definition\"; }\n\t\t~ForeignFuncDefn() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tbool isIntrinsic = false;\n\t\tstd::string realName;\n\t};\n\n\tstruct OperatorOverloadDefn : FunctionDefn\n\t{\n\t\tOperatorOverloadDefn(const Location& l) : FunctionDefn(l) { this->readableName = \"operator overload definition\"; }\n\t\t~OperatorOverloadDefn() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\t};\n\n\n\tstruct DecompDefn : Stmt\n\t{\n\t\tDecompDefn(const Location& l) : Stmt(l) { this->readableName = \"destructuring variable definition\"; }\n\t\t~DecompDefn() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tExpr* init = 0;\n\t\tbool immutable = false;\n\t\tDecompMapping bindings;\n\t};\n\n\n\tstruct StructFieldDefn : VarDefn\n\t{\n\t\tStructFieldDefn(const Location& l) : VarDefn(l) { }\n\t\t~StructFieldDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"field\"; }\n\t\tvirtual CGResult _codegen(cgn::CodegenState*, fir::Type* = 0) override { return CGResult(0); }\n\n\t\tTypeDefn* parentType = 0;\n\t\tbool isTransparentField = false;\n\t};\n\n\tstruct ClassInitialiserDefn : FunctionDefn\n\t{\n\t\tClassInitialiserDefn(const Location& l) : FunctionDefn(l) { }\n\t\t~ClassInitialiserDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"initialiser\"; }\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override { return this->FunctionDefn::_codegen(cs, inferred); }\n\t};\n\n\n\tstruct BareTypeDefn : TypeDefn\n\t{\n\t\tBareTypeDefn(const Location& l) : TypeDefn(l) { this->readableName = \"type definition\"; }\n\t\t~BareTypeDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"type\"; }\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\t};\n\n\n\tstruct TraitDefn : TypeDefn\n\t{\n\t\tTraitDefn(const Location& l) : TypeDefn(l) { this->readableName = \"trait definition\"; }\n\t\t~TraitDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"trait\"; }\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tstd::vector<FunctionDecl*> methods;\n\t};\n\n\tstruct StructDefn : TypeDefn\n\t{\n\t\tStructDefn(const Location& l) : TypeDefn(l) { this->readableName = \"struct definition\"; }\n\t\t~StructDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"struct\"; }\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tstd::vector<StructFieldDefn*> fields;\n\t\tstd::vector<FunctionDefn*> methods;\n\t\tstd::vector<TraitDefn*> traits;\n\t};\n\n\n\tstruct ClassDefn : StructDefn\n\t{\n\t\tClassDefn(const Location& l) : StructDefn(l) { this->readableName = \"class definition\"; }\n\t\t~ClassDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"class\"; }\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\n\t\tClassDefn* baseClass = 0;\n\n\t\tstd::vector<TypeDefn*> nestedTypes;\n\t\tstd::vector<VarDefn*> staticFields;\n\t\tstd::vector<FunctionDefn*> staticMethods;\n\t\tstd::vector<FunctionDefn*> initialisers;\n\n\t\tFunctionDefn* deinitialiser = 0;\n\t\tFunctionDefn* copyInitialiser = 0;\n\t\tFunctionDefn* moveInitialiser = 0;\n\t};\n\n\n\tstruct EnumCaseDefn : Defn\n\t{\n\t\tEnumCaseDefn(const Location& l) : Defn(l) { this->readableName = \"enum case definition\"; }\n\t\t~EnumCaseDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"enum case\"; }\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tExpr* val = 0;\n\t\tsize_t index = 0;\n\t\tEnumDefn* parentEnum = 0;\n\t\tfir::ConstantValue* value = 0;\n\t};\n\n\tstruct EnumDefn : TypeDefn\n\t{\n\t\tEnumDefn(const Location& l) : TypeDefn(l) { this->readableName = \"enum definition\"; }\n\t\t~EnumDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"enum\"; }\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tfir::Type* memberType = 0;\n\t\tutil::hash_map<std::string, EnumCaseDefn*> cases;\n\t};\n\n\n\tstruct RawUnionDefn : TypeDefn\n\t{\n\t\tRawUnionDefn(const Location& l) : TypeDefn(l) { this->readableName = \"raw union definition\"; }\n\t\t~RawUnionDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"raw union\"; }\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tutil::hash_map<std::string, StructFieldDefn*> fields;\n\t\tstd::vector<StructFieldDefn*> transparentFields;\n\t};\n\n\n\n\tstruct UnionVariantDefn;\n\tstruct UnionDefn : TypeDefn\n\t{\n\t\tUnionDefn(const Location& l) : TypeDefn(l) { this->readableName = \"union definition\"; }\n\t\t~UnionDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"union\"; }\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tutil::hash_map<std::string, UnionVariantDefn*> variants;\n\t};\n\n\tstruct UnionVariantDefn : TypeDefn\n\t{\n\t\tUnionVariantDefn(const Location& l) : TypeDefn(l) { this->readableName = \"union variant definition\"; }\n\t\t~UnionVariantDefn() { }\n\n\t\tvirtual std::string getKind() override { return \"union variant\"; }\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tstd::string variantName;\n\t\tUnionDefn* parentUnion = 0;\n\t};\n\n\tstruct UnionVariantConstructor : Expr\n\t{\n\t\tUnionVariantConstructor(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"union constructor\"; }\n\t\t~UnionVariantConstructor() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tsize_t variantId = 0;\n\t\tUnionDefn* parentUnion = 0;\n\t\tstd::vector<FnCallArgument> args;\n\t};\n\n\tstruct RunDirective : Expr\n\t{\n\t\tRunDirective(const Location& l, fir::Type* t) : Expr(l, t) { this->readableName = \"run directive\"; }\n\t\t~RunDirective() { }\n\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\t// mutually exclusive!\n\t\tBlock* block = 0;\n\t\tExpr* insideExpr = 0;\n\t};\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/sst_expr.h",
    "content": "// sst_expr.h\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n#include \"defs.h\"\n#include \"stcommon.h\"\n\nnamespace cgn\n{\n\tstruct CodegenState;\n}\n\nnamespace sst\n{\n\tstruct Stmt : Locatable\n\t{\n\t\tStmt(const Location& l) : Locatable(l, \"statement\") { }\n\t\tvirtual ~Stmt() { }\n\n\t\tvirtual CGResult codegen(cgn::CodegenState* cs, fir::Type* inferred = 0);\n\t\tvirtual CGResult _codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) = 0;\n\n\t\tAttribSet attrs;\n\t};\n\n\tstruct Expr : Stmt\n\t{\n\t\tExpr(const Location& l, fir::Type* t) : Stmt(l), type(t) { this->readableName = \"expression\"; }\n\t\t~Expr() { }\n\n\t\tfir::Type* type = 0;\n\t};\n\n\tstruct Defn : Stmt\n\t{\n\t\tDefn(const Location& l) : Stmt(l) { this->readableName = \"definition\"; }\n\t\t~Defn() { }\n\n\t\tvirtual CGResult codegen(cgn::CodegenState* cs, fir::Type* inferred = 0) override;\n\n\t\tIdentifier id;\n\t\tfir::Type* type = 0;\n\t\tbool global = false;\n\t\tstd::string bareName;\n\t\tVisibilityLevel visibility = VisibilityLevel::Internal;\n\t\tScope enclosingScope;\n\n\t\tsize_t cachedCSId = 0;\n\t\tbool didCodegen = false;\n\t\tCGResult cachedResult = CGResult(0);\n\n\t\tvirtual std::string getKind() = 0;\n\t};\n}\n\n\n\n"
  },
  {
    "path": "source/include/stcommon.h",
    "content": "// stcommon.h\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n#include \"defs.h\"\n\nnamespace sst\n{\n\tstruct VarDefn;\n\tstruct StateTree;\n}\n\nnamespace ast\n{\n\tstruct Expr;\n}\n\nnamespace attr\n{\n\tusing FlagTy = uint32_t;\n\n\tconstexpr FlagTy NONE               = 0x0;\n\tconstexpr FlagTy FN_ENTRYPOINT      = 0x1;\n\tconstexpr FlagTy NO_MANGLE          = 0x2;\n\tconstexpr FlagTy RAW                = 0x4;\n\tconstexpr FlagTy PACKED             = 0x8;\n}\n\nstruct AttribSet\n{\n\tusing FlagTy = attr::FlagTy;\n\n\tstruct UserAttrib\n\t{\n\t\tUserAttrib(const std::string& name, const std::vector<std::string>& args) : name(name), args(args) { }\n\n\t\tstd::string name;\n\t\tstd::vector<std::string> args;\n\t};\n\n\n\n\tbool has(const std::string& uaName)\n\t{\n\t\treturn std::find_if(this->userAttribs.begin(), this->userAttribs.end(), [uaName](const UserAttrib& ua) -> bool {\n\t\t\treturn ua.name == uaName;\n\t\t}) != this->userAttribs.end();\n\t}\n\n\tUserAttrib get(const std::string& uaName)\n\t{\n\t\tauto it = std::find_if(this->userAttribs.begin(), this->userAttribs.end(), [uaName](const UserAttrib& ua) -> bool {\n\t\t\treturn ua.name == uaName;\n\t\t});\n\n\t\t// would use optionals or something but lazy\n\t\tif(it != this->userAttribs.end())   return *it;\n\t\telse                                return UserAttrib(\"\", {});\n\t}\n\n\tvoid set(FlagTy x) { this->flags |= x; }\n\tbool has(FlagTy x) const { return (this->flags & x); }\n\tbool hasAny(FlagTy x) const { return (this->flags & x); }\n\tbool hasAll(FlagTy x) const { return (this->flags & x); }\n\n\ttemplate <typename... Args> void set(FlagTy x, Args... xs) { this->flags |= x; set(xs...); }\n\ttemplate <typename... Args> bool hasAny(FlagTy x, Args... xs) const { return (this->flags & x) || hasAny(xs...); }\n\ttemplate <typename... Args> bool hasAll(FlagTy x, Args... xs) const { return (this->flags & x) && hasAll(xs...); }\n\n\tvoid add(const UserAttrib& ua)\n\t{\n\t\tthis->userAttribs.push_back(ua);\n\t}\n\n\tstatic AttribSet of(FlagTy flags, const std::vector<UserAttrib>& attribs = {})\n\t{\n\t\treturn AttribSet {\n\t\t\t.flags = flags,\n\t\t\t.userAttribs = attribs\n\t\t};\n\t}\n\n\tFlagTy flags = attr::NONE;\n\tstd::vector<UserAttrib> userAttribs;\n};\n\n\nstruct DecompMapping\n{\n\tLocation loc;\n\tstd::string name;\n\tbool ref = false;\n\tbool array = false;\n\n\tsst::VarDefn* createdDefn = 0;\n\n\tstd::vector<DecompMapping> inner;\n\n\t// for array decompositions, this will hold the rest.\n\tstd::string restName;\n\tbool restRef = false;\n\tsst::VarDefn* restDefn = 0;\n};\n\nstruct FnCallArgument\n{\n\tFnCallArgument() { }\n\tFnCallArgument(const Location& l, const std::string& n, sst::Expr* v, ast::Expr* o) : loc(l), name(n), value(v), orig(o) { }\n\n\tLocation loc;\n\tstd::string name;\n\tsst::Expr* value = 0;\n\n\tast::Expr* orig = 0;\n\tbool ignoreName = false;\n\n\tstatic FnCallArgument make(const Location& l, const std::string& n, fir::Type* t, bool ignoreName = false);\n\n\tbool operator == (const FnCallArgument& other) const\n\t{\n\t\treturn this->loc == other.loc && this->name == other.name && this->value == other.value && this->orig == other.orig;\n\t}\n};\n\nstruct FnParam\n{\n\tFnParam() { }\n\tFnParam(const Location& l, const std::string& n, fir::Type* t) : loc(l), name(n), type(t) { }\n\n\tLocation loc;\n\tstd::string name;\n\tfir::Type* type = 0;\n\tsst::Expr* defaultVal = 0;\n};\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/string_consts.h",
    "content": "// string_consts.h\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n\n// is this too many levels of nesting?\nnamespace strs\n{\n\tnamespace attrs\n\t{\n\t\tinline constexpr auto COMPILER_SUPPORT      = \"compiler_support\";\n\t}\n\n\tnamespace names\n\t{\n\t\tnamespace saa\n\t\t{\n\t\t\tinline constexpr auto FN_APPEND         = \"append\";\n\t\t\tinline constexpr auto FN_CLONE          = \"clone\";\n\n\t\t\tinline constexpr auto FIELD_LENGTH      = \"length\";\n\t\t\tinline constexpr auto FIELD_POINTER     = \"ptr\";\n\t\t\tinline constexpr auto FIELD_REFCOUNT    = \"refcount\";\n\t\t\tinline constexpr auto FIELD_CAPACITY    = \"capacity\";\n\t\t}\n\n\t\tnamespace range\n\t\t{\n\t\t\tinline constexpr auto FIELD_BEGIN       = \"begin\";\n\t\t\tinline constexpr auto FIELD_END         = \"end\";\n\t\t\tinline constexpr auto FIELD_STEP        = \"step\";\n\t\t}\n\n\t\t// obviously cos enum is a keyword\n\t\tnamespace enumeration\n\t\t{\n\t\t\tinline constexpr auto FIELD_VALUE       = \"value\";\n\t\t\tinline constexpr auto FIELD_INDEX       = \"index\";\n\t\t\tinline constexpr auto FIELD_NAME        = \"name\";\n\t\t}\n\n\t\tnamespace string\n\t\t{\n\t\t\tinline constexpr auto FIELD_COUNT       = \"count\";\n\t\t}\n\n\t\tnamespace array\n\t\t{\n\t\t\tinline constexpr auto FN_POP            = \"pop\";\n\t\t}\n\n\t\tnamespace any\n\t\t{\n\t\t\tinline constexpr auto FIELD_TYPEID      = \"id\";\n\t\t\tinline constexpr auto FIELD_REFCOUNT    = \"refcount\";\n\t\t}\n\n\t\tnamespace support\n\t\t{\n\t\t\tinline constexpr auto RAII_TRAIT_DROP       = \"raii_trait::drop\";\n\t\t\tinline constexpr auto RAII_TRAIT_COPY       = \"raii_trait::copy\";\n\t\t\tinline constexpr auto RAII_TRAIT_MOVE       = \"raii_trait::move\";\n\t\t}\n\n\t\tinline constexpr auto GLOBAL_INIT_FUNCTION      = \"global_init_function__\";\n\t}\n}\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/typecheck.h",
    "content": "// typecheck.h\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#pragma once\n#include \"sst.h\"\n\n#include \"precompile.h\"\n\n#include <set>\n#include <unordered_set>\n\nnamespace parser\n{\n\tstruct ParsedFile;\n}\n\nnamespace frontend\n{\n\tstruct CollectorState;\n\tstruct ImportThing;\n}\n\nnamespace pts\n{\n\tstruct Type;\n}\n\nnamespace ast\n{\n\tstruct Stmt;\n\tstruct TypeDefn;\n\tstruct FuncDefn;\n\tstruct Parameterisable;\n}\n\nnamespace fir\n{\n\tstruct ConstantNumberType;\n}\n\nnamespace sst\n{\n\tnamespace poly\n\t{\n\t\tstruct Solution_t;\n\t}\n\n\tstruct StateTree\n\t{\n\t\tStateTree(const std::string& nm, StateTree* p, bool anon = false) : name(nm), parent(p), isAnonymous(anon) { }\n\n\t\tstd::string name;\n\t\tstd::string moduleName;\n\n\t\tStateTree* parent = 0;\n\n\t\t// for those anonymous scopes (with numbers) that we create.\n\t\t// currently we only keep track of this for scope-path resolution, so we can skip them\n\t\t// when we do '^' -- if not we'll end up in the middle of something and the user doesn't expect\n\t\t// there to be scopes where there are no braces!\n\t\tbool isAnonymous = false;\n\n\t\t// this flag allows us to skip definitions that are generated by the compiler. every module\n\t\t// needs these definitions to be generated, but they should *not* be imported into other modules\n\t\t// like normal things.\n\t\tbool isCompilerGenerated = false;\n\n\t\tutil::hash_map<std::string, StateTree*> subtrees;\n\t\tutil::hash_map<std::string, std::vector<ast::Parameterisable*>> unresolvedGenericDefs;\n\n\t\tutil::hash_map<std::string, std::vector<Defn*>> definitions;\n\n\t\tstd::vector<Defn*> exports;\n\t\tstd::vector<StateTree*> imports;\n\t\tstd::vector<StateTree*> reexports;\n\n\t\t// when importing *not* `as _`, the module goes into a new StateTree with the same name, and that new tree\n\t\t// is the one that imports the target module. (this is because the 'imports' list does not introduce a \"new layer\")\n\t\t// so, we must point the newly created module to the target module somehow.\n\t\tStateTree* proxyOf = nullptr;\n\n\t\t// this is a mapping from every StateTree in `imports` to the location of the `import` or `using` statement.\n\t\t// it only used for error-reporting, so it is stored out-of-line so the usage of `this->imports` is not more\n\t\t// cumbersome than it needs to be.\n\t\tstd::map<const StateTree*, Location> importMetadata;\n\n\t\t// the same thing, but for reexports (ie. public imports).\n\t\tstd::map<const StateTree*, Location> reexportMetadata;\n\n\n\t\t// what's there to explain? a simple map of operators to their functions. we use\n\t\t// function overload resolution to determine which one to call, and ambiguities are\n\t\t// handled the usual way.\n\t\tutil::hash_map<std::string, std::vector<sst::FunctionDefn*>> infixOperatorOverloads;\n\t\tutil::hash_map<std::string, std::vector<sst::FunctionDefn*>> prefixOperatorOverloads;\n\t\tutil::hash_map<std::string, std::vector<sst::FunctionDefn*>> postfixOperatorOverloads;\n\n\t\tScope cachedScope;\n\t\tconst Scope& getScope();\n\n\t\tStateTree* findSubtree(const std::string& name);\n\t\tStateTree* findOrCreateSubtree(const std::string& name, bool anonymous = false);\n\n\t\tstd::vector<Defn*> getAllDefinitions();\n\n\t\tstd::vector<Defn*> getDefinitionsWithName(const std::string& name);\n\t\tstd::vector<ast::Parameterisable*> getUnresolvedGenericDefnsWithName(const std::string& name);\n\n\t\tvoid addDefinition(const std::string& name, Defn* def, const TypeParamMap_t& gmaps = { });\n\t};\n\n\tstruct DefinitionTree\n\t{\n\t\tDefinitionTree(StateTree* st) : base(st) { }\n\n\t\tStateTree* base = 0;\n\t\tNamespaceDefn* topLevel = 0;\n\t\tstd::unordered_set<std::string> thingsImported;\n\n\t\tutil::hash_map<fir::Type*, TypeDefn*> typeDefnMap;\n\t\tutil::hash_map<std::string, sst::Defn*> compilerSupportDefinitions;\n\t};\n\n\tstruct TypecheckState\n\t{\n\t\tTypecheckState(StateTree* st) : dtree(new DefinitionTree(st)), stree(dtree->base), typeDefnMap(dtree->typeDefnMap) { }\n\n\t\tstd::string moduleName;\n\n\t\tDefinitionTree* dtree = 0;\n\t\tStateTree* stree = 0;\n\n\t\tutil::hash_map<fir::Type*, TypeDefn*>& typeDefnMap;\n\n\n\t\tstd::vector<int> bodyStack;\n\t\tstd::vector<FunctionDefn*> currentFunctionStack;\n\t\tbool isInFunctionBody();\n\n\n\t\tFunctionDefn* getCurrentFunction();\n\t\tvoid enterFunctionBody(FunctionDefn* fn);\n\t\tvoid leaveFunctionBody();\n\n\n\t\tstd::vector<Expr*> subscriptArrayStack;\n\t\tExpr* getCurrentSubscriptArray();\n\t\tvoid enterSubscript(Expr* arr);\n\t\tvoid leaveSubscript();\n\t\tbool isInSubscript();\n\n\n\t\tstd::vector<fir::Type*> selfContextStack;\n\t\tfir::Type* getCurrentSelfContext();\n\t\tvoid pushSelfContext(fir::Type* str);\n\t\tvoid popSelfContext();\n\t\tbool hasSelfContext();\n\n\n\t\tstd::vector<TypeParamMap_t> genericContextStack;\n\t\tstd::vector<TypeParamMap_t> getGenericContextStack();\n\n\n\t\tvoid pushGenericContext();\n\t\tfir::Type* findGenericMapping(const std::string& name, bool allowFail);\n\t\tvoid addGenericMapping(const std::string& name, fir::Type* ty);\n\t\tvoid removeGenericMapping(const std::string& name);\n\t\tvoid popGenericContext();\n\n\n\t\tint breakableBodyNest = 0;\n\t\tvoid enterBreakableBody();\n\t\tvoid leaveBreakableBody();\n\t\tbool isInBreakableBody();\n\n\t\tint deferBlockNest = 0;\n\t\tvoid enterDeferBlock();\n\t\tvoid leaveDeferBlock();\n\t\tbool isInDeferBlock();\n\n\n\t\tstd::vector<Location> locationStack;\n\t\tvoid pushLoc(const Location& l);\n\t\tvoid pushLoc(ast::Stmt* stmt);\n\t\tLocation popLoc();\n\t\tLocation loc();\n\n\t\tvoid pushAnonymousTree();\n\t\tvoid pushTree(const std::string& name, bool createAnonymously = false);\n\t\tStateTree* popTree();\n\n\n\t\tScope scope();\n\n\t\tstd::vector<StateTree*> teleportationStack;\n\t\tvoid teleportInto(const Scope& scope);\n\t\tvoid teleportOut();\n\n\n\n\t\tstd::vector<Defn*> getDefinitionsWithName(const std::string& name, StateTree* tree = 0);\n\t\tErrorMsg* checkForShadowingOrConflictingDefinition(Defn* def,\n\t\t\tstd::function<bool (TypecheckState* fs, Defn* other)> checkConflicting, StateTree* tree = 0);\n\n\t\tfir::Type* getBinaryOpResultType(fir::Type* a, fir::Type* b, const std::string& op, sst::FunctionDefn** overloadFn = 0);\n\n\t\tfir::Type* convertParserTypeToFIR(pts::Type* pt, bool allowFailure = false);\n\n\t\tfir::Type* checkIsBuiltinConstructorCall(const std::string& name, const std::vector<FnCallArgument>& arguments);\n\n\t\tbool checkAllPathsReturn(FunctionDefn* fn);\n\n\t\tstd::pair<util::hash_map<std::string, size_t>, SimpleError> verifyStructConstructorArguments(const std::string& name,\n\t\t\tconst std::set<std::string>& fieldNames, const std::vector<FnCallArgument>& params);\n\n\t\tDecompMapping typecheckDecompositions(const DecompMapping& bind, fir::Type* rhs, bool immut, bool allowref);\n\t};\n\n\tfir::Type* inferCorrectTypeForLiteral(fir::ConstantNumberType* lit);\n\n\tbool isDuplicateOverload(const std::vector<FnParam>& a, const std::vector<FnParam>& b);\n\tint getOverloadDistance(const std::vector<fir::Type*>& a, const std::vector<fir::Type*>& b);\n\n\tvoid mergeExternalTree(const Location& importer, const char* kind, sst::StateTree* base, sst::StateTree* branch);\n\n\tDefinitionTree* typecheck(frontend::CollectorState* cs, const parser::ParsedFile& file,\n\t\tconst std::vector<std::pair<frontend::ImportThing, DefinitionTree*>>& imports, bool addPreludeDefinitions);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/zfu.h",
    "content": "// zfu.h\n// Copyright (c) 2020, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n// updated 10/06/2020\n// origins:\n// flax     -- post 16/06/2020\n// ikurabot -- pre  16/06/2020\n\n#pragma once\n#include <map>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <type_traits>\n#include <unordered_map>\n\ntemplate <typename T>\nstd::vector<T> operator + (const std::vector<T>& vec, const T& elm)\n{\n\tauto copy = vec;\n\n\tcopy.push_back(elm);\n\treturn copy;\n}\n\ntemplate <typename T>\nstd::vector<T> operator + (const T& elm, const std::vector<T>& vec)\n{\n\tauto copy = vec;\n\n\tcopy.insert(copy.begin(), elm);\n\treturn copy;\n}\n\ntemplate <typename T>\nstd::vector<T> operator + (const std::vector<T>& a, const std::vector<T>& b)\n{\n\tauto ret = a;\n\tret.insert(ret.end(), b.begin(), b.end());\n\n\treturn ret;\n}\n\n\ntemplate <typename T>\nstd::vector<T>& operator += (std::vector<T>& vec, const T& elm)\n{\n\tvec.push_back(elm);\n\treturn vec;\n}\n\ntemplate <typename T>\nstd::vector<T>& operator += (std::vector<T>& vec, const std::vector<T>& xs)\n{\n\tvec.insert(vec.end(), xs.begin(), xs.end());\n\treturn vec;\n}\n\n\nnamespace zfu\n{\n\ttemplate <typename T>\n\tbool match(const T&)\n\t{\n\t\treturn true;\n\t}\n\n\ttemplate <typename T, typename U>\n\tbool match(const T& first, const U& second)\n\t{\n\t\treturn (first == second);\n\t}\n\n\ttemplate <typename T, typename U, typename... Args>\n\tbool match(const T& first, const U& second, const Args&... comps)\n\t{\n\t\treturn (first == second) || match(first, comps...);\n\t}\n\n\ttemplate <typename T, typename... Args>\n\tstd::vector<T> merge(const std::vector<T>& x, const Args&... xs)\n\t{\n\t\treturn (x + ... + xs);\n\t}\n\n\n\n\ttemplate <typename T>\n\tstd::vector<T> vectorOf(const T& x)\n\t{\n\t\treturn std::vector<T>({ x });\n\t}\n\n\ttemplate <typename T, typename... Args>\n\tstd::vector<T> vectorOf(const T& x, const Args&... xs)\n\t{\n\t\treturn x + vectorOf<T>(xs...);\n\t}\n\n\ttemplate <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>\n\tstd::vector<T> rangeOpen(const T& begin, const T& end, const T& step = 1)\n\t{\n\t\tstd::vector<T> ret;\n\t\tret.reserve((end - begin + 1) / step);\n\n\t\tT x = begin;\n\t\twhile(x != end)\n\t\t{\n\t\t\tret.push_back(x);\n\t\t\tx += step;\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\ttemplate <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>\n\tstd::vector<T> rangeClosed(const T& begin, const T& end, const T& step = 1)\n\t{\n\t\treturn rangeOpen<T>(begin, end + 1, step);\n\t}\n\n\ttemplate <typename T, typename Predicate, typename UnaryOp>\n\tstd::vector<T> iterateWhile(const T& seed, Predicate pred, UnaryOp fn)\n\t{\n\t\tT x = seed;\n\t\tstd::vector<T> ret;\n\n\t\twhile(pred(x))\n\t\t{\n\t\t\tret.push_back(x);\n\t\t\tx = fn(x);\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\n\n\ttemplate <typename Container, typename U, typename FoldOp>\n\tU foldl(const U& i, const Container& xs, FoldOp fn)\n\t{\n\t\tauto ret = i;\n\t\tfor(const auto& x : xs)\n\t\t\tret = fn(ret, x);\n\n\t\treturn ret;\n\t}\n\n\ttemplate <typename Container, typename T = typename Container::value_type>\n\tT sum(const Container& xs)\n\t{\n\t\treturn foldl(T(), xs, [](const T& a, const T& b) -> T { return a + b; });\n\t}\n\n\n\n\ttemplate <typename Container, typename UnaryOp, typename T = typename Container::value_type>\n\tauto map(const Container& input, UnaryOp fn) -> std::vector<decltype(fn(std::declval<T>()))>\n\t{\n\t\tstd::vector<decltype(fn(std::declval<T>()))> ret;\n\t\tret.reserve(input.size());\n\n\t\tfor(const auto& i : input)\n\t\t\tret.push_back(fn(i));\n\n\t\treturn ret;\n\t}\n\n\ttemplate <typename Container, typename UnaryOp, typename T = typename Container::value_type>\n\tauto map(Container&& input, UnaryOp fn) -> std::vector<decltype(fn(std::move(std::declval<T>())))>\n\t{\n\t\tstd::vector<decltype(fn(std::move(std::declval<T>())))> ret;\n\t\tret.reserve(input.size());\n\n\t\tfor(auto& i : input)\n\t\t\tret.push_back(fn(std::move(i)));\n\n\t\treturn ret;\n\t}\n\n\ttemplate <typename Container, typename UnaryOp, typename T = typename Container::value_type>\n\tauto flatmap(const Container& input, UnaryOp fn) -> std::vector<decltype(fn(std::declval<T>()))>\n\t{\n\t\tstd::vector<decltype(fn(std::declval<T>()))> ret;\n\t\tret.reserve(input.size());\n\n\t\tfor(const auto& i : input)\n\t\t{\n\t\t\tauto x = fn(i);\n\t\t\tret.insert(ret.end(), x.begin(), x.end());\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\n\n\n\n\n\ttemplate <typename Container, typename UnaryOp>\n\tvoid foreach(const Container& input, UnaryOp fn)\n\t{\n\t\tfor(const auto& i : input)\n\t\t\tfn(i);\n\t}\n\n\n\ttemplate <typename Container, typename UnaryOp>\n\tvoid foreachWhile(const Container& input, UnaryOp fn)\n\t{\n\t\tfor(const auto& i : input)\n\t\t\tif(!fn(i)) break;\n\t}\n\n\ttemplate <typename Container, typename UnaryOp>\n\tvoid foreachIdx(const Container& input, UnaryOp fn)\n\t{\n\t\tfor(size_t i = 0; i < input.size(); i++)\n\t\t\tfn(input[i], i);\n\t}\n\n\n\ttemplate <typename Container, typename UnaryOp, typename T = typename Container::value_type>\n\tauto mapIdx(const Container& input, UnaryOp fn) -> std::vector<decltype(fn(std::declval<T>(), static_cast<size_t>(0)))>\n\t{\n\t\tstd::vector<decltype(fn(std::declval<T>(), static_cast<size_t>(0)))> ret;\n\t\tret.reserve(input.size());\n\n\t\tfor(size_t i = 0; i < input.size(); i++)\n\t\t\tret.push_back(fn(input[i], i));\n\n\t\treturn ret;\n\t}\n\n\n\n\ttemplate <typename Container, typename UnaryOp, typename Predicate, typename T = typename Container::value_type>\n\tauto filterMap(const Container& input, Predicate cond, UnaryOp fn) -> std::vector<decltype(fn(std::declval<T>()))>\n\t{\n\t\tstd::vector<decltype(fn(std::declval<T>()))> ret;\n\t\tfor(const auto& i : input)\n\t\t\tif(cond(i)) ret.push_back(fn(i));\n\n\t\treturn ret;\n\t}\n\n\ttemplate <typename Container, typename UnaryOp, typename Predicate, typename T = typename Container::value_type>\n\tauto mapFilter(const Container& input, UnaryOp fn, Predicate cond) -> std::vector<decltype(fn(std::declval<T>()))>\n\t{\n\t\tstd::vector<decltype(fn(std::declval<T>()))> ret;\n\t\tfor(const auto& i : input)\n\t\t{\n\t\t\tauto k = fn(i);\n\t\t\tif(cond(k)) ret.push_back(k);\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\ttemplate <typename Container, typename Predicate>\n\tContainer filter(const Container& input, Predicate cond)\n\t{\n\t\tContainer ret;\n\t\tfor(const auto& i : input)\n\t\t\tif(cond(i))\n\t\t\t\tret.push_back(i);\n\n\t\treturn ret;\n\t}\n\n\ttemplate <typename Container, typename Predicate>\n\tbool matchAny(const Container& input, Predicate cond)\n\t{\n\t\tfor(const auto& x : input)\n\t\t\tif(cond(x)) return true;\n\n\t\treturn false;\n\t}\n\n\ttemplate <typename Container, typename Predicate>\n\tbool matchNone(const Container& input, Predicate cond)\n\t{\n\t\treturn !matchAny(input, cond);\n\t}\n\n\ttemplate <typename Container, typename Predicate>\n\tbool matchAll(const Container& input, Predicate cond)\n\t{\n\t\tfor(const auto& x : input)\n\t\t\tif(!cond(x)) return false;\n\n\t\treturn true;\n\t}\n\n\ttemplate <typename Container, typename Predicate>\n\tsize_t indexOf(const Container& input, Predicate cond)\n\t{\n\t\tfor(size_t i = 0; i < input.size(); i++)\n\t\t\tif(cond(input[i])) return i;\n\n\t\treturn -1;\n\t}\n\n\ttemplate <typename Container, typename U>\n\tbool contains(const Container& input, const U& x)\n\t{\n\t\treturn std::find(input.begin(), input.end(), x) != input.end();\n\t}\n\n\ttemplate <typename T>\n\tstd::vector<T> take(const std::vector<T>& v, size_t num)\n\t{\n\t\treturn std::vector<T>(v.begin(), v.begin() + std::min(num, v.size()));\n\t}\n\n\ttemplate <typename T, typename Predicate>\n\tstd::vector<T> takeWhile(const std::vector<T>& input, Predicate cond)\n\t{\n\t\tstd::vector<T> ret;\n\t\tfor(const auto& i : input)\n\t\t{\n\t\t\tif(cond(i)) ret.push_back(i);\n\t\t\telse        break;\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\ttemplate <typename T>\n\tstd::vector<T> drop(const std::vector<T>& v, size_t num)\n\t{\n\t\treturn std::vector<T>(v.begin() + std::min(num, v.size()), v.end());\n\t}\n\n\ttemplate <typename T, typename Predicate>\n\tstd::vector<T> dropWhile(const std::vector<T>& input, Predicate cond)\n\t{\n\t\tbool flag = false;\n\t\tstd::vector<T> ret;\n\n\t\tfor(const auto& i : input)\n\t\t{\n\t\t\tif(!flag && cond(i))    continue;\n\t\t\telse                    flag = true;\n\n\t\t\tret.push_back(i);\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\n\n\ttemplate <typename T, typename GroupFn, typename R = decltype(std::declval<GroupFn(T)>())>\n\tstd::map<R, std::vector<T>> groupBy(const std::vector<T>& xs, GroupFn gfn)\n\t{\n\t\tstd::map<R, std::vector<T>> groups;\n\t\tfor(const T& x : xs)\n\t\t\tgroups[gfn(x)].push_back(x);\n\n\t\treturn groups;\n\t}\n\n\t// special case for one to many. so cartesian(1, { 1, 2, 3, 4 }) gives (1, 1), (1, 2), (1, 3), ...\n\ttemplate <typename T, typename U>\n\tstd::vector<std::pair<T, U>> cartesian(const T& a, const std::vector<U>& xs)\n\t{\n\t\treturn map(xs, [&a](const U& x) -> auto {\n\t\t\treturn std::make_pair(a, x);\n\t\t});\n\t}\n\n\t// special case for two vectors, because tuples are a major pain in the ass. pairs >>> tuples.\n\ttemplate <typename T, typename U>\n\tstd::vector<std::pair<T, U>> cartesian(const std::vector<T>& a, const std::vector<U>& b)\n\t{\n\t\tstd::vector<std::pair<T, U>> ret;\n\n\t\tfor(size_t i = 0; i < a.size(); i++)\n\t\t\tfor(size_t k = 0; k < b.size(); k++)\n\t\t\t\tret.push_back({ a[i], b[k] });\n\n\t\treturn ret;\n\t}\n\n\ttemplate <typename F>\n\tinline void cross_imp(F f) { f(); }\n\n\ttemplate <typename F, typename H, typename... Ts>\n\tinline void cross_imp(F f, const std::vector<H>& h, const std::vector<Ts>&... t)\n\t{\n\t\tfor(const H& hs : h)\n\t\t\tcross_imp([&](const Ts&... ts) { f(hs, ts...); }, t...);\n\t}\n\n\ttemplate <typename... Ts>\n\tstd::vector<std::tuple<Ts...>> cartesian(const std::vector<Ts>&... in)\n\t{\n\t\tstd::vector<std::tuple<Ts...>> res;\n\n\t\tcross_imp([&](Ts const&... ts) {\n\t\t\tres.emplace_back(ts...);\n\t\t}, in...);\n\n\t\treturn res;\n\t}\n\n\n\n\n\ttemplate <typename T, bool permute_inside>\n\tstd::vector<std::vector<T>> _permutations(const std::vector<T>& xs, size_t r)\n\t{\n\t\tif(r == 0) return { };\n\n\t\tauto fact = [](size_t x) -> size_t {\n\t\t\tsize_t ret = 1;\n\t\t\twhile(x > 1)\n\t\t\t\tret *= x, x -= 1;\n\n\t\t\treturn ret;\n\t\t};\n\n\t\tstd::vector<std::vector<T>> ret;\n\t\tif(permute_inside)  ret.reserve(fact(xs.size()) / fact(xs.size() - r));\n\t\telse                ret.reserve(fact(xs.size()) / (fact(r) * fact(xs.size() - r)));\n\n\n\t\tstd::function<void (size_t, size_t, size_t, std::vector<T>)> recurse;\n\n\t\trecurse = [&recurse, &xs, &ret](size_t R, size_t r, size_t i, std::vector<T> cur) {\n\t\t\tif(r == R)\n\t\t\t{\n\t\t\t\tif(permute_inside)\n\t\t\t\t{\n\t\t\t\t\tdo {\n\t\t\t\t\t\tret.push_back(cur);\n\t\t\t\t\t} while(std::next_permutation(cur.begin(), cur.end()));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tstd::sort(cur.begin(), cur.end());\n\t\t\t\t\tret.push_back(cur);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfor(size_t k = i; k < xs.size(); k++)\n\t\t\t\t{\n\t\t\t\t\tcur.push_back(xs[k]);\n\t\t\t\t\trecurse(R, r + 1, k + 1, cur);\n\t\t\t\t\tcur.pop_back();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\trecurse(r, 0, 0, { });\n\t\treturn ret;\n\t}\n\n\ttemplate <typename T>\n\tstd::vector<std::vector<T>> powerset(const std::vector<T>& xs)\n\t{\n\t\tstd::vector<std::vector<T>> ret;\n\n\t\t// well... if there's more than 64 elements then gg\n\t\tret.reserve(2 << xs.size());\n\n\t\tfor(size_t i = 0; i < xs.size(); i++)\n\t\t{\n\t\t\tauto x = _permutations<T, false>(xs, i);\n\t\t\tret.insert(ret.end(), x.begin(), x.end());\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\ttemplate <typename T>\n\tstd::vector<std::vector<T>> combinations(const std::vector<T>& xs, size_t r)\n\t{\n\t\treturn _permutations<T, false>(xs, r);\n\t}\n\n\ttemplate <typename T>\n\tstd::vector<std::vector<T>> permutations(const std::vector<T>& xs, size_t r)\n\t{\n\t\treturn _permutations<T, true>(xs, r);\n\t}\n\n\ttemplate <typename T>\n\tstd::vector<std::vector<T>> permutations(const std::vector<T>& xs)\n\t{\n\t\treturn _permutations<T, true>(xs, xs.size());\n\t}\n\n\n\n\n\n\ttemplate <typename T, typename U>\n\tstd::vector<std::pair<T, U>> zip(const std::vector<T>& a, const std::vector<U>& b)\n\t{\n\t\tstd::vector<std::pair<T, U>> ret;\n\t\tfor(size_t i = 0; i < std::min(a.size(), b.size()); i++)\n\t\t\tret.push_back({ a[i], b[i] });\n\n\t\treturn ret;\n\t}\n\n\tstatic inline std::string join(const std::vector<std::string>& list, const std::string& sep)\n\t{\n\t\tif(list.empty())            return \"\";\n\t\telse if(list.size() == 1)   return list[0];\n\n\t\tstd::string ret;\n\t\tfor(size_t i = 0; i < list.size() - 1; i++)\n\t\t\tret += list[i] + sep;\n\n\t\treturn ret + list.back();\n\t}\n\n\n\n\n\n\tstatic inline std::string serialiseScope(const std::vector<std::string>& scope)\n\t{\n\t\tif(scope.empty()) return \"\";\n\n\t\tstd::string ret = scope[0];\n\t\tfor(size_t i = 1; i < scope.size(); i++)\n\t\t\tret += \"::\" + scope[i];\n\n\t\treturn ret;\n\t}\n\n\tstatic inline std::string plural(const std::string& thing, size_t count)\n\t{\n\t\treturn thing + (count == 1 ? \"\" : \"s\");\n\t}\n\n\ttemplate <typename Container, typename UnaryOp>\n\tstd::string listToString(const Container& list, UnaryOp fn, bool braces = true, const std::string& sep = \", \")\n\t{\n\t\tstd::string ret;\n\t\tfor(size_t i = 0; i < list.size(); i++)\n\t\t{\n\t\t\tret += fn(list[i]);\n\t\t\tif(i != list.size() - 1)\n\t\t\t\tret += sep;\n\t\t}\n\n\t\treturn braces ? (\"[ \" + ret + \" ]\") : ret;\n\t}\n\n\ttemplate <typename K, typename V>\n\tstd::vector<std::pair<K, V>> pairs(const std::unordered_map<K, V>& map)\n\t{\n\t\tauto ret = std::vector<std::pair<K, V>>(map.begin(), map.end());\n\t\treturn ret;\n\t}\n\n\ttemplate <typename K, typename V>\n\tstd::vector<std::pair<K, V>> pairs(const std::map<K, V>& map)\n\t{\n\t\tauto ret = std::vector<std::pair<K, V>>(map.begin(), map.end());\n\t\treturn ret;\n\t}\n\n\n\tstruct identity\n\t{\n\t\ttemplate <typename T>\n\t\tT&& operator() (T&& x) { return std::forward<T>(x); }\n\t};\n\n\tstruct tostring\n\t{\n\t\ttemplate <typename T>\n\t\tstd::string operator() (const T& x) { return std::to_string(x); }\n\t};\n\n\tstruct pair_first\n\t{\n\t\ttemplate <typename T, typename U>\n\t\tT operator() (const std::pair<T, U>& x) { return x.first; }\n\t};\n\n\tstruct pair_second\n\t{\n\t\ttemplate <typename T, typename U>\n\t\tU operator() (const std::pair<T, U>& x) { return x.second; }\n\t};\n\n\ttemplate <typename T>\n\tstruct equals_to\n\t{\n\t\tequals_to(const T& x) : value(x) { }\n\t\tbool operator() (const T& x) { return x == this->value; }\n\n\tprivate:\n\t\tconst T& value;\n\t};\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/zpr.h",
    "content": "// zpr.h\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n// updated 12/07/2020\n// origins:\n// flax         -- 12/07/2020\n// ikurabot     -- 10/06/2020\n\n#pragma once\n\n#include <math.h>\n#include <stdint.h>\n#include <stddef.h>\n\n#include <string>\n#include <string_view>\n#include <type_traits>\n\n#ifndef ENABLE_FIELD_SIZES\n\t#define ENABLE_FIELD_SIZES          1\n#endif\n\n#ifndef HEX_0X_RESPECTS_UPPERCASE\n\t#define HEX_0X_RESPECTS_UPPERCASE   1\n#endif\n\nnamespace zpr\n{\n\tstruct format_args\n\t{\n\t\tbool zero_pad = false;\n\t\tbool alternate = false;\n\t\tbool prepend_plus_if_positive = false;\n\t\tbool prepend_blank_if_positive = false;\n\n\t\tchar specifier      = 0;\n\n\t\tint64_t width       = 0;\n\t\tint64_t length      = 0;\n\t\tint64_t precision   = -1;\n\n\t\tconstexpr static int LENGTH_DEFAULT     = 0;\n\t\tconstexpr static int LENGTH_SHORT_SHORT = 1;\n\t\tconstexpr static int LENGTH_SHORT       = 2;\n\t\tconstexpr static int LENGTH_LONG        = 3;\n\t\tconstexpr static int LENGTH_LONG_LONG   = 4;\n\t\tconstexpr static int LENGTH_LONG_DOUBLE = 5;\n\t\tconstexpr static int LENGTH_INTMAX_T    = 6;\n\t\tconstexpr static int LENGTH_SIZE_T      = 7;\n\t\tconstexpr static int LENGTH_PTRDIFF_T   = 8;\n\t};\n\n\ttemplate <typename T, typename = void>\n\tstruct print_formatter\n\t{\n\t\ttemplate <typename K>\n\t\tstruct has_formatter { static constexpr bool value = false; };\n\n\t\t// when printing, we use print_formatter<T>().print(...). if there is no specialisation\n\t\t// for print_formatter<T>, then we will instantiate this base class -- which causes the nice\n\t\t// static_assert message. note that we must use some predicate that depends on T, so that the\n\t\t// compiler can only know the value when it tries to instantiate. using static_assert(false)\n\t\t// will always fail to compile.\n\n\t\t// we make a inner type has_formatter which is more descriptive, and since we only make this\n\t\t// error when we try to instantiate the base, any specialisations don't even need to care!\n\t\tstatic_assert(true || has_formatter<T>::value, \"no formatter defined for type!\");\n\t};\n\n\n\n\n\tnamespace _internal\n\t{\n\t\tinline format_args parseFormatArgs(const char* fmt, const char** end, bool* need_width, bool* need_prec)\n\t\t{\n\t\t\tauto ret = format_args();\n\t\t\tif(fmt[0] != '%')\n\t\t\t\treturn ret;\n\n\t\t\tfmt++;\n\n\t\t\tbool negative_width = false;\n\t\t\twhile(true)\n\t\t\t{\n\t\t\t\tswitch(*fmt++)\n\t\t\t\t{\n\t\t\t\t\tcase '0':   ret.zero_pad = true; continue;\n\t\t\t\t\tcase '#':   ret.alternate = true; continue;\n\t\t\t\t\tcase '-':   negative_width = true; continue;\n\t\t\t\t\tcase '+':   ret.prepend_plus_if_positive = true; continue;\n\t\t\t\t\tcase ' ':   ret.prepend_blank_if_positive = true; continue;\n\t\t\t\t\tdefault:    fmt--; break;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif(*fmt == '*' && (fmt++, true))\n\t\t\t{\n\t\t\t\t// note: if you use *, then the negative width is ignored!\n\t\t\t\t*need_width = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\twhile((*fmt >= '0') && (*fmt <= '9'))\n\t\t\t\t\tret.width = 10 * ret.width + (*fmt++ - '0');\n\n\t\t\t\tif(negative_width)\n\t\t\t\t\tret.width *= -1;\n\t\t\t}\n\n\t\t\tif(*fmt == '.' && (fmt++, true))\n\t\t\t{\n\t\t\t\tif(*fmt == '*' && (fmt++, true))\n\t\t\t\t{\n\t\t\t\t\t// int int_precision = va_arg(parameters, int);\n\t\t\t\t\t// ret.precision = 0 <= int_precision ? (size_t) int_precision : 0;\n\t\t\t\t\t*need_prec = true;\n\t\t\t\t}\n\t\t\t\telse if(*fmt == '-' && (fmt++, true))\n\t\t\t\t{\n\t\t\t\t\twhile(('0' <= *fmt) && (*fmt <= '9'))\n\t\t\t\t\t\tfmt++;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tret.precision = 0;\n\t\t\t\t\twhile((*fmt >= '0') && (*fmt <= '9'))\n\t\t\t\t\t\tret.precision = 10 * ret.precision + (*fmt++ - '0');\n\t\t\t\t}\n\t\t\t}\n\n\t\t#if ENABLE_FIELD_SIZES\n\n\t\t\tif(fmt[0] == 'h')\n\t\t\t{\n\t\t\t\tif(fmt[1] == 'h')   fmt += 2, ret.length = format_args::LENGTH_SHORT_SHORT;\n\t\t\t\telse                fmt += 1, ret.length = format_args::LENGTH_SHORT;\n\t\t\t}\n\t\t\telse if(fmt[0] == 'l')\n\t\t\t{\n\t\t\t\tif(fmt[1] == 'l')   fmt += 2, ret.length = format_args::LENGTH_LONG_LONG;\n\t\t\t\telse                fmt += 1, ret.length = format_args::LENGTH_LONG;\n\t\t\t}\n\t\t\telse if(fmt[0] == 'L')  fmt += 1, ret.length = format_args::LENGTH_LONG_DOUBLE;\n\t\t\telse if(fmt[0] == 't')  fmt += 1, ret.length = format_args::LENGTH_PTRDIFF_T;\n\t\t\telse if(fmt[0] == 'j')  fmt += 1, ret.length = format_args::LENGTH_INTMAX_T;\n\t\t\telse if(fmt[0] == 'z')  fmt += 1, ret.length = format_args::LENGTH_SIZE_T;\n\n\t\t#endif\n\n\t\t\tret.specifier = fmt[0];\n\t\t\tfmt++;\n\n\t\t\t*end = fmt;\n\t\t\treturn ret;\n\t\t}\n\n\n\t\tinline std::string skip(const char* fmt, const char** end)\n\t\t{\n\t\t\tstd::string ret;\n\n\t\t\ttop:\n\t\t\twhile(*fmt && *fmt != '%')\n\t\t\t\tret += *fmt++;\n\n\t\t\tif(*fmt && fmt[1] == '%')\n\t\t\t{\n\t\t\t\tret += \"%\";\n\t\t\t\tfmt += 2;\n\t\t\t\tgoto top;\n\t\t\t}\n\n\t\t\t*end = fmt;\n\t\t\treturn ret;\n\t\t}\n\n\t\tinline std::string sprint(const char* &fmt)\n\t\t{\n\t\t\tif(!fmt || !*fmt)\n\t\t\t\treturn \"\";\n\n\t\t\tauto tmp = skip(fmt, &fmt);\n\t\t\treturn tmp + sprint(fmt);\n\t\t}\n\n\t\t// we need to forward declare this.\n\t\ttemplate <typename... Args>\n\t\tstd::string sprint(const char* fmt, Args&&... xs);\n\n\n\n\t\t// we need bogus ones that don't take the arguments. if we get error handling, these will throw errors.\n\t\ttemplate <typename... Args>\n\t\tstd::string _consume_both_sprint(const format_args&, const char* fmt, Args&&... xs)\n\t\t{\n\t\t\treturn std::string(\"<missing width and prec>\")\n\t\t\t\t.append(sprint(fmt, xs...));\n\t\t}\n\n\t\ttemplate <typename... Args>\n\t\tstd::string _consume_prec_sprint(const format_args&, const char* fmt, Args&&... xs)\n\t\t{\n\t\t\treturn std::string(\"<missing prec>\")\n\t\t\t\t.append(sprint(fmt, xs...));\n\t\t}\n\n\t\ttemplate <typename... Args>\n\t\tstd::string _consume_width_sprint(const format_args&, const char* fmt, Args&&... xs)\n\t\t{\n\t\t\treturn std::string(\"<missing width>\")\n\t\t\t\t.append(sprint(fmt, xs...));\n\t\t}\n\n\t\t// we need separate versions of these functions that only enable if the argument is\n\t\t// a pointer, THEN check if the specifier is 'p', THEN do the void* thing.\n\n\t\ttemplate <typename T>\n\t\tconstexpr bool _stupid_type_tester(decltype(!std::is_pointer_v<std::decay<T>>\n\t\t\t|| &print_formatter<std::decay_t<T>>::print)*) { return true; }\n\n\t\ttemplate <typename>\n\t\tconstexpr bool _stupid_type_tester(...) { return false; }\n\n\n\t\ttemplate <typename T, typename... Args, typename = std::enable_if_t<_stupid_type_tester<T>(0)>>\n\t\tstd::string _consume_neither_sprint(const format_args& args, const char* fmt, T&& x, Args&&... xs)\n\t\t{\n\t\t\treturn print_formatter<std::decay_t<T>>().print(x, args).append(sprint(fmt, xs...));\n\t\t}\n\n\t\ttemplate <typename T, typename... Args, typename = std::enable_if_t<!_stupid_type_tester<T>(0)>, typename F = void*>\n\t\tstd::string _consume_neither_sprint(const format_args& args, const char* fmt, T&& x, Args&&... xs)\n\t\t{\n\t\t\treturn print_formatter<F>().print(x, args).append(sprint(fmt, xs...));\n\t\t}\n\n\n\n\t\ttemplate <typename W, typename T, typename... Args,\n\t\t\ttypename = std::enable_if_t<std::is_integral_v<std::remove_reference_t<W>> && _stupid_type_tester<T>(0)>\n\t\t>\n\t\tstd::string _consume_width_sprint(format_args args, const char* fmt, W&& width, T&& x, Args&&... xs)\n\t\t{\n\t\t\targs.width = width;\n\t\t\treturn print_formatter<std::decay_t<T>>().print(x, args).append(sprint(fmt, xs...));\n\t\t}\n\n\t\ttemplate <typename W, typename T, typename... Args,\n\t\t\ttypename = std::enable_if_t<std::is_integral_v<std::remove_reference_t<W>> && !_stupid_type_tester<T>(0)>,\n\t\t\ttypename F = void*\n\t\t>\n\t\tstd::string _consume_width_sprint(format_args args, const char* fmt, W&& width, T&& x, Args&&... xs)\n\t\t{\n\t\t\targs.width = width;\n\t\t\treturn print_formatter<F>().print(x, args).append(sprint(fmt, xs...));\n\t\t}\n\n\n\n\t\ttemplate <typename P, typename T, typename... Args,\n\t\t\ttypename = std::enable_if_t<std::is_integral_v<std::remove_reference_t<P>> && _stupid_type_tester<T>(0)>\n\t\t>\n\t\tstd::string _consume_prec_sprint(format_args args, const char* fmt, P&& prec, T&& x, Args&&... xs)\n\t\t{\n\t\t\targs.precision = prec;\n\t\t\treturn print_formatter<std::decay_t<T>>().print(x, args).append(sprint(fmt, xs...));\n\t\t}\n\n\t\ttemplate <typename P, typename T, typename... Args,\n\t\t\ttypename = std::enable_if_t<std::is_integral_v<std::remove_reference_t<P>> && !_stupid_type_tester<T>(0)>,\n\t\t\ttypename F = void*\n\t\t>\n\t\tstd::string _consume_prec_sprint(format_args args, const char* fmt, P&& prec, T&& x, Args&&... xs)\n\t\t{\n\t\t\targs.precision = prec;\n\t\t\treturn print_formatter<F>().print(x, args).append(sprint(fmt, xs...));\n\t\t}\n\n\n\n\n\n\t\ttemplate <typename W, typename P, typename T, typename... Args,\n\t\t\ttypename = std::enable_if_t<std::is_integral_v<std::remove_reference_t<W>>\n\t\t\t\t&& std::is_integral_v<std::remove_reference_t<P>> && _stupid_type_tester<T>(0)>\n\t\t>\n\t\tstd::string _consume_both_sprint(format_args args, const char* fmt, W&& width, P&& prec, T&& x, Args&&... xs)\n\t\t{\n\t\t\targs.width = width;\n\t\t\targs.precision = prec;\n\t\t\treturn print_formatter<std::decay_t<T>>().print(x, args).append(sprint(fmt, xs...));\n\t\t}\n\n\t\ttemplate <typename W, typename P, typename T, typename... Args,\n\t\t\ttypename = std::enable_if_t<std::is_integral_v<std::remove_reference_t<W>>\n\t\t\t\t&& std::is_integral_v<std::remove_reference_t<P>> && !_stupid_type_tester<T>(0)>,\n\t\t\ttypename F = void*\n\t\t>\n\t\tstd::string _consume_both_sprint(format_args args, const char* fmt, W&& width, P&& prec, T&& x, Args&&... xs)\n\t\t{\n\t\t\targs.width = width;\n\t\t\targs.precision = prec;\n\t\t\treturn print_formatter<F>().print(x, args).append(sprint(fmt, xs...));\n\t\t}\n\n\n\n\t\ttemplate <typename... Args>\n\t\tstd::string sprint(const char* fmt, Args&&... xs)\n\t\t{\n\t\t\tbool need_prec = false;\n\t\t\tbool need_width = false;\n\n\t\t\tstd::string ret = skip(fmt, &fmt);\n\n\t\t\tauto args = parseFormatArgs(fmt, &fmt, &need_width, &need_prec);\n\n\t\t\t// because the if happens at runtime, all these functions need to be instantiable. that's\n\t\t\t// why we make bogus ones that just return error strings when there aren't enough arguments.\n\t\t\tif(need_width && need_prec) return ret.append(_consume_both_sprint(args, fmt, xs...));\n\t\t\telse if(need_prec)          return ret.append(_consume_prec_sprint(args, fmt, xs...));\n\t\t\telse if(need_width)         return ret.append(_consume_width_sprint(args, fmt, xs...));\n\t\t\telse                        return ret.append(_consume_neither_sprint(args, fmt, xs...));\n\t\t}\n\t}\n\n\n\tinline std::string sprint(const std::string& fmt)\n\t{\n\t\treturn fmt;\n\t}\n\n\tinline int print(const std::string& fmt)\n\t{\n\t\treturn printf(\"%s\", fmt.c_str());\n\t}\n\n\tinline int println(const std::string& fmt)\n\t{\n\t\treturn printf(\"%s\\n\", fmt.c_str());\n\t}\n\n\n\n\ttemplate <typename... Args>\n\tstd::string sprint(const std::string& fmt, Args&&... xs)\n\t{\n\t\treturn _internal::sprint(fmt.c_str(), xs...);\n\t}\n\n\ttemplate <typename... Args>\n\tint print(const std::string& fmt, Args&&... xs)\n\t{\n\t\tauto x = _internal::sprint(fmt.c_str(), xs...);\n\t\treturn printf(\"%s\", x.c_str());\n\t}\n\n\ttemplate <typename... Args>\n\tint println(const std::string& fmt, Args&&... xs)\n\t{\n\t\tauto x = _internal::sprint(fmt.c_str(), xs...);\n\t\treturn printf(\"%s\\n\", x.c_str());\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\t// formatters lie here\n\n\ttemplate <typename T>\n\tstruct print_formatter<T, typename std::enable_if<\n\t\t(\n\t\t\tstd::is_integral_v<std::remove_cv_t<std::decay_t<T>>> &&\n\t\t\t!std::is_same_v<char, std::remove_cv_t<std::decay_t<T>>> &&\n\t\t\t!std::is_same_v<bool, std::remove_cv_t<std::decay_t<T>>> &&\n\t\t\tsizeof(T) <= sizeof(uint64_t)\n\t\t) ||\n\t\t(std::is_enum_v<std::remove_cv_t<std::decay_t<T>>>)\n\t>::type>\n\t{\n\t\tstd::string print(T x, format_args args)\n\t\t{\n\t\t\tint base = 10;\n\t\t\tif(args.specifier == 'x' || args.specifier == 'X')      base = 16;\n\t\t\t// else if(args.specifier == 'o')                          base = 8;\n\t\t\t// else if(args.specifier == 'b')                          base = 2;\n\n\t\t#if 0\n\t\t\t// handle negative values ourselves btw, due to padding\n\t\t\tbool is_neg = false;\n\n\t\t\tif constexpr (!std::is_enum_v<T> && std::is_signed_v<T>)\n\t\t\t{\n\t\t\t\tis_neg = (x < 0);\n\n\t\t\t\tif(is_neg)\n\t\t\t\t\tx = -x;\n\t\t\t}\n\t\t#endif\n\n\t\t\tstd::string digits;\n\t\t\t{\n\t\t\t\t// if we print base 2 we need 64 digits!\n\t\t\t\tchar buf[65] = {0};\n\n\t\t\t\tsize_t digits_len = 0;\n\t\t\t\tauto spec = args.specifier;\n\n\t\t\t\tstatic const char* len_specs[] = {\n\t\t\t\t\t/* LENGTH_DEFAULT */        \"\",\n\t\t\t\t\t/* LENGTH_SHORT_SHORT */    \"hh\",\n\t\t\t\t\t/* LENGTH_SHORT */          \"h\",\n\t\t\t\t\t/* LENGTH_LONG */           \"l\",\n\t\t\t\t\t/* LENGTH_LONG_LONG */      \"ll\",\n\t\t\t\t\t/* LENGTH_LONG_DOUBLE */    \"L\",\n\t\t\t\t\t/* LENGTH_INTMAX_T */       \"j\",\n\t\t\t\t\t/* LENGTH_SIZE_T */         \"z\",\n\t\t\t\t\t/* LENGTH_PTRDIFF_T */      \"t\",\n\t\t\t\t};\n\n\t\t\t\tauto len_spec = len_specs[args.length];\n\t\t\t\tif(std::is_same_v<int64_t, std::remove_cv_t<std::decay_t<T>>>)\n\t\t\t\t\tlen_spec = \"ll\";\n\n\t\t\t\tif(std::is_same_v<size_t, std::remove_cv_t<std::decay_t<T>>>)\n\t\t\t\t\tlen_spec = \"z\";\n\n\t\t\t\tif(std::is_same_v<uint64_t, std::remove_cv_t<std::decay_t<T>>>)\n\t\t\t\t\tlen_spec = \"ll\";\n\n\n\t\t\t\tauto fmt_str = (\"%\" + std::string(len_spec) + spec);\n\n\t\t\t\tdigits_len = snprintf(&buf[0], 64, fmt_str.c_str(), x);\n\n\t\t\t\t// sadly, we must cheat here as well, because osx doesn't bloody have charconv (STILL)?\n\n\t\t\t\t// std::to_chars_result ret;\n\t\t\t\t// if constexpr (std::is_enum_v<T>)\n\t\t\t\t// \tret = std::to_chars(&buf[0], &buf[65], static_cast<std::underlying_type_t<T>>(x), /* base: */ base);\n\n\t\t\t\t// else\n\t\t\t\t// \tret = std::to_chars(&buf[0], &buf[65], x, /* base: */ base);\n\n\n\t\t\t\t// if(ret.ec == std::errc())   digits_len = (ret.ptr - &buf[0]), *ret.ptr = 0;\n\t\t\t\t// else                        return \"<to_chars(int) error>\";\n\n\t\t\t\tif(isupper(args.specifier))\n\t\t\t\t\tfor(size_t i = 0; i < digits_len; i++)\n\t\t\t\t\t\tbuf[i] = static_cast<char>(toupper(buf[i]));\n\n\t\t\t\tdigits = std::string(buf, digits_len);\n\t\t\t}\n\n\t\t\tstd::string prefix;\n\t\t\t#if 0\n\t\t\tif(is_neg)                              prefix += \"-\";\n\t\t\telse\n\t\t\t#endif\n\n\t\t\tif(args.prepend_plus_if_positive)       prefix += \"+\";\n\t\t\telse if(args.prepend_blank_if_positive) prefix += \" \";\n\n\t\t\t// prepend 0x or 0b or 0o for alternate.\n\t\t\tint64_t prefix_digits_length = 0;\n\t\t\tif((base == 2 || base == 8 || base == 16) && args.alternate)\n\t\t\t{\n\t\t\t\tprefix += \"0\";\n\t\t\t\t#if HEX_0X_RESPECTS_UPPERCASE\n\t\t\t\t\tprefix += args.specifier;\n\t\t\t\t#else\n\t\t\t\t\tprefix += tolower(args.specifier);\n\t\t\t\t#endif\n\t\t\t\tprefix_digits_length += 2;\n\t\t\t}\n\n\t\t\tint64_t output_length_with_precision = (args.precision == -1\n\t\t\t\t? digits.size()\n\t\t\t\t: std::max(args.precision, static_cast<int64_t>(digits.size()))\n\t\t\t);\n\n\t\t\tint64_t digits_length = prefix_digits_length + digits.size();\n\t\t\tint64_t normal_length = prefix.size() + digits.size();\n\t\t\tint64_t length_with_precision = prefix.size() + output_length_with_precision;\n\n\t\t\tbool use_precision = (args.precision != -1);\n\t\t\tbool use_zero_pad = args.zero_pad && 0 <= args.width && !use_precision;\n\t\t\tbool use_left_pad = !use_zero_pad && 0 <= args.width;\n\t\t\tbool use_right_pad = !use_zero_pad && args.width < 0;\n\n\t\t\tint64_t abs_field_width = std::abs(args.width);\n\n\t\t\tstd::string pre_prefix;\n\t\t\tif(use_left_pad)\n\t\t\t\tpre_prefix = std::string(std::max(int64_t(0), abs_field_width - length_with_precision), ' ');\n\n\t\t\tstd::string post_prefix;\n\t\t\tif(use_zero_pad)\n\t\t\t\tpost_prefix = std::string(std::max(int64_t(0), abs_field_width - normal_length), '0');\n\n\t\t\tstd::string prec_string;\n\t\t\tif(use_precision)\n\t\t\t\tprec_string = std::string(std::max(int64_t(0), args.precision - digits_length), '0');\n\n\t\t\tstd::string postfix;\n\t\t\tif(use_right_pad)\n\t\t\t\tpostfix = std::string(std::max(int64_t(0), abs_field_width - length_with_precision), ' ');\n\n\t\t\treturn pre_prefix + prefix + post_prefix + prec_string + digits + postfix;\n\t\t}\n\t};\n\n\ttemplate <typename T>\n\tstruct print_formatter<T, typename std::enable_if<\n\t\tstd::is_floating_point_v<std::remove_cv_t<std::remove_reference_t<std::remove_cv_t<T>>>>\n\t>::type>\n\t{\n\t\tstd::string print(const T& x, const format_args& args)\n\t\t{\n\t\t\tconstexpr int default_prec = 6;\n\n\t\t\tchar buf[81] = { 0 };\n\t\t\tint64_t num_length = 0;\n\n\t\t\t// lmao. nobody except msvc stl (and only the most recent version) implements std::to_chars\n\t\t\t// for floating point types, even though it's in the c++17 standard. so we just cheat.\n\n\t\t\t// let printf handle the precision, but we'll handle the width and the negativity.\n\t\t\t{\n\t\t\t\tconst char* fmt_str = 0;\n\t\t\t\tbool longdouble = (args.length == format_args::LENGTH_LONG_DOUBLE);\n\n\t\t\t\tswitch(args.specifier)\n\t\t\t\t{\n\t\t\t\t\tcase 'E': fmt_str = (longdouble ? \"%.*LE\" : \"%.*E\"); break;\n\t\t\t\t\tcase 'e': fmt_str = (longdouble ? \"%.*Le\" : \"%.*e\"); break;\n\t\t\t\t\tcase 'F': fmt_str = (longdouble ? \"%.*LF\" : \"%.*F\"); break;\n\t\t\t\t\tcase 'f': fmt_str = (longdouble ? \"%.*Lf\" : \"%.*f\"); break;\n\t\t\t\t\tcase 'G': fmt_str = (longdouble ? \"%.*LG\" : \"%.*G\"); break;\n\n\t\t\t\t\tcase 'g': [[fallthrough]];\n\t\t\t\t\tdefault:  fmt_str = (longdouble ? \"%.*Lg\" : \"%.*g\"); break;\n\t\t\t\t}\n\n\t\t\t\tnum_length = snprintf(&buf[0], 80, fmt_str,\n\t\t\t\t\t(args.precision == -1 ? default_prec : args.precision), fabs(x));\n\t\t\t}\n\n\t\t\tauto abs_field_width = std::abs(args.width);\n\n\t\t\tbool use_zero_pad = args.zero_pad && args.width >= 0;\n\t\t\tbool use_left_pad = !use_zero_pad && args.width >= 0;\n\t\t\tbool use_right_pad = !use_zero_pad && args.width < 0;\n\n\t\t\t// account for the signs, if any.\n\t\t\tif(x < 0 || args.prepend_plus_if_positive || args.prepend_blank_if_positive)\n\t\t\t\tnum_length += 1;\n\n\t\t\tstd::string pre_prefix;\n\t\t\tif(use_left_pad)\n\t\t\t\tpre_prefix = std::string(std::max(int64_t(0), abs_field_width - num_length), ' ');\n\n\t\t\tstd::string prefix;\n\t\t\tif(x < 0)                               prefix = \"-\";\n\t\t\telse if(args.prepend_plus_if_positive)  prefix = \"+\";\n\t\t\telse if(args.prepend_blank_if_positive) prefix = \" \";\n\n\t\t\tstd::string post_prefix;\n\t\t\tif(use_zero_pad)\n\t\t\t\tpost_prefix = std::string(std::max(int64_t(0), abs_field_width - num_length), '0');\n\n\t\t\tstd::string postfix;\n\t\t\tif(use_right_pad)\n\t\t\t\tpostfix = std::string(std::max(int64_t(0), abs_field_width - num_length), ' ');\n\n\t\t\treturn pre_prefix + prefix + post_prefix + std::string(buf) + postfix;\n\t\t}\n\t};\n\n\n\ttemplate <typename T>\n\tstruct print_formatter<T, typename std::enable_if<\n\t\t(std::is_same_v<std::string, T>) || (std::is_same_v<std::string_view, T>) ||\n\t\t(std::is_same_v<const char*, std::decay_t<T>>) || (std::is_same_v<char*, std::decay_t<T>>)\n\t>::type>\n\t{\n\t\tstd::string print(const T& x, const format_args& args)\n\t\t{\n\t\t\tint64_t string_length = 0;\n\t\t\tint64_t abs_field_width = std::abs(args.width);\n\n\t\t\tif constexpr (std::is_pointer_v<std::remove_reference_t<std::decay_t<T>>>)\n\t\t\t{\n\t\t\t\tfor(int64_t i = 0; (args.precision != -1 ? (i < args.precision && x && x[i]) : (x && x[i])); i++)\n\t\t\t\t\tstring_length++;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif(args.precision >= 0) string_length = std::min(args.precision, static_cast<int64_t>(x.size()));\n\t\t\t\telse                    string_length = static_cast<int64_t>(x.size());\n\t\t\t}\n\n\t\t\tstd::string prefix;\n\t\t\tif(args.width >= 0 && string_length < abs_field_width)\n\t\t\t\tprefix = std::string(abs_field_width - string_length, ' ');\n\n\t\t\tstd::string postfix;\n\t\t\tif(args.width < 0 && string_length < abs_field_width)\n\t\t\t\tpostfix = std::string(abs_field_width - string_length, ' ');\n\n\n\t\t\tif constexpr (std::is_pointer_v<std::decay_t<T>>)\n\t\t\t\treturn prefix + std::string(x, string_length) + postfix;\n\n\t\t\telse\n\t\t\t\treturn prefix + std::string(x, 0, string_length) + postfix;\n\t\t}\n\t};\n\n\ttemplate <typename T>\n\tstruct print_formatter<T, typename std::enable_if<\n\t\t(std::is_same_v<char, std::remove_cv_t<std::remove_reference_t<std::remove_cv_t<T>>>>)\n\t>::type>\n\t{\n\t\tstd::string print(const T& x, const format_args& args)\n\t\t{\n\t\t\t// just reuse the string printer, but with a one-char-long string.\n\t\t\t// probably not so efficient, but idgaf for now.\n\t\t\treturn print_formatter<std::string>()\n\t\t\t\t.print(std::string(1, x), args);\n\t\t}\n\t};\n\n\ttemplate <typename T>\n\tstruct print_formatter<T, typename std::enable_if<\n\t\t(std::is_same_v<bool, std::remove_cv_t<std::remove_reference_t<std::remove_cv_t<T>>>>)\n\t>::type>\n\t{\n\t\tstd::string print(const T& x, format_args args)\n\t\t{\n\t\t\treturn print_formatter<std::string>()\n\t\t\t\t.print(x ? \"true\" : \"false\", args);\n\t\t}\n\t};\n\n\ttemplate <typename T>\n\tstruct print_formatter<T, typename std::enable_if<\n\t\t(std::is_same_v<void*, std::decay_t<T>>)\n\t>::type>\n\t{\n\t\tstd::string print(const T& x, format_args args)\n\t\t{\n\t\t\targs.specifier = 'x';\n\t\t\treturn print_formatter<uintptr_t>()\n\t\t\t\t.print(reinterpret_cast<uintptr_t>(x), args);\n\t\t}\n\t};\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/include/ztmu.h",
    "content": "// ztmu.h\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n// terminal manipulation utilities\n\n#pragma once\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <stddef.h>\n\n#include <map>\n#include <vector>\n#include <string>\n#include <sstream>\n#include <optional>\n#include <functional>\n#include <string_view>\n\n\nnamespace ztmu\n{\n\tenum class Key\n\t{\n\t\t// start above 0xFF, so anything below we can just use as normal chars.\n\t\tESCAPE = 0x100,\n\t\tENTER,\n\t\tUP,\n\t\tDOWN,\n\t\tLEFT,\n\t\tRIGHT,\n\t\tHOME,\n\t\tEND,\n\t\tDELETE,\n\t\tINSERT,\n\t\tPAGEUP,\n\t\tPAGEDOWN,\n\t\tF0, F1, F2, F3, F4, F5, F6, F7, F8, F9,\n\t\tF10, F11, F12, F13, F14, F15, F16, F17,\n\t\tF18, F19, F20, F21, F22, F23, F24\n\t};\n\n\tenum class HandlerAction\n\t{\n\t\tCONTINUE,   // do nothing, and continue reading the line.\n\t\tRETURN,     // as if enter was pressed -- finish the line and give it back.\n\t\tQUIT        // abandon ship -- return EOF.\n\t};\n\n\tstruct State\n\t{\n\t\tvoid clear();\n\n\t\tvoid setupConsole();\n\t\tvoid unsetupConsole();\n\n\t\tstd::optional<std::string> read();\n\t\tstd::optional<std::vector<std::string>> readContinuation(const std::string& seed = \"\");\n\n\t\tvoid setPrompt(const std::string& prompt);\n\t\tvoid setContPrompt(const std::string& prompt);\n\t\tvoid setWrappedPrompt(const std::string& prompt);\n\n\t\tvoid useUniqueHistory(bool enable);\n\t\tvoid addPreviousInputToHistory();\n\t\tvoid loadHistory(const std::vector<std::vector<std::string>>& h);\n\t\tstd::vector<std::vector<std::string>> getHistory();\n\n\t\tvoid move_cursor_left(int n);\n\t\tvoid move_cursor_right(int n);\n\n\t\tvoid move_cursor_up(int n);\n\t\tvoid move_cursor_down(int n);\n\n\t\tvoid move_cursor_home();\n\t\tvoid move_cursor_end();\n\n\t\tvoid delete_left(int n);\n\t\tvoid delete_right(int n);\n\n\t\t// the handler will return true to continue reading, false to stop and return all input.\n\t\tvoid setKeyHandler(Key k, std::function<HandlerAction (State*, Key)> handler);\n\t\tvoid unsetKeyHandler(Key k);\n\n\t\tstd::string getCurrentLine();\n\t\tvoid setCurrentLine(const std::string& s);\n\n\t\tvoid setMessageOnControlC(const std::string& msg);\n\t\tvoid enableExitOnEmptyControlC();\n\n\t\tstd::string promptString;\n\t\tstd::string contPromptString;\n\t\tstd::string wrappedPromptString;\n\n\t\tsize_t normPL = 0;\n\t\tsize_t contPL = 0;\n\t\tsize_t wrapPL = 0;\n\n\t\tsize_t cursor = 0;\n\t\tsize_t byteCursor = 0;\n\n\t\tsize_t lineIdx = 0;\n\t\tsize_t wrappedLineIdx = 0;\n\t\tsize_t cachedNWLForCurrentLine = 0;\n\n\t\tsize_t termWidth = 0;\n\t\tsize_t termHeight = 0;\n\n\t\tstd::vector<std::string> lines;\n\t\tstd::map<Key, std::function<HandlerAction (State*, Key)>> keyHandlers;\n\n\t\tstd::vector<std::vector<std::string>> history;\n\t\tstd::vector<std::string> savedCurrentInput;\n\t\tbool uniqueHistory = true;\n\t\tsize_t historyIdx = 0;\n\n\t\tbool wasAborted = false;\n\t\tbool emptyCtrlCExits = false;\n\t\tstd::string uselessControlCMsg;\n\t};\n\n\tsize_t getTerminalWidth();\n\tsize_t displayedTextLength(const std::string_view& str);\n\n\tinline std::vector<std::string> prettyFormatTextBlock(const std::vector<std::string>& paragraphs,\n\t\tconst char* leftMargin, const char* rightMargin, size_t maxLines = 0);\n\tstd::vector<std::string> prettyFormatTextBlock(const std::string& block, const char* leftMargin,\n\t\tconst char* rightMargin, size_t maxLines = 0);\n}\n\n\n\n\n\nnamespace ztmu {\nnamespace detail\n{\n\tstruct CursorPosition\n\t{\n\t\tint x = -1;\n\t\tint y = -1;\n\t};\n\n\tstruct ControlSeq\n\t{\n\t\tControlSeq() { }\n\t\tControlSeq(char c) : lastChar(c) { }\n\n\t\tchar lastChar;\n\n\t\t// only support max 8 params for now.\n\t\tint numParams = 0;\n\t\tint params[8];\n\t};\n\n\tvoid setup_console();\n\tvoid unsetup_console();\n\n\tsize_t getTerminalWidth();\n\tsize_t getTerminalHeight();\n\tsize_t displayedTextLength(const std::string_view& str);\n\tbool read_line(State* st, int promptMode, std::string seed);\n\tvoid cursor_left(State* st, bool refresh = true);\n\tvoid cursor_right(State* st, bool refresh = true);\n\tvoid refresh_line(State* st, std::string* oldLine = 0);\n\tvoid cursor_up(State* st);\n\tvoid cursor_down(State* st);\n\tvoid cursor_home(State* st);\n\tvoid cursor_end(State* st, bool refresh = true);\n\tvoid delete_left(State* st);\n\tvoid delete_right(State* st);\n\tsize_t convertCursorToByteCursor(const char* bytes, size_t cursor);\n\n\tstd::vector<std::string> pretty_print_text_block(const std::vector<std::string>& paragraphs, const char* leftMargin,\n\t\tconst char* rightMargin, size_t maxLines);\n\n\n\n// close out the scope here -- we don't want to #include headers in a namespace.\n}\n}\n\n\n\n\n\n\n\n\n\n\n\n#if ZTMU_CREATE_IMPL\n\n// comes as a pair yo\n#include \"zpr.h\"\n\n#ifndef _WIN32\n\n\t#include <unistd.h>\n\t#include <signal.h>\n\t#include <termios.h>\n\t#include <sys/ioctl.h>\n\n\nnamespace ztmu {\nnamespace detail\n{\n\tstatic struct termios original_termios;\n\n\n\tstatic inline void platform_write(const char* s, size_t len)\n\t{\n\t\twrite(STDOUT_FILENO, s, len);\n\t}\n\n\tstatic inline int platform_read_one(char* c)\n\t{\n\t\treturn read(STDIN_FILENO, c, 1);\n\t}\n\n\tstatic inline int platform_read(char* c, size_t len)\n\t{\n\t\treturn read(STDIN_FILENO, c, len);\n\t}\n\n\tstatic bool isInRawMode = false;\n\tstatic bool didRegisterAtexit = false;\n\tstatic inline void leaveRawMode()\n\t{\n\t\tif(isInRawMode && tcsetattr(STDIN_FILENO, TCSAFLUSH, &original_termios) != -1)\n\t\t\tisInRawMode = false;\n\n\t\t// disable bracketed paste:\n\t\tauto tmp = std::string_view(\"\\x1b[?2004l\");\n\t\tplatform_write(tmp.data(), tmp.size());\n\t}\n\n\tstatic inline void enterRawMode()\n\t{\n\t\tif(!isatty(STDIN_FILENO))\n\t\t\treturn;\n\n\t\tif(!didRegisterAtexit)\n\t\t{\n\t\t\tatexit([]() {\n\t\t\t\tleaveRawMode();\n\t\t\t});\n\n\t\t\tdidRegisterAtexit = true;\n\t\t}\n\n\t\tif(tcgetattr(STDIN_FILENO, &original_termios) == -1)\n\t\t\treturn;\n\n\t\t// copy the original\n\t\ttermios raw = original_termios;\n\n\t\t// input modes: no break, no CR to NL, no parity check, no strip char,\n\t\t// no start/stop output control.\n\t\traw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);\n\n\t\t// output modes - disable post processing\n\t\traw.c_oflag &= ~(OPOST);\n\n\t\t// control modes - set 8 bit chars\n\t\traw.c_cflag |= (CS8);\n\n\t\t// local modes - echoing off, canonical off, no extended functions,\n\t\t// no signal chars (^Z,^C)\n\t\traw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);\n\n\t\t// control chars - set return condition: min number of bytes and timer.\n\t\t// We want read to return every single byte, without timeout.\n\t\traw.c_cc[VMIN] = 1;\n\t\traw.c_cc[VTIME] = 0;\n\n\t\t/* put terminal in raw mode after flushing */\n\t\tif(tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) < 0)\n\t\t\treturn;\n\n\t\t// enable bracketed paste:\n\t\tauto tmp = std::string_view(\"\\x1b[?2004h\");\n\t\tplatform_write(tmp.data(), tmp.size());\n\t\tisInRawMode = true;\n\t}\n\n\tinline void setup_console()\n\t{\n\t\t// on unix, we don't really need to do anything \"globally\".\n\t}\n\n\tinline void unsetup_console()\n\t{\n\t}\n\n\tstatic struct sigaction old_sigact;\n\tstatic State* currentStateForSignal = 0;\n\tstatic inline bool setup_sigwinch()\n\t{\n\t\t// time for some signalling!\n\t\tstruct sigaction new_sa;\n\n\t\t// i would use designated initialisers, but some compilers refuse to cooperate.\n\t\tnew_sa.sa_flags = SA_RESTART;   // this is important, if not read() will return EINTR (interrupted by signal)\n\t\tnew_sa.sa_handler = [](int sig) {\n\t\t\tif(currentStateForSignal)\n\t\t\t{\n\t\t\t\tcurrentStateForSignal->termWidth = getTerminalWidth();\n\t\t\t\tcurrentStateForSignal->termHeight = getTerminalHeight();\n\t\t\t}\n\t\t};\n\n\n\t\tif(sigaction(SIGWINCH, &new_sa, &old_sigact) == 0)\n\t\t\treturn true;\n\n\t\treturn false;\n\t}\n\n\tstatic inline void restore_sigwinch()\n\t{\n\t\tsigaction(SIGWINCH, &old_sigact, nullptr);\n\t}\n\n\n#else\n\t// mfw\n\t#define WIN32_LEAN_AND_MEAN 1\n\n\t#ifndef NOMINMAX\n\t\t#define NOMINMAX\n\t#endif\n\n\t#include <windows.h>\n\n\t#include <io.h>\n\t#include <signal.h>\n\nnamespace ztmu {\nnamespace detail\n{\n\tstatic constexpr int STDOUT_FILENO = 1;\n\tstatic constexpr int STDIN_FILENO  = 0;\n\n\tstatic inline void platform_write(const char* s, size_t len)\n\t{\n\t\tDWORD written = 0;\n\t\tWriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), s, static_cast<DWORD>(len), &written, NULL);\n\t}\n\n\tstatic inline int platform_read_one(char* c)\n\t{\n\t\t// return _read(STDIN_FILENO, c, 1);\n\t\tDWORD didRead = 0;\n\t\tReadConsole(GetStdHandle(STD_INPUT_HANDLE), c, 1, &didRead, NULL);\n\t\treturn didRead;\n\t}\n\n\tstatic inline int platform_read(char* c, size_t len)\n\t{\n\t\tDWORD didRead = 0;\n\t\tReadConsole(GetStdHandle(STD_INPUT_HANDLE), c, static_cast<DWORD>(len), &didRead, NULL);\n\t\treturn didRead;\n\t}\n\n\tstatic DWORD old_stdin_mode = 0;\n\tstatic DWORD old_stdout_mode = 0;\n\n\tstatic bool isInRawMode = false;\n\tstatic bool didRegisterAtexit = false;\n\n\tstatic inline void leaveRawMode()\n\t{\n\t\tif(!isInRawMode)\n\t\t\treturn;\n\n\t\tauto stdin_handle = GetStdHandle(STD_INPUT_HANDLE);\n\t\tauto stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);\n\n\t\tSetConsoleMode(stdin_handle, old_stdin_mode);\n\t\tSetConsoleMode(stdout_handle, old_stdout_mode);\n\n\t\tisInRawMode = false;\n\t}\n\n\n\tstatic inline void enterRawMode()\n\t{\n\t\tif(!_isatty(STDIN_FILENO))\n\t\t\treturn;\n\n\t\tisInRawMode = true;\n\n\t\tauto stdin_handle = GetStdHandle(STD_INPUT_HANDLE);\n\t\tauto stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);\n\n\t\tGetConsoleMode(stdin_handle, &old_stdin_mode);\n\t\tGetConsoleMode(stdout_handle, &old_stdout_mode);\n\n\t\t{\n\t\t\t// this is pretty much the only flag we want.\n\t\t\tDWORD stdin_mode = ENABLE_EXTENDED_FLAGS | ENABLE_VIRTUAL_TERMINAL_INPUT;\n\t\t\tSetConsoleMode(stdin_handle, stdin_mode);\n\n\n\t\t\t// then stdout:\n\t\t\tDWORD stdout_mode = ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN;\n\t\t\tSetConsoleMode(stdout_handle, stdout_mode);\n\t\t}\n\n\t\tif(!didRegisterAtexit)\n\t\t{\n\t\t\tatexit([]() {\n\t\t\t\tleaveRawMode();\n\t\t\t});\n\n\t\t\tdidRegisterAtexit = true;\n\t\t}\n\t}\n\n\tstatic UINT old_input_cp;\n\tstatic UINT old_output_cp;\n\tinline void setup_console()\n\t{\n\t\told_input_cp = GetConsoleCP();\n\t\told_output_cp = GetConsoleOutputCP();\n\n\t\tSetConsoleCP(CP_UTF8);\n\t\tSetConsoleOutputCP(CP_UTF8);\n\t}\n\n\tinline void unsetup_console()\n\t{\n\t\tSetConsoleCP(old_input_cp);\n\t\tSetConsoleOutputCP(old_output_cp);\n\t}\n\n\tstatic State* currentStateForSignal = 0;\n\tstatic inline bool setup_sigwinch()\n\t{\n\t\t// on windows we can't really do anything. knowing about window size changes requires using\n\t\t// ReadConsoleInput to poll for events, which we obviously can't do here, or use another\n\t\t// thread, which i'm loathe to do. so for now, suck it up, windows users.\n\t\treturn false;\n\t}\n\n\tstatic inline void restore_sigwinch()\n\t{\n\t}\n\n#endif\n\n\n\t#if 0\n\t\ttemplate <typename... Args>\n\t\tvoid ztmu_dbg(const char* fmt, Args&&... args)\n\t\t{\n\t\t\tif(!isatty(STDERR_FILENO))\n\t\t\t\tfprintf(stderr, \"%s\", zpr::sprint(fmt, args...).c_str());\n\t\t}\n\t#else\n\t\ttemplate <typename... Args>\n\t\tvoid ztmu_dbg(const char* fmt, Args&&... args) { }\n\t#endif\n\n\n\n\n\n\n\tstatic constexpr const char  ESC = '\\x1b';\n\tstatic constexpr const char* CSI = \"\\x1b[\";\n\n\tstatic inline void platform_write(const std::string_view& sv)\n\t{\n\t\tplatform_write(sv.data(), sv.size());\n\t}\n\n\tstatic inline std::string moveCursorUp(size_t n);\n\tstatic inline std::string moveCursorDown(size_t n);\n\tstatic inline std::string moveCursorLeft(size_t n);\n\tstatic inline std::string moveCursorRight(size_t n);\n\n\tstatic inline std::string moveCursorUp(size_t n)\n\t{\n\t\tif(n == 0)  return \"\";\n\t\telse        return zpr::sprint(\"%s%dA\", CSI, n);\n\t}\n\n\tstatic inline std::string moveCursorDown(size_t n)\n\t{\n\t\tif(n == 0)  return \"\";\n\t\telse        return zpr::sprint(\"%s%dB\", CSI, n);\n\t}\n\n\tstatic inline std::string moveCursorLeft(size_t n)\n\t{\n\t\tif(n == 0)  return \"\";\n\t\telse        return zpr::sprint(\"%s%dD\", CSI, n);\n\t}\n\n\tstatic inline std::string moveCursorRight(size_t n)\n\t{\n\t\tif(n == 0)  return \"\";\n\t\telse        return zpr::sprint(\"%s%dC\", CSI, n);\n\t}\n\n\tstatic CursorPosition getCursorPosition()\n\t{\n\t\tplatform_write(zpr::sprint(\"%s6n\", CSI));\n\n\t\t// ok, time to read it back. format is CSI [ rows ; cols R\n\t\tchar buf[33] { 0 };\n\t\tfor(size_t i = 0; i < 32; i++)\n\t\t{\n\t\t\tif(platform_read_one(buf + i) != 1)\n\t\t\t\tbreak;\n\n\t\t\tif(buf[i] == 'R')\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// give up.\n\t\tif(buf[0] != ESC || buf[1] != '[')\n\t\t\treturn CursorPosition();\n\n\t\tCursorPosition ret;\n\t\tint gotted = sscanf(&buf[2], \"%d;%d\", &ret.y, &ret.x);\n\t\tif(gotted != 2)\n\t\t\treturn CursorPosition();\n\n\t\treturn ret;\n\t}\n\n\t// static std::string setCursorPosition(const CursorPosition& pos)\n\t// {\n\t// \tif(pos.x <= 0 || pos.y <= 0)\n\t// \t\treturn \"\";\n\n\t// \treturn zpr::sprint(\"%s%d;%dH\", CSI, pos.y, pos.x);\n\t// }\n\n\n\n\n\n\n\n\n\n\n\n\tstatic size_t parseEscapeSequence(const std::string_view& str)\n\t{\n\t\tif(str.size() < 2 || str[0] != ESC)\n\t\t\treturn 0;\n\n\t\tauto read_digits = [](const std::string_view& s, int* out) -> size_t {\n\t\t\tint ret = 0;\n\t\t\tsize_t cons = 0;\n\t\t\tfor(char c : s)\n\t\t\t{\n\t\t\t\tif(!isdigit(c))\n\t\t\t\t\tbreak;\n\n\t\t\t\tcons++;\n\t\t\t\tret = (10 * ret) + (c - '0');\n\t\t\t}\n\n\t\t\t*out = ret;\n\t\t\treturn cons;\n\t\t};\n\n\n\n\n\t\tif(str[1] == ESC)\n\t\t{\n\t\t\treturn 2;\n\t\t}\n\t\telse if(str[1] == 'N' || str[1] == 'O' || str[1] == 'c')\n\t\t{\n\t\t\treturn 2;\n\t\t}\n\t\telse if(str[1] == 'P' || str[1] == ']' || str[1] == 'X' || str[1] == '^' || str[1] == '_')\n\t\t{\n\t\t\t// read till the terminator (ESC\\).\n\t\t\tsize_t cons = 2;\n\t\t\twhile(cons + 1 < str.size() && (str[cons] != ESC || str[cons + 1] != '\\\\'))\n\t\t\t\tcons++;\n\n\t\t\treturn cons;\n\t\t}\n\t\telse if(str[1] == '[')\n\t\t{\n\t\t\t// parse the params.\n\t\t\tControlSeq csi;\n\n\t\t\tsize_t cons = 2;\n\t\t\twhile(csi.numParams < 8)\n\t\t\t{\n\t\t\t\tint n = 0;\n\t\t\t\tsize_t rd = read_digits(str.substr(cons), &n);\n\t\t\t\tif(rd > 0)\n\t\t\t\t{\n\t\t\t\t\tcsi.params[csi.numParams++] = n;\n\t\t\t\t\tcons += rd;\n\n\t\t\t\t\tif(cons < str.size() && str[cons] == ';')\n\t\t\t\t\t{\n\t\t\t\t\t\tcons++;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcsi.lastChar = str[cons++];\n\t\t\treturn cons;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\n\tinline size_t displayedTextLength(const std::string_view& str)\n\t{\n\t\tauto utf8_len = [](const char* begin, const char* end) -> size_t {\n\t\t\tsize_t len = 0;\n\n\t\t\twhile(*begin && begin != end)\n\t\t\t{\n\t\t\t\tif((*begin & 0xC0) != 0x80)\n\t\t\t\t\tlen += 1;\n\n\t\t\t\tbegin++;\n\t\t\t}\n\t\t\treturn len;\n\t\t};\n\n\t\tauto len = utf8_len(str.data(), str.data() + str.size());\n\t\t{\n\t\t\tsize_t cons = 0;\n\t\t\tstd::string_view sv = str;\n\n\t\t\tsize_t i = 0;\n\t\t\twhile(i < sv.size())\n\t\t\t{\n\t\t\t\tif(sv[i] == ESC)\n\t\t\t\t{\n\t\t\t\t\tsize_t k = parseEscapeSequence(sv.substr(i));\n\t\t\t\t\ti += k;\n\t\t\t\t\tcons += k;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn len - cons;\n\t\t}\n\t}\n\n\n\tinline size_t getTerminalWidth()\n\t{\n\t\t#ifdef _WIN32\n\t\t\tCONSOLE_SCREEN_BUFFER_INFO csbi;\n\t\t\tGetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);\n\t\t\treturn csbi.srWindow.Right - csbi.srWindow.Left + 1;\n\t\t#else\n\n\t\t\t#ifdef _MSC_VER\n\t\t\t#else\n\t\t\t\t#pragma GCC diagnostic push\n\t\t\t\t#pragma GCC diagnostic ignored \"-Wold-style-cast\"\n\t\t\t#endif\n\n\t\t\tstruct winsize w;\n\t\t\tioctl(STDOUT_FILENO, TIOCGWINSZ, &w);\n\t\t\treturn w.ws_col;\n\n\t\t\t#ifdef _MSC_VER\n\t\t\t#else\n\t\t\t\t#pragma GCC diagnostic pop\n\t\t\t#endif\n\n\t\t#endif\n\t}\n\n\tinline size_t getTerminalHeight()\n\t{\n\t\t#ifdef _WIN32\n\t\t\tCONSOLE_SCREEN_BUFFER_INFO csbi;\n\t\t\tGetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);\n\t\t\treturn csbi.srWindow.Bottom - csbi.srWindow.Top + 1;\n\t\t#else\n\n\t\t\t#ifdef _MSC_VER\n\t\t\t#else\n\t\t\t\t#pragma GCC diagnostic push\n\t\t\t\t#pragma GCC diagnostic ignored \"-Wold-style-cast\"\n\t\t\t#endif\n\n\t\t\tstruct winsize w;\n\t\t\tioctl(STDOUT_FILENO, TIOCGWINSZ, &w);\n\t\t\treturn w.ws_row;\n\n\t\t\t#ifdef _MSC_VER\n\t\t\t#else\n\t\t\t\t#pragma GCC diagnostic pop\n\t\t\t#endif\n\n\t\t#endif\n\t}\n\n\tstatic std::string& getCurLine(State* st)\n\t{\n\t\treturn st->lines[st->lineIdx];\n\t}\n\n\tstatic size_t findBeginningOfUTF8CP(const uint8_t* bytes, size_t i)\n\t{\n\t\tif(bytes[i] <= 0x7F)\n\t\t\treturn i;\n\n\t\twhile(i > 0 && (bytes[i] & 0xC0) == 0x80)\n\t\t\ti -= 1;\n\n\t\treturn i;\n\t}\n\n\tstatic size_t findEndOfUTF8CP(const uint8_t* bytes, size_t i)\n\t{\n\t\tif(bytes[i] <= 0x7F)\n\t\t\treturn i;\n\n\t\tif((bytes[i] & 0xE0) == 0xC0)\n\t\t\treturn i + 1;\n\n\t\telse if((bytes[i] & 0xF0) == 0xE0)\n\t\t\treturn i + 2;\n\n\t\telse if((bytes[i] & 0xF8) == 0xF0)\n\t\t\treturn i + 3;\n\n\t\treturn i;\n\t}\n\n\tinline size_t convertCursorToByteCursor(const char* bytes, size_t cursor)\n\t{\n\t\tsize_t bc = 0;\n\t\tfor(size_t i = 0; i < cursor; i++)\n\t\t\tbc = 1 + findEndOfUTF8CP(reinterpret_cast<const uint8_t*>(bytes), bc);\n\n\t\treturn bc;\n\t}\n\n\n\tstatic std::pair<size_t, size_t> calculate_left_codepoints(size_t n, const std::string_view& sv, size_t cursor, size_t byteCursor)\n\t{\n\t\tfor(size_t i = 0; i < n; i++)\n\t\t{\n\t\t\tif(cursor > 0)\n\t\t\t{\n\t\t\t\tauto x = byteCursor - 1;\n\t\t\t\tauto l = findBeginningOfUTF8CP(reinterpret_cast<const uint8_t*>(sv.data()), x);\n\t\t\t\tbyteCursor -= (x - l + 1);\n\t\t\t\tcursor -= 1;\n\t\t\t}\n\t\t}\n\n\t\treturn { cursor, byteCursor };\n\t}\n\n\t// static std::pair<size_t, size_t> calculate_right_codepoints(int n, const std::string_view& sv, size_t cursor, size_t byteCursor)\n\t// {\n\t// \tfor(int i = 0; i < n; i++)\n\t// \t{\n\t// \t\tif(byteCursor < sv.size())\n\t// \t\t{\n\t// \t\t\tauto x = byteCursor;\n\t// \t\t\tauto l = findEndOfUTF8CP(reinterpret_cast<const uint8_t*>(sv.data()), x);\n\n\t// \t\t\tbyteCursor += (l - x + 1);\n\t// \t\t\tcursor += 1;\n\t// \t\t}\n\t// \t}\n\n\t// \treturn { cursor, byteCursor };\n\t// }\n\n\n\n\tstatic size_t get_cursor_line_offset(size_t termWidth, size_t num, size_t firstPromptLen, size_t subsequentPromptLen, bool* didWrap = 0)\n\t{\n\t\tsize_t hcursor = firstPromptLen;\n\t\tsize_t x = num;\n\n\t\twhile(true)\n\t\t{\n\t\t\tauto left = termWidth - hcursor;\n\t\t\tauto todo = std::min(left, x);\n\t\t\tx -= todo;\n\n\t\t\tif(x == 0)\n\t\t\t{\n\t\t\t\thcursor += todo;\n\t\t\t\tif(hcursor == termWidth)\n\t\t\t\t{\n\t\t\t\t\thcursor = subsequentPromptLen;\n\t\t\t\t\tif(didWrap) *didWrap = true;\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\thcursor = subsequentPromptLen;\n\t\t}\n\n\t\treturn hcursor;\n\t}\n\n\tstatic size_t calculate_wli(State* st, size_t len)\n\t{\n\t\tsize_t done = 0;\n\t\tsize_t remaining = len;\n\n\t\tsize_t lc = 1;\n\t\tsize_t wli = 0;\n\n\t\twhile(true)\n\t\t{\n\t\t\tauto left = st->termWidth - (lc == 1 ? (st->lineIdx == 0 ? st->normPL : st->contPL) : st->wrapPL);\n\t\t\tauto todo = std::min(left, remaining);\n\n\t\t\tif(remaining == left)\n\t\t\t\twli++;\n\n\t\t\tremaining -= todo;\n\t\t\tdone += todo;\n\n\t\t\tif(remaining == 0)\n\t\t\t\tbreak;\n\n\t\t\t// if your cursor is beyond this point, then you are on the next line.\n\t\t\tif(st->cursor >= done + 1)\n\t\t\t{\n\t\t\t\twli++;\n\t\t\t\tlc++;\n\t\t\t}\n\t\t}\n\n\t\treturn wli;\n\t}\n\n\tstatic size_t calculate_nwl(State* st, size_t lineIdx, size_t len)\n\t{\n\t\tauto width = st->termWidth;\n\n\t\tsize_t lines = 1;\n\t\twhile(len > 0)\n\t\t{\n\t\t\tauto left = width - (lines == 1 ? (lineIdx == 0 ? st->normPL : st->contPL) : st->wrapPL);\n\t\t\tif(left == len)\n\t\t\t\tlines += 1;\n\n\t\t\tlen -= std::min(left, len);\n\t\t\tif(len == 0)\n\t\t\t\tbreak;\n\n\t\t\tlines += 1;\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\n\t// returns (linesBelowCursor, finalHcursor)\n\tstatic std::pair<size_t, size_t> _refresh_line(State* st, size_t lineIdx, bool skip_cursor, const std::string& oldLine,\n\t\tbool defer_flush, std::string* commandBuffer)\n\t{\n\t\tstd::string commands;\n\t\tauto qcmd = [&commands](const std::string_view& c) {\n\t\t\tcommands += c;\n\t\t};\n\n\t\tauto flushcmd = [&commands]() {\n\t\t\tplatform_write(commands);\n\t\t\tcommands.clear();\n\t\t};\n\n\n\t\tauto getPromptForLine = [&](size_t wli) -> std::pair<std::string, size_t> {\n\t\t\tif(lineIdx == 0)\n\t\t\t{\n\t\t\t\tif(wli == 0) return { st->promptString, st->normPL };\n\t\t\t\telse         return { st->wrappedPromptString, st->wrapPL };\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif(wli == 0) return { st->contPromptString, st->contPL };\n\t\t\t\telse         return { st->wrappedPromptString, st->wrapPL };\n\t\t\t}\n\t\t};\n\n\n\t\tstd::string_view currentLine = st->lines[lineIdx];\n\n\t\tsize_t numWrappingLines = calculate_nwl(st, st->lineIdx, displayedTextLength(currentLine));\n\n\t\t// if we're operating on the current line, shun bian cache the NWL count.\n\t\t// we'll use this for cursor_down among other things.\n\t\tif(st->lineIdx == lineIdx)\n\t\t\tst->cachedNWLForCurrentLine = numWrappingLines;\n\n\t\tsize_t old_NWL = calculate_nwl(st, st->lineIdx, displayedTextLength(oldLine));\n\n\t\tauto new_wli = calculate_wli(st, st->cursor);\n\n\t\tqcmd(moveCursorLeft(9999));\n\n\t\tztmu_dbg(\"nwl: %zu, old_nwl: %zu, new_wli: %zu, old_wli: %zu\\n\", numWrappingLines, old_NWL, new_wli, st->wrappedLineIdx);\n\n\t\t// what we want to do here is go all the way to the bottom of the string (regardless of cursor position), and clear it.\n\t\t// then go up one line and repeat, basically clearing the whole thing. we don't clear lines above the cursor!\n\t\t{\n\t\t\tauto nwl = std::max(numWrappingLines, old_NWL);\n\n\t\t\tif(numWrappingLines > st->wrappedLineIdx)\n\t\t\t{\n\t\t\t\t// the the current position (just the vcursor):\n\t\t\t\tauto vcursor = getCursorPosition().y;\n\t\t\t\tauto tomove = nwl - st->wrappedLineIdx - 1;\n\n\t\t\t\t// ztmu_dbg(\"height: %zu, vc: %zu, tm: %zu\\n\", st->termHeight, vcursor, tomove);\n\t\t\t\tif(st->termHeight - vcursor < tomove)\n\t\t\t\t{\n\t\t\t\t\tztmu_dbg(\"need to scroll\\n\");\n\t\t\t\t\t// scroll the screen down -- but move the text *up*\n\t\t\t\t\tqcmd(zpr::sprint(\"%s%dS\", CSI, tomove - (st->termHeight - vcursor)));\n\t\t\t\t}\n\n\t\t\t\tqcmd(moveCursorDown(tomove));\n\t\t\t}\n\n\t\t\tfor(size_t i = 1; i < nwl - new_wli; i++)\n\t\t\t{\n\t\t\t\tqcmd(\"\\x1b[2K\");\n\t\t\t\tqcmd(moveCursorUp(1));\n\t\t\t}\n\t\t}\n\n\n\t\t// move to the leftmost position.\n\t\tqcmd(moveCursorLeft(9999));\n\n\t\t{\n\t\t\t// there's stuff on the left of the cursor that we need to print too, since we cleared the entire line.\n\n\t\t\tbool didWrap = false;\n\t\t\tsize_t alrPrinted = 0;\n\n\t\t\t// TODO: we always use normPL here, but we should choose between normPL and contPL!\n\t\t\tauto hcursor = get_cursor_line_offset(st->termWidth, st->cursor, st->normPL, st->wrapPL, &didWrap);\n\t\t\tztmu_dbg(\"didWrap: %d\\n\", didWrap);\n\n\t\t\tif(didWrap)\n\t\t\t{\n\t\t\t\t// we always use new_wli - 1, because we might be moving left-to-right or right-to-left!\n\t\t\t\tauto [ pstr, plen ] = getPromptForLine(new_wli - 1);\n\n\t\t\t\tauto leftCPs = st->termWidth - plen;\n\t\t\t\tauto leftByteCursor = calculate_left_codepoints(leftCPs, currentLine, st->cursor, st->byteCursor).second;\n\t\t\t\tauto leftPortion = currentLine.substr(leftByteCursor, st->byteCursor - leftByteCursor);\n\t\t\t\tcurrentLine.remove_prefix(st->byteCursor);\n\n\t\t\t\t// before proceeding, move the cursor up one, and to the left.\n\t\t\t\tqcmd(moveCursorUp(1));\n\t\t\t\tqcmd(moveCursorLeft(9999));\n\n\t\t\t\tqcmd(pstr);\n\t\t\t\tqcmd(leftPortion);\n\n\t\t\t\t// ok, now move the line down, and print the continuation prompt.\n\t\t\t\tqcmd(moveCursorDown(1));\n\t\t\t\tqcmd(moveCursorLeft(9999));\n\t\t\t\tqcmd(st->wrappedPromptString);\n\n\t\t\t\talrPrinted = st->wrapPL;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto [ pstr, plen ] = getPromptForLine(new_wli);\n\n\t\t\t\tauto leftCPs = hcursor - plen;\n\t\t\t\tauto leftByteCursor = calculate_left_codepoints(leftCPs, currentLine, st->cursor, st->byteCursor).second;\n\n\t\t\t\t// we need to print leftCPs of stuff *before* the current cursor.\n\t\t\t\tauto leftPortion = currentLine.substr(leftByteCursor, st->byteCursor - leftByteCursor);\n\t\t\t\tcurrentLine.remove_prefix(st->byteCursor);\n\n\n\t\t\t\tauto rem = displayedTextLength(currentLine);\n\t\t\t\tztmu_dbg(\"hcursor = %zu, remaining = %zu, bc = %zu, lbc = %zu, len = %zu, line = '%.*s', pr = '%s', plen = %zu\\n\",\n\t\t\t\t\thcursor, rem, st->byteCursor, leftByteCursor, currentLine.length(), static_cast<int>(currentLine.length()),\n\t\t\t\t\tcurrentLine.data(), pstr.c_str(), plen);\n\n\t\t\t\tztmu_dbg(\"leftportion = '%s'\\n\", std::string(leftPortion).c_str());\n\n\t\t\t\tqcmd(pstr);\n\t\t\t\tqcmd(leftPortion);\n\n\t\t\t\talrPrinted = plen + displayedTextLength(leftPortion);\n\t\t\t}\n\n\t\t\tsize_t printedLines = 0;\n\t\t\tsize_t remaining = displayedTextLength(currentLine);\n\n\t\t\t// clear to the right, just in case\n\t\t\tqcmd(zpr::sprint(\"%s0K\", CSI));\n\n\t\t\twhile(remaining > 0)\n\t\t\t{\n\t\t\t\t// ok, now we can print the rest of the string \"normally\".\n\t\t\t\tauto adv_and_cons = [&currentLine](size_t cons) -> std::string_view {\n\t\t\t\t\t// return the view from [here, cons) -- in terms of codepoints\n\t\t\t\t\t// and advance the line by cons codepoints.\n\n\t\t\t\t\tsize_t bytes_to_adv = 0;\n\t\t\t\t\tfor(size_t i = 0; i < cons; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tbytes_to_adv = 1 + findEndOfUTF8CP(reinterpret_cast<const uint8_t*>(currentLine.data()),\n\t\t\t\t\t\t\tbytes_to_adv);\n\t\t\t\t\t}\n\n\t\t\t\t\tauto ret = currentLine.substr(0, bytes_to_adv);\n\t\t\t\t\tcurrentLine.remove_prefix(bytes_to_adv);\n\n\t\t\t\t\treturn ret;\n\t\t\t\t};\n\n\t\t\t\tauto left = st->termWidth - (printedLines == 0 ? alrPrinted : st->wrapPL);\n\t\t\t\tauto todo = std::min(left, remaining);\n\n\t\t\t\tqcmd(adv_and_cons(todo));\n\t\t\t\tremaining -= todo;\n\n\t\t\t\tif(remaining == 0)\n\t\t\t\t{\n\t\t\t\t\t// clear the rest of the line (cursor to end)\n\t\t\t\t\tif(todo != left)\n\t\t\t\t\t\tqcmd(zpr::sprint(\"%s0K\", CSI));\n\n\t\t\t\t\tztmu_dbg(\"broke\\n\");\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// if there's more:\n\t\t\t\t// move the cursor down and left.\n\t\t\t\tqcmd(moveCursorDown(1));\n\t\t\t\tqcmd(moveCursorLeft(9999));\n\n\t\t\t\t// print the wrap prompt.\n\t\t\t\tqcmd(st->wrappedPromptString);\n\t\t\t\tprintedLines += 1;\n\t\t\t}\n\n\t\t\tif(!skip_cursor)\n\t\t\t{\n\t\t\t\t// ok time to move up... we know that we padded with spaces all the way to the edge\n\t\t\t\t// so we can move up by printedLines, and left by width - hcursor\n\t\t\t\tqcmd(moveCursorUp(static_cast<int>(printedLines)));\n\t\t\t\tqcmd(moveCursorLeft(9999));\n\t\t\t\tqcmd(moveCursorRight(hcursor));\n\t\t\t}\n\n\t\t\tztmu_dbg(\"hcursor = %zu\\n\", hcursor);\n\n\t\t\tst->wrappedLineIdx = calculate_wli(st, st->cursor);\n\t\t\tztmu_dbg(\"updated wli: %zu\\n\\n\", st->wrappedLineIdx);\n\n\t\t\tif(defer_flush) *commandBuffer = commands;\n\t\t\telse            flushcmd();\n\n\t\t\treturn std::make_pair(printedLines, hcursor);\n\t\t}\n\t}\n\n\tinline void refresh_line(State* st, std::string* oldLine)\n\t{\n\t\t// refresh the top line manually:\n\n\t\tztmu_dbg(\"\\n\\n** refreshing line %d...\\n\", st->lineIdx);\n\t\tauto [ down, hcursor ] = _refresh_line(st, st->lineIdx, /* skip_cursor: */ false,\n\t\t\toldLine ? *oldLine : st->lines[st->lineIdx], /* defer_flush: */ false, /* cmd_buffer: */ nullptr);\n\n\t\tdown += 1;\n\t\tztmu_dbg(\"down = %zu\\n\", down);\n\n\t\t// this is not re-entrant!!!\n\t\tauto old_wli = st->wrappedLineIdx;\n\t\tauto old_bcr = st->byteCursor;\n\t\tauto old_cur = st->cursor;\n\n\t\tsize_t downAccum = 0;\n\n\t\tstd::string buffer;\n\n\t\t// refresh every line including and after the current line.\n\t\tfor(size_t i = st->lineIdx + 1; i < st->lines.size(); i++)\n\t\t{\n\t\t\tst->wrappedLineIdx = 0;\n\t\t\tst->byteCursor = 0;\n\t\t\tst->cursor = 0;\n\n\t\t\t// see if we need to scroll. note that _refresh_line will scroll for the current line -- ONLY IF IT WRAPS\n\t\t\t// but because we are drawing all lines, we need space for the next line as well.\n\t\t\tif(getCursorPosition().y == static_cast<int>(st->termHeight))\n\t\t\t\tbuffer += zpr::sprint(\"%s1S\", CSI); // one should be enough.\n\n\t\t\tbuffer += moveCursorDown(down);\n\t\t\tdownAccum += down;\n\n\t\t\tztmu_dbg(\"** refreshing line %zu...\\n\", i);\n\n\t\t\tstd::string buf;\n\t\t\tdown = _refresh_line(st, i, /* skip_cursor: */ true, st->lines[i], /* defer_flush: */ true,\n\t\t\t\t&buf).first + 1;\n\n\t\t\tbuffer += buf;\n\n\t\t\tztmu_dbg(\"down = %zu\\n\", down);\n\t\t}\n\n\t\tif(downAccum > 0)\n\t\t{\n\t\t\tplatform_write(zpr::sprint(\"%s%s%s%s\", buffer, moveCursorUp(downAccum), moveCursorLeft(9999),\n\t\t\t\tmoveCursorRight(hcursor)));\n\t\t}\n\n\t\tst->wrappedLineIdx = old_wli;\n\t\tst->byteCursor = old_bcr;\n\t\tst->cursor = old_cur;\n\t}\n\n\n\n\tstatic size_t _calculate_total_nwl_for_all_lines(State* st, size_t startingLineIdx = 0)\n\t{\n\t\tsize_t down = 0;\n\t\tfor(size_t i = startingLineIdx; i < st->lines.size(); i++)\n\t\t\tdown += calculate_nwl(st, i, displayedTextLength(st->lines[i]));\n\n\t\treturn down;\n\t}\n\n\tinline void touch_line(State* st)\n\t{\n\t\t// when we touch the line, we reset the history index.\n\t\tst->historyIdx = 0;\n\t}\n\n\tinline void cursor_home(State* st)\n\t{\n\t\tst->cursor = 0;\n\t\tst->byteCursor = 0;\n\n\t\trefresh_line(st);\n\t\ttouch_line(st);\n\t}\n\n\tinline void cursor_end(State* st, bool refresh)\n\t{\n\t\tst->cursor = displayedTextLength(getCurLine(st));\n\t\tst->byteCursor = getCurLine(st).size();\n\n\t\tif(refresh)\n\t\t\trefresh_line(st);\n\n\t\ttouch_line(st);\n\t}\n\n\n\t// note: internal code doesn't use delete_left or delete_right, so we don't need two\n\t// versions that handle lines.\n\tinline void delete_left(State* st)\n\t{\n\t\ttouch_line(st);\n\t\tif(st->cursor > 0 && getCurLine(st).size() > 0)\n\t\t{\n\t\t\tauto x = st->byteCursor - 1;\n\t\t\tauto l = findBeginningOfUTF8CP(reinterpret_cast<const uint8_t*>(getCurLine(st).c_str()), x);\n\n\t\t\tauto old = getCurLine(st);\n\n\t\t\tgetCurLine(st).erase(l, x - l + 1);\n\t\t\tst->byteCursor -= (x - l + 1);\n\t\t\tst->cursor -= 1;\n\n\t\t\trefresh_line(st, &old);\n\t\t}\n\t\telse if(st->lineIdx > 0)\n\t\t{\n\t\t\tst->lineIdx -= 1;\n\n\t\t\tst->cursor = displayedTextLength(st->lines[st->lineIdx]);\n\t\t\tst->byteCursor = st->lines[st->lineIdx].size();\n\t\t\tst->wrappedLineIdx = calculate_wli(st, st->cursor);\n\n\t\t\t// here's the thing: the remaining pieces of this line needs to be appended\n\t\t\t// to the previous line! (+1 here cos we already -= 1 above)\n\t\t\tauto remaining = st->lines[st->lineIdx + 1];\n\t\t\tst->lines[st->lineIdx].insert(st->byteCursor, remaining);\n\n\t\t\t// before we refresh, we need to go all the way to the bottom and erase the last physical line,\n\t\t\t// so that it won't be lingering later on.\n\t\t\t{\n\t\t\t\tauto down = _calculate_total_nwl_for_all_lines(st, st->lineIdx) - 2;\n\t\t\t\tztmu_dbg(\"** down = %zu\\n\", down);\n\n\t\t\t\t// physical cursor needs to move up one, so move up one more than we moved down.\n\t\t\t\tplatform_write(zpr::sprint(\"%s%s2K%s\", moveCursorDown(down), CSI, moveCursorUp(down + 1)));\n\t\t\t}\n\n\t\t\t// then we need to erase this line from the lines!\n\t\t\tst->lines.erase(st->lines.begin() + st->lineIdx + 1);\n\n\t\t\t// need to refresh.\n\t\t\trefresh_line(st);\n\t\t}\n\t}\n\n\tinline void delete_right(State* st)\n\t{\n\t\ttouch_line(st);\n\t\tif(st->byteCursor < getCurLine(st).size())\n\t\t{\n\t\t\tauto x = st->byteCursor;\n\t\t\tauto l = findEndOfUTF8CP(reinterpret_cast<const uint8_t*>(getCurLine(st).c_str()), x);\n\n\t\t\tauto old = getCurLine(st);\n\n\t\t\tgetCurLine(st).erase(x, l - x + 1);\n\n\t\t\t// both cursors remain unchanged.\n\t\t\trefresh_line(st, &old);\n\t\t}\n\t\telse if(st->lineIdx + 1 < st->lines.size())\n\t\t{\n\t\t\t// we don't move anything. all the text from the next line gets appended to the current line.\n\t\t\tauto nextLine = st->lines[st->lineIdx + 1];\n\t\t\tst->lines[st->lineIdx].insert(st->byteCursor, nextLine);\n\n\t\t\t// before we refresh, we need to go all the way to the bottom and erase the last physical line,\n\t\t\t// so that it won't be lingering later on.\n\t\t\t{\n\t\t\t\tauto down = _calculate_total_nwl_for_all_lines(st, st->lineIdx) - 1;\n\t\t\t\tplatform_write(zpr::sprint(\"%s%s2K%s\", moveCursorDown(down), CSI, moveCursorUp(down)));\n\t\t\t}\n\n\t\t\t// then we need to erase the next line from the lines!\n\t\t\tst->lines.erase(st->lines.begin() + st->lineIdx + 1);\n\n\t\t\t// need to refresh.\n\t\t\trefresh_line(st);\n\t\t}\n\t}\n\n\t// bound to C-k by default\n\tstatic void delete_line_right(State* st)\n\t{\n\t\ttouch_line(st);\n\t\tif(st->byteCursor < st->lines[st->lineIdx].size())\n\t\t{\n\t\t\tst->lines[st->lineIdx].erase(st->byteCursor);\n\t\t\trefresh_line(st);\n\t\t}\n\t\telse if(st->lineIdx + 1 < st->lines.size())\n\t\t{\n\t\t\t// just call delete_right, which will collapse this line.\n\t\t\tdelete_right(st);\n\t\t}\n\t}\n\n\n\n\n\n\n\t// we differentiate between _cursor_left() and cursor_left() -- the latter only moves along\n\t// a single line (\"logical line\"), while the latter will move to the previous line if the current\n\t// line is exhausted. user-inputs call cursor_left(), while internal users should call _cursor_left().\n\n\tstatic void _cursor_left(State* st, size_t n, bool refresh = true)\n\t{\n\t\ttouch_line(st);\n\t\tfor(size_t i = 0; i < n; i++)\n\t\t{\n\t\t\tif(st->cursor > 0)\n\t\t\t{\n\t\t\t\tauto x = st->byteCursor - 1;\n\t\t\t\tauto l = findBeginningOfUTF8CP(reinterpret_cast<const uint8_t*>(getCurLine(st).c_str()), x);\n\t\t\t\tst->byteCursor -= (x - l + 1);\n\t\t\t\tst->cursor -= 1;\n\t\t\t}\n\t\t}\n\n\t\tif(refresh)\n\t\t\trefresh_line(st);\n\t}\n\n\tinline void cursor_left(State* st, bool refresh)\n\t{\n\t\ttouch_line(st);\n\t\tif(st->cursor > 0)\n\t\t{\n\t\t\t_cursor_left(st, 1, refresh);\n\t\t}\n\t\telse if(st->lineIdx > 0)\n\t\t{\n\t\t\tst->lineIdx -= 1;\n\n\t\t\t// physical cursor needs to move up one.\n\t\t\tplatform_write(moveCursorUp(1));\n\n\t\t\tst->cursor = displayedTextLength(st->lines[st->lineIdx]);\n\t\t\tst->byteCursor = st->lines[st->lineIdx].size();\n\t\t\tst->wrappedLineIdx = calculate_wli(st, st->cursor);\n\n\t\t\t// need to refresh.\n\t\t\trefresh_line(st);\n\t\t}\n\t}\n\n\n\t// same deal with _cursor_right as for _cursor_left.\n\tstatic void _cursor_right(State* st, size_t n, bool refresh = true)\n\t{\n\t\ttouch_line(st);\n\t\tfor(size_t i = 0; i < n; i++)\n\t\t{\n\t\t\tif(st->byteCursor < getCurLine(st).size())\n\t\t\t{\n\t\t\t\tauto x = st->byteCursor;\n\t\t\t\tauto l = findEndOfUTF8CP(reinterpret_cast<const uint8_t*>(getCurLine(st).c_str()), x);\n\n\t\t\t\tst->byteCursor += (l - x + 1);\n\t\t\t\tst->cursor += 1;\n\t\t\t}\n\t\t}\n\n\t\tif(refresh)\n\t\t\trefresh_line(st);\n\t}\n\n\tinline void cursor_right(State* st, bool refresh)\n\t{\n\t\ttouch_line(st);\n\t\tif(st->byteCursor < getCurLine(st).size())\n\t\t{\n\t\t\t_cursor_right(st, 1, refresh);\n\t\t}\n\t\telse if(st->lineIdx + 1 < st->lines.size())\n\t\t{\n\t\t\tst->lineIdx += 1;\n\n\t\t\t// physical cursor needs to move down one.\n\t\t\tplatform_write(moveCursorDown(1));\n\n\t\t\tst->cursor = 0;\n\t\t\tst->byteCursor = 0;\n\t\t\tst->wrappedLineIdx = 0;\n\n\t\t\t// need to refresh.\n\t\t\trefresh_line(st);\n\t\t}\n\t}\n\n\n\t// shared stuff that history-manipulating people need to do, basically moving the\n\t// cursor all the way to the end of the text, including the physical cursor.\n\tstatic void _move_cursor_to_end_of_input(State* st)\n\t{\n\t\t// we want the cursor to be at the very end of the last line of input!\n\n\t\t// but first, go to the very beginning, and refresh -- this draws all the lines.\n\t\tst->lineIdx = 0;\n\t\tst->cursor = 0;\n\t\tst->byteCursor = 0;\n\t\tst->wrappedLineIdx = 0;\n\n\t\trefresh_line(st);\n\n\t\t// then we can move to the bottom and refresh again.\n\t\t{\n\t\t\tsize_t down = _calculate_total_nwl_for_all_lines(st) - 1;\n\n\t\t\tplatform_write(moveCursorDown(down));\n\t\t}\n\n\t\tst->cursor = displayedTextLength(st->lines.back());\n\t\tst->byteCursor = convertCursorToByteCursor(st->lines.back().c_str(), st->cursor);\n\n\t\tst->lineIdx = st->lines.size() - 1;\n\t\tst->wrappedLineIdx = calculate_wli(st, st->cursor);\n\n\t\trefresh_line(st);\n\t}\n\n\tinline void cursor_up(State* st)\n\t{\n\t\tif(st->cursor > 0 && st->wrappedLineIdx > 0)\n\t\t{\n\t\t\ttouch_line(st);\n\t\t\tsize_t promptL = st->lineIdx == 0 ? st->normPL : st->contPL;\n\n\t\t\t// first, get the current horz cursor position:\n\t\t\tauto hcursor = get_cursor_line_offset(st->termWidth, st->cursor, promptL, st->wrapPL);\n\n\t\t\t// because wrappedLineIdx > 0, we know we're wrapping. this is the number of chars on the current\n\t\t\t// line (of text!), to the left of the cursor.\n\t\t\tauto h_curlength = hcursor - st->wrapPL;\n\n\t\t\t// this is how many extra chars to go left.\n\t\t\tauto rightmargin = st->termWidth - hcursor;\n\n\t\t\t// this will stop when we can't go further, so there's no need to limit.\n\t\t\t_cursor_left(st, h_curlength + rightmargin);\n\n\t\t\t/*\n\t\t\t\tso what we want to do, ideally, is move \"left\" termWidth number of codepoints. HOWEVER,\n\t\t\t \tif we have such a situation:\n\t\t\t\t * > some long str\n\t\t\t\t | ing\n\t\t\t\t   ^\n\n\t\t\t\tif the cursor is there and we want to go \"up\", what ought to happen is that the cursor gets\n\t\t\t\tmoved to the left extreme -- ie. before the \"s\" in \"some\". we will make and document an\n\t\t\t\tassumption here: all the wrapped prompts are the same length, and the only situation where\n\t\t\t\tyou get this problem is when you move from the second line up to the first line. thus, we\n\t\t\t\tcan use the length of the string, without having to do stupid weird math to figure out\n\t\t\t\thow many chars are on the previous line.\n\t\t\t*/\n\t\t}\n\t\telse if(st->lineIdx > 0)\n\t\t{\n\t\t\ttouch_line(st);\n\n\t\t\t// ok -- we are now into weird strange territory. move up into the previous continuation line...\n\t\t\tztmu_dbg(\"going up...\\n\");\n\n\t\t\tstd::string_view prevLine = st->lines[st->lineIdx - 1];\n\t\t\tsize_t prevLineLen = displayedTextLength(prevLine);\n\n\t\t\t// first, get the current horz cursor position. for the current line, we must always be\n\t\t\t// in a continuation if are able to go upwards.\n\t\t\tauto hcursor = get_cursor_line_offset(st->termWidth, st->cursor, st->contPL, st->wrapPL);\n\n\t\t\t// now, we get the offset of the previous line:\n\t\t\tauto prev_hcursor = get_cursor_line_offset(st->termWidth, prevLineLen,\n\t\t\t\tst->lineIdx > 1 ? st->contPL : st->normPL, st->wrapPL);\n\n\t\t\tauto prev_right_margin = st->termWidth - prev_hcursor;\n\n\t\t\tst->cursor = prevLineLen;\n\t\t\tst->byteCursor = convertCursorToByteCursor(prevLine.data(), st->cursor);\n\t\t\tztmu_dbg(\"c: %zu, bc: %zu, margin: %zu, pl: '%s'\\n\", st->cursor, st->byteCursor,\n\t\t\t\tprev_right_margin, std::string(prevLine).c_str());\n\n\t\t\tst->lineIdx -= 1;\n\t\t\tst->wrappedLineIdx = calculate_wli(st, st->cursor);\n\n\t\t\t// and then we move the cursor.\n\t\t\tplatform_write(moveCursorUp(1));\n\t\t\t_cursor_left(st, st->termWidth - hcursor - prev_right_margin, /* refresh: */ false);\n\t\t\trefresh_line(st);\n\n\t\t\tztmu_dbg(\"c: %zu, bc: %zu, margin: %zu, pl: '%s'\\n\", st->cursor, st->byteCursor,\n\t\t\t\tprev_right_margin, std::string(prevLine).c_str());\n\t\t}\n\t\telse if(st->history.size() > 0 && st->historyIdx < st->history.size())\n\t\t{\n\t\t\tztmu_dbg(\"## history up (%zu)\\n\", st->historyIdx);\n\n\t\t\t// save it, so we can go back to it.\n\t\t\tif(st->historyIdx == 0)\n\t\t\t\tst->savedCurrentInput = st->lines;\n\n\t\t\t// ok, so we're already at the top of the thing, so we should clear the screen from here\n\t\t\t// to the bottom.\n\t\t\tplatform_write(zpr::sprint(\"%s0J\", CSI));\n\n\t\t\t// set the index, set the lines, and refresh.\n\t\t\tst->historyIdx += 1;\n\t\t\tst->lines = st->history[st->history.size() - st->historyIdx];\n\n\t\t\tztmu_dbg(\"setting: \\n\");\n\t\t\tfor(const auto& l : st->lines)\n\t\t\t\tztmu_dbg(\"'%s'\\n\", l);\n\n\t\t\tztmu_dbg(\"\\n\");\n\n\t\t\t_move_cursor_to_end_of_input(st);\n\t\t}\n\t}\n\n\tinline void cursor_down(State* st)\n\t{\n\t\tif(st->byteCursor < getCurLine(st).size() && (st->lines.size() == 1 || st->wrappedLineIdx + 1 < st->cachedNWLForCurrentLine))\n\t\t{\n\t\t\ttouch_line(st);\n\t\t\t// works on a similar principle as cursor_up.\n\n\t\t\tauto hcursor = get_cursor_line_offset(st->termWidth, st->cursor,\n\t\t\t\tst->lineIdx == 0 ? st->normPL : st->contPL, st->wrapPL);\n\n\t\t\t// again, we make a similar assumption -- that only the first and second prompts can differ; the second and\n\t\t\t// subsequent wrapping prompts must have the same length.\n\n\t\t\tauto rightmargin = st->termWidth - hcursor;\n\n\t\t\t// in the next line, the prompt will always be a wrapping prompt.\n\t\t\tauto leftmargin = hcursor - st->wrapPL;\n\n\t\t\t_cursor_right(st, rightmargin + leftmargin);\n\t\t}\n\t\telse if(st->lineIdx + 1 < st->lines.size())\n\t\t{\n\t\t\ttouch_line(st);\n\n\t\t\tztmu_dbg(\"going down...\\n\");\n\n\t\t\tstd::string_view nextLine = st->lines[st->lineIdx + 1];\n\t\t\tsize_t nextLineLen = displayedTextLength(nextLine);\n\n\t\t\t// first, get the current horz cursor position:\n\t\t\tauto hcursor = get_cursor_line_offset(st->termWidth, st->cursor,\n\t\t\t\tst->lineIdx == 0 ? st->normPL:  st->contPL, st->wrapPL);\n\n\t\t\t// ok, the next line will definitely be a continuation prompt. so, see how many chars into the line\n\t\t\t// we'll actually put ourselves -- and handle the edge case of negative values!\n\t\t\tauto next_leftChars = (hcursor < st->contPL\n\t\t\t\t? 0     // snap to the beginning of the line, then.\n\t\t\t\t: std::min(hcursor - st->contPL, nextLineLen)\n\t\t\t);\n\n\t\t\t// ok, time to do the real work.\n\t\t\tst->cursor = next_leftChars;\n\t\t\tst->byteCursor = convertCursorToByteCursor(nextLine.data(), st->cursor);\n\t\t\tst->lineIdx += 1;\n\n\t\t\t// now move the cursor and refresh!\n\t\t\tplatform_write(moveCursorDown(1));\n\t\t\trefresh_line(st);\n\t\t}\n\t\telse if(st->historyIdx > 0)\n\t\t{\n\t\t\tztmu_dbg(\"## history down (%zu)\\n\", st->historyIdx);\n\n\t\t\t// somewhat similar to moving up in history. first, we will already be at the bottom of\n\t\t\t// all lines. so, we need to move the physical and virtual cursor to the top of the entire\n\t\t\t// input. to do this, calculate the total NWL of all lines:\n\t\t\t{\n\t\t\t\t// we must do this for the current input state, before we change into the history.\n\t\t\t\tauto up = _calculate_total_nwl_for_all_lines(st) - 1;\n\n\t\t\t\t// as we move up, we must clear the entire line, to get rid of the lingering text.\n\t\t\t\tfor(size_t i = 0; i < up; i++)\n\t\t\t\t{\n\t\t\t\t\tplatform_write(zpr::sprint(\"%s2K\", CSI));\n\t\t\t\t\tplatform_write(moveCursorUp(1));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// ok, now we can change:\n\t\t\tst->historyIdx -= 1;\n\t\t\tif(st->historyIdx == 0) st->lines = st->savedCurrentInput, st->savedCurrentInput.clear();\n\t\t\telse                    st->lines = st->history[st->history.size() - st->historyIdx];\n\n\t\t\t// now, fix it.\n\t\t\t_move_cursor_to_end_of_input(st);\n\t\t}\n\t}\n\n\n\n\n\n\t// this is ugly!!!\n\tinline bool read_line(State* st, int promptMode, std::string seed)\n\t{\n\t\tconstexpr char CTRL_A       = '\\x01';\n\t\tconstexpr char CTRL_C       = '\\x03';\n\t\tconstexpr char CTRL_D       = '\\x04';\n\t\tconstexpr char CTRL_E       = '\\x05';\n\t\tconstexpr char CTRL_H       = '\\x08';\n\t\tconstexpr char CTRL_K       = '\\x0B';\n\t\tconstexpr char ENTER        = '\\x0D';\n\t\tconstexpr char BACKSPACE    = '\\x7F';\n\n\t\t// NOT THREAD SAFE!!\n\t\tenterRawMode();\n\t\tcurrentStateForSignal = st;\n\t\tst->termWidth = getTerminalWidth();\n\t\tst->termHeight = getTerminalHeight();\n\n\t\tst->wrappedLineIdx = 0;\n\t\t{\n\t\t\t// TODO: fix this. probably pull out calc_wli from the refresh function.\n\t\t\t// if your seed exceeds the terminal width, then you deserve it.\n\t\t\tst->lines.push_back(seed);\n\t\t\tst->cursor = seed.size();\n\t\t\tst->byteCursor = convertCursorToByteCursor(seed.c_str(), st->cursor);\n\t\t}\n\n\t\tplatform_write(promptMode == 0 ? st->promptString : st->contPromptString);\n\t\tplatform_write(seed);\n\n\t\tbool didSetSignalHandler = setup_sigwinch();\n\n\n\t\tauto commit_line = [&](bool refresh = true) {\n\t\t\t// move the cursor to the end, refresh the line, then leave raw mode -- this makes sure\n\t\t\t// that we leave the cursor in a nice place after the call to this function returns.\n\t\t\tcursor_end(st, refresh);\n\n\t\t\t// see how many lines we need to go down.\n\t\t\tsize_t down = 0;\n\t\t\tfor(size_t i = st->lineIdx + 1; i < st->lines.size(); i++)\n\t\t\t\tdown += calculate_nwl(st, i, displayedTextLength(st->lines[i]));\n\n\t\t\tplatform_write(moveCursorDown(down));\n\t\t\tplatform_write(moveCursorLeft(9999));\n\t\t};\n\n\t\tst->wasAborted = false;\n\n\t\tbool eof = false;\n\t\twhile(true)\n\t\t{\n\t\t// lol\n\t\tloop_top:\n\n\t\t\tchar c = 0;\n\t\t\tif(platform_read_one(&c) <= 0)\n\t\t\t\tbreak;\n\n\t\t\tztmu_dbg(\"[%d]\", static_cast<int>(c));\n\t\t\tswitch(c)\n\t\t\t{\n\t\t\t\tcase CTRL_C: {\n\t\t\t\t\tst->wasAborted = true;\n\n\t\t\t\t\tif(st->lines.size() == 1 && st->lines[0].empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tif(st->emptyCtrlCExits)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tst->wasAborted = true;\n\t\t\t\t\t\t\teof = true;\n\t\t\t\t\t\t\tgoto finish;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tplatform_write(st->uselessControlCMsg);\n\t\t\t\t\t\t\tgoto finish_now;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tcommit_line(/* refresh: */ false);\n\n\t\t\t\t\t\t// if we are multi-line, we can return eof. if not, just return empty.\n\t\t\t\t\t\tif(st->lines.size() > 1)\n\t\t\t\t\t\t\teof = true;\n\n\t\t\t\t\t\tst->clear();\n\n\t\t\t\t\t\t// to prevent fuckery, we need to add an empty line back in!\n\t\t\t\t\t\tst->lines.push_back(\"\");\n\t\t\t\t\t\tgoto finish_now;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// this is a little complex; control-D is apparently both EOF: when the buffer is empty,\n\t\t\t\t// and delete-left: when it is not...\n\t\t\t\tcase CTRL_D: {\n\t\t\t\t\t// if the buffer is empty, then quit.\n\t\t\t\t\tif(getCurLine(st).empty() && st->lineIdx == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tst->wasAborted = true;\n\n\t\t\t\t\t\teof = true;\n\t\t\t\t\t\tgoto finish;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tdelete_right(st);\n\t\t\t\t\t}\n\t\t\t\t} break;\n\n\n\n\t\t\t\tcase CTRL_A: {\n\t\t\t\t\tcursor_home(st);\n\t\t\t\t} break;\n\n\t\t\t\tcase CTRL_E: {\n\t\t\t\t\tcursor_end(st);\n\t\t\t\t} break;\n\n\t\t\t\t// backspace\n\t\t\t\tcase CTRL_H: [[fallthrough]];\n\t\t\t\tcase BACKSPACE: {\n\t\t\t\t\tdelete_left(st);\n\t\t\t\t} break;\n\n\t\t\t\tcase CTRL_K: {\n\t\t\t\t\t// delete to end of line.\n\t\t\t\t\tdelete_line_right(st);\n\t\t\t\t} break;\n\n\t\t\t\t// enter\n\t\t\t\tcase ENTER: {\n\t\t\t\t\tif(auto fn = st->keyHandlers[Key::ENTER]; fn)\n\t\t\t\t\t{\n\t\t\t\t\t\tauto res = fn(st, Key::ENTER);\n\t\t\t\t\t\tswitch(res)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase HandlerAction::CONTINUE:\n\t\t\t\t\t\t\t\tgoto loop_top;\n\n\t\t\t\t\t\t\tcase HandlerAction::QUIT:\n\t\t\t\t\t\t\t\teof = true;\n\t\t\t\t\t\t\t\tgoto finish;\n\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tgoto finish;\n\t\t\t\t}\n\n\n\n\t\t\t\t// time for some fun.\n\t\t\t\tcase ESC: {\n\t\t\t\t\t// there should be at least two more!\n\t\t\t\t\tchar seq[2]; platform_read(seq, 2);\n\t\t\t\t\tchar thing = 0;\n\t\t\t\t\tif(seq[0] == '[')\n\t\t\t\t\t{\n\t\t\t\t\t\tif(seq[1] >= '0' && seq[1] <= '9')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint n = 0;\n\n\t\t\t\t\t\t\t// ok now time to read until a ~\n\t\t\t\t\t\t\tchar x = seq[1];\n\t\t\t\t\t\t\twhile(x >= '0' && x <= '9')\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tn = (10 * n) + (x - '0');\n\t\t\t\t\t\t\t\tplatform_read_one(&x);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// we have a modifier -- for now, ignore them.\n\t\t\t\t\t\t\tif(x == ';')\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// advance it.\n\t\t\t\t\t\t\t\tplatform_read_one(&x);\n\n\t\t\t\t\t\t\t\tint mods = 0;\n\t\t\t\t\t\t\t\twhile(x >= '0' && x <= '9')\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tmods = (10 * mods) + (x - '0');\n\t\t\t\t\t\t\t\t\tplatform_read_one(&x);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tthing = x;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tthing = static_cast<char>(n);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif(n == 200)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tztmu_dbg(\"PASTE!\\n\");\n\n\t\t\t\t\t\t\t\t// keep reading until we find an esc.\n\t\t\t\t\t\t\t\tstd::string pasted;\n\n\t\t\t\t\t\t\t\tchar x = 0;\n\t\t\t\t\t\t\t\twhile(platform_read_one(&x) > 0)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tpasted += x;\n\t\t\t\t\t\t\t\t\tif(pasted.rfind(\"\\x1b[201~\") != std::string::npos)\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// get rid of the thing at the end.\n\t\t\t\t\t\t\t\tpasted.erase(pasted.rfind(\"\\x1b[201~\"));\n\n\t\t\t\t\t\t\t\tztmu_dbg(\"PASTED: '%s'\\n\", pasted);\n\n\t\t\t\t\t\t\t\tauto oldline = getCurLine(st);\n\n\t\t\t\t\t\t\t\tauto len = displayedTextLength(pasted);\n\n\t\t\t\t\t\t\t\tgetCurLine(st).insert(st->byteCursor, pasted);\n\n\t\t\t\t\t\t\t\tst->cursor += len;\n\t\t\t\t\t\t\t\tst->byteCursor += pasted.size();\n\n\t\t\t\t\t\t\t\tztmu_dbg(\"c: %zu, bc: %zu\\n\", st->cursor, st->byteCursor);\n\n\n\t\t\t\t\t\t\t\trefresh_line(st, &oldline);\n\n\t\t\t\t\t\t\t\tgoto loop_top;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tthing = seq[1];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tswitch(thing)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase 3: delete_right(st); break;\n\n\t\t\t\t\t\t\tcase 1: cursor_home(st); break;\n\t\t\t\t\t\t\tcase 7: cursor_home(st); break;\n\n\t\t\t\t\t\t\tcase 4: cursor_end(st); break;\n\t\t\t\t\t\t\tcase 8: cursor_end(st); break;\n\n\t\t\t\t\t\t\tcase 'A': cursor_up(st); break;\n\t\t\t\t\t\t\tcase 'B': cursor_down(st); break;\n\t\t\t\t\t\t\tcase 'C': cursor_right(st); break;\n\t\t\t\t\t\t\tcase 'D': cursor_left(st); break;\n\t\t\t\t\t\t\tcase 'H': cursor_home(st); break;\n\t\t\t\t\t\t\tcase 'F': cursor_end(st); break;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if(seq[0] == 'O')\n\t\t\t\t\t{\n\t\t\t\t\t\tif(seq[1] == 'H')       cursor_home(st);\n\t\t\t\t\t\telse if(seq[1] == 'F')  cursor_end(st);\n\t\t\t\t\t}\n\n\t\t\t\t} break;\n\n\t\t\t\t// default: just append -- if it's not a control char.\n\t\t\t\tdefault: {\n\t\t\t\t\tauto old = getCurLine(st);\n\n\t\t\t\t\tuint8_t uc = static_cast<uint8_t>(c);\n\n\t\t\t\t\t// also: for handlers, we don't bother about giving you codepoints, so... tough luck.\n\t\t\t\t\t// TODO.\n\t\t\t\t\tif(auto fn = st->keyHandlers[static_cast<Key>(uc)]; fn)\n\t\t\t\t\t{\n\t\t\t\t\t\tswitch(fn(st, static_cast<Key>(uc)))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase HandlerAction::CONTINUE:\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase HandlerAction::QUIT: eof = true; [[fallthrough]];\n\t\t\t\t\t\t\tcase HandlerAction::RETURN: [[fallthrough]];\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tgoto finish;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(uc >= 0x20 && uc <= 0x7F)\n\t\t\t\t\t{\n\t\t\t\t\t\tgetCurLine(st).insert(getCurLine(st).begin() + st->byteCursor, c);\n\n\t\t\t\t\t\tst->cursor += 1;\n\t\t\t\t\t\tst->byteCursor += 1;\n\t\t\t\t\t}\n\t\t\t\t\telse if(uc >= 0x20)\n\t\t\t\t\t{\n\t\t\t\t\t\tstd::string cp;\n\t\t\t\t\t\tcp += c;\n\n\t\t\t\t\t\t// if it's unicode, then try and read even more.\n\t\t\t\t\t\t// see: https://en.wikipedia.org/wiki/UTF-8 for the bitmasks we're using.\n\t\t\t\t\t\tif((uc & 0xE0) == 0xC0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// one extra byte\n\t\t\t\t\t\t\tchar c = 0; platform_read_one(&c);\n\t\t\t\t\t\t\tcp += c;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if((uc & 0xF0) == 0xE0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// two extra bytes\n\t\t\t\t\t\t\tchar buf[2]; platform_read(buf, 2);\n\t\t\t\t\t\t\tcp += buf;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if((uc & 0xF8) == 0xF0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// three extra bytes\n\t\t\t\t\t\t\tchar buf[3]; platform_read(buf, 3);\n\t\t\t\t\t\t\tcp += buf;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tgetCurLine(st).insert(st->byteCursor, cp);\n\n\t\t\t\t\t\tst->byteCursor += cp.size();\n\t\t\t\t\t\tst->cursor += displayedTextLength(cp);\n\t\t\t\t\t}\n\n\t\t\t\t\trefresh_line(st, &old);\n\t\t\t\t} break;\n\t\t\t}\n\t\t}\n\n\n\n\n\tfinish:\n\t\tcommit_line();\n\n\tfinish_now:\n\t\t// restore the signal state, and reset the terminal to normal mode.\n\t\tcurrentStateForSignal = 0;\n\t\tif(didSetSignalHandler)\n\t\t\trestore_sigwinch();\n\n\t\tleaveRawMode();\n\n\t\tplatform_write(\"\\n\");\n\t\treturn eof;\n\t}\n\n\tstd::vector<std::string> pretty_print_text_block(const std::vector<std::string>& paragraphs, const char* leftMargin,\n\t\tconst char* rightMargin, size_t maxLines)\n\t{\n\t\tauto split_words = [](const std::string& s) -> std::vector<std::string_view> {\n\t\t\tstd::vector<std::string_view> ret;\n\n\t\t\tsize_t word_start = 0;\n\t\t\tfor(size_t i = 0; i < s.size(); i++)\n\t\t\t{\n\t\t\t\tif(s[i] == ' ')\n\t\t\t\t{\n\t\t\t\t\tret.push_back(std::string_view(s.c_str() + word_start, i - word_start));\n\t\t\t\t\tword_start = i + 1;\n\t\t\t\t}\n\t\t\t\telse if(s[i] == '-')\n\t\t\t\t{\n\t\t\t\t\tret.push_back(std::string_view(s.c_str() + word_start, i - word_start + 1));\n\t\t\t\t\tword_start = i + 1;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tret.push_back(std::string_view(s.c_str() + word_start));\n\t\t\treturn ret;\n\t\t};\n\n\t\tauto tw = ztmu::getTerminalWidth();\n\t\ttw = std::min(tw, tw - strlen(leftMargin) - strlen(rightMargin));\n\n\t\tauto disp_len = ztmu::displayedTextLength;\n\n\t\tstd::vector<std::string> output;\n\n\t\tsize_t lines = 1;\n\t\tsize_t paras = 0;\n\t\tfor(auto& l : paragraphs)\n\t\t{\n\t\t\tsize_t remaining = tw;\n\n\t\t\t// sighs.\n\t\t\tauto ss = std::stringstream();\n\t\t\tss << leftMargin;\n\n\t\t\t// each \"line\" is actually a paragraph. we want to be nice, so pad on the right by a few spaces\n\t\t\t// and hyphenate split words.\n\n\t\t\t// first split into words\n\t\t\tauto words = split_words(l);\n\t\t\tfor(const auto& word : words)\n\t\t\t{\n\t\t\t\tif(maxLines > 0 && lines == maxLines && remaining <= word.size() + 4)\n\t\t\t\t{\n\t\t\t\t\t// don't. just quit.\n\t\t\t\t\tss << \"...\";\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tauto len = disp_len(word);\n\t\t\t\tif(remaining >= len)\n\t\t\t\t{\n\t\t\t\t\tss << word << (word.back() != '-' ? \" \" : \"\");\n\n\t\t\t\t\tremaining -= len;\n\n\t\t\t\t\tif(remaining > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tremaining -= 1;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tss << \"\\n\" << leftMargin;\n\t\t\t\t\t\tlines++;\n\n\t\t\t\t\t\tremaining = tw;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(remaining < 3 || len < 5)\n\t\t\t\t{\n\t\t\t\t\t// for anything less than 5 chars, put it on the next line -- don't hyphenate.\n\t\t\t\t\tss << \"\\n\" << leftMargin << word << (word.back() != '-' ? \" \" : \"\");\n\n\t\t\t\t\tremaining = tw - (len + 1);\n\t\t\t\t\tlines++;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tauto thisline = remaining - 2;\n\n\t\t\t\t\t// if we end up making a fragment 3 letters or shorter,\n\t\t\t\t\t// push it to the next line instead.\n\t\t\t\t\tif(std::min(word.size(), thisline ) <= 3)\n\t\t\t\t\t{\n\t\t\t\t\t\tthisline = 0;\n\t\t\t\t\t\tss << \"\\n\" << leftMargin << word << (word.back() != '-' ? \" \" : \"\");\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// split it.\n\t\t\t\t\t\tss << word.substr(0, thisline) << \"-\" << \"\\n\";\n\t\t\t\t\t\tss << leftMargin << word.substr(thisline) << \" \";\n\t\t\t\t\t}\n\n\t\t\t\t\tremaining = tw - word.substr(thisline).size();\n\n\t\t\t\t\tlines++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\toutput.push_back(ss.str());\n\n\t\t\t// if the paragraph has some space remaining at the end, then\n\t\t\t// don't print the next one, just stop here.\n\t\t\tif(maxLines > 0 && lines == maxLines && paras < paragraphs.size())\n\t\t\t\tbreak;\n\n\t\t\tparas++;\n\t\t}\n\n\t\treturn output;\n\t}\n}\n}\n#endif\n\n\n\nnamespace ztmu\n{\n\tinline std::vector<std::string> prettyFormatTextBlock(const std::vector<std::string>& paragraphs, const char* leftMargin,\n\t\tconst char* rightMargin, size_t maxLines)\n\t{\n\t\treturn detail::pretty_print_text_block(paragraphs, leftMargin, rightMargin, maxLines);\n\t}\n\n\tinline std::vector<std::string> prettyFormatTextBlock(const std::string& block, const char* leftMargin,\n\t\tconst char* rightMargin, size_t maxLines)\n\t{\n\t\tauto splitString = [](std::string_view view, char delim = '\\n') -> std::vector<std::string_view> {\n\n\t\t\tstd::vector<std::string_view> ret;\n\n\t\t\twhile(true)\n\t\t\t{\n\t\t\t\tsize_t ln = view.find(delim);\n\n\t\t\t\tif(ln != std::string_view::npos)\n\t\t\t\t{\n\t\t\t\t\tret.emplace_back(view.data(), ln);\n\t\t\t\t\tview.remove_prefix(ln + 1);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// account for the case when there's no trailing newline, and we still have some stuff stuck in the view.\n\t\t\tif(!view.empty())\n\t\t\t\tret.emplace_back(view.data(), view.length());\n\n\t\t\treturn ret;\n\t\t};\n\n\t\tstd::vector<std::string> paragraphs;\n\t\tauto splits = splitString(block);\n\t\tfor(auto sv : splits)\n\t\t{\n\t\t\tauto s = std::string(sv);\n\t\t\ts.erase(std::remove(s.begin(), s.end(), '\\r'));\n\n\t\t\tif(!s.empty())\n\t\t\t\tparagraphs.push_back(s);\n\t\t}\n\n\t\treturn detail::pretty_print_text_block(paragraphs, leftMargin, rightMargin, maxLines);\n\t}\n\n\tinline size_t displayedTextLength(const std::string_view& str)\n\t{\n\t\treturn detail::displayedTextLength(str);\n\t}\n\n\tinline size_t getTerminalWidth()\n\t{\n\t\treturn detail::getTerminalWidth();\n\t}\n\n\tinline void State::setupConsole()\n\t{\n\t\tdetail::setup_console();\n\t}\n\n\tinline void State::unsetupConsole()\n\t{\n\t\tdetail::unsetup_console();\n\t}\n\n\tinline void State::clear()\n\t{\n\t\t// reset the thing.\n\t\tthis->savedCurrentInput.clear();\n\t\tthis->lines.clear();\n\t\tthis->lineIdx = 0;\n\n\t\tthis->cachedNWLForCurrentLine = 0;\n\t\tthis->wrappedLineIdx = 0;\n\n\t\t// we call clear on commit, so the history index needs to go back to 0.\n\t\tthis->historyIdx = 0;\n\t}\n\n\tinline void State::setPrompt(const std::string& prompt)\n\t{\n\t\tthis->promptString = prompt;\n\t\tthis->normPL = detail::displayedTextLength(prompt);\n\t}\n\n\tinline void State::setContPrompt(const std::string& prompt)\n\t{\n\t\tthis->contPromptString = prompt;\n\t\tthis->contPL = detail::displayedTextLength(prompt);\n\t}\n\n\tinline void State::setWrappedPrompt(const std::string& prompt)\n\t{\n\t\tthis->wrappedPromptString = prompt;\n\t\tthis->wrapPL = detail::displayedTextLength(prompt);\n\t}\n\n\tinline void State::move_cursor_left(int n)\n\t{\n\t\tif(n < 0)   move_cursor_right(-n);\n\n\t\tfor(int i = 0; i < n; i++)\n\t\t\tdetail::cursor_left(this, /* refresh: */ false);\n\n\t\tdetail::refresh_line(this);\n\t}\n\n\tinline void State::move_cursor_right(int n)\n\t{\n\t\tif(n < 0)   move_cursor_left(-n);\n\n\t\tfor(int i = 0; i < n; i++)\n\t\t\tdetail::cursor_right(this, /* refresh: */ false);\n\n\t\tdetail::refresh_line(this);\n\t}\n\n\tinline void State::move_cursor_up(int n)\n\t{\n\t\tif(n < 0)   move_cursor_down(-n);\n\n\t\tfor(int i = 0; i < n; i++)\n\t\t\tdetail::cursor_up(this);\n\n\t\tdetail::refresh_line(this);\n\t}\n\n\tinline void State::move_cursor_down(int n)\n\t{\n\t\tif(n < 0)   move_cursor_up(-n);\n\n\t\tfor(int i = 0; i < n; i++)\n\t\t\tdetail::cursor_down(this);\n\n\t\tdetail::refresh_line(this);\n\t}\n\n\n\tinline void State::move_cursor_home()\n\t{\n\t\tdetail::cursor_home(this);\n\t}\n\n\tinline void State::move_cursor_end()\n\t{\n\t\tdetail::cursor_end(this);\n\t}\n\n\tinline void State::delete_left(int n)\n\t{\n\t\tif(n <= 0) return;\n\n\t\tfor(int i = 0; i < n; i++)\n\t\t\tdetail::delete_left(this);\n\t}\n\n\tinline void State::delete_right(int n)\n\t{\n\t\tif(n <= 0) return;\n\n\t\tfor(int i = 0; i < n; i++)\n\t\t\tdetail::delete_right(this);\n\t}\n\n\tinline void State::setKeyHandler(Key k, std::function<HandlerAction (State*, Key)> handler)\n\t{\n\t\tthis->keyHandlers[k] = handler;\n\t}\n\n\tinline void State::unsetKeyHandler(Key k)\n\t{\n\t\tthis->keyHandlers[k] = std::function<HandlerAction (State*, Key)>();\n\t}\n\n\tinline std::string State::getCurrentLine()\n\t{\n\t\treturn this->lines[this->lineIdx];\n\t}\n\n\tinline void State::setCurrentLine(const std::string& s)\n\t{\n\t\tauto old = this->lines[this->lineIdx];\n\t\tthis->lines[this->lineIdx] = s;\n\n\t\t// we need to ensure the cursors are updated!\n\t\tthis->cursor = std::min(this->cursor, detail::displayedTextLength(s));\n\t\tthis->byteCursor = detail::convertCursorToByteCursor(s.c_str(), this->cursor);\n\n\t\tdetail::refresh_line(this, &old);\n\t}\n\n\tinline void State::useUniqueHistory(bool enable)\n\t{\n\t\tthis->uniqueHistory = enable;\n\t}\n\n\t// your responsibility to check if the input was empty!\n\t// well if you unique it then you'll only get one empty history entry, but still.\n\tinline void State::addPreviousInputToHistory()\n\t{\n\t\tif(this->wasAborted)\n\t\t\treturn;\n\n\t\t// now, if we need to unique the history, then erase (if any) the\n\t\t// prior occurrence of that item. we shouldn't really need to check for more\n\t\t// than one, because any previous call to addHistory() should have already\n\t\t// left us with at most two.\n\n\t\t// obviously, we check for dupes before adding the current entry, because then we'll\n\t\t// just end up erasing the new entry like an idiot.\n\t\tif(auto it = std::find(this->history.begin(), this->history.end(), this->lines); it != this->history.end())\n\t\t\tthis->history.erase(it);\n\n\t\t// this must be called before the next invocation of read() or readContinuation()\n\t\t// so that State->lines is still preserved.\n\t\tthis->history.push_back(this->lines);\n\t}\n\n\tinline void State::loadHistory(const std::vector<std::vector<std::string>>& h)\n\t{\n\t\tthis->historyIdx = 0;\n\t\tthis->history = h;\n\t}\n\n\t// it's up to you to serialise it!\n\tinline std::vector<std::vector<std::string>> State::getHistory()\n\t{\n\t\treturn this->history;\n\t}\n\n\tinline void State::setMessageOnControlC(const std::string& msg)\n\t{\n\t\tthis->uselessControlCMsg = msg;\n\t}\n\n\tinline void State::enableExitOnEmptyControlC()\n\t{\n\t\tthis->emptyCtrlCExits = true;\n\t}\n\n\tinline std::optional<std::string> State::read()\n\t{\n\t\t// clear.\n\t\tthis->clear();\n\t\tbool eof = detail::read_line(this, /* promptMode: */ 0, \"\");\n\n\t\tif(eof) return std::nullopt;\n\t\telse    return this->lines.back();\n\t}\n\n\tinline std::optional<std::vector<std::string>> State::readContinuation(const std::string& seed)\n\t{\n\t\t// don't clear\n\t\tthis->lineIdx++;\n\n\t\tbool eof = detail::read_line(this, /* promptMode: */ 1, seed);\n\n\t\tif(eof) return std::nullopt;\n\t\telse    return this->lines;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/main.cpp",
    "content": "// main.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"defs.h\"\n#include \"repl.h\"\n#include \"errors.h\"\n#include \"backend.h\"\n#include \"frontend.h\"\n\n#include \"ir/module.h\"\n#include \"ir/interp.h\"\n\n#include \"memorypool.h\"\n#include \"allocator.h\"\n\n#include <chrono>\n\n\nstruct timer\n{\n\tusing hrc = std::chrono::high_resolution_clock;\n\n\ttimer() : out(nullptr)              { start = hrc::now(); }\n\texplicit timer(double* t) : out(t)  { start = hrc::now(); }\n\t~timer()                            { if(out) *out = static_cast<double>((hrc::now() - start).count()) / 1000000.0; }\n\tdouble measure()                    { return static_cast<double>((hrc::now() - start).count()) / 1000000.0; }\n\n\tdouble* out = 0;\n\tstd::chrono::time_point<hrc> start;\n};\n\n\nstatic void compile(std::string in, std::string out)\n{\n\tauto start_time = std::chrono::high_resolution_clock::now();\n\n\tdouble lexer_ms     = 0;\n\tdouble parser_ms    = 0;\n\tdouble typecheck_ms = 0;\n\tdouble codegen_ms   = 0;\n\n\ttimer total;\n\n\tauto printStats = [&total](const std::string& name) {\n\t\tif(frontend::getPrintProfileStats())\n\t\t{\n\t\t\tdebuglogln(\"%-9s (%.1f ms)\\t[w: %.1fk, f: %.1fk, a: %.1fk]\", name, total.measure(), mem::getWatermark() / 1024.0,\n\t\t\t\tmem::getDeallocatedCount() / 1024.0, mem::getAllocatedCount() / 1024.0);\n\t\t}\n\t};\n\n\n\tauto cd = backend::CompiledData();\n\t{\n\t\tfrontend::CollectorState state;\n\t\tsst::DefinitionTree* dtree = 0;\n\n\t\t{\n\t\t\ttimer t(&lexer_ms);\n\t\t\tfrontend::collectFiles(in, &state);\n\t\t\tprintStats(\"lex\");\n\t\t}\n\n\t\t{\n\t\t\ttimer t(&parser_ms);\n\t\t\tfrontend::parseFiles(&state);\n\t\t\tprintStats(\"parse\");\n\t\t}\n\n\t\t{\n\t\t\ttimer t(&typecheck_ms);\n\t\t\tdtree = frontend::typecheckFiles(&state);\n\t\t\tprintStats(\"typecheck\");\n\t\t}\n\n\t\t{\n\t\t\ttimer t(&codegen_ms);\n\t\t\ticeAssert(dtree);\n\n\t\t\tauto module = frontend::generateFIRModule(&state, dtree);\n\t\t\tmodule->finaliseGlobalConstructors();\n\t\t\tprintStats(\"codegen\");\n\n\t\t\t// if we requested to dump, then dump the IR here.\n\t\t\tif(frontend::getPrintFIR())\n\t\t\t\tfprintf(stderr, \"%s\\n\", module->print().c_str());\n\n\n\t\t\tcd.module = module;\n\t\t}\n\n\n\t\t// delete *most* of the memory we've allocated. obviously IR values need to stay alive,\n\t\t// since we haven't run the backend yet. so this just kills the AST and SST values.\n\t\tutil::clearAllPools();\n\t\tprintStats(\"free_mem\");\n\n\n\t\t// print the final stats.\n\t\tif(frontend::getPrintProfileStats())\n\t\t{\n\t\t\tauto compile_ms = static_cast<double>((std::chrono::high_resolution_clock::now() - start_time).count()) / 1000.0 / 1000.0;\n\n\n\t\t\tdebuglogln(\"%-9s (%.1f ms)\\t[lex: %.1f, parse: %.1f, typechk: %.1f, codegen: %.1f]\", \"compile\",\n\t\t\t\tcompile_ms, lexer_ms, parser_ms, typecheck_ms, codegen_ms);\n\n\t\t\tdebuglogln(\"processed: %d lines, %.2f loc/s, %d fir values\\n\", state.totalLinesOfCode,\n\t\t\t\tstatic_cast<double>(state.totalLinesOfCode) / (compile_ms / 1000.0),\n\t\t\t\tfir::Value::getCurrentValueId());\n\t\t}\n\t}\n\n\ticeAssert(cd.module);\n\n\n\n\n\t{\n\t\t#if !OS_DARWIN\n\t\t\tif(frontend::getFrameworksToLink().size() > 0 || frontend::getFrameworkSearchPaths().size() > 0)\n\t\t\t\terror(\"backend: frameworks are only supported on Darwin\");\n\t\t#endif\n\n\n\t\tusing namespace backend;\n\t\tBackend* backend = Backend::getBackendFromOption(frontend::getBackendOption(), cd, { in }, out);\n\t\tif(backend == 0) return;\n\n\t\tint _capsneeded = 0;\n\t\t{\n\t\t\tif(frontend::getOutputMode() == ProgOutputMode::RunJit)\n\t\t\t\t_capsneeded |= BackendCaps::JIT;\n\n\t\t\tif(frontend::getOutputMode() == ProgOutputMode::ObjectFile)\n\t\t\t\t_capsneeded |= BackendCaps::EmitObject;\n\n\t\t\tif(frontend::getOutputMode() == ProgOutputMode::Program)\n\t\t\t\t_capsneeded |= BackendCaps::EmitProgram;\n\t\t}\n\t\tauto capsneeded = static_cast<BackendCaps::Capabilities>(_capsneeded);\n\n\n\t\tif(backend->hasCapability(capsneeded))\n\t\t{\n\t\t\tbackend->performCompilation();\n\t\t\tbackend->optimiseProgram();\n\t\t\tbackend->writeOutput();\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(\"selected backend '%s' does not have some required capabilities (missing %s)\\n\", backend->str(),\n\t\t\t\tcapabilitiesToString(capsneeded));\n\t\t}\n\t}\n}\n\n\n\nint main(int argc, char** argv)\n{\n\tplatform::setupCrashHandlers();\n\tplatform::setupTerminalIfNecessary();\n\tplatform::compiler::performSelfDlOpen();\n\n\tauto [ input_file, output_file ] = frontend::parseCmdLineOpts(argc, argv);\n\n\tif(frontend::getIsReplMode())   repl::start();\n\telse                            compile(input_file, output_file);\n\n\n\treturn 0;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/misc/allocator.cpp",
    "content": "// allocator.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include <stdlib.h>\n\n#include \"defs.h\"\n#include \"allocator.h\"\n\n#include \"platform.h\"\n\n#if OS_WINDOWS\n\t#define WIN32_LEAN_AND_MEAN 1\n\n\t#ifndef NOMINMAX\n\t\t#define NOMINMAX\n\t#endif\n\t#include <windows.h>\n#else\n\t#include <unistd.h>\n\t#include <sys/mman.h>\n\t#include <sys/ioctl.h>\n#endif\n\nnamespace mem\n{\n\tstatic void* _alloc(size_t bytes)\n\t{\n\t\t#if OS_WINDOWS\n\t\t\tauto ret = VirtualAlloc(nullptr, bytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);\n\t\t\tif(ret == nullptr) _error_and_exit(\"failed to allocate %d bytes of memory (large page min: %d)\\n\", bytes, GetLargePageMinimum());\n\n\t\t\treturn ret;\n\t\t#else\n\t\t\tauto ret = mmap(nullptr, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n\t\t\tif(ret == nullptr || reinterpret_cast<uintptr_t>(ret) == static_cast<uintptr_t>(-1))\n\t\t\t\t_error_and_exit(\"failed to allocate %d bytes of memory\\n\", bytes);\n\n\t\t\treturn ret;\n\t\t#endif\n\t}\n\n\tstatic void _dealloc(void* ptr, size_t bytes)\n\t{\n\t\t#if OS_WINDOWS\n\t\t\tVirtualFree(ptr, 0, MEM_RELEASE);\n\t\t#else\n\t\t\tmunmap(ptr, bytes);\n\t\t#endif\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tstatic size_t allocated_count = 0;\n\tstatic size_t freed_count = 0;\n\tstatic size_t watermark = 0;\n\n\tvoid* allocate_memory(size_t bytes)\n\t{\n\t\twatermark += bytes;\n\t\tallocated_count += bytes;\n\t\treturn _alloc(bytes);\n\t}\n\n\tvoid deallocate_memory(void* ptr, size_t bytes)\n\t{\n\t\twatermark -= bytes;\n\t\tfreed_count += bytes;\n\t\t_dealloc(ptr, bytes);\n\t}\n\n\tvoid resetStats()\n\t{\n\t\tallocated_count = 0;\n\t\tfreed_count = 0;\n\t\twatermark = 0;\n\t}\n\n\tsize_t getAllocatedCount()\n\t{\n\t\treturn allocated_count;\n\t}\n\n\tsize_t getDeallocatedCount()\n\t{\n\t\treturn freed_count;\n\t}\n\n\tsize_t getWatermark()\n\t{\n\t\treturn watermark;\n\t}\n}\n"
  },
  {
    "path": "source/misc/destructors.cpp",
    "content": "// destructors.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n\nnamespace ast\n{\n\tStmt::~Stmt() { }\n\tExpr::~Expr() { }\n}\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/misc/identifier.cpp",
    "content": "// identifier.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"defs.h\"\n#include \"sst.h\"\n#include \"frontend.h\"\n\n#include \"ir/type.h\"\n\n\nsst::Stmt* TCResult::stmt() const\n{\n\tif(this->_kind == RK::Error)\n\t{\n\t\tthis->_pe->postAndQuit();\n\t\t// throw ErrorException(this->_pe);\n\t}\n\n\tswitch(this->_kind)\n\t{\n\t\tcase RK::Statement:     return this->_st;\n\t\tcase RK::Expression:    return this->_ex;\n\t\tcase RK::Definition:    return this->_df;\n\t\tdefault:                _error_and_exit(\"not stmt\\n\");\n\t}\n}\n\nsst::Expr* TCResult::expr() const\n{\n\tif(this->_kind == RK::Error)\n\t{\n\t\tthis->_pe->postAndQuit();\n\t\t// throw ErrorException(this->_pe);\n\t}\n\n\tif(this->_kind != RK::Expression)\n\t\t_error_and_exit(\"not expr\\n\");\n\n\treturn this->_ex;\n}\n\nsst::Defn* TCResult::defn() const\n{\n\tif(this->_kind == RK::Error)\n\t{\n\t\tthis->_pe->postAndQuit();\n\t\t// throw ErrorException(this->_pe);\n\t}\n\n\tif(this->_kind != RK::Definition)\n\t\t_error_and_exit(\"not defn\\n\");\n\n\treturn this->_df;\n}\n\n\n\n\nvoid PolyArgMapping_t::add(const std::string& name, pts::Type* t)\n{\n\tSingleArg arg;\n\targ.name = name;\n\targ.type = t;\n\targ.index = static_cast<size_t>(-1);\n\n\tthis->maps.push_back(arg);\n}\n\nvoid PolyArgMapping_t::add(size_t idx, pts::Type* t)\n{\n\tSingleArg arg;\n\targ.name = \"\";\n\targ.type = t;\n\targ.index = idx;\n\n\tthis->maps.push_back(arg);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nbool Identifier::operator == (const Identifier& other) const\n{\n\treturn (other.name == this->name) && (other.str() == this->str());\n}\nbool Identifier::operator != (const Identifier& other) const\n{\n\treturn !(other == *this);\n}\n\n\nstd::string Identifier::str() const\n{\n\tstd::string ret;\n\tfor(const auto& s : this->scope.components())\n\t\tret += s + \".\";\n\n\tret += this->name;\n\n\tif(this->kind == IdKind::Function)\n\t{\n\t\tret += \"(\";\n\t\tfor(const auto& p : this->params)\n\t\t\tret += p->str() + \", \";\n\n\t\tif(this->params.size() > 0)\n\t\t\tret.pop_back(), ret.pop_back();\n\n\t\tret += \")\";\n\t}\n\n\treturn ret;\n}\n\nfir::Name Identifier::convertToName() const\n{\n\tswitch(this->kind)\n\t{\n\t\tcase IdKind::Name: return fir::Name::of(this->name, this->scope.components());\n\t\tcase IdKind::Type: return fir::Name::type(this->name, this->scope.components());\n\t\tcase IdKind::Function: return fir::Name::function(this->name, this->scope.components(), this->params, this->returnType);\n\t\tdefault: iceAssert(0 && \"invalid identifier\");\n\t}\n}\n\nstd::string Location::toString() const\n{\n\treturn strprintf(\"(%s:%d:%d)\", frontend::getFilenameFromID(this->fileID), this->line + 1, this->col + 1);\n}\n\nstd::string Location::shortString() const\n{\n\treturn strprintf(\"(%s:%d:%d)\", frontend::getFilenameFromPath(frontend::getFilenameFromID(this->fileID)),\n\t\tthis->line + 1, this->col + 1);\n}\n\n\n\n\n\n\nnamespace util\n{\n\tstd::string typeParamMapToString(const std::string& name, const TypeParamMap_t& map)\n\t{\n\t\tif(map.empty())\n\t\t\treturn name;\n\n\t\tstd::string ret;\n\t\tfor(auto m : map)\n\t\t\tret += (m.first + \":\" + m.second->encodedStr()) + \",\";\n\n\t\t// shouldn't be empty.\n\t\ticeAssert(ret.size() > 0);\n\t\treturn strprintf(\"%s<%s>\", name, ret.substr(0, ret.length() - 1));\n\t}\n}\n\nnamespace zpr\n{\n\tstd::string print_formatter<Identifier>::print(const Identifier& x, const format_args&)\n\t{\n\t\treturn x.str();\n\t}\n\n\tstd::string print_formatter<VisibilityLevel>::print(const VisibilityLevel& x, const format_args&)\n\t{\n\t\tswitch(x)\n\t\t{\n\t\t\tcase VisibilityLevel::Invalid:\treturn \"invalid\";\n\t\t\tcase VisibilityLevel::Public:\treturn \"public\";\n\t\t\tcase VisibilityLevel::Private:\treturn \"private\";\n\t\t\tcase VisibilityLevel::Internal:\treturn \"internal\";\n\t\t\tdefault:                        return \"unknown\";\n\t\t}\n\t}\n}\n\n\n\n\n"
  },
  {
    "path": "source/misc/mpool.cpp",
    "content": "// mpool.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"defs.h\"\n#include \"memorypool.h\"\n\n#include <unordered_set>\n\nnamespace util\n{\n\tstatic std::unordered_set<MemoryPool_base*> pools;\n\tvoid addPool(MemoryPool_base* pool)\n\t{\n\t\tpools.insert(pool);\n\t}\n\n\tvoid clearAllPools()\n\t{\n\t\tfor(auto pool : pools)\n\t\t\tpool->clear();\n\t}\n}\n"
  },
  {
    "path": "source/platform/backtrace.cpp",
    "content": "// backtrace.cpp\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include <inttypes.h>\n\n#include \"errors.h\"\n#include \"platform.h\"\n\n#if OS_DARWIN\n#include <cxxabi.h>\n\n// note: we declare these ourselves because there's some issue with execinfo.h on osx ):\nextern \"C\" {\n\tint backtrace(void**, int);\n\tchar** backtrace_symbols(void* const*, int);\n}\n#elif OS_UNIX\n#include <cxxabi.h>\n#include <execinfo.h>\n#endif\n\n\nnamespace platform\n{\n\tconstexpr size_t MAX_FRAMES     = 128;\n\tconstexpr size_t SKIP_FRAMES    = 1;\n\n\tstruct piece_t\n\t{\n\t\tsize_t num;\n\t\tuintptr_t address;\n\t\tsize_t offset;\n\n\t\tstd::string modName;\n\t\tstd::string mangledName;\n\t\tstd::string demangledName;\n\t};\n\n\tvoid printStackTrace()\n\t{\n\t\t#if OS_WINDOWS\n\n\n\t\t#else\n\n\t\tvoid* arr[MAX_FRAMES] { };\n\t\tsize_t num = backtrace(arr, MAX_FRAMES);\n\t\tchar** strs = backtrace_symbols(arr, num);\n\n\t\tstd::vector<piece_t> pieces;\n\n\t\tfor(size_t i = SKIP_FRAMES; i < num; i++)\n\t\t{\n\t\t\t// platform-specific output!\n\t\t\tif constexpr (OS_DARWIN)\n\t\t\t{\n\t\t\t\tpiece_t piece;\n\t\t\t\tpiece.num = i;\n\n\t\t\t\tchar modname[1024] { };\n\t\t\t\tchar funcname[1024] { };\n\n\t\t\t\tsscanf(strs[i], \"%*s %s %zx %s %*s %zu\", &modname[0], &piece.address, &funcname[0], &piece.offset);\n\n\t\t\t\tpiece.mangledName = funcname;\n\t\t\t\tpiece.modName = modname;\n\n\t\t\t\tif(piece.mangledName.find(\"_Z\") == 0)\n\t\t\t\t{\n\t\t\t\t\tint status = -1;\n\t\t\t\t\tchar* demangledName = abi::__cxa_demangle(piece.mangledName.c_str(), nullptr, nullptr, &status);\n\t\t\t\t\tif(status == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tstd::string deman = demangledName;\n\t\t\t\t\t\tfree(demangledName);\n\n\t\t\t\t\t\t// do replacements.\n\t\t\t\t\t\tstd::map<std::string, std::string> replacements = {\n\t\t\t\t\t\t\t{ \"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >\", \"std::string\" }\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tfor(const auto& [ from, to ] : replacements)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsize_t it = -1;\n\t\t\t\t\t\t\twhile((it = deman.find(from)) != std::string::npos)\n\t\t\t\t\t\t\t\tdeman.replace(it, from.size(), to);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tpiece.demangledName = deman;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tpiece.demangledName = \"??\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// skip some.\n\t\t\t\t\tif(piece.demangledName == \"sst::Stmt::codegen(cgn::CodegenState*, fir::Type*)\")\n\t\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tpiece.demangledName = piece.mangledName;\n\t\t\t\t}\n\n\t\t\t\tdebuglogln(\"    %2d: %12x   |   %s + %#x\", piece.num, piece.address, piece.demangledName, piece.offset);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// TODO.\n\t\t\t}\n\t\t}\n\t\t#endif\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/platform/compiler.cpp",
    "content": "// compiler.cpp\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n\n#include <fcntl.h>\n\n#include \"errors.h\"\n#include \"frontend.h\"\n\n#if OS_WINDOWS\n\t#define WIN32_LEAN_AND_MEAN 1\n\n\t#ifndef NOMINMAX\n\t\t#define NOMINMAX\n\t#endif\n\n\t#include <windows.h>\n#else\n\t#include <dlfcn.h>\n\t#include <unistd.h>\n\t#include <sys/mman.h>\n\t#include <sys/ioctl.h>\n#endif\n\n\nnamespace platform {\nnamespace compiler\n{\n\t#if OS_WINDOWS\n\t\tstatic HMODULE currentModule = 0;\n\t\tstatic std::vector<HMODULE> otherModules;\n\t\tstatic std::vector<DLL_DIRECTORY_COOKIE> loadedDllDirs;\n\t#else\n\t\tvoid* currentModule = 0;\n\t#endif\n\n\n\tstd::string getCompilerCommandLine(const std::vector<std::string>& inputObjects, const std::string& outputFilename)\n\t{\n\t\tstd::string cmdline;\n\t\t#if OS_WINDOWS\n\n\t\t\t// TODO: get set the target properly!!\n\t\t\t// TODO: get set the target properly!!\n\t\t\t// TODO: get set the target properly!!\n\n\t\t\tcmdline = strprintf(\"%s\\\\x64\\\\link.exe /nologo /incremental:no /out:%s /nodefaultlib\",\n\t\t\t\tgetVSToolchainBinLocation(), outputFilename);\n\n\t\t\tcmdline += strprintf(\" /machine:AMD64\");\n\n\t\t\tfor(const auto& i : inputObjects)\n\t\t\t\tcmdline += strprintf(\" %s\", i);\n\n\t\t\tif(!frontend::getIsFreestanding() && !frontend::getIsNoStandardLibraries())\n\t\t\t{\n\t\t\t\t// these dumb paths have spaces in them, so we need to quote it.\n\t\t\t\t// link.exe handles its own de-quoting, not cmd.exe or whatever shell.\n\n\t\t\t\tauto sdkRoot = strprintf(\"\\\"%s\\\"\", getWindowsSDKLocation());\n\t\t\t\tauto vsLibRoot = strprintf(\"\\\"%s\\\"\", getVSToolchainLibLocation());\n\n\t\t\t\tstd::vector<std::string> umLibs     = { \"kernel32.lib\" };\n\t\t\t\tstd::vector<std::string> ucrtLibs   = { \"libucrt.lib\" };\n\t\t\t\tstd::vector<std::string> msvcLibs   = {\n\t\t\t\t\t\"libcmt.lib\", \"libvcruntime.lib\",\n\t\t\t\t\t\"legacy_stdio_definitions.lib\", \"legacy_stdio_wide_specifiers.lib\"\n\t\t\t\t};\n\n\t\t\t\tfor(const auto& l : umLibs)\n\t\t\t\t\tcmdline += strprintf(\" %s\\\\um\\\\x64\\\\%s\", sdkRoot, l);\n\n\t\t\t\tfor(const auto& l : ucrtLibs)\n\t\t\t\t\tcmdline += strprintf(\" %s\\\\ucrt\\\\x64\\\\%s\", sdkRoot, l);\n\n\t\t\t\tfor(const auto& l : msvcLibs)\n\t\t\t\t\tcmdline += strprintf(\" %s\\\\x64\\\\%s\", vsLibRoot, l);\n\t\t\t}\n\n\t\t#else\n\n\t\t\t// cc -o <output>\n\t\t\tcmdline = strprintf(\"cc -o %s\", outputFilename);\n\n\t\t\tfor(const auto& i : inputObjects)\n\t\t\t\tcmdline += strprintf(\" %s\", i);\n\n\t\t\tfor(const auto& p : frontend::getLibrarySearchPaths())\n\t\t\t\tcmdline += strprintf(\" -L%s\", p);\n\n\t\t\tfor(const auto& p : frontend::getFrameworkSearchPaths())\n\t\t\t\tcmdline += strprintf(\" -F%s\", p);\n\n\t\t\tfor(const auto& l : frontend::getLibrariesToLink())\n\t\t\t\tcmdline += strprintf(\" -l%s\", l);\n\n\t\t\tfor(const auto& f : frontend::getFrameworksToLink())\n\t\t\t\tcmdline += strprintf(\" -framework %s\", f);\n\n\t\t\tif(!frontend::getIsFreestanding() && !frontend::getIsNoStandardLibraries())\n\t\t\t\tcmdline += strprintf(\" -lm -lc\");\n\n\t\t#endif\n\n\t\treturn cmdline;\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tvoid addLibrarySearchPaths()\n\t{\n\t\tauto libPaths = frontend::getLibrarySearchPaths();\n\t\tauto frameworkPaths = frontend::getFrameworkSearchPaths();\n\n\t\t#if OS_WINDOWS\n\t\t\tfor(const auto& path : libPaths)\n\t\t\t{\n\t\t\t\tif(path.empty()) continue;\n\n\t\t\t\tauto wpath = convertStringToWChar(path);\n\t\t\t\tauto cookie = AddDllDirectory(wpath.c_str());\n\n\t\t\t\tif(cookie)\n\t\t\t\t\tloadedDllDirs.push_back(cookie);\n\n\t\t\t}\n\t\t#else\n\t\t\tauto env = getEnvironmentVar(\"LD_LIBRARY_PATH\");\n\t\t\tfor(auto L : libPaths)\n\t\t\t\tenv += strprintf(\":%s\", L);\n\n\t\t\tpushEnvironmentVar(\"LD_LIBRARY_PATH\", env);\n\n\t\t\t#if OS_DARWIN\n\t\t\t{\n\t\t\t\tauto env = getEnvironmentVar(\"DYLD_FRAMEWORK_PATH\");\n\t\t\t\tfor(auto L : frameworkPaths)\n\t\t\t\t\tenv += strprintf(\":%s\", L);\n\n\t\t\t\tpushEnvironmentVar(\"DYLD_FRAMEWORK_PATH\", env);\n\t\t\t}\n\t\t\t#endif\n\t\t#endif\n\t}\n\n\tvoid restoreLibrarySearchPaths()\n\t{\n\t\t#if OS_WINDOWS\n\t\t\tfor(auto cookie : loadedDllDirs)\n\t\t\t\tRemoveDllDirectory(cookie);\n\t\t#else\n\t\t\tpopEnvironmentVar(\"LD_LIBRARY_PATH\");\n\n\t\t\t#if OS_DARWIN\n\t\t\t\tpopEnvironmentVar(\"DYLD_FRAMEWORK_PATH\");\n\t\t\t#endif\n\t\t#endif\n\t}\n\n\tstd::vector<std::string> getDefaultSharedLibraries()\n\t{\n\t\tif(frontend::getIsFreestanding() || frontend::getIsNoStandardLibraries())\n\t\t\treturn { };\n\n\t\t#if OS_WINDOWS\n\n\t\t\t//? the name is \"vcruntime140.dll\", which is apparently specific to MSVC 14.0+, apparently 140 is the only number that\n\t\t\t//? appears to be referenced in online sources.\n\t\t\treturn {\n\t\t\t\t\"ucrtbase.dll\",\n\t\t\t\t\"vcruntime140.dll\"\n\t\t\t};\n\t\t#elif OS_DARWIN\n\t\t\treturn {\n\t\t\t\t\"libc.dylib\", \"libm.dylib\"\n\t\t\t};\n\t\t#elif OS_UNIX\n\t\t\t// note: we do not (and cannot) link libc and libm explicitly under linux.\n\t\t\t// not sure about other unices.\n\t\t\treturn {\n\t\t\t};\n\t\t#endif\n\t}\n\n\tstd::string getSharedLibraryName(const std::string& name)\n\t{\n\t\t#if OS_WINDOWS\n\t\t\treturn strprintf(\"%s.dll\", name);\n\t\t#elif OS_DARWIN\n\t\t\treturn strprintf(\"lib%s.dylib\", name);\n\t\t#elif OS_UNIX\n\t\t\treturn strprintf(\"lib%s.so\", name);\n\t\t#endif\n\t}\n\n\tstd::string getExecutableName(const std::string& name)\n\t{\n\t\t#if OS_WINDOWS\n\t\t\treturn strprintf(\"%s.exe\", name);\n\t\t#else\n\t\t\treturn name;\n\t\t#endif\n\t}\n\n\tstd::string getObjectFileName(const std::string& name)\n\t{\n\t\t#if OS_WINDOWS\n\t\t\treturn strprintf(\"%s.obj\", name);\n\t\t#else\n\t\t\treturn strprintf(\"%s.o\", name);\n\t\t#endif\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tvoid performSelfDlOpen()\n\t{\n\t\t#if OS_WINDOWS\n\t\t\tcurrentModule = GetModuleHandle(nullptr);\n\n\t\t\totherModules.push_back(LoadLibrary(\"ucrtbase.dll\"));\n\t\t\totherModules.push_back(LoadLibrary(\"vcruntime140.dll\"));\n\t\t#else\n\t\t\tcurrentModule = dlopen(nullptr, RTLD_LAZY);\n\t\t#endif\n\t}\n\n\tvoid performSelfDlClose()\n\t{\n\t\t#if OS_WINDOWS\n\t\t\tfor(auto mod : otherModules)\n\t\t\t\tFreeLibrary(mod);\n\t\t#endif\n\t}\n\n\tvoid* getSymbol(const std::string& name)\n\t{\n\t\tif(!currentModule) error(\"backend: failed to load current module!\");\n\n\t\tvoid* ret = 0;\n\t\t#if OS_WINDOWS\n\t\t\tret = GetProcAddress(currentModule, name.c_str());\n\t\t\tfor(size_t i = 0; !ret && i < otherModules.size(); i++)\n\t\t\t\tret = GetProcAddress(otherModules[i], name.c_str());\n\t\t#else\n\t\t\tret = dlsym(currentModule, name.c_str());\n\t\t#endif\n\n\t\treturn ret;\n\t}\n\n}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/platform/msvcfinder.cpp",
    "content": "// msvcfinder.cpp\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"defs.h\"\n#include \"errors.h\"\n#include \"frontend.h\"\n\n#include <sstream>\n#include <fstream>\n\n#if OS_WINDOWS\n\n#ifndef NOMINMAX\n\t#define NOMINMAX\n#endif\n\n#include <windows.h>\n\nnamespace platform {\nnamespace compiler\n{\n\t// the techniques used here are with reference to Jon Blow's \"microsoft_craziness.h\" file.\n\t// it was released under the MIT license. see: https://gist.github.com/machinamentum/a2b587a68a49094257da0c39a6c4405f\n\n\tstruct DECLSPEC_UUID(\"B41463C3-8866-43B5-BC33-2B0676F7F42E\") DECLSPEC_NOVTABLE ISetupInstance : public IUnknown\n\t{\n\t\tSTDMETHOD(GetInstanceId)(_Out_ BSTR* pbstrInstanceId) = 0;\n\t\tSTDMETHOD(GetInstallDate)(_Out_ LPFILETIME pInstallDate) = 0;\n\t\tSTDMETHOD(GetInstallationName)(_Out_ BSTR* pbstrInstallationName) = 0;\n\t\tSTDMETHOD(GetInstallationPath)(_Out_ BSTR* pbstrInstallationPath) = 0;\n\t\tSTDMETHOD(GetInstallationVersion)(_Out_ BSTR* pbstrInstallationVersion) = 0;\n\t\tSTDMETHOD(GetDisplayName)(_In_ LCID lcid, _Out_ BSTR* pbstrDisplayName) = 0;\n\t\tSTDMETHOD(GetDescription)(_In_ LCID lcid, _Out_ BSTR* pbstrDescription) = 0;\n\t\tSTDMETHOD(ResolvePath)(_In_opt_z_ LPCOLESTR pwszRelativePath, _Out_ BSTR* pbstrAbsolutePath) = 0;\n\t};\n\n\tstruct DECLSPEC_UUID(\"6380BCFF-41D3-4B2E-8B2E-BF8A6810C848\") DECLSPEC_NOVTABLE IEnumSetupInstances : public IUnknown\n\t{\n\t\tSTDMETHOD(Next)(_In_ ULONG celt, _Out_writes_to_(celt, *pceltFetched) ISetupInstance** rgelt,\n\t\t\t_Out_opt_ _Deref_out_range_(0, celt) ULONG* pceltFetched) = 0;\n\n\t\tSTDMETHOD(Skip)(_In_ ULONG celt) = 0;\n\t\tSTDMETHOD(Reset)(void) = 0;\n\t\tSTDMETHOD(Clone)(_Deref_out_opt_ IEnumSetupInstances** ppenum) = 0;\n\t};\n\n\tstruct DECLSPEC_UUID(\"42843719-DB4C-46C2-8E7C-64F1816EFD5B\") DECLSPEC_NOVTABLE ISetupConfiguration : public IUnknown\n\t{\n\t\tSTDMETHOD(EnumInstances)(_Out_ IEnumSetupInstances** ppEnumInstances) = 0;\n\t\tSTDMETHOD(GetInstanceForCurrentProcess)(_Out_ ISetupInstance** ppInstance) = 0;\n\t\tSTDMETHOD(GetInstanceForPath)(_In_z_ LPCWSTR wzPath, _Out_ ISetupInstance** ppInstance) = 0;\n\t};\n\n\tstruct DECLSPEC_UUID(\"42B21B78-6192-463E-87BF-D577838F1D5C\") DECLSPEC_NOVTABLE ISetupHelper : public IUnknown\n\t{\n\t\tSTDMETHOD(ParseVersion)(_In_ LPCOLESTR pwszVersion, _Out_ PULONGLONG pullVersion) = 0;\n\t\tSTDMETHOD(ParseVersionRange)(_In_ LPCOLESTR pwszVersionRange, _Out_ PULONGLONG pullMinVersion, _Out_ PULONGLONG pullMaxVersion) = 0;\n\t};\n\n\n\n\tstruct VersionData\n\t{\n\t\tint32_t bestVersion[4];\n\t\tstd::wstring bestName;\n\t};\n\n\tstruct FindResult\n\t{\n\t\tint windowsVersion;\n\t\tstd::string windowsSDKRoot;\n\t\tstd::string vsBinDirectory;\n\t\tstd::string vsLibDirectory;\n\t};\n\n\tstatic bool checkFileExists(const std::wstring& name)\n\t{\n\t\tauto attrib = GetFileAttributesW(name.c_str());\n\t\treturn attrib != INVALID_FILE_ATTRIBUTES;\n\t}\n\n\tstatic bool visitFiles(const std::wstring& dir, VersionData* vd, std::function<void (const std::wstring& shortName,\n\t\tconst std::wstring& fullName, VersionData* vd)> visitor)\n\t{\n\t\tauto wildcard = dir + L\"\\\\*\";\n\n\t\tWIN32_FIND_DATAW findData;\n\t\tauto handle = FindFirstFileW(wildcard.c_str(), &findData);\n\t\tif(handle == INVALID_HANDLE_VALUE) return false;\n\n\n\t\twhile(true)\n\t\t{\n\t\t\t// make sure it's a directory, and don't read '.' or '..'\n\t\t\tif((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (findData.cFileName[0] != '.'))\n\t\t\t{\n\t\t\t\tauto full = dir + L\"\\\\\" + findData.cFileName;\n\t\t\t\tvisitor(findData.cFileName, full, vd);\n\t\t\t}\n\n\t\t\tauto success = FindNextFileW(handle, &findData);\n\t\t\tif(!success) break;\n\t\t}\n\n\t\tFindClose(handle);\n\t\treturn true;\n\t}\n\n\n\tstatic std::wstring readRegistryString(HKEY key, const std::wstring& name)\n\t{\n\t\t// If the registry data changes between the first and second calls to RegQueryValueExW,\n\t\t// we may fail to get the entire key, even though it told us initially that our buffer length\n\t\t// would be big enough. The only solution is to keep looping until we don't fail.\n\n\t\tDWORD required = 0;\n\t\tauto rc = RegQueryValueExW(key, name.c_str(), NULL, NULL, NULL, &required);\n\t\tif(rc != 0) return L\"\";\n\n\n\t\twchar_t* value = 0;\n\t\tDWORD length = 0;\n\n\t\twhile(true)\n\t\t{\n\t\t\tlength = required + 2;\n\t\t\tvalue = (wchar_t*) malloc(length + 2);\n\t\t\tif(!value)\n\t\t\t\treturn L\"\";\n\n\t\t\tDWORD type;\n\t\t\trc = RegQueryValueExW(key, name.c_str(), NULL, &type, (LPBYTE) value, &length);\n\t\t\tif(rc == ERROR_MORE_DATA)\n\t\t\t{\n\t\t\t\tfree(value);\n\t\t\t\trequired = length;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// only get strings\n\t\t\tif((rc != 0) || (type != REG_SZ))\n\t\t\t{\n\t\t\t\tfree(value);\n\t\t\t\treturn L\"\";\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\n\t\tauto num_wchars = length / 2;\n\t\tvalue[num_wchars] = 0;\n\n\t\tauto ret = std::wstring(value);\n\t\tfree(value);\n\n\t\treturn ret;\n\t}\n\n\tstatic void getBestWin10Version(const std::wstring& shortName, const std::wstring& fullName, VersionData* vd)\n\t{\n\t\t// find the win10 subdir with the highest version number.\n\t\tint i0 = 0;\n\t\tint i1 = 0;\n\t\tint i2 = 0;\n\t\tint i3 = 0;\n\n\t\tauto gots = swscanf_s(shortName.c_str(), L\"%d.%d.%d.%d\", &i0, &i1, &i2, &i3);\n\t\tif(gots < 4) return;\n\n\t\tauto b0 = vd->bestVersion[0];\n\t\tauto b1 = vd->bestVersion[1];\n\t\tauto b2 = vd->bestVersion[2];\n\t\tauto b3 = vd->bestVersion[3];\n\n\t\t// short-circuiting ftw.\n\t\tif((b0 > i0) || (b1 > i1) || (b2 > i2) || (b3 > i3))\n\t\t\treturn;\n\n\t\tvd->bestName = fullName;\n\t\tvd->bestVersion[0] = i0;\n\t\tvd->bestVersion[1] = i1;\n\t\tvd->bestVersion[2] = i2;\n\t\tvd->bestVersion[3] = i3;\n\t}\n\n\tstatic void getBestWin8Version(const std::wstring& shortName, const std::wstring& fullName, VersionData* vd)\n\t{\n\t\t// find the win8 subdir with the highest version number.\n\t\tint i0 = 0;\n\t\tint i1 = 0;\n\n\t\tauto gots = swscanf_s(shortName.c_str(), L\"winv%d.%d\", &i0, &i1);\n\t\tif(gots < 2)\n\t\t\treturn;\n\n\t\tauto b0 = vd->bestVersion[0];\n\t\tauto b1 = vd->bestVersion[1];\n\n\t\t// short-circuiting ftw.\n\t\tif((b0 > i0) || (b1 > i1))\n\t\t\treturn;\n\n\t\tvd->bestName = fullName;\n\t\tvd->bestVersion[0] = i0;\n\t\tvd->bestVersion[1] = i1;\n\t}\n\n\n\tstatic void findWindowsKitRoot(FindResult* result)\n\t{\n\t\tHKEY key;\n\t\tauto rc = RegOpenKeyExA(HKEY_LOCAL_MACHINE, \"SOFTWARE\\\\Microsoft\\\\Windows Kits\\\\Installed Roots\", 0,\n\t\t\tKEY_QUERY_VALUE | KEY_WOW64_32KEY | KEY_ENUMERATE_SUB_KEYS, &key);\n\n\t\tif(rc != S_OK)\n\t\t\treturn;\n\n\t\tdefer(RegCloseKey(key));\n\n\n\t\t// find a windows 10 thing\n\t\tauto win10root = readRegistryString(key, L\"KitsRoot10\");\n\t\tif(!win10root.empty())\n\t\t{\n\t\t\tauto win10lib = win10root + L\"Lib\";\n\n\t\t\tVersionData vd;\n\t\t\tmemset(&vd, 0, sizeof(VersionData));\n\n\t\t\tvisitFiles(win10lib, &vd, &getBestWin10Version);\n\n\t\t\tif(!vd.bestName.empty())\n\t\t\t{\n\t\t\t\tresult->windowsVersion = 10;\n\t\t\t\tresult->windowsSDKRoot = convertWCharToString(vd.bestName);\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tauto win8root = readRegistryString(key, L\"KitsRoot81\");\n\t\tif(!win8root.empty())\n\t\t{\n\t\t\tauto win10lib = win10root + L\"Lib\";\n\n\t\t\tVersionData vd;\n\t\t\tmemset(&vd, 0, sizeof(VersionData));\n\n\t\t\tvisitFiles(win10lib, &vd, &getBestWin8Version);\n\n\t\t\tif(!vd.bestName.empty())\n\t\t\t{\n\t\t\t\tresult->windowsVersion = 8;\n\t\t\t\tresult->windowsSDKRoot = convertWCharToString(vd.bestName);\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\n\tstatic std::string trim(std::string s)\n\t{\n\t\tauto ltrim = [](std::string& s) -> std::string& {\n\t\t\ts.erase(0, s.find_first_not_of(\" \\t\\n\\r\\f\\v\"));\n\t\t\treturn s;\n\t\t};\n\n\t\tauto rtrim = [](std::string& s) -> std::string& {\n\t\t\ts.erase(s.find_last_not_of(\" \\t\\n\\r\\f\\v\") + 1);\n\t\t\treturn s;\n\t\t};\n\n\t\treturn ltrim(rtrim(s));\n\t}\n\n\n\n\tstatic bool findVSToolchain(FindResult* result)\n\t{\n\t\t// for vs >= 2017, we need to do some COM stupidity.\n\n\t\tCoInitializeEx(NULL, COINIT_MULTITHREADED);\n\n\t\tGUID my_uid             = { 0x42843719, 0xDB4C, 0x46C2, { 0x8E, 0x7C, 0x64, 0xF1, 0x81, 0x6E, 0xFD, 0x5B } };\n\t\tGUID clsid_setupConfig  = { 0x177F0C4A, 0x1CD3, 0x4DE7, { 0xA3, 0x2C, 0x71, 0xDB, 0xBB, 0x9F, 0xA3, 0x6D } };\n\n\t\tISetupConfiguration* config = NULL;\n\t\tauto hr = CoCreateInstance(clsid_setupConfig, NULL, CLSCTX_INPROC_SERVER, my_uid, (void**) &config);\n\t\tif(hr != S_OK) return false;\n\n\t\tdefer(config->Release());\n\n\n\t\tIEnumSetupInstances* instances = NULL;\n\t\thr = config->EnumInstances(&instances);\n\t\tif(hr != S_OK)  return false;\n\t\tif(!instances)  return false;\n\n\t\tdefer(instances->Release());\n\n\n\t\tISetupInstance* inst = 0;\n\t\tuint64_t newestVersionNum = 0;\n\n\t\t// we look for the newest version that's installed, as opposed to the first.\n\t\twhile(true)\n\t\t{\n\t\t\tISetupInstance* instance = NULL;\n\t\t\tauto hr = instances->Next(1, &instance, NULL);\n\t\t\tif(hr != S_OK) break;\n\n\t\t\tBSTR versionString;\n\t\t\tuint64_t versionNum = 0;\n\n\t\t\thr = instance->GetInstallationVersion(&versionString);\n\t\t\tif(hr != S_OK) continue;\n\n\t\t\tdefer(SysFreeString(versionString));\n\n\t\t\thr = ((ISetupHelper*) config)->ParseVersion(versionString, &versionNum);\n\t\t\tif(hr != S_OK) continue;\n\n\t\t\tif(newestVersionNum == 0 || versionNum > newestVersionNum)\n\t\t\t{\n\t\t\t\tinst = instance;\n\t\t\t\tnewestVersionNum = versionNum;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tinstance->Release();\n\t\t\t}\n\t\t}\n\n\n\t\tif(!inst)\n\t\t\treturn false;\n\n\t\tstd::string vsRoot;\n\t\t{\n\t\t\tBSTR tmp;\n\t\t\tauto hr = inst->ResolvePath(L\"VC\", &tmp);\n\t\t\tif(hr != S_OK) return false;\n\n\t\t\tvsRoot = convertWCharToString(std::wstring(tmp));\n\t\t\tSysFreeString(tmp);\n\n\t\t\tinst->Release();\n\t\t}\n\n\t\tstd::string toolchainVersion;\n\t\t{\n\t\t\tauto path = strprintf(\"%s\\\\Auxiliary\\\\Build\\\\Microsoft.VCToolsVersion.default.txt\", vsRoot);\n\n\t\t\tauto in = std::ifstream(path, std::ios::in);\n\t\t\tstd::getline(in, toolchainVersion);\n\n\t\t\ttoolchainVersion = trim(toolchainVersion);\n\t\t}\n\n\t\tstd::string toolchainPath = strprintf(\"%s\\\\Tools\\\\MSVC\\\\%s\", vsRoot, toolchainVersion);\n\t\tif(checkFileExists(convertStringToWChar(toolchainPath)))\n\t\t{\n\t\t\t//* this is *HOST* architecture, so we can just use our defines.\n\t\t\tresult->vsBinDirectory = strprintf(\"%s\\\\bin\\\\Host%s\", toolchainPath, ARCH_64 ? \"x64\" : \"x86\");\n\t\t\tresult->vsLibDirectory = strprintf(\"%s\\\\lib\", toolchainPath);\n\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\n\tstatic FindResult* getResult()\n\t{\n\t\tstatic bool cached = false;\n\t\tstatic FindResult cachedResult;\n\n\t\tif(!cached)\n\t\t{\n\t\t\tmemset(&cachedResult, 0, sizeof(FindResult));\n\n\t\t\tfindWindowsKitRoot(&cachedResult);\n\t\t\tauto found = findVSToolchain(&cachedResult);\n\t\t\tif(!found) error(\"backend: failed to find installed Visual Studio location!\");\n\n\t\t\tcached = true;\n\t\t}\n\n\t\treturn &cachedResult;\n\t}\n\n\tstd::string getWindowsSDKLocation()\n\t{\n\t\treturn getResult()->windowsSDKRoot;\n\t}\n\n\tstd::string getVSToolchainLibLocation()\n\t{\n\t\treturn getResult()->vsLibDirectory;\n\t}\n\n\tstd::string getVSToolchainBinLocation()\n\t{\n\t\treturn getResult()->vsBinDirectory;\n\t}\n}\n}\n\n#endif\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/platform/platform.cpp",
    "content": "// platform.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include <fcntl.h>\n#include <stdlib.h>\n\n#include \"errors.h\"\n#include \"frontend.h\"\n#include \"platform.h\"\n\n\n#if OS_WINDOWS\n\t#define WIN32_LEAN_AND_MEAN 1\n\n\t#ifndef NOMINMAX\n\t\t#define NOMINMAX\n\t#endif\n\n\t#include <windows.h>\n\n\t#define USE_MMAP false\n#else\n\t#include <dlfcn.h>\n\t#include <unistd.h>\n\t#include <signal.h>\n\t#include <sys/mman.h>\n\t#include <sys/ioctl.h>\n\n\t#define USE_MMAP true\n\n\t#ifdef __MACH__\n\t\t#include <mach/vm_statistics.h>\n\t\t#define EXTRA_MMAP_FLAGS VM_FLAGS_SUPERPAGE_SIZE_2MB\n\t#elif defined(MAP_HUGE_2MB)\n\t\t#define EXTRA_MMAP_FLAGS MAP_HUGE_2MB\n\t#else\n\t\t#define EXTRA_MMAP_FLAGS 0\n\t#endif\n#endif\n\n\nnamespace platform\n{\n\t#if OS_WINDOWS\n\t\tfilehandle_t InvalidFileHandle = INVALID_HANDLE_VALUE;\n\t#else\n\t\tfilehandle_t InvalidFileHandle = -1;\n\t#endif\n\n\n\tstatic util::hash_map<std::string, std::vector<std::string>> environmentStack;\n\n\tstd::string getEnvironmentVar(const std::string& name)\n\t{\n\t#if OS_WINDOWS\n\t\tchar buffer[256] = { 0 };\n\t\tsize_t len = 0;\n\n\t\tif(getenv_s(&len, buffer, name.c_str()) != 0)\n\t\t\treturn \"\";\n\n\t\telse\n\t\t\treturn std::string(buffer, len);\n\t#else\n\t\tif(char* val = getenv(name.c_str()); val)\n\t\t\treturn std::string(val);\n\n\t\telse\n\t\t\treturn \"\";\n\t#endif\n\t}\n\n\tvoid pushEnvironmentVar(const std::string& name, const std::string& value)\n\t{\n\t\tenvironmentStack[name].push_back(value);\n\n\t\t#if OS_WINDOWS\n\t\t\t_putenv_s(name.c_str(), value.c_str());\n\t\t#else\n\t\t\tsetenv(name.c_str(), value.c_str(), /* overwrite: */ 1);\n\t\t#endif\n\t}\n\n\tvoid popEnvironmentVar(const std::string& name)\n\t{\n\t\tauto it = environmentStack.find(name);\n\t\tif(it == environmentStack.end() || it->second.empty())\n\t\t\terror(\"did not push '%s'\", name.c_str());\n\n\t\tit->second.pop_back();\n\n\t\tauto restore = it->second.empty() ? \"\" : it->second.back();\n\n\t\t#if OS_WINDOWS\n\t\t\t_putenv_s(name.c_str(), restore.c_str());\n\t\t#else\n\t\t\tsetenv(name.c_str(), restore.c_str(), /* overwrite: */ 1);\n\t\t#endif\n\t}\n\n\t#if OS_WINDOWS\n\n\tstd::wstring convertStringToWChar(const std::string& s)\n\t{\n\t\tif(s.empty())\n\t\t\treturn L\"\";\n\n\t\tif(s.size() > INT_MAX)\n\t\t\terror(\"string length %d is too large\", s.size());\n\n\t\tint required = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), (int) s.size(), NULL, 0);\n\t\tif(required == 0) error(\"failed to convert string\");\n\n\n\t\tauto buf = (LPWSTR) malloc(sizeof(WCHAR) * (required + 1));\n\t\tif(!buf) error(\"failed to allocate buffer\");\n\n\t\tauto ret = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), (int) s.size(), buf, required);\n\t\ticeAssert(ret > 0);\n\n\t\tauto wstr = std::wstring(buf, ret);\n\t\tfree(buf);\n\n\t\treturn wstr;\n\t}\n\n\tstd::string convertWCharToString(const std::wstring& s)\n\t{\n\t\tif(s.empty())\n\t\t\treturn \"\";\n\n\t\tif(s.size() > INT_MAX)\n\t\t\terror(\"string length %d is too large\", s.size());\n\n\t\tint required = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s.c_str(), -1, NULL, 0, NULL, NULL);\n\t\tif(required == 0) error(\"failed to convert wstring\");\n\n\t\tauto buf = (char*) malloc(sizeof(char) * (required + 1));\n\t\tif(!buf) error(\"failed to allocate buffer\");\n\n\t\tauto ret = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s.c_str(), -1, buf, required, NULL, NULL);\n\t\ticeAssert(ret > 0);\n\n\t\tauto str = std::string(buf, ret - 1);\n\t\tfree(buf);\n\n\t\treturn str;\n\t}\n\n\t#endif\n\n\n\n\n\tsize_t getFileSize(const std::string& path)\n\t{\n\t\t#if OS_WINDOWS\n\n\t\t\t// note: jesus christ this thing is horrendous\n\n\t\t\tHANDLE hd = CreateFile((LPCSTR) path.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);\n\t\t\tif(hd == INVALID_HANDLE_VALUE)\n\t\t\t\terror(\"failed to get filesize for '%s' (error code %d)\", path, GetLastError());\n\n\t\t\t// ok, presumably it exists. so, get the size\n\t\t\tLARGE_INTEGER sz;\n\t\t\tbool success = GetFileSizeEx(hd, &sz);\n\t\t\tif(!success)\n\t\t\t\terror(\"failed to get filesize for '%s' (error code %d)\", path, GetLastError());\n\n\t\t\tCloseHandle(hd);\n\n\t\t\treturn (size_t) sz.QuadPart;\n\n\t\t#else\n\n\t\t\tstruct stat st;\n\t\t\tif(stat(path.c_str(), &st) != 0)\n\t\t\t\terror(\"failed to get filesize for '%s' (error code %d / %s)\", path, errno, strerror(errno));\n\n\t\t\treturn st.st_size;\n\n\t\t#endif\n\t}\n\n\n\tstatic util::hash_map<std::string, std::string_view> cachedFileContents;\n\n\tvoid cachePreExistingFile(const std::string& path, const std::string& contents)\n\t{\n\t\tcachedFileContents[path] = contents;\n\n\t\t// this will give cache a new id for us. (over there)\n\t\tfrontend::cachePreExistingFilename(path);\n\t}\n\n\tstd::string_view readEntireFile(const std::string& path)\n\t{\n\t\tif(auto it = cachedFileContents.find(path); it != cachedFileContents.end())\n\t\t\treturn it->second;\n\n\t\t// first, get the size of the file\n\t\tsize_t fileLength = getFileSize(path);\n\n\t\tauto fd = openFile(path.c_str(), O_RDONLY, 0);\n\t\tif(fd == platform::InvalidFileHandle)\n\t\t{\n\t\t\tperror(\"there was an error getting opening the file\");\n\t\t\texit(-1);\n\t\t}\n\n\n\t\t// check if we should mmap\n\t\t// explanation: if we have EXTRA_MMAP_FLAGS, then we're getting 2MB pages -- in which case we should probably only do it\n\t\t// if we have at least 4mb worth of file.\n\t\t// if not, then just 2 * pagesize.\n\t\t#define MINIMUM_MMAP_THRESHOLD (static_cast<size_t>(((EXTRA_MMAP_FLAGS) != 0) ? (2 * 2 * 1024 * 1024) : 2 * getpagesize()))\n\n\t\tstd::string_view contents;\n\n\t\t// here's the thing -- we use USE_MMAP at *compile-time*, because on windows some of the constants we're going to use\n\t\t// here aren't available at all if we include it, then it'll be parsed and everything and error out. So, we #ifdef it away.\n\n\t\t// Problem is, there's another scenario in which we won't want to use mmap -- when the file size is too small. so, that's why the stuff\n\t\t// below is structured the way it is.\n\t\t#if USE_MMAP\n\t\t{\n\t\t\tif(fileLength >= MINIMUM_MMAP_THRESHOLD)\n\t\t\t{\n\t\t\t\t// ok, do an mmap\n\t\t\t\tconst char* buf = static_cast<const char*>(mmap(0, fileLength, PROT_READ, MAP_PRIVATE | EXTRA_MMAP_FLAGS, fd, 0));\n\t\t\t\tif(buf == reinterpret_cast<void*>(-1))\n\t\t\t\t{\n\t\t\t\t\tperror(\"there was an error reading the file\");\n\t\t\t\t\texit(-1);\n\t\t\t\t}\n\n\t\t\t\tcontents = std::string_view(buf, fileLength);\n\t\t\t}\n\t\t}\n\t\t#endif\n\n\t\tif(contents.empty())\n\t\t{\n\t\t\t// read normally\n\t\t\t//! MEMORY LEAK\n\t\t\tauto buf = new char[fileLength + 1];\n\t\t\tsize_t didRead = platform::readFile(fd, buf, fileLength);\n\t\t\tif(didRead != fileLength)\n\t\t\t{\n\t\t\t\tperror(\"there was an error reading the file\");\n\t\t\t\terror(\"expected %d bytes, but read only %d\", fileLength, didRead);\n\t\t\t}\n\n\t\t\tcontents = std::string_view(buf, fileLength);\n\t\t}\n\n\t\tcloseFile(fd);\n\n\t\tcachedFileContents[path] = contents;\n\t\treturn cachedFileContents[path];\n\t}\n\n\tfilehandle_t openFile(const char* name, int mode, int flags)\n\t{\n\t\t#if OS_WINDOWS\n\t\t\tbool writing = (mode & O_WRONLY) || (mode & O_RDWR);\n\t\t\tbool create = (mode & O_CREAT);\n\n\t\t\tHANDLE hd = CreateFile((LPCSTR) name, GENERIC_READ | (writing ? GENERIC_WRITE : 0), FILE_SHARE_READ, 0,\n\t\t\t\tcreate ? CREATE_ALWAYS : OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);\n\n\t\t\tif(hd == INVALID_HANDLE_VALUE)\n\t\t\t\treturn platform::InvalidFileHandle;\n\n\t\t\treturn hd;\n\t\t#else\n\t\t\treturn open(name, mode, flags);\n\t\t#endif\n\t}\n\n\tvoid closeFile(filehandle_t fd)\n\t{\n\t\t#if OS_WINDOWS\n\t\t\tCloseHandle(fd);\n\t\t#else\n\t\t\tclose(fd);\n\t\t#endif\n\t}\n\n\tvoid deleteFile(filehandle_t fd)\n\t{\n\t}\n\n\tsize_t readFile(filehandle_t fd, void* buf, size_t count)\n\t{\n\t\t#if OS_WINDOWS\n\t\t\tDWORD didRead = 0;\n\t\t\tbool success = ReadFile(fd, buf, (DWORD) count, &didRead, 0);\n\t\t\tif(!success)\n\t\t\t\terror(\"failed to read file (wanted %d bytes, read %d bytes); (error code %d)\", count, didRead, GetLastError());\n\n\t\t\treturn (size_t) didRead;\n\t\t#else\n\t\t\treturn read(fd, buf, count);\n\t\t#endif\n\t}\n\n\tsize_t writeFile(filehandle_t fd, void* buf, size_t count)\n\t{\n\t\t#if OS_WINDOWS\n\t\t\tDWORD didWrite = 0;\n\t\t\tbool success = WriteFile(fd, buf, (DWORD) count, &didWrite, 0);\n\t\t\tif(!success)\n\t\t\t\terror(\"failed to write file (wanted %d bytes, wrote %d bytes); (error code %d)\", count, didWrite, GetLastError());\n\n\t\t\treturn (size_t) didWrite;\n\t\t#else\n\t\t\treturn write(fd, buf, count);\n\t\t#endif\n\t}\n\n\n\n\tbool checkFileExists(const std::string& path)\n\t{\n\t\t#if OS_WINDOWS\n\t\t\tTCHAR* p = (TCHAR*) path.c_str();\n\t\t\tDWORD dwAttrib = GetFileAttributes(p);\n\t\t\treturn (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));\n\t\t#else\n\t\t\tstruct stat st;\n\t\t\treturn stat(path.c_str(), &st) == 0;\n\t\t#endif\n\t}\n\n\n\n\n\tstd::string getFullPath(const std::string& partial)\n\t{\n\t\t#if OS_WINDOWS\n\t\t{\n\t\t\t// auto checkFileExists = [](const TCHAR* szPath) -> bool {\n\t\t\t// \tDWORD dwAttrib = GetFileAttributes(szPath);\n\t\t\t// \treturn (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));\n\t\t\t// };\n\n\t\t\tstd::string p = partial;\n\t\t\tstd::replace(p.begin(), p.end(), '/', '\\\\');\n\n\n\t\t\tHANDLE hd = CreateFile((LPCSTR) p.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);\n\t\t\tif(hd == INVALID_HANDLE_VALUE)\n\t\t\t\treturn \"\";\n\n\t\t\t// ok, presumably it exists.\n\t\t\tdefer(CloseHandle(hd));\n\n\t\t\tTCHAR* out = new TCHAR[MAX_PATH];\n\t\t\tdefer(delete[] out);\n\t\t\tauto ret = GetFinalPathNameByHandleA(hd, out, MAX_PATH, VOLUME_NAME_DOS);\n\n\t\t\tif(ret != 0)\n\t\t\t{\n\t\t\t\tauto str = std::string(out);\n\n\t\t\t\treturn str;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn \"\";\n\t\t\t}\n\t\t}\n\t\t#else\n\t\t{\n\t\t\tauto ret = realpath(partial.c_str(), 0);\n\t\t\tif(ret == 0) return \"\";\n\n\t\t\tauto str = std::string(ret);\n\t\t\tfree(ret);\n\n\t\t\treturn str;\n\t\t}\n\t\t#endif\n\t}\n\n#ifdef _MSC_VER\n#else\n\t#pragma GCC diagnostic push\n\t#pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#endif\n\n\tsize_t getTerminalWidth()\n\t{\n\t\t#if OS_WINDOWS\n\t\t{\n\t\t\tCONSOLE_SCREEN_BUFFER_INFO csbi;\n\t\t\tGetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);\n\t\t\treturn csbi.srWindow.Right - csbi.srWindow.Left + 1;\n\t\t}\n\t\t#else\n\t\t{\n\t\t\tstruct winsize w;\n\t\t\tioctl(STDOUT_FILENO, TIOCGWINSZ, &w);\n\t\t\treturn w.ws_col;\n\t\t}\n\t\t#endif\n\t}\n\n\tvoid setupTerminalIfNecessary()\n\t{\n\t\t#if OS_WINDOWS\n\n\t\t\t// first, enable ansi colours\n\t\t\tstd::vector<DWORD> handles = {\n\t\t\t\tSTD_OUTPUT_HANDLE,\n\t\t\t\tSTD_ERROR_HANDLE\n\t\t\t};\n\n\t\t\tfor(auto x : handles)\n\t\t\t{\n\t\t\t\tauto h = GetStdHandle(x);\n\t\t\t\tSetConsoleMode(h, ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);\n\t\t\t}\n\n\t\t\t// then, change the codepage to utf-8:\n\t\t\tSetConsoleCP(CP_UTF8);\n\n\t\t#else\n\n\t\t#endif\n\t}\n\n\tvoid setupCrashHandlers()\n\t{\n\t\t#if OS_WINDOWS\n\n\t\t#else\n\t\t\tsignal(SIGSEGV, [](int) -> void {\n\t\t\t\tconstexpr const char* msg = COLOUR_RED_BOLD \"\\n\\ncompiler crash! \" COLOUR_RESET \"(segmentation fault)\\n\"\n\t\t\t\t\t\t\t\t\t\t\tCOLOUR_BLUE_BOLD \"stacktrace:\\n\" COLOUR_RESET;\n\n\t\t\t\twrite(1, msg, strlen(msg));\n\n\t\t\t\t// note: this does not care about being re-entrant in signal handlers.\n\t\t\t\t// fuck that noise.\n\t\t\t\tprintStackTrace();\n\n\t\t\t\tabort();\n\t\t\t});\n\t\t#endif\n\t}\n\n#ifdef _MSC_VER\n#else\n\t#pragma GCC diagnostic pop\n#endif\n\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/repl/commands.cpp",
    "content": "// commands.cpp\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include <sstream>\n\n#include \"defs.h\"\n#include \"repl.h\"\n#include \"ztmu.h\"\n\n#include \"sst.h\"\n#include \"ir/type.h\"\n\nnamespace repl\n{\n\tstatic void print_help();\n\tstatic void print_type(const std::string& expr);\n\n\tbool runCommand(const std::string& s, ztmu::State* consoleState)\n\t{\n\t\tif(s == \"q\")\n\t\t{\n\t\t\trepl::log(\"exiting repl\");\n\t\t\treturn true;\n\t\t}\n\t\telse if(s == \"reset\")\n\t\t{\n\t\t\trepl::setupEnvironment();\n\t\t\trepl::log(\"environment reset\");\n\t\t}\n\t\telse if(s == \"help\" || s == \"?\")\n\t\t{\n\t\t\tprint_help();\n\t\t}\n\t\telse if(s.find(\"t \") == 0)\n\t\t{\n\t\t\tprint_type(s.substr(2));\n\t\t}\n\t\telse if(s.find(\"clear_history\") == 0)\n\t\t{\n\t\t\t// just loading an empty history will effectively clear the history.\n\t\t\tconsoleState->loadHistory({ });\n\t\t}\n\t\telse\n\t\t{\n\t\t\trepl::error(\"invalid command '%s'\", s);\n\t\t}\n\n\t\treturn false;\n\t}\n\n\n\n\n\n\n\tstatic void print_type(const std::string& line)\n\t{\n\t\tbool needmore = false;\n\t\tauto stmt = repl::parseAndTypecheck(line, &needmore);\n\t\tif(needmore)\n\t\t{\n\t\t\trepl::error(\"':t' does not support continuations\");\n\t\t}\n\t\telse if(!stmt)\n\t\t{\n\t\t\trepl::error(\"invalid expression\");\n\t\t}\n\t\telse if(auto expr = dcast(sst::Expr, *stmt))\n\t\t{\n\t\t\tzpr::println(\"%s%s%s: %s\", COLOUR_GREY_BOLD, line, COLOUR_RESET, expr->type);\n\t\t}\n\t\telse\n\t\t{\n\t\t\trepl::error(\"'%s' is not an expression\", (*stmt)->readableName);\n\t\t}\n\t}\n\n\n\n\tstatic std::vector<std::string> helpLines = {\n\t\tzpr::sprint(\"\"),\n\t\tzpr::sprint(\"%s*%s overview %s*%s\", COLOUR_GREEN_BOLD, COLOUR_RESET, COLOUR_GREEN_BOLD, COLOUR_RESET),\n\t\tzpr::sprint(\"\\u203e\\u203e\\u203e\\u203e\\u203e\\u203e\\u203e\\u203e\\u203e\\u203e\\u203e\\u203e\"),\n\t\tzpr::sprint(\"The repl accepts Flax expressions and statements; press enter to evaluate the currently entered\"\n\t\t\t\" input. If the input was incomplete (eg. ending with a '{'), then the repl will enter a multi-line continuation\"\n\t\t\t\" mode. In either case, use the standard keybindings (arrow keys, home/end, etc.) to navigate.\"),\n\t\tzpr::sprint(\"\"),\n\t\tzpr::sprint(\"Any definitions (eg. variables, functions) will be treated as if they were declared at global\"\n\t\t\t\" scope, while expressions and statements (eg. loops, arithmetic) will be treated as if they were\"\n\t\t\t\" written in a function body.\"),\n\t\tzpr::sprint(\"\"),\n\t\tzpr::sprint(\"Expressions with values (eg. 3 + 1) will be given monotonic identifiers (eg. %s_0%s, %s_1%s) that\"\n\t\t\t\" can be used like any other identifier in code.\", COLOUR_BLUE, COLOUR_RESET, COLOUR_BLUE, COLOUR_RESET),\n\t\tzpr::sprint(\"\"),\n\t\tzpr::sprint(\"Commands begin with ':', and modify the state of the repl or perform other meta-actions.\"),\n\n\t\tzpr::sprint(\"\"),\n\t\tzpr::sprint(\"%s*%s commands %s*%s\", COLOUR_GREEN_BOLD, COLOUR_RESET, COLOUR_GREEN_BOLD, COLOUR_RESET),\n\t\tzpr::sprint(\"\\u203e\\u203e\\u203e\\u203e\\u203e\\u203e\\u203e\\u203e\\u203e\\u203e\\u203e\\u203e\"),\n\t\tzpr::sprint(\" :? / :help        -  display help (this listing)\"),\n\t\tzpr::sprint(\" :q                -  quit the repl\"),\n\t\tzpr::sprint(\" :reset            -  reset the environment, discarding all existing definitions\"),\n\t\tzpr::sprint(\" :clear_history    -  clear the history of things\"),\n\t\tzpr::sprint(\" :t <expr>         -  display the type of an expression\"),\n\t};\n\n\tstatic void print_help()\n\t{\n\t\tauto xs = ztmu::prettyFormatTextBlock(helpLines, \" \", \" \");\n\t\tfor(const auto& x : xs)\n\t\t\tzpr::println(x);\n\t}\n\n}\n\n\n\n\n\n\n"
  },
  {
    "path": "source/repl/driver.cpp",
    "content": "// driver.cpp\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include <stdlib.h>\n\n#include \"repl.h\"\n#include \"frontend.h\"\n\n#define ZTMU_CREATE_IMPL 1\n#include \"ztmu.h\"\n\nnamespace repl\n{\n\tstatic constexpr const char* PROMPT_STRING      = COLOUR_BLUE_BOLD \" * \" COLOUR_GREY_BOLD \">\" COLOUR_RESET \" \";\n\tstatic constexpr const char* WRAP_PROMPT_STRING = COLOUR_GREY_BOLD \" |\" COLOUR_RESET \" \";\n\tstatic constexpr const char* CONT_PROMPT_STRING = COLOUR_YELLOW_BOLD \".. \" COLOUR_GREY_BOLD \">\" COLOUR_RESET \" \";\n\n\tstatic constexpr const char* EXTRA_INDENT       = \"  \";\n\tstatic constexpr size_t EXTRA_INDENT_LEN        = std::char_traits<char>::length(EXTRA_INDENT);\n\n\tvoid start()\n\t{\n\t\tzpr::println(\"flax repl -- version %s\", frontend::getVersion());\n\t\tzpr::println(\"type %s:?%s for help\\n\", COLOUR_GREEN_BOLD, COLOUR_RESET);\n\n\t\trepl::setupEnvironment();\n\n\t\tauto st = ztmu::State();\n\t\tst.setPrompt(PROMPT_STRING);\n\t\tst.setContPrompt(CONT_PROMPT_STRING);\n\t\tst.setWrappedPrompt(WRAP_PROMPT_STRING);\n\t\tst.setMessageOnControlC(zpr::sprint(\"%s(use %s:q%s to quit)%s\", COLOUR_GREY_BOLD, COLOUR_GREEN, COLOUR_GREY_BOLD, COLOUR_RESET));\n\n\t\t// temporary.\n\t\tst.enableExitOnEmptyControlC();\n\n\t\t// load the history.\n\t\tst.loadHistory(repl::loadHistory());\n\n\t\t// setup the console (on windows, this changes to utf8 codepage.)\n\t\tst.setupConsole();\n\n\t\t// we need to put this up here, so the handler can capture it.\n\t\tint indentLevel = 0;\n\n\t\tst.setKeyHandler(static_cast<ztmu::Key>('}'), [&indentLevel](ztmu::State* st, ztmu::Key k) -> ztmu::HandlerAction {\n\t\t\t// a bit dirty, but we just do this -- if we can find the indent at the back, then remove it.\n\t\t\tauto line = st->getCurrentLine();\n\t\t\tif(indentLevel > 0 && line.size() >= 2 && line.find(EXTRA_INDENT, line.size() - EXTRA_INDENT_LEN) != -1)\n\t\t\t{\n\t\t\t\tst->setCurrentLine(line.substr(0, line.size() - 2));\n\t\t\t\tindentLevel--;\n\t\t\t}\n\n\t\t\treturn ztmu::HandlerAction::CONTINUE;\n\t\t});\n\n\t\twhile(auto line = st.read())\n\t\t{\n\t\t\tauto input = std::string(*line);\n\n\t\t\tif(input.empty())\n\t\t\t\tcontinue;\n\n\t\t\t// commands start with ':', but also allow '::' path-prefix.\n\t\t\tif(input[0] == ':' && input.find(\"::\") != 0)\n\t\t\t{\n\t\t\t\tauto quit = repl::runCommand(input.substr(1), &st);\n\t\t\t\tif(quit) break;\n\t\t\t}\n\t\t\telse if(bool needmore = repl::processLine(input); needmore)\n\t\t\t{\n\t\t\t\tsize_t last_indented_line = 0;\n\t\t\t\tauto calc_indent = [&last_indented_line, &st](char c) -> int {\n\n\t\t\t\t\t// note: we use +1 so that last_indented_line is 1-indexed. this\n\t\t\t\t\t// entire thing is so we don't get increasing indentation levels if\n\t\t\t\t\t// we delete and re-enter on a brace.\n\t\t\t\t\tif(last_indented_line == 0 || st.lineIdx + 1 > last_indented_line)\n\t\t\t\t\t{\n\t\t\t\t\t\tswitch(c)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase '{': [[fallthrough]];\n\t\t\t\t\t\t\tcase '(': [[fallthrough]];\n\t\t\t\t\t\t\tcase '[': [[fallthrough]];\n\t\t\t\t\t\t\tcase ',': {\n\t\t\t\t\t\t\t\tlast_indented_line = st.lineIdx + 1;\n\t\t\t\t\t\t\t\treturn 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn 0;\n\t\t\t\t};\n\n\t\t\t\tauto join_lines = [](const std::vector<std::string>& lines) -> std::string {\n\t\t\t\t\tstd::string ret;\n\t\t\t\t\tfor(const auto& l : lines)\n\t\t\t\t\t\tret += \"\\n\" + l;\n\n\t\t\t\t\treturn ret;\n\t\t\t\t};\n\n\t\t\t\tindentLevel = calc_indent(input.back());\n\n\t\t\t\t// read more.\n\t\t\t\twhile(auto lines = st.readContinuation(std::string(indentLevel * EXTRA_INDENT_LEN, ' ')))\n\t\t\t\t{\n\t\t\t\t\tauto input = join_lines(*lines);\n\t\t\t\t\tindentLevel += calc_indent(input.back());\n\n\t\t\t\t\tneedmore = repl::processLine(input);\n\n\t\t\t\t\tif(!needmore)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tst.addPreviousInputToHistory();\n\n\t\t\t// add an extra line\n\t\t\tprintf(\"\\n\");\n\t\t}\n\n\t\t// save the history.\n\t\trepl::saveHistory(st.getHistory());\n\n\t\t// restore the console.\n\t\tst.unsetupConsole();\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/repl/execute.cpp",
    "content": "// execute.cpp\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"repl.h\"\n#include \"parser.h\"\n#include \"frontend.h\"\n#include \"parser_internal.h\"\n\n#include \"codegen.h\"\n#include \"typecheck.h\"\n\n#include \"ir/module.h\"\n#include \"ir/interp.h\"\n#include \"ir/irbuilder.h\"\n\n#include \"memorypool.h\"\n\n// defined in codegen/directives.cpp\nfir::ConstantValue* magicallyRunExpressionAtCompileTime(cgn::CodegenState* cs, sst::Stmt* stmt, fir::Type* infer,\n\tconst fir::Name& fname, fir::interp::InterpState* is = 0);\n\nnamespace repl\n{\n\tstruct State\n\t{\n\t\tState()\n\t\t{\n\t\t\tauto modname = \"__repl_mod__\";\n\n\t\t\tthis->module = new fir::Module(modname);\n\n\t\t\tsst::StateTree* tree = new sst::StateTree(modname, 0);\n\t\t\tthis->fs = new sst::TypecheckState(tree);\n\t\t\tthis->cs = new cgn::CodegenState(fir::IRBuilder(this->module));\n\t\t\tthis->cs->module = this->module;\n\n\n\t\t\tthis->interpState = new fir::interp::InterpState(this->module);\n\t\t\tthis->interpState->initialise(/* runGlobalInit: */ true);\n\n\t\t\t// so we don't crash, give us a starting location.\n\t\t\tthis->cs->pushLoc(Location());\n\t\t}\n\n\t\t~State()\n\t\t{\n\t\t\tdelete this->interpState;\n\t\t\tdelete this->cs;\n\t\t\tdelete this->fs;\n\t\t\tdelete this->module;\n\t\t}\n\n\t\tfir::Module* module;\n\t\tcgn::CodegenState* cs;\n\t\tsst::TypecheckState* fs;\n\t\tfir::interp::InterpState* interpState;\n\n\t\tsize_t fnCounter = 0;\n\t\tsize_t varCounter = 0;\n\t};\n\n\tstatic State* state = 0;\n\tvoid setupEnvironment()\n\t{\n\t\tif(state)\n\t\t\tdelete state;\n\n\t\tstate = new State();\n\t}\n\n\tvoid setEnvironment(State* st)\n\t{\n\t\tstate = st;\n\t}\n\n\tState* getEnvironment()\n\t{\n\t\treturn state;\n\t}\n\n\n\tstd::optional<sst::Stmt*> parseAndTypecheck(const std::string& line, bool* needmore)\n\t{\n\t\tstd::string replName = \"<repl>\";\n\n\t\tfrontend::CollectorState collector;\n\n\t\t// lex.\n\t\tplatform::cachePreExistingFile(replName, line);\n\t\tauto lexResult = frontend::lexTokensFromString(replName, line);\n\n\t\t// parse, but first setup the environment.\n\t\tauto st = parser::State(lexResult.tokens);\n\t\tauto _stmt = parser::parseStmt(st, /* exprs: */ true);\n\n\t\t*needmore = false;\n\t\tif(_stmt.needsMoreTokens())\n\t\t{\n\t\t\t*needmore = true;\n\t\t\treturn std::nullopt;\n\t\t}\n\t\telse if(_stmt.isError())\n\t\t{\n\t\t\t_stmt.err()->post();\n\n\t\t\treturn std::nullopt;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto stmt = _stmt.val();\n\n\t\t\t// ugh.\n\t\t\tauto tcr = TCResult(reinterpret_cast<sst::Stmt*>(0));\n\n\t\t\t// there's no need to fiddle with AST-level trees -- once we typecheck it,\n\t\t\t// it will store the relevant state into the TypecheckState.\n\n\t\t\ttry\n\t\t\t{\n\t\t\t\t// note: usually, visitDeclarables in the top-level typecheck will set the realScope.\n\t\t\t\t// BUT, since we're not doing that, we must set it manually!\n\t\t\t\tif(auto def = dcast(ast::Parameterisable, stmt); def)\n\t\t\t\t\tdef->enclosingScope = state->fs->scope();\n\n\t\t\t\ttcr = stmt->typecheck(state->fs);\n\t\t\t}\n\t\t\tcatch(ErrorException& ee)\n\t\t\t{\n\t\t\t\tee.err->post();\n\t\t\t\tprintf(\"\\n\");\n\n\t\t\t\treturn std::nullopt;\n\t\t\t}\n\n\t\t\tif(tcr.isError())\n\t\t\t{\n\t\t\t\ttcr.error()->post();\n\t\t\t\tprintf(\"\\n\");\n\t\t\t}\n\t\t\telse if(!tcr.isParametric() && !tcr.isDummy())\n\t\t\t{\n\t\t\t\treturn tcr.stmt();\n\t\t\t}\n\n\t\t\treturn std::nullopt;\n\t\t}\n\t}\n\n\n\tbool processLine(const std::string& line)\n\t{\n\t\t// before we begin, bring us into a new namespace.\n\t\tstate->fs->pushAnonymousTree();\n\n\t\tbool needmore = false;\n\t\tauto stmt = repl::parseAndTypecheck(line, &needmore);\n\t\tif(!stmt)\n\t\t\treturn needmore;\n\n\n\t\t{\n\t\t\t// copy some stuff over.\n\t\t\tstate->cs->typeDefnMap = state->fs->typeDefnMap;\n\n\t\t\t// so the thing is, all the previous things have already been code-generated,\n\t\t\t// and have had their initialisers run. so there's really no need for their\n\t\t\t// init pieces to stick around. we need to remove the functions as well for this\n\t\t\t// to work properly!\n\t\t\tfor(auto [ gv, pc ] : state->cs->globalInitPieces)\n\t\t\t{\n\t\t\t\tstate->module->removeFunction(pc);\n\t\t\t\tdelete pc;\n\t\t\t}\n\n\t\t\tstate->cs->globalInitPieces.clear();\n\n\t\t\t// ok, we have a thing. try to run it. note: this will help us to run is->initialise(true),\n\t\t\t// which will call the global inits. this function also calls Stmt::codegen, which will\n\t\t\t// (potentially) populate the globalInitPieces, before calling cs->finishGlobalInits(). basically,\n\t\t\t// it's all handled.\n\t\t\tauto value = magicallyRunExpressionAtCompileTime(state->cs, *stmt, nullptr,\n\t\t\t\tfir::Name::obfuscate(\"__anon_runner_\", state->fnCounter++),\n\t\t\t\tstate->interpState);\n\n\t\t\tstate->interpState->finalise();\n\n\t\t\tif(value)\n\t\t\t{\n\t\t\t\t// if it was an expression, then give it a name so we can refer to it later.\n\t\t\t\tauto init = util::pool<sst::RawValueExpr>(Location(), value->getType());\n\t\t\t\tinit->rawValue = CGResult(value);\n\n\t\t\t\tauto vardef = util::pool<sst::VarDefn>(Location());\n\t\t\t\tvardef->type = init->type;\n\t\t\t\tvardef->id = Identifier(zpr::sprint(\"_%d\", state->varCounter++), IdKind::Name);\n\t\t\t\tvardef->global = true;\n\t\t\t\tvardef->init = init;\n\n\t\t\t\tstate->fs->stree->addDefinition(vardef->id.name, vardef);\n\n\t\t\t\tzpr::println(\"%s: %s = %s\", vardef->id.name, value->getType(), value->str());\n\t\t\t}\n\t\t}\n\n\n\t\treturn false;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/repl/history.cpp",
    "content": "// history.cpp\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include <errno.h>\n#include <string.h>\n\n#include <fstream>\n\n#include \"repl.h\"\n#include \"platform.h\"\n\nnamespace repl\n{\n\tstatic std::string getConfigPath()\n\t{\n\t\tauto home = platform::getEnvironmentVar(\"HOME\");\n\n\t\t// do some checks so we don't try to write stuff into the root directory.\n\t\treturn (home + ((home.empty() || home.back() == '/') ? \"\" : \"/\")) + \".flax-repl-history\";\n\t}\n\n\n\tvoid saveHistory(const std::vector<std::vector<std::string>>& history)\n\t{\n\t\tauto path = getConfigPath();\n\t\tauto file = std::ofstream(path, std::ios::out | std::ios::binary | std::ios::trunc);\n\t\tif(!file.is_open() || !file.good())\n\t\t{\n\t\t\trepl::log(\"failed to open file to load history (tried '%s')\", path);\n\n\t\t\tchar buf[128] = { 0 };\n\t\t#if OS_WINDOWS\n\t\t\tstrerror_s(buf, 127, errno);\n\t\t#else\n\t\t\tstrerror_r(errno, buf, 127);\n\t\t#endif\n\t\t\trepl::log(\"error was: '%s'\", buf);\n\t\t\treturn;\n\t\t}\n\n\n\t\t// the format is that each \"entry\" is NULL-terminated, while each line in each entry is just\n\t\t// newline-terminated.\n\n\t\tfor(const auto& lines : history)\n\t\t{\n\t\t\tfor(const auto& line : lines)\n\t\t\t{\n\t\t\t\tfile.write(line.c_str(), line.size());\n\t\t\t\tfile.put('\\n');\n\t\t\t}\n\n\t\t\t// write the null-terminator\n\t\t\tfile.put('\\0');\n\t\t}\n\n\t\t// ok.\n\t\tfile.close();\n\t}\n\n\tstd::vector<std::vector<std::string>> loadHistory()\n\t{\n\t\tauto path = getConfigPath();\n\t\tauto file = std::ifstream(path, std::ios::in | std::ios::binary);\n\t\tif(!file.is_open() || !file.good())\n\t\t\treturn { };\n\n\t\tstd::vector<std::vector<std::string>> history;\n\n\t\twhile(file.good())\n\t\t{\n\t\t\tstd::vector<std::string> current;\n\t\t\tfor(std::string line; std::getline(file, line, '\\n'); )\n\t\t\t{\n\t\t\t\tcurrent.push_back(line);\n\t\t\t\tif(file.peek() == '\\0')\n\t\t\t\t{\n\t\t\t\t\tfile.get();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(!current.empty())\n\t\t\t\thistory.push_back(current);\n\t\t}\n\n\n\t\tfile.close();\n\t\treturn history;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/alloc.cpp",
    "content": "// alloc.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"pts.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"ir/type.h\"\n#include \"resolver.h\"\n\n#include \"memorypool.h\"\n\nTCResult ast::AllocOp::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tfir::Type* elm = fs->convertParserTypeToFIR(this->allocTy);\n\ticeAssert(elm);\n\n\tif(this->attrs.has(attr::RAW) && this->counts.size() > 1)\n\t\terror(this, \"only one length dimension is supported for raw memory allocation (have %d)\", this->counts.size());\n\n\tstd::vector<sst::Expr*> counts = zfu::map(this->counts, [fs](ast::Expr* e) -> auto {\n\t\tauto c = e->typecheck(fs, fir::Type::getNativeWord()).expr();\n\t\tif(!c->type->isIntegerType())\n\t\t\terror(c, \"expected integer type ('i64') for alloc count, found '%s' instead\", c->type);\n\n\t\treturn c;\n\t});\n\n\t// check for initialiser.\n\tif(!elm->isClassType() && !elm->isStructType() && this->args.size() > 0)\n\t\terror(this, \"cannot provide arguments to non-struct type '%s'\", elm);\n\n\n\tfir::Type* resType = (this->attrs.has(attr::RAW) || counts.empty() ?\n\t\t(this->isMutable ? elm->getMutablePointerTo() : elm->getPointerTo()) : fir::DynamicArrayType::get(elm));\n\n\tauto ret = util::pool<sst::AllocOp>(this->loc, resType);\n\n\n\t// ok, check if we're a struct.\n\tif((elm->isStructType() || elm->isClassType()))\n\t{\n\t\tauto cdf = fs->typeDefnMap[elm];\n\t\ticeAssert(cdf);\n\n\t\tauto arguments = sst::resolver::misc::typecheckCallArguments(fs, this->args);\n\t\tauto constructor = sst::resolver::resolveConstructorCall(fs, this->loc, cdf, arguments, PolyArgMapping_t::none());\n\n\t\tret->constructor = constructor.defn();\n\t\tret->arguments = arguments;\n\t}\n\telse if(!this->args.empty())\n\t{\n\t\tif(this->args.size() > 1) error(this, \"expected 1 argument in alloc expression for non-struct type '%s' (for value-copy-initialisation), but found %d arguments instead\", this->args.size());\n\n\t\tauto args = sst::resolver::misc::typecheckCallArguments(fs, this->args);\n\t\tif(args[0].value->type != elm)\n\t\t\terror(this, \"expected argument of type '%s' for value-copy-initialisation in alloc expression, but found '%s' instead\", elm, args[0].value->type);\n\n\t\t// ok loh\n\t\tret->arguments = args;\n\t}\n\n\tif(this->initBody)\n\t{\n\t\ticeAssert(!this->attrs.has(attr::RAW) && this->counts.size() > 0);\n\n\t\t// ok, make a fake vardefn and insert it first.\n\t\tauto fake = util::pool<ast::VarDefn>(this->initBody->loc);\n\t\tfake->type = this->allocTy;\n\t\tfake->name = \"it\";\n\n\t\tauto fake2 = util::pool<ast::VarDefn>(this->initBody->loc);\n\t\tfake2->type = pts::NamedType::create(this->initBody->loc, INTUNSPEC_TYPE_STRING);\n\t\tfake2->name = \"i\";\n\n\t\t// make a temp scope to enclose it, I guess\n\t\tfs->pushAnonymousTree();\n\t\t{\n\t\t\tret->initBlockVar = dcast(sst::VarDefn, fake->typecheck(fs).defn());\n\t\t\tret->initBlockIdx = dcast(sst::VarDefn, fake2->typecheck(fs).defn());\n\t\t\tret->initBlock = dcast(sst::Block, this->initBody->typecheck(fs).stmt());\n\n\t\t\ticeAssert(ret->initBlockVar && ret->initBlockIdx && ret->initBlock);\n\t\t}\n\t\tfs->popTree();\n\t}\n\n\n\tret->elmType    = elm;\n\tret->counts     = counts;\n\tret->attrs      = this->attrs;\n\tret->isMutable  = this->isMutable;\n\n\treturn TCResult(ret);\n}\n\nTCResult ast::DeallocOp::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto ex = this->expr->typecheck(fs).expr();\n\tif(ex->type->isDynamicArrayType())\n\t\terror(ex, \"dynamic arrays are reference-counted, and cannot be manually freed\");\n\n\telse if(!ex->type->isPointerType())\n\t\terror(ex, \"expected pointer or dynamic array type to deallocate; found '%s' instead\", ex->type);\n\n\tauto ret = util::pool<sst::DeallocOp>(this->loc);\n\tret->expr = ex;\n\n\treturn TCResult(ret);\n}\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/arithmetic.cpp",
    "content": "// arithmetic.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"ir/type.h\"\n#include \"memorypool.h\"\n\n\nstatic sst::FunctionDefn* getOverloadedOperator(sst::TypecheckState* fs, const Location& loc, int kind, std::string op,\n\tstd::vector<fir::Type*> args)\n{\n\tauto tree = fs->stree;\n\twhile(tree)\n\t{\n\t\tint best = 10000000;\n\t\tstd::vector<sst::FunctionDefn*> cands;\n\n\t\tauto thelist = (kind == 0 ? &tree->infixOperatorOverloads : (kind == 1\n\t\t\t? &tree->prefixOperatorOverloads : &tree->postfixOperatorOverloads));\n\n\t\tfor(auto ovp : (*thelist)[op])\n\t\t{\n\t\t\tint dist = sst::getOverloadDistance(zfu::map(ovp->params, [](const auto& p) { return p.type; }), args);\n\t\t\tif(dist == -1) continue;\n\n\t\t\tif(dist == best)\n\t\t\t{\n\t\t\t\tcands.push_back(ovp);\n\t\t\t}\n\t\t\telse if(dist < best)\n\t\t\t{\n\t\t\t\tbest = dist;\n\n\t\t\t\tcands.clear();\n\t\t\t\tcands.push_back(ovp);\n\t\t\t}\n\t\t}\n\n\t\tif(cands.size() > 0)\n\t\t{\n\t\t\tif(cands.size() > 1)\n\t\t\t{\n\t\t\t\tauto err = SimpleError::make(loc, \"ambiguous use of overloaded operator '%s'\", op);\n\n\t\t\t\tfor(auto c : cands)\n\t\t\t\t\terr->append(SimpleError::make(MsgType::Note, c->loc, \"potential overload candidate here:\"));\n\n\t\t\t\terr->postAndQuit();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn cands[0];\n\t\t\t}\n\t\t}\n\n\t\t// only go up if we didn't find anything here.\n\t\ttree = tree->parent;\n\t}\n\n\treturn 0;\n}\n\n\n\nfir::Type* sst::TypecheckState::getBinaryOpResultType(fir::Type* left, fir::Type* right, const std::string& op, sst::FunctionDefn** overloadFn)\n{\n\tif(op == Operator::LogicalOr || op == Operator::LogicalAnd || op == Operator::LogicalNot)\n\t{\n\t\treturn fir::Type::getBool();\n\t}\n\telse if(op == Operator::CompareEQ || op == Operator::CompareNEQ)\n\t{\n\t\tif(left == right || fir::getCastDistance(left, right) >= 0 || fir::getCastDistance(right, left) >= 0\n\t\t\t|| (left->isConstantNumberType() && right->isConstantNumberType()))\n\t\t{\n\t\t\treturn fir::Type::getBool();\n\t\t}\n\t}\n\telse if(op == Operator::CompareLT || op == Operator::CompareGT || op == Operator::CompareLEQ || op == Operator::CompareGEQ)\n\t{\n\t\t// we handle this separately because we only want to check for number types and string types.\n\t\tbool ty_compat = (left == right || fir::getCastDistance(left, right) >= 0 || fir::getCastDistance(right, left) >= 0\n\t\t\t|| (left->isConstantNumberType() && right->isConstantNumberType()));\n\n\t\tbool ty_comparable = (left->isStringType() || left->isArraySliceType() || left->isArrayType() || left->isDynamicArrayType()\n\t\t\t|| left->isPrimitiveType() || left->isEnumType() || left->isConstantNumberType());\n\n\t\tif(ty_compat && ty_comparable)\n\t\t{\n\t\t\treturn fir::Type::getBool();\n\t\t}\n\t}\n\telse if(op == Operator::TypeIs)\n\t{\n\t\treturn fir::Type::getBool();\n\t}\n\telse if(op == Operator::TypeCast)\n\t{\n\t\tif(right->isUnionVariantType())\n\t\t\treturn right->toUnionVariantType()->getInteriorType();\n\n\t\treturn right;\n\t}\n\telse if(op == Operator::Plus)\n\t{\n\t\tif(left->isConstantNumberType() && right->isConstantNumberType())\n\t\t\treturn fir::unifyConstantTypes(left->toConstantNumberType(), right->toConstantNumberType());\n\n\t\telse if(left->isPrimitiveType() && right->isPrimitiveType() && left == right)\n\t\t\treturn left;\n\n\t\telse if(left->isStringType() && (right->isStringType() || right->isCharSliceType() || right->isCharType()))\n\t\t\treturn fir::Type::getString();\n\n\t\telse if(left->isDynamicArrayType() && right->isDynamicArrayType() && left == right)\n\t\t\treturn left;\n\n\t\telse if(left->isDynamicArrayType() && left->getArrayElementType() == right)\n\t\t\treturn left;\n\n\t\telse if((left->isConstantNumberType() && right->isPrimitiveType()) || (left->isPrimitiveType() && right->isConstantNumberType()))\n\t\t\treturn (left->isConstantNumberType() ? right : left);\n\n\t\telse if(left->isPointerType() && (right->isIntegerType() || right->isConstantNumberType()))\n\t\t\treturn left;\n\n\t\telse if(right->isPointerType() && (left->isIntegerType() || left->isConstantNumberType()))\n\t\t\treturn right;\n\t}\n\telse if(op == Operator::Minus)\n\t{\n\t\tif(left->isConstantNumberType() && right->isConstantNumberType())\n\t\t\treturn fir::unifyConstantTypes(left->toConstantNumberType(), right->toConstantNumberType());\n\n\t\telse if(left->isPrimitiveType() && right->isPrimitiveType() && left == right)\n\t\t\treturn left;\n\n\t\telse if((left->isConstantNumberType() && right->isPrimitiveType()) || (left->isPrimitiveType() && right->isConstantNumberType()))\n\t\t\treturn (left->isConstantNumberType() ? right : left);\n\n\t\telse if(left->isPointerType() && (right->isIntegerType() || right->isConstantNumberType()))\n\t\t\treturn left;\n\n\t\telse if(right->isPointerType() && (left->isIntegerType() || left->isConstantNumberType()))\n\t\t\treturn right;\n\t}\n\telse if(op == Operator::Multiply)\n\t{\n\t\tif(left->isConstantNumberType() && right->isConstantNumberType())\n\t\t\treturn fir::unifyConstantTypes(left->toConstantNumberType(), right->toConstantNumberType());\n\n\t\telse if(left->isPrimitiveType() && right->isPrimitiveType() && left == right)\n\t\t\treturn left;\n\n\t\telse if((left->isConstantNumberType() && right->isPrimitiveType()) || (left->isPrimitiveType() && right->isConstantNumberType()))\n\t\t\treturn (left->isConstantNumberType() ? right : left);\n\n\t}\n\telse if(op == Operator::Divide)\n\t{\n\t\tif(left->isConstantNumberType() && right->isConstantNumberType())\n\t\t\treturn fir::unifyConstantTypes(left->toConstantNumberType(), right->toConstantNumberType());\n\n\t\telse if(left->isPrimitiveType() && right->isPrimitiveType() && left == right)\n\t\t\treturn left;\n\n\t\telse if((left->isConstantNumberType() && right->isPrimitiveType()) || (left->isPrimitiveType() && right->isConstantNumberType()))\n\t\t\treturn (left->isConstantNumberType() ? right : left);\n\t}\n\telse if(op == Operator::Modulo)\n\t{\n\t\tif(left->isConstantNumberType() && right->isConstantNumberType())\n\t\t{\n\t\t\treturn fir::unifyConstantTypes(left->toConstantNumberType(), right->toConstantNumberType());\n\t\t}\n\t\telse if((left->isIntegerType() && right->isIntegerType()) || (left->isFloatingPointType() && right->isFloatingPointType()))\n\t\t{\n\t\t\treturn (left->getBitWidth() > right->getBitWidth()) ? left : right;\n\t\t}\n\t\telse if((left->isIntegerType() && right->isFloatingPointType()) || (left->isFloatingPointType() && right->isIntegerType()))\n\t\t{\n\t\t\treturn (left->isFloatingPointType() ? left : right);\n\t\t}\n\t\telse if((left->isConstantNumberType() && right->isPrimitiveType()) || (left->isPrimitiveType() && right->isConstantNumberType()))\n\t\t{\n\t\t\treturn (left->isConstantNumberType() ? right : left);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn left;\n\t\t}\n\t}\n\telse if(zfu::match(op, Operator::BitwiseOr, Operator::BitwiseAnd, Operator::BitwiseXor))\n\t{\n\t\tif(left == right)\n\t\t\treturn left;\n\t}\n\n\n\t// ok, check the operator map.\n\t{\n\t\tauto oper = getOverloadedOperator(this, this->loc(), 0, op, { left, right });\n\t\tif(oper)\n\t\t{\n\t\t\tif(overloadFn) *overloadFn = oper;\n\t\t\treturn oper->returnType;\n\t\t}\n\t}\n\n\n\treturn 0;\n}\n\n\n\nTCResult ast::BinaryOp::typecheck(sst::TypecheckState* fs, fir::Type* inferred)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\ticeAssert(!Operator::isAssignment(this->op));\n\n\tauto l = this->left->typecheck(fs, inferred).expr();\n\n\tsst::Expr* r = 0;\n\n\t//* this checks for the cast like this: `foo as mut` or `foo as !mut`\n\t//* the former makes an immutable thing mutable, and the latter vice versa.\n\tif(auto mte = dcast(MutabilityTypeExpr, this->right))\n\t{\n\t\t// see what the left side type is.\n\t\tif(l->type->isPointerType())\n\t\t{\n\t\t\tif(l->type->isMutablePointer() == mte->mut)\n\t\t\t\twarn(this, \"redundant cast: type '%s' is already %smutable\", l->type, mte->mut ? \"\" : \"im\");\n\n\t\t\tif(mte->mut)    r = sst::TypeExpr::make(mte->loc, l->type->getMutablePointerVersion());\n\t\t\telse            r = sst::TypeExpr::make(mte->loc, l->type->getImmutablePointerVersion());\n\t\t}\n\t\telse if(l->type->isArraySliceType())\n\t\t{\n\t\t\tif(l->type->toArraySliceType()->isMutable() == mte->mut)\n\t\t\t\twarn(this, \"redundant cast: type '%s' is already %smutable\", l->type, mte->mut ? \"\" : \"im\");\n\n\t\t\tr = sst::TypeExpr::make(mte->loc, fir::ArraySliceType::get(l->type->getArrayElementType(), mte->mut));\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(this, \"invalid cast: type '%s' does not distinguish between mutable and immutable variants\", l->type);\n\t\t}\n\t}\n\telse\n\t{\n\t\tthis->right->checkAsType = (this->op == Operator::TypeCast || this->op == Operator::TypeIs);\n\t\tif(this->right->checkAsType && l->type->isUnionType())\n\t\t\tinferred = l->type;\n\n\t\tr = this->right->typecheck(fs, inferred).expr();\n\n\t\tif(this->right->checkAsType)\n\t\t\tr = util::pool<sst::TypeExpr>(r->loc, r->type);\n\n\t\t// final check -- see if we're trying to unwrap to a union variant with no value (ie. a void type!)\n\t\t// note: this is valid if we're just checking 'if' -- but not if we're casting (ie unwrapping!)\n\t\tif(this->op == Operator::TypeCast && l->type->isUnionType() && r->type->isUnionVariantType()\n\t\t\t&& r->type->toUnionVariantType()->getInteriorType()->isVoidType())\n\t\t{\n\t\t\terror(this->right, \"unwrapping a value (of union type '%s') to the variant '%s' does not yield a value (the variant has no data)\",\n\t\t\t\tl->type, r->type->toUnionVariantType()->getName());\n\t\t}\n\t}\n\n\ticeAssert(l && r);\n\n\tauto lt = l->type;\n\tauto rt = r->type;\n\n\tsst::FunctionDefn* overloadFn = 0;\n\n\tfir::Type* rest = fs->getBinaryOpResultType(lt, rt, this->op, &overloadFn);\n\tif(!rest)\n\t{\n\t\tSpanError::make(SimpleError::make(this->loc, \"unsupported operator '%s' between types '%s' and '%s'\", this->op, lt, rt))\n\t\t\t->add(util::ESpan(this->left->loc, strprintf(\"type '%s'\", lt)))\n\t\t\t->add(util::ESpan(this->right->loc, strprintf(\"type '%s'\", rt)))\n\t\t\t->postAndQuit();\n\t}\n\n\tauto ret = util::pool<sst::BinaryOp>(this->loc, rest);\n\n\tret->left = dcast(sst::Expr, l);\n\tret->right = dcast(sst::Expr, r);\n\tret->op = this->op;\n\n\tret->overloadedOpFunction = overloadFn;\n\n\treturn TCResult(ret);\n}\n\nTCResult ast::UnaryOp::typecheck(sst::TypecheckState* fs, fir::Type* inferred)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto v = this->expr->typecheck(fs, inferred).expr();\n\n\tauto t = v->type;\n\tfir::Type* out = 0;\n\n\t// check for custom ops first, i guess.\n\t{\n\t\tauto oper = getOverloadedOperator(fs, this->loc, this->isPostfix ? 2 : 1, this->op, { t });\n\t\tif(oper)\n\t\t{\n\t\t\tauto ret = util::pool<sst::UnaryOp>(this->loc, oper->returnType);\n\t\t\tret->op = this->op;\n\t\t\tret->expr = v;\n\n\t\t\tret->overloadedOpFunction = oper;\n\t\t\treturn TCResult(ret);\n\t\t}\n\t}\n\n\n\n\tif(this->op == Operator::LogicalNot)\n\t{\n\t\t// check if we're convertible to bool\n\t\tif(!t->isBoolType())\n\t\t\terror(this, \"invalid use of logical-not-operator '!' on non-boolean type '%s'\", t);\n\n\t\tout = fir::Type::getBool();\n\t}\n\telse if(this->op == Operator::UnaryPlus || this->op == Operator::UnaryMinus)\n\t{\n\t\tif(t->isConstantNumberType())\n\t\t{\n\t\t\tout = (op == \"-\" ? fir::ConstantNumberType::get(t->toConstantNumberType()->isSigned(),\n\t\t\t\tt->toConstantNumberType()->isFloating(), t->toConstantNumberType()->getMinBits()) : t);\n\t\t}\n\t\telse if(!t->isIntegerType() && !t->isFloatingPointType())\n\t\t{\n\t\t\terror(this, \"invalid use of unary plus/minus operator '+'/'-' on non-numerical type '%s'\", t);\n\t\t}\n\t\telse if(op == \"-\" && t->isIntegerType() && !t->isSignedIntType())\n\t\t{\n\t\t\terror(this, \"invalid use of unary negation operator '-' on unsigned integer type '%s'\", t);\n\t\t}\n\t\tout = t;\n\t}\n\telse if(this->op == Operator::BitwiseNot)\n\t{\n\t\tif(t->isConstantNumberType())\n\t\t\terror(this, \"bitwise operations are not supported on literal numbers\");\n\n\t\telse if(!t->isIntegerType())\n\t\t\terror(this, \"invalid use of bitwise not operator '~' on non-integer type '%s'\", t);\n\n\t\telse if(t->isSignedIntType())\n\t\t\terror(this, \"invalid use of bitwise not operator '~' on signed integer type '%s'\", t);\n\n\t\tout = t;\n\t}\n\telse if(this->op == Operator::PointerDeref)\n\t{\n\t\tif(!t->isPointerType())\n\t\t\terror(this, \"invalid use of dereference operator '*' on non-pointer type '%s'\", t);\n\n\t\tout = t->getPointerElementType();\n\t}\n\telse if(this->op == Operator::AddressOf)\n\t{\n\t\tif(t->isFunctionType())\n\t\t\terror(this, \"cannot take the address of a function; use it as a value type\");\n\n\t\tout = t->getPointerTo();\n\t}\n\telse\n\t{\n\t\terror(this, \"unsupported unary operator '%s' on type '%s'\", this->op, v->type);\n\t}\n\n\n\tauto ret = util::pool<sst::UnaryOp>(this->loc, out);\n\tret->op = this->op;\n\tret->expr = v;\n\n\treturn TCResult(ret);\n}\n\n\n\n\n\n\n\nTCResult ast::ComparisonOp::typecheck(sst::TypecheckState* fs, fir::Type* inferred)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\ticeAssert(this->exprs.size() == this->ops.size() + 1);\n\n\t/*\n\t\tbasically, we transform us into a series of chained \"&&\" binops.\n\t\teg:\n\n\t\t10 < 20 < 30 > 25 > 15\n\n\t\tbecomes\n\n\t\t(10 < 20) && (20 < 30) && (30 > 25) && (25 > 15)\n\t*/\n\n\tstd::vector<std::pair<BinaryOp*, Location>> bins;\n\n\t// loop till the second last.\n\tfor(size_t i = 0; i < this->exprs.size() - 1; i++)\n\t{\n\t\tauto left = this->exprs[i];\n\t\tauto right = this->exprs[i + 1];\n\n\t\tauto op = this->ops[i];\n\t\tbins.push_back({ util::pool<BinaryOp>(op.second, op.first, left, right), op.second });\n\t}\n\ticeAssert(bins.size() > 0);\n\n\n\t// we handle single-comparisons too, so make sure to account for that.\n\tif(bins.size() == 1)\n\t{\n\t\treturn bins[0].first->typecheck(fs, inferred);\n\t}\n\telse\n\t{\n\t\t// make a binop combining everything, left-associatively.\n\t\ticeAssert(bins.size() > 1);\n\t\tBinaryOp* lhs = util::pool<BinaryOp>(bins[0].second, Operator::LogicalAnd, bins[0].first, bins[1].first);\n\n\t\tfor(size_t i = 2; i < bins.size(); i++)\n\t\t\tlhs = util::pool<BinaryOp>(bins[i].second, Operator::LogicalAnd, lhs, bins[i].first);\n\n\t\treturn lhs->typecheck(fs, inferred);\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/assign.cpp",
    "content": "// assign.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"ir/type.h\"\n#include \"ir/constant.h\"\n\n#include \"memorypool.h\"\n\nTCResult ast::AssignOp::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\t// check the left side\n\tauto l = this->left->typecheck(fs).expr();\n\tauto r = this->right->typecheck(fs, l->type).expr();\n\n\tif(r->type->isVoidType())\terror(this->right, \"value has void type\");\n\n\t// check if we can do it first\n\tauto lt = l->type;\n\tauto rt = r->type;\n\n\tbool skipCheck = false;\n\tif(this->op != Operator::Assign)\n\t{\n\t\tauto nonass = Operator::getNonAssignmentVersion(this->op);\n\t\tif(fs->getBinaryOpResultType(lt, rt, nonass) == 0)\n\t\t{\n\t\t\terror(this, \"unsupported operator '%s' between types '%s' and '%s', in compound assignment operator '%s'\",\n\t\t\t\tnonass, lt, rt, this->op);\n\t\t}\n\n\t\tskipCheck = true;\n\t}\n\n\n\tif(!skipCheck && lt != rt && fir::getCastDistance(rt, lt) < 0)\n\t{\n\t\tSpanError::make(SimpleError::make(this->loc, \"cannot assign value of type '%s' to expected type '%s'\", rt, lt))\n\t\t\t->add(util::ESpan(this->left->loc, strprintf(\"type '%s'\", lt)))\n\t\t\t->add(util::ESpan(this->right->loc, strprintf(\"type '%s'\", rt)))\n\t\t\t->postAndQuit();\n\t}\n\n\t//* note: check for the special case of assigning to a tuple literal, to allow the (a, b) = (b, a) swapping idiom\n\tif(auto tuple = dcast(sst::LiteralTuple, l))\n\t{\n\t\tauto ret = util::pool<sst::TupleAssignOp>(this->loc);\n\t\tfor(auto v : tuple->values)\n\t\t\tret->lefts.push_back(v);\n\n\t\tret->right = r;\n\n\t\treturn TCResult(ret);\n\t}\n\telse\n\t{\n\t\tauto ret = util::pool<sst::AssignOp>(this->loc);\n\t\tret->op = this->op;\n\t\tret->left = l;\n\t\tret->right = r;\n\n\t\treturn TCResult(ret);\n\t}\n}\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/call.cpp",
    "content": "// call.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"sst.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"resolver.h\"\n\n#include \"ir/type.h\"\n\n#include \"memorypool.h\"\n\nsst::Expr* ast::FunctionCall::typecheckWithArguments(sst::TypecheckState* fs, const std::vector<FnCallArgument>& _arguments, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tif(auto ty = fs->checkIsBuiltinConstructorCall(this->name, _arguments))\n\t{\n\t\tauto ret = util::pool<sst::ExprCall>(this->loc, ty);\n\t\tret->callee = sst::TypeExpr::make(this->loc, ty);\n\t\tret->arguments = zfu::map(_arguments, [](const auto& e) -> sst::Expr* { return e.value; });\n\n\t\treturn ret;\n\t}\n\n\t// resolve the function call here\n\tstd::vector<FnCallArgument> ts = _arguments;\n\n\tauto res = sst::resolver::resolveFunctionCall(fs, this->loc, this->name, &ts, this->mappings, this->traverseUpwards, infer);\n\n\tauto target = res.defn();\n\ticeAssert(target);\n\n\tif(auto strdf = dcast(sst::StructDefn, target))\n\t{\n\t\tauto ret = util::pool<sst::StructConstructorCall>(this->loc, strdf->type);\n\n\t\tret->target = strdf;\n\t\tret->arguments = ts;\n\n\t\treturn ret;\n\t}\n\telse if(auto uvd = dcast(sst::UnionVariantDefn, target))\n\t{\n\t\tauto unn = uvd->parentUnion;\n\t\ticeAssert(unn);\n\n\t\tauto ret = util::pool<sst::UnionVariantConstructor>(this->loc, unn->type);\n\n\t\tret->variantId = unn->type->toUnionType()->getIdOfVariant(uvd->variantName);\n\t\tret->parentUnion = unn;\n\t\tret->args = ts;\n\n\t\treturn ret;\n\t}\n\telse\n\t{\n\t\ticeAssert(target->type->isFunctionType());\n\n\t\t//* note: we check for this->name != \"init\" because when we explicitly call an init function, we don't want the extra stuff that\n\t\t//* comes with that -- we'll just treat it as a normal function call.\n\t\tif(auto fnd = dcast(sst::FunctionDefn, target); this->name != \"init\" && fnd && fnd->id.name == \"init\" && fnd->parentTypeForMethod && fnd->parentTypeForMethod->isClassType())\n\t\t{\n\t\t\t// ok, great... I guess?\n\t\t\tauto ret = util::pool<sst::ClassConstructorCall>(this->loc, fnd->parentTypeForMethod);\n\n\t\t\tret->target = fnd;\n\t\t\tret->arguments = ts;\n\t\t\tret->classty = dcast(sst::ClassDefn, fs->typeDefnMap[fnd->parentTypeForMethod]);\n\n\t\t\ticeAssert(ret->target);\n\n\t\t\treturn ret;\n\t\t}\n\n\n\n\t\tauto call = util::pool<sst::FunctionCall>(this->loc, target->type->toFunctionType()->getReturnType());\n\t\tcall->name = this->name;\n\t\tcall->target = target;\n\t\tcall->arguments = ts;\n\n\t\tif(auto fd = dcast(sst::FunctionDefn, target); fd && fd->parentTypeForMethod)\n\t\t{\n\t\t\t// check if it's a method call\n\t\t\t// if so, indicate it. here, we set 'isImplicitMethodCall' to true, as an assumption.\n\t\t\t// in DotOp's typecheck, *after* calling this typecheck(), we set it back to false\n\n\t\t\t// so, if it was really an implicit call, it remains set\n\t\t\t// if it was a dot-op call, it gets set back to false by the dotop checking.\n\n\t\t\tcall->isImplicitMethodCall = true;\n\t\t}\n\n\t\treturn call;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\nsst::Expr* ast::ExprCall::typecheckWithArguments(sst::TypecheckState* fs, const std::vector<FnCallArgument>& arguments, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\n\tauto target = this->callee->typecheck(fs).expr();\n\ticeAssert(target);\n\n\tif(!target->type->isFunctionType())\n\t\terror(this->callee, \"expression with non-function-type '%s' cannot be called\", target->type);\n\n\tauto ft = target->type->toFunctionType();\n\tauto [ dist, errs ] = sst::resolver::computeOverloadDistance(this->loc, zfu::map(ft->getArgumentTypes(), [](fir::Type* t) -> auto {\n\t\treturn fir::LocatedType(t, Location());\n\t}), zfu::map(arguments, [](const FnCallArgument& fca) -> fir::LocatedType {\n\t\treturn fir::LocatedType(fca.value->type, fca.loc);\n\t}), target->type->toFunctionType()->isCStyleVarArg(), this->loc);\n\n\tif(errs != nullptr || dist == -1)\n\t{\n\t\tauto x = SimpleError::make(this->loc, \"mismatched types in call to function pointer\");\n\t\tif(errs)    errs->prepend(x);\n\t\telse        errs = x;\n\n\t\terrs->postAndQuit();\n\t}\n\n\tauto ret = util::pool<sst::ExprCall>(this->loc, target->type->toFunctionType()->getReturnType());\n\tret->callee = target;\n\tret->arguments = zfu::map(arguments, [](const auto& e) -> sst::Expr* { return e.value; });\n\n\treturn ret;\n}\n\n\nTCResult ast::ExprCall::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\treturn TCResult(this->typecheckWithArguments(fs, sst::resolver::misc::typecheckCallArguments(fs, this->args), infer));\n}\n\nTCResult ast::FunctionCall::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\treturn TCResult(this->typecheckWithArguments(fs, sst::resolver::misc::typecheckCallArguments(fs, this->args), infer));\n}\n\n\n"
  },
  {
    "path": "source/typecheck/classes.cpp",
    "content": "// classes.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"defs.h\"\n#include \"pts.h\"\n#include \"errors.h\"\n\n#include \"ir/type.h\"\n#include \"resolver.h\"\n\n#include \"typecheck.h\"\n\n#include \"memorypool.h\"\n\n// defined in typecheck/structs.cpp\nvoid checkFieldRecursion(sst::TypecheckState* fs, fir::Type* strty, fir::Type* field, const Location& floc);\n\n\n\n\nTCResult ast::ClassDefn::generateDeclaration(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\n\tauto [ success, ret ] = this->checkForExistingDeclaration(fs, gmaps);\n\tif(!success)    return TCResult::getParametric();\n\telse if(ret)    return TCResult(ret);\n\n\tauto defnname = util::typeParamMapToString(this->name, gmaps);\n\n\tauto defn = util::pool<sst::ClassDefn>(this->loc);\n\tdefn->bareName = this->name;\n\tdefn->attrs = this->attrs;\n\n\tdefn->id = Identifier(defnname, IdKind::Type);\n\tdefn->id.scope = this->enclosingScope;\n\tdefn->visibility = this->visibility;\n\tdefn->original = this;\n\tdefn->enclosingScope = this->enclosingScope;\n\tdefn->innerScope = this->enclosingScope.appending(defnname);\n\n\n\t// make all our methods be methods\n\tfor(auto m : this->methods)\n\t{\n\t\tm->parentType = this;\n\t\tm->enclosingScope = defn->innerScope;\n\t}\n\n\tfor(auto m : this->initialisers)\n\t{\n\t\tm->parentType = this;\n\t\tm->enclosingScope = defn->innerScope;\n\t}\n\n\tfor(auto m : this->staticMethods)\n\t{\n\t\tm->enclosingScope = defn->innerScope;\n\t}\n\n\n\tauto cls = fir::ClassType::createWithoutBody(defn->id.convertToName());\n\tdefn->type = cls;\n\n\n\t// why do we do this when generating the declaration instead of only when we typecheck?\n\t// as it currently stands, this means that our base class + any traits must appear before\n\t// this class definition in the source code, which is kinda dumb.\n\tfor(auto base : zfu::map(this->bases, [fs](auto t) -> auto { return fs->convertParserTypeToFIR(t); }))\n\t{\n\t\tif(base->isClassType())\n\t\t{\n\t\t\tif(defn->baseClass)\n\t\t\t\terror(this, \"cannot inherit from more than one class (already inherited from '%s')\", defn->baseClass->id.name);\n\n\t\t\telse if(!defn->traits.empty())\n\t\t\t\terror(this, \"base class must come before any traits in the inheritance list\");\n\n\t\t\tauto basedef = dcast(sst::ClassDefn, fs->typeDefnMap[base]);\n\t\t\ticeAssert(basedef);\n\n\t\t\tdefn->baseClass = basedef;\n\t\t\tcls->setBaseClass(base->toClassType());\n\t\t}\n\t\telse if(base->isTraitType())\n\t\t{\n\t\t\tauto tdef = dcast(sst::TraitDefn, fs->typeDefnMap[base]);\n\t\t\ticeAssert(tdef);\n\n\t\t\tdefn->traits.push_back(tdef);\n\t\t\tcls->addTraitImpl(tdef->type->toTraitType());\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(this, \"invalid type '%s' in inheritance list of class\", base);\n\t\t}\n\t}\n\n\tif(auto err = fs->checkForShadowingOrConflictingDefinition(defn, [](auto, auto) -> bool { return true; }))\n\t\treturn TCResult(err);\n\n\t// add it first so we can use it in the method bodies,\n\t// and make pointers to it\n\t{\n\t\tdefn->enclosingScope.stree->addDefinition(defnname, defn, gmaps);\n\t\tfs->typeDefnMap[cls] = defn;\n\t}\n\n\tfs->teleportInto(defn->innerScope);\n\t{\n\t\tfor(auto t : this->nestedTypes)\n\t\t{\n\t\t\tt->enclosingScope = defn->innerScope;\n\t\t\tt->generateDeclaration(fs, 0, { });\n\t\t}\n\t}\n\tfs->teleportOut();\n\n\tthis->genericVersions.push_back({ defn, fs->getGenericContextStack() });\n\treturn TCResult(defn);\n}\n\nTCResult ast::ClassDefn::typecheck(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto tcr = this->generateDeclaration(fs, infer, gmaps);\n\tif(tcr.isParametric())  return tcr;\n\telse if(!tcr.isDefn())  error(this, \"failed to generate declaration for function '%s'\", this->name);\n\n\tauto defn = dcast(sst::ClassDefn, tcr.defn());\n\ticeAssert(defn);\n\n\tif(this->finishedTypechecking.find(defn) != this->finishedTypechecking.end())\n\t\treturn TCResult(defn);\n\n\tauto cls = defn->type->toClassType();\n\ticeAssert(cls);\n\n\tfs->teleportInto(defn->innerScope);\n\n\tif(this->initialisers.empty())\n\t\terror(this, \"class must have at least one initialiser\");\n\n\n\n\n\tfor(auto t : this->nestedTypes)\n\t{\n\t\tauto tcr = t->typecheck(fs);\n\t\tif(tcr.isParametric())  continue;\n\t\tif(tcr.isError())       error(t, \"failed to generate declaration for nested type '%s' in struct '%s'\", t->name, this->name);\n\n\t\tauto st = dcast(sst::TypeDefn, tcr.defn());\n\t\ticeAssert(st);\n\n\t\tdefn->nestedTypes.push_back(st);\n\t}\n\n\n\n\tfs->pushSelfContext(cls);\n\t{\n\t\tstd::vector<std::pair<std::string, fir::Type*>> tys;\n\t\tfor(auto f : this->fields)\n\t\t{\n\t\t\tauto v = dcast(sst::StructFieldDefn, f->typecheck(fs).defn());\n\t\t\ticeAssert(v);\n\n\t\t\tdefn->fields.push_back(v);\n\t\t\ttys.push_back({ v->id.name, v->type });\n\n\t\t\tcheckFieldRecursion(fs, cls, v->type, v->loc);\n\n\t\t\tstd::function<void (sst::ClassDefn*, sst::StructFieldDefn*)> checkDupe = [](sst::ClassDefn* cls, sst::StructFieldDefn* fld) -> auto {\n\t\t\t\twhile(cls)\n\t\t\t\t{\n\t\t\t\t\tfor(auto bf : cls->fields)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(bf->id.name == fld->id.name)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tSimpleError::make(fld->loc, \"redefinition of field '%s' (with type '%s'), that exists in the base class '%s'\",\n\t\t\t\t\t\t\t\tfld->id.name, fld->type, cls->id)\n\t\t\t\t\t\t\t\t->append(SimpleError::make(MsgType::Note, bf->loc, \"'%s' was previously defined in the base class here:\", fld->id.name))\n\t\t\t\t\t\t\t\t->append(SimpleError::make(MsgType::Note, cls->loc, \"base class '%s' was defined here:\", cls->id))\n\t\t\t\t\t\t\t\t->postAndQuit();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcls = cls->baseClass;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tcheckDupe(defn->baseClass, v);\n\t\t}\n\t\tcls->setMembers(tys);\n\n\n\t\t{\n\t\t\t//* check for what would be called 'method hiding' in c++, and also valid overrides.\n\t\t\t// TODO: make an error note about co/contra-variance for param/return types. right now it just complains and it's vague af.\n\t\t\tauto checkAgainstBaseClasses = [](sst::ClassDefn* cls, sst::FunctionDefn* meth) -> auto {\n\n\t\t\t\tauto checkSingleMethod = [](sst::ClassDefn* cls, sst::FunctionDefn* self, sst::FunctionDefn* bf, bool* matchedName) -> bool {\n\n\t\t\t\t\tif(bf->id.name == self->id.name)\n\t\t\t\t\t{\n\t\t\t\t\t\t*matchedName |= true;\n\n\t\t\t\t\t\tif(!fir::areMethodsVirtuallyCompatible(bf->type->toFunctionType(), self->type->toFunctionType(),\n\t\t\t\t\t\t\t/* trait checking: */ false))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// check for virtual functions.\n\t\t\t\t\t\t//* note: we don't need to care if 'bf' is the base method, because if we are 'isOverride', then we are also\n\t\t\t\t\t\t//* 'isVirtual'.\n\n\t\t\t\t\t\t// nice comprehensive error messages, I hope.\n\t\t\t\t\t\tif(!self->isOverride)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tauto err = SimpleError::make(self->loc, \"redefinition of method '%s' (with type '%s'), that exists in\"\n\t\t\t\t\t\t\t\t\" the base class '%s'\", self->id.name, self->type, cls->id);\n\n\t\t\t\t\t\t\tif(bf->isVirtual)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\terr->append(SimpleError::make(MsgType::Note, bf->loc, \"'%s' was defined as a virtual method; to override it, use the 'override' keyword\", bf->id.name));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\terr->append(\n\t\t\t\t\t\t\t\t\tSimpleError::make(MsgType::Note, bf->loc, \"'%s' was previously defined in the base class '%s'\"\n\t\t\t\t\t\t\t\t\t\t\" as a non-virtual method here:\", bf->id.name, cls->id.name\n\t\t\t\t\t\t\t\t\t\t)->append(BareError::make(MsgType::Note, \"to override it, define '%s' as a virtual method\",\n\t\t\t\t\t\t\t\t\t\t\tbf->id.name)\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\terr->postAndQuit();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(!bf->isVirtual)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tSimpleError::make(self->loc, \"cannot override non-virtual method '%s'\", bf->id.name)\n\t\t\t\t\t\t\t\t->append(SimpleError::make(MsgType::Note, bf->loc,\n\t\t\t\t\t\t\t\t\t\"'%s' was previously defined in the base class '%s' as a non-virtual method here:\", bf->id.name, cls->id.name)\n\t\t\t\t\t\t\t\t)->append(BareError::make(MsgType::Note, \"to override it, define '%s' as a virtual method\", bf->id.name))\n\t\t\t\t\t\t\t\t->postAndQuit();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t};\n\n\t\t\t\tbool matchedSig = false;\n\t\t\t\tbool matchedName = false;\n\t\t\t\twhile(cls)\n\t\t\t\t{\n\t\t\t\t\tfor(auto bf : cls->methods)\n\t\t\t\t\t\tmatchedSig |= checkSingleMethod(cls, meth, bf, &matchedName);\n\n\t\t\t\t\tcls = cls->baseClass;\n\t\t\t\t}\n\n\t\t\t\tif(meth->isOverride && !matchedSig)\n\t\t\t\t{\n\t\t\t\t\tif(matchedName && !matchedSig)\n\t\t\t\t\t{\n\t\t\t\t\t\terror(meth, \"invalid override: no method named '%s' in any base class with a signature matching\"\n\t\t\t\t\t\t\t\" (or compatible with) '%s'\", meth->id.name, meth->type->str());\n\t\t\t\t\t}\n\t\t\t\t\telse if(!matchedName)\n\t\t\t\t\t{\n\t\t\t\t\t\terror(meth, \"invalid override: no method in any base class named '%s'\", meth->id.name);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tfor(auto m : this->methods)\n\t\t\t{\n\t\t\t\tif(m->name == \"init\")\n\t\t\t\t\terror(m, \"cannot have methods named 'init' in a class; to create an initialiser, omit the 'fn' keyword.\");\n\n\t\t\t\tauto res = m->generateDeclaration(fs, cls, { });\n\t\t\t\tif(res.isParametric())\n\t\t\t\t\tcontinue;\n\n\t\t\t\tauto decl = dcast(sst::FunctionDefn, res.defn());\n\t\t\t\ticeAssert(decl);\n\n\t\t\t\tdefn->methods.push_back(decl);\n\n\t\t\t\tcheckAgainstBaseClasses(defn->baseClass, decl);\n\t\t\t}\n\t\t}\n\n\n\t\t{\n\t\t\t// make the constructors\n\t\t\tfor(auto it : this->initialisers)\n\t\t\t{\n\t\t\t\tauto decl = dcast(sst::FunctionDefn, it->generateDeclaration(fs, cls, { }).defn());\n\t\t\t\ticeAssert(decl);\n\n\t\t\t\tdefn->methods.push_back(decl);\n\t\t\t\tdefn->initialisers.push_back(decl);\n\t\t\t}\n\n\t\t\t// and the destructor\n\t\t\tif(this->deinitialiser)\n\t\t\t{\n\t\t\t\tauto decl = dcast(sst::FunctionDefn, this->deinitialiser->generateDeclaration(fs, cls, { }).defn());\n\t\t\t\ticeAssert(decl);\n\n\t\t\t\tdefn->methods.push_back(decl);\n\t\t\t\tdefn->deinitialiser = decl;\n\t\t\t}\n\t\t\tif(this->copyInitialiser)\n\t\t\t{\n\t\t\t\tauto decl = dcast(sst::FunctionDefn, this->copyInitialiser->generateDeclaration(fs, cls, { }).defn());\n\t\t\t\ticeAssert(decl);\n\n\t\t\t\tdefn->methods.push_back(decl);\n\t\t\t\tdefn->copyInitialiser = decl;\n\t\t\t}\n\t\t\tif(this->moveInitialiser)\n\t\t\t{\n\t\t\t\tauto decl = dcast(sst::FunctionDefn, this->moveInitialiser->generateDeclaration(fs, cls, { }).defn());\n\t\t\t\ticeAssert(decl);\n\n\t\t\t\tdefn->methods.push_back(decl);\n\t\t\t\tdefn->moveInitialiser = decl;\n\t\t\t}\n\t\t}\n\n\n\n\t\t// copy all the things from the superclass into ourselves.\n\t\tif(defn->baseClass)\n\t\t{\n\t\t\t// basically, the only things we want to import from the base class are fields and methods -- not initialisers.\n\t\t\t// base-class-constructors must be called using `super(...)` syntax.\n\n\t\t\tauto tree = defn->baseClass->innerScope.stree;\n\t\t\ticeAssert(tree);\n\n\t\t\tstd::function<void (sst::StateTree*, sst::StateTree*)> recursivelyImport = [&](sst::StateTree* from, sst::StateTree* to) -> void {\n\n\t\t\t\tfor(auto def : from->getAllDefinitions())\n\t\t\t\t{\n\t\t\t\t\tif(!dcast(sst::ClassInitialiserDefn, def))\n\t\t\t\t\t\tto->addDefinition(def->id.name, def);\n\t\t\t\t}\n\n\t\t\t\tfor(auto sub : from->subtrees)\n\t\t\t\t{\n\t\t\t\t\tif(to->subtrees.find(sub.first) == to->subtrees.end())\n\t\t\t\t\t\tto->findOrCreateSubtree(sub.first);\n\n\t\t\t\t\trecursivelyImport(sub.second, to->subtrees[sub.first]);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\trecursivelyImport(tree, fs->stree);\n\t\t}\n\n\t\tfor(auto f : this->staticFields)\n\t\t{\n\t\t\tauto v = dcast(sst::VarDefn, f->typecheck(fs).defn());\n\t\t\ticeAssert(v);\n\n\t\t\tdefn->staticFields.push_back(v);\n\t\t}\n\n\t\tfor(auto m : this->staticMethods)\n\t\t{\n\t\t\t// infer is 0 because this is a static thing\n\t\t\tauto res = m->generateDeclaration(fs, 0, { });\n\t\t\tif(res.isParametric())\n\t\t\t\tcontinue;\n\n\t\t\tauto decl = dcast(sst::FunctionDefn, res.defn());\n\t\t\ticeAssert(decl);\n\n\t\t\tdefn->staticMethods.push_back(decl);\n\t\t}\n\n\n\n\n\t\t// once we get all the proper declarations and such, create the function bodies.\n\t\tif(!cls->containsPlaceholders())\n\t\t{\n\t\t\tfor(auto m : this->methods)\n\t\t\t\tm->typecheck(fs, cls, { });\n\n\t\t\tfor(auto m : this->initialisers)\n\t\t\t\tm->typecheck(fs, cls, { });\n\n\t\t\tfor(auto m : this->staticMethods)\n\t\t\t\tm->typecheck(fs, 0, { });\n\n\t\t\tif(this->deinitialiser)     this->deinitialiser->typecheck(fs, cls, { });\n\t\t\tif(this->copyInitialiser)   this->copyInitialiser->typecheck(fs, cls, { });\n\t\t\tif(this->moveInitialiser)   this->moveInitialiser->typecheck(fs, cls, { });\n\t\t}\n\t}\n\tfs->popSelfContext();\n\n\n\tfs->teleportOut();\n\n\tthis->finishedTypechecking.insert(defn);\n\treturn TCResult(defn);\n}\n\n\n\n\n\n\n\n\n\n\n\n\nTCResult ast::InitFunctionDefn::typecheck(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps)\n{\n\ticeAssert(infer && infer->isClassType());\n\tauto cls = infer->toClassType();\n\n\tauto ret = dcast(sst::FunctionDefn, this->actualDefn->typecheck(fs, cls, gmaps).defn());\n\n\t// if the initialiser was polymorphic, then don't generate bodies!\n\tif(ret->type->containsPlaceholders())\n\t\treturn TCResult::getParametric();\n\n\t// only check this stuff for the real constructor.\n\tif(this->name == \"init\")\n\t{\n\t\tif(cls->getBaseClass() && !this->didCallSuper)\n\t\t{\n\t\t\terror(this, \"initialiser for class '%s' must explicitly call an initialiser of the base class '%s'\", cls->getTypeName().name,\n\t\t\t\tcls->getBaseClass()->getTypeName().name);\n\t\t}\n\t\telse if(!cls->getBaseClass() && this->didCallSuper)\n\t\t{\n\t\t\terror(this, \"cannot call base class initialiser for class '%s' when it does not inherit from a base class\",\n\t\t\t\tcls->getTypeName().name);\n\t\t}\n\t\telse if(cls->getBaseClass() && this->didCallSuper)\n\t\t{\n\t\t\tauto base = cls->getBaseClass();\n\t\t\tauto call = util::pool<sst::BaseClassConstructorCall>(this->loc, base);\n\n\t\t\tcall->classty = dcast(sst::ClassDefn, fs->typeDefnMap[base]);\n\t\t\ticeAssert(call->classty);\n\n\t\t\tstd::vector<FnCallArgument> baseargs;\n\t\t\t{\n\t\t\t\tauto restore = fs->stree;\n\t\t\t\tfs->stree = ret->insideTree;\n\n\t\t\t\tbaseargs = sst::resolver::misc::typecheckCallArguments(fs, this->superArgs);\n\n\t\t\t\tfs->stree = restore;\n\t\t\t}\n\n\t\t\tauto constr = sst::resolver::resolveConstructorCall(fs, this->loc, call->classty, baseargs, PolyArgMapping_t::none());\n\n\t\t\tcall->arguments = baseargs;\n\t\t\tcall->target = dcast(sst::FunctionDefn, constr.defn());\n\t\t\ticeAssert(call->target);\n\n\t\t\t// insert it as the first thing.\n\t\t\tret->body->statements.insert(ret->body->statements.begin(), call);\n\t\t}\n\t}\n\n\treturn TCResult(ret);\n}\n\n\nTCResult ast::InitFunctionDefn::generateDeclaration(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps)\n{\n\t//* so here's the thing\n\t//* basically this init function thingy is just a normal function definition\n\t//* but due to the way the AST was built, and because it's actually slightly less messy IMO,\n\t//* we return a separate AST type that does not inherit from FuncDefn.\n\n\t//* so, to reduce code dupe and make it less stupid, we actually make a fake FuncDefn from ourselves,\n\t//* and typecheck that, returning that as the result.\n\n\t//* we don't want to be carrying too many distinct types around in SST nodes.\n\n\ticeAssert(infer);\n\n\tthis->actualDefn = util::pool<ast::FuncDefn>(this->loc);\n\n\tthis->actualDefn->name = this->name;\n\tthis->actualDefn->body = this->body;\n\tthis->actualDefn->params = this->params;\n\tthis->actualDefn->parentType = this->parentType;\n\tthis->actualDefn->returnType = pts::NamedType::create(this->loc, VOID_TYPE_STRING);\n\n\tthis->actualDefn->enclosingScope = this->enclosingScope;\n\n\t//* note: constructors will always mutate, definitely.\n\tthis->actualDefn->isMutating = true;\n\n\tauto ret = this->actualDefn->generateDeclaration(fs, infer, gmaps);\n\tif(ret.isDefn())\n\t{\n\t\tauto def = dcast(sst::FunctionDefn, ret.defn());\n\t\ticeAssert(def);\n\n\t\t// do some checks.\n\t\tif(this->name == \"copy\")\n\t\t{\n\t\t\tif(def->params.size() != 2)\n\t\t\t{\n\t\t\t\terror(def, \"copy initialiser must take exactly one argument, %d were found\", def->params.size() - 1);\n\t\t\t}\n\t\t\telse if(auto ty = def->params[1].type; !ty->isImmutablePointer() || ty->getPointerElementType() != def->parentTypeForMethod)\n\t\t\t{\n\t\t\t\terror(def->params[1].loc, \"parameter of copy initialiser must have type '&self' (aka '%s'), found '%s' instead\",\n\t\t\t\t\tdef->parentTypeForMethod->getPointerTo(), ty);\n\t\t\t}\n\t\t}\n\t\telse if(this->name == \"move\")\n\t\t{\n\t\t\tif(def->params.size() != 2)\n\t\t\t{\n\t\t\t\terror(def, \"move initialiser must take exactly one argument, %d were found\", def->params.size() - 1);\n\t\t\t}\n\t\t\telse if(auto ty = def->params[1].type; !ty->isMutablePointer() || ty->getPointerElementType() != def->parentTypeForMethod)\n\t\t\t{\n\t\t\t\terror(def->params[1].loc, \"parameter of move initialiser must have type '&mut self' (aka '%s'), found '%s' instead\",\n\t\t\t\t\tdef->parentTypeForMethod->getMutablePointerTo(), ty);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn ret;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/controlflow.cpp",
    "content": "// controlflow.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"ir/type.h\"\n\n#include \"memorypool.h\"\n\nTCResult ast::IfStmt::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tusing Case = sst::IfStmt::Case;\n\tauto ret = util::pool<sst::IfStmt>(this->loc);\n\n\tfs->pushAnonymousTree();\n\tdefer(fs->popTree());\n\n\tfor(auto c : this->cases)\n\t{\n\t\t//* here, it is implicit that all the inits of every case live in the same scope.\n\t\t//? we might want to change this eventually? i'm not sure.\n\n\t\tauto inits = zfu::map(c.inits, [fs](Stmt* s) -> auto { return s->typecheck(fs).stmt(); });\n\t\tauto cs = Case(c.cond->typecheck(fs).expr(), dcast(sst::Block, c.body->typecheck(fs).stmt()), inits);\n\n\t\tif(!cs.cond->type->isBoolType() && !cs.cond->type->isPointerType())\n\t\t\terror(cs.cond, \"non-boolean expression with type '%s' cannot be used as a conditional\", cs.cond->type);\n\n\t\tret->cases.push_back(cs);\n\n\t\ticeAssert(ret->cases.back().body);\n\t}\n\n\tif(this->elseCase)\n\t{\n\t\tret->elseCase = dcast(sst::Block, this->elseCase->typecheck(fs).stmt());\n\t\ticeAssert(ret->elseCase);\n\t}\n\n\treturn TCResult(ret);\n}\n\nTCResult ast::ReturnStmt::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tauto ret = util::pool<sst::ReturnStmt>(this->loc);\n\n\tif(fs->isInDeferBlock())\n\t\terror(this, \"cannot 'return' while inside a deferred block\");\n\n\n\t// ok, get the current function\n\tauto fn = fs->getCurrentFunction();\n\tauto retty = fn->returnType;\n\n\tif(this->value)\n\t{\n\t\tret->value = this->value->typecheck(fs, retty).expr();\n\n\t\tif(fir::getCastDistance(ret->value->type, retty) < 0)\n\t\t{\n\t\t\tSpanError::make(SimpleError::make(this->loc, \"mismatched type in return statement; function returns '%s', value has type '%s'\",\n\t\t\t\tretty, ret->value->type))->add(util::ESpan(this->value->loc, strprintf(\"type '%s'\", ret->value->type)))\n\t\t\t\t->append(SimpleError::make(MsgType::Note, fn->loc, \"function definition is here:\"))\n\t\t\t\t->postAndQuit();\n\t\t}\n\n\t\t// ok\n\t}\n\telse if(!retty->isVoidType())\n\t{\n\t\terror(this, \"expected value after 'return'; function return type is '%s'\", retty);\n\t}\n\n\tret->expectedType = retty;\n\treturn TCResult(ret);\n}\n\n\nstatic bool checkBlockPathsReturn(sst::TypecheckState* fs, sst::Block* block, fir::Type* retty, std::vector<sst::Block*>* faulty)\n{\n\t// return value is whether or not the block had a return value;\n\t// true if all paths explicitly returned, false if not\n\t// this return value is used to determine whether we need to insert a\n\t// 'return void' thing.\n\n\tbool ret = false;\n\tfor(size_t i = 0; i < block->statements.size(); i++)\n\t{\n\t\tauto& s = block->statements[i];\n\t\tif(auto retstmt = dcast(sst::ReturnStmt, s))\n\t\t{\n\t\t\t// ok...\n\t\t\tret = true;\n\t\t\tauto t = retstmt->expectedType;\n\t\t\ticeAssert(t);\n\n\t\t\tif(fir::getCastDistance(t, retty) < 0)\n\t\t\t{\n\t\t\t\tif(retstmt->expectedType->isVoidType())\n\t\t\t\t{\n\t\t\t\t\terror(retstmt, \"expected value after 'return'; function return type is '%s'\", retty);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tstd::string msg;\n\t\t\t\t\tif(block->isSingleExpr) msg = \"invalid single-expression with type '%s' in function returning '%s'\";\n\t\t\t\t\telse                    msg = \"mismatched type in return statement; function returns '%s', value has type '%s'\";\n\n\t\t\t\t\tSpanError::make(SimpleError::make(retstmt->loc, msg.c_str(), retty, retstmt->expectedType))\n\t\t\t\t\t\t->add(util::ESpan(retstmt->value->loc, strprintf(\"type '%s'\", retstmt->expectedType)))\n\t\t\t\t\t\t->append(SimpleError::make(MsgType::Note, fs->getCurrentFunction()->loc, \"function definition is here:\"))\n\t\t\t\t\t\t->postAndQuit();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(i != block->statements.size() - 1)\n\t\t\t{\n\t\t\t\tSimpleError::make(block->statements[i + 1]->loc, \"unreachable code after return statement\")\n\t\t\t\t\t->append(SimpleError::make(MsgType::Note, retstmt->loc, \"return statement was here:\"))\n\t\t\t\t\t->postAndQuit();;\n\t\t\t}\n\t\t}\n\t\telse /* if(i == block->statements.size() - 1) */\n\t\t{\n\t\t\t//* it's our duty to check the internals of these things regardless of their exhaustiveness\n\t\t\t//* so that we can check for the elision of the merge block.\n\t\t\t//? eg: if 's' itself does not have an else case, but say one of its branches is exhaustive (all arms return),\n\t\t\t//? then we can elide the merge block for that branch, even though we can't for 's' itself.\n\t\t\t//* this isn't strictly necessary (the program is still correct without it), but we generate nicer IR this way.\n\n\t\t\tbool exhausted = false;\n\t\t\tif(auto ifstmt = dcast(sst::IfStmt, s); ifstmt)\n\t\t\t{\n\t\t\t\tbool all = true;\n\t\t\t\tfor(const auto& c: ifstmt->cases)\n\t\t\t\t\tall = all && checkBlockPathsReturn(fs, c.body, retty, faulty);\n\n\t\t\t\texhausted = all && ifstmt->elseCase && checkBlockPathsReturn(fs, ifstmt->elseCase, retty, faulty);\n\t\t\t\tifstmt->elideMergeBlock = exhausted;\n\t\t\t}\n\t\t\telse if(auto whileloop = dcast(sst::WhileLoop, s); whileloop)\n\t\t\t{\n\t\t\t\texhausted = checkBlockPathsReturn(fs, whileloop->body, retty, faulty) && whileloop->isDoVariant;\n\t\t\t\twhileloop->elideMergeBlock = exhausted;\n\t\t\t}\n\t\t\telse if(auto feloop = dcast(sst::ForeachLoop, s); feloop)\n\t\t\t{\n\t\t\t\t// we don't set 'exhausted' here beacuse for loops cannot be guaranteed to be exhaustive.\n\t\t\t\t// but we still want to check the block inside for elision.\n\t\t\t\tfeloop->elideMergeBlock = checkBlockPathsReturn(fs, feloop->body, retty, faulty);\n\t\t\t}\n\n\t\t\tret = exhausted;\n\t\t}\n\t}\n\n\treturn ret;\n}\n\nbool sst::TypecheckState::checkAllPathsReturn(FunctionDefn* fn)\n{\n\tfir::Type* expected = fn->returnType;\n\n\tstd::vector<sst::Block*> faults { fn->body };\n\tauto ret = checkBlockPathsReturn(this, fn->body, expected, &faults);\n\n\tif(!expected->isVoidType() && !ret)\n\t{\n\t\tauto err = SimpleError::make(fn->loc, \"not all paths return a value; expected value of type '%s'\", expected);\n\n\t\tfor(auto b : faults)\n\t\t\terr->append(SimpleError::make(MsgType::Note, b->closingBrace, \"potentially missing return statement here:\"));\n\n\t\terr->postAndQuit();\n\t}\n\n\treturn ret;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/defer.cpp",
    "content": "// defer.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"memorypool.h\"\n\n\nTCResult ast::DeferredStmt::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\t// disallow certain things from being deferred\n\tauto ret = this->actual->typecheck(fs, infer).stmt();\n\n\tstd::function<void (const Location&, std::vector<sst::Stmt*>)> checkRecursively\n\t\t= [&checkRecursively](const Location& loc, std::vector<sst::Stmt*> stmts) -> void\n\t{\n\t\tfor(auto stmt : stmts)\n\t\t{\n\t\t\tif(dcast(sst::Defn, stmt))\n\t\t\t{\n\t\t\t\tSimpleError::make(stmt->loc, \"definitions cannot be deferred\")\n\t\t\t\t\t->append(SimpleError::make(MsgType::Note, loc, \"in deferred block here:\"))\n\t\t\t\t\t->postAndQuit();\n\t\t\t}\n\t\t\telse if(dcast(sst::BreakStmt, stmt) || dcast(sst::ContinueStmt, stmt) || dcast(sst::ReturnStmt, stmt))\n\t\t\t{\n\t\t\t\tSimpleError::make(stmt->loc, \"control flow cannot be deferred\")\n\t\t\t\t\t->append(SimpleError::make(MsgType::Note, loc, \"in deferred block here:\"))\n\t\t\t\t\t->postAndQuit();\n\t\t\t}\n\t\t\telse if(auto hb = dcast(sst::HasBlocks, stmt))\n\t\t\t{\n\t\t\t\tfor(auto b : hb->getBlocks())\n\t\t\t\t\tcheckRecursively(loc, b->statements);\n\t\t\t}\n\t\t}\n\t};\n\n\tif(auto b = dcast(sst::Block, ret))\n\t\tcheckRecursively(this->loc, b->statements);\n\n\telse\n\t\tcheckRecursively(this->loc, { ret });\n\n\treturn TCResult(ret);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/destructure.cpp",
    "content": "// destructure.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"ir/type.h\"\n\n#include \"memorypool.h\"\n\nstatic void checkAndAddBinding(sst::TypecheckState* fs, DecompMapping* bind, fir::Type* rhs, bool immut, bool allowref);\nstatic void checkTuple(sst::TypecheckState* fs, DecompMapping* bind, fir::Type* rhs, bool immut)\n{\n\ticeAssert(!bind->array);\n\tif(!rhs->isTupleType())\n\t\terror(bind->loc, \"expected tuple type in destructuring declaration; found type '%s' instead\", rhs);\n\n\tauto tty = rhs->toTupleType();\n\tif(bind->inner.size() != tty->getElementCount())\n\t{\n\t\terror(bind->loc, \"too %s bindings in destructuring declaration; expected %d, found %d instead\",\n\t\t\t(bind->inner.size() < tty->getElementCount() ? \"few\" : \"many\"), tty->getElementCount(), bind->inner.size());\n\t}\n\n\tfor(size_t i = 0; i < tty->getElementCount(); i++)\n\t\tcheckAndAddBinding(fs, &bind->inner[i], tty->getElementN(i), immut, true);\n}\n\nstatic void checkArray(sst::TypecheckState* fs, DecompMapping* bind, fir::Type* rhs, bool immut)\n{\n\ticeAssert(bind->array);\n\n\tif(!rhs->isArrayType() && !rhs->isDynamicArrayType() && !rhs->isArraySliceType() && !rhs->isStringType())\n\t\terror(bind->loc, \"expected array type in destructuring declaration; found type '%s' instead\", rhs);\n\n\tif(rhs->isStringType())\n\t{\n\t\t//* note: special-case this, because 1. we want to return chars, but 2. strings are supposed to be immutable.\n\t\tfor(auto& b : bind->inner)\n\t\t\tcheckAndAddBinding(fs, &b, fir::Type::getInt8(), immut, false);\n\n\t\tif(!bind->restName.empty())\n\t\t{\n\t\t\tauto fake = util::pool<sst::VarDefn>(bind->loc);\n\n\t\t\tfake->id = Identifier(bind->restName, IdKind::Name);\n\t\t\tfake->immutable = immut;\n\n\t\t\t//* note: see typecheck/slices.cpp for mutability rules.\n\t\t\tif(bind->restRef)   fake->type = fir::Type::getCharSlice(sst::getMutabilityOfSliceOfType(rhs));\n\t\t\telse                fake->type = fir::Type::getString();\n\n\t\t\tfs->stree->addDefinition(bind->restName, fake);\n\n\t\t\tbind->restDefn = fake;\n\t\t}\n\t}\n\telse\n\t{\n\t\tfor(auto& b : bind->inner)\n\t\t\tcheckAndAddBinding(fs, &b, rhs->getArrayElementType(), immut, true);\n\n\t\tif(!bind->restName.empty())\n\t\t{\n\t\t\tauto fake = util::pool<sst::VarDefn>(bind->loc);\n\n\t\t\tfake->id = Identifier(bind->restName, IdKind::Name);\n\t\t\tfake->immutable = immut;\n\n\t\t\t//* note: see typecheck/slices.cpp for mutability rules.\n\t\t\tif(bind->restRef || rhs->isArraySliceType())\n\t\t\t\tfake->type = fir::ArraySliceType::get(rhs->getArrayElementType(), sst::getMutabilityOfSliceOfType(rhs));\n\n\t\t\telse\n\t\t\t\tfake->type = fir::DynamicArrayType::get(rhs->getArrayElementType());\n\n\t\t\tfs->stree->addDefinition(bind->restName, fake);\n\t\t\tbind->restDefn = fake;\n\t\t}\n\t}\n}\n\n\n\nstatic void checkAndAddBinding(sst::TypecheckState* fs, DecompMapping* bind, fir::Type* rhs, bool immut, bool allowref)\n{\n\tif(!bind->name.empty())\n\t{\n\t\tif(bind->name != \"_\")\n\t\t{\n\t\t\tauto fake = util::pool<sst::VarDefn>(bind->loc);\n\n\t\t\tfake->id = Identifier(bind->name, IdKind::Name);\n\t\t\tfake->immutable = immut;\n\n\t\t\tif(bind->ref && !allowref)\n\t\t\t\terror(bind->loc, \"cannot bind to value of type '%s' by reference\", rhs);\n\n\t\t\telse if(bind->ref)\n\t\t\t\tfake->type = rhs->getPointerTo();\n\n\t\t\telse\n\t\t\t\tfake->type = rhs;\n\n\t\t\tfs->stree->addDefinition(bind->name, fake);\n\t\t\tbind->createdDefn = fake;\n\t\t}\n\t}\n\telse if(bind->array)\n\t{\n\t\tcheckArray(fs, bind, rhs, immut);\n\t}\n\telse\n\t{\n\t\tcheckTuple(fs, bind, rhs, immut);\n\t}\n}\n\n\nDecompMapping sst::TypecheckState::typecheckDecompositions(const DecompMapping& bind, fir::Type* rhs, bool immut, bool allowref)\n{\n\tauto copy = bind;\n\tcheckAndAddBinding(this, &copy, rhs, immut, allowref);\n\n\treturn copy;\n}\n\n\nTCResult ast::DecompVarDefn::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\n\tauto ret = util::pool<sst::DecompDefn>(this->loc);\n\n\tret->immutable = this->immut;\n\tif(auto splat = dcast(ast::SplatOp, this->initialiser))\n\t{\n\t\tif(this->bindings.array)\n\t\t{\n\t\t\tSpanError::make(SimpleError::make(this->loc, \"value splats can only be assigned to tuple decompositions\"))\n\t\t\t\t->add(util::ESpan(this->initialiser->loc, \"\"))\n\t\t\t\t->postAndQuit();\n\t\t}\n\n\t\tbool isnest = false;\n\t\tfor(const auto& b : this->bindings.inner)\n\t\t{\n\t\t\tif(b.name.empty())\n\t\t\t{\n\t\t\t\tisnest = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif(isnest)\n\t\t{\n\t\t\tSpanError::make(SimpleError::make(this->loc, \"cannot assign value splats to nested tuple decomposition\"))\n\t\t\t\t->add(util::ESpan(this->initialiser->loc, \"\"))\n\t\t\t\t->postAndQuit();\n\t\t}\n\n\t\t// ok, at this point we should be fine.\n\t\tthis->initialiser = util::pool<ast::LitTuple>(splat->loc, std::vector<ast::Expr*>(this->bindings.inner.size(), splat->expr));\n\t}\n\n\tret->init = this->initialiser->typecheck(fs).expr();\n\tret->bindings = fs->typecheckDecompositions(this->bindings, ret->init->type, this->immut, false);\n\n\treturn TCResult(ret);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/directives.cpp",
    "content": "// directives.cpp\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"pts.h\"\n#include \"errors.h\"\n#include \"resolver.h\"\n\n#include \"codegen.h\"\n#include \"typecheck.h\"\n\n#include \"ir/type.h\"\n#include \"ir/interp.h\"\n\n#include \"memorypool.h\"\n\n\nTCResult ast::RunDirective::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto rundir = util::pool<sst::RunDirective>(this->loc, nullptr);\n\tif(this->insideExpr)\n\t{\n\t\trundir->insideExpr = this->insideExpr->typecheck(fs, infer).expr();\n\t\trundir->type = rundir->insideExpr->type;\n\t}\n\telse\n\t{\n\t\trundir->block = dcast(sst::Block, this->block->typecheck(fs, infer).stmt());\n\t\ticeAssert(rundir->block);\n\n\t\trundir->type = fir::Type::getVoid();\n\t}\n\n\treturn TCResult(rundir);\n}\n\n\n\n\n// defined in codegen/directives.cpp\nfir::ConstantValue* magicallyRunExpressionAtCompileTime(cgn::CodegenState* cs, sst::Stmt* stmt, fir::Type* infer,\n\tconst fir::Name& fname, fir::interp::InterpState* is = 0);\n\nstatic size_t condCounter = 0;\nTCResult ast::IfDirective::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\t// the entire point of #if is that when the condition is false, we don't typecheck it at all.\n\t// (of course, it must still parse.) in order to achieve this, together with arbitrary code in the\n\t// conditions, we first need to codegen anything that might have been seen -- eg. globals, functions, etc,\n\t// so that we can run the interpreter.\n\n\t// thus, we need to *run codegen* *right now*, to get a module. we don't call cgn::codegen directly, but we setup the\n\t// internals ourselves, since cgn::codegen expects a fully typechecked module/dtree, which we don't have right now\n\tauto mod = new fir::Module(\"\");\n\tauto cs = new cgn::CodegenState(fir::IRBuilder(mod));\n\tcs->typeDefnMap = fs->typeDefnMap;\n\tcs->module = mod;\n\n\t// so we don't crash, give us a starting location.\n\tcs->pushLoc(this->loc);\n\n\tdefer(delete cs);\n\tdefer(delete mod);\n\n\tsst::Block* execBlock = 0;\n\tfor(auto c : this->cases)\n\t{\n\t\tif(!c.inits.empty())\n\t\t\terror(c.inits[0], \"compile-time #if currently does not support initialisers\");\n\n\t\tauto cond = c.cond->typecheck(fs, fir::Type::getBool()).expr();\n\t\tauto value = magicallyRunExpressionAtCompileTime(cs, cond, fir::Type::getBool(),\n\t\t\tfir::Name::obfuscate(\"interp_if_cond\", condCounter++));\n\n\t\tif(!value->getType()->isBoolType())\n\t\t\terror(c.cond, \"expression with non-boolean type '%s' cannot be used as a conditional in an #if\", value->getType());\n\n\t\tauto b = dcast(fir::ConstantBool, value);\n\t\ticeAssert(b);\n\n\t\tif(b->getValue() == true)   // be a bit explicit\n\t\t{\n\t\t\texecBlock = dcast(sst::Block, c.body->typecheck(fs).stmt());\n\t\t\ticeAssert(execBlock);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif(!execBlock && this->elseCase)\n\t{\n\t\texecBlock = dcast(sst::Block, this->elseCase->typecheck(fs).stmt());\n\t\ticeAssert(execBlock);\n\t}\n\n\tif(!execBlock)\n\t{\n\t\treturn TCResult::getDummy();\n\t}\n\telse\n\t{\n\t\treturn TCResult(execBlock);\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/dotop.cpp",
    "content": "// dotop.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"gluecode.h\"\n#include \"resolver.h\"\n#include \"polymorph.h\"\n\n#include \"ir/type.h\"\n\n#include \"memorypool.h\"\n\nnamespace names = strs::names;\n\n\n// make the nice message.\nstatic ErrorMsg* wrongDotOpError(ErrorMsg* e, sst::StructDefn* str, const Location& l, const std::string& name, bool usedStatic)\n{\n\tif(usedStatic)\n\t{\n\t\t// check static ones for a better error message.\n\t\tsst::Defn* found = 0;\n\t\tfor(auto sm : str->methods)\n\t\t\tif(sm->id.name == name) { found = sm; break; }\n\n\t\tif(!found)\n\t\t{\n\t\t\tfor(auto sf : str->fields)\n\t\t\t\tif(sf->id.name == name) { found = sf; break; }\n\t\t}\n\n\t\tif(found) e->append(SimpleError::make(MsgType::Note, found->loc, \"use '.' to refer to the instance member '%s'\", name));\n\n\t\treturn e;\n\t}\n\telse\n\t{\n\t\tif(auto cls = dcast(sst::ClassDefn, str))\n\t\t{\n\t\t\t// check static ones for a better error message.\n\t\t\tsst::Defn* found = 0;\n\t\t\tfor(auto sm : cls->staticMethods)\n\t\t\t\tif(sm->id.name == name) { found = sm; break; }\n\n\t\t\tif(!found)\n\t\t\t{\n\t\t\t\tfor(auto sf : cls->staticFields)\n\t\t\t\t\tif(sf->id.name == name) { found = sf; break; }\n\t\t\t}\n\n\n\t\t\tif(found) e->append(SimpleError::make(MsgType::Note, found->loc, \"use '::' to refer to the static member '%s'\", name));\n\t\t}\n\n\t\treturn e;\n\t}\n};\n\n\n\n\n\n\n\nstruct search_result_t\n{\n\tsearch_result_t() { }\n\tsearch_result_t(fir::Type* t, size_t i, bool tr) : type(t), fieldIdx(i), isTransparent(tr) { }\n\n\tfir::Type* type = 0;\n\tsize_t fieldIdx = 0;\n\tbool isTransparent = false;\n};\n\nstatic std::vector<search_result_t> searchTransparentFields(sst::TypecheckState* fs, std::vector<search_result_t> stack,\n\tconst std::vector<sst::StructFieldDefn*>& fields, const Location& loc, const std::string& name)\n{\n\t// search for them by name first, instead of doing a super-depth-first-search.\n\tfor(auto df : fields)\n\t{\n\t\tif(df->id.name == name)\n\t\t{\n\t\t\tstack.push_back(search_result_t(df->type, 0, false));\n\t\t\treturn stack;\n\t\t}\n\t}\n\n\n\tsize_t idx = 0;\n\tfor(auto df : fields)\n\t{\n\t\tif(df->isTransparentField)\n\t\t{\n\t\t\tauto ty = df->type;\n\t\t\ticeAssert(ty->isRawUnionType() || ty->isStructType());\n\n\t\t\tauto defn = fs->typeDefnMap[ty];\n\t\t\ticeAssert(defn);\n\n\t\t\tstd::vector<sst::StructFieldDefn*> flds;\n\t\t\tif(auto str = dcast(sst::StructDefn, defn); str)\n\t\t\t\tflds = str->fields;\n\n\t\t\telse if(auto unn = dcast(sst::RawUnionDefn, defn); unn)\n\t\t\t\tflds = zfu::map(unn->fields, zfu::pair_second()) + unn->transparentFields;\n\n\t\t\telse\n\t\t\t\terror(loc, \"what kind of type is this? '%s'\", ty);\n\n\t\t\tstack.push_back(search_result_t(ty, idx, true));\n\t\t\tauto ret = searchTransparentFields(fs, stack, flds, loc, name);\n\n\t\t\tif(!ret.empty())    return ret;\n\t\t\telse                stack.pop_back();\n\t\t}\n\n\t\tidx += 1;\n\t}\n\n\t// if we've reached the end of the line, return nothing.\n\treturn { };\n}\n\n\nstatic sst::FieldDotOp* resolveFieldNameDotOp(sst::TypecheckState* fs, sst::Expr* lhs, const std::vector<sst::StructFieldDefn*>& fields,\n\tconst Location& loc, const std::string& name)\n{\n\tfor(auto df : fields)\n\t{\n\t\tif(df->id.name == name)\n\t\t{\n\t\t\tauto ret = util::pool<sst::FieldDotOp>(loc, df->type);\n\t\t\tret->lhs = lhs;\n\t\t\tret->rhsIdent = name;\n\n\t\t\treturn ret;\n\t\t}\n\t}\n\n\t// sad. search for the field, recursively, in transparent members.\n\tauto ops = searchTransparentFields(fs, { }, fields, loc, name);\n\tif(ops.empty())\n\t\treturn nullptr;\n\n\t// ok, now we just need to make a link of fielddotops...\n\tsst::Expr* cur = lhs;\n\tfor(const auto& x : ops)\n\t{\n\t\tauto op = util::pool<sst::FieldDotOp>(loc, x.type);\n\n\t\top->lhs = cur;\n\t\top->isTransparentField = x.isTransparent;\n\t\top->indexOfTransparentField = x.fieldIdx;\n\n\t\t// don't set a name if we're transparent.\n\t\top->rhsIdent = (x.isTransparent ? \"\" : name);\n\n\t\tcur = op;\n\t}\n\n\tauto ret = dcast(sst::FieldDotOp, cur);\n\ticeAssert(ret);\n\n\treturn ret;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nstatic sst::Expr* doExpressionDotOp(sst::TypecheckState* fs, ast::DotOperator* dotop, fir::Type* infer)\n{\n\tauto lhs = dotop->left->typecheck(fs).expr();\n\n\t// first we got to find the struct defn based on the type\n\tauto type = lhs->type;\n\tif(!type)\n\t{\n\t\tif(dcast(sst::ScopeExpr, lhs))\n\t\t{\n\t\t\terror(dotop, \"invalid use of '.' for static scope access; use '::' instead\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(lhs, \"failed to resolve type of lhs in expression dot-op!\");\n\t\t}\n\t}\n\telse if(auto vr = dcast(sst::VarRef, lhs); vr && (dcast(sst::UnionDefn, vr->def) || dcast(sst::EnumDefn, vr->def)))\n\t{\n\t\terror(dotop, \"use '::' to access enumeration cases and union variants\");\n\t}\n\n\tif(type->isTupleType())\n\t{\n\t\tast::LitNumber* ln = dcast(ast::LitNumber, dotop->right);\n\t\tif(!ln)\n\t\t\terror(dotop->right, \"right-hand side of dot-operator on tuple type ('%s') must be a number literal\", type);\n\n\t\tif(ln->num.find(\".\") != std::string::npos || ln->num.find(\"-\") != std::string::npos)\n\t\t\terror(dotop->right, \"tuple indices must be non-negative integer numerical literals\");\n\n\t\tsize_t n = std::stoul(ln->num);\n\t\tauto tup = type->toTupleType();\n\n\t\tif(n >= tup->getElementCount())\n\t\t\terror(dotop->right, \"tuple only has %d elements, cannot access element %d\", tup->getElementCount(), n);\n\n\t\tauto ret = util::pool<sst::TupleDotOp>(dotop->loc, tup->getElementN(n));\n\t\tret->lhs = lhs;\n\t\tret->index = n;\n\n\t\treturn ret;\n\t}\n\telse if(type->isPointerType() && (type->getPointerElementType()->isStructType() || type->getPointerElementType()->isClassType()))\n\t{\n\t\ttype = type->getPointerElementType();\n\n\t\t//* note: it's in the else-if here because we currently don't support auto deref-ing (ie. use '.' on pointers)\n\t\t//*       for builtin types, only for classes and structs.\n\n\t\t// TODO: reevaluate this decision?\n\t}\n\telse if(type->isStringType())\n\t{\n\t\tauto rhs = dotop->right;\n\t\tif(auto vr = dcast(ast::Ident, rhs))\n\t\t{\n\t\t\t// TODO: Extension support here\n\t\t\tfir::Type* res = 0;\n\t\t\tif(zfu::match(vr->name, names::saa::FIELD_LENGTH, names::saa::FIELD_CAPACITY,\n\t\t\t\tnames::saa::FIELD_REFCOUNT, names::string::FIELD_COUNT))\n\t\t\t{\n\t\t\t\tres = fir::Type::getNativeWord();\n\t\t\t}\n\t\t\telse if(vr->name == names::saa::FIELD_POINTER)\n\t\t\t{\n\t\t\t\tres = fir::Type::getInt8Ptr();\n\t\t\t}\n\n\n\t\t\tif(res)\n\t\t\t{\n\t\t\t\tauto tmp = util::pool<sst::BuiltinDotOp>(dotop->right->loc, res);\n\t\t\t\ttmp->lhs = lhs;\n\t\t\t\ttmp->name = vr->name;\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\t// else: break out below, for extensions\n\t\t}\n\t\telse if(auto fc = dcast(ast::FunctionCall, rhs))\n\t\t{\n\t\t\tfir::Type* res = 0;\n\t\t\tstd::vector<sst::Expr*> args;\n\t\t\tif(fc->name == names::saa::FN_CLONE)\n\t\t\t{\n\t\t\t\tres = type;\n\t\t\t\tif(fc->args.size() != 0)\n\t\t\t\t\terror(fc, \"builtin string method 'clone' expects exactly 0 arguments, found %d instead\", fc->args.size());\n\t\t\t}\n\t\t\telse if(fc->name == names::saa::FN_APPEND)\n\t\t\t{\n\t\t\t\tres = fir::Type::getVoid();\n\t\t\t\tif(fc->args.size() != 1)\n\t\t\t\t\terror(fc, \"builtin string method 'append' expects exactly 1 argument, found %d instead\", fc->args.size());\n\n\t\t\t\telse if(!fc->args[0].first.empty())\n\t\t\t\t\terror(fc, \"argument to builtin method 'append' cannot be named\");\n\n\t\t\t\targs.push_back(fc->args[0].second->typecheck(fs).expr());\n\t\t\t\tif(!args[0]->type->isCharType() && !args[0]->type->isStringType() && !args[0]->type->isCharSliceType())\n\t\t\t\t{\n\t\t\t\t\terror(fc, \"invalid argument type '%s' to builtin string method 'append'; expected one of '%s', '%s', or '%s'\",\n\t\t\t\t\t\targs[0]->type, fir::Type::getInt8(), fir::Type::getCharSlice(false), fir::Type::getString());\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\tif(res)\n\t\t\t{\n\t\t\t\tauto tmp = util::pool<sst::BuiltinDotOp>(dotop->right->loc, res);\n\t\t\t\ttmp->lhs = lhs;\n\t\t\t\ttmp->args = args;\n\t\t\t\ttmp->name = fc->name;\n\t\t\t\ttmp->isFunctionCall = true;\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t}\n\t}\n\telse if(type->isDynamicArrayType() || type->isArraySliceType() || type->isArrayType())\n\t{\n\t\tauto rhs = dotop->right;\n\t\tif(auto vr = dcast(ast::Ident, rhs))\n\t\t{\n\t\t\tfir::Type* res = 0;\n\t\t\tif(vr->name == names::saa::FIELD_LENGTH || (type->isDynamicArrayType()\n\t\t\t\t&& zfu::match(vr->name, names::saa::FIELD_CAPACITY, names::saa::FIELD_REFCOUNT)))\n\t\t\t{\n\t\t\t\tres = fir::Type::getNativeWord();\n\t\t\t}\n\t\t\telse if(vr->name == names::saa::FIELD_POINTER)\n\t\t\t{\n\t\t\t\tres = type->getArrayElementType()->getPointerTo();\n\t\t\t\tif(type->isDynamicArrayType())\n\t\t\t\t\tres = res->getMutablePointerVersion();\n\n\t\t\t\telse if(type->isArraySliceType() && type->toArraySliceType()->isMutable())\n\t\t\t\t\tres = res->getMutablePointerVersion();\n\t\t\t}\n\n\n\n\t\t\tif(res)\n\t\t\t{\n\t\t\t\tauto tmp = util::pool<sst::BuiltinDotOp>(dotop->right->loc, res);\n\t\t\t\ttmp->lhs = lhs;\n\t\t\t\ttmp->name = vr->name;\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\t// else: break out below, for extensions\n\t\t}\n\t\telse if(auto fc = dcast(ast::FunctionCall, rhs))\n\t\t{\n\t\t\tfir::Type* res = 0;\n\t\t\tstd::vector<sst::Expr*> args;\n\n\t\t\tif(fc->name == names::saa::FN_CLONE)\n\t\t\t{\n\t\t\t\tres = type;\n\t\t\t\tif(fc->args.size() != 0)\n\t\t\t\t\terror(fc, \"builtin array method 'clone' expects exactly 0 arguments, found %d instead\", fc->args.size());\n\t\t\t}\n\t\t\telse if(fc->name == names::saa::FN_APPEND)\n\t\t\t{\n\t\t\t\tif(type->isArrayType())\n\t\t\t\t\terror(fc, \"'append' method cannot be called on arrays\");\n\n\t\t\t\tres = fir::DynamicArrayType::get(type->getArrayElementType());\n\n\t\t\t\tif(fc->args.size() != 1)\n\t\t\t\t\terror(fc, \"builtin array method 'append' expects exactly 1 argument, found %d instead\", fc->args.size());\n\n\t\t\t\telse if(!fc->args[0].first.empty())\n\t\t\t\t\terror(fc, \"argument to builtin method 'append' cannot be named\");\n\n\t\t\t\targs.push_back(fc->args[0].second->typecheck(fs).expr());\n\t\t\t\tif(args[0]->type != type->getArrayElementType()     //? vv logic below looks a little sketch.\n\t\t\t\t\t&& ((args[0]->type->isArraySliceType() && args[0]->type->getArrayElementType() != type->getArrayElementType()))\n\t\t\t\t\t&& args[0]->type != type)\n\t\t\t\t{\n\t\t\t\t\terror(fc, \"invalid argument type '%s' to builtin array method 'append'; expected one of '%s', '%s', or '%s'\",\n\t\t\t\t\t\targs[0]->type, type, type->getArrayElementType(),\n\t\t\t\t\t\tfir::ArraySliceType::get(type->getArrayElementType(), false));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(fc->name == names::array::FN_POP)\n\t\t\t{\n\t\t\t\tif(!type->isDynamicArrayType())\n\t\t\t\t\terror(fc, \"'pop' method can only be called on dynamic arrays\");\n\n\t\t\t\tres = type->getArrayElementType();\n\n\t\t\t\tif(fc->args.size() != 0)\n\t\t\t\t\terror(fc, \"builtin array method 'pop' expects no arguments, found %d instead\", fc->args.size());\n\t\t\t}\n\n\t\t\t// fallthrough\n\n\t\t\tif(res)\n\t\t\t{\n\t\t\t\tauto tmp = util::pool<sst::BuiltinDotOp>(dotop->right->loc, res);\n\t\t\t\ttmp->lhs = lhs;\n\t\t\t\ttmp->args = args;\n\t\t\t\ttmp->name = fc->name;\n\t\t\t\ttmp->isFunctionCall = true;\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t}\n\t}\n\telse if(type->isEnumType())\n\t{\n\t\t// allow getting name, raw and value\n\t\tauto rhs = dotop->right;\n\t\tif(auto vr = dcast(ast::Ident, rhs))\n\t\t{\n\t\t\t// TODO: Extension support here\n\t\t\tfir::Type* res = 0;\n\t\t\tif(vr->name == names::enumeration::FIELD_NAME)\n\t\t\t\tres = fir::Type::getCharSlice(false);\n\n\t\t\telse if(vr->name == names::enumeration::FIELD_INDEX)\n\t\t\t\tres = fir::Type::getNativeWord();\n\n\t\t\telse if(vr->name == names::enumeration::FIELD_VALUE)\n\t\t\t\tres = type->toEnumType()->getCaseType();\n\n\n\t\t\tif(res)\n\t\t\t{\n\t\t\t\tauto tmp = util::pool<sst::BuiltinDotOp>(dotop->right->loc, res);\n\t\t\t\ttmp->lhs = lhs;\n\t\t\t\ttmp->name = vr->name;\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\t// else: break out below, for extensions\n\t\t}\n\t}\n\telse if(type->isRangeType())\n\t{\n\t\tauto rhs = dotop->right;\n\t\tif(auto vr = dcast(ast::Ident, rhs))\n\t\t{\n\t\t\t// TODO: extension support here\n\t\t\tfir::Type* res = 0;\n\t\t\tif(vr->name == names::range::FIELD_BEGIN || vr->name == names::range::FIELD_END || vr->name == names::range::FIELD_STEP)\n\t\t\t\tres = fir::Type::getNativeWord();\n\n\t\t\tif(res)\n\t\t\t{\n\t\t\t\tauto tmp = util::pool<sst::BuiltinDotOp>(dotop->right->loc, res);\n\t\t\t\ttmp->lhs = lhs;\n\t\t\t\ttmp->name = vr->name;\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t}\n\n\t\t// else: fallthrough;\n\t}\n\telse if(type->isAnyType())\n\t{\n\t\tauto rhs = dotop->right;\n\t\tif(auto vr = dcast(ast::Ident, rhs))\n\t\t{\n\t\t\t// TODO: extension support here\n\t\t\tfir::Type* res = 0;\n\t\t\tif(vr->name == names::any::FIELD_TYPEID)\n\t\t\t\tres = fir::Type::getNativeUWord();\n\n\t\t\telse if(vr->name == names::any::FIELD_REFCOUNT)\n\t\t\t\tres = fir::Type::getNativeWord();\n\n\t\t\tif(res)\n\t\t\t{\n\t\t\t\tauto tmp = util::pool<sst::BuiltinDotOp>(dotop->right->loc, res);\n\t\t\t\ttmp->lhs = lhs;\n\t\t\t\ttmp->name = vr->name;\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t}\n\n\t\t// else: fallthrough\n\t}\n\n\n\n\t// ok.\n\tauto defn = fs->typeDefnMap[type];\n\n\t// note: if `defn` is null, then all the dcasts will fail and we'll\n\t// fallthrough to the bottom.\n\tif(auto str = dcast(sst::StructDefn, defn))\n\t{\n\t\t// right.\n\t\tif(auto fc = dcast(ast::FunctionCall, dotop->right))\n\t\t{\n\t\t\tfs->pushSelfContext(str->type);\n\t\t\tdefer(fs->popSelfContext());\n\n\n\t\t\t// check methods first\n\t\t\tstd::vector<FnCallArgument> arguments = zfu::map(fc->args, [fs](auto arg) -> FnCallArgument {\n\t\t\t\treturn FnCallArgument(arg.second->loc, arg.first, arg.second->typecheck(fs).expr(), arg.second);\n\t\t\t});\n\n\t\t\t//! SELF HANDLING (INSERTION) (DOT-METHOD-CALL)\n\t\t\t//* note: how we handle this is that we insert the self argument to interface with our resolver,\n\t\t\t//* then remove it below since our codegen will handle the actual insertion.\n\t\t\targuments.insert(arguments.begin(), FnCallArgument::make(fc->loc, \"this\", str->type->getMutablePointerTo(),\n\t\t\t\t/* ignoreName: */ true));\n\n\t\t\tfs->teleportInto(str->innerScope);\n\n\t\t\tErrorMsg* err = 0;\n\t\t\tsst::Defn* resolved = 0;\n\n\t\t\tauto curstr = str;\n\t\t\twhile(!resolved)\n\t\t\t{\n\t\t\t\tauto arg_copy = arguments;\n\t\t\t\tauto res = sst::resolver::resolveFunctionCall(fs, fc->loc, fc->name, &arg_copy, fc->mappings,\n\t\t\t\t\t/* traverseUp: */ false, infer);\n\n\t\t\t\tif(res.isDefn())\n\t\t\t\t{\n\t\t\t\t\tresolved = res.defn();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif(auto cls = dcast(sst::ClassDefn, curstr); cls && cls->baseClass)\n\t\t\t\t{\n\t\t\t\t\t// teleport out, then back in.\n\t\t\t\t\tfs->teleportOut();\n\t\t\t\t\tfs->teleportInto(cls->baseClass->innerScope);\n\n\t\t\t\t\tcurstr = cls->baseClass;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// sighs\n\t\t\t\terr = res.error();\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\t\tif(!resolved)\n\t\t\t{\n\t\t\t\ticeAssert(err);\n\t\t\t\twrongDotOpError(SimpleError::make(fc->loc, \"no valid call to method named '%s' in type '%s'%s\", fc->name, str->id.name,\n\t\t\t\t\tcurstr != str ? \" (or any of its parent types)\" : \"\"),\n\t\t\t\t\tstr, fc->loc, fc->name, false)->append(err)->postAndQuit();\n\t\t\t}\n\n\n\t\t\tsst::Expr* finalCall = 0;\n\t\t\tif(auto fndef = dcast(sst::FunctionDefn, resolved); fndef)\n\t\t\t{\n\t\t\t\tauto c = util::pool<sst::FunctionCall>(fc->loc, resolved->type->toFunctionType()->getReturnType());\n\t\t\t\tc->arguments = arguments;\n\t\t\t\tc->name = fc->name;\n\t\t\t\tc->target = resolved;\n\t\t\t\tc->isImplicitMethodCall = false;\n\n\t\t\t\t//! SELF HANDLING (REMOVAL) (DOT-METHOD-CALL)\n\t\t\t\tc->arguments.erase(c->arguments.begin(), c->arguments.begin() + 1);\n\t\t\t\tfinalCall = c;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto c = util::pool<sst::ExprCall>(fc->loc, resolved->type->toFunctionType()->getReturnType());\n\t\t\t\tc->arguments = zfu::map(arguments, [](const FnCallArgument& e) -> sst::Expr* { return e.value; });\n\n\t\t\t\tauto tmp = util::pool<sst::FieldDotOp>(fc->loc, resolved->type);\n\t\t\t\ttmp->lhs = lhs;\n\t\t\t\ttmp->rhsIdent = fc->name;\n\n\t\t\t\tc->callee = tmp;\n\n\t\t\t\t//! SELF HANDLING (REMOVAL) (DOT-METHOD-CALL)\n\t\t\t\tc->arguments.erase(c->arguments.begin(), c->arguments.begin() + 1);\n\t\t\t\tfinalCall = c;\n\t\t\t}\n\n\n\t\t\tauto ret = util::pool<sst::MethodDotOp>(fc->loc, resolved->type->toFunctionType()->getReturnType());\n\t\t\tret->lhs = lhs;\n\t\t\tret->call = finalCall;\n\n\t\t\tfs->teleportOut();\n\t\t\treturn ret;\n\t\t}\n\t\telse if(auto fld = dcast(ast::Ident, dotop->right))\n\t\t{\n\t\t\tauto name = fld->name;\n\t\t\t{\n\t\t\t\tauto copy = str;\n\n\t\t\t\twhile(copy)\n\t\t\t\t{\n\t\t\t\t\tauto hmm = resolveFieldNameDotOp(fs, lhs, copy->fields, dotop->loc, name);\n\t\t\t\t\tif(hmm) return hmm;\n\n\t\t\t\t\t// ok, we didn't find it.\n\t\t\t\t\tif(auto cls = dcast(sst::ClassDefn, copy); cls)\n\t\t\t\t\t\tcopy = cls->baseClass;\n\n\t\t\t\t\telse\n\t\t\t\t\t\tcopy = nullptr;\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\t// check for method references\n\t\t\tstd::vector<sst::FunctionDefn*> meths;\n\t\t\tfor(auto m : str->methods)\n\t\t\t{\n\t\t\t\tif(m->id.name == name)\n\t\t\t\t\tmeths.push_back(m);\n\t\t\t}\n\n\t\t\tif(meths.empty())\n\t\t\t{\n\t\t\t\twrongDotOpError(SimpleError::make(fld->loc, \"no field named '%s' in type '%s'\", fld->name, str->id.name),\n\t\t\t\t\tstr, fld->loc, fld->name, false)->postAndQuit();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// ok, we potentially have a method -- if we used '.', error out.\n\t\t\t\tif(!dotop->isStatic)\n\t\t\t\t\terror(dotop, \"use '::' to refer to a method of a type\");\n\n\t\t\t\tfir::Type* retty = 0;\n\n\t\t\t\t// ok, disambiguate if we need to\n\t\t\t\tif(meths.size() == 1)\n\t\t\t\t{\n\t\t\t\t\tretty = meths[0]->type;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// ok, we need to.\n\t\t\t\t\tif(infer == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tauto err = SimpleError::make(dotop->right->loc, \"ambiguous reference to method '%s' in struct '%s'\", name, str->id.name);\n\t\t\t\t\t\tfor(auto m : meths)\n\t\t\t\t\t\t\terr->append(SimpleError::make(MsgType::Note, m->loc, \"potential target here:\"));\n\n\t\t\t\t\t\terr->postAndQuit();\n\t\t\t\t\t}\n\n\t\t\t\t\t// else...\n\t\t\t\t\tif(!infer->isFunctionType())\n\t\t\t\t\t{\n\t\t\t\t\t\terror(dotop->right, \"non-function type '%s' inferred for reference to method '%s' of struct '%s'\",\n\t\t\t\t\t\t\tinfer, name, str->id.name);\n\t\t\t\t\t}\n\n\t\t\t\t\t// ok.\n\t\t\t\t\tfor(auto m : meths)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(m->type == infer)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tretty = m->type;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// hm, okay\n\t\t\t\t\terror(dotop->right, \"no matching method named '%s' with signature '%s' to match inferred type\",\n\t\t\t\t\t\tname, infer);\n\t\t\t\t}\n\n\t\t\t\tauto ret = util::pool<sst::FieldDotOp>(dotop->loc, retty);\n\t\t\t\tret->lhs = lhs;\n\t\t\t\tret->rhsIdent = name;\n\t\t\t\tret->isMethodRef = true;\n\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(dotop->right, \"unsupported right-side expression for dot-operator on type '%s'\", str->id.name);\n\t\t}\n\t}\n\telse if(auto rnn = dcast(sst::RawUnionDefn, defn))\n\t{\n\t\tif(auto fld = dcast(ast::Ident, dotop->right))\n\t\t{\n\t\t\tauto flds = zfu::map(rnn->fields, zfu::pair_second()) + rnn->transparentFields;\n\t\t\tauto hmm = resolveFieldNameDotOp(fs, lhs, flds, dotop->loc, fld->name);\n\t\t\tif(hmm)\n\t\t\t{\n\t\t\t\treturn hmm;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// ok we didn't return. this is a raw union so extensions R NOT ALLOWED!! (except methods maybe)\n\t\t\t\terror(fld, \"union '%s' has no member named '%s'\", rnn->id.name, fld->name);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(dotop->right, \"unsupported right-side expression for dot-operator on type '%s'\", defn->id.name);\n\t\t}\n\t}\n\telse\n\t{\n\t\t// TODO: this error message could be better!!!\n\t\t//* it's because we are pending extension support!\n\t\terror(lhs, \"unsupported left-side expression (with type '%s') for dot-operator\", lhs->type);\n\t}\n\n\t// TODO: plug in extensions here!!\n}\n\n\n\nstatic sst::Expr* checkRhs2(sst::TypecheckState* fs, ast::DotOperator* dot, const sst::Scope& olds, const sst::Scope& news,\n\tfir::Type* rhs_infer, sst::StructDefn* possibleStructDefn = 0)\n{\n\tif(auto id = dcast(ast::Ident, dot->right))\n\t\tid->traverseUpwards = false;\n\n\telse if(auto fc = dcast(ast::FunctionCall, dot->right))\n\t\tfc->traverseUpwards = false;\n\n\t// note: for function/expr calls, we typecheck the arguments *before* we teleport to the scope, so that we don't conflate\n\t// the scope of the argument (which is the current scope) with the scope of the call target (which is in whatever namespace)\n\n\tsst::Expr* ret = 0;\n\tif(auto fc = dcast(ast::FunctionCall, dot->right))\n\t{\n\t\tauto args = zfu::map(fc->args, [fs](auto e) -> FnCallArgument { return FnCallArgument(e.second->loc, e.first,\n\t\t\te.second->typecheck(fs).expr(), e.second);\n\t\t});\n\n\t\tfs->teleportInto(news);\n\t\tret = fc->typecheckWithArguments(fs, args, rhs_infer);\n\t}\n\telse if(auto ec = dcast(ast::ExprCall, dot->right))\n\t{\n\t\tauto args = zfu::map(fc->args, [fs](auto e) -> FnCallArgument { return FnCallArgument(e.second->loc, e.first,\n\t\t\te.second->typecheck(fs).expr(), e.second);\n\t\t});\n\n\t\tfs->teleportInto(news);\n\t\tret = ec->typecheckWithArguments(fs, args, rhs_infer);\n\t}\n\telse if(dcast(ast::Ident, dot->right) || dcast(ast::DotOperator, dot->right))\n\t{\n\t\tfs->teleportInto(news);\n\t\tauto res = dot->right->typecheck(fs, rhs_infer);\n\t\tif(res.isError() && possibleStructDefn && dcast(ast::Ident, dot->right))\n\t\t{\n\t\t\twrongDotOpError(res.error(), possibleStructDefn, dot->right->loc, dcast(ast::Ident, dot->right)->name, true)->postAndQuit();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// will post if res is an error, even if we didn't give the fancy error.\n\t\t\tret = res.expr();\n\t\t}\n\t}\n\telse\n\t{\n\t\terror(dot->right, \"unexpected %s on right-side of dot-operator following static scope '%s' on the left\", dot->right->readableName,\n\t\t\tnews.string());\n\t}\n\n\ticeAssert(ret);\n\n\tfs->teleportOut();\n\treturn ret;\n}\n\n\n\n\nstatic sst::Expr* doStaticDotOp(sst::TypecheckState* fs, ast::DotOperator* dot, sst::Expr* left, fir::Type* infer)\n{\n\t// if we get a type expression, then we want to dig up the definition from the type.\n\tif(auto ident = dcast(sst::VarRef, left); ident || dcast(sst::TypeExpr, left))\n\t{\n\t\tsst::Defn* def = 0;\n\t\tif(ident)\n\t\t{\n\t\t\tdef = ident->def;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto te = dcast(sst::TypeExpr, left);\n\t\t\ticeAssert(te);\n\n\t\t\tdef = fs->typeDefnMap[te->type];\n\t\t}\n\n\t\tif(!def)\n\t\t{\n\t\t\terror(left->loc, \"could not resolve definition\");\n\t\t}\n\n\t\tif(auto typdef = dcast(sst::TypeDefn, def))\n\t\t{\n\t\t\tif(dcast(sst::ClassDefn, def) || dcast(sst::StructDefn, def))\n\t\t\t{\n\t\t\t\tfs->pushSelfContext(def->type);\n\n\t\t\t\tauto oldscope = fs->scope();\n\t\t\t\tauto newscope = typdef->innerScope;\n\n\t\t\t\tfs->pushGenericContext();\n\t\t\t\tdefer(fs->popGenericContext());\n\t\t\t\t{\n\t\t\t\t\tint pses = sst::poly::internal::getNextSessionId();\n\n\t\t\t\t\ticeAssert(typdef->original);\n\t\t\t\t\tfor(auto g : typdef->original->generics)\n\t\t\t\t\t\tfs->addGenericMapping(g.first, fir::PolyPlaceholderType::get(g.first, pses));\n\t\t\t\t}\n\n\t\t\t\tauto ret = checkRhs2(fs, dot, oldscope, newscope, infer);\n\t\t\t\tfs->popSelfContext();\n\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t\telse if(auto unn = dcast(sst::UnionDefn, def))\n\t\t\t{\n\t\t\t\tbool wasfncall = false;\n\t\t\t\tstd::string name;\n\t\t\t\tif(auto fc = dcast(ast::FunctionCall, dot->right))\n\t\t\t\t{\n\t\t\t\t\twasfncall = true;\n\t\t\t\t\tname = fc->name;\n\t\t\t\t}\n\t\t\t\telse if(auto id = dcast(ast::Ident, dot->right))\n\t\t\t\t{\n\t\t\t\t\tname = id->name;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\terror(dot->right, \"unexpected right-hand expression on dot-operator on union '%s'\",\n\t\t\t\t\t\tunn->id.name);\n\t\t\t\t}\n\n\n\t\t\t\tif(!unn->type->toUnionType()->hasVariant(name))\n\t\t\t\t{\n\t\t\t\t\tSimpleError::make(dot->right->loc, \"union '%s' has no variant '%s'\", unn->id.name, name)\n\t\t\t\t\t\t->append(SimpleError::make(MsgType::Note, unn->loc, \"union was defined here:\"))\n\t\t\t\t\t\t->postAndQuit();\n\t\t\t\t}\n\t\t\t\telse if(!wasfncall && unn->type->containsPlaceholders() && infer == nullptr)\n\t\t\t\t{\n\t\t\t\t\t// note that we check infer == 0 before giving this error.\n\t\t\t\t\t// we should be able to pass in the infer value such that it works properly\n\t\t\t\t\t// eg. let x: Foo<int> = Foo.none\n\t\t\t\t\tSimpleError::make(dot->right->loc,\n\t\t\t\t\t\t\"could not infer type parameters for polymorphic union '%s' using variant '%s' \",\n\t\t\t\t\t\tunn->id.name, name)->append(SimpleError::make(MsgType::Note, unn->variants[name]->loc, \"variant was defined here:\"))->postAndQuit();\n\t\t\t\t}\n\t\t\t\telse if(wasfncall && unn->type->toUnionType()->getVariants().at(name)->getInteriorType()->isVoidType())\n\t\t\t\t{\n\t\t\t\t\tSimpleError::make(dot->right->loc,\n\t\t\t\t\t\t\"variant '%s' of union does not have values, and cannot be constructed via function-call\",\n\t\t\t\t\t\tname, unn->id.name)->append(SimpleError::make(MsgType::Note, unn->variants[name]->loc, \"variant was defined here:\"))->postAndQuit();\n\t\t\t\t}\n\n\t\t\t\t// dot-op on the union to access its variants; we need constructor stuff for it.\n\t\t\t\tauto oldscope = fs->scope();\n\t\t\t\tauto newscope = unn->innerScope;\n\n\t\t\t\treturn checkRhs2(fs, dot, oldscope, newscope, infer);\n\t\t\t}\n\t\t\telse if(auto enm = dcast(sst::EnumDefn, def))\n\t\t\t{\n\t\t\t\tauto oldscope = fs->scope();\n\t\t\t\tauto newscope = enm->innerScope;\n\n\t\t\t\tauto rhs = checkRhs2(fs, dot, oldscope, newscope, infer);\n\n\t\t\t\tif(auto vr = dcast(sst::VarRef, rhs))\n\t\t\t\t{\n\t\t\t\t\ticeAssert(vr->def && enm->cases[vr->name] == vr->def);\n\t\t\t\t\treturn vr;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\terror(rhs, \"unsupported right-hand expression on enum '%s'\", enm->id.name);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\terror(dot, \"static access is not supported on type '%s'\", def->type);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(dot, \"invalid static access on variable (of type '%s'); use '.' to refer to instance members\", def->type);\n\t\t}\n\t}\n\telse if(auto scp = dcast(sst::ScopeExpr, left))\n\t{\n\t\tauto oldscope = fs->scope();\n\t\tauto newscope = scp->scope;\n\n\t\treturn checkRhs2(fs, dot, oldscope, newscope, infer);\n\t}\n\n\terror(\"????!!!!\");\n}\n\n\n\nTCResult ast::DotOperator::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tthis->left->checkAsType = this->checkAsType;\n\tthis->right->checkAsType = this->checkAsType;\n\n\tif(this->isStatic)  return TCResult(doStaticDotOp(fs, this, this->left->typecheck(fs).expr(), infer));\n\telse                return TCResult(doExpressionDotOp(fs, this, infer));\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/enums.cpp",
    "content": "// enums.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"ir/type.h\"\n\n#include \"memorypool.h\"\n\n/*\n\tok, here's some documentation of how enumerations work\n\tthey're basically strong enums, unlike C enums.\n\tyou can cast them to ints, and they'll be numbered appropriately starting at 0.\n\n\teach enumeration value is a struct: { index: i64, value: $T }\n\tthe index is the index of the thing, and allows some runtime things on the enum;\n\n\tfor example, a value of type enumeration can have a .name, and in the future can simplify\n\truntime type information getting by having a simpler array-index mechanism.\n\n\tso, a fir::EnumType will now be like a StringType, opaque-ish thing. we'll have IRB things in a similar\n\tfashion (it'll be a value type), and that's about it.\n*/\n\n\nTCResult ast::EnumDefn::generateDeclaration(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto [ success, ret ] = this->checkForExistingDeclaration(fs, gmaps);\n\tif(!success)    return TCResult::getParametric();\n\telse if(ret)    return TCResult(ret);\n\n\tauto defnname = util::typeParamMapToString(this->name, gmaps);\n\tauto defn = util::pool<sst::EnumDefn>(this->loc);\n\tdefn->bareName = this->name;\n\n\tdefn->id = Identifier(defnname, IdKind::Type);\n\tdefn->id.scope = this->enclosingScope;\n\tdefn->visibility = this->visibility;\n\tdefn->original = this;\n\tdefn->enclosingScope = this->enclosingScope;\n\tdefn->innerScope = this->enclosingScope.appending(defnname);\n\n\t// set it to void first, because we want to defer typechecking the member type.\n\tdefn->type = fir::EnumType::get(defn->id.convertToName(), fir::Type::getVoid());\n\n\tif(auto err = fs->checkForShadowingOrConflictingDefinition(defn, [](auto, auto) -> bool { return true; }))\n\t\treturn TCResult(err);\n\n\tdefn->enclosingScope.stree->addDefinition(defnname, defn, gmaps);\n\n\tthis->genericVersions.push_back({ defn, fs->getGenericContextStack() });\n\treturn TCResult(defn);\n}\n\n\nTCResult ast::EnumDefn::typecheck(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto tcr = this->generateDeclaration(fs, infer, gmaps);\n\tif(tcr.isParametric())  return tcr;\n\telse if(tcr.isError())  error(this, \"failed to generate declaration for enum '%s'\", this->name);\n\n\tauto defn = dcast(sst::EnumDefn, tcr.defn());\n\ticeAssert(defn);\n\n\tfs->teleportInto(defn->innerScope);\n\n\tif(this->memberType)\tdefn->memberType = fs->convertParserTypeToFIR(this->memberType);\n\telse\t\t\t\t\tdefn->memberType = fir::Type::getNativeWord();\n\n\tauto ety = defn->type->toEnumType();\n\ticeAssert(ety);\n\tety->setCaseType(defn->memberType);\n\n\tsize_t index = 0;\n\tfor(auto cs : this->cases)\n\t{\n\t\tsst::Expr* val = 0;\n\t\tif(cs.value)\n\t\t{\n\t\t\ticeAssert(defn->memberType);\n\t\t\tval = cs.value->typecheck(fs, defn->memberType).expr();\n\n\t\t\tif(val->type != defn->memberType)\n\t\t\t\terror(cs.value, \"mismatched type in enum case value; expected type '%s', but found type '%s'\", defn->memberType, val->type);\n\t\t}\n\n\t\tauto ecd = util::pool<sst::EnumCaseDefn>(cs.loc);\n\t\tecd->id = Identifier(cs.name, IdKind::Name);\n\t\tecd->id.scope = fs->scope();\n\t\tecd->type = ety;\n\t\tecd->parentEnum = defn;\n\t\tecd->val = val;\n\t\tecd->index = index++;\n\n\t\tdefn->cases[cs.name] = ecd;\n\t\tfs->stree->addDefinition(cs.name, ecd);\n\t}\n\n\tdefn->type = ety;\n\n\tfs->teleportOut();\n\treturn TCResult(defn);\n}\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/function.cpp",
    "content": "// function.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"polymorph.h\"\n\n#include \"ir/type.h\"\n#include \"memorypool.h\"\n\n\nTCResult ast::FuncDefn::generateDeclaration(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto [ success, ret ] = this->checkForExistingDeclaration(fs, gmaps);\n\tif(!success)    return TCResult::getParametric();\n\telse if(ret)    return TCResult(ret);\n\n\tstd::vector<FnParam> ps;\n\tstd::vector<fir::Type*> ptys;\n\n\tint polyses = sst::poly::internal::getNextSessionId();\n\tfor(auto t : this->params)\n\t{\n\t\tauto p = FnParam(t.loc, t.name, sst::poly::internal::convertPtsType(fs, this->generics, t.type, polyses));\n\t\tif(auto dv = t.defaultValue; dv)\n\t\t{\n\t\t\tp.defaultVal = dv->typecheck(fs, p.type).expr();\n\t\t\tif(p.defaultVal->type != p.type)\n\t\t\t{\n\t\t\t\terror(p.defaultVal, \"type mismatch for default value of argument '%s': expected '%s', received '%s' intead\",\n\t\t\t\t\tp.name, p.type, p.defaultVal->type);\n\t\t\t}\n\t\t}\n\n\t\tps.push_back(p);\n\t\tptys.push_back(p.type);\n\t}\n\n\tfir::Type* retty = sst::poly::internal::convertPtsType(fs, this->generics, this->returnType, polyses);\n\tfir::Type* fnType = fir::FunctionType::get(ptys, retty);\n\n\tauto defn = (infer && infer->isClassType() && this->name == \"init\" ? util::pool<sst::ClassInitialiserDefn>(this->loc)\n\t\t: util::pool<sst::FunctionDefn>(this->loc));\n\n\tdefn->type = fnType;\n\n\tif(this->name != \"init\")\n\t\tdefn->original = this;\n\n\ticeAssert(!infer || (infer->isStructType() || infer->isClassType()));\n\tdefn->parentTypeForMethod = infer;\n\n\n\tdefn->attrs = this->attrs;\n\tdefn->bareName = this->name;\n\tdefn->id = Identifier(this->name, IdKind::Function);\n\tdefn->id.scope = this->enclosingScope;\n\tdefn->id.params = ptys;\n\tdefn->id.returnType = retty;\n\tdefn->enclosingScope = this->enclosingScope;\n\n\tdefn->params = ps;\n\tdefn->returnType = retty;\n\tdefn->visibility = this->visibility;\n\n\tdefn->global = !fs->isInFunctionBody();\n\n\tdefn->isVirtual = this->isVirtual;\n\tdefn->isOverride = this->isOverride;\n\tdefn->isMutating = this->isMutating;\n\n\tif(defn->isVirtual && !defn->parentTypeForMethod)\n\t{\n\t\terror(defn, \"only methods can be marked 'virtual' or 'override' at this point in time\");\n\t}\n\telse if(defn->isVirtual && defn->parentTypeForMethod && !defn->parentTypeForMethod->isClassType())\n\t{\n\t\terror(defn, \"only methods of a class (which '%s' is not) can be marked 'virtual' or 'override'\",\n\t\t\tdefn->parentTypeForMethod->str());\n\t}\n\telse if(defn->isMutating && !defn->parentTypeForMethod)\n\t{\n\t\terror(defn, \"only methods of a type can be marked as mutating with 'mut'\");\n\t}\n\n\tauto conflict_err = fs->checkForShadowingOrConflictingDefinition(defn, [defn](sst::TypecheckState* fs, sst::Stmt* other) -> bool {\n\n\t\tif(auto oth = dcast(sst::FunctionDecl, other))\n\t\t{\n\t\t\t// make sure we didn't fuck up somewhere\n\t\t\ticeAssert(oth->id.name == defn->id.name);\n\t\t\treturn sst::isDuplicateOverload(defn->params, oth->params);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// variables and functions always conflict if they're in the same namespace\n\t\t\treturn true;\n\t\t}\n\t});\n\n\tif(conflict_err)\n\t\treturn TCResult(conflict_err);\n\n\tif(!defn->type->containsPlaceholders())\n\t\tdefn->enclosingScope.stree->addDefinition(this->name, defn, gmaps);\n\n\telse if(defn->enclosingScope.stree->unresolvedGenericDefs[this->name].empty())\n\t\tdefn->enclosingScope.stree->unresolvedGenericDefs[this->name].push_back(this);\n\n\n\t// add to our versions.\n\tthis->genericVersions.push_back({ defn, fs->getGenericContextStack() });\n\treturn TCResult(defn);\n}\n\nTCResult ast::FuncDefn::typecheck(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto tcr = this->generateDeclaration(fs, infer, gmaps);\n\tif(tcr.isParametric())  return tcr;\n\telse if(!tcr.isDefn())  error(this, \"failed to generate declaration for function '%s'\", this->name);\n\n\tauto defn = dcast(sst::FunctionDefn, tcr.defn());\n\ticeAssert(defn);\n\n\tif(this->finishedTypechecking.find(defn) != this->finishedTypechecking.end())\n\t\treturn TCResult(defn);\n\n\t// if we have placeholders, don't bother generating anything.\n\tif(!defn->type->containsPlaceholders())\n\t{\n\t\tfs->teleportInto(defn->enclosingScope);\n\n\t\tfs->enterFunctionBody(defn);\n\t\tfs->pushTree(defn->id.convertToName().mangledWithoutScope());\n\t\t{\n\t\t\t// add the arguments to the tree\n\n\t\t\tfor(auto arg : defn->params)\n\t\t\t{\n\t\t\t\tauto vd = util::pool<sst::ArgumentDefn>(arg.loc);\n\t\t\t\tvd->id = Identifier(arg.name, IdKind::Name);\n\t\t\t\tvd->id.scope = fs->scope();\n\n\t\t\t\tvd->type = arg.type;\n\n\t\t\t\tfs->stree->addDefinition(arg.name, vd);\n\n\t\t\t\tdefn->arguments.push_back(vd);\n\t\t\t}\n\n\t\t\tthis->body->isFunctionBody = true;\n\t\t\tdefn->body = dcast(sst::Block, this->body->typecheck(fs, defn->returnType).stmt());\n\t\t\tdefn->body->isSingleExpr = this->body->isArrow;\n\n\t\t\ticeAssert(defn->body);\n\n\t\t\tdefn->insideTree = fs->stree;\n\t\t}\n\t\tfs->popTree();\n\t\tfs->leaveFunctionBody();\n\n\t\tfs->teleportOut();\n\n\t\t// ok, do the check.\n\t\tdefn->needReturnVoid = !fs->checkAllPathsReturn(defn);\n\t}\n\n\tthis->finishedTypechecking.insert(defn);\n\treturn TCResult(defn);\n}\n\n\nTCResult ast::ForeignFuncDefn::typecheck(sst::TypecheckState* fs, fir::Type* inferred)\n{\n\tif(this->generatedDecl)\n\t\treturn TCResult(this->generatedDecl);\n\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto defn = util::pool<sst::ForeignFuncDefn>(this->loc);\n\tstd::vector<FnParam> ps;\n\n\tfor(auto t : this->params)\n\t\tps.push_back(FnParam(t.loc, t.name, fs->convertParserTypeToFIR(t.type)));\n\n\tauto retty = fs->convertParserTypeToFIR(this->returnType);\n\n\tdefn->id = Identifier(this->name, IdKind::Name);\n\tdefn->bareName = this->name;\n\tdefn->attrs = this->attrs;\n\n\tdefn->params = ps;\n\tdefn->returnType = retty;\n\tdefn->visibility = this->visibility;\n\tdefn->isVarArg = this->isVarArg;\n\n\t// the realname is the actual name of the function.\n\tdefn->realName = this->realName;\n\tdefn->isIntrinsic = this->isIntrinsic;\n\n\tif(this->isVarArg)\n\t\tdefn->type = fir::FunctionType::getCVariadicFunc(zfu::map(ps, [](const FnParam& p) -> auto { return p.type; }), retty);\n\n\telse\n\t\tdefn->type = fir::FunctionType::get(zfu::map(ps, [](const FnParam& p) -> auto { return p.type; }), retty);\n\n\n\tauto conflict_err = fs->checkForShadowingOrConflictingDefinition(defn, [defn](sst::TypecheckState* fs, sst::Stmt* other) -> bool {\n\n\t\tif(auto decl = dcast(sst::FunctionDecl, other))\n\t\t{\n\t\t\t// make sure we didn't fuck up somewhere\n\t\t\ticeAssert(decl->id.name == defn->id.name);\n\n\t\t\t// check the typelists, then\n\t\t\tbool ret = fir::Type::areTypeListsEqual(\n\t\t\t\tzfu::map(defn->params, [](const FnParam& p) -> fir::Type* { return p.type; }),\n\t\t\t\tzfu::map(decl->params, [](const FnParam& p) -> fir::Type* { return p.type; })\n\t\t\t);\n\n\t\t\treturn ret;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// variables and functions always conflict if they're in the same namespace\n\t\t\treturn true;\n\t\t}\n\t});\n\n\tif(conflict_err)\n\t\treturn TCResult(conflict_err);\n\n\tthis->generatedDecl = defn;\n\n\tfs->stree->addDefinition(this->name, defn);\n\n\treturn TCResult(defn);\n}\n\n\n\n\n\nTCResult ast::Block::typecheck(sst::TypecheckState* fs, fir::Type* inferred)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tif(!this->isFunctionBody && !this->doNotPushNewScope)\n\t\tfs->pushAnonymousTree();\n\n\tdefer((!this->isFunctionBody && !this->doNotPushNewScope) ? fs->popTree() : static_cast<sst::StateTree*>(nullptr));\n\n\tauto ret = util::pool<sst::Block>(this->loc);\n\n\tret->closingBrace = this->closingBrace;\n\n\tif(this->isArrow && this->isFunctionBody)\n\t{\n\t\ticeAssert(this->deferredStatements.empty());\n\t\ticeAssert(this->statements.size() == 1);\n\n\t\tauto s = this->statements[0];\n\t\tif(auto e = dcast(ast::Expr, s))\n\t\t{\n\t\t\tauto ex = e->typecheck(fs, inferred).expr();\n\t\t\tif(inferred && fir::getCastDistance(ex->type, inferred) < 0)\n\t\t\t{\n\t\t\t\tif(inferred->isVoidType())\n\t\t\t\t{\n\t\t\t\t\tret->statements = { ex };\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\terror(ex, \"invalid single-expression with type '%s' in function returning '%s'\", ex->type, inferred);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif(!fs->getCurrentFunction()->returnType->isVoidType())\n\t\t\t\t{\n\t\t\t\t\tauto rst = util::pool<sst::ReturnStmt>(s->loc);\n\t\t\t\t\trst->expectedType = (inferred ? inferred : fs->getCurrentFunction()->returnType);\n\t\t\t\t\trst->value = ex;\n\n\t\t\t\t\tret->statements = { rst };\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tret->statements = { ex };\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(s, \"invalid use of statement in single-expression function body\");\n\t\t}\n\t}\n\telse\n\t{\n\t\tfor(auto stmt : this->statements)\n\t\t{\n\t\t\tif(auto p = dcast(Parameterisable, stmt); p)\n\t\t\t{\n\t\t\t\tp->enclosingScope = fs->scope();\n\t\t\t}\n\n\t\t\tauto tcr = stmt->typecheck(fs);\n\t\t\tif(tcr.isError())\n\t\t\t\treturn TCResult(tcr.error());\n\n\t\t\telse if(!tcr.isParametric() && !tcr.isDummy())\n\t\t\t\tret->statements.push_back(tcr.stmt());\n\t\t}\n\n\t\tfor(auto dstmt : this->deferredStatements)\n\t\t{\n\t\t\tif(auto p = dcast(Parameterisable, dstmt); p)\n\t\t\t{\n\t\t\t\tp->enclosingScope = fs->scope();\n\t\t\t}\n\n\t\t\tauto tcr = dstmt->typecheck(fs);\n\t\t\tif(tcr.isError())\n\t\t\t\treturn TCResult(tcr.error());\n\n\t\t\telse if(!tcr.isParametric() && !tcr.isDummy())\n\t\t\t\tret->deferred.push_back(tcr.stmt());\n\t\t}\n\t}\n\n\n\treturn TCResult(ret);\n}\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/literals.cpp",
    "content": "// literals.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"typecheck.h\"\n\n#include \"ir/type.h\"\n#include \"ir/constant.h\"\n\n#include \"memorypool.h\"\n\nTCResult ast::LitNumber::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\t// i don't think mpfr auto-detects base, LMAO\n\tint base = 10;\n\tif(this->num.find(\"0x\") == 0 || this->num.find(\"0X\") == 0)\n\t\tbase = 16;\n\n\tauto number = mpfr::mpreal(this->num, mpfr_get_default_prec(), base);\n\tbool sgn = mpfr::signbit(number);\n\tbool flt = ((this->num.find(\".\") != std::string::npos) || !mpfr::isint(number));\n\n\tsize_t bits = 0;\n\tif(flt)\n\t{\n\t\t// fuck it lah.\n\t\tbits = sizeof(double) * CHAR_BIT;\n\t}\n\telse\n\t{\n\t\tauto m_ptr = number.mpfr_ptr();\n\t\tauto m_rnd = MPFR_RNDN;\n\t\tif(mpfr_fits_sshort_p(m_ptr, m_rnd))\n\t\t\tbits = sizeof(short) * CHAR_BIT;\n\n\t\telse if(mpfr_fits_sint_p(m_ptr, m_rnd))\n\t\t\tbits = sizeof(int) * CHAR_BIT;\n\n\t\telse if(mpfr_fits_slong_p(m_ptr, m_rnd))\n\t\t\tbits = sizeof(long) * CHAR_BIT;\n\n\t\telse if(mpfr_fits_intmax_p(m_ptr, m_rnd))\n\t\t\tbits = sizeof(intmax_t) * CHAR_BIT;\n\n\t\telse if(!sgn && mpfr_fits_uintmax_p(m_ptr, m_rnd))\n\t\t\tbits = sizeof(uintmax_t) * CHAR_BIT;\n\n\t\telse    // lmao\n\t\t\tbits = sizeof(uintmax_t) * CHAR_BIT;\n\t}\n\n\tauto ret = util::pool<sst::LiteralNumber>(this->loc, (infer && infer->isPrimitiveType()) ? infer\n\t\t: fir::ConstantNumberType::get(sgn, flt, bits));\n\n\tret->num = number;\n\n\treturn TCResult(ret);\n}\n\nTCResult ast::LitNull::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto ret = util::pool<sst::LiteralNull>(this->loc, fir::Type::getNull());\n\treturn TCResult(ret);\n}\n\nTCResult ast::LitBool::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto ret = util::pool<sst::LiteralBool>(this->loc, fir::Type::getBool());\n\tret->value = this->value;\n\n\treturn TCResult(ret);\n}\n\nTCResult ast::LitChar::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto ret = util::pool<sst::LiteralChar>(this->loc, fir::Type::getInt8());\n\tret->value = this->value;\n\n\treturn TCResult(ret);\n}\n\nTCResult ast::LitTuple::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tstd::vector<sst::Expr*> vals;\n\tstd::vector<fir::Type*> fts;\n\n\tif(infer)\n\t{\n\t\tif(!infer->isTupleType())\n\t\t\terror(this, \"assigning tuple to inferred non-tuple type '%s'\", infer);\n\n\t\tauto tt = infer->toTupleType();\n\t\tif(tt->getElementCount() != this->values.size())\n\t\t{\n\t\t\terror(this, \"mismatched types in inferred type: have literal with %d elements, inferred type has %d\", this->values.size(),\n\t\t\t\ttt->getElementCount());\n\t\t}\n\t}\n\n\tsize_t k = 0;\n\tfor(auto v : this->values)\n\t{\n\t\tauto inf = (infer ? infer->toTupleType()->getElementN(k) : 0);\n\t\tauto expr = v->typecheck(fs, inf).expr();\n\n\t\tauto ty = expr->type;\n\t\tif(expr->type->isConstantNumberType() && (!inf || !inf->isPrimitiveType()))\n\t\t\tty = sst::inferCorrectTypeForLiteral(expr->type->toConstantNumberType());\n\n\t\tvals.push_back(expr);\n\t\tfts.push_back(ty);\n\n\t\tk++;\n\t}\n\n\t// warn(this, \"%s\", fir::TupleType::get(fts));\n\tauto ret = util::pool<sst::LiteralTuple>(this->loc, fir::TupleType::get(fts));\n\tret->values = vals;\n\n\treturn TCResult(ret);\n}\n\nTCResult ast::LitString::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\n\tfir::Type* ty = 0;\n\tif(this->isCString || (infer && infer == fir::Type::getInt8Ptr()))\n\t{\n\t\tty = fir::Type::getInt8Ptr();\n\t}\n\telse\n\t{\n\t\tty = fir::Type::getCharSlice(false);\n\t}\n\n\tauto ret = util::pool<sst::LiteralString>(this->loc, ty);\n\tret->isCString = this->isCString;\n\tret->str = this->str;\n\n\treturn TCResult(ret);\n}\n\nTCResult ast::LitArray::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tstd::vector<sst::Expr*> vals;\n\n\tfir::Type* type = 0;\n\tif(this->values.empty())\n\t{\n\t\tif(this->explicitType)\n\t\t{\n\t\t\tauto explty = fs->convertParserTypeToFIR(this->explicitType);\n\t\t\ticeAssert(explty);\n\n\t\t\ttype = fir::DynamicArrayType::get(explty);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif(infer == 0)\n\t\t\t{\n\t\t\t\t// facilitate passing empty array literals around (that can be cast to a bunch of things like slices and such)\n\t\t\t\tinfer = fir::DynamicArrayType::get(fir::VoidType::get());\n\t\t\t}\n\t\t\telse if(infer->isArrayType())\n\t\t\t{\n\t\t\t\tif(infer->toArrayType()->getArraySize() != 0)\n\t\t\t\t\terror(this, \"array type with non-zero length %d was inferred for empty array literal\", infer->toArrayType()->getArraySize());\n\t\t\t}\n\t\t\telse if(!(infer->isDynamicArrayType() || infer->isArraySliceType()))\n\t\t\t{\n\t\t\t\terror(this, \"invalid type '%s' inferred for array literal\", infer);\n\t\t\t}\n\t\t}\n\n\t\ttype = infer;\n\t}\n\telse\n\t{\n\t\tfir::Type* elmty = (this->explicitType ? fs->convertParserTypeToFIR(this->explicitType) : 0);\n\n\t\tif(!elmty && infer)\n\t\t{\n\t\t\tif(!infer->isDynamicArrayType() && !infer->isArraySliceType() && !infer->isArrayType())\n\t\t\t\terror(this, \"invalid type '%s' inferred for array literal\", infer);\n\n\t\t\telmty = infer->getArrayElementType();\n\t\t}\n\n\t\tfor(auto v : this->values)\n\t\t{\n\t\t\tauto e = v->typecheck(fs, elmty).expr();\n\n\t\t\tif(!elmty)\n\t\t\t{\n\t\t\t\tif(e->type->isConstantNumberType() && !infer)\n\t\t\t\t\telmty = sst::inferCorrectTypeForLiteral(e->type->toConstantNumberType());\n\n\t\t\t\telse\n\t\t\t\t\telmty = e->type;\n\t\t\t}\n\t\t\telse if(elmty != e->type)\n\t\t\t{\n\t\t\t\terror(v, \"mismatched type for expression in array literal; expected '%s'%s, found '%s'\",\n\t\t\t\t\telmty, (this->explicitType ? \"\" : \" as inferred from previous elements\"), e->type);\n\t\t\t}\n\n\n\t\t\tif(e->type->isVoidType())\n\t\t\t{\n\t\t\t\t// be helpful\n\t\t\t\tauto err = SimpleError::make(v->loc, \"expected value in array literal, found 'void' value instead\");\n\n\t\t\t\tif(auto fc = dcast(sst::FunctionCall, e); fc && fc->target)\n\t\t\t\t\terr->append(SimpleError::make(MsgType::Note, fc->target->loc, \"function was defined here:\"));\n\n\t\t\t\terr->postAndQuit();\n\t\t\t}\n\n\t\t\tvals.push_back(e);\n\t\t}\n\n\t\t//* note: prefer slices by default.\n\t\t// this behaviour changed as of 08/04/2018\n\t\tif(this->raw || (infer && infer->isArrayType()))\n\t\t{\n\t\t\ttype = fir::ArrayType::get(elmty, this->values.size());\n\t\t}\n\t\telse if(infer == 0 || infer->isArraySliceType())\n\t\t{\n\t\t\t// slices from a constant array generally should remain immutable.\n\t\t\ttype = fir::ArraySliceType::get(elmty, false);\n\t\t}\n\t\telse if(infer->isDynamicArrayType())\n\t\t{\n\t\t\t// do something\n\t\t\ttype = fir::DynamicArrayType::get(elmty);\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(this, \"invalid type '%s' inferred for array literal\", infer);\n\t\t}\n\t}\n\n\tauto ret = util::pool<sst::LiteralArray>(this->loc, type);\n\tret->values = vals;\n\n\treturn TCResult(ret);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/loops.cpp",
    "content": "// loops.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"pts.h\"\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"ir/type.h\"\n\n#include \"memorypool.h\"\n\nTCResult ast::ForeachLoop::typecheck(sst::TypecheckState* fs, fir::Type* inferred)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto ret = util::pool<sst::ForeachLoop>(this->loc);\n\n\tfs->pushAnonymousTree();\n\tdefer(fs->popTree());\n\n\n\tret->array = this->array->typecheck(fs).expr();\n\n\tfir::Type* elmty = 0;\n\tif(ret->array->type->isArrayType() || ret->array->type->isDynamicArrayType() || ret->array->type->isArraySliceType())\n\t\telmty = ret->array->type->getArrayElementType();\n\n\telse if(ret->array->type->isRangeType())\n\t\telmty = fir::Type::getNativeWord();\n\n\telse if(ret->array->type->isStringType())\n\t\telmty = fir::Type::getInt8();\n\n\telse\n\t\terror(this->array, \"invalid type '%s' in foreach loop\", ret->array->type);\n\n\ticeAssert(elmty);\n\tbool allowref = !(ret->array->type->isStringType() || ret->array->type->isRangeType());\n\n\tif(!this->indexVar.empty())\n\t{\n\t\tauto fake = util::pool<ast::VarDefn>(this->loc);\n\t\tfake->name = this->indexVar;\n\t\tfake->type = pts::NamedType::create(this->loc, INTUNSPEC_TYPE_STRING);\n\n\t\tret->indexVar = dcast(sst::VarDefn, fake->typecheck(fs).defn());\n\t\ticeAssert(ret->indexVar);\n\t}\n\n\tret->mappings = fs->typecheckDecompositions(this->bindings, elmty, true, allowref);\n\n\tfs->enterBreakableBody();\n\t{\n\t\tret->body = dcast(sst::Block, this->body->typecheck(fs).stmt());\n\t\ticeAssert(ret->body);\n\t}\n\tfs->leaveBreakableBody();\n\n\treturn TCResult(ret);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTCResult ast::WhileLoop::typecheck(sst::TypecheckState* fs, fir::Type* inferred)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tsst::WhileLoop* ret = util::pool<sst::WhileLoop>(this->loc);\n\tret->isDoVariant = this->isDoVariant;\n\n\tfs->pushAnonymousTree();\n\tdefer(fs->popTree());\n\n\tfs->enterBreakableBody();\n\t{\n\t\tret->body = dcast(sst::Block, this->body->typecheck(fs).stmt());\n\t\ticeAssert(ret->body);\n\t}\n\tfs->leaveBreakableBody();\n\n\tif(this->cond)\n\t{\n\t\tret->cond = this->cond->typecheck(fs, fir::Type::getBool()).expr();\n\t\tif(ret->cond->type != fir::Type::getBool() && !ret->cond->type->isPointerType())\n\t\t\terror(this->cond, \"non-boolean expression with type '%s' cannot be used as a conditional\", ret->cond->type);\n\t}\n\n\treturn TCResult(ret);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTCResult ast::BreakStmt::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tif(!fs->isInBreakableBody())\n\t\terror(this, \"cannot 'break' while not inside a loop\");\n\n\telse if(fs->isInDeferBlock())\n\t\terror(this, \"cannot 'break' while inside a deferred block\");\n\n\treturn TCResult(util::pool<sst::BreakStmt>(this->loc));\n}\n\nTCResult ast::ContinueStmt::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tif(!fs->isInBreakableBody())\n\t\terror(this, \"cannot 'continue' while not inside a loop\");\n\n\telse if(fs->isInDeferBlock())\n\t\terror(this, \"cannot 'continue' while inside a deferred block\");\n\n\treturn TCResult(util::pool<sst::ContinueStmt>(this->loc));\n}\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/misc.cpp",
    "content": "// misc.cpp\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"pts.h\"\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n#include \"ir/type.h\"\n\n#include \"memorypool.h\"\n\n\nTCResult ast::PlatformDefn::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tif(this->defnType == Type::Intrinsic)\n\t{\n\t\tthis->intrinsicDefn->isIntrinsic = true;\n\t\treturn this->intrinsicDefn->typecheck(fs, infer);\n\t}\n\telse if(this->defnType == Type::IntegerType)\n\t{\n\t\tauto defn = util::pool<sst::BareTypeDefn>(this->loc);\n\t\t// auto opty = fir::OpaqueType::get(this->typeName, this->typeSizeInBits);\n\t\tauto ty = fir::PrimitiveType::getUintN(this->typeSizeInBits);\n\n\t\tdefn->type = ty;\n\t\tdefn->id = Identifier(this->typeName, IdKind::Type);\n\t\tdefn->id.scope = fs->scope();\n\n\t\tfs->checkForShadowingOrConflictingDefinition(defn, [](sst::TypecheckState* fs, sst::Defn* other) -> bool { return true; });\n\n\t\t// add it first so we can use it in the method bodies,\n\t\t// and make pointers to it\n\t\t{\n\t\t\tfs->stree->addDefinition(this->typeName, defn);\n\t\t\tfs->typeDefnMap[ty] = defn;\n\t\t}\n\n\t\treturn TCResult(defn);\n\t}\n\telse\n\t{\n\t\treturn TCResult(SimpleError::make(this->loc, \"nani?\"));\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/operators.cpp",
    "content": "// operators.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"ir/type.h\"\n\nstatic bool isBuiltinType(fir::Type* ty)\n{\n\treturn (ty->isConstantNumberType()\n\t\t|| ty->isDynamicArrayType()\n\t\t|| ty->isArraySliceType()\n\t\t|| ty->isPrimitiveType()\n\t\t|| ty->isFunctionType()\n\t\t|| ty->isPointerType()\n\t\t|| ty->isStringType()\n\t\t|| ty->isRangeType()\n\t\t|| ty->isArrayType()\n\t\t|| ty->isVoidType()\n\t\t|| ty->isNullType()\n\t\t|| ty->isCharType()\n\t\t|| ty->isBoolType());\n}\n\nstatic bool isBuiltinOperator(std::string op)\n{\n\treturn (op == Operator::Plus ||\n\t\t\top == Operator::Minus ||\n\t\t\top == Operator::Multiply ||\n\t\t\top == Operator::Divide ||\n\t\t\top == Operator::Modulo ||\n\t\t\top == Operator::UnaryPlus ||\n\t\t\top == Operator::UnaryMinus ||\n\t\t\top == Operator::PointerDeref ||\n\t\t\top == Operator::AddressOf ||\n\t\t\top == Operator::BitwiseNot ||\n\t\t\top == Operator::BitwiseAnd ||\n\t\t\top == Operator::BitwiseOr ||\n\t\t\top == Operator::BitwiseXor ||\n\t\t\top == Operator::BitwiseShiftLeft ||\n\t\t\top == Operator::BitwiseShiftRight ||\n\t\t\top == Operator::LogicalNot ||\n\t\t\top == Operator::LogicalAnd ||\n\t\t\top == Operator::LogicalOr ||\n\t\t\top == Operator::CompareEQ ||\n\t\t\top == Operator::CompareNEQ ||\n\t\t\top == Operator::CompareLT ||\n\t\t\top == Operator::CompareLEQ ||\n\t\t\top == Operator::CompareGT ||\n\t\t\top == Operator::CompareGEQ ||\n\t\t\top == Operator::Assign ||\n\t\t\top == Operator::PlusEquals ||\n\t\t\top == Operator::MinusEquals ||\n\t\t\top == Operator::MultiplyEquals ||\n\t\t\top == Operator::DivideEquals ||\n\t\t\top == Operator::ModuloEquals ||\n\t\t\top == Operator::BitwiseShiftLeftEquals ||\n\t\t\top == Operator::BitwiseShiftRightEquals ||\n\t\t\top == Operator::BitwiseAndEquals ||\n\t\t\top == Operator::BitwiseOrEquals ||\n\t\t\top == Operator::TypeCast || op == Operator::TypeIs ||\n\t\t\top == \".\");\n}\n\n\n\nTCResult ast::OperatorOverloadDefn::typecheck(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tif(this->kind == Kind::Invalid)\n\t\terror(this, \"invalid operator kind; must be one of 'infix', 'postfix', or 'prefix'\");\n\n\tif(fs->hasSelfContext())\n\t\terror(this, \"operator overloads cannot be methods of a type.\");\n\n\tthis->generateDeclaration(fs, infer, { });\n\n\t// call the superclass method.\n\treturn this->ast::FuncDefn::typecheck(fs, infer, gmaps);\n}\n\nTCResult ast::OperatorOverloadDefn::generateDeclaration(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto [ success, ret ] = this->checkForExistingDeclaration(fs, gmaps);\n\tif(!success)    return TCResult::getParametric();\n\telse if(ret)    return TCResult(ret);\n\n\t// there's nothing different.\n\tauto defn = dcast(sst::FunctionDefn, this->ast::FuncDefn::generateDeclaration(fs, infer, gmaps).defn());\n\ticeAssert(defn);\n\n\n\t//! ACHTUNG !\n\t// TODO: is there actually a problem with allowing both types to be user-defined?\n\t//? eg we want some_string * 5 to repeat 'some_string' 5 times???\n\t//? is that a legit use-case??\n\n\t// ok, do our checks on the defn instead.\n\tauto ft = defn->type->toFunctionType();\n\n\tif(this->kind == Kind::Infix)\n\t{\n\t\tif(ft->getArgumentCount() != 2)\n\t\t{\n\t\t\terror(this, \"operator overload for binary operator '%s' must have exactly 2 parameters, but %d %s found\",\n\t\t\t\tthis->symbol, ft->getArgumentCount(), ft->getArgumentCount() == 1 ? \"was\" : \"were\");\n\t\t}\n\t\telse if(!Operator::isAssignment(this->symbol) && isBuiltinType(ft->getArgumentN(0)) && isBuiltinType(ft->getArgumentN(1))\n\t\t\t && isBuiltinOperator(this->symbol))\n\t\t{\n\t\t\tSimpleError::make(this->loc, \"binary operator overload (for operator '%s') cannot take two builtin types as arguments (have '%s' and '%s')\",\n\t\t\t\tthis->symbol, ft->getArgumentN(0), ft->getArgumentN(1))\n\t\t\t\t->append(BareError::make(MsgType::Note, \"at least one of the parameters must be a user-defined type\"))\n\t\t\t\t->postAndQuit();\n\t\t}\n\t}\n\telse if(this->kind == Kind::Postfix || this->kind == Kind::Prefix)\n\t{\n\t\tif(ft->getArgumentCount() != 1)\n\t\t{\n\t\t\terror(this, \"operator overload for unary operator '%s' must have exactly 1 parameter, but %d %s found\",\n\t\t\t\tthis->symbol, ft->getArgumentCount(), ft->getArgumentCount() == 1 ? \"was\" : \"were\");\n\t\t}\n\t\telse if(isBuiltinType(ft->getArgumentN(0)) && isBuiltinOperator(this->symbol))\n\t\t{\n\t\t\terror(defn->arguments[0], \"unary operator '%s' cannot be overloaded for the builtin type '%s'\",\n\t\t\t\tthis->symbol, ft->getArgumentN(0));\n\t\t}\n\t}\n\n\t// ok, further checks.\n\tif(Operator::isAssignment(this->symbol))\n\t{\n\t\tif(!ft->getReturnType()->isVoidType())\n\t\t{\n\t\t\terror(this, \"operator overload for assignment operators (have '%s') must return void, but a return type of '%s' was found\",\n\t\t\t\tthis->symbol, ft->getReturnType());\n\t\t}\n\t\telse if(!ft->getArgumentN(0)->isPointerType())\n\t\t{\n\t\t\terror(defn->arguments[0], \"operator overload for assignment operator '%s' must take a pointer to the type as the first parameter, found '%s'\",\n\t\t\t\tthis->symbol, ft->getArgumentN(0));\n\t\t}\n\t\telse if(isBuiltinType(ft->getArgumentN(0)->getPointerElementType()))\n\t\t{\n\t\t\terror(defn->arguments[0], \"assignment operator '%s' cannot be overloaded for the builtin type '%s'\",\n\t\t\t\tthis->symbol, ft->getArgumentN(0));\n\t\t}\n\t}\n\n\t// before we add, check for duplication.\n\tauto thelist = (this->kind == Kind::Infix ? &fs->stree->infixOperatorOverloads : (this->kind == Kind::Prefix\n\t\t? &fs->stree->prefixOperatorOverloads : &fs->stree->postfixOperatorOverloads));\n\n\tfor(auto it : (*thelist)[this->symbol])\n\t{\n\t\tif(sst::isDuplicateOverload(it->params, defn->params))\n\t\t{\n\t\t\tSimpleError::make(this->loc, \"duplicate operator overload for '%s' taking identical arguments\", this->symbol)\n\t\t\t\t->append(SimpleError::make(MsgType::Note, it->loc, \"previous definition was here:\"))\n\t\t\t\t->postAndQuit();\n\t\t}\n\t}\n\n\t// ok, we should be good now.\n\t(*thelist)[this->symbol].push_back(defn);\n\treturn TCResult(defn);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/polymorph/driver.cpp",
    "content": "// driver.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"sst.h\"\n\n#include \"ir/type.h\"\n\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"resolver.h\"\n#include \"polymorph.h\"\n\n#include \"memorypool.h\"\n\n#include <set>\n\nnamespace sst {\nnamespace poly\n{\n\tstd::vector<PolyRefResult> findPolymorphReferences(TypecheckState* fs, const std::string& name, const std::vector<ast::Parameterisable*>& gdefs,\n\t\tconst PolyArgMapping_t& pams, fir::Type* return_infer, fir::Type* type_infer, bool isFnCall, std::vector<FnCallArgument>* args)\n\t{\n\t\ticeAssert(gdefs.size() > 0);\n\n\t\t//? now if we have multiple things then we need to try them all, which can get real slow real quick.\n\t\t//? unfortunately I see no better way to do this.\n\t\t// TODO: find a better way to do this??\n\n\t\tstd::vector<PolyRefResult> pots;\n\n\t\tfor(const auto& gdef : gdefs)\n\t\t{\n\t\t\tauto [ gmaps, err ] = resolver::misc::canonicalisePolyArguments(fs, gdef, pams);\n\t\t\tif(err != nullptr)\n\t\t\t{\n\t\t\t\tpots.push_back(PolyRefResult(TCResult(err), Solution_t(), gdef));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto [ r, s ] = attemptToInstantiatePolymorph(fs, gdef, name, gmaps, return_infer, type_infer, isFnCall,\n\t\t\t\t\targs, /* fillplaceholders: */ true);\n\n\t\t\t\tpots.push_back(PolyRefResult(r, s, gdef));\n\t\t\t}\n\t\t}\n\n\t\treturn pots;\n\t}\n\n\n\n\n\n\tnamespace internal\n\t{\n\t\tstatic std::pair<Solution_t, ErrorMsg*> inferPolymorphicType(TypecheckState* fs, ast::TypeDefn* td, const std::string& name,\n\t\t\tconst ProblemSpace_t& problems, const std::vector<FnCallArgument>& input, const TypeParamMap_t& partial, fir::Type* return_infer,\n\t\t\tfir::Type* type_infer, bool isFnCall, fir::Type* problem_infer, util::hash_map<std::string, size_t>* origParamOrder)\n\t\t{\n\t\t\tauto soln = Solution_t(partial);\n\n\t\t\tif(!isFnCall && !type_infer)\n\t\t\t{\n\t\t\t\tif(auto missing = getMissingSolutions(problems, soln.solutions, true); missing.size() > 0)\n\t\t\t\t{\n\t\t\t\t\tauto ret = solvePolymorphWithPlaceholders(fs, td, name, partial);\n\t\t\t\t\treturn { ret.second, nullptr };\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn { soln, nullptr };\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(auto cls = dcast(ast::ClassDefn, td))\n\t\t\t{\n\t\t\t\tutil::hash_map<std::string, size_t> paramOrder;\n\n\t\t\t\tauto inputcopy = input;\n\t\t\t\tauto selfty = fir::PolyPlaceholderType::get(fir::obfuscateName(\"self_infer\"), getNextSessionId());\n\t\t\t\tinputcopy.insert(inputcopy.begin(), FnCallArgument(fs->loc(), \"\", util::pool<sst::RawValueExpr>(fs->loc(),\n\t\t\t\t\tselfty->getMutablePointerTo()), 0));\n\n\t\t\t\tfs->pushSelfContext(selfty);\n\t\t\t\tdefer(fs->popSelfContext());\n\n\n\n\t\t\t\tstd::vector<std::pair<Solution_t, ErrorMsg*>> rets;\n\t\t\t\tfor(auto init : cls->initialisers)\n\t\t\t\t{\n\t\t\t\t\trets.push_back(inferTypesForPolymorph(fs, init, name, cls->generics, inputcopy, partial, return_infer, type_infer, isFnCall,\n\t\t\t\t\t\tproblem_infer, &paramOrder));\n\t\t\t\t}\n\n\t\t\t\t// check the distance of all the solutions... i guess?\n\t\t\t\tstd::pair<Solution_t, ErrorMsg*> best;\n\t\t\t\tbest.first = soln;\n\t\t\t\tbest.first.distance = INT_MAX;\n\t\t\t\tbest.second = SimpleError::make(fs->loc(), \"ambiguous reference to constructor of class '%s'\", cls->name);\n\n\t\t\t\tfor(const auto& r : rets)\n\t\t\t\t{\n\t\t\t\t\tif(r.first.distance < best.first.distance && r.second == nullptr)\n\t\t\t\t\t\tbest = r;\n\t\t\t\t}\n\n\t\t\t\t*origParamOrder = paramOrder;\n\t\t\t\treturn best;\n\t\t\t}\n\t\t\telse if(auto str = dcast(ast::StructDefn, td))\n\t\t\t{\n\t\t\t\t//* for constructors, we look like a function call, so type_infer is actually return_infer.\n\t\t\t\tif(!type_infer && return_infer)\n\t\t\t\t{\n\t\t\t\t\t//* so what we do here is, if we have type_infer, we lookup the sst::Defn, and use it to find the matching genericVersion\n\t\t\t\t\t//* in the ast::Defn, and extract the solution map, then recursively call inferPolymorphicType with our new solution.\n\t\t\t\t\tstd::swap(type_infer, return_infer);\n\t\t\t\t\tif(auto gen_str = fs->typeDefnMap[type_infer])\n\t\t\t\t\t{\n\t\t\t\t\t\tfor(const auto& v : str->genericVersions)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif(v.first == gen_str)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn inferPolymorphicType(fs, str, name, problems, input, v.second.back(), /* return_infer: */ nullptr,\n\t\t\t\t\t\t\t\t\t/* type_infer: */ nullptr, isFnCall, problem_infer, origParamOrder);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tstd::vector<std::string> fields;\n\t\t\t\tutil::hash_map<std::string, size_t> fieldNames;\n\t\t\t\t{\n\t\t\t\t\tsize_t i = 0;\n\t\t\t\t\tfor(auto f : str->fields)\n\t\t\t\t\t{\n\t\t\t\t\t\tauto nm = std::get<0>(f);\n\n\t\t\t\t\t\tfields.push_back(nm);\n\t\t\t\t\t\tfieldNames[nm] = i++;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tauto [ seen, err ] = resolver::verifyStructConstructorArguments(fs->loc(), str->name, fields, input);\n\t\t\t\tif(err) return { soln, err };\n\n\t\t\t\tint session = getNextSessionId();\n\t\t\t\tstd::vector<ArgType> given(seen.size());\n\t\t\t\tstd::vector<ArgType> target(seen.size());\n\n\t\t\t\tfor(const auto& s : seen)\n\t\t\t\t{\n\t\t\t\t\tauto idx = fieldNames[s.first];\n\n\t\t\t\t\ttarget[idx] = ArgType(std::get<0>(str->fields[idx]), convertPtsType(fs, str->generics, std::get<2>(str->fields[idx]), session),\n\t\t\t\t\t\tstd::get<1>(str->fields[idx]));\n\n\t\t\t\t\tgiven[idx] = ArgType(input[s.second].name, input[s.second].value->type, input[s.second].loc);\n\t\t\t\t}\n\n\t\t\t\t*origParamOrder = fieldNames;\n\t\t\t\treturn solveTypeList(fs->loc(), target, given, soln, isFnCall);\n\t\t\t}\n\t\t\telse if(auto unn = dcast(ast::UnionDefn, td))\n\t\t\t{\n\t\t\t\t//* see the comment above -- same thing about infer, except we look for type_infer because for unions we know to pass it there\n\t\t\t\t//* (since we don't really look like a function call most of the time)\n\t\t\t\tif(type_infer)\n\t\t\t\t{\n\t\t\t\t\tif(auto gen_str = fs->typeDefnMap[type_infer])\n\t\t\t\t\t{\n\t\t\t\t\t\tfor(const auto& v : unn->genericVersions)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif(v.first == gen_str)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn inferPolymorphicType(fs, unn, name, problems, input, v.second.back(), /* return_infer: */ nullptr,\n\t\t\t\t\t\t\t\t\t/* type_infer: */ nullptr, isFnCall, problem_infer, origParamOrder);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(unn->cases.find(name) == unn->cases.end())\n\t\t\t\t\terror(\"no variant named '%s'\", name);\n\n\t\t\t\tauto uvloc = std::get<1>(unn->cases[name]);\n\n\t\t\t\tint session = getNextSessionId();\n\t\t\t\tfir::Type* vty = convertPtsType(fs, unn->generics, std::get<2>(unn->cases[name]), session);\n\n\t\t\t\t// ok, then. check the type + arguments.\n\t\t\t\tstd::vector<ArgType> target;\n\t\t\t\tif(vty->isTupleType())\n\t\t\t\t{\n\t\t\t\t\tfor(auto t : vty->toTupleType()->getElements())\n\t\t\t\t\t\ttarget.push_back(ArgType(\"\", t, uvloc));\n\t\t\t\t}\n\t\t\t\telse if(!vty->isVoidType())\n\t\t\t\t{\n\t\t\t\t\ttarget.push_back(ArgType(\"\", vty, uvloc));\n\t\t\t\t}\n\n\t\t\t\tauto given = zfu::map(input, [](const FnCallArgument& fca) -> ArgType {\n\t\t\t\t\treturn ArgType(fca.name, fca.value->type, fca.loc);\n\t\t\t\t});\n\n\t\t\t\treturn solveTypeList(fs->loc(), target, given, soln, isFnCall);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\terror(\"no\");\n\t\t\t}\n\t\t}\n\n\n\n\n\t\tstatic std::pair<Solution_t, ErrorMsg*> inferPolymorphicFunction(TypecheckState* fs, ast::Parameterisable* thing, const std::string& name,\n\t\t\tconst ProblemSpace_t& problems, const std::vector<FnCallArgument>& input,\n\t\t\tconst TypeParamMap_t& partial, fir::Type* return_infer, fir::Type* type_infer, bool isFnCall, fir::Type* problem_infer,\n\t\t\tutil::hash_map<std::string, size_t>* origParamOrder)\n\t\t{\n\t\t\tauto soln = Solution_t(partial);\n\n\t\t\tbool isinit = dcast(ast::InitFunctionDefn, thing) != nullptr;\n\t\t\ticeAssert(dcast(ast::FuncDefn, thing) || isinit);\n\n\t\t\tstd::vector<ArgType> given;\n\t\t\tstd::vector<ArgType> target;\n\n\t\t\tpts::Type* retty = 0;\n\t\t\tstd::vector<ast::FuncDefn::Param> params;\n\n\t\t\tif(isinit)\n\t\t\t{\n\t\t\t\tauto i = dcast(ast::InitFunctionDefn, thing);\n\t\t\t\tparams = i->params;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto i = dcast(ast::FuncDefn, thing);\n\t\t\t\tretty = i->returnType;\n\t\t\t\tparams = i->params;\n\t\t\t}\n\n\t\t\tint session = getNextSessionId();\n\n\t\t\tif(!problem_infer)\n\t\t\t{\n\t\t\t\ttarget = internal::unwrapFunctionParameters(fs, problems, params, session);\n\n\t\t\t\tif(!isinit && (!isFnCall || return_infer))\n\t\t\t\t{\n\t\t\t\t\t// add the return type to the fray. it doesn't have a name tho\n\t\t\t\t\ttarget.push_back(ArgType(\"<return_type>\", convertPtsType(fs, thing->generics, retty, session), thing->loc));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto ift = problem_infer->toFunctionType();\n\n\t\t\t\tzfu::foreachIdx(ift->getArgumentTypes(), [&target, &params](fir::Type* ty, size_t i) {\n\t\t\t\t\ttarget.push_back(ArgType(params[i].name, ty, params[i].loc));\n\t\t\t\t});\n\n\t\t\t\tif(!isFnCall || return_infer)\n\t\t\t\t\ttarget.push_back(ArgType(\"<return_type>\", ift->getReturnType(), Location()));\n\t\t\t}\n\n\n\t\t\tif(isFnCall)\n\t\t\t{\n\t\t\t\tgiven = zfu::map(input, [](const FnCallArgument& a) -> poly::ArgType {\n\t\t\t\t\treturn ArgType(a.name, a.value->type, a.loc, /* opt: */ false, /* ignoreName: */ a.ignoreName);\n\t\t\t\t});\n\n\t\t\t\tif(return_infer)\n\t\t\t\t\tgiven.push_back(ArgType(\"<return_type>\", return_infer, Location()));\n\n\t\t\t\t*origParamOrder = resolver::misc::getNameIndexMap(params);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif(type_infer == 0)\n\t\t\t\t\treturn { soln, nullptr };\n\n\t\t\t\telse if(!type_infer->isFunctionType())\n\t\t\t\t\treturn { soln, SimpleError::make(fs->loc(), \"invalid type '%s' inferred for '%s'\", type_infer, thing->name) };\n\n\t\t\t\t// ok, we should have it.\n\t\t\t\ticeAssert(type_infer->isFunctionType());\n\t\t\t\tgiven = zfu::mapIdx(type_infer->toFunctionType()->getArgumentTypes(), [&params](fir::Type* t, size_t i) -> ArgType {\n\t\t\t\t\treturn ArgType(params[i].name, t, params[i].loc);\n\t\t\t\t}) + ArgType(\"<return_type>\", type_infer->toFunctionType()->getReturnType(), thing->loc);\n\t\t\t}\n\n\t\t\treturn solveTypeList(fs->loc(), target, given, soln, isFnCall);\n\t\t}\n\n\n\n\n\n\n\t\tstd::pair<Solution_t, ErrorMsg*> inferTypesForPolymorph(TypecheckState* fs, ast::Parameterisable* thing, const std::string& name,\n\t\t\tconst ProblemSpace_t& problems, const std::vector<FnCallArgument>& input,\n\t\t\tconst TypeParamMap_t& partial, fir::Type* return_infer, fir::Type* type_infer, bool isFnCall,\n\t\t\tfir::Type* problem_infer, util::hash_map<std::string, size_t>* origParamOrder)\n\t\t{\n\t\t\tif(auto td = dcast(ast::TypeDefn, thing))\n\t\t\t{\n\t\t\t\treturn inferPolymorphicType(fs, td, name, problems, input, partial, return_infer, type_infer, isFnCall, problem_infer, origParamOrder);\n\t\t\t}\n\t\t\telse if(dcast(ast::FuncDefn, thing) || dcast(ast::InitFunctionDefn, thing))\n\t\t\t{\n\t\t\t\treturn inferPolymorphicFunction(fs, thing, name, problems, input, partial, return_infer, type_infer, isFnCall, problem_infer, origParamOrder);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ticeAssert(thing);\n\t\t\t\treturn std::make_pair(Solution_t(partial),\n\t\t\t\t\tSimpleError::make(thing->loc, \"unable to infer type for unsupported entity '%s'\", thing->getKind())\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/polymorph/instantiator.cpp",
    "content": "// instantiator.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"sst.h\"\n#include \"ir/type.h\"\n\n#include \"typecheck.h\"\n#include \"polymorph.h\"\n#include \"resolver.h\"\n\nnamespace sst {\nnamespace poly\n{\n\tnamespace internal\n\t{\n\t\tstatic SimpleError* complainAboutMissingSolutions(const Location& l, ast::Parameterisable* thing,\n\t\t\tconst std::vector<fir::PolyPlaceholderType*>& missing)\n\t\t{\n\t\t\tauto strs = zfu::map(missing, [](fir::PolyPlaceholderType* p) -> std::string {\n\t\t\t\treturn p->str().substr(1);\n\t\t\t});\n\n\t\t\tauto mstr = util::listToEnglish(strs);\n\t\t\treturn SimpleError::make(l, \"type %s %s could not be inferred\", zfu::plural(\"parameter\", strs.size()), mstr);\n\t\t}\n\n\t\tstd::vector<std::string> getMissingSolutions(const ProblemSpace_t& needed, const TypeParamMap_t& solution,\n\t\t\tbool allowPlaceholders)\n\t\t{\n\t\t\tstd::vector<std::string> missing;\n\t\t\tfor(const auto& [ name, constr ] : needed)\n\t\t\t{\n\t\t\t\t(void) constr;\n\n\t\t\t\tif(auto it = solution.find(name); it == solution.end())\n\t\t\t\t\tmissing.push_back(name);\n\n\t\t\t\telse if(!allowPlaceholders && it->second->containsPlaceholders())\n\t\t\t\t\tmissing.push_back(name);\n\t\t\t}\n\n\t\t\treturn missing;\n\t\t}\n\n\n\t\tstd::pair<TCResult, Solution_t> solvePolymorphWithPlaceholders(TypecheckState* fs, ast::Parameterisable* thing, const std::string& name,\n\t\t\tconst TypeParamMap_t& partial)\n\t\t{\n\t\t\tTypeParamMap_t copy = partial;\n\n\t\t\tint session = getNextSessionId();\n\t\t\tfor(const auto& p : thing->generics)\n\t\t\t{\n\t\t\t\tif(copy.find(p.first) == copy.end())\n\t\t\t\t\tcopy[p.first] = fir::PolyPlaceholderType::get(p.first, session);\n\t\t\t}\n\n\t\t\treturn attemptToInstantiatePolymorph(fs, thing, name, copy, /* return_infer: */ 0, /* type_infer: */ 0,\n\t\t\t\t/* isFnCall: */ false, /* args: */ { }, /* fillplaceholders: */ false);\n\t\t}\n\t}\n\n\n\n\n\n\n\tstd::pair<TCResult, Solution_t> attemptToInstantiatePolymorph(TypecheckState* fs, ast::Parameterisable* thing, const std::string& name,\n\t\tconst TypeParamMap_t& _gmaps, fir::Type* return_infer, fir::Type* type_infer, bool isFnCall, std::vector<FnCallArgument>* args,\n\t\tbool fillplaceholders, fir::Type* problem_infer)\n\t{\n\t\tif(!isFnCall && type_infer == 0 && fillplaceholders)\n\t\t\treturn internal::solvePolymorphWithPlaceholders(fs, thing, name, _gmaps);\n\n\t\t// used below.\n\t\tutil::hash_map<std::string, size_t> origParamOrder;\n\t\tauto [ soln, err ] = internal::inferTypesForPolymorph(fs, thing, name, thing->generics, *args, _gmaps, return_infer, type_infer, isFnCall,\n\t\t\tproblem_infer, &origParamOrder);\n\n\t\tif(err) return { TCResult(err), soln };\n\n\t\tif(auto d = fullyInstantiatePolymorph(fs, thing, soln.solutions); d.isDefn())\n\t\t{\n\t\t\tif(isFnCall)\n\t\t\t{\n\t\t\t\t// if(auto missing = internal::getMissingSolutions(thing->generics, soln.solutions, /* allowPlaceholders: */ false); missing.size() > 0)\n\t\t\t\tif(auto missing = d.defn()->type->getContainedPlaceholders(); missing.size() > 0)\n\t\t\t\t{\n\t\t\t\t\tauto se = SpanError::make(internal::complainAboutMissingSolutions(thing->loc, thing, missing));\n\n\t\t\t\t\treturn std::make_pair(\n\t\t\t\t\t\tTCResult(err->append(se)->append(SimpleError::make(fs->loc(), \"partial solution: %s\",\n\t\t\t\t\t\t\tzfu::listToString(zfu::map(soln.solutions, [](const std::pair<std::string, fir::Type*>& p) -> std::string {\n\t\t\t\t\t\t\t\treturn strprintf(\"%s = %s\", p.first, p.second);\n\t\t\t\t\t\t\t}), [](const std::string& s) -> std::string {\n\t\t\t\t\t\t\t\treturn s;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t)))), soln\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tsize_t counter = 0;\n\t\t\t\t\tfor(auto& arg : *args)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(arg.value->type->containsPlaceholders() && arg.orig)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//! ACHTUNG !\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t* note *\n\t\t\t\t\t\t\t\tthe implication here is that by calling 'inferTypesForPolymorph', which itself calls 'solveTypeList',\n\t\t\t\t\t\t\t\twe will have weeded out all of the function candidates that don't match (ie. overload distance == -1)\n\n\t\t\t\t\t\t\t\ttherefore, we can operate under the assumption that the _parameter_ type of the function will be fully\n\t\t\t\t\t\t\t\tsubstituted and not have any placeholders, and that it will be a valid infer target for the _argument_.\n\n\t\t\t\t\t\t\t\tusing the newly-gained arg_infer information, we can re-typecheck the argument with concrete types.\n\n\t\t\t\t\t\t\t\t- zhiayang\n\t\t\t\t\t\t\t\t- 06/10/18/2318\n\t\t\t\t\t\t\t*/\n\n\t\t\t\t\t\t\tauto arg_infer = d.defn()->type->toFunctionType()->getArgumentN(arg.name.empty() ? counter : origParamOrder[arg.name]);\n\n\t\t\t\t\t\t\tauto tc = arg.orig->typecheck(fs, arg_infer);\n\t\t\t\t\t\t\targ.value = tc.expr();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcounter += 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn std::make_pair(TCResult(d.defn()), soln);\n\t\t}\n\t\telse\n\t\t{\n\t\t\ticeAssert(d.isError());\n\t\t\treturn std::make_pair(TCResult(d.error()), soln);\n\t\t}\n\t}\n\n\n\n\n\n\n\t//* gets an generic type in the AST form and returns a concrete SST node from it, given the mappings.\n\tTCResult fullyInstantiatePolymorph(TypecheckState* fs, ast::Parameterisable* thing, const TypeParamMap_t& mappings)\n\t{\n\t\ticeAssert(thing);\n\t\t// iceAssert(!thing->generics.empty());\n\n\t\t// try to see if we already have a generic version.\n\t\tif(auto [ found, def ] = thing->checkForExistingDeclaration(fs, mappings); found && def)\n\t\t\treturn TCResult(def);\n\n\n\t\tfs->pushGenericContext();\n\t\tdefer(fs->popGenericContext());\n\n\t\tfor(auto map : mappings)\n\t\t{\n\t\t\tint ptrs = 0;\n\t\t\t{\n\t\t\t\tauto t = map.second;\n\n\t\t\t\twhile(t->isPointerType())\n\t\t\t\t\tt = t->getPointerElementType(), ptrs++;\n\t\t\t}\n\n\t\t\tif(auto it = std::find_if(thing->generics.begin(), thing->generics.end(), [&map](const auto& p) -> bool {\n\t\t\t\treturn map.first == p.first;\n\t\t\t}); it != thing->generics.end() && ptrs < it->second.pointerDegree)\n\t\t\t{\n\t\t\t\treturn TCResult(\n\t\t\t\t\tSimpleError::make(fs->loc(), \"cannot map type '%s' to type parameter '%s' in instantiation of generic type '%s'\",\n\t\t\t\t\t\tmap.second, map.first, thing->name)->append(\n\t\t\t\t\t\t\tSimpleError::make(MsgType::Note, thing->loc,\n\t\t\t\t\t\t\t\t\"replacement type has pointer degree %d, which is less than the required %d\", ptrs, it->second.pointerDegree)\n\t\t\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// TODO: check if the type conforms to the protocols specified.\n\t\t\t//* check if it satisfies the protocols.\n\n\t\t\t// ok, push the thing.\n\t\t\tfs->addGenericMapping(map.first, map.second);\n\t\t}\n\n\t\tfir::Type* self_infer = 0;\n\t\tif(thing->parentType)\n\t\t{\n\t\t\t// instantiate that as well, I guess.\n\t\t\tauto res = fullyInstantiatePolymorph(fs, thing->parentType, /* mappings */ {});\n\t\t\tif(res.isError()) return TCResult(res);\n\n\t\t\tself_infer = res.defn()->type;\n\t\t}\n\n\t\tif(auto missing = internal::getMissingSolutions(thing->generics, mappings, true); missing.size() > 0)\n\t\t{\n\t\t\tauto mstr = util::listToEnglish(missing);\n\t\t\treturn TCResult(SimpleError::make(fs->loc(), \"type %s %s could not be inferred\",\n\t\t\t\tzfu::plural(\"parameter\", missing.size()), mstr));\n\t\t}\n\n\t\treturn thing->typecheck(fs, self_infer, mappings);\n\t}\n}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/polymorph/misc.cpp",
    "content": "// misc.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"pts.h\"\n#include \"ast.h\"\n#include \"ir/type.h\"\n#include \"typecheck.h\"\n\n#include \"errors.h\"\n#include \"polymorph.h\"\n\nnamespace sst\n{\n\tnamespace poly\n\t{\n\t\tnamespace internal\n\t\t{\n\t\t\tstatic int polySessionId = 0;\n\t\t\tint getNextSessionId()\n\t\t\t{\n\t\t\t\treturn polySessionId++;\n\t\t\t}\n\n\t\t\tfir::Type* mergeNumberTypes(fir::Type* a, fir::Type* b)\n\t\t\t{\n\t\t\t\tif(a->isConstantNumberType() && b->isConstantNumberType())\n\t\t\t\t{\n\t\t\t\t\treturn fir::unifyConstantTypes(a->toConstantNumberType(), b->toConstantNumberType());\n\t\t\t\t}\n\t\t\t\telse if(a->isFloatingPointType() && b->isIntegerType())\n\t\t\t\t{\n\t\t\t\t\treturn a;\n\t\t\t\t}\n\t\t\t\telse if(a->isIntegerType() && b->isFloatingPointType())\n\t\t\t\t{\n\t\t\t\t\treturn b;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif(a->getBitWidth() > b->getBitWidth())\n\t\t\t\t\t\treturn a;\n\n\t\t\t\t\telse\n\t\t\t\t\t\treturn b;\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\tfir::Type* convertPtsType(TypecheckState* fs, const ProblemSpace_t& problems, pts::Type* input, int polysession)\n\t\t\t{\n\t\t\t\tfir::Type* fty = 0;\n\t\t\t\tauto [ _ty, trfs ] = decomposeIntoTransforms(input);\n\t\t\t\tpts::Type* ty = _ty;\n\n\t\t\t\tif(ty->isNamedType())\n\t\t\t\t{\n\t\t\t\t\tfty = fs->convertParserTypeToFIR(ty, true);\n\t\t\t\t\tif(!fty && (std::find_if(problems.begin(), problems.end(), [ty](const auto& a) -> bool {\n\t\t\t\t\t\t\treturn ty->toNamedType()->name == a.first;\n\t\t\t\t\t\t}) != problems.end()))\n\t\t\t\t\t{\n\t\t\t\t\t\tfty = fir::PolyPlaceholderType::get(ty->toNamedType()->name, polysession);\n\t\t\t\t\t}\n\n\t\t\t\t\tif(!fty) error(\"failed to find type '%s'\", input->str());\n\t\t\t\t}\n\t\t\t\telse if(ty->isTupleType())\n\t\t\t\t{\n\t\t\t\t\tfty = fir::TupleType::get(convertPtsTypeList(fs, problems, ty->toTupleType()->types, polysession));\n\t\t\t\t}\n\t\t\t\telse if(ty->isFunctionType())\n\t\t\t\t{\n\t\t\t\t\tfty = fir::FunctionType::get(convertPtsTypeList(fs, problems, ty->toFunctionType()->argTypes, polysession),\n\t\t\t\t\t\tconvertPtsType(fs, problems, ty->toFunctionType()->returnType, polysession));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\terror(\"unsupported pts type '%s'\", ty->str());\n\t\t\t\t}\n\n\t\t\t\treturn applyTransforms(fty, trfs);\n\t\t\t}\n\n\t\t\tstd::vector<fir::Type*> convertPtsTypeList(TypecheckState* fs, const ProblemSpace_t& problems, const std::vector<pts::Type*>& input,\n\t\t\t\tint polysession)\n\t\t\t{\n\t\t\t\t// mm, smells functional.\n\t\t\t\treturn zfu::map(input, [fs, problems, polysession](pts::Type* pt) -> fir::Type* {\n\t\t\t\t\treturn convertPtsType(fs, problems, pt, polysession);\n\t\t\t\t});\n\t\t\t}\n\n\n\n\t\t\tstd::vector<ArgType> unwrapFunctionParameters(TypecheckState* fs, const ProblemSpace_t& problems,\n\t\t\t\tconst std::vector<ast::FuncDefn::Param>& args, int polysession)\n\t\t\t{\n\t\t\t\treturn zfu::mapIdx(convertPtsTypeList(fs, problems, zfu::map(args,\n\t\t\t\t\t[](const ast::FuncDefn::Param& a) -> pts::Type* {\n\t\t\t\t\t\treturn a.type;\n\t\t\t\t\t}\n\t\t\t\t), polysession), [args](fir::Type* t, size_t idx) -> ArgType {\n\t\t\t\t\treturn ArgType(args[idx].name, t, args[idx].loc);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\n\n\n\n\tstd::vector<TypeParamMap_t> TypecheckState::getGenericContextStack()\n\t{\n\t\treturn this->genericContextStack;\n\t}\n\n\tvoid TypecheckState::pushGenericContext()\n\t{\n\t\tthis->genericContextStack.push_back({ });\n\t}\n\n\tvoid TypecheckState::addGenericMapping(const std::string& name, fir::Type* ty)\n\t{\n\t\ticeAssert(this->genericContextStack.size() > 0);\n\t\tif(auto it = this->genericContextStack.back().find(name); it != this->genericContextStack.back().end())\n\t\t\terror(this->loc(), \"mapping for type parameter '%s' already exists in current context (is currently '%s')\", name, it->second);\n\n\t\tthis->genericContextStack.back()[name] = ty;\n\t}\n\n\tvoid TypecheckState::removeGenericMapping(const std::string& name)\n\t{\n\t\ticeAssert(this->genericContextStack.size() > 0);\n\t\tif(auto it = this->genericContextStack.back().find(name); it == this->genericContextStack.back().end())\n\t\t\terror(this->loc(), \"no mapping for type parameter '%s' exists in current context, cannot remove\", name);\n\n\t\telse\n\t\t\tthis->genericContextStack.back().erase(it);\n\t}\n\n\tvoid TypecheckState::popGenericContext()\n\t{\n\t\ticeAssert(this->genericContextStack.size() > 0);\n\t\tthis->genericContextStack.pop_back();\n\t}\n\n\n\tfir::Type* TypecheckState::findGenericMapping(const std::string& name, bool allowFail)\n\t{\n\t\t// look upwards.\n\t\tfor(auto it = this->genericContextStack.rbegin(); it != this->genericContextStack.rend(); it++)\n\t\t\tif(auto iit = it->find(name); iit != it->end())\n\t\t\t\treturn iit->second;\n\n\t\tif(allowFail)   return 0;\n\t\telse            error(this->loc(), \"no mapping for type parameter '%s'\", name);\n\t}\n}\n\n\n//* helper method that abstracts away the common error-checking\nstd::pair<bool, sst::Defn*> ast::Parameterisable::checkForExistingDeclaration(sst::TypecheckState* fs, const TypeParamMap_t& gmaps)\n{\n\t//! ACHTUNG !\n\t//* IMPORTANT *\n\t/*\n\t\t? the reason we match the *ENTIRE* generic context stack when checking for an existing definition is because of nesting.\n\t\t* if we only checked the current map, then for methods of generic types and/or nested, non-generic types inside generic types,\n\t\t* we'd match an existing definition even though all the generic types are probably completely different.\n\n\t\t* so, pretty much the only way to make sure we're absolutely certain it's the same context is to compare the entire type stack.\n\n\t\t? given that a given definition cannot 'move' to another scope, there cannot be circumstances where we can (by chance or otherwise)\n\t\t? be typechecking the current definition in another, completely different context, and somehow mistake it for our own -- even if all\n\t\t? the generic types match in the stack.\n\n\t\t* note: bug fix: what we should really be checking for is that the stored generic map is a strict child (ie. the last N elements match\n\t\t* our stored state, while the preceding ones don't matter). (this is why we use reverse iterators for std::equal)\n\n\t\t* note: bug fix of the bug fix: we should be checking whether our current state is a child of the stored state, instead of the\n\t\t* other way around. probably.\n\t*/\n\n\t{\n\t\tauto doRootsMatch = [](const std::vector<TypeParamMap_t>& expected, const std::vector<TypeParamMap_t>& given) -> bool {\n\t\t\tif(given.size() > expected.size())\n\t\t\t\treturn false;\n\n\t\t\t//* reverse iterators\n\t\t\treturn std::equal(given.rbegin(), given.rend(), expected.rbegin());\n\t\t};\n\n\t\tauto currentGCS = fs->getGenericContextStack();\n\t\tif(!gmaps.empty())\n\t\t\tcurrentGCS.push_back(gmaps);\n\n\t\tfor(const auto& gv : this->genericVersions)\n\t\t{\n\t\t\t//* note!! Defn::type can be null for enums -- we need to find a way to prevent this!!\n\t\t\t// TODO: prevent this!!\n\t\t\t// TODO: prevent this!!\n\t\t\t// TODO: prevent this!!\n\t\t\t// TODO: prevent this!!\n\t\t\tif(gv.first->type && !gv.first->type->containsPlaceholders() && doRootsMatch(gv.second, currentGCS))\n\t\t\t\treturn { true, gv.first };\n\t\t}\n\n\n\t\tif(this->generics.size() > 0 && gmaps.empty())\n\t\t{\n\t\t\tif(const auto& tys = fs->stree->unresolvedGenericDefs[this->name]; std::find(tys.begin(), tys.end(), this) == tys.end())\n\t\t\t\tfs->stree->unresolvedGenericDefs[this->name].push_back(this);\n\n\t\t\treturn { false, 0 };\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//? note: if we call with an empty map, then this is just a non-generic type/function/thing. Even for such things,\n\t\t\t//? the genericVersions list will have 1 entry which is just the type itself.\n\t\t\treturn { true, 0 };\n\t\t}\n\t}\n}\n\n\nstd::string PolyArgMapping_t::print() const\n{\n\tstd::string ret;\n\tfor(const auto& m : this->maps)\n\t{\n\t\tret += \", \";\n\t\tif(!m.name.empty())\n\t\t\tret += strprintf(\"%s: \", m.name);\n\n\t\tret += m.type->str();\n\t}\n\n\tif(!ret.empty())\n\t\tret = ret.erase(0, 2);\n\n\treturn ret;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/polymorph/solver.cpp",
    "content": "// solver.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"pts.h\"\n#include \"ast.h\"\n#include \"sst.h\"\n#include \"errors.h\"\n#include \"ir/type.h\"\n#include \"typecheck.h\"\n\n#include \"polymorph.h\"\n\n\nnamespace sst\n{\n\tnamespace poly\n\t{\n\t\tstatic ErrorMsg* solveSingleTypeList(Solution_t* soln, const Location& callLoc, const std::vector<ArgType>& target,\n\t\t\tconst std::vector<ArgType>& given, bool isFnCall);\n\n\t\tstatic ErrorMsg* solveSingleType(Solution_t* soln, const fir::LocatedType& target, const fir::LocatedType& given)\n\t\t{\n\t\t\tauto tgt = target.type;\n\t\t\tauto gvn = given.type;\n\n\t\t\t// if we're just looking at normal types, then just add the cost.\n\t\t\tif(!tgt->containsPlaceholders() && !gvn->containsPlaceholders())\n\t\t\t{\n\t\t\t\tint dist = fir::getCastDistance(gvn, tgt);\n\t\t\t\tif(dist >= 0)\n\t\t\t\t{\n\t\t\t\t\tsoln->distance += dist;\n\t\t\t\t\treturn nullptr;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tsoln->distance = -1;\n\t\t\t\t\treturn SimpleError::make(given.loc, \"no valid cast from given type '%s' to target type '%s'\", gvn, tgt);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// limit decomposition of the given types by the number of transforms on the target type.\n\t\t\t\tauto [ tt, ttrfs ] = internal::decomposeIntoTransforms(tgt, static_cast<size_t>(-1));\n\t\t\t\tauto [ gt, gtrfs ] = internal::decomposeIntoTransforms(gvn, ttrfs.size());\n\n\t\t\t\t// if(ttrfs != gtrfs)\n\t\t\t\t// hmm???\n\n\t\t\t\t// substitute if possible.\n\t\t\t\tif(auto _gt = soln->substitute(gt); _gt != gt)\n\t\t\t\t\tgt = _gt;\n\n\t\t\t\t// check what kind of monster we're dealing with.\n\t\t\t\tif(tt->isPolyPlaceholderType())\n\t\t\t\t{\n\t\t\t\t\t// see if there's a match.\n\t\t\t\t\tauto ptt = tt->toPolyPlaceholderType();\n\t\t\t\t\tif(auto ltt = soln->getSolution(ptt->getName()); ltt != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t// check for conflict.\n\t\t\t\t\t\tif(!ltt->isPolyPlaceholderType() && !gt->isPolyPlaceholderType())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif(ltt->isConstantNumberType() || gt->isConstantNumberType())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tgt = internal::mergeNumberTypes(ltt, gt);\n\t\t\t\t\t\t\t\tif(gt != ltt)\n\t\t\t\t\t\t\t\t\tsoln->addSolution(ptt->getName(), fir::LocatedType(gt, given.loc));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if(ltt != gt)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif(int d = fir::getCastDistance(gt, ltt); d >= 0)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tsoln->distance += d;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\treturn SimpleError::make(given.loc, \"conflicting solutions for type parameter '%s': previous: '%s', current: '%s'\",\n\t\t\t\t\t\t\t\t\t\tptt->getName(), ltt->str(), gvn);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(ltt->isPolyPlaceholderType() && !gt->isPolyPlaceholderType())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsoln->addSubstitution(ltt, gt);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(!ltt->isPolyPlaceholderType() && gt->isPolyPlaceholderType())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsoln->addSubstitution(gt, ltt);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(ltt->isPolyPlaceholderType() && gt->isPolyPlaceholderType())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\twarn(\"what???? '%s' and '%s' are both poly??\", ltt->str(), gt);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// debuglogln(\"solved %s = %s\", ptt->getName(), gt);\n\t\t\t\t\t\tsoln->addSolution(ptt->getName(), fir::LocatedType(gt, given.loc));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(tt->isFunctionType() || tt->isTupleType())\n\t\t\t\t{\n\t\t\t\t\t// make sure they're the same 'kind' of type first.\n\t\t\t\t\tif(tt->isFunctionType() != gt->isFunctionType() || tt->isTupleType() != gt->isTupleType())\n\t\t\t\t\t\treturn SimpleError::make(given.loc, \"no valid conversion from given type '%s' to target type '%s'\", gt, tt);\n\n\t\t\t\t\tstd::vector<ArgType> problem;\n\t\t\t\t\tstd::vector<ArgType> input;\n\t\t\t\t\tif(gt->isFunctionType())\n\t\t\t\t\t{\n\t\t\t\t\t\tinput = zfu::map(gt->toFunctionType()->getArgumentTypes(), [given](fir::Type* t) -> ArgType {\n\t\t\t\t\t\t\treturn ArgType(\"\", t, given.loc);\n\t\t\t\t\t\t}) + ArgType(\"\", gt->toFunctionType()->getReturnType(), given.loc);\n\n\t\t\t\t\t\tproblem = zfu::map(tt->toFunctionType()->getArgumentTypes(), [target](fir::Type* t) -> ArgType {\n\t\t\t\t\t\t\treturn ArgType(\"\", t, target.loc);\n\t\t\t\t\t\t}) + ArgType(\"\", tt->toFunctionType()->getReturnType(), target.loc);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\ticeAssert(gt->isTupleType());\n\t\t\t\t\t\tinput = zfu::map(gt->toTupleType()->getElements(), [given](fir::Type* t) -> ArgType {\n\t\t\t\t\t\t\treturn ArgType(\"\", t, given.loc);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tproblem = zfu::map(tt->toTupleType()->getElements(), [target](fir::Type* t) -> ArgType {\n\t\t\t\t\t\t\treturn ArgType(\"\", t, target.loc);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\t// for recursive solving, we're never a function call.\n\t\t\t\t\t// related: so, firstOptionalArgument is always -1 in these cases.\n\t\t\t\t\treturn solveSingleTypeList(soln, given.loc, problem, input, /* isFnCall: */ false);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\terror(\"'%s' not supported\", tt);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn nullptr;\n\t\t}\n\n\n\n\t\tstatic ErrorMsg* solveSingleTypeList(Solution_t* soln, const Location& callLoc, const std::vector<ArgType>& target,\n\t\t\tconst std::vector<ArgType>& given, bool isFnCall)\n\t\t{\n\t\t\tbool fvararg = (isFnCall && target.size() > 0 && target.back()->isVariadicArrayType());\n\n\t\t\tutil::hash_map<std::string, size_t> targetnames;\n\n\t\t\t// either we have all names or no names for the target!\n\t\t\tif(target.size() > 0 && target[0].name != \"\")\n\t\t\t{\n\t\t\t\tzfu::foreachIdx(target, [&targetnames](const ArgType& t, size_t i) {\n\t\t\t\t\ttargetnames[t.name] = i;\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tstd::set<size_t> unsolvedtargets;\n\t\t\tzfu::foreachIdx(target, [&unsolvedtargets, &target, fvararg](const ArgType& a, size_t i) {\n\t\t\t\t// if it's optional, we don't mark it as 'unsolved'.\n\t\t\t\tif((!fvararg || i + 1 != target.size()) && !a.optional)\n\t\t\t\t\tunsolvedtargets.insert(i);\n\t\t\t});\n\n\t\t\t// record which optionals we passed, for a better error message.\n\t\t\tstd::set<std::string> providedOptionals;\n\n\n\t\t\tsize_t last_arg = std::min(target.size() + (fvararg ? -1 : 0), given.size());\n\n\t\t\t// we used to do this check in the parser, but to support more edge cases (like passing varargs)\n\t\t\t// we moved it here so we can actually check stuff.\n\t\t\tbool didNames = false;\n\n\t\t\tsize_t positionalCounter = 0;\n\t\t\tsize_t varArgStart = last_arg;\n\t\t\tfor(size_t i = 0; i < last_arg; i++)\n\t\t\t{\n\t\t\t\tconst ArgType* targ = 0;\n\n\t\t\t\t// note that when we call std::set::erase(), if the key did not exist (because it was optional),\n\t\t\t\t// nothing will happen, which is fine.\n\t\t\t\tif(targetnames.size() > 0 && given[i].name != \"\")\n\t\t\t\t{\n\t\t\t\t\tif(auto it = targetnames.find(given[i].name); it != targetnames.end())\n\t\t\t\t\t{\n\t\t\t\t\t\ttarg = &target[it->second];\n\t\t\t\t\t\tunsolvedtargets.erase(it->second);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\treturn SimpleError::make(given[i].loc, \"function has no parameter named '%s'\", given[i].name);\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t\toptional arguments \"don't count\" as passing by name. this means that you can do this, for example:\n\n\t\t\t\t\t\tfoo(x: 30, \"blabla\")\n\n\t\t\t\t\t\twhere 'x' is an optional argument. this should be fine in terms of the rest of the compiler, because when\n\t\t\t\t\t\twe *declare* the function, all optional arguments must come last. this gives us a good compromise because\n\t\t\t\t\t\toptional arguments must still be passed by name, but we can actually have optional arguments together with\n\t\t\t\t\t\tvariadic functions without needing to name all the arguments.\n\t\t\t\t\t*/\n\n\t\t\t\t\tif(!targ->optional)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!given[i].ignoreName)\n\t\t\t\t\t\t\tdidNames = true;\n\n\t\t\t\t\t\tpositionalCounter++;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tprovidedOptionals.insert(given[i].name);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t/*\n\t\t\t\t\t\twe didn't pass a name. if the function is variadic, we might have wanted to pass the following argument(s)\n\t\t\t\t\t\tvariadically. so, instead of assuming we made a mistake (like not passing the optional by name), assume we\n\t\t\t\t\t\twanted to pass it to the vararg.\n\n\t\t\t\t\t\tso, `positionalCounter` counts the paramters on the declaration-side. thus, once we encounter a default value,\n\t\t\t\t\t\tit must mean that the rest of the parameters will be optional as well.\n\n\t\t\t\t\t\t* ie. we've passed all the positional arguments already, leaving the optional ones, which means every argument from\n\t\t\t\t\t\t* here onwards (including this one) must be named. since this is *not* named, we just skip straight to the varargs if\n\t\t\t\t\t\t* it was present.\n\t\t\t\t\t*/\n\n\t\t\t\t\ttarg = &target[positionalCounter];\n\n\t\t\t\t\tif(fvararg && targ->optional)\n\t\t\t\t\t{\n\t\t\t\t\t\tvarArgStart = i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tunsolvedtargets.erase(positionalCounter);\n\t\t\t\t\tpositionalCounter++;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t\tTODO: not sure if there's a way to get around this, but if we have a function like this:\n\n\t\t\t\t\tfn foo(a: int, b: int, c: int, x: int = 9, y: int = 8, z: int = 7) { ... }\n\n\t\t\t\t\tthen calling it wrongly like this: foo(x: 4, 1, 2, 5, z: 6, 3)\n\n\t\t\t\t\tresults in an error at the last argument ('3') saying taht optional argument 'x' must be passed by name.\n\t\t\t\t\tthe problem is that we can't really tell what argument you wanted to pass; after seeing '1', '2', and '5',\n\t\t\t\t\tthe positionalCounter now points to the 4th argument, 'x'.\n\n\t\t\t\t\teven though you already passed x prior, we don't really know that? and we assume you wanted to pass x (again)\n\t\t\t\t*/\n\n\t\t\t\tif(given[i].name.empty())\n\t\t\t\t{\n\t\t\t\t\tif(didNames)\n\t\t\t\t\t\treturn SimpleError::make(given[i].loc, \"positional arguments cannot appear after named arguments\");\n\n\t\t\t\t\telse if(targ->optional)\n\t\t\t\t\t{\n\t\t\t\t\t\tstd::string probablyIntendedArgumentName;\n\t\t\t\t\t\tfor(const auto& a : target)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif(!a.optional)\n\t\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\t\tif(auto it = providedOptionals.find(a.name); it == providedOptionals.end())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tprobablyIntendedArgumentName = a.name;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tif(probablyIntendedArgumentName.empty())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//* this shouldn't happen, because we only get here if we're not variadic, but if we weren't\n\t\t\t\t\t\t\t//* variadic, then we would've errored out if the argument count was wrong to begin with.\n\t\t\t\t\t\t\treturn SimpleError::make(given[i].loc, \"extraneous argument without corresponding parameter\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn SimpleError::make(given[i].loc, \"optional argument '%s' must be passed by name\",\n\t\t\t\t\t\t\t\tprobablyIntendedArgumentName);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\ticeAssert(targ);\n\t\t\t\tauto err = solveSingleType(soln, targ->toFLT(), given[i].toFLT());\n\t\t\t\tif(err != nullptr) return err;\n\n\t\t\t\t// possibly increase solution completion by re-substituting with new information\n\t\t\t\tsoln->resubstituteIntoSolutions();\n\t\t\t}\n\n\t\t\tif(unsolvedtargets.size() > 0 || (!fvararg && given.size() > target.size()))\n\t\t\t{\n\t\t\t\tif(targetnames.empty() || given.size() > target.size())\n\t\t\t\t{\n\t\t\t\t\treturn SimpleError::make(callLoc, \"expected %d %s, but %d %s provided\",\n\t\t\t\t\t\ttarget.size(), zfu::plural(\"argument\", target.size()), given.size(), given.size() == 1 ? \"was\" : \"were\");\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tstd::vector<std::string> missings;\n\t\t\t\t\tfor(const auto& us : unsolvedtargets)\n\t\t\t\t\t\tmissings.push_back(target[us].name);\n\n\t\t\t\t\tauto s = util::listToEnglish(missings, /* quote: */ true);\n\t\t\t\t\treturn SimpleError::make(callLoc, \"missing %s for %s %s\", zfu::plural(\"argument\", missings.size()),\n\t\t\t\t\t\tzfu::plural(\"parameter\", missings.size()), s);\n\t\t\t\t}\n\t\t\t}\n\n\n\n\t\t\t// solve the variadic part.\n\t\t\tif(fvararg)\n\t\t\t{\n\t\t\t\t// check for forwarding first.\n\t\t\t\tif(given.size() == target.size() && given.back()->isVariadicArrayType())\n\t\t\t\t{\n\t\t\t\t\tauto copy = *soln;\n\n\t\t\t\t\t// ok, if we fulfil all the conditions to forward, then we forward.\n\t\t\t\t\tauto err = solveSingleType(&copy, target.back().toFLT(), given.back().toFLT());\n\t\t\t\t\tif(err == nullptr)\n\t\t\t\t\t{\n\t\t\t\t\t\ticeAssert(copy.distance >= 0);\n\t\t\t\t\t\t*soln = copy;\n\n\t\t\t\t\t\t// ok, things should be solved, and we will forward.\n\t\t\t\t\t\treturn nullptr;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t//* note: the reason we put this outside an 'else' is so that, in the event we're unable to solve\n\t\t\t\t//* for the forwarding case for whatever reason, we will treat it as an argument-passing case.\n\n\t\t\t\t// get the supposed type of the thing.\n\t\t\t\tauto varty = target.back()->toArraySliceType()->getArrayElementType();\n\t\t\t\tauto ltvarty = fir::LocatedType(varty, target.back().loc);\n\n\t\t\t\tfor(size_t i = varArgStart; i < given.size(); i++)\n\t\t\t\t{\n\t\t\t\t\tauto err = solveSingleType(soln, ltvarty, given[i].toFLT());\n\t\t\t\t\tif(err) return err->append(SimpleError::make(MsgType::Note, target.back().loc, \"in argument of variadic parameter\"));\n\t\t\t\t}\n\n\t\t\t\t// ok, everything should be good??\n\t\t\t\treturn nullptr;\n\t\t\t}\n\n\t\t\treturn nullptr;\n\t\t}\n\n\n\n\n\n\n\n\n\t\tstd::pair<Solution_t, ErrorMsg*> solveTypeList(const Location& callLoc, const std::vector<ArgType>& target,\n\t\t\tconst std::vector<ArgType>& given, const Solution_t& partial, bool isFnCall)\n\t\t{\n\t\t\tSolution_t prevSoln = partial;\n\n\t\t\tstd::vector<fir::PolyPlaceholderType*> tosolve;\n\t\t\tfor(auto t : target)\n\t\t\t\ttosolve = tosolve + t->getContainedPlaceholders();\n\n\t\t\tauto checkFinished = [&tosolve](const Solution_t& soln) -> bool {\n\t\t\t\tfor(auto t : tosolve)\n\t\t\t\t{\n\t\t\t\t\tif(!soln.hasSolution(t->getName()))\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t};\n\n\t\t\twhile(true)\n\t\t\t{\n\t\t\t\t//* note!! we reset the distance here, because we will always loop through every argument.\n\t\t\t\t//* if we didn't reset the distance, it would just keep increasing to infinity (and overflow)\n\t\t\t\tauto soln = prevSoln; soln.distance = 0;\n\n\t\t\t\tauto errs = solveSingleTypeList(&soln, callLoc, target, given, isFnCall);\n\t\t\t\tif(errs) return { soln, errs };\n\n\t\t\t\tif(soln == prevSoln)            { break; }\n\t\t\t\telse if(checkFinished(soln))    { prevSoln = soln; break; }\n\t\t\t\telse                            { prevSoln = soln; }\n\t\t\t}\n\n\n\t\t\tfor(auto& pair : prevSoln.solutions)\n\t\t\t{\n\t\t\t\tif(pair.second->isConstantNumberType())\n\t\t\t\t\tpair.second = fir::getBestFitTypeForConstant(pair.second->toConstantNumberType());\n\t\t\t}\n\n\t\t\treturn { prevSoln, nullptr };\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/polymorph/transforms.cpp",
    "content": "// transforms.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"pts.h\"\n#include \"ir/type.h\"\n\n#include \"errors.h\"\n#include \"polymorph.h\"\n\nnamespace sst {\nnamespace poly\n{\n\n\tvoid Solution_t::addSolution(const std::string& x, const fir::LocatedType& y)\n\t{\n\t\tthis->solutions[x] = y.type;\n\t}\n\n\tvoid Solution_t::addSubstitution(fir::Type* x, fir::Type* y)\n\t{\n\t\tif(auto it = this->substitutions.find(x); it != this->substitutions.end())\n\t\t{\n\t\t\tif(it->second != y) error(\"conflicting substitutions for '%s': '%s' and '%s'\", x, y, it->second);\n\t\t\tdebuglogln(\"substitution: '%s' -> '%s'\", x, y);\n\t\t}\n\n\t\tthis->substitutions[x] = y;\n\t}\n\n\tbool Solution_t::hasSolution(const std::string& n) const\n\t{\n\t\treturn this->solutions.find(n) != this->solutions.end();\n\t}\n\n\tfir::LocatedType Solution_t::getSolution(const std::string& n) const\n\t{\n\t\tif(auto it = this->solutions.find(n); it != this->solutions.end())\n\t\t\treturn fir::LocatedType(it->second);\n\n\t\telse\n\t\t\treturn fir::LocatedType(0);\n\t}\n\n\tfir::Type* Solution_t::substitute(fir::Type* x) const\n\t{\n\t\tif(auto it = this->substitutions.find(x); it != this->substitutions.end())\n\t\t\treturn it->second;\n\n\t\telse\n\t\t\treturn x;\n\t}\n\n\tvoid Solution_t::resubstituteIntoSolutions()\n\t{\n\t\t// iterate through everything\n\t\tfor(auto& [ n, t ] : this->solutions)\n\t\t\tt = this->substitute(t);\n\t}\n\n\tbool Solution_t::operator == (const Solution_t& other) const\n\t{\n\t\treturn other.distance == this->distance\n\t\t\t&& other.solutions == this->solutions\n\t\t\t&& other.substitutions == this->substitutions;\n\t}\n\n\tbool Solution_t::operator != (const Solution_t& other) const\n\t{\n\t\treturn !(other == *this);\n\t}\n\n\n\tnamespace internal\n\t{\n\t\tstd::pair<fir::Type*, std::vector<Trf>> decomposeIntoTransforms(fir::Type* t, size_t max)\n\t\t{\n\t\t\tstd::vector<Trf> ret;\n\n\t\t\tfor(size_t i = 0; i < max; i++)\n\t\t\t{\n\t\t\t\tif(t->isDynamicArrayType())\n\t\t\t\t{\n\t\t\t\t\tret.push_back(Trf(TrfType::DynamicArray));\n\t\t\t\t\tt = t->getArrayElementType();\n\t\t\t\t}\n\t\t\t\telse if(t->isArraySliceType())\n\t\t\t\t{\n\t\t\t\t\tif(t->isVariadicArrayType())    ret.push_back(Trf(TrfType::VariadicArray));\n\t\t\t\t\telse                            ret.push_back(Trf(TrfType::Slice, t->toArraySliceType()->isMutable()));\n\n\t\t\t\t\tt = t->getArrayElementType();\n\t\t\t\t}\n\t\t\t\telse if(t->isArrayType())\n\t\t\t\t{\n\t\t\t\t\tret.push_back(Trf(TrfType::FixedArray, t->toArrayType()->getArraySize()));\n\t\t\t\t\tt = t->getArrayElementType();\n\t\t\t\t}\n\t\t\t\telse if(t->isPointerType())\n\t\t\t\t{\n\t\t\t\t\tret.push_back(Trf(TrfType::Pointer, t->isMutablePointer()));\n\t\t\t\t\tt = t->getPointerElementType();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { t, ret };\n\t\t}\n\n\t\tstd::pair<pts::Type*, std::vector<Trf>> decomposeIntoTransforms(pts::Type* t)\n\t\t{\n\t\t\tstd::vector<Trf> ret;\n\n\t\t\twhile(true)\n\t\t\t{\n\t\t\t\tif(t->isDynamicArrayType())\n\t\t\t\t{\n\t\t\t\t\tret.push_back(Trf(TrfType::DynamicArray));\n\t\t\t\t\tt = t->toDynamicArrayType()->base;\n\t\t\t\t}\n\t\t\t\telse if(t->isArraySliceType())\n\t\t\t\t{\n\t\t\t\t\tret.push_back(Trf(TrfType::Slice, t->toArraySliceType()->mut));\n\t\t\t\t\tt = t->toArraySliceType()->base;\n\t\t\t\t}\n\t\t\t\telse if(t->isFixedArrayType())\n\t\t\t\t{\n\t\t\t\t\tret.push_back(Trf(TrfType::FixedArray, t->toFixedArrayType()->size));\n\t\t\t\t\tt = t->toFixedArrayType()->base;\n\t\t\t\t}\n\t\t\t\telse if(t->isPointerType())\n\t\t\t\t{\n\t\t\t\t\tret.push_back(Trf(TrfType::Pointer, t->toPointerType()->isMutable));\n\t\t\t\t\tt = t->toPointerType()->base;\n\t\t\t\t}\n\t\t\t\telse if(t->isVariadicArrayType())\n\t\t\t\t{\n\t\t\t\t\tret.push_back(Trf(TrfType::VariadicArray));\n\t\t\t\t\tt = t->toVariadicArrayType()->base;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { t, ret };\n\t\t}\n\n\n\t\tfir::Type* applyTransforms(fir::Type* base, const std::vector<Trf>& trfs)\n\t\t{\n\t\t\tfor(auto it = trfs.rbegin(); it != trfs.rend(); it++)\n\t\t\t{\n\t\t\t\tswitch(it->type)\n\t\t\t\t{\n\t\t\t\t\tcase TrfType::None:\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase TrfType::Slice:\n\t\t\t\t\t\tbase = fir::ArraySliceType::get(base, static_cast<bool>(it->data));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase TrfType::Pointer:\n\t\t\t\t\t\tbase = base->getPointerTo();\n\t\t\t\t\t\tif(static_cast<bool>(it->data)) base = base->getMutablePointerVersion();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase TrfType::FixedArray:\n\t\t\t\t\t\tbase = fir::ArrayType::get(base, it->data);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase TrfType::DynamicArray:\n\t\t\t\t\t\tbase = fir::DynamicArrayType::get(base);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase TrfType::VariadicArray:\n\t\t\t\t\t\tbase = fir::ArraySliceType::getVariadic(base);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\terror(\"unsupported transformation '%d'\", static_cast<int>(it->type));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn base;\n\t\t}\n\t}\n}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/ranges.cpp",
    "content": "// ranges.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"ir/type.h\"\n\n#include \"memorypool.h\"\n\nTCResult ast::RangeExpr::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto ret = util::pool<sst::RangeExpr>(this->loc, fir::RangeType::get());\n\tret->halfOpen = this->halfOpen;\n\n\tret->start = this->start->typecheck(fs, fir::Type::getNativeWord()).expr();\n\tif(!ret->start->type->isIntegerType())\n\t\terror(ret->start, \"expected integer type in range expression (start), found '%s' instead\", ret->start->type);\n\n\tret->end = this->end->typecheck(fs, fir::Type::getNativeWord()).expr();\n\tif(!ret->end->type->isIntegerType())\n\t\terror(ret->end, \"expected integer type in range expression (end), found '%s' instead\", ret->end->type);\n\n\tif(this->step)\n\t{\n\t\tret->step = this->step->typecheck(fs, fir::Type::getNativeWord()).expr();\n\t\tif(!ret->step->type->isIntegerType())\n\t\t\terror(ret->step, \"expected integer type in range expression (step), found '%s' instead\", ret->step->type);\n\t}\n\n\treturn TCResult(ret);\n}\n"
  },
  {
    "path": "source/typecheck/resolver/driver.cpp",
    "content": "// call.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"pts.h\"\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"polymorph.h\"\n#include \"resolver.h\"\n\n#include \"ir/type.h\"\n\n#include <set>\n\nnamespace sst {\nnamespace resolver\n{\n\tTCResult resolveFunctionCallFromCandidates(TypecheckState* fs, const Location& callLoc, const std::vector<Defn*>& cands,\n\t\tstd::vector<FnCallArgument>* args, const PolyArgMapping_t& gmaps, bool allowImplicitSelf)\n\t{\n\t\tauto cds = zfu::map(cands, [&args](auto c) -> std::pair<Defn*, std::vector<FnCallArgument>> { return { c, *args }; });\n\t\tauto [ ret, new_args ] = resolver::internal::resolveFunctionCallFromCandidates(fs, fs->loc(), cds, gmaps, allowImplicitSelf, nullptr);\n\n\t\t*args = new_args;\n\t\treturn ret;\n\t}\n\n\tTCResult resolveFunctionCall(TypecheckState* fs, const Location& callLoc, const std::string& name, std::vector<FnCallArgument>* arguments,\n\t\tconst PolyArgMapping_t& gmaps, bool travUp, fir::Type* return_infer)\n\t{\n\t\tStateTree* tree = fs->stree;\n\n\t\t//* the purpose of this 'didVar' flag (because I was fucking confused reading this)\n\t\t//* is so we only consider the innermost (ie. most local) variable, because variables don't participate in overloading.\n\t\t//! ACHTUNG !\n\t\t// TODO: do we even need this didVar nonsense? variables don't overload yes, but we can't even define more than one\n\t\t// TODO: variable in a scope with the same name. if we find something with a matching name we quit immediately, so there\n\t\t// TODO: shouldn't be a point in having 'didVar'!!\n\t\t// TODO: - zhiayang, 28/10/18\n\n\n\t\t//? I can't find any information about this behaviour in languages other than C++, because we need to have a certain set of\n\t\t//? features for it to manifest -- 1. user-defined, explicit namespaces; 2. function overloading.\n\n\t\t//* how it works in C++, and for now also in Flax, is that once we match *any* names in the current scope, we stop searching upwards\n\t\t//* -- even if it means we will throw an error because of mismatched arguments or whatever.\n\t\t// bool didVar = false;\n\n\t\tbool didGeneric = false;\n\n\t\tstd::vector<std::pair<Locatable*, ErrorMsg*>> fails;\n\t\tstd::vector<std::tuple<Defn*, std::vector<FnCallArgument>, poly::Solution_t>> fns;\n\n\t\twhile(tree)\n\t\t{\n\t\t\t{\n\t\t\t\tauto defs = tree->getDefinitionsWithName(name);\n\t\t\t\tfor(auto d : defs)\n\t\t\t\t\tfns.push_back({ d, *arguments, poly::Solution_t() });\n\t\t\t}\n\n\t\t\tif(auto gdefs = tree->getUnresolvedGenericDefnsWithName(name); gdefs.size() > 0)\n\t\t\t{\n\t\t\t\tdidGeneric = true;\n\t\t\t\tauto argcopy = *arguments;\n\n\t\t\t\tauto pots = poly::findPolymorphReferences(fs, name, gdefs, gmaps, /* return_infer: */ return_infer,\n\t\t\t\t\t/* type_infer: */ 0, /* isFnCall: */ true, &argcopy);\n\n\t\t\t\tfor(const auto& pot : pots)\n\t\t\t\t{\n\t\t\t\t\tif(!pot.res.isDefn())\n\t\t\t\t\t{\n\t\t\t\t\t\ticeAssert(pot.res.isError());\n\t\t\t\t\t\tfails.push_back({ pot.thing, pot.res.error() });\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tauto def = pot.res.defn();\n\t\t\t\t\t\tif(def->type->containsPlaceholders())\n\t\t\t\t\t\t\terror(\"wtf??? '%s'\", def->type);\n\n\t\t\t\t\t\t// make sure we didn't already find this in the non-generic search\n\t\t\t\t\t\t//? (can happen when we recursively call a generic function!)\n\t\t\t\t\t\tif(auto it = std::find_if(fns.begin(), fns.end(), [def](const auto& tup) -> bool {\n\t\t\t\t\t\t\treturn std::get<0>(tup) == def;\n\t\t\t\t\t\t}); it != fns.end())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tauto sln = pot.soln;\n\t\t\t\t\t\t// ! ACHTUNG !\n\t\t\t\t\t\t// insert a hefty penalty for using a polymorphic function!\n\t\t\t\t\t\t// this doesn't disallow polymorphic functions from participating in\n\t\t\t\t\t\t// overloading, but this makes our resolver prefer non-generic functions.\n\t\t\t\t\t\tsln.distance += 10;\n\n\t\t\t\t\t\tfns.push_back({ def, argcopy, sln });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(travUp && fns.empty())\n\t\t\t\ttree = tree->parent;\n\n\t\t\telse\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif(fns.empty())\n\t\t{\n\t\t\tif(!didGeneric)\n\t\t\t{\n\t\t\t\tauto top = fs->stree;\n\t\t\t\twhile(top && top->parent)\n\t\t\t\t\ttop = top->parent;\n\n\t\t\t\treturn TCResult(SimpleError::make(fs->loc(), \"no function named '%s' in the current scope\", name));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto err = createErrorFromFailedCandidates(fs, callLoc, name, *arguments, fails);\n\t\t\t\treturn TCResult(err);\n\t\t\t}\n\t\t}\n\n\n\t\tstd::vector<std::pair<sst::Defn*, std::vector<FnCallArgument>>> cands;\n\t\tfor(const auto& [ def, args, soln ] : fns)\n\t\t{\n\t\t\tauto ts = args; // copy it.\n\n\t\t\tif(dcast(FunctionDecl, def) || dcast(TypeDefn, def))\n\t\t\t{\n\t\t\t\tcands.push_back({ def, ts });\n\t\t\t}\n\t\t\telse if(dcast(VarDefn, def) && def->type->isFunctionType() /* && !didVar */)\n\t\t\t{\n\t\t\t\tcands.push_back({ def, ts });\n\t\t\t\t// didVar = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn TCResult(\n\t\t\t\t\tSimpleError::make(fs->loc(), \"'%s' cannot be called as a function; it was defined with type '%s'\",\n\t\t\t\t\t\tname, def->type)->append(SimpleError::make(def->loc, \"the definition was here:\"))\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tauto [ res, new_args ] = resolver::internal::resolveFunctionCallFromCandidates(fs, fs->loc(), cands, gmaps, travUp, return_infer);\n\t\tif(res.isDefn())\n\t\t\t*arguments = new_args;\n\n\t\treturn res;\n\t}\n\n\n\n\n\tTCResult resolveConstructorCall(TypecheckState* fs, const Location& callLoc, TypeDefn* typedf, const std::vector<FnCallArgument>& arguments,\n\t\tconst PolyArgMapping_t& pams)\n\t{\n\t\t//! ACHTUNG: DO NOT REARRANGE !\n\t\t//* NOTE: ClassDefn inherits from StructDefn *\n\n\t\tif(auto cls = dcast(ClassDefn, typedf))\n\t\t{\n\t\t\t// class initialisers must be called with named arguments only.\n\t\t\tfor(const auto& arg : arguments)\n\t\t\t{\n\t\t\t\tif(arg.name.empty())\n\t\t\t\t{\n\t\t\t\t\treturn TCResult(SimpleError::make(arg.loc, \"arguments to class initialisers (for class '%s' here) must be named\", cls->id.name));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tauto copy = arguments;\n\n\t\t\t//! SELF HANDLING (INSERTION) (CONSTRUCTOR CALL)\n\t\t\tcopy.insert(copy.begin(), FnCallArgument::make(cls->loc, \"this\", cls->type->getMutablePointerTo(),\n\t\t\t\t/* ignoreName: */ true));\n\n\t\t\tauto copy1 = copy;\n\n\t\t\tauto cand = resolveFunctionCallFromCandidates(fs, callLoc, zfu::map(cls->initialisers, [](auto e) -> auto {\n\t\t\t\treturn dcast(sst::Defn, e);\n\t\t\t}), &copy, pams, true);\n\n\t\t\t// TODO: support re-eval of constructor args!\n\t\t\t// TODO: support re-eval of constructor args!\n\t\t\t// TODO: support re-eval of constructor args!\n\n\t\t\tif(cand.isError())\n\t\t\t{\n\t\t\t\tcand.error()->prepend(SimpleError::make(fs->loc(), \"failed to find matching initialiser for class '%s':\", cls->id.name));\n\t\t\t\treturn TCResult(cand.error());\n\t\t\t}\n\n\t\t\tif(copy1 != copy)\n\t\t\t\terror(fs->loc(), \"args changed for constructor call -- fixme!!!\");\n\n\t\t\treturn TCResult(cand);\n\t\t}\n\t\telse if(auto str = dcast(StructDefn, typedf))\n\t\t{\n\t\t\tstd::vector<std::string> fieldNames;\n\n\t\t\tfor(auto f : str->fields)\n\t\t\t\tfieldNames.push_back(f->id.name);\n\n\t\t\tauto [ seen, err ] = resolver::verifyStructConstructorArguments(fs->loc(), str->id.name, fieldNames, arguments);\n\n\t\t\tif(err != nullptr)\n\t\t\t{\n\t\t\t\treturn TCResult(err);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto seencopy = seen;\n\t\t\t\tstd::vector<FnParam> target = zfu::filterMap(str->fields, [&seencopy](sst::StructFieldDefn* f) -> bool {\n\t\t\t\t\treturn seencopy.find(f->id.name) != seencopy.end();\n\t\t\t\t}, [](sst::StructFieldDefn* f) -> FnParam {\n\t\t\t\t\treturn FnParam(f->loc, f->id.name, f->type);\n\t\t\t\t});\n\n\t\t\t\tauto args = zfu::map(arguments, [](const FnCallArgument& a) -> poly::ArgType {\n\t\t\t\t\treturn poly::ArgType(a.name, a.value->type, a.loc);\n\t\t\t\t});\n\n\t\t\t\tauto [ soln, err ] = poly::solveTypeList(fs->loc(), zfu::map(target, [](const FnParam& f) -> poly::ArgType {\n\t\t\t\t\treturn poly::ArgType(f.name, f.type, f.loc, f.defaultVal != 0);\n\t\t\t\t}), args, poly::Solution_t(), /* isFnCall: */ true);\n\n\t\t\t\t// in actual fact we just return the thing here. sigh.\n\t\t\t\tif(err != nullptr)  return TCResult(err);\n\t\t\t\telse                return TCResult(str);\n\t\t\t}\n\t\t}\n\t\telse if(auto uvd = dcast(sst::UnionVariantDefn, typedf))\n\t\t{\n\t\t\t// TODO: support re-eval of constructor args!\n\t\t\t// TODO: support re-eval of constructor args!\n\t\t\t// TODO: support re-eval of constructor args!\n\n\t\t\tauto copy = arguments;\n\n\t\t\tauto ret = resolver::resolveAndInstantiatePolymorphicUnion(fs, uvd, &copy, /* type_infer: */ nullptr, /* isFnCall: */ true);\n\n\t\t\tif(copy != arguments)\n\t\t\t\terror(fs->loc(), \"args changed for constructor call -- fixme!!!\");\n\n\t\t\treturn ret;\n\t\t}\n\t\telse if(auto rud = dcast(sst::RawUnionDefn, typedf))\n\t\t{\n\t\t\treturn TCResult(SimpleError::make(fs->loc(), \"constructors are not defined for raw unions\")\n\t\t\t\t->append(SimpleError::make(MsgType::Note, rud->loc, \"type was defined here:\"))\n\t\t\t);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn TCResult(\n\t\t\t\tSimpleError::make(fs->loc(), \"unsupported constructor call on type '%s'\", typedf->id.name)\n\t\t\t    ->append(SimpleError::make(MsgType::Note, typedf->loc, \"type was defined here:\"))\n\t\t\t);\n\t\t}\n\t}\n\t}\n\n\n\tfir::Type* TypecheckState::checkIsBuiltinConstructorCall(const std::string& name, const std::vector<FnCallArgument>& arguments)\n\t{\n\t\tif(auto type = fir::Type::fromBuiltin(name))\n\t\t{\n\t\t\tfor(const auto& a : arguments)\n\t\t\t{\n\t\t\t\tif(!a.name.empty())\n\t\t\t\t\terror(a.loc, \"builtin type initialisers do not accept named arguments\");\n\t\t\t}\n\n\t\t\t// all builtin types can be zero-initialised.\n\t\t\tif(arguments.empty())\n\t\t\t{\n\t\t\t\treturn type;\n\t\t\t}\n\t\t\telse if(arguments.size() == 1)\n\t\t\t{\n\t\t\t\tif(int d = getCastDistance(arguments[0].value->type, type); d >= 0 || (type->isStringType() && arguments[0].value->type->isCharSliceType()))\n\t\t\t\t{\n\t\t\t\t\treturn type;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\terror(arguments[0].loc, \"type mismatch in initialiser call to builtin type '%s', found type '%s' instead\", type,\n\t\t\t\t\t\targuments[0].value->type);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif(type->isStringType())\n\t\t\t\t{\n\t\t\t\t\t// either from a slice, or from a ptr + len\n\t\t\t\t\tif(arguments.size() == 1)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!arguments[0].value->type->isCharSliceType())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\terror(arguments[0].loc, \"single argument to string initialiser must be a slice of char, aka '%s', found '%s' instead\",\n\t\t\t\t\t\t\t\tfir::Type::getCharSlice(false), arguments[0].value->type);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn type;\n\t\t\t\t\t}\n\t\t\t\t\telse if(arguments.size() == 2)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(auto t1 = arguments[0].value->type; (t1 != fir::Type::getInt8Ptr() && t1 != fir::Type::getMutInt8Ptr()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\terror(arguments[0].loc, \"first argument to two-arg string initialiser (data pointer) must be '%s' or '%s', found '%s' instead\",\n\t\t\t\t\t\t\t\tfir::Type::getInt8Ptr(), fir::Type::getMutInt8Ptr(), t1);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(auto t2 = arguments[1].value->type; fir::getCastDistance(t2, fir::Type::getNativeWord()) < 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\terror(arguments[0].loc, \"second argument to two-arg string initialiser (length) must be '%s', found '%s' instead\",\n\t\t\t\t\t\t\t\tfir::Type::getNativeWord(), t2);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn type;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\terror(arguments[2].loc, \"string initialiser only takes 1 (from slice) or 2 (from pointer+length)\"\n\t\t\t\t\t\t\t\" arguments, found '%d' instead\", arguments.size());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\terror(arguments[1].loc, \"builtin type '%s' cannot be initialised with more than 1 value\", type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn 0;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/resolver/misc.cpp",
    "content": "// misc.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"resolver.h\"\n#include \"polymorph.h\"\n#include \"typecheck.h\"\n\n#include \"ir/type.h\"\n\nnamespace sst\n{\n\tnamespace resolver\n\t{\n\t\tnamespace misc\n\t\t{\n\t\t\tstd::pair<TypeParamMap_t, ErrorMsg*> canonicalisePolyArguments(TypecheckState* fs, ast::Parameterisable* thing, const PolyArgMapping_t& pams)\n\t\t\t{\n\t\t\t\tif(thing->generics.empty())\n\t\t\t\t\treturn { { }, SimpleError::make(fs->loc(), \"cannot canonicalise poly arguments for non-generic (or nested) entity '%s'\", thing->name) };\n\n\t\t\t\tTypeParamMap_t ret;\n\n\t\t\t\t//? we only check if we provided more than necessary, because (1) we might have optional args in the future, and (2) we can omit args\n\t\t\t\t//? to infer stuff.\n\t\t\t\tif(thing->generics.size() < pams.maps.size())\n\t\t\t\t{\n\t\t\t\t\treturn { { }, SimpleError::make(fs->loc(), \"mismatched number of type arguments to polymorph '%s'; expected %d, found %d instead\",\n\t\t\t\t\t\tthing->name, thing->generics.size(), pams.maps.size()) };\n\t\t\t\t}\n\n\t\t\t\tfor(const auto& pam : pams.maps)\n\t\t\t\t{\n\t\t\t\t\tif(!pam.name.empty())\n\t\t\t\t\t{\n\t\t\t\t\t\t// check if it exists.\n\t\t\t\t\t\tauto it = std::find_if(thing->generics.begin(), thing->generics.end(),\n\t\t\t\t\t\t\t[&pam](const std::pair<std::string, TypeConstraints_t>& a) -> bool {\n\t\t\t\t\t\t\t\treturn a.first == pam.name;\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif(it == thing->generics.end())\n\t\t\t\t\t\t\treturn { { }, SimpleError::make(fs->loc(), \"no type parameter named '%s' in polymorph '%s'\", pam.name, thing->name) };\n\n\t\t\t\t\t\t// ok, it works.\n\t\t\t\t\t\tret[pam.name] = fs->convertParserTypeToFIR(pam.type, /* allowFailure: */ false);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// ok, the index ought to exist.\n\t\t\t\t\t\ticeAssert(pam.index < thing->generics.size());\n\n\t\t\t\t\t\t// should be simple.\n\t\t\t\t\t\tret[thing->generics[pam.index].first] = fs->convertParserTypeToFIR(pam.type, /* allowFailure: */ false);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn { ret, nullptr };\n\t\t\t}\n\n\n\t\t\tstd::vector<FnCallArgument> typecheckCallArguments(TypecheckState* fs, const std::vector<std::pair<std::string, ast::Expr*>>& args)\n\t\t\t{\n\t\t\t\treturn zfu::map(args, [fs](const auto& a) -> FnCallArgument {\n\t\t\t\t\treturn FnCallArgument(a.second->loc, a.first, a.second->typecheck(fs).expr(), a.second);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t\tTCResult resolveAndInstantiatePolymorphicUnion(TypecheckState* fs, sst::UnionVariantDefn* uvd, std::vector<FnCallArgument>* arguments,\n\t\t\tfir::Type* union_infer, bool isFnCall)\n\t\t{\n\t\t\tauto name = uvd->variantName;\n\t\t\tauto unn = uvd->parentUnion;\n\t\t\ticeAssert(unn);\n\n\t\t\tif(unn->type->containsPlaceholders())\n\t\t\t{\n\t\t\t\tauto orig_unn = unn->original;\n\t\t\t\ticeAssert(orig_unn);\n\n\t\t\t\tauto [ res, soln ] = poly::attemptToInstantiatePolymorph(fs, orig_unn, name, /* gmaps: */ { }, /* return_infer */ nullptr,\n\t\t\t\t\t/* type_infer: */ union_infer, isFnCall, arguments, /* fillPlaceholders: */ false, /* problem_infer: */ nullptr);\n\n\t\t\t\tif(res.isError() || (res.isDefn() && res.defn()->type->containsPlaceholders()))\n\t\t\t\t{\n\t\t\t\t\tErrorMsg* e = SimpleError::make(fs->loc(), \"unable to infer types for union '%s' using variant '%s'\", unn->id.name, name);\n\n\t\t\t\t\tif(res.isError())\n\t\t\t\t\t\te->append(res.error());\n\n\t\t\t\t\treturn TCResult(e);\n\t\t\t\t}\n\n\t\t\t\t// make it so\n\t\t\t\tunn = dcast(sst::UnionDefn, res.defn());\n\t\t\t\ticeAssert(unn);\n\n\t\t\t\t// re-do it.\n\t\t\t\tuvd = unn->variants[name];\n\t\t\t\ticeAssert(uvd);\n\t\t\t}\n\n\t\t\tauto vty = uvd->type->toUnionVariantType()->getInteriorType();\n\n\t\t\tif(isFnCall)\n\t\t\t{\n\t\t\t\tstd::vector<fir::LocatedType> target;\n\t\t\t\tif(vty->isTupleType())\n\t\t\t\t{\n\t\t\t\t\tfor(auto t : vty->toTupleType()->getElements())\n\t\t\t\t\t\ttarget.push_back(fir::LocatedType(t, uvd->loc));\n\t\t\t\t}\n\t\t\t\telse if(!vty->isVoidType())\n\t\t\t\t{\n\t\t\t\t\ttarget.push_back(fir::LocatedType(vty, uvd->loc));\n\t\t\t\t}\n\n\t\t\t\tauto [ dist, errs ] = resolver::computeOverloadDistance(unn->loc, target, zfu::map(*arguments, [](const FnCallArgument& fca) -> auto {\n\t\t\t\t\treturn fir::LocatedType(fca.value->type, fca.loc);\n\t\t\t\t}), /* isCVarArg: */ false, fs->loc());\n\n\t\t\t\tif(errs != nullptr || dist == -1)\n\t\t\t\t{\n\t\t\t\t\tauto x = SimpleError::make(fs->loc(), \"mismatched types in construction of variant '%s' of union '%s'\", name, unn->id.name);\n\t\t\t\t\tif(errs)    errs->prepend(x);\n\t\t\t\t\telse        errs = x;\n\n\t\t\t\t\treturn TCResult(errs);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn TCResult(uvd);\n\t\t}\n\n\n\t\tstd::pair<util::hash_map<std::string, size_t>, ErrorMsg*> verifyStructConstructorArguments(const Location& callLoc,\n\t\t\tconst std::string& name, const std::vector<std::string>& fieldNames, const std::vector<FnCallArgument>& arguments)\n\t\t{\n\t\t\t//* note that structs don't have inline member initialisers, so there's no trouble with this approach (in the codegeneration)\n\t\t\t//* of inserting missing arguments as just '0' or whatever their default value is\n\n\t\t\t//* in the case of classes, they will have inline initialisers, so the constructor calling must handle such things.\n\t\t\t//* but then class constructors are handled like regular functions, so it should be fine.\n\n\t\t\tbool useNames = false;\n\t\t\tbool firstName = true;\n\n\t\t\tsize_t ctr = 0;\n\t\t\tutil::hash_map<std::string, size_t> seenNames;\n\t\t\tfor(const auto& arg : arguments)\n\t\t\t{\n\t\t\t\tif((arg.name.empty() && useNames) || (!firstName && !useNames && !arg.name.empty()))\n\t\t\t\t{\n\t\t\t\t\treturn { { }, SimpleError::make(arg.loc, \"named arguments cannot be mixed with positional arguments in a struct constructor\") };\n\t\t\t\t}\n\t\t\t\telse if(firstName && !arg.name.empty())\n\t\t\t\t{\n\t\t\t\t\tuseNames = true;\n\t\t\t\t}\n\n\n\t\t\t\tif(!arg.name.empty() && std::find(fieldNames.begin(), fieldNames.end(), arg.name) == fieldNames.end())\n\t\t\t\t{\n\t\t\t\t\treturn { { }, SimpleError::make(arg.loc, \"field '%s' does not exist in struct '%s'\", arg.name, name) };\n\t\t\t\t}\n\t\t\t\telse if(!arg.name.empty() && seenNames.find(arg.name) != seenNames.end())\n\t\t\t\t{\n\t\t\t\t\treturn { { }, SimpleError::make(arg.loc, \"duplicate argument for field '%s' in constructor call to struct '%s'\",\n\t\t\t\t\t\targ.name, name) };\n\t\t\t\t}\n\n\t\t\t\tfirstName = false;\n\t\t\t\tseenNames[arg.name] = ctr;\n\t\t\t\tctr += 1;\n\t\t\t}\n\n\t\t\t//* note: if we're doing positional args, allow only all or none.\n\t\t\tif(!useNames)\n\t\t\t{\n\t\t\t\tif(arguments.size() != fieldNames.size() && arguments.size() > 0)\n\t\t\t\t{\n\t\t\t\t\treturn { { }, SimpleError::make(callLoc,\n\t\t\t\t\t\t\"mismatched number of arguments in constructor call to type '%s'; expected %d, found %d instead\",\n\t\t\t\t\t\tname, fieldNames.size(), arguments.size())->append(\n\t\t\t\t\t\t\tBareError::make(MsgType::Note, \"all arguments are mandatory when using positional arguments\")\n\t\t\t\t\t\t)\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// ok; populate 'seenNames' with all the fields, because we 'saw' them, I guess.\n\t\t\t\tfor(size_t i = 0; i < fieldNames.size(); i++)\n\t\t\t\t\tseenNames[fieldNames[i]] = i;\n\t\t\t}\n\n\t\t\treturn { seenNames, nullptr };\n\t\t}\n\n\t}\n\n\n\n\n\n\n\tint getOverloadDistance(const std::vector<fir::Type*>& a, const std::vector<fir::Type*>& b)\n\t{\n\t\treturn resolver::computeOverloadDistance(Location(), zfu::map(a, [](fir::Type* t) -> fir::LocatedType {\n\t\t\treturn fir::LocatedType(t, Location());\n\t\t}), zfu::map(b, [](fir::Type* t) -> fir::LocatedType {\n\t\t\treturn fir::LocatedType(t, Location());\n\t\t}), /* isCVarArg: */ false, Location()).first;\n\t}\n\n\tbool isDuplicateOverload(const std::vector<FnParam>& a, const std::vector<FnParam>& b)\n\t{\n\t\treturn getOverloadDistance(zfu::map(a, [](const auto& p) -> auto { return p.type; }),\n\t\t\tzfu::map(b, [](const auto& p) -> auto { return p.type; })) == 0;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/resolver/resolver.cpp",
    "content": "// resolver.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"sst.h\"\n#include \"errors.h\"\n#include \"ir/type.h\"\n#include \"typecheck.h\"\n\n#include \"resolver.h\"\n#include \"polymorph.h\"\n\nnamespace sst {\nnamespace resolver\n{\n\tstd::pair<int, ErrorMsg*> computeOverloadDistance(const Location& fnLoc, const std::vector<fir::LocatedType>& _target,\n\t\tconst std::vector<fir::LocatedType>& _args, bool cvararg, const Location& callLoc)\n\t{\n\t\tstd::vector<fir::LocatedType> _input;\n\t\tif(cvararg) _input = zfu::take(_args, _target.size());\n\t\telse        _input = _args;\n\n\t\tauto input = zfu::map(_input, [](auto t) -> poly::ArgType {\n\t\t\treturn poly::ArgType(\"\", t.type, t.loc);\n\t\t});\n\n\t\tauto target = zfu::map(_target, [](auto t) -> poly::ArgType {\n\t\t\treturn poly::ArgType(\"\", t.type, t.loc);\n\t\t});\n\n\t\tauto [ soln, err ] = poly::solveTypeList(callLoc, target, input, poly::Solution_t(), /* isFnCall: */ true);\n\n\t\tif(err != nullptr)  return { -1, err };\n\t\telse                return { soln.distance, nullptr };\n\t}\n\n\n\n\tstd::pair<int, ErrorMsg*> computeNamedOverloadDistance(const Location& fnLoc, const std::vector<FnParam>& target,\n\t\tconst std::vector<FnCallArgument>& _args, bool cvararg, const Location& callLoc)\n\t{\n\t\tstd::vector<FnCallArgument> input;\n\t\tif(cvararg) input = zfu::take(_args, target.size());\n\t\telse        input = _args;\n\n\t\tauto arguments = zfu::map(input, [](const FnCallArgument& a) -> poly::ArgType {\n\t\t\treturn poly::ArgType(a.name, a.value->type, a.loc, /* opt: */ false, /* ignoreName: */ a.ignoreName);\n\t\t});\n\n\t\t// ok, in this case we should figure out where the first optional argument lives, and pass that to\n\t\t// the type-list solver. it doesn't need to know what the actual value is --- when we typechecked the function, we should\n\t\t// have already verified the default value fits the type, and it doesn't actually change the type of the receiver.\n\n\t\tauto [ soln, err1 ] = poly::solveTypeList(callLoc, zfu::map(target, [](const FnParam& p) -> poly::ArgType {\n\t\t\treturn poly::ArgType(p.name, p.type, p.loc, p.defaultVal != 0);\n\t\t}), arguments, poly::Solution_t(), /* isFnCall: */ true);\n\n\n\t\tif(err1 != nullptr) return { -1, err1 };\n\t\telse                return { soln.distance, nullptr };\n\t}\n\n\n\n\tErrorMsg* createErrorFromFailedCandidates(TypecheckState* fs, const Location& callLoc, const std::string& name,\n\t\tconst std::vector<FnCallArgument>& args, const std::vector<std::pair<Locatable*, ErrorMsg*>>& fails)\n\t{\n\t\t// if we only had one candidate, there are no 'overloads' -- don't be a c++ and say stupid things.\n\t\t// we just directly post the error message instead.\n\n\t\tif(fails.size() == 1)\n\t\t{\n\t\t\tauto fail = fails.begin();\n\n\t\t\tauto ret = fail->second;\n\t\t\tif(auto f = dcast(FunctionDefn, fail->first); f)\n\t\t\t{\n\t\t\t\tret->append(SimpleError::make(MsgType::Note, f->loc, \"function '%s' was defined here:\", f->id.name));\n\t\t\t}\n\t\t\telse if(auto v = dcast(VarDefn, fail->first); v)\n\t\t\t{\n\t\t\t\tret->append(SimpleError::make(MsgType::Note, v->loc, \"'%s' was defined here with type '%s':\", v->id.name,\n\t\t\t\t\tv->type));\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::vector<fir::Type*> tmp = zfu::map(args, [](const FnCallArgument& p) -> auto { return p.value->type; });\n\n\t\t\tauto errs = OverloadError::make(SimpleError::make(callLoc, \"no overload in call to '%s' with arguments (%s) amongst %d %s\",\n\t\t\t\tname, fir::Type::typeListToString(tmp), fails.size(), zfu::plural(\"candidate\", fails.size())));\n\n\t\t\tfor(auto f : fails)\n\t\t\t{\n\t\t\t\t// TODO: HACK -- pass the location around more then!!\n\t\t\t\t// patch in the location if it's not present!\n\t\t\t\tif(auto se = dcast(SimpleError, f.second); se)\n\t\t\t\t{\n\t\t\t\t\tse->loc = f.first->loc;\n\t\t\t\t\tse->msg = \"candidate unsuitable: \" + se->msg;\n\t\t\t\t}\n\n\t\t\t\terrs->addCand(f.first, f.second);\n\t\t\t}\n\n\t\t\treturn errs;\n\t\t}\n\t}\n\n\n\n\tnamespace internal\n\t{\n\t\tstd::pair<TCResult, std::vector<FnCallArgument>> resolveFunctionCallFromCandidates(TypecheckState* fs, const Location& callLoc,\n\t\t\tconst std::vector<std::pair<Defn*, std::vector<FnCallArgument>>>& _cands, const PolyArgMapping_t& pams, bool allowImplicitSelf,\n\t\t\tfir::Type* return_infer)\n\t\t{\n\t\t\tif(_cands.empty())\n\t\t\t\treturn { TCResult(BareError::make(\"no candidates\")), { } };\n\n\t\t\tint bestDist = INT_MAX;\n\t\t\tstd::map<Defn*, ErrorMsg*> fails;\n\t\t\tstd::vector<std::tuple<Defn*, std::vector<FnCallArgument>, int>> finals;\n\n\t\t\tauto cands = _cands;\n\n\n\t\t\tauto complainAboutExtraneousPAMs = [&fs](const std::string& kind, Defn* def, const std::string& action, bool printdef) -> ErrorMsg* {\n\t\t\t\tauto ret = SimpleError::make(fs->loc(), \"%s '%s' cannot be %s with type arguments\",\n\t\t\t\t\tkind, def->id.name, action);\n\n\t\t\t\tif(printdef)\n\t\t\t\t\tret->append(SimpleError::make(MsgType::Note, def->loc, \"function was defined here:\"));\n\n\t\t\t\treturn ret;\n\t\t\t};\n\n\t\t\tfor(const auto& [ _cand, _args ] : cands)\n\t\t\t{\n\t\t\t\tint dist = -1;\n\t\t\t\tDefn* curcandidate = _cand;\n\t\t\t\tstd::vector<FnCallArgument> replacementArgs = _args;\n\n\t\t\t\tif(auto fn = dcast(FunctionDecl, curcandidate))\n\t\t\t\t{\n\t\t\t\t\t// check for placeholders -- means that we should attempt to infer the type of the parent if its a static method.\n\t\t\t\t\t//* there are some assumptions we can make -- primarily that this will always be a static method of a type.\n\t\t\t\t\t//? (a): namespaces cannot be generic.\n\t\t\t\t\t//? (b): instance methods must have an associated 'self', and you can't have a variable of generic type\n\t\t\t\t\t//! are these assumptions still valid?? 02/12/18\n\n\t\t\t\t\t//! SELF HANDLING (INSERTION) (METHOD CALL)\n\t\t\t\t\tbool insertedSelf = false;\n\t\t\t\t\tif(fn->parentTypeForMethod && (replacementArgs.size() == fn->params.size() - 1))\n\t\t\t\t\t{\n\t\t\t\t\t\tinsertedSelf = true;\n\n\t\t\t\t\t\t// ignoreName records the fact that we are not actually passing 'self' with a name; it\n\t\t\t\t\t\t// is there so we do not \"pass positional arguments after named arguments\".\n\t\t\t\t\t\treplacementArgs.insert(replacementArgs.begin(), FnCallArgument::make(fn->loc, \"this\",\n\t\t\t\t\t\t\tfn->parentTypeForMethod->getMutablePointerTo(), /* ignoreName: */ true));\n\t\t\t\t\t}\n\n\n\t\t\t\t\tif(fn->type->containsPlaceholders())\n\t\t\t\t\t{\n\t\t\t\t\t\tif(auto fd = dcast(FunctionDefn, fn); !fd)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\terror(fd, \"invalid non-definition of a function with placeholder types\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// ok, i guess.\n\t\t\t\t\t\t\ticeAssert(fd);\n\t\t\t\t\t\t\ticeAssert(fd->original);\n\n\t\t\t\t\t\t\tauto [ gmaps, err ] = resolver::misc::canonicalisePolyArguments(fs, fd->original, pams);\n\t\t\t\t\t\t\tif(err != nullptr)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfails[fn] = err;\n\t\t\t\t\t\t\t\tdist = -1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// do an inference -- with the arguments that we have.\n\t\t\t\t\t\t\t\tauto [ res, soln ] = poly::attemptToInstantiatePolymorph(fs, fd->original, fn->id.name, gmaps, /* return_infer: */ return_infer,\n\t\t\t\t\t\t\t\t\t/* type_infer: */ nullptr, /* isFnCall: */ true, &replacementArgs, /* fillPlacholders: */ false,\n\t\t\t\t\t\t\t\t\t/* problem_infer: */ fn->type);\n\n\t\t\t\t\t\t\t\tif(!res.isDefn())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfails[fn] = res.error();\n\t\t\t\t\t\t\t\t\tdist = -1;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcurcandidate = res.defn();\n\t\t\t\t\t\t\t\t\tstd::tie(dist, fails[fn]) = std::make_tuple(soln.distance, nullptr);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// if it's not generic but you gave type args, you don't deserve to call it.\n\t\t\t\t\t\t//? we might change this\n\n\t\t\t\t\t\tif(!pams.empty())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfails[fn] = complainAboutExtraneousPAMs(\"non-polymorphic function\", fn, \"called\", /* printdef: */ true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstd::tie(dist, fails[fn]) = computeNamedOverloadDistance(fn->loc, fn->params, replacementArgs, fn->isVarArg, callLoc);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t//! SELF HANDLING (REMOVAL) (METHOD CALL)\n\t\t\t\t\tif(insertedSelf)\n\t\t\t\t\t\treplacementArgs.erase(replacementArgs.begin());\n\t\t\t\t}\n\t\t\t\telse if(auto vr = dcast(VarDefn, curcandidate))\n\t\t\t\t{\n\t\t\t\t\ticeAssert(vr->type->isFunctionType());\n\t\t\t\t\tauto ft = vr->type->toFunctionType();\n\n\t\t\t\t\tif(!pams.empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tfails[vr] = complainAboutExtraneousPAMs(\"variables\", vr, \"used\", /* printdef: */ false);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// check if have any names\n\t\t\t\t\tfor(auto p : replacementArgs)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(p.name != \"\")\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn { TCResult(SimpleError::make(p.loc, \"function values cannot be called with named arguments\")->append(\n\t\t\t\t\t\t\t\tSimpleError::make(vr->loc, \"'%s' was defined here:\", vr->id.name))\n\t\t\t\t\t\t\t), { } };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tauto prms = ft->getArgumentTypes();\n\t\t\t\t\tstd::tie(dist, fails[vr]) = computeOverloadDistance(curcandidate->loc, zfu::map(prms, [](fir::Type* t) -> fir::LocatedType {\n\t\t\t\t\t\treturn fir::LocatedType(t, Location());\n\t\t\t\t\t}), zfu::map(replacementArgs, [](const FnCallArgument& p) -> fir::LocatedType {\n\t\t\t\t\t\treturn fir::LocatedType(p.value->type, Location());\n\t\t\t\t\t}), /* isCVarArg: */ false, callLoc);\n\t\t\t\t}\n\t\t\t\telse if(auto td = dcast(TypeDefn, curcandidate))\n\t\t\t\t{\n\t\t\t\t\tif(!pams.empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!td->type->containsPlaceholders())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfails[td] = complainAboutExtraneousPAMs(\"non-polymorphic type\", td, \"constructed\", /* printdef: */ true);\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(auto uvd = dcast(UnionVariantDefn, curcandidate))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// fails[td] = complainAboutExtraneousPAMs(\"non-polymorphic type\", td, \"constructed\", /* printdef: */ true);\n\t\t\t\t\t\t\tfails[td] = SimpleError::make(fs->loc(), \"type arguments should be specified on the union instead of the variant\")\n\t\t\t\t\t\t\t\t->append(ExampleMsg::make(strprintf(\"%s!<%s>::%s(...)\", uvd->parentUnion->bareName, pams.print(),\n\t\t\t\t\t\t\t\tuvd->variantName))\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tauto res = resolveConstructorCall(fs, callLoc, td, replacementArgs, pams);\n\t\t\t\t\tif(!res.isDefn())\n\t\t\t\t\t{\n\t\t\t\t\t\tfails[td] = res.error();\n\t\t\t\t\t\tdist = -1;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tcurcandidate = res.defn();\n\t\t\t\t\t\tstd::tie(dist, fails[td]) = std::make_tuple(0, nullptr);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfails[curcandidate] = SimpleError::make(fs->loc(), \"unsupported entity '%s'\", curcandidate->getKind());\n\t\t\t\t}\n\n\t\t\t\tif(dist == -1)\n\t\t\t\t\tcontinue;\n\n\t\t\t\telse if(dist < bestDist)\n\t\t\t\t\tfinals.clear(), finals.push_back({ curcandidate, replacementArgs, dist }), bestDist = dist;\n\n\t\t\t\telse if(dist == bestDist)\n\t\t\t\t\tfinals.push_back({ curcandidate, replacementArgs, dist });\n\t\t\t}\n\n\n\n\t\t\tif(finals.empty())\n\t\t\t{\n\t\t\t\tauto err = createErrorFromFailedCandidates(fs, callLoc, cands[0].first->id.name, cands[0].second,\n\t\t\t\t\tzfu::map(zfu::pairs(fails), [](auto p) -> std::pair<Locatable*, ErrorMsg*> {\n\t\t\t\t\t\treturn std::make_pair(p.first, p.second);\n\t\t\t\t\t}));\n\n\t\t\t\treturn { TCResult(err), { } };\n\t\t\t}\n\t\t\telse if(finals.size() > 1)\n\t\t\t{\n\t\t\t\t// check if all of the targets we found are virtual, and that they belong to the same class.\n\n\t\t\t\tbool virt = true;\n\t\t\t\tfir::ClassType* self = 0;\n\n\t\t\t\tDefn* ret = std::get<0>(finals[0]);\n\n\t\t\t\tfor(auto def : finals)\n\t\t\t\t{\n\t\t\t\t\tif(auto fd = dcast(sst::FunctionDefn, std::get<0>(def)); fd && fd->isVirtual)\n\t\t\t\t\t{\n\t\t\t\t\t\ticeAssert(fd->parentTypeForMethod);\n\t\t\t\t\t\ticeAssert(fd->parentTypeForMethod->isClassType());\n\n\t\t\t\t\t\tif(!self)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tself = fd->parentTypeForMethod->toClassType();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// check if they're co/contra variant\n\t\t\t\t\t\t\tauto ty = fd->parentTypeForMethod->toClassType();\n\n\t\t\t\t\t\t\t//* here we're just checking that 'ty' and 'self' are part of the same class hierarchy -- we don't really care about the method\n\t\t\t\t\t\t\t//* that we resolve being at the lowest or highest level of that hierarchy.\n\n\t\t\t\t\t\t\tif(!ty->hasParent(self) && !self->hasParent(ty))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvirt = false;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tvirt = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(virt)\n\t\t\t\t{\n\t\t\t\t\treturn { TCResult(ret), std::get<1>(finals[0]) };\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tauto err = SimpleError::make(callLoc, \"ambiguous call to function '%s', have %d candidates:\",\n\t\t\t\t\t\tcands[0].first->id.name, finals.size());\n\n\t\t\t\t\tfor(auto f : finals)\n\t\t\t\t\t{\n\t\t\t\t\t\terr->append(SimpleError::make(MsgType::Note, std::get<0>(f)->loc, \"possible target (overload distance %d):\", std::get<2>(f)));\n\t\t\t\t\t}\n\n\t\t\t\t\treturn { TCResult(err), { } };\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn { TCResult(std::get<0>(finals[0])), std::get<1>(finals[0]) };\n\t\t\t}\n\t\t}\n\t}\n}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/sizeof.cpp",
    "content": "// sizeof.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"pts.h\"\n#include \"errors.h\"\n#include \"ir/type.h\"\n#include \"typecheck.h\"\n\n#include \"memorypool.h\"\n\nTCResult ast::SizeofOp::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto ret = util::pool<sst::SizeofOp>(this->loc, fir::Type::getNativeWord());\n\n\tif(dcast(ast::LitNumber, this->expr))\n\t{\n\t\terror(this->expr, \"literal numbers cannot be sized\");\n\t}\n\n\tthis->expr->checkAsType = true;\n \tfir::Type* out = this->expr->typecheck(fs).expr()->type;\n\n\ticeAssert(out);\n\tret->typeToSize = out;\n\n\treturn TCResult(ret);\n}\n\n\nTCResult ast::TypeidOp::typecheck(sst::TypecheckState* fs, fir::Type* inferred)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto ret = util::pool<sst::TypeidOp>(this->loc, fir::Type::getNativeUWord());\n\n\tif(dcast(ast::LitNumber, this->expr))\n\t{\n\t\terror(this->expr, \"literal numbers cannot be typeid'd\");\n\t}\n\n\tthis->expr->checkAsType = true;\n \tfir::Type* out = this->expr->typecheck(fs).expr()->type;\n\n\ticeAssert(out);\n\tret->typeToId = out;\n\n\treturn TCResult(ret);\n}\n\n\n\n"
  },
  {
    "path": "source/typecheck/slice.cpp",
    "content": "// slice.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"ir/type.h\"\n\n#include \"memorypool.h\"\n\nbool sst::getMutabilityOfSliceOfType(fir::Type* ty)\n{\n\tif(ty->isStringType() || ty->isDynamicArrayType())\n\t\treturn true;\n\n\telse if(ty->isArrayType())\n\t\treturn false;\n\n\telse if(ty->isArraySliceType())\n\t\treturn ty->toArraySliceType()->isMutable();\n\n\telse if(ty->isPointerType())\n\t\treturn ty->isMutablePointer();\n\n\telse\n\t\terror(\"type '%s' does not have mutable variants\", ty);\n}\n\nTCResult ast::SliceOp::typecheck(sst::TypecheckState* fs, fir::Type* inferred)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tfs->pushAnonymousTree();\n\tdefer(fs->popTree());\n\n\tauto array = this->expr->typecheck(fs).expr();\n\tauto ty = array->type;\n\n\tfs->enterSubscript(array);\n\tdefer(fs->leaveSubscript());\n\n\tfir::Type* elm = 0;\n\tif(ty->isDynamicArrayType() || ty->isArraySliceType() || ty->isArrayType())\n\t\telm = ty->getArrayElementType();\n\n\telse if(ty->isStringType())\n\t\telm = fir::Type::getInt8();\n\n\telse if(ty->isPointerType())\n\t\telm = ty->getPointerElementType();\n\n\telse\n\t\terror(array, \"invalid type '%s' for slice operation\", ty);\n\n\tauto begin = this->start ? this->start->typecheck(fs, fir::Type::getNativeWord()).expr() : 0;\n\tauto end = this->end ? this->end->typecheck(fs, fir::Type::getNativeWord()).expr() : 0;\n\n\tif(begin && !begin->type->isIntegerType())\n\t\terror(begin, \"expected integer type for start index of slice; found '%s'\", begin->type);\n\n\tif(end && !end->type->isIntegerType())\n\t\terror(end, \"expected integer type for end index of slice; found '%s'\", end->type);\n\n\t//* how it goes:\n\t// 1. strings and dynamic arrays are always sliced mutably.\n\t// 2. slices of slices naturally inherit their mutability.\n\t// 3. arrays are sliced immutably.\n\t// 4. pointers inherit their mutability as well.\n\n\tbool ismut = sst::getMutabilityOfSliceOfType(ty);\n\n\tauto ret = util::pool<sst::SliceOp>(this->loc, fir::ArraySliceType::get(elm, ismut));\n\tret->expr = array;\n\tret->begin = begin;\n\tret->end = end;\n\n\treturn TCResult(ret);\n}\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/special.cpp",
    "content": "// misc.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"ir/type.h\"\n#include \"memorypool.h\"\n\nTCResult ast::TypeExpr::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tauto ret = sst::TypeExpr::make(this->loc, fs->convertParserTypeToFIR(this->type));\n\treturn TCResult(ret);\n}\n\nTCResult ast::MutabilityTypeExpr::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\terror(this, \"unable to typecheck mutability cast, this shouldn't happen!\");\n}\n\nTCResult ast::ImportStmt::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\t// nothing to check??\n\terror(this->loc, \"unexpected import statement\");\n}\n\nTCResult ast::SplatOp::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto inside = this->expr->typecheck(fs, infer).expr();\n\n\tif(!inside->type->isArraySliceType() && !inside->type->isArrayType() && !inside->type->isDynamicArrayType() && !inside->type->isTupleType())\n\t\treturn TCResult(SimpleError::make(this->loc, \"invalid use of splat operator on type '%s'\", inside->type));\n\n\tif(inside->type->isTupleType())\n\t\treturn TCResult(SimpleError::make(this->loc, \"splat operator on tuple not allowed in this context\"));\n\n\tauto ret = util::pool<sst::SplatExpr>(this->loc, fir::ArraySliceType::getVariadic(inside->type->getArrayElementType()));\n\tret->inside = inside;\n\n\treturn TCResult(ret);\n}\n\nTCResult ast::Parameterisable::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\treturn this->typecheck(fs, infer, { });\n}\n\n\nstatic util::hash_map<fir::Type*, sst::TypeExpr*> cache;\nsst::TypeExpr* sst::TypeExpr::make(const Location& l, fir::Type* t)\n{\n\tif(auto it = cache.find(t); it != cache.end())\n\t\treturn it->second;\n\n\treturn (cache[t] = util::pool<sst::TypeExpr>(l, t));\n}\n\nFnCallArgument FnCallArgument::make(const Location& l, const std::string& n, fir::Type* t, bool ignoreName)\n{\n\tauto te = sst::TypeExpr::make(l, t);\n\tauto ret = FnCallArgument(l, n, te, nullptr);\n\tret.ignoreName = ignoreName;\n\n\treturn ret;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/structs.cpp",
    "content": "// structs.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"pts.h\"\n#include \"errors.h\"\n#include \"ir/type.h\"\n#include \"typecheck.h\"\n\n#include <set>\n#include \"memorypool.h\"\n\nstatic void _checkFieldRecursion(sst::TypecheckState* fs, fir::Type* strty, fir::Type* field, const Location& floc, std::set<fir::Type*>& seeing);\nstatic void _checkTransparentFieldRedefinition(sst::TypecheckState* fs, sst::TypeDefn* defn, const std::vector<sst::StructFieldDefn*>& fields,\n\tutil::hash_map<std::string, Location>& seen);\n\n// used in typecheck/unions.cpp and typecheck/classes.cpp\nvoid checkFieldRecursion(sst::TypecheckState* fs, fir::Type* strty, fir::Type* field, const Location& floc)\n{\n\tstd::set<fir::Type*> seeing;\n\t_checkFieldRecursion(fs, strty, field, floc, seeing);\n}\n\nvoid checkTransparentFieldRedefinition(sst::TypecheckState* fs, sst::TypeDefn* defn, const std::vector<sst::StructFieldDefn*>& fields)\n{\n\tutil::hash_map<std::string, Location> seen;\n\t_checkTransparentFieldRedefinition(fs, defn, fields, seen);\n}\n\n// defined in typecheck/traits.cpp\nvoid checkTraitConformity(sst::TypecheckState* fs, sst::TypeDefn* defn);\n\n\n\nTCResult ast::StructDefn::generateDeclaration(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\n\tauto [ success, ret ] = this->checkForExistingDeclaration(fs, gmaps);\n\tif(!success)    return TCResult::getParametric();\n\telse if(ret)    return TCResult(ret);\n\n\tauto defnname = util::typeParamMapToString(this->name, gmaps);\n\tauto defn = util::pool<sst::StructDefn>(this->loc);\n\tdefn->bareName = this->name;\n\tdefn->attrs = this->attrs;\n\n\tdefn->id = Identifier(defnname, IdKind::Type);\n\tdefn->id.scope = this->enclosingScope;\n\tdefn->visibility = this->visibility;\n\tdefn->original = this;\n\tdefn->enclosingScope = this->enclosingScope;\n\tdefn->innerScope = this->enclosingScope.appending(defnname);\n\n\t// make all our methods be methods\n\tfor(auto m : this->methods)\n\t{\n\t\tm->parentType = this;\n\t\tm->enclosingScope = defn->innerScope;\n\t}\n\n\tauto str = fir::StructType::createWithoutBody(defn->id.convertToName(), /* isPacked: */ this->attrs.has(attr::PACKED));\n\tdefn->type = str;\n\n\tif(auto err = fs->checkForShadowingOrConflictingDefinition(defn, [](auto, auto) -> bool { return true; }))\n\t\treturn TCResult(err);\n\n\t// add it first so we can use it in the method bodies,\n\t// and make pointers to it\n\t{\n\t\tthis->enclosingScope.stree->addDefinition(defnname, defn, gmaps);\n\t\tfs->typeDefnMap[str] = defn;\n\t}\n\n\tthis->genericVersions.push_back({ defn, fs->getGenericContextStack() });\n\treturn TCResult(defn);\n}\n\nTCResult ast::StructDefn::typecheck(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto tcr = this->generateDeclaration(fs, infer, gmaps);\n\n\tif(tcr.isParametric()) return tcr;\n\n\tauto defn = dcast(sst::StructDefn, tcr.defn());\n\ticeAssert(defn);\n\n\tif(this->finishedTypechecking.find(defn) != this->finishedTypechecking.end())\n\t\treturn TCResult(defn);\n\n\tauto str = defn->type->toStructType();\n\ticeAssert(str);\n\n\tfor(auto t : this->bases)\n\t{\n\t\tauto base = fs->convertParserTypeToFIR(t);\n\t\tif(!base->isTraitType())\n\t\t\terror(this, \"struct '%s' can only implement traits, which '%s' is not\", this->name, base);\n\n\t\tauto tdef = dcast(sst::TraitDefn, fs->typeDefnMap[base]);\n\t\ticeAssert(tdef);\n\n\t\tdefn->traits.push_back(tdef);\n\t\tstr->addTraitImpl(tdef->type->toTraitType());\n\t}\n\n\tfs->teleportInto(defn->innerScope);\n\n\tstd::vector<std::pair<std::string, fir::Type*>> tys;\n\n\tfs->pushSelfContext(str);\n\t{\n\t\tfor(auto f : this->fields)\n\t\t{\n\t\t\tauto vdef = util::pool<ast::VarDefn>(std::get<1>(f));\n\t\t\tvdef->immut = false;\n\t\t\tvdef->name = std::get<0>(f);\n\t\t\tvdef->initialiser = nullptr;\n\t\t\tvdef->type = std::get<2>(f);\n\t\t\tvdef->isField = true;\n\n\t\t\tauto v = dcast(sst::StructFieldDefn, vdef->typecheck(fs).defn());\n\t\t\ticeAssert(v);\n\n\t\t\tif(v->id.name == \"_\")\n\t\t\t\tv->isTransparentField = true;\n\n\t\t\tdefn->fields.push_back(v);\n\t\t\ttys.push_back({ v->id.name, v->type });\n\n\t\t\tcheckFieldRecursion(fs, str, v->type, v->loc);\n\t\t}\n\n\t\t//* generate all the decls first so we can call methods out of order.\n\t\tfor(auto m : this->methods)\n\t\t{\n\t\t\tauto res = m->generateDeclaration(fs, str, { });\n\t\t\tif(res.isParametric())\n\t\t\t\tcontinue;\n\n\t\t\tauto decl = dcast(sst::FunctionDefn, res.defn());\n\t\t\ticeAssert(decl);\n\n\t\t\tdefn->methods.push_back(decl);\n\t\t}\n\n\t\tfor(auto m : this->methods)\n\t\t\tm->typecheck(fs, str, { });\n\t}\n\n\tcheckTransparentFieldRedefinition(fs, defn, defn->fields);\n\n\tfs->popSelfContext();\n\n\tstr->setBody(tys);\n\n\tfs->teleportOut();\n\n\tcheckTraitConformity(fs, defn);\n\n\tthis->finishedTypechecking.insert(defn);\n\treturn TCResult(defn);\n}\n\n\n\n\n\n\n\n\n\n\nstatic void _checkFieldRecursion(sst::TypecheckState* fs, fir::Type* strty, fir::Type* field, const Location& floc, std::set<fir::Type*>& seeing)\n{\n\tseeing.insert(strty);\n\n\tif(field == strty)\n\t{\n\t\tSimpleError::make(floc, \"composite type '%s' cannot contain a field of its own type; use a pointer.\", strty)\n\t\t\t->append(SimpleError::make(MsgType::Note, fs->typeDefnMap[strty]->loc, \"type '%s' was defined here:\", strty))\n\t\t\t->postAndQuit();\n\t}\n\telse if(seeing.find(field) != seeing.end())\n\t{\n\t\tSimpleError::make(floc, \"recursive definition of field with a non-pointer type; mutual recursion between types '%s' and '%s'\", field, strty)\n\t\t\t->append(SimpleError::make(MsgType::Note, fs->typeDefnMap[strty]->loc, \"type '%s' was defined here:\", strty))\n\t\t\t->postAndQuit();\n\t}\n\telse if(field->isClassType())\n\t{\n\t\tfor(auto f : field->toClassType()->getElements())\n\t\t\t_checkFieldRecursion(fs, field, f, floc, seeing);\n\t}\n\telse if(field->isStructType())\n\t{\n\t\tfor(auto f : field->toStructType()->getElements())\n\t\t\t_checkFieldRecursion(fs, field, f, floc, seeing);\n\t}\n\telse if(field->isRawUnionType())\n\t{\n\t\tfor(auto f : field->toRawUnionType()->getVariants())\n\t\t\t_checkFieldRecursion(fs, field, f.second, floc, seeing);\n\t}\n\n\t// ok, we should be fine...?\n}\n\nstatic void _checkTransparentFieldRedefinition(sst::TypecheckState* fs, sst::TypeDefn* defn, const std::vector<sst::StructFieldDefn*>& fields,\n\tutil::hash_map<std::string, Location>& seen)\n{\n\tfor(auto fld : fields)\n\t{\n\t\tif(fld->isTransparentField)\n\t\t{\n\t\t\tauto ty = fld->type;\n\t\t\tif(!ty->isRawUnionType() && !ty->isStructType())\n\t\t\t{\n\t\t\t\t// you can't have a transparentl field if it's not an aggregate type, lmao\n\t\t\t\terror(fld, \"transparent fields must have either a struct or raw-union type.\");\n\t\t\t}\n\n\t\t\tauto innerdef = fs->typeDefnMap[ty];\n\t\t\ticeAssert(innerdef);\n\n\t\t\tstd::vector<sst::StructFieldDefn*> flds;\n\t\t\tif(auto str = dcast(sst::StructDefn, innerdef); str)\n\t\t\t\tflds = str->fields;\n\n\t\t\telse if(auto unn = dcast(sst::RawUnionDefn, innerdef); unn)\n\t\t\t\tflds = zfu::map(unn->fields, zfu::pair_second()) + unn->transparentFields;\n\n\t\t\telse\n\t\t\t\terror(fs->loc(), \"what kind of type is this? '%s'\", ty);\n\n\t\t\t_checkTransparentFieldRedefinition(fs, innerdef, flds, seen);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif(auto it = seen.find(fld->id.name); it != seen.end())\n\t\t\t{\n\t\t\t\tSimpleError::make(fld->loc, \"redefinition of transparently accessible field '%s'\", fld->id.name)\n\t\t\t\t\t->append(SimpleError::make(MsgType::Note, it->second, \"previous definition was here:\"))\n\t\t\t\t\t->postAndQuit();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tseen[fld->id.name] = fld->loc;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/subscript.cpp",
    "content": "// subscript.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"ir/type.h\"\n#include \"memorypool.h\"\n\nTCResult ast::SubscriptOp::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tfs->pushAnonymousTree();\n\tdefer(fs->popTree());\n\n\tauto ls = this->expr->typecheck(fs).expr();\n\tfs->enterSubscript(ls);\n\tdefer(fs->leaveSubscript());\n\n\tauto rs = this->inside->typecheck(fs).expr();\n\n\t// check what's the type\n\tauto lt = ls->type;\n\tauto rt = rs->type;\n\n\tif((rt->isConstantNumberType() && rt->toConstantNumberType()->isFloating()) && !rt->isIntegerType())\n\t\terror(this->inside, \"subscript index must be an integer type, found '%s'\", rt);\n\n\n\tfir::Type* res = 0;\n\n\t// check what it is, then\n\tif(lt->isDynamicArrayType())\tres = lt->toDynamicArrayType()->getElementType();\n\telse if(lt->isArraySliceType())\tres = lt->toArraySliceType()->getElementType();\n\telse if(lt->isPointerType())\tres = lt->getPointerElementType();\n\telse if(lt->isArrayType())\t\tres = lt->toArrayType()->getElementType();\n\telse if(lt->isStringType())\t\tres = fir::Type::getInt8();\n\telse\t\t\t\t\t\t\terror(this->expr, \"cannot subscript type '%s'\", lt);\n\n\ticeAssert(res);\n\tauto ret = util::pool<sst::SubscriptOp>(this->loc, res);\n\tret->expr = ls;\n\tret->inside = rs;\n\n\treturn TCResult(ret);\n}\n\n\nTCResult ast::SubscriptDollarOp::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tif(!fs->isInSubscript())\n\t\terror(this, \"invalid use of '$' in non-subscript context\");\n\n\telse if(auto arr = fs->getCurrentSubscriptArray();\n\t\tarr->type->isPointerType() || !(arr->type->isArraySliceType() || arr->type->isArrayType() || arr->type->isStringType()\n\t\t\t|| arr->type->isDynamicArrayType()))\n\t{\n\t\tSpanError::make(SimpleError::make(this->loc, \"invalid use of '$' on subscriptee with %stype '%s'\",\n\t\t\tarr->type->isPointerType() ? \"pointer \" : \"\", arr->type))\n\t\t\t->add(util::ESpan(arr->loc, \"here\"))->postAndQuit();\n\t}\n\n\treturn TCResult(util::pool<sst::SubscriptDollarOp>(this->loc, fir::Type::getNativeWord()));\n}\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/toplevel.cpp",
    "content": "// toplevel.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include <optional>\n\n#include \"defs.h\"\n#include \"sst.h\"\n#include \"ast.h\"\n#include \"pts.h\"\n#include \"errors.h\"\n#include \"parser.h\"\n#include \"frontend.h\"\n#include \"typecheck.h\"\n#include \"string_consts.h\"\n\n#include \"ir/type.h\"\n#include \"memorypool.h\"\n\nusing namespace ast;\n\nnamespace sst\n{\n\tstruct OsStrings\n\t{\n\t\tstd::string name;\n\t\tstd::string vendor;\n\t};\n\n\tstatic OsStrings getOsStrings();\n\tstatic void generatePreludeDefinitions(TypecheckState* fs, const std::string& filename);\n\n\tstatic bool definitionsConflict(const sst::Defn* a, const sst::Defn* b)\n\t{\n\t\tauto fda = dcast(const sst::FunctionDecl, a);\n\t\tauto fdb = dcast(const sst::FunctionDecl, b);\n\n\t\tauto uva = dcast(const sst::UnionVariantDefn, a);\n\t\tauto uvb = dcast(const sst::UnionVariantDefn, b);\n\n\t\tif(fda && fdb)\n\t\t{\n\t\t\treturn sst::isDuplicateOverload(fda->params, fdb->params);\n\t\t}\n\t\telse if(uva && uvb)\n\t\t{\n\t\t\treturn uva->parentUnion == uvb->parentUnion;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tstruct ExportMetadata\n\t{\n\t\tLocation loc;\n\t\tstd::string module;\n\t\tstd::string imported;\n\t};\n\n\tstatic void checkConflictingDefinitions(Location loc, const char* kind, const sst::StateTree* base, const sst::StateTree* branch,\n\t\tstd::optional<Location> importer = { }, std::optional<ExportMetadata> exporter = { })\n\t{\n\t\tfor(const auto& [ name, defns ] : base->definitions)\n\t\t{\n\t\t\tif(auto it = branch->definitions.find(name); it != branch->definitions.end())\n\t\t\t{\n\t\t\t\tfor(auto d1 : defns)\n\t\t\t\t{\n\t\t\t\t\tfor(auto d2 : it->second)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!definitionsConflict(d1, d2))\n\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\tauto error = SimpleError::make(MsgType::Error, loc, \"'%s' here introduces duplicate definitions:\", kind);\n\n\t\t\t\t\t\tif(d1 == d2)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif(importer && exporter)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\terror->append(SimpleError::make(MsgType::Note, exporter->loc,\n\t\t\t\t\t\t\t\t\t\"this public import (from the imported module '%s') brings '%s' into scope ...\",\n\t\t\t\t\t\t\t\t\texporter->module, exporter->imported));\n\n\t\t\t\t\t\t\t\terror->append(SimpleError::make(MsgType::Note, *importer,\n\t\t\t\t\t\t\t\t\t\"... which conflicts with this using/import statement here:\"));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if(importer)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\terror->append(SimpleError::make(MsgType::Note, *importer,\n\t\t\t\t\t\t\t\t\t\"most likely caused by this import here:\"));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if(exporter)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\terror->append(SimpleError::make(MsgType::Note, exporter->loc,\n\t\t\t\t\t\t\t\t\t\"most likely caused by this public import here, in module '%s':\", exporter->module));\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\terror->append(SimpleError::make(MsgType::Note, d1->loc, \"for reference, here is the (first) \"\n\t\t\t\t\t\t\t\t\"conflicting definition:\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\terror->append(SimpleError::make(MsgType::Note, d1->loc, \"first definition here:\"))\n\t\t\t\t\t\t\t\t->append(SimpleError::make(MsgType::Note, d2->loc, \"second definition here:\"));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\terror->postAndQuit();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tstatic std::optional<ExportMetadata> getExportInfo(const sst::StateTree* base, const sst::StateTree* branch)\n\t{\n\t\tif(auto it = base->reexportMetadata.find(branch); it != base->reexportMetadata.end())\n\t\t{\n\t\t\treturn ExportMetadata {\n\t\t\t\t.loc = it->second,\n\t\t\t\t.module = base->moduleName,\n\t\t\t\t.imported = branch->name\n\t\t\t};\n\t\t}\n\t\treturn { };\n\t}\n\n\tstatic void checkExportsRecursively(const Location& loc, const char* kind, sst::StateTree* base, sst::StateTree* branch,\n\t\tstd::optional<Location> importer = { }, std::optional<ExportMetadata> exporter = { })\n\t{\n\t\tif(branch->isAnonymous || branch->isCompilerGenerated)\n\t\t\treturn;\n\n\t\tcheckConflictingDefinitions(loc, kind, base, branch, importer, exporter);\n\n\t\tfor(auto exp : base->reexports)\n\t\t\tcheckExportsRecursively(loc, kind, exp, branch, importer, getExportInfo(base, exp));\n\t}\n\n\tvoid mergeExternalTree(const Location& loc, const char* kind, sst::StateTree* base, sst::StateTree* branch)\n\t{\n\t\tif(branch->isAnonymous || branch->isCompilerGenerated)\n\t\t\treturn;\n\n\t\t// first check conflicts for this level:\n\t\tcheckConflictingDefinitions(loc, kind, base, branch);\n\n\t\t// then, for every one of *our* imports:\n\t\tfor(auto import : base->imports)\n\t\t{\n\t\t\tstd::optional<Location> importer;\n\t\t\tif(auto it = base->importMetadata.find(import); it != base->importMetadata.end())\n\t\t\t\timporter = it->second;\n\n\t\t\t// check that the new tree doesn't trample over it.\n\t\t\tcheckConflictingDefinitions(loc, kind, import, branch, importer);\n\n\t\t\t// then, recursively check every single re-export on *our* side for conflicts:\n\t\t\tfor(auto rexp : import->reexports)\n\t\t\t\tcheckExportsRecursively(loc, kind, rexp, branch, importer, getExportInfo(import, rexp));\n\n\t\t\t// then, also check that, for every one of *their* public imports:\n\t\t\tfor(auto rexp : branch->reexports)\n\t\t\t{\n\t\t\t\tauto exportInfo = getExportInfo(import, rexp);\n\n\t\t\t\t// it doesn't trample with anything in our tree,\n\t\t\t\tcheckConflictingDefinitions(loc, kind, base, rexp, importer, exportInfo);\n\n\t\t\t\t// and it doesn't conflict with anything in our imports.\n\t\t\t\tcheckConflictingDefinitions(loc, kind, import, rexp, importer, exportInfo);\n\n\t\t\t\t// finally, also check that, for every one of *our* imports' re-exports,\n\t\t\t\tfor(auto rexp2 : import->reexports)\n\t\t\t\t{\n\t\t\t\t\tauto exportInfo = getExportInfo(import, rexp2);\n\n\t\t\t\t\t// check that *they* don't trample anything:\n\t\t\t\t\tcheckConflictingDefinitions(loc, kind, rexp2, branch, importer, exportInfo);\n\n\t\t\t\t\t// and neither does their reexport:\n\t\t\t\t\tcheckConflictingDefinitions(loc, kind, rexp2, rexp, importer, exportInfo);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// no problem -- attach the trees\n\t\tbase->imports.push_back(branch);\n\t\tbase->importMetadata[branch] = loc;\n\n\t\t// merge the subtrees as well.\n\t\tfor(const auto& [ name, tr ] : branch->subtrees)\n\t\t{\n\t\t\tif(tr->isCompilerGenerated || tr->isAnonymous)\n\t\t\t\tcontinue;\n\n\t\t\tmergeExternalTree(loc, kind, base->findOrCreateSubtree(name), tr);\n\t\t}\n\t}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\tDefinitionTree* typecheck(frontend::CollectorState* cs, const parser::ParsedFile& file,\n\t\tconst std::vector<std::pair<frontend::ImportThing, DefinitionTree*>>& imports, bool addPreludeDefinitions)\n\t{\n\t\tauto tree = new StateTree(file.moduleName, nullptr);\n\t\ttree->moduleName = file.moduleName;\n\n\t\tauto fs = new TypecheckState(tree);\n\n\t\tfor(auto [ ithing, import ] : imports)\n\t\t{\n\t\t\tauto ias = ithing.importAs;\n\t\t\tif(ias.empty())\n\t\t\t\tias = cs->parsed[ithing.name].modulePath + cs->parsed[ithing.name].moduleName;\n\n\t\t\tStateTree* insertPoint = tree;\n\t\t\tif(ias.size() == 1 && ias[0] == \"_\")\n\t\t\t{\n\t\t\t\t// do nothing.\n\t\t\t\t// insertPoint = tree;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tStateTree* curinspt = insertPoint;\n\n\t\t\t\t// iterate through the import-as list, which is a list of nested scopes to import into\n\t\t\t\t// eg we can `import foo as some::nested::namespace`, which means we need to create\n\t\t\t\t// the intermediate trees.\n\n\t\t\t\tfor(const auto& impas : ias)\n\t\t\t\t{\n\t\t\t\t\tif(impas == curinspt->name)\n\t\t\t\t\t{\n\t\t\t\t\t\t// skip it.\n\t\t\t\t\t}\n\t\t\t\t\telse if(auto it = curinspt->subtrees.find(impas); it != curinspt->subtrees.end())\n\t\t\t\t\t{\n\t\t\t\t\t\tcurinspt = it->second;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tauto newinspt = curinspt->findOrCreateSubtree(impas);\n\t\t\t\t\t\tcurinspt->subtrees[impas] = newinspt;\n\n\t\t\t\t\t\tcurinspt = newinspt;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tinsertPoint = curinspt;\n\t\t\t\tinsertPoint->proxyOf = import->base;\n\t\t\t}\n\n\t\t\ticeAssert(insertPoint);\n\t\t\tmergeExternalTree(ithing.loc, \"import\", insertPoint, import->base);\n\n\t\t\tif(ithing.pubImport)\n\t\t\t{\n\t\t\t\tinsertPoint->reexports.push_back(import->base);\n\t\t\t\tinsertPoint->reexportMetadata[import->base] = ithing.loc;\n\t\t\t}\n\n\t\t\tfs->dtree->thingsImported.insert(ithing.name);\n\t\t\tfs->dtree->typeDefnMap.insert(import->typeDefnMap.begin(), import->typeDefnMap.end());\n\n\t\t\t// merge the things. hopefully there are no conflicts????\n\t\t\t// TODO: check for conflicts!\n\t\t\tfs->dtree->compilerSupportDefinitions.insert(import->compilerSupportDefinitions.begin(),\n\t\t\t\timport->compilerSupportDefinitions.end());\n\t\t}\n\n\t\tif(addPreludeDefinitions)\n\t\t\tgeneratePreludeDefinitions(fs, file.name);\n\n\t\t// handle exception here:\n\t\ttry {\n\t\t\tauto tns = dcast(NamespaceDefn, file.root->typecheck(fs).stmt());\n\t\t\ticeAssert(tns);\n\n\t\t\ttns->name = file.moduleName;\n\n\t\t\tfs->dtree->topLevel = tns;\n\t\t}\n\t\tcatch(ErrorException& ee)\n\t\t{\n\t\t\tee.err->postAndQuit();\n\t\t}\n\n\t\treturn fs->dtree;\n\t}\n\n\n\tstatic OsStrings getOsStrings()\n\t{\n\t\t// TODO: handle cygwin/msys/mingw???\n\t\t// like how do we want to expose these? at the end of the day the os is still windows...\n\n\t\t// TODO: this should be set for the target we are compiling FOR, so it definitely\n\t\t// cannot be done using ifdefs!!!!!!!!!!\n\n\t\tOsStrings ret;\n\n\t\t#if defined(_WIN32)\n\t\t\tret.name = \"windows\";\n\t\t\tret.vendor = \"microsoft\";\n\t\t#elif __MINGW__\n\t\t\tret.name = \"mingw\";\n\t\t#elif __CYGWIN__\n\t\t\tret.name = \"cygwin\";\n\t\t#elif __APPLE__\n\t\t\tret.vendor = \"apple\";\n\t\t\t#include \"TargetConditionals.h\"\n\t\t\t#if TARGET_IPHONE_SIMULATOR\n\t\t\t\tret.name = \"iossimulator\";\n\t\t\t#elif TARGET_OS_IOS\n\t\t\t\tret.name = \"ios\";\n\t\t\t#elif TARGET_OS_WATCH\n\t\t\t\tret.name = \"watchos\";\n\t\t\t#elif TARGET_OS_TV\n\t\t\t\tret.name = \"tvos\";\n\t\t\t#elif TARGET_OS_OSX\n\t\t\t\tret.name = \"macos\";\n\t\t\t#else\n\t\t\t\t#error \"unknown apple operating system\"\n\t\t\t#endif\n\t\t#elif __ANDROID__\n\t\t\tret.vendor = \"google\";\n\t\t\tret.name = \"android\";\n\t\t#elif __linux__ || __linux || linux\n\t\t\tret.name = \"linux\";\n\t\t#elif __FreeBSD__\n\t\t\tret.name = \"freebsd\";\n\t\t#elif __OpenBSD__\n\t\t\tret.name = \"openbsd\";\n\t\t#elif __NetBSD__\n\t\t\tret.name = \"netbsd\";\n\t\t#elif __DragonFly__\n\t\t\tret.name = \"dragonflybsd\";\n\t\t#elif __unix__\n\t\t\tret.name = \"unix\";\n\t\t#elif defined(_POSIX_VERSION)\n\t\t\tret.name = \"posix\";\n\t\t#endif\n\n\t\treturn ret;\n\t}\n\n\tstatic void generatePreludeDefinitions(TypecheckState* fs, const std::string& filename)\n\t{\n\t\tauto loc = Location();\n\t\tloc.fileID = frontend::getFileIDFromFilename(filename);\n\n\t\tauto strings = getOsStrings();\n\n\t\tfs->pushTree(\"os\");\n\t\tfs->stree->isCompilerGenerated = true;\n\n\t\tdefer(fs->popTree());\n\n\t\tauto strty = fir::Type::getCharSlice(false);\n\n\t\t{\n\t\t\t// add the name\n\t\t\tauto name_def = util::pool<sst::VarDefn>(loc);\n\t\t\tname_def->id = Identifier(\"name\", IdKind::Name);\n\t\t\tname_def->type = strty;\n\t\t\tname_def->global = true;\n\t\t\tname_def->immutable = true;\n\t\t\tname_def->visibility = VisibilityLevel::Private;\n\n\t\t\tauto s = util::pool<sst::LiteralString>(loc, strty);\n\t\t\ts->str = strings.name;\n\n\t\t\tname_def->init = s;\n\t\t\tfs->stree->addDefinition(\"name\", name_def);\n\t\t}\n\t\t{\n\t\t\t// add the name\n\t\t\tauto vendor_def = util::pool<sst::VarDefn>(loc);\n\t\t\tvendor_def->id = Identifier(\"vendor\", IdKind::Name);\n\t\t\tvendor_def->type = strty;\n\t\t\tvendor_def->global = true;\n\t\t\tvendor_def->immutable = true;\n\t\t\tvendor_def->visibility = VisibilityLevel::Private;\n\n\t\t\tauto s = util::pool<sst::LiteralString>(loc, strty);\n\t\t\ts->str = strings.vendor;\n\n\t\t\tvendor_def->init = s;\n\t\t\tfs->stree->addDefinition(\"vendor\", vendor_def);\n\t\t}\n\t}\n}\n\n\nstatic void visitDeclarables(sst::TypecheckState* fs, ast::TopLevelBlock* top)\n{\n\tfor(auto stmt : top->statements)\n\t{\n\t\tif(auto decl = dcast(ast::Parameterisable, stmt))\n\t\t{\n\t\t\tdecl->enclosingScope = fs->scope();\n\t\t\tdecl->generateDeclaration(fs, 0, { });\n\t\t}\n\n\t\telse if(auto ffd = dcast(ast::ForeignFuncDefn, stmt))\n\t\t\tffd->typecheck(fs);\n\n\t\telse if(auto ns = dcast(ast::TopLevelBlock, stmt))\n\t\t{\n\t\t\tfs->pushTree(ns->name);\n\t\t\tvisitDeclarables(fs, ns);\n\t\t\tfs->popTree();\n\t\t}\n\t}\n}\n\n\nTCResult ast::TopLevelBlock::typecheck(sst::TypecheckState* fs, fir::Type* inferred)\n{\n\tauto ret = util::pool<sst::NamespaceDefn>(this->loc);\n\n\tif(this->name != \"\")\n\t\tfs->pushTree(this->name);\n\n\tsst::StateTree* tree = fs->stree;\n\n\tif(!fs->isInFunctionBody())\n\t{\n\t\t// visit all functions first, to get out-of-order calling -- but only at the namespace level, not inside functions.\n\t\t// once we're in function-body-land, everything should be imperative-driven, and you shouldn't\n\t\t// be able to see something before it is defined/declared\n\n\t\tvisitDeclarables(fs, this);\n\t}\n\n\n\tfor(auto stmt : this->statements)\n\t{\n\t\tif(dcast(ast::ImportStmt, stmt))\n\t\t\tcontinue;\n\n\t\tauto tcr = stmt->typecheck(fs);\n\t\tif(tcr.isError())\n\t\t\treturn TCResult(tcr.error());\n\n\t\telse if(!tcr.isParametric() && !tcr.isDummy())\n\t\t\tret->statements.push_back(tcr.stmt());\n\n\t\tif(tcr.isDefn() && tcr.defn()->visibility == VisibilityLevel::Public)\n\t\t\ttree->exports.push_back(tcr.defn());\n\n\t\t// check for compiler support so we can add it to the big list of things.\n\t\tif((tcr.isStmt() || tcr.isDefn()) && tcr.stmt()->attrs.has(strs::attrs::COMPILER_SUPPORT))\n\t\t{\n\t\t\tif(!tcr.isDefn())\n\t\t\t\terror(tcr.stmt(), \"@compiler_support can only be applied to definitions\");\n\n\t\t\tauto ua = tcr.stmt()->attrs.get(strs::attrs::COMPILER_SUPPORT);\n\t\t\ticeAssert(!ua.name.empty() && ua.args.size() == 1);\n\n\t\t\tfs->dtree->compilerSupportDefinitions[ua.args[0]] = tcr.defn();\n\t\t}\n\t}\n\n\tif(this->name != \"\")\n\t\tfs->popTree();\n\n\tret->name = this->name;\n\n\treturn TCResult(ret);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/traits.cpp",
    "content": "// traits.cpp\n// Copyright (c) 2019, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n#include \"polymorph.h\"\n\n#include \"memorypool.h\"\n#include \"ir/type.h\"\n\n\nTCResult ast::TraitDefn::generateDeclaration(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto [ success, ret ] = this->checkForExistingDeclaration(fs, gmaps);\n\tif(!success)    return TCResult::getParametric();\n\telse if(ret)    return TCResult(ret);\n\n\tauto defnname = util::typeParamMapToString(this->name, gmaps);\n\tauto defn = util::pool<sst::TraitDefn>(this->loc);\n\tdefn->bareName = this->name;\n\n\tdefn->attrs = this->attrs;\n\tdefn->id = Identifier(defnname, IdKind::Type);\n\tdefn->id.scope = this->enclosingScope;\n\tdefn->visibility = this->visibility;\n\tdefn->original = this;\n\tdefn->enclosingScope = this->enclosingScope;\n\tdefn->innerScope = this->enclosingScope.appending(defnname);\n\n\t// make all our methods be methods\n\tfor(auto m : this->methods)\n\t{\n\t\tm->parentType = this;\n\t\tm->enclosingScope = defn->innerScope;\n\t}\n\n\tauto str = fir::TraitType::create(defn->id.convertToName());\n\tdefn->type = str;\n\n\tif(auto err = fs->checkForShadowingOrConflictingDefinition(defn, [](auto, auto) -> bool { return true; }))\n\t\treturn TCResult(err);\n\n\t// add it first so we can use it in the method bodies,\n\t// and make pointers to it\n\t{\n\t\tdefn->enclosingScope.stree->addDefinition(defnname, defn, gmaps);\n\t\tfs->typeDefnMap[str] = defn;\n\t}\n\n\tthis->genericVersions.push_back({ defn, fs->getGenericContextStack() });\n\treturn TCResult(defn);\n}\n\nTCResult ast::TraitDefn::typecheck(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto tcr = this->generateDeclaration(fs, infer, gmaps);\n\n\tif(tcr.isParametric()) return tcr;\n\n\tauto defn = dcast(sst::TraitDefn, tcr.defn());\n\ticeAssert(defn);\n\n\tif(this->finishedTypechecking.find(defn) != this->finishedTypechecking.end())\n\t\treturn TCResult(defn);\n\n\tauto trt = defn->type->toTraitType();\n\ticeAssert(trt);\n\n\tfs->teleportInto(defn->innerScope);\n\tfs->pushSelfContext(trt);\n\n\tstd::vector<std::pair<std::string, fir::FunctionType*>> meths;\n\n\tfor(auto m : this->methods)\n\t{\n\t\t// make sure we don't have bodies -- for now!\n\t\ticeAssert(m->body == 0);\n\n\t\tauto res = m->generateDeclaration(fs, 0, { });\n\t\tif(res.isParametric())\n\t\t\tcontinue;\n\n\t\tauto decl = dcast(sst::FunctionDecl, res.defn());\n\t\ticeAssert(decl);\n\n\t\tdefn->methods.push_back(decl);\n\t\tmeths.push_back({ m->name, decl->type->toFunctionType() });\n\t}\n\n\ttrt->setMethods(meths);\n\n\tfs->popSelfContext();\n\tfs->teleportOut();\n\n\tthis->finishedTypechecking.insert(defn);\n\treturn TCResult(defn);\n}\n\n\n\n\n\n\n\n\n// used by typecheck/structs.cpp and typecheck/classes.cpp\nstatic bool _checkFunctionTypesMatch(fir::Type* trait, fir::Type* type, fir::FunctionType* required, fir::FunctionType* candidate)\n{\n\tauto as = required->getArgumentTypes() + required->getReturnType();\n\tauto bs = candidate->getArgumentTypes() + candidate->getReturnType();\n\n\t// all candidates must have a self!!\n\ticeAssert(as.size() > 0 && bs.size() > 0);\n\tif(as.size() != bs.size())\n\t\treturn false;\n\n\tfor(size_t i = 0; i < as.size(); i++)\n\t{\n\t\tauto ax = as[i];\n\t\tauto bx = bs[i];\n\n\t\t// TODO: wtf is this doing?!\n\t\tif(ax != bx)\n\t\t{\n\t\t\tauto [ abase, atrfs ] = sst::poly::internal::decomposeIntoTransforms(ax, SIZE_MAX);\n\t\t\tauto [ bbase, btrfs ] = sst::poly::internal::decomposeIntoTransforms(bx, SIZE_MAX);\n\n\t\t\tif(atrfs != btrfs)\n\t\t\t\treturn false;\n\n\t\t\tif(abase != trait || bbase != type)\n\t\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n// TODO: needs to handle extensions!!!\nvoid checkTraitConformity(sst::TypecheckState* fs, sst::TypeDefn* defn)\n{\n\tstd::vector<sst::TraitDefn*> traits;\n\tutil::hash_map<std::string, std::vector<sst::FunctionDecl*>> methods;\n\n\tif(auto cls = dcast(sst::ClassDefn, defn))\n\t{\n\t\tfor(auto m : cls->methods)\n\t\t\tmethods[m->id.name].push_back(m);\n\n\t\terror(\"wait a bit\");\n\t}\n\telse if(auto str = dcast(sst::StructDefn, defn))\n\t{\n\t\tfor(auto m : str->methods)\n\t\t\tmethods[m->id.name].push_back(m);\n\n\t\ttraits = str->traits;\n\t}\n\telse\n\t{\n\t\treturn;\n\t}\n\n\n\t// make this a little less annoying: report errors by trait, so all the missing methods for a trait are given at once\n\tfor(auto trait : traits)\n\t{\n\t\tstd::vector<std::tuple<Location, std::string, fir::FunctionType*>> missings;\n\t\tfor(auto meth : trait->methods)\n\t\t{\n\t\t\tauto cands = methods[meth->id.name];\n\t\t\tbool found = false;\n\n\t\t\tfor(auto cand : cands)\n\t\t\t{\n\t\t\t\t// c++ really fucking needs named arguments!!\n\t\t\t\tif(_checkFunctionTypesMatch(trait->type, defn->type,\n\t\t\t\t\t/* required: */ meth->type->toFunctionType(),\n\t\t\t\t\t/* candidate: */ cand->type->toFunctionType()\n\t\t\t\t))\n\t\t\t\t{\n\t\t\t\t\tfound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(!found)\n\t\t\t\tmissings.push_back({ meth->loc, meth->id.name, meth->type->toFunctionType() });\n\t\t}\n\n\t\tif(missings.size() > 0)\n\t\t{\n\t\t\tauto err = SimpleError::make(defn->loc, \"type '%s' does not conform to trait '%s'\",\n\t\t\t\tdefn->id.name, trait->id.name);\n\n\t\t\tfor(const auto& m : missings)\n\t\t\t{\n\t\t\t\terr->append(SimpleError::make(MsgType::Note, std::get<0>(m), \"missing implementation for method '%s': %s:\",\n\t\t\t\t\tstd::get<1>(m), std::get<2>(m)));\n\t\t\t}\n\n\t\t\terr->append(\n\t\t\t\tSimpleError::make(MsgType::Note, trait->loc, \"trait '%s' was defined here:\", trait->id.name)\n\t\t\t)->postAndQuit();\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/type.cpp",
    "content": "// type.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"pts.h\"\n#include \"errors.h\"\n#include \"ir/type.h\"\n#include \"typecheck.h\"\n\n#include \"resolver.h\"\n#include \"polymorph.h\"\n\n#include <deque>\n\nnamespace sst\n{\n\tfir::Type* inferCorrectTypeForLiteral(fir::ConstantNumberType* type)\n\t{\n\t\tauto ty = type->toConstantNumberType();\n\t\t{\n\t\t\tif(ty->isFloating())\n\t\t\t{\n\t\t\t\tif(ty->getMinBits() <= fir::Type::getFloat64()->getBitWidth())\n\t\t\t\t\treturn fir::Type::getFloat64();\n\n\t\t\t\telse if(ty->getMinBits() <= fir::Type::getFloat128()->getBitWidth())\n\t\t\t\t\treturn fir::Type::getFloat128();\n\n\t\t\t\telse\n\t\t\t\t\terror(\"float overflow\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif(ty->getMinBits() <= fir::Type::getNativeWord()->getBitWidth() - 1)\n\t\t\t\t\treturn fir::Type::getNativeWord();\n\n\t\t\t\telse if(!ty->isSigned() && ty->getMinBits() <= fir::Type::getNativeUWord()->getBitWidth())\n\t\t\t\t\treturn fir::Type::getNativeUWord();\n\n\t\t\t\telse\n\t\t\t\t\terror(\"int overflow\");\n\t\t\t}\n\t\t}\n\t}\n\n\n\tstatic ErrorMsg* _complainNoParentScope(TypecheckState* fs, const std::string& top)\n\t{\n\t\treturn SimpleError::make(fs->loc(), \"invalid use of '^' at the topmost scope '%s'\", top);\n\t}\n\n\n\tstatic StateTree* recursivelyFindTreeUpwards(TypecheckState* fs, const std::string& name)\n\t{\n\t\tauto from = fs->stree;\n\n\t\tif(name == \"^\")\n\t\t{\n\t\t\tif(!from->parent)\n\t\t\t\t_complainNoParentScope(fs, from->name)->postAndQuit();\n\n\t\t\t// move to our parent scope.\n\t\t\twhile(from->parent && from->isAnonymous)\n\t\t\t\tfrom = from->parent;\n\n\t\t\treturn from;\n\t\t}\n\n\t\twhile(from)\n\t\t{\n\t\t\tif(from->name == name)\n\t\t\t\treturn from;\n\n\t\t\telse if(auto it = from->subtrees.find(name); it != from->subtrees.end())\n\t\t\t\treturn it->second;\n\n\t\t\tfrom = from->parent;\n\t\t}\n\n\t\treturn 0;\n\t}\n\n\n\tfir::Type* TypecheckState::convertParserTypeToFIR(pts::Type* pt, bool allowFail)\n\t{\n\t\t//* note: 'allowFail' allows failure when we *don't find anything*\n\t\t//* but if we find something _wrong_, then we will always fail.\n\n\t\ticeAssert(pt);\n\t\tthis->pushLoc(pt->loc);\n\t\tdefer(this->popLoc());\n\n\t\tif(pt->isNamedType())\n\t\t{\n\t\t\tauto builtin = fir::Type::fromBuiltin(pt->toNamedType()->str());\n\t\t\tif(builtin)\n\t\t\t{\n\t\t\t\treturn builtin;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto name = pt->toNamedType()->name;\n\t\t\t\tif(name == \"self\")\n\t\t\t\t{\n\t\t\t\t\tif(!this->hasSelfContext())\n\t\t\t\t\t\terror(this->loc(), \"invalid use of 'self' type while not in method body\");\n\n\t\t\t\t\telse\n\t\t\t\t\t\treturn this->getCurrentSelfContext();\n\t\t\t\t}\n\n\n\t\t\t\tauto returnTheThing = [this, pt](StateTree* tree, const std::string& name, bool scoped, bool allowFail) -> fir::Type* {\n\n\t\t\t\t\tif(auto gmt = this->findGenericMapping(name, true))\n\t\t\t\t\t\treturn gmt;\n\n\t\t\t\t\tstd::vector<Defn*> defs;\n\n\t\t\t\t\tif(scoped)  defs = tree->getDefinitionsWithName(name);\n\t\t\t\t\telse        defs = this->getDefinitionsWithName(name);\n\n\t\t\t\t\tif(defs.empty())\n\t\t\t\t\t{\n\t\t\t\t\t\t// try generic defs.\n\t\t\t\t\t\tStateTree* str = (scoped ? tree : this->stree);\n\t\t\t\t\t\tstd::vector<ast::Parameterisable*> gdefs;\n\t\t\t\t\t\twhile(str && (gdefs = str->getUnresolvedGenericDefnsWithName(name)).size() == 0)\n\t\t\t\t\t\t\tstr = (scoped ? 0 : str->parent);   // if we're scoped, we can't go upwards.\n\n\t\t\t\t\t\tif(gdefs.empty())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif(allowFail)   return 0;\n\t\t\t\t\t\t\telse            error(this->loc(), \"no type named '%s' in scope '%s'\", name, tree->name);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(gdefs.size() > 1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tauto err = SimpleError::make(this->loc(), \"ambiguous reference to entity '%s' in scope\", name);\n\t\t\t\t\t\t\tfor(auto d : gdefs)\n\t\t\t\t\t\t\t\terr->append(SimpleError::make(MsgType::Note, d->loc, \"possible reference:\"));\n\n\t\t\t\t\t\t\terr->postAndQuit();\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t// TODO: not re-entrant either.\n\t\t\t\t\t\tauto restore = this->stree;\n\n\t\t\t\t\t\tthis->stree = (scoped ? tree : str);\n\t\t\t\t\t\ticeAssert(this->stree);\n\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tauto gdef = gdefs[0];\n\t\t\t\t\t\t\ticeAssert(gdef);\n\n\t\t\t\t\t\t\tauto atd = dcast(ast::TypeDefn, gdef);\n\t\t\t\t\t\t\tif(!atd) error(this->loc(), \"entity '%s' is not a type\", name);\n\n\t\t\t\t\t\t\tif(pt->toNamedType()->genericMapping.empty())\n\t\t\t\t\t\t\t\terror(this->loc(), \"parametric type '%s' cannot be referenced without type arguments\", pt->toNamedType()->name);\n\n\t\t\t\t\t\t\t// right, now we instantiate it.\n\t\t\t\t\t\t\tauto [ mapping, err ] = sst::resolver::misc::canonicalisePolyArguments(this, gdef, pt->toNamedType()->genericMapping);\n\n\t\t\t\t\t\t\tif(err != nullptr)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\terr->prepend(BareError::make(\"mismatched type arguments to instantiation of polymorphic type '%s':\", gdef->name)\n\t\t\t\t\t\t\t\t\t)->postAndQuit();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// types generally cannot be overloaded, so it doesn't make sense for it to be SFINAE-ed.\n\t\t\t\t\t\t\t// unwrapping it will post the error if any.\n\t\t\t\t\t\t\tauto td = poly::fullyInstantiatePolymorph(this, atd, mapping).defn();\n\n\t\t\t\t\t\t\tthis->stree = restore;\n\t\t\t\t\t\t\treturn td->type;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if(defs.size() > 1)\n\t\t\t\t\t{\n\t\t\t\t\t\tauto err = SimpleError::make(this->loc(), \"ambiguous reference to entity '%s' in scope '%s'\", name, tree->name);\n\t\t\t\t\t\tfor(auto d : defs)\n\t\t\t\t\t\t\terr->append(SimpleError::make(MsgType::Note, d->loc, \"possible reference:\"));\n\n\t\t\t\t\t\terr->postAndQuit();\n\t\t\t\t\t}\n\n\n\t\t\t\t\tauto d = defs[0];\n\n\t\t\t\t\tauto tyd = dcast(TypeDefn, d);\n\t\t\t\t\tif(!tyd)\n\t\t\t\t\t{\n\t\t\t\t\t\t// helpful error message: see if there's a actually a type further up!\n\t\t\t\t\t\tErrorMsg* extraHelp = 0;\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tauto t = tree->parent;\n\t\t\t\t\t\t\twhile(!extraHelp && t)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif(auto ds = t->getDefinitionsWithName(name); ds.size() > 0)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfor(const auto& d : ds)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tif(dcast(sst::TypeDefn, d))\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tstd::vector<std::string> ss;\n\t\t\t\t\t\t\t\t\t\t\tauto t1 = tree;\n\t\t\t\t\t\t\t\t\t\t\twhile(t1 != t)\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tt1 = t1->parent;\n\t\t\t\t\t\t\t\t\t\t\t\tif(!t1->isAnonymous)\n\t\t\t\t\t\t\t\t\t\t\t\t\tss.push_back(\"^\");\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\tss.push_back(name);\n\n\t\t\t\t\t\t\t\t\t\t\textraHelp = SimpleError::make(MsgType::Note, d->loc,\n\t\t\t\t\t\t\t\t\t\t\t\t\"'%s' was defined as a type in the parent scope, here:\", name)\n\t\t\t\t\t\t\t\t\t\t\t\t->append(BareError::make(MsgType::Note, \"to refer to it, use '%s'\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tzfu::join(ss, \"::\")));\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tt = t->parent;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t//* example of something 'wrong'\n\t\t\t\t\t\tauto err = SimpleError::make(this->loc(), \"definition of '%s' cannot be used as a type\", d->id.name)\n\t\t\t\t\t\t\t->append(SimpleError::make(MsgType::Note, d->loc, \"'%s' was defined here:\", d->id.name));\n\n\t\t\t\t\t\tif(extraHelp) err->append(extraHelp);\n\n\t\t\t\t\t\terr->postAndQuit();\n\t\t\t\t\t}\n\n\t\t\t\t\treturn tyd->type;\n\t\t\t\t};\n\n\n\t\t\t\tif(name.find(\"::\") == std::string::npos)\n\t\t\t\t{\n\t\t\t\t\treturn returnTheThing(this->stree, name, false, allowFail);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// fuck me\n\t\t\t\t\tstd::string actual;\n\t\t\t\t\tbool skip_to_root = false;\n\t\t\t\t\tstd::deque<std::string> scopes;\n\t\t\t\t\t{\n\t\t\t\t\t\tstd::string tmp;\n\t\t\t\t\t\tfor(size_t i = 0; i < name.size(); i++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif(name[i] == ':' && (i + 1 < name.size()) && name[i+1] == ':')\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif(tmp.empty())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif(i == 0)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\t\t\t\tskip_to_root = true;\n\t\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\terror(this->loc(), \"expected identifier between consecutive scopes ('::') in nested type specifier\");\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tscopes.push_back(tmp);\n\t\t\t\t\t\t\t\ttmp.clear();\n\n\t\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if(name[i] == '^')\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif(!tmp.empty())\n\t\t\t\t\t\t\t\t\terror(this->loc(), \"parent-scope-specifier '^' must appear in its own path segment ('%s' is invalid)\", tmp + name[i]);\n\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\ttmp = \"^\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttmp += name[i];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif(tmp.empty())\n\t\t\t\t\t\t\terror(this->loc(), \"expected identifier after final '::' in nested type specifier\");\n\n\t\t\t\t\t\t// don't push back.\n\t\t\t\t\t\tactual = tmp;\n\t\t\t\t\t}\n\n\t\t\t\t\tStateTree* begin = 0;\n\n\t\t\t\t\tif(skip_to_root)\n\t\t\t\t\t{\n\t\t\t\t\t\tbegin = this->stree;\n\t\t\t\t\t\twhile(begin->parent)\n\t\t\t\t\t\t\tbegin = begin->parent;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\ticeAssert(scopes.size() > 0);\n\t\t\t\t\t\tbegin = recursivelyFindTreeUpwards(this, scopes.front());\n\t\t\t\t\t}\n\n\t\t\t\t\tif(!begin)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(allowFail)   return 0;\n\t\t\t\t\t\telse            error(this->loc(), \"nonexistent scope '%s'\", scopes.front());\n\t\t\t\t\t}\n\n\n\t\t\t\t\tif(scopes.size() > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tstd::string prev = scopes.front();\n\n\t\t\t\t\t\tif(!skip_to_root)\n\t\t\t\t\t\t\tscopes.pop_front();\n\n\t\t\t\t\t\twhile(scopes.size() > 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif(scopes.front() == \"^\")\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif(!begin->parent)\n\t\t\t\t\t\t\t\t\t_complainNoParentScope(this, begin->name)->postAndQuit();\n\n\t\t\t\t\t\t\t\twhile(begin->parent && begin->isAnonymous)\n\t\t\t\t\t\t\t\t\tbegin = begin->parent;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tauto it = begin->subtrees.find(scopes.front());\n\t\t\t\t\t\t\t\tif(it == begin->subtrees.end())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif(allowFail)   return 0;\n\t\t\t\t\t\t\t\t\telse            error(this->loc(), \"no entity '%s' in scope '%s'\", scopes.front(), prev);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tbegin = it->second;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tprev = scopes.front();\n\t\t\t\t\t\t\tscopes.pop_front();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn returnTheThing(begin, actual, true, allowFail);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if(pt->isPointerType())\n\t\t{\n\t\t\tif(pt->toPointerType()->isMutable)\n\t\t\t\treturn this->convertParserTypeToFIR(pt->toPointerType()->base)->getMutablePointerTo();\n\n\t\t\telse\n\t\t\t\treturn this->convertParserTypeToFIR(pt->toPointerType()->base)->getPointerTo();\n\t\t}\n\t\telse if(pt->isTupleType())\n\t\t{\n\t\t\tstd::vector<fir::Type*> ts;\n\t\t\tfor(auto t : pt->toTupleType()->types)\n\t\t\t\tts.push_back(this->convertParserTypeToFIR(t));\n\n\t\t\treturn fir::TupleType::get(ts);\n\t\t}\n\t\telse if(pt->isArraySliceType())\n\t\t{\n\t\t\treturn fir::ArraySliceType::get(this->convertParserTypeToFIR(pt->toArraySliceType()->base), pt->toArraySliceType()->mut);\n\t\t}\n\t\telse if(pt->isDynamicArrayType())\n\t\t{\n\t\t\treturn fir::DynamicArrayType::get(this->convertParserTypeToFIR(pt->toDynamicArrayType()->base));\n\t\t}\n\t\telse if(pt->isVariadicArrayType())\n\t\t{\n\t\t\treturn fir::ArraySliceType::getVariadic(this->convertParserTypeToFIR(pt->toVariadicArrayType()->base));\n\t\t}\n\t\telse if(pt->isFixedArrayType())\n\t\t{\n\t\t\treturn fir::ArrayType::get(this->convertParserTypeToFIR(pt->toFixedArrayType()->base), pt->toFixedArrayType()->size);\n\t\t}\n\t\telse if(pt->isFunctionType())\n\t\t{\n\t\t\tstd::vector<fir::Type*> ps;\n\t\t\tfor(auto p : pt->toFunctionType()->argTypes)\n\t\t\t\tps.push_back(this->convertParserTypeToFIR(p));\n\n\t\t\tauto ret = this->convertParserTypeToFIR(pt->toFunctionType()->returnType);\n\t\t\treturn fir::FunctionType::get(ps, ret);\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror(this->loc(), \"invalid pts::Type found\");\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/typecheckstate.cpp",
    "content": "// typecheckstate.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"defs.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"ir/type.h\"\n#include \"memorypool.h\"\n#include \"zfu.h\"\n\n#include <algorithm>\n#include <deque>\n#include <iterator>\n\nnamespace sst\n{\n\n\tvoid TypecheckState::pushLoc(ast::Stmt* stmt)\n\t{\n\t\tthis->locationStack.push_back(stmt->loc);\n\t}\n\n\tvoid TypecheckState::pushLoc(const Location& l)\n\t{\n\t\tthis->locationStack.push_back(l);\n\t}\n\n\n\n\tLocation TypecheckState::popLoc()\n\t{\n\t\ticeAssert(this->locationStack.size() > 0);\n\t\tauto last = this->locationStack.back();\n\t\tthis->locationStack.pop_back();\n\n\t\treturn last;\n\t}\n\n\tLocation TypecheckState::loc()\n\t{\n\t\ticeAssert(this->locationStack.size() > 0);\n\t\treturn this->locationStack.back();\n\t}\n\n\t#define BODY_FUNC       1\n\t#define BODY_STRUCT     2\n\tvoid TypecheckState::enterFunctionBody(FunctionDefn* fn)\n\t{\n\t\tthis->currentFunctionStack.push_back(fn);\n\t\tthis->bodyStack.push_back(BODY_FUNC);\n\t}\n\n\tvoid TypecheckState::leaveFunctionBody()\n\t{\n\t\tif(this->currentFunctionStack.empty())\n\t\t\terror(this->loc(), \"not inside function\");\n\n\t\tthis->currentFunctionStack.pop_back();\n\n\t\ticeAssert(this->bodyStack.back() == BODY_FUNC);\n\t\tthis->bodyStack.pop_back();\n\t}\n\n\tFunctionDefn* TypecheckState::getCurrentFunction()\n\t{\n\t\tif(this->currentFunctionStack.empty())\n\t\t\terror(this->loc(), \"not inside function\");\n\n\t\treturn this->currentFunctionStack.back();\n\t}\n\n\tbool TypecheckState::isInFunctionBody()\n\t{\n\t\treturn this->currentFunctionStack.size() > 0 && this->bodyStack.back() == BODY_FUNC;\n\t}\n\n\n\n\tfir::Type* TypecheckState::getCurrentSelfContext()\n\t{\n\t\tif(this->selfContextStack.empty())\n\t\t\terror(this->loc(), \"not inside struct body\");\n\n\t\treturn this->selfContextStack.back();\n\t}\n\n\tbool TypecheckState::hasSelfContext()\n\t{\n\t\treturn this->selfContextStack.size() > 0;\n\t}\n\n\tvoid TypecheckState::pushSelfContext(fir::Type* str)\n\t{\n\t\tthis->selfContextStack.push_back(str);\n\t\tthis->bodyStack.push_back(BODY_STRUCT);\n\t}\n\n\tvoid TypecheckState::popSelfContext()\n\t{\n\t\tif(this->selfContextStack.empty())\n\t\t\terror(this->loc(), \"not inside struct body\");\n\n\t\tthis->selfContextStack.pop_back();\n\n\t\ticeAssert(this->bodyStack.back() == BODY_STRUCT);\n\t\tthis->bodyStack.pop_back();\n\t}\n\n\n\n\n\n\tvoid TypecheckState::enterSubscript(Expr* arr)\n\t{\n\t\tthis->subscriptArrayStack.push_back(arr);\n\t}\n\n\tExpr* TypecheckState::getCurrentSubscriptArray()\n\t{\n\t\ticeAssert(this->subscriptArrayStack.size() > 0);\n\t\treturn this->subscriptArrayStack.back();\n\t}\n\n\tvoid TypecheckState::leaveSubscript()\n\t{\n\t\ticeAssert(this->subscriptArrayStack.size() > 0);\n\t\tthis->subscriptArrayStack.pop_back();\n\t}\n\n\tbool TypecheckState::isInSubscript()\n\t{\n\t\treturn this->subscriptArrayStack.size() > 0;\n\t}\n\n\n\n\n\n\n\n\n\tvoid TypecheckState::pushTree(const std::string& name, bool createAnonymously)\n\t{\n\t\ticeAssert(this->stree);\n\t\tthis->stree = this->stree->findOrCreateSubtree(name, createAnonymously);\n\t}\n\n\tStateTree* TypecheckState::popTree()\n\t{\n\t\ticeAssert(this->stree);\n\t\tauto ret = this->stree;\n\t\tthis->stree = this->stree->parent;\n\n\t\treturn ret;\n\t}\n\n\tvoid TypecheckState::enterBreakableBody()\n\t{\n\t\tthis->breakableBodyNest++;\n\t}\n\n\tvoid TypecheckState::leaveBreakableBody()\n\t{\n\t\ticeAssert(this->breakableBodyNest > 0);\n\t\tthis->breakableBodyNest--;\n\t}\n\n\tbool TypecheckState::isInBreakableBody()\n\t{\n\t\treturn this->breakableBodyNest > 0;\n\t}\n\n\tvoid TypecheckState::enterDeferBlock()\n\t{\n\t\tthis->deferBlockNest++;\n\t}\n\n\tvoid TypecheckState::leaveDeferBlock()\n\t{\n\t\ticeAssert(this->deferBlockNest > 0);\n\t\tthis->deferBlockNest--;\n\t}\n\n\tbool TypecheckState::isInDeferBlock()\n\t{\n\t\treturn this->deferBlockNest > 0;\n\t}\n\n\tScope TypecheckState::scope()\n\t{\n\t\treturn this->stree->getScope();\n\t}\n\n\tstd::vector<Defn*> StateTree::getAllDefinitions()\n\t{\n\t\tstd::vector<Defn*> ret;\n\t\tfor(const auto& [ n, ds ] : this->definitions)\n\t\t\tfor(auto d : ds)\n\t\t\t\tret.push_back(d);\n\n\t\treturn ret;\n\t}\n\n\tstatic void fetchDefinitionsFrom(const std::string& name, StateTree* tree, bool recursively, bool includePrivate, std::vector<Defn*>& out)\n\t{\n\t\tif(auto it = tree->definitions.find(name); it != tree->definitions.end())\n\t\t{\n\t\t\tstd::copy_if(it->second.begin(), it->second.end(), std::back_inserter(out), [includePrivate](Defn* defn) -> bool {\n\t\t\t\treturn (includePrivate ? true : defn->visibility == VisibilityLevel::Public);\n\t\t\t});\n\t\t}\n\n\t\tauto sameOrigin = [](const StateTree* a, const StateTree* b) -> bool {\n\t\t\tauto p1 = a; while(p1->parent) p1 = p1->parent;\n\t\t\tauto p2 = b; while(p2->parent) p2 = p2->parent;\n\n\t\t\treturn p1 == p2;\n\t\t};\n\n\t\tfor(auto import : tree->imports)\n\t\t{\n\t\t\tif(recursively)\n\t\t\t{\n\t\t\t\t// only include private things if we're in the same file.\n\t\t\t\tbool priv = sameOrigin(tree, import);\n\t\t\t\tfetchDefinitionsFrom(name, import, /* recursively: */ false, /* includePrivate: */ priv, out);\n\t\t\t}\n\n\t\t\t// in theory we should never include the private definitions from re-exports\n\t\t\tfor(auto reexp : import->reexports)\n\t\t\t\tfetchDefinitionsFrom(name, reexp, /* recursively: */ false, /* includePrivate: */ false, out);\n\t\t}\n\t}\n\n\tstd::vector<Defn*> StateTree::getDefinitionsWithName(const std::string& name)\n\t{\n\t\tstd::vector<Defn*> ret;\n\t\tfetchDefinitionsFrom(name, this, /* recursively: */ true, /* includePrivate: */ true, ret);\n\n\t\treturn ret;\n\t}\n\n\tstd::vector<ast::Parameterisable*> StateTree::getUnresolvedGenericDefnsWithName(const std::string& name)\n\t{\n\t\tif(auto it = this->unresolvedGenericDefs.find(name); it != this->unresolvedGenericDefs.end())\n\t\t\treturn it->second;\n\n\t\telse\n\t\t\treturn { };\n\t}\n\n\tvoid StateTree::addDefinition(const std::string& name, Defn* def, const TypeParamMap_t& gmaps)\n\t{\n\t\tthis->definitions[name].push_back(def);\n\t}\n\n\n\tstd::string Scope::string() const\n\t{\n\t\treturn zfu::join(this->components(), \"::\");\n\t}\n\n\tconst std::vector<std::string>& Scope::components() const\n\t{\n\t\tif(!this->cachedComponents.empty())\n\t\t\treturn this->cachedComponents;\n\n\t\tauto& ret = this->cachedComponents;\n\n\t\tconst Scope* s = this;\n\t\twhile(s && s->stree)\n\t\t{\n\t\t\tret.push_back(s->stree->name);\n\t\t\ts = s->prev;\n\t\t}\n\n\t\tstd::reverse(ret.begin(), ret.end());\n\t\treturn ret;\n\t}\n\n\tconst Scope& StateTree::getScope()\n\t{\n\t\tif(!this->cachedScope.stree)\n\t\t{\n\t\t\tthis->cachedScope.stree = this;\n\n\t\t\tif(this->parent)\n\t\t\t\tthis->cachedScope.prev = &this->parent->getScope();\n\t\t}\n\n\t\treturn this->cachedScope;\n\t}\n\n\tconst Scope& Scope::appending(const std::string& name) const\n\t{\n\t\treturn this->stree->findOrCreateSubtree(name)->getScope();\n\t}\n\n\tvoid TypecheckState::teleportInto(const Scope& scope)\n\t{\n\t\tthis->teleportationStack.push_back(this->stree);\n\t\tthis->stree = scope.stree;\n\t}\n\n\tvoid TypecheckState::teleportOut()\n\t{\n\t\tthis->stree = this->teleportationStack.back();\n\t\tthis->teleportationStack.pop_back();\n\t}\n\n\tStateTree* StateTree::findSubtree(const std::string& name)\n\t{\n\t\tif(auto it = this->subtrees.find(name); it != this->subtrees.end())\n\t\t\treturn it->second;\n\n\t\t// check our imports, and our imports' reexports.\n\t\tfor(const auto imp : this->imports)\n\t\t{\n\t\t\tif(imp->name == name)\n\t\t\t\treturn imp;\n\n\t\t\tfor(const auto exp : imp->reexports)\n\t\t\t\tif(exp->name == name)\n\t\t\t\t\treturn exp;\n\t\t}\n\n\t\treturn nullptr;\n\t}\n\n\tStateTree* StateTree::findOrCreateSubtree(const std::string& name, bool anonymous)\n\t{\n\t\tif(auto it = this->subtrees.find(name); it != this->subtrees.end())\n\t\t{\n\t\t\treturn it->second;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto newtree = util::pool<StateTree>(name, this, anonymous);\n\t\t\tnewtree->moduleName = this->moduleName;\n\t\t\tthis->subtrees[name] = newtree;\n\t\t\treturn newtree;\n\t\t}\n\t}\n\n\n\n\n\n\n\n\tstd::vector<Defn*> TypecheckState::getDefinitionsWithName(const std::string& name, StateTree* tree)\n\t{\n\t\tif(tree == 0)\n\t\t\ttree = this->stree;\n\n\t\tstd::vector<Defn*> ret;\n\n\t\ticeAssert(tree);\n\t\twhile(tree)\n\t\t{\n\t\t\tauto fns = tree->getDefinitionsWithName(name);\n\n\t\t\tif(fns.size() > 0)\n\t\t\t\treturn fns;\n\n\t\t\ttree = tree->parent;\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\tErrorMsg* TypecheckState::checkForShadowingOrConflictingDefinition(Defn* defn,\n\t\tstd::function<bool (TypecheckState* fs, Defn* other)> conflictCheckCallback, StateTree* tree)\n\t{\n\t\tif(tree == 0)\n\t\t\ttree = this->stree;\n\n\t\t// first, check for shadowing\n\t\tbool didWarnAboutShadow = false;\n\n\t\tauto _tree = tree->parent;\n\t\twhile(_tree)\n\t\t{\n\t\t\tif(auto defs = _tree->getDefinitionsWithName(defn->id.name); defs.size() > 0)\n\t\t\t{\n\t\t\t\tif(false && !didWarnAboutShadow)\n\t\t\t\t{\n\t\t\t\t\tdidWarnAboutShadow = true;\n\t\t\t\t\twarn(defn, \"definition of %s '%s' shadows one or more previous definitions\", defn->getKind(), defn->id.name);\n\n\t\t\t\t\tfor(auto d : defs)\n\t\t\t\t\t\tinfo(d, \"previously defined here:\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t_tree = _tree->parent;\n\t\t}\n\n\t\tauto makeTheError = [](Locatable* a, const std::string& n, const std::string& ak,\n\t\t\tconst std::vector<std::pair<Locatable*, std::string>>& conflicts) -> SimpleError* {\n\n\t\t\tauto err = SimpleError::make(a->loc, \"duplicate definition of '%s'\", n);\n\n\t\t\tbool first = true;\n\n\t\t\tfor(const auto& [ l, kind ] : conflicts)\n\t\t\t{\n\t\t\t\terr->append(SimpleError::make(MsgType::Note, l->loc, \"%shere%s:\", first ? strprintf(\"conflicting %s \",\n\t\t\t\t\tzfu::plural(\"definition\", conflicts.size())) : \"and \", ak == kind ? \"\" : strprintf(\" (as a %s)\", kind)));\n\n\t\t\t\tfirst = false;\n\t\t\t}\n\n\t\t\treturn err;\n\t\t};\n\n\n\t\t// ok, now check only the current scope\n\t\tauto defs = tree->getDefinitionsWithName(defn->id.name);\n\n\t\tfor(auto otherdef : defs)\n\t\t{\n\t\t\tif(!otherdef->type->containsPlaceholders() && conflictCheckCallback(this, otherdef))\n\t\t\t{\n\t\t\t\tauto errs = makeTheError(defn, defn->id.name, defn->getKind(), { std::make_pair(otherdef, otherdef->getKind()) });\n\n\t\t\t\t// TODO: be more intelligent about when we give this informative tidbit\n\t\t\t\tif(dcast(sst::FunctionDecl, otherdef) && dcast(sst::FunctionDecl, defn))\n\t\t\t\t{\n\t\t\t\t\tauto a = dcast(sst::FunctionDecl, defn);\n\t\t\t\t\tauto b = dcast(sst::FunctionDecl, otherdef);\n\t\t\t\t\tif(fir::Type::areTypeListsEqual(zfu::map(a->params, [](const auto& p) -> fir::Type* { return p.type; }),\n\t\t\t\t\t\tzfu::map(b->params, [](const auto& p) -> fir::Type* { return p.type; })))\n\t\t\t\t\t{\n\t\t\t\t\t\terrs->append(BareError::make(MsgType::Note, \"functions cannot be overloaded over argument names or\"\n\t\t\t\t\t\t\t\" return types alone\"));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn errs;\n\t\t\t}\n\t\t}\n\n\t\t// while in the interests of flexibility we provide a predicate for users to specify whether or not the duplicate definition is\n\t\t// actually conflicting, for generics i couldn't be damned.\n\t\t//? to know for certain that a definition will conflict with a generic thing, either we are:\n\t\t// A: variable & generic anything\n\t\t// B: function & generic type\n\t\t// C: type & generic anything\n\n\t\tif(auto gdefs = tree->getUnresolvedGenericDefnsWithName(defn->id.name); gdefs.size() > 0)\n\t\t{\n\t\t\tif(auto fn = dcast(sst::FunctionDecl, defn))\n\t\t\t{\n\t\t\t\t// honestly we can't know if we will conflict with other functions.\n\t\t\t\t// filter out by kind.\n\n\t\t\t\tauto newgds = zfu::filterMap(gdefs,\n\t\t\t\t\t[](ast::Parameterisable* d) -> bool {\n\t\t\t\t\t\treturn dcast(ast::FuncDefn, d) == nullptr;\n\t\t\t\t\t},\n\t\t\t\t\t[](ast::Parameterisable* d) -> std::pair<Locatable*, std::string> {\n\t\t\t\t\t\treturn std::make_pair(d, d->getKind());\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\t\tif(newgds.size() > 0)\n\t\t\t\t\treturn makeTheError(fn, fn->id.name, fn->getKind(), newgds);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// assume everything conflicts, since functions are the only thing that can overload.\n\t\t\t\treturn makeTheError(defn, defn->id.name, defn->getKind(),\n\t\t\t\t\tzfu::map(gdefs, [](ast::Parameterisable* d) -> std::pair<Locatable*, std::string> {\n\t\t\t\t\t\treturn std::make_pair(d, d->getKind());\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// no error.\n\t\treturn nullptr;\n\t}\n\n\tvoid TypecheckState::pushAnonymousTree()\n\t{\n\t\tstatic size_t _anonId = 0;\n\t\tthis->pushTree(std::to_string(_anonId++), /* createAnonymously: */ true);\n\t}\n\n\n\tScope::Scope(StateTree* st)\n\t{\n\t\tthis->prev = 0;\n\t\tthis->stree = st;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/unions.cpp",
    "content": "// unions.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"typecheck.h\"\n\n#include \"ir/type.h\"\n#include \"memorypool.h\"\n\n// defined in typecheck/structs.cpp\nvoid checkFieldRecursion(sst::TypecheckState* fs, fir::Type* strty, fir::Type* field, const Location& floc);\nvoid checkTransparentFieldRedefinition(sst::TypecheckState* fs, sst::TypeDefn* defn, const std::vector<sst::StructFieldDefn*>& fields);\n\n\n\n\nTCResult ast::UnionDefn::generateDeclaration(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto [ success, ret ] = this->checkForExistingDeclaration(fs, gmaps);\n\tif(!success)    return TCResult::getParametric();\n\telse if(ret)    return TCResult(ret);\n\n\tauto defnname = util::typeParamMapToString(this->name, gmaps);\n\n\tbool israw = this->attrs.has(attr::RAW);\n\n\tsst::TypeDefn* defn = 0;\n\tif(israw)   defn = util::pool<sst::RawUnionDefn>(this->loc);\n\telse        defn = util::pool<sst::UnionDefn>(this->loc);\n\n\tdefn->bareName = this->name;\n\tdefn->attrs = this->attrs;\n\n\tdefn->id = Identifier(defnname, IdKind::Type);\n\tdefn->id.scope = this->enclosingScope;\n\tdefn->visibility = this->visibility;\n\tdefn->original = this;\n\tdefn->enclosingScope = this->enclosingScope;\n\tdefn->innerScope = this->enclosingScope.appending(defnname);\n\n\tif(israw)   defn->type = fir::RawUnionType::createWithoutBody(defn->id.convertToName());\n\telse        defn->type = fir::UnionType::createWithoutBody(defn->id.convertToName());\n\n\tif(auto err = fs->checkForShadowingOrConflictingDefinition(defn, [](auto, auto) -> bool { return true; }))\n\t\treturn TCResult(err);\n\n\tdefn->enclosingScope.stree->addDefinition(defnname, defn, gmaps);\n\n\tthis->genericVersions.push_back({ defn, fs->getGenericContextStack() });\n\n\tfs->typeDefnMap[defn->type] = defn;\n\treturn TCResult(defn);\n}\n\n\nTCResult ast::UnionDefn::typecheck(sst::TypecheckState* fs, fir::Type* infer, const TypeParamMap_t& gmaps)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tauto tcr = this->generateDeclaration(fs, infer, gmaps);\n\tif(tcr.isParametric())  return tcr;\n\telse if(tcr.isError())  error(this, \"failed to generate declaration for union '%s'\", this->name);\n\n\n\tif(this->finishedTypechecking.find(tcr.defn()) != this->finishedTypechecking.end())\n\t\treturn TCResult(tcr.defn());\n\n\tsst::TypeDefn* ret = 0;\n\tif(this->attrs.has(attr::RAW))\n\t{\n\t\tauto defn = dcast(sst::RawUnionDefn, tcr.defn());\n\t\ticeAssert(defn);\n\n\t\tfs->teleportInto(defn->innerScope);\n\n\t\t//* in many ways raw unions resemble structs rather than tagged unions\n\t\t//* and since we are using sst::StructFieldDefn for the variants, we will need\n\t\t//* to enter the struct body.\n\n\t\tauto unionTy = defn->type->toRawUnionType();\n\t\tfs->pushSelfContext(unionTy);\n\n\t\tutil::hash_map<std::string, fir::Type*> types;\n\t\tutil::hash_map<std::string, sst::StructFieldDefn*> fields;\n\n\n\n\t\tauto make_field = [fs, unionTy](const std::string& name, const Location& loc, pts::Type* ty) -> sst::StructFieldDefn* {\n\n\t\t\tauto vdef = util::pool<ast::VarDefn>(loc);\n\t\t\tvdef->immut = false;\n\t\t\tvdef->name = name;\n\t\t\tvdef->initialiser = nullptr;\n\t\t\tvdef->type = ty;\n\t\t\tvdef->isField = true;\n\n\t\t\tauto sfd = dcast(sst::StructFieldDefn, vdef->typecheck(fs).defn());\n\t\t\ticeAssert(sfd);\n\n\t\t\tif(fir::isRefCountedType(sfd->type))\n\t\t\t\terror(sfd, \"reference-counted type '%s' cannot be a member of a raw union\", sfd->type);\n\n\t\t\tcheckFieldRecursion(fs, unionTy, sfd->type, sfd->loc);\n\t\t\treturn sfd;\n\t\t};\n\n\t\tstd::vector<sst::StructFieldDefn*> tfields;\n\t\tstd::vector<sst::StructFieldDefn*> allFields;\n\n\t\tfor(auto variant : this->cases)\n\t\t{\n\t\t\tauto sfd = make_field(variant.first, std::get<1>(variant.second), std::get<2>(variant.second));\n\t\t\ticeAssert(sfd);\n\n\t\t\tfields[sfd->id.name] = sfd;\n\t\t\ttypes[sfd->id.name] = sfd->type;\n\n\t\t\tallFields.push_back(sfd);\n\t\t}\n\n\n\t\t// do the transparent fields\n\t\t{\n\t\t\tsize_t tfn = 0;\n\t\t\tfor(auto [ loc, pty ] : this->transparentFields)\n\t\t\t{\n\t\t\t\tauto sfd = make_field(fir::obfuscateName(\"transparent_field\", tfn++), loc, pty);\n\t\t\t\ticeAssert(sfd);\n\n\t\t\t\tsfd->isTransparentField = true;\n\n\t\t\t\t// still add to the types, cos we need to compute sizes and stuff\n\t\t\t\ttypes[sfd->id.name] = sfd->type;\n\t\t\t\ttfields.push_back(sfd);\n\t\t\t\tallFields.push_back(sfd);\n\t\t\t}\n\t\t}\n\n\t\tcheckTransparentFieldRedefinition(fs, defn, allFields);\n\n\n\t\tdefn->fields = fields;\n\t\tdefn->transparentFields = tfields;\n\n\n\n\n\t\tunionTy->setBody(types);\n\n\t\tfs->popSelfContext();\n\t\tret = defn;\n\t}\n\telse\n\t{\n\t\tauto defn = dcast(sst::UnionDefn, tcr.defn());\n\t\ticeAssert(defn);\n\n\t\tfs->teleportInto(defn->innerScope);\n\n\t\tutil::hash_map<std::string, std::pair<size_t, fir::Type*>> vars;\n\t\tstd::vector<std::pair<sst::UnionVariantDefn*, size_t>> vdefs;\n\n\t\ticeAssert(this->transparentFields.empty());\n\n\t\tfor(auto variant : this->cases)\n\t\t{\n\t\t\tvars[variant.first] = { std::get<0>(variant.second), (std::get<2>(variant.second)\n\t\t\t\t? fs->convertParserTypeToFIR(std::get<2>(variant.second)) : fir::Type::getVoid())\n\t\t\t};\n\n\n\t\t\tauto vdef = util::pool<sst::UnionVariantDefn>(std::get<1>(variant.second));\n\t\t\tvdef->parentUnion = defn;\n\t\t\tvdef->variantName = variant.first;\n\t\t\tvdef->id = Identifier(defn->id.name + \"::\" + variant.first, IdKind::Name);\n\t\t\tvdef->id.scope = fs->scope();\n\n\t\t\tvdefs.push_back({ vdef, std::get<0>(variant.second) });\n\n\t\t\tfs->stree->addDefinition(variant.first, vdef);\n\n\t\t\tdefn->variants[variant.first] = vdef;\n\t\t}\n\n\t\tauto unionTy = defn->type->toUnionType();\n\t\tunionTy->setBody(vars);\n\n\t\t// in a bit of stupidity, we need to set the type of each definition properly.\n\t\tfor(const auto& [ uvd, id ] : vdefs)\n\t\t\tuvd->type = unionTy->getVariant(id);\n\n\t\tret = defn;\n\t}\n\n\ticeAssert(ret);\n\tthis->finishedTypechecking.insert(ret);\n\n\tfs->teleportOut();\n\n\treturn TCResult(ret);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/using.cpp",
    "content": "// using.cpp\n// Copyright (c) 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"ast.h\"\n#include \"defs.h\"\n#include \"errors.h\"\n#include \"sst.h\"\n#include \"typecheck.h\"\n\n#include \"ir/type.h\"\n#include \"memorypool.h\"\n\n\nTCResult ast::UsingStmt::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\t// check what kind of expression we have.\n\tauto used = this->expr->typecheck(fs).expr();\n\tif(!dcast(sst::ScopeExpr, used) && !dcast(sst::VarRef, used))\n\t\terror(this->expr, \"unsupported expression on left-side of 'using' declaration\");\n\n\n\t// check for enumerations -- we need to handle those a little specially.\n\t// due to the magic of good code architecture, (haha, who am i kidding, it's pure luck)\n\t// if the LHS is a dot operator of any kind, we'll resolve it appropriately -- getting a VarRef to an EnumDefn if it is an enum,\n\t// and only getting ScopeExpr if it's really a namespace reference.\n\n\n\tsst::Scope scopes;\n\tauto vr = dcast(sst::VarRef, used);\n\n\tif(vr && dcast(sst::EnumDefn, vr->def))\n\t{\n\t\tauto enrd = dcast(sst::EnumDefn, vr->def);\n\t\tscopes = enrd->innerScope;\n\t}\n\t// uses the same 'vr' from the branch above\n\telse if(vr && dcast(sst::UnionDefn, vr->def))\n\t{\n\t\tauto unn = dcast(sst::UnionDefn, vr->def);\n\t\tscopes = unn->innerScope;\n\t}\n\telse\n\t{\n\t\tsst::TypeDefn* td = nullptr;\n\n\t\t// this happens in cases like `foo::bar`\n\t\tif(auto se = dcast(sst::ScopeExpr, used))\n\t\t\tscopes = se->scope;\n\n\t\t// and this happens in cases like `foo`\n\t\telse if(vr && (td = dcast(sst::TypeDefn, vr->def)))\n\t\t\tscopes = td->innerScope;\n\n\t\telse\n\t\t\terror(\"unsupported LHS of using: '%s'\", used->readableName);\n\t}\n\n\tauto target = scopes.stree;\n\twhile(target->proxyOf)\n\t\ttarget = target->proxyOf;\n\n\tif(this->useAs == \"_\")\n\t{\n\t\tsst::mergeExternalTree(this->loc, \"using\", fs->stree, target);\n\t}\n\telse\n\t{\n\t\t// check that the current scope doesn't contain this thing\n\t\tif(auto existing = fs->getDefinitionsWithName(this->useAs); existing.size() > 0)\n\t\t{\n\t\t\tauto err = SimpleError::make(this->loc, \"cannot use scope '%s' as '%s'; one or more conflicting definitions exist\",\n\t\t\t\tscopes.string(), this->useAs);\n\n\t\t\terr->append(SimpleError::make(MsgType::Note, existing[0]->loc, \"first conflicting definition here:\"));\n\t\t\terr->postAndQuit();\n\t\t}\n\n\t\tauto tree = fs->stree->findOrCreateSubtree(this->useAs);\n\t\tsst::mergeExternalTree(this->loc, \"using\", tree, target);\n\t}\n\n\treturn TCResult::getDummy();\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/typecheck/variable.cpp",
    "content": "// variable.cpp\n// Copyright (c) 2014 - 2017, zhiayang\n// Licensed under the Apache License Version 2.0.\n\n#include \"defs.h\"\n#include \"pts.h\"\n#include \"ast.h\"\n#include \"errors.h\"\n#include \"sst.h\"\n#include \"typecheck.h\"\n\n#include \"resolver.h\"\n#include \"polymorph.h\"\n\n#include \"ir/type.h\"\n#include \"memorypool.h\"\n\n\n\n\nstatic TCResult getResult(ast::Ident* ident, sst::Defn* def, bool implicit = false)\n{\n\tauto ret = util::pool<sst::VarRef>(ident->loc, def->type);\n\tret->name = ident->name;\n\tret->def = def;\n\tret->isImplicitField = implicit;\n\n\treturn TCResult(ret);\n}\n\n\n\nstatic TCResult checkPotentialCandidate(sst::TypecheckState* fs, ast::Ident* ident, sst::Defn* def, fir::Type* infer)\n{\n\tbool implicit = false;\n\tif(auto fld = dcast(sst::StructFieldDefn, def))\n\t{\n\t\timplicit = true;\n\n\t\t// check that we're actually in a method def.\n\t\t//* this is superior to the previous 'isInStructBody()' approach, because this will properly handle defining nested functions\n\t\t//* -- those are technically \"in\" a function body, but they're certainly not methods.\n\t\tif(!fs->isInFunctionBody() || !fs->getCurrentFunction()->parentTypeForMethod)\n\t\t{\n\t\t\treturn TCResult(\n\t\t\t\tSimpleError::make(ident->loc, \"field '%s' is an instance member of type '%s', and cannot be accessed statically\",\n\t\t\t\t\tident->name, fld->parentType->id.name)\n\t\t\t\t->append(SimpleError::make(MsgType::Note, def->loc, \"field '%s' was defined here:\", def->id.name))\n\t\t\t);\n\t\t}\n\t}\n\n\t// check if we're not doing something stupid!\n\tif(auto vd = dcast(sst::VarDefn, def))\n\t{\n\t\tif(fs->isInFunctionBody() && vd->definingFunction && vd->definingFunction != fs->getCurrentFunction())\n\t\t{\n\t\t\treturn TCResult(\n\t\t\t\tSimpleError::make(ident->loc, \"invalid reference to variable '%s', which was defined in another function\", ident->name)\n\t\t\t\t\t->append(SimpleError::make(MsgType::Note, vd->loc, \"'%s' was defined here:\", ident->name))\n\t\t\t\t\t->append(BareError::make(MsgType::Note, \"variable capturing (ie. closures) are currently not supported\"))\n\t\t\t);\n\t\t}\n\t}\n\n\n\tif(def->type->isUnionVariantType())\n\t{\n\t\tauto uvd = dcast(sst::UnionVariantDefn, def);\n\t\ticeAssert(uvd);\n\n\t\tif(uvd->type->containsPlaceholders() || uvd->parentUnion->type->containsPlaceholders())\n\t\t{\n\t\t\tstd::vector<FnCallArgument> fake_args;\n\t\t\tauto res = sst::resolver::resolveAndInstantiatePolymorphicUnion(fs, uvd, &fake_args, infer,\n\t\t\t\t/* isFnCall: */ /* uvd->type->toUnionVariantType()->getInteriorType()->isVoidType() ? true :  */ false);\n\n\t\t\tif(res.isError())\n\t\t\t\treturn TCResult(res);\n\n\t\t\t// update uvd\n\t\t\tuvd = dcast(sst::UnionVariantDefn, res.defn());\n\t\t}\n\n\t\t// see the explanation in ast.h for ident flag.\n\t\tif(ident->checkAsType)\n\t\t{\n\t\t\t// make sure the types match, at least.\n\t\t\tif(infer && uvd->parentUnion->type != infer)\n\t\t\t{\n\t\t\t\tif(!infer->isUnionType())\n\t\t\t\t{\n\t\t\t\t\treturn TCResult(SimpleError::make(ident->loc, \"non-union type '%s' inferred for variant '%s' of union '%s'\",\n\t\t\t\t\t\tinfer, ident->name, uvd->parentUnion->type)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn TCResult(SimpleError::make(ident->loc, \"inferred union '%s' cannot yield variant '%s' of unrelated union '%s'\",\n\t\t\t\t\t\tinfer, ident->name, uvd->parentUnion->type)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn getResult(ident, uvd, implicit);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto ret = util::pool<sst::UnionVariantConstructor>(ident->loc, uvd->parentUnion->type);\n\n\t\t\tret->variantId = uvd->parentUnion->type->toUnionType()->getIdOfVariant(uvd->variantName);\n\t\t\tret->parentUnion = uvd->parentUnion;\n\t\t\tret->args = { };\n\n\t\t\treturn TCResult(ret);\n\t\t}\n\t}\n\telse if(infer && def->type->containsPlaceholders())\n\t{\n\t\tauto fd = dcast(sst::FunctionDefn, def);\n\t\ticeAssert(fd);\n\n\t\tstd::vector<FnCallArgument> infer_args;\n\t\tauto [ res, soln ] = sst::poly::attemptToInstantiatePolymorph(fs, fd->original, fd->id.name, { }, /* return_infer: */ nullptr,\n\t\t\t/* type_infer: */ infer, /* isFnCall: */ false, &infer_args, /* fillPlacholders: */ false,\n\t\t\t/* problem_infer: */ def->type);\n\n\t\tif(res.isError())\n\t\t\treturn TCResult(res);\n\n\t\telse\n\t\t\treturn getResult(ident, res.defn(), implicit);\n\t}\n\n\treturn getResult(ident, def, implicit);\n}\n\n\n\n\nTCResult ast::Ident::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\tif(this->name == \"_\")\n\t{\n\t\treturn TCResult(\n\t\t\tSimpleError::make(this->loc, \"'_' is a discarding binding; it does not yield a value and cannot be referred to\")\n\t\t);\n\t}\n\n\tauto makeScopeExpr = [this](const sst::Scope& scope) -> sst::ScopeExpr* {\n\t\treturn util::pool<sst::ScopeExpr>(this->loc, fir::Type::getVoid(), scope);\n\t};\n\n\tif(this->name == \"::\")\n\t{\n\t\t// find the root.\n\t\tauto t = fs->stree;\n\t\twhile(t->parent)\n\t\t\tt = t->parent;\n\n\t\treturn TCResult(makeScopeExpr(t->getScope()));\n\t}\n\telse if(this->name == \"^\")\n\t{\n\t\tif(!fs->stree->parent)\n\t\t{\n\t\t\treturn TCResult(\n\t\t\t\tSimpleError::make(fs->loc(), \"invalid use of '^' at the topmost scope '%s'\", fs->stree->name)\n\t\t\t);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto t = fs->stree->parent;\n\t\t\twhile(t->isAnonymous && t->parent)\n\t\t\t\tt = t->parent;\n\n\t\t\treturn TCResult(makeScopeExpr(t->getScope()));\n\t\t}\n\t}\n\n\tif(auto builtin = fir::Type::fromBuiltin(this->name))\n\t\treturn TCResult(util::pool<sst::TypeExpr>(this->loc, builtin));\n\n\tif(infer && infer->containsPlaceholders())\n\t\tinfer = 0;\n\n\tif(this->name == \"this\" && fs->isInFunctionBody() && fs->getCurrentFunction()->parentTypeForMethod)\n\t\treturn TCResult(util::pool<sst::SelfVarRef>(this->loc, fs->getCurrentFunction()->parentTypeForMethod));\n\n\t// hm.\n\tsst::StateTree* tree = fs->stree;\n\twhile(tree)\n\t{\n\t\tif(auto vs = tree->getDefinitionsWithName(this->name); vs.size() == 1)\n\t\t{\n\t\t\treturn checkPotentialCandidate(fs, this, vs[0], infer);\n\t\t}\n\t\telse if(vs.size() > 1)\n\t\t{\n\t\t\tstd::vector<std::pair<sst::Defn*, TCResult>> ambigs;\n\n\t\t\tfor(auto v : vs)\n\t\t\t{\n\t\t\t\tauto res = checkPotentialCandidate(fs, this, v, infer);\n\t\t\t\tambigs.push_back({ v, res });\n\t\t\t}\n\n\n\t\t\tif(ambigs.size() == 1)\n\t\t\t{\n\t\t\t\treturn ambigs[0].second;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstd::vector<std::pair<sst::Defn*, TCResult>> fails;\n\t\t\t\tstd::vector<std::pair<sst::Defn*, TCResult>> succs;\n\n\t\t\t\tfor(const auto& v : ambigs)\n\t\t\t\t{\n\t\t\t\t\tif(v.second.isError())  fails.push_back(v);\n\t\t\t\t\telse                    succs.push_back(v);\n\t\t\t\t}\n\n\t\t\t\tif(succs.empty())\n\t\t\t\t{\n\t\t\t\t\tauto errs = SimpleError::make(this->loc, \"no definition of '%s'%s\", this->name,\n\t\t\t\t\t\tinfer ? strprintf(\" matching type '%s'\", infer) : \"\");\n\n\t\t\t\t\tfor(const auto& v : succs)\n\t\t\t\t\t\terrs->append(v.second.error());\n\n\t\t\t\t\treturn TCResult(errs);\n\t\t\t\t}\n\t\t\t\telse if(succs.size() > 1)\n\t\t\t\t{\n\t\t\t\t\tauto errs = SimpleError::make(this->loc, \"ambiguous reference to '%s'\", this->name);\n\n\t\t\t\t\tfor(const auto& v : succs)\n\t\t\t\t\t\terrs->append(SimpleError::make(MsgType::Note, v.first->loc, \"potential target here:\", v.first));\n\n\t\t\t\t\treturn TCResult(errs);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn getResult(this, succs[0].first, false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if(auto gdefs = tree->getUnresolvedGenericDefnsWithName(this->name); gdefs.size() > 0)\n\t\t{\n\t\t\tstd::vector<FnCallArgument> fake;\n\t\t\tauto pots = sst::poly::findPolymorphReferences(fs, this->name, gdefs, this->mappings, /* return_infer: */ 0, /* type_infer: */ infer,\n\t\t\t\t/* isFnCall: */ false, &fake);\n\n\t\t\tif(pots.size() > 1)\n\t\t\t{\n\t\t\t\tauto err = SimpleError::make(this->loc, \"ambiguous reference to '%s', potential candidates:\", this->name);\n\t\t\t\tfor(const auto& p : pots)\n\t\t\t\t\terr->append(SimpleError::make(p.res.defn()->loc, \"\"));\n\n\t\t\t\treturn TCResult(err);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ticeAssert(pots.size() == 1);\n\t\t\t\tif(pots[0].res.isDefn())\n\t\t\t\t\treturn getResult(this, pots[0].res.defn());\n\n\t\t\t\telse\n\t\t\t\t\treturn pots[0].res;\n\t\t\t}\n\t\t}\n\n\t\t// check if there is a subtree with this name.\n\t\tif(auto it = tree->subtrees.find(this->name); it != tree->subtrees.end())\n\t\t\treturn TCResult(makeScopeExpr(it->second->getScope()));\n\n\t\tif(this->traverseUpwards)\n\t\t\ttree = tree->parent;\n\n\t\telse\n\t\t\tbreak;\n\t}\n\n\t// ok, we haven't found anything\n\treturn TCResult(\n\t\tSimpleError::make(this->loc, \"reference to unknown entity '%s'\", this->name)\n\t);\n}\n\n\n\n\nTCResult ast::VarDefn::typecheck(sst::TypecheckState* fs, fir::Type* infer)\n{\n\tfs->pushLoc(this);\n\tdefer(fs->popLoc());\n\n\t// ok, then.\n\tsst::VarDefn* defn = 0;\n\tif(this->isField)\n\t{\n\t\tauto fld = util::pool<sst::StructFieldDefn>(this->loc);\n\t\tfld->parentType = fs->typeDefnMap[fs->getCurrentSelfContext()];\n\t\ticeAssert(fld->parentType);\n\n\t\tdefn = fld;\n\t}\n\telse\n\t{\n\t\tdefn = util::pool<sst::VarDefn>(this->loc);\n\t}\n\n\t// check for people being stupid.\n\tif(this->name == \"this\" && fs->isInFunctionBody() && fs->getCurrentFunction()->parentTypeForMethod)\n\t\treturn TCResult(SimpleError::make(this->loc, \"invalid redefinition of 'this' inside method body\"));\n\n\n\n\ticeAssert(defn);\n\tdefn->bareName = this->name;\n\n\tdefn->attrs = this->attrs;\n\tdefn->id = Identifier(this->name, IdKind::Name);\n\tdefn->id.scope = fs->scope();\n\n\tdefn->immutable = this->immut;\n\tdefn->visibility = this->visibility;\n\n\tdefn->global = !fs->isInFunctionBody();\n\n\n\tif(this->type != pts::InferredType::get())\n\t\tdefn->type = fs->convertParserTypeToFIR(this->type);\n\n\telse if(!this->initialiser)\n\t\terror(this, \"initialiser is required for type inference\");\n\n\n\t//* for variables, as long as the name matches, we conflict.\n\tif(auto err = fs->checkForShadowingOrConflictingDefinition(defn, [](auto, auto) -> bool { return true; }))\n\t\treturn TCResult(err);\n\n\t// check the defn\n\tif(this->initialiser)\n\t{\n\t\tdefn->init = this->initialiser->typecheck(fs, defn->type).expr();\n\t\tif(defn->init->type->isVoidType())\n\t\t\terror(defn->init, \"value has void type\");\n\n\t\tif(defn->type == 0)\n\t\t{\n\t\t\tauto t = defn->init->type;\n\t\t\tif(t->isConstantNumberType())\n\t\t\t\tt = sst::inferCorrectTypeForLiteral(defn->init->type->toConstantNumberType());\n\n\t\t\tdefn->type = t;\n\t\t}\n\t\telse if(fir::getCastDistance(defn->init->type, defn->type) < 0)\n\t\t{\n\t\t\tSpanError::make(SimpleError::make(this->loc, \"cannot initialise variable of type '%s' with a value of type '%s'\", defn->type, defn->init->type))\n\t\t\t\t->add(util::ESpan(defn->init->loc, strprintf(\"type '%s'\", defn->init->type)))\n\t\t\t\t->postAndQuit();\n\t\t}\n\t}\n\n\tif(this->name != \"_\")\n\t\tfs->stree->addDefinition(this->name, defn);\n\n\t// store the place where we were defined.\n\tif(fs->isInFunctionBody())\n\t\tdefn->definingFunction = fs->getCurrentFunction();\n\n\treturn TCResult(defn);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  }
]